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:
38
specs.md
38
specs.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user