feat(lang): backtick raw-identifier escape + #import c foreign-name exemption [F0.6]
Reserved type-name spellings (s1, s2, u8, …) can now be used as value identifiers two ways, resolving issue 0089: 1. Backtick raw identifier: a leading backtick (`s2) lexes to an .identifier token carrying a new Token.is_raw flag, with the backtick excluded from the text. A raw identifier is never type-classified — the parser skips Type.fromName for it — so it is always a value identifier. The flag threads to VarDecl.is_raw / Param.is_raw at binding sites, and the reserved-type-name check (UnknownTypeChecker) skips raw bindings. Because the token tag stays .identifier, the escape works in every position (local, global, param, field, fn name, struct member, later reference) with no per-site parser change. 2. #import c exemption: c_import.zig synthesizes foreign decls with Param.is_raw = true, so generated C param names that collide with reserved type names (s1, s2) import unedited. A bare reserved-name binding in sx still errors (issue 0076 preserved): the is_raw-gated skip only fires for backtick / foreign names, and a raw binding's address-of / autoref lowering stays correct because every occurrence is an .identifier, never a .type_expr. Tests: examples/0151 (backtick, every position), examples/1220 (foreign exemption, compiled+run), lexer unit tests. 1119 (bare-binding rejection) stays green. specs.md + readme.md updated.
This commit is contained in:
44
specs.md
44
specs.md
@@ -13,6 +13,50 @@ Line comments start with `//` and extend to end of line.
|
||||
- UPPER_SNAKE_CASE for constants: `SOME_INT`, `SOME_STR`
|
||||
- PascalCase for types: `Foo`
|
||||
|
||||
#### Reserved type names
|
||||
|
||||
A spelling that names a builtin type — the arbitrary-width integers `s1`..`s64` /
|
||||
`u1`..`u64`, plus `bool`, `string`, `void`, `f32`, `f64`, `usize`, `isize`, `Any` —
|
||||
is reserved. A bare value binding (`:=` / typed local / parameter name) spelled as
|
||||
one of these is rejected: such a spelling parses as a *type*, not a value, so the
|
||||
address-of / autoref paths would mis-lower it.
|
||||
|
||||
```sx
|
||||
s2 := 2.5; // ERROR: 's2' is a reserved type name and cannot be used as an identifier
|
||||
```
|
||||
|
||||
#### Backtick raw-identifier escape
|
||||
|
||||
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.
|
||||
|
||||
```sx
|
||||
`s2 := 2.5; // OK — value identifier "s2", distinct from the s2 type
|
||||
print("{}\n", `s2); // 2.5
|
||||
```
|
||||
|
||||
The escape works in every identifier position — local, global, parameter, struct
|
||||
field, function name, and a later reference:
|
||||
|
||||
```sx
|
||||
`u8 := 100; // global
|
||||
`s2 :: (`s1: s64) -> s64 { `s1 } // function name + parameter
|
||||
P :: struct { `s2: f64; } // struct field
|
||||
```
|
||||
|
||||
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
|
||||
hand-written sx code.
|
||||
|
||||
### Literals
|
||||
|
||||
| Kind | Examples | Type |
|
||||
|
||||
Reference in New Issue
Block a user