feat(lang): backtick raw identifier in every binding form + raw-not-a-type + foreign reserved-name fn bare-call [F0.6]
Completes the issue-0089 backtick raw-identifier / `#import c` exemption across all remaining identifier positions and closes three boundary gaps the F0.6 review found. 1. Exhaustive raw-binding coverage. The `is_raw` bit now threads through `ast.Identifier` and EVERY binding/capture form — `IfExpr`/`WhileExpr` optional bindings, `ForExpr` capture + index, `MatchArm` capture, `CatchExpr`/`OnFailStmt` tag bindings, `DestructureDecl` per-name, and the protocol-default-body / foreign-class method param lists — not just `var_decl`/`param`. `UnknownTypeChecker` skips the reserved-name check at each arm when raw, so a backtick works in every identifier position while a bare reserved spelling still errors (issue 0076 preserved). 2. Raw identifier is never a type. `parseTypeExpr`'s atom rejects a raw identifier in type position (`x : `s2 = 1`, `List(`s2)`) with an accurate diagnostic instead of silently type-classifying it. 3. Reserved-name function bare-callable. A bare `s2(4)` parses its callee as a `.type_expr` (reserved spelling); `lowerCall` now rewrites a type_expr callee to an identifier when a function of that name is in scope, so a backtick-declared sx fn and a `#import c` foreign fn whose C name collides with a reserved type spelling both resolve by their bare name. (`TypeName(val)` is not a cast, so there is no ambiguity.) Tests: examples/0152 (every control-flow/capture form + bare ref/call/member access), examples/1054 (catch/onfail tag bindings), examples/1139 (raw in type position rejected), examples/1220 extended (foreign reserved-name function bare-call). 0076 negatives 1119/1121/1122/1123/1124/1125 stay green. Gate: zig build + zig build test + 422 examples pass. specs.md + readme.md updated; issues/0089 RESOLVED banner refreshed.
This commit is contained in:
37
src/ast.zig
37
src/ast.zig
@@ -188,6 +188,10 @@ pub const StringLiteral = struct {
|
||||
|
||||
pub const Identifier = struct {
|
||||
name: []const u8,
|
||||
/// True when written as a backtick raw identifier (`` `s2 ``). Carried so a
|
||||
/// destructure target (`` `s2, b := … ``) can be recognised as raw and
|
||||
/// exempted from the reserved-type-name binding check (issue 0089).
|
||||
is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const EnumLiteral = struct {
|
||||
@@ -277,6 +281,9 @@ pub const IfExpr = struct {
|
||||
is_comptime: bool = false, // true for `inline if` — compile-time branch elimination
|
||||
binding_name: ?[]const u8 = null, // for `if val := expr { ... }` optional binding
|
||||
binding_span: ?Span = null, // span of `binding_name` (set iff `binding_name` is)
|
||||
/// True when the optional binding was a backtick raw identifier
|
||||
/// (`` if `s2 := … ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
binding_is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const MatchExpr = struct {
|
||||
@@ -291,6 +298,9 @@ pub const MatchArm = struct {
|
||||
is_break: bool,
|
||||
capture: ?[]const u8 = null, // payload binding name: case .variant: (name) { ... }
|
||||
capture_span: ?Span = null, // span of `capture` (set iff `capture` is)
|
||||
/// True when the capture was a backtick raw identifier
|
||||
/// (`` case .v: (`s2) ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
capture_is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const ConstDecl = struct {
|
||||
@@ -341,6 +351,10 @@ pub const MultiAssign = struct {
|
||||
pub const DestructureDecl = struct {
|
||||
names: []const []const u8,
|
||||
name_spans: []const Span, // one per entry in `names`, same order
|
||||
/// One per entry in `names`, same order: true when that target was a
|
||||
/// backtick raw identifier (`` `s2, b := … ``) — exempt from the
|
||||
/// reserved-type-name binding check (issue 0089).
|
||||
name_is_raw: []const bool,
|
||||
value: *Node,
|
||||
};
|
||||
|
||||
@@ -462,6 +476,9 @@ pub const CatchExpr = struct {
|
||||
operand: *Node,
|
||||
binding: ?[]const u8 = null,
|
||||
binding_span: ?Span = null, // span of `binding` (set iff `binding` is)
|
||||
/// True when the binding was a backtick raw identifier
|
||||
/// (`` x catch `s2 { … } ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
binding_is_raw: bool = false,
|
||||
body: *Node,
|
||||
is_match_body: bool = false,
|
||||
};
|
||||
@@ -472,6 +489,9 @@ pub const CatchExpr = struct {
|
||||
pub const OnFailStmt = struct {
|
||||
binding: ?[]const u8 = null,
|
||||
binding_span: ?Span = null, // span of `binding` (set iff `binding` is)
|
||||
/// True when the binding was a backtick raw identifier
|
||||
/// (`` onfail `s2 { … } ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
binding_is_raw: bool = false,
|
||||
body: *Node,
|
||||
};
|
||||
|
||||
@@ -566,6 +586,9 @@ pub const WhileExpr = struct {
|
||||
body: *Node,
|
||||
binding_name: ?[]const u8 = null, // for `while val := expr { ... }` optional binding
|
||||
binding_span: ?Span = null, // span of `binding_name` (set iff `binding_name` is)
|
||||
/// True when the optional binding was a backtick raw identifier
|
||||
/// (`` while `s2 := … ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
binding_is_raw: bool = false,
|
||||
};
|
||||
|
||||
pub const ForExpr = struct {
|
||||
@@ -573,8 +596,14 @@ pub const ForExpr = struct {
|
||||
body: *Node,
|
||||
capture_name: []const u8,
|
||||
capture_span: ?Span = null, // span of `capture_name` (null when omitted, e.g. `for 0..N { }`)
|
||||
/// True when `capture_name` was a backtick raw identifier
|
||||
/// (`` for xs: (`s2) ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
capture_is_raw: bool = false,
|
||||
index_name: ?[]const u8 = null,
|
||||
index_span: ?Span = null, // span of `index_name` (set iff `index_name` is)
|
||||
/// True when `index_name` was a backtick raw identifier
|
||||
/// (`` for xs: (x, `s2) ``) — exempt from the reserved-type-name check (issue 0089).
|
||||
index_is_raw: bool = false,
|
||||
/// Range form `for start..end (i) { }`: `iterable` is the start, `range_end`
|
||||
/// the (exclusive) end. Null for the iterate-a-collection form
|
||||
/// (`for coll : (x) { }`). For the range form `capture_name` is the cursor
|
||||
@@ -663,6 +692,10 @@ pub const ProtocolMethodDecl = struct {
|
||||
params: []const *Node, // type_expr nodes for parameter types (excluding implicit self)
|
||||
param_names: []const []const u8, // parameter names (excluding implicit self)
|
||||
param_name_spans: []const Span = &.{}, // one per `param_names` entry; empty for synthesized methods
|
||||
/// One per `param_names` entry: true when written as a backtick raw
|
||||
/// identifier — exempt from the reserved-type-name check (issue 0089).
|
||||
/// Empty for synthesized methods (treated as all-false).
|
||||
param_name_is_raw: []const bool = &.{},
|
||||
return_type: ?*Node, // null = void return
|
||||
default_body: ?*Node, // null = required method, non-null = default implementation
|
||||
};
|
||||
@@ -689,6 +722,10 @@ pub const ForeignMethodDecl = struct {
|
||||
params: []const *Node, // type_expr nodes — first is `*Self` for instance methods
|
||||
param_names: []const []const u8,
|
||||
param_name_spans: []const Span = &.{}, // one per `param_names` entry; empty for synthesized methods
|
||||
/// One per `param_names` entry: true when written as a backtick raw
|
||||
/// identifier — exempt from the reserved-type-name check (issue 0089).
|
||||
/// Empty for synthesized methods (treated as all-false).
|
||||
param_name_is_raw: []const bool = &.{},
|
||||
return_type: ?*Node, // null = void
|
||||
is_static: bool = false, // true for `static name :: ...`
|
||||
jni_descriptor_override: ?[]const u8 = null, // `#jni_method_descriptor("(Sig)Ret")` — JNI runtime only
|
||||
|
||||
Reference in New Issue
Block a user