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:
agra
2026-06-12 09:31:53 +03:00
parent 515ecebea7
commit d8076b9333
1054 changed files with 6836 additions and 6839 deletions

View File

@@ -38,8 +38,8 @@ game rebuilt.
<details><summary>Prior steps (2026-05-25 era)</summary>
- **`resolveType(null) → .s64` silent fallback removed.** `resolveType`
now takes a non-optional `*const Node`; the `null → .s64` branch is
- **`resolveType(null) → .i64` silent fallback removed.** `resolveType`
now takes a non-optional `*const Node`; the `null → .i64` branch is
gone. Callers that legitimately had no annotation handle it
themselves: top-level `var_decl` at `lower.zig:630` infers from the
initializer or diagnoses if neither is present (matches the
@@ -54,7 +54,7 @@ game rebuilt.
...`), which makes the always-non-null path obvious from the type.
Real-world impact: `g_pi := 3.14;` at the top level used to be
silently typed as `s64`. Now it infers as `f64`. Regression at
silently typed as `i64`. Now it infers as `f64`. Regression at
`examples/137-toplevel-var-type-inference.sx` (count/pi/flag — int /
float / bool inferred correctly). 159/159 example tests + chess
clean.
@@ -161,7 +161,7 @@ game rebuilt.
recursive heap content).
Also closes the type-inference half of the same bug: `NAME :: #run
expr;` with no annotation used to default to `s64` (silent fallback
expr;` with no annotation used to default to `i64` (silent fallback
in `resolveType(null)`). `lowerComptimeGlobal` now infers from the
expression's return type when no annotation is provided. The
silent fallback in `resolveType` itself is left in place for other
@@ -255,7 +255,7 @@ Phase 0 spike outcomes:
inst.zig BuiltinId, lower.zig (registry + return-type + reflection
handler), interp.zig (fallback), sema.zig (allowed-builtins list),
lsp/server.zig (both completion tables), library/modules/std.sx.
Smoke coverage added in `examples/50-smoke.sx` (u8/s32/s64/Point).
Smoke coverage added in `examples/50-smoke.sx` (u8/i32/i64/Point).
- **0.7** `#import` transitivity — surfaced and fixed via issue-0038.
- **0.8** `#foreign("c")` rename syntax — confirmed
`#foreign libc "name"`.
@@ -270,7 +270,7 @@ verification: `size_of(*u8)=8`, `size_of(Ptr where Ptr::*u8)=8`,
`size_of(?u8)=2`, `size_of(Maybe where Maybe::?u8)=2` — all clean on
interp + codegen.
Also landed during 0041/0042: the silent `.s64` fallback in
Also landed during 0041/0042: the silent `.i64` fallback in
`resolveTypeArg` is gone — unresolved type names now emit a real
diagnostic. Surfaced and removed two bogus `size_of(Complex)` /
`size_of(Sx)` calls in `examples/10-generic-struct.sx` that were
@@ -334,7 +334,7 @@ What landed:
store honours the destination width — no more "assume 8 bytes"
silent clobber. Regression test at
`examples/132-comptime-typed-store-widths.sx` exercises every
primitive width (u8/u16/u32/u64, s8..s64, bool, f32, f64) via
primitive width (u8/u16/u32/u64, i8..i64, bool, f32, f64) via
comptime checksums compared to runtime checksums.
- Call-convention mismatch at bare-fn → fn-pointer coercion is now
a compile error (commit `f886d5f`). The chess-debug sweep that
@@ -563,7 +563,7 @@ Allocator value naturally.
builds) + m3te (23/23). Suite 582/582, zbt 0. Discriminator note:
Obj-C `.alloc()` is zero-arg; Allocator `.alloc(size)` has an arg —
the sed keyed on `\.alloc\((?!\))`.
- **2026-05-25 (latest)** — `resolveType(null) → .s64` removed.
- **2026-05-25 (latest)** — `resolveType(null) → .i64` removed.
Signature changed to non-optional `*const Node`; 12 callers
surveyed and classified. The three unguarded ones — top-level
`var_decl` at `lower.zig:630` (now mirrors lowerVarDecl's
@@ -573,7 +573,7 @@ Allocator value naturally.
`if (x != null)` blocks; cleaned up to optional-payload syntax.
`examples/137-toplevel-var-type-inference.sx` proves the visible
win: `g_pi := 3.14;` at module scope now infers `f64` (used to be
silent `s64`). 159/159 + chess clean.
silent `i64`). 159/159 + chess clean.
- **2026-05-25 (penultimate)** — Phase 1.4a shipped. `valueToLLVMConst`
takes IR `TypeId` (not LLVM type) + an interpreter handle.
String/slice fat pointers are serialized by capturing the
@@ -616,8 +616,8 @@ Allocator value naturally.
at line 676 now passes `global.name` so the diagnostic locates the
offending `#run` site. `lowerComptimeGlobal` (`lower.zig:6384`)
infers the return type from the expression when the user omits
the type annotation — closes the silent-s64 default for `NAME ::
#run expr;` bindings. The broader `resolveType(null) -> .s64`
the type annotation — closes the silent-i64 default for `NAME ::
#run expr;` bindings. The broader `resolveType(null) -> .i64`
fallback is left in place for other callers — flagged for a
follow-up audit. Regression at
`examples/134-comptime-aggregate-global.sx`. 156/156 + chess green.
@@ -687,7 +687,7 @@ Allocator value naturally.
(`Tracer.count = 1`) — interp + codegen parity. 152/152 +
chess green.
- **2026-05-24** — issue-0041 and issue-0042 both fixed end-to-end.
Also removed the silent `.s64` fallback in `resolveTypeArg`,
Also removed the silent `.i64` fallback in `resolveTypeArg`,
guarded the two upstream callers (`buildTypeBindings`,
`inferGenericReturnType`) with `type_bridge.isTypeShapedAstNode`,
and fixed three parser regressions introduced by the 0041 work
@@ -759,8 +759,8 @@ Allocator value naturally.
`mi.ret_type == void_ptr`, but `*void` is overloaded — both
Self-disguised-as-*void AND a literal `-> *void` return appear as
the same `TypeId`. With `target_type` leaking from the enclosing
function's return type (e.g. `main -> s32`), every `*void` return
was loaded as `s32`, yielding 0 → null. Fix: stash `ret_is_self`
function's return type (e.g. `main -> i32`), every `*void` return
was loaded as `i32`, yielding 0 → null. Fix: stash `ret_is_self`
on `ProtocolMethodInfo` during `registerProtocolDecl` (set when
the AST return-type node is the `Self` type-expr), and gate the
unbox on that flag. Regression at
@@ -781,12 +781,12 @@ Allocator value naturally.
## Known issues (discovered during execution)
### ISSUE-MEM-001: Type inference defaults `p := malloc(64)` to `s64`
### ISSUE-MEM-001: Type inference defaults `p := malloc(64)` to `i64`
**Severity:** medium (workaround exists; bites unexpectedly).
**Symptom:** Writing `p := malloc(64)` (no explicit type) infers
`p: s64` instead of `p: *void`. Subsequent `free(p)` then fails LLVM
`p: i64` instead of `p: *void`. Subsequent `free(p)` then fails LLVM
verification with "Call parameter type does not match function
signature!" because `free` expects `ptr` but receives `i64`.
@@ -795,8 +795,8 @@ or `xx malloc(64);` at the call site.
**Reproduction:**
```sx
main :: () -> s32 {
p := malloc(64); // p inferred as s64
main :: () -> i32 {
p := malloc(64); // p inferred as i64
free(p); // LLVM verify fails: ptr expected, i64 given
0;
}
@@ -804,7 +804,7 @@ main :: () -> s32 {
**Root cause:** Likely in the inference path for `:=` declarations
when the RHS is a `*void`-returning #builtin. The compiler defaults
the binding to s64 instead of matching the return type. To
the binding to i64 instead of matching the return type. To
investigate in a future session.
**Status:** Open. Not blocking mem.sx work but worth fixing as a
@@ -920,9 +920,9 @@ where users need the underlying state (TrackingAllocator).
its auto-unbox path on `mi.ret_type == void_ptr`, but the same
`TypeId` covers both Self-disguised-as-*void and a literal
`-> *void`. With `target_type` leaking from the surrounding
function (e.g. `main -> s32`), every protocol call returning
function (e.g. `main -> i32`), every protocol call returning
`*void` got its result loaded as `sizeof(target_type)` bytes — for
`s32` that's the first 4 bytes of the malloc'd block, which were
`i32` that's the first 4 bytes of the malloc'd block, which were
zero, comparing equal to null.
**Fix:** Tag `ProtocolMethodInfo` with `ret_is_self: bool`, set in