lang: rename signed integer types sN -> iN
Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
> never the reserved keyword/type." The backtick is never part of the name's text.
|
||||
>
|
||||
> 1. **Backtick raw identifier.** The lexer recognises a leading backtick
|
||||
> (`` `s2 ``) and emits an `.identifier` token whose span excludes the backtick,
|
||||
> (`` `i2 ``) and emits an `.identifier` token whose span excludes the backtick,
|
||||
> carrying a `Token.is_raw` flag ([src/lexer.zig], [src/token.zig]). The flag
|
||||
> threads through `ast.Identifier`, `ast.TypeExpr`, and EVERY binding / capture /
|
||||
> declaration node ([src/ast.zig]): `VarDecl` / `ConstDecl` / `Param` / `FnDecl`
|
||||
@@ -19,19 +19,19 @@
|
||||
> `NamespaceDecl` / `ImportDecl` / `CImportDecl` / `LibraryDecl`.
|
||||
>
|
||||
> - **Value position.** The parser skips `Type.fromName` for a raw identifier
|
||||
> in expression position ([src/parser.zig] `parsePrimary`), so `` `s2 `` is a
|
||||
> in expression position ([src/parser.zig] `parsePrimary`), so `` `i2 `` is a
|
||||
> value identifier; a later bare reference resolves to the binding.
|
||||
> - **Type position.** `parseTypeExpr` sets the raw flag on the type ATOM and
|
||||
> lets it flow through the SAME continuations as a bare name (attempt 5), so a
|
||||
> raw reference parameterizes a reserved-spelled template (`` `s2(s64) ``) and
|
||||
> raw reference parameterizes a reserved-spelled template (`` `i2(i64) ``) and
|
||||
> composes under the pointer / optional / slice wrappers; `ParameterizedTypeExpr`
|
||||
> carries `is_raw` and `resolveParameterizedWithBindings` skips the `Vector`
|
||||
> intrinsic when raw. Resolution skips the builtin classifier
|
||||
> (`TypeResolver.resolveNamed`'s `skip_builtin`, threaded from `te.is_raw` in
|
||||
> [src/ir/lower.zig] and [src/ir/type_bridge.zig]) and looks up a
|
||||
> `` `s2 ``-declared type (struct / enum / union / alias), else a NORMAL
|
||||
> "unknown type 's2'" error (`UnknownTypeChecker.reportIfUnknownType` skips the
|
||||
> builtin-name exemption when raw). A bare `s2` in type position is still the
|
||||
> `` `i2 ``-declared type (struct / enum / union / alias), else a NORMAL
|
||||
> "unknown type 'i2'" error (`UnknownTypeChecker.reportIfUnknownType` skips the
|
||||
> builtin-name exemption when raw). A bare `i2` in type position is still the
|
||||
> builtin int. The SECOND (editor/LSP) classifier in [src/sema.zig]
|
||||
> (`Type.fromTypeExpr` / `resolveTypeNode` / `resolveTypeNameStr`) honors
|
||||
> `is_raw` too, so a backtick reserved-name annotation resolves to the user type
|
||||
@@ -40,9 +40,9 @@
|
||||
> `PointerTypeInfo` / `OptionalTypeInfo` / `SliceTypeInfo` / `ManyPointerTypeInfo`
|
||||
> / `ArrayTypeInfo` each store a REQUIRED `is_raw` ([src/types.zig], no default,
|
||||
> so a future construction site cannot drop it) that every `resolveTypeNameStr`
|
||||
> call passes as its `skip_builtin` — so `` *`s2 ``, `` ?`s2 ``, `` [N]`s2 ``,
|
||||
> `` []`s2 ``, `` [*]`s2 `` field-access / unwrap / index / deref in the editor
|
||||
> index all reach the user type instead of reclassifying the inner `s2` to the
|
||||
> call passes as its `skip_builtin` — so `` *`i2 ``, `` ?`i2 ``, `` [N]`i2 ``,
|
||||
> `` []`i2 ``, `` [*]`i2 `` field-access / unwrap / index / deref in the editor
|
||||
> index all reach the user type instead of reclassifying the inner `i2` to the
|
||||
> builtin (the divergence the DIRECT-only attempt left for compound forms).
|
||||
> - **Declaration position.** A bare reserved-name declaration of EVERY kind
|
||||
> still errors (issue 0076 preserved); the backtick form is exempt. The check
|
||||
@@ -54,7 +54,7 @@
|
||||
> symmetry is enforced structurally for the bug-prone node: `ConstDecl`'s
|
||||
> `name_span` + `is_raw` carry NO default (attempt 5), so the compiler rejects
|
||||
> any construction site — including the two struct-body const forms (untyped
|
||||
> `` `s2 :: 5 `` and typed `` `s2 : T : v ``) that previously dropped both —
|
||||
> `` `i2 :: 5 `` and typed `` `i2 : T : v ``) that previously dropped both —
|
||||
> that omits them. `FnDecl` is built at every parser site through `parseFnDecl`,
|
||||
> whose `name_is_raw` is a REQUIRED parameter (the equivalent guarantee); the
|
||||
> type decls likewise route through parse-functions taking `name_is_raw`.
|
||||
@@ -66,31 +66,31 @@
|
||||
> / `union_decl` / `enum_decl` / `protocol_decl` arms
|
||||
> ([src/ir/semantic_diagnostics.zig]) check only the *type* name (and method
|
||||
> *params*), not field / tag / variant / method-signature names. The backtick
|
||||
> is optional there (`obj.s2` and `` obj.`s2 `` resolve to the same member).
|
||||
> is optional there (`obj.i2` and `` obj.`i2 `` resolve to the same member).
|
||||
> This bare member-name exemption covers only the **identifier-classified**
|
||||
> reserved spellings — `s1`..`s64`, `u1`..`u64`, `bool`, `string`, `void`,
|
||||
> reserved spellings — `i1`..`i64`, `u1`..`u64`, `bool`, `string`, `void`,
|
||||
> `usize`, `isize`, `Any` — which all lex as ordinary identifiers. The two
|
||||
> **keyword-classified** spellings, `f32` and `f64`, are lexer keywords
|
||||
> ([src/token.zig]), and a member-name slot requires an identifier token
|
||||
> ([src/parser.zig]); a bare `f32` / `f64` is therefore rejected at parse
|
||||
> (`expected field name in struct`) even in a member position, and still needs
|
||||
> the backtick there too — `` struct { `f32: s64; } `` / `` union { `f64: … } ``
|
||||
> / `` protocol { `f32 :: () -> s64; } `` work as field / tag / method names.
|
||||
> the backtick there too — `` struct { `f32: i64; } `` / `` union { `f64: … } ``
|
||||
> / `` protocol { `f32 :: () -> i64; } `` work as field / tag / method names.
|
||||
> The exemption stops at member *definitions*: an `impl` method is a real
|
||||
> function reached through the `impl_block` → `fn_decl` arm, so a
|
||||
> reserved-spelled impl method needs the backtick (`` `s2 :: (self) ``), no
|
||||
> reserved-spelled impl method needs the backtick (`` `i2 :: (self) ``), no
|
||||
> more exempt than a free function (cf. `examples/1122`). Pinned by
|
||||
> `examples/0158-types-reserved-name-member-exempt.sx`.
|
||||
> 2. **`#import c` foreign-name exemption.** `c_import.zig` synthesizes foreign
|
||||
> `#foreign` decls with `Param.is_raw = true` (and the synthesized `FnDecl`
|
||||
> `is_raw = true`), so generated C names that collide with reserved type names
|
||||
> (`s1`, `s2`) import unedited and a reserved-name foreign fn is bare-callable.
|
||||
> (`i1`, `i2`) import unedited and a reserved-name foreign fn is bare-callable.
|
||||
>
|
||||
> **Bare-callable foreign / backtick fn.** `lowerCall` rewrites a `.type_expr`
|
||||
> callee to an identifier when a function **of RAW provenance** of that name is in
|
||||
> scope ([src/ir/lower.zig]) — scoped to the callee `FnDecl`'s `is_raw` flag, so it
|
||||
> only ever fires for a backtick / `#import c` foreign fn (the decl check guarantees
|
||||
> no bare reserved-name fn exists). `s2(4)` resolves to the function (`TypeName(val)`
|
||||
> no bare reserved-name fn exists). `i2(4)` resolves to the function (`TypeName(val)`
|
||||
> is not a cast).
|
||||
>
|
||||
> **Regression tests.** `examples/0151-types-backtick-raw-identifier.sx` (every
|
||||
@@ -98,7 +98,7 @@
|
||||
> control-flow / capture form), `examples/0153-types-backtick-const-fn-decl.sx`
|
||||
> (backtick `::` const + fn decl, bare + backtick call),
|
||||
> `examples/0154-types-backtick-raw-type-reference.sx` (raw in TYPE position —
|
||||
> struct / enum / union / alias decl + reference; bare `s2` still the int),
|
||||
> struct / enum / union / alias decl + reference; bare `i2` still the int),
|
||||
> `examples/0155-types-backtick-typed-const-union-tag.sx` (typed const + union tag),
|
||||
> `examples/0156-types-backtick-struct-const.sx` (struct-body const, untyped + typed),
|
||||
> `examples/0157-types-backtick-parameterized-raw-type.sx` (raw parameterized type +
|
||||
@@ -117,8 +117,8 @@
|
||||
> caret on the name). Backtick lexer + `resolveNamed(skip_builtin)` unit tests in
|
||||
> `src/lexer.zig` / `src/ir/type_resolver.test.zig`; the editor/LSP raw-type
|
||||
> resolution (the second classifier) is pinned in `src/sema.test.zig` — the direct
|
||||
> case plus raw provenance through every compound shape (`` *`s2 `` field access,
|
||||
> `` ?`s2 `` unwrap, `` [N]`s2 `` index, parameterized `` `s2(s64) ``), each with a
|
||||
> case plus raw provenance through every compound shape (`` *`i2 `` field access,
|
||||
> `` ?`i2 `` unwrap, `` [N]`i2 `` index, parameterized `` `i2(i64) ``), each with a
|
||||
> bare-spelling control that stays the builtin (fail-before verified).
|
||||
>
|
||||
> The original report is preserved below.
|
||||
@@ -129,12 +129,12 @@
|
||||
|
||||
Importing non-sx source whose names collide with sx reserved type names is
|
||||
rejected. `library/modules/stb_truetype.sx` is a `#import c { ... }` block over a
|
||||
vendored C header (`vendors/stb_truetype/stb_truetype.h`); C identifiers `s1`,
|
||||
`s2` (which collide with sx's signed-int type keywords `s1`..`sN`) produce:
|
||||
vendored C header (`vendors/stb_truetype/stb_truetype.h`); C identifiers `i1`,
|
||||
`i2` (which collide with sx's signed-int type keywords `i1`..`sN`) produce:
|
||||
|
||||
```
|
||||
error: 's1' is a reserved type name and cannot be used as an identifier
|
||||
error: 's2' is a reserved type name and cannot be used as an identifier
|
||||
error: 'i1' is a reserved type name and cannot be used as an identifier
|
||||
error: 'i2' is a reserved type name and cannot be used as an identifier
|
||||
```
|
||||
|
||||
The user cannot hand-edit these — they are generated from the vendored C header.
|
||||
@@ -143,13 +143,13 @@ identifier even when it wants to.
|
||||
|
||||
## Root cause
|
||||
|
||||
The parser classifies any reserved-type-name spelling (`s2`, `u8`, `f64`, …) as a
|
||||
The parser classifies any reserved-type-name spelling (`i2`, `u8`, `f64`, …) as a
|
||||
`.type_expr` via `name_class.Type.fromName`, never as an `.identifier`. The F0.1 /
|
||||
issue-0076 fix added `UnknownTypeChecker.checkBindingName`
|
||||
(`src/ir/semantic_diagnostics.zig`) to reject a value binding / param spelled as
|
||||
a reserved type name (the `.type_expr`-vs-`.identifier` mismatch otherwise breaks
|
||||
address-of / autoref lowering). F0.1 deliberately extended this check to imported
|
||||
declarations — which is what now fires on the C-imported `s1`/`s2`.
|
||||
declarations — which is what now fires on the C-imported `i1`/`i2`.
|
||||
|
||||
## Desired behaviour (Agra ruling)
|
||||
|
||||
@@ -164,12 +164,12 @@ mechanisms:
|
||||
reserved-name rule:
|
||||
|
||||
```sx
|
||||
`s2 := 2.5; // OK — identifier "s2", distinct from the s2 signed-int type
|
||||
s2 := 2.5; // ERROR — bare s2 is still the reserved type name
|
||||
`i2 := 2.5; // OK — identifier "i2", distinct from the i2 signed-int type
|
||||
i2 := 2.5; // ERROR — bare i2 is still the reserved type name
|
||||
```
|
||||
|
||||
Prefix form (single leading backtick on the identifier). The raw identifier's
|
||||
TEXT is `s2` (the backtick is not part of the name). A bare `s2` used as a TYPE
|
||||
TEXT is `i2` (the backtick is not part of the name). A bare `i2` used as a TYPE
|
||||
remains the signed-int type.
|
||||
|
||||
## Reproduction
|
||||
@@ -179,10 +179,10 @@ sx-side (minimal):
|
||||
```sx
|
||||
#import "modules/std.sx";
|
||||
main :: () {
|
||||
`s2 := 2.5; // must compile: identifier s2 = 2.5
|
||||
print("{}\n", `s2); // 2.5
|
||||
`i2 := 2.5; // must compile: identifier i2 = 2.5
|
||||
print("{}\n", `i2); // 2.5
|
||||
}
|
||||
```
|
||||
|
||||
Import-side: a `#import c` block over a header declaring `int s1, s2;` (or
|
||||
Import-side: a `#import c` block over a header declaring `int i1, i2;` (or
|
||||
`stb_truetype.sx`) must NOT emit the reserved-type-name error.
|
||||
|
||||
Reference in New Issue
Block a user