feat(lang): universal backtick raw identifier — valid in value, decl, AND type position [F0.6]
AGRA ruling (attempt 4): `` `name `` is THE LITERAL identifier `name`, usable in EVERY position — the backtick only means "treat this token as a plain identifier, never the reserved keyword/type", and is never part of the name's text. - Raw in TYPE position is now VALID (reverses attempt-2 "raw is not a type"): `parseTypeExpr` emits a raw `type_expr`; `TypeResolver.resolveNamed` gains a `skip_builtin` flag (threaded from `te.is_raw` via lower.zig + type_bridge) so a `` `s2 `` reference resolves to a `` `s2 ``-declared type (struct/enum/union/alias), else a normal "unknown type 's2'" error (reportIfUnknownType skips the builtin exemption when raw). Bare `s2` in type position stays the builtin int. - Every declaration-name site is is_raw-exemptible: `is_raw` added to TypeExpr + StructDecl/EnumDecl/UnionDecl/ErrorSetDecl/ProtocolDecl/ForeignClassDecl/UfcsAlias/ NamespaceDecl/ImportDecl/CImportDecl/LibraryDecl; parser threads name_is_raw to every decl parse fn; namespace imports carry it through imports.addNamespace. Typed-const path (`` `s2 : s64 : 5 ``) now threads name_span+is_raw (fixes the 1:1-caret bug). - Check<->exemption made structurally symmetric: checkBindingName/checkDeclName take is_raw as a REQUIRED argument and skip inside the check, so no call site can validate a name without honoring the exemption (the desync cause of prior rounds). - Bare reserved-name declarations of every kind still error (0076 preserved); `#import c` foreign names stay auto-raw + bare-callable. specs.md + readme.md updated to the universal model. issue 0089 RESOLVED banner rewritten. Examples: replace 1139 (raw-not-a-type) with 0154 (raw type reference); add 0155 (typed const + union tag) and 1141 (bare type-decl negatives). Gate: zig build + zig build test + run_examples (426 passed, 0 failed).
This commit is contained in:
42
src/ast.zig
42
src/ast.zig
@@ -380,12 +380,19 @@ pub const EnumDecl = struct {
|
||||
is_flags: bool = false,
|
||||
variant_values: []const ?*Node = &.{}, // explicit value per variant (null = auto), empty = all auto
|
||||
backing_type: ?*Node = null, // optional backing type: enum u8 { ... }
|
||||
/// True when the declared NAME was a backtick raw identifier
|
||||
/// (`` `s2 :: enum { … } ``) — exempt from the reserved-type-name decl
|
||||
/// check (issue 0089). A bare reserved-name decl still errors.
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const UnionDecl = struct {
|
||||
name: []const u8,
|
||||
field_names: []const []const u8,
|
||||
field_types: []const *Node,
|
||||
/// True when the declared NAME was a backtick raw identifier — exempt from
|
||||
/// the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
/// `Foo :: error { TagA, TagB }` — a named error set. Tags are bare
|
||||
@@ -393,6 +400,9 @@ pub const UnionDecl = struct {
|
||||
pub const ErrorSetDecl = struct {
|
||||
name: []const u8,
|
||||
tag_names: []const []const u8,
|
||||
/// True when the declared NAME was a backtick raw identifier — exempt from
|
||||
/// the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const StructTypeParam = struct {
|
||||
@@ -418,6 +428,10 @@ pub const StructDecl = struct {
|
||||
using_entries: []const UsingEntry = &.{},
|
||||
methods: []const *Node = &.{}, // fn_decl nodes for struct methods
|
||||
constants: []const *Node = &.{}, // const_decl nodes for struct-level constants
|
||||
/// True when the declared NAME was a backtick raw identifier
|
||||
/// (`` `s2 :: struct { … } ``) — exempt from the reserved-type-name decl
|
||||
/// check (issue 0089). A bare reserved-name decl still errors.
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const StructFieldInit = struct {
|
||||
@@ -444,6 +458,12 @@ pub const TypeExpr = struct {
|
||||
name: []const u8,
|
||||
is_generic: bool = false,
|
||||
protocol_constraints: []const []const u8 = &.{}, // e.g. ["Eq", "Hashable"] for $T/Eq/Hashable
|
||||
/// True when written as a backtick raw identifier in type position
|
||||
/// (`` `s2 ``). Such a reference is the LITERAL name `s2` used as a type —
|
||||
/// resolution skips the builtin/reserved classifier and looks up a
|
||||
/// `` `s2 ``-declared type (struct/enum/union/alias), else "unknown type"
|
||||
/// (issue 0089). A bare `s2` keeps `is_raw = false` and is the int type.
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
/// `$<pack_name>[<index>]` in type position. Resolves to the i-th
|
||||
@@ -530,6 +550,10 @@ pub const ReturnStmt = struct {
|
||||
pub const ImportDecl = struct {
|
||||
path: []const u8,
|
||||
name: ?[]const u8,
|
||||
/// True when the namespace NAME was a backtick raw identifier
|
||||
/// (`` `s2 :: #import "…" ``) — exempt from the reserved-type-name decl
|
||||
/// check (issue 0089). A flat `#import` (name == null) binds nothing.
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const ArrayTypeExpr = struct {
|
||||
@@ -638,6 +662,9 @@ pub const SpreadExpr = struct {
|
||||
pub const NamespaceDecl = struct {
|
||||
name: []const u8,
|
||||
decls: []const *Node,
|
||||
/// True when the namespace NAME was a backtick raw identifier — exempt
|
||||
/// from the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const ForeignExpr = struct {
|
||||
@@ -648,6 +675,9 @@ pub const ForeignExpr = struct {
|
||||
pub const LibraryDecl = struct {
|
||||
lib_name: []const u8,
|
||||
name: []const u8, // sx-side constant name
|
||||
/// True when the constant NAME was a backtick raw identifier — exempt from
|
||||
/// the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const FrameworkDecl = struct {
|
||||
@@ -691,6 +721,9 @@ pub const TupleElement = struct {
|
||||
pub const UfcsAlias = struct {
|
||||
name: []const u8,
|
||||
target: []const u8,
|
||||
/// True when the alias NAME was a backtick raw identifier — exempt from
|
||||
/// the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const CImportDecl = struct {
|
||||
@@ -700,6 +733,9 @@ pub const CImportDecl = struct {
|
||||
flags: []const []const u8,
|
||||
name: ?[]const u8 = null,
|
||||
bitcode_paths: []const []const u8 = &.{}, // populated during import resolution
|
||||
/// True when the namespace NAME was a backtick raw identifier — exempt
|
||||
/// from the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const ProtocolMethodDecl = struct {
|
||||
@@ -720,6 +756,9 @@ pub const ProtocolDecl = struct {
|
||||
methods: []const ProtocolMethodDecl,
|
||||
is_inline: bool = false, // #inline — embedded fn ptrs instead of vtable pointer
|
||||
type_params: []const StructTypeParam = &.{}, // for `protocol(Target: Type) { ... }`
|
||||
/// True when the declared NAME was a backtick raw identifier — exempt from
|
||||
/// the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const ForeignRuntime = enum {
|
||||
@@ -776,6 +815,9 @@ pub const ForeignClassDecl = struct {
|
||||
members: []const ForeignClassMember = &.{},
|
||||
is_foreign: bool = false, // `#foreign #...` prefix — class is provided by the foreign runtime; we only reference it
|
||||
is_main: bool = false, // `#jni_main` / `#objc_main` — class is the launchable entry (Activity / UIApplicationDelegate / ...)
|
||||
/// True when the sx-side alias NAME was a backtick raw identifier — exempt
|
||||
/// from the reserved-type-name decl check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const JniEnvBlock = struct {
|
||||
|
||||
Reference in New Issue
Block a user