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:
agra
2026-06-04 18:31:08 +03:00
parent 0dbdc530ba
commit 640f59dc54
23 changed files with 356 additions and 56 deletions

View File

@@ -29,32 +29,50 @@ s2 := 2.5; // ERROR: 's2' is a reserved type name and cannot be used as an ide
A leading backtick makes the following identifier **raw**: its text excludes the
backtick and it is never type-classified, so a reserved-type-name spelling can be
used as an ordinary value identifier. The backtick is required at every occurrence
of that identifier (declaration and each reference); a *bare* `s2` is still the
signed-int type.
used as an ordinary value identifier. The backtick is required at the **binding
site** — the declaration that introduces the name — to escape the reserved-name
rule. A later reference is resolved by position: in **value** position a bare `s2`
resolves to the binding; in **type** position a bare `s2` is still the signed-int
type.
```sx
`s2 := 2.5; // OK — value identifier "s2", distinct from the s2 type
print("{}\n", `s2); // 2.5
print("{}\n", `s2); // 2.5 (backtick reference)
print("{}\n", s2); // 2.5 (bare reference, resolves to the binding)
x : s2 = 3; // bare `s2` in TYPE position is still the s2 type
```
The escape works in every identifier position — local, global, parameter, struct
field, function name, and a later reference:
A raw identifier is a value name and is **never a type**: using one in type
position (`x : `s2 = 1`) is a parse error.
The escape works in **every identifier position** — local, global, parameter,
struct field, function name, a later reference, and every control-flow / capture /
binding form: a destructure name, an `if` / `while` optional binding, a `for`
capture and index, a match-arm capture, and a `catch` / `onfail` tag binding:
```sx
`u8 := 100; // global
`s2 :: (`s1: s64) -> s64 { `s1 } // function name + parameter
P :: struct { `s2: f64; } // struct field
`u8, rest := pair(); // destructure name
if `s16 := maybe() { } // optional binding
for xs: (`bool, `u16) { } // for capture + index
x catch `s2 { } // catch tag binding
```
A reserved-spelled **function** is bare-callable: `` `s2 :: (n: s64) -> s64 { … } ``
can be invoked as `s2(10)` (the callee spelling parses as a type but resolves to
the function when one of that name is in scope; `TypeName(val)` is not a cast).
A backtick may also escape a keyword spelling (`` `for ``, `` `struct ``), yielding
an identifier with that text.
**`#import c` exemption.** Foreign declarations synthesized by an `#import c { … }`
block are treated as raw automatically: a generated C parameter or name that
collides with a reserved type name (e.g. `s1`, `s2`) imports unedited, with no
backticks and no reserved-name error. The exemption is scoped to the foreign decls —
it does not make a foreign `s2` usable as the sx `s2` type, nor relax the rule for
block are treated as raw automatically: a generated C parameter or function name
that collides with a reserved type name (e.g. `s1`, `s2`) imports unedited, with no
backticks and no reserved-name error, and a foreign reserved-name function is
bare-callable by its C name. The exemption is scoped to the foreign decls — it does
not make a foreign `s2` usable as the sx `s2` type, nor relax the rule for
hand-written sx code.
### Literals