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

@@ -72,16 +72,16 @@ test "calls: builtin and reflection result types, unknown fallthrough" {
var args = [_]*Node{&arg};
const cases = [_]struct { name: []const u8, want: TypeId }{
.{ .name = "size_of", .want = .s64 },
.{ .name = "align_of", .want = .s64 },
.{ .name = "size_of", .want = .i64 },
.{ .name = "align_of", .want = .i64 },
// Reflection builtins (resolved by callee name, outside the
// `resolveBuiltin` table) — each must keep its own result tag so a
// pack-fn caller boxes the value with the right type.
.{ .name = "type_name", .want = .string },
.{ .name = "type_eq", .want = .bool },
.{ .name = "has_impl", .want = .bool },
.{ .name = "field_count", .want = .s64 },
.{ .name = "field_index", .want = .s64 },
.{ .name = "field_count", .want = .i64 },
.{ .name = "field_index", .want = .i64 },
.{ .name = "field_name", .want = .string },
.{ .name = "error_tag_name", .want = .string },
.{ .name = "is_comptime", .want = .bool },
@@ -110,15 +110,15 @@ test "calls: cast result type is its resolved type argument" {
defer module.deinit();
var l = Lowering.init(&module);
// `cast(s64) x` types as the resolved target type — the first arg is the
// `cast(i64) x` types as the resolved target type — the first arg is the
// type expression, resolved via `resolveTypeArg` (a primitive needs no
// scope / registration).
var target = node(.{ .type_expr = .{ .name = "s64" } });
var target = node(.{ .type_expr = .{ .name = "i64" } });
var value = node(.{ .int_literal = .{ .value = 1 } });
var cast_args = [_]*Node{ &target, &value };
var cast_callee = node(.{ .identifier = .{ .name = "cast" } });
var cast_call = node(.{ .call = .{ .callee = &cast_callee, .args = &cast_args } });
try std.testing.expectEqual(TypeId.s64, l.inferExprType(&cast_call));
try std.testing.expectEqual(TypeId.i64, l.inferExprType(&cast_call));
}
test "calls: dot-shorthand enum construction types as the target type" {
@@ -136,8 +136,8 @@ test "calls: dot-shorthand enum construction types as the target type" {
try std.testing.expectEqual(TypeId.unresolved, l.inferExprType(&enum_call));
l.target_type = .s32;
try std.testing.expectEqual(TypeId.s32, l.inferExprType(&enum_call));
l.target_type = .i32;
try std.testing.expectEqual(TypeId.i32, l.inferExprType(&enum_call));
}
// ── Layer 2: the CallPlan object (kind / target / variant / properties) ─────
@@ -157,7 +157,7 @@ test "plan: builtin and reflection carry kind + target" {
const so = cr.plan(&so_call.data.call);
try std.testing.expectEqual(CallPlan.Kind.builtin, so.kind);
try std.testing.expectEqual(BuiltinId.size_of, so.target.builtin);
try std.testing.expectEqual(TypeId.s64, so.return_type);
try std.testing.expectEqual(TypeId.i64, so.return_type);
var tn_callee = node(.{ .identifier = .{ .name = "type_name" } });
var tn_call = node(.{ .call = .{ .callee = &tn_callee, .args = &args } });
@@ -190,13 +190,13 @@ test "plan: lazy free fn classifies as direct_fn and flags default-arg expansion
var l = Lowering.init(&module);
const cr = CallResolver{ .l = &l };
// greet :: (a: s64, b: s64 = 0) -> s64 — registered but NOT lowered, so
// greet :: (a: i64, b: i64 = 0) -> i64 — registered but NOT lowered, so
// it resolves through the AST (lazy) arm and `b`'s default is splice-able.
const params = [_]ast.Param{
.{ .name = "a", .name_span = .{ .start = 0, .end = 0 }, .type_expr = typeExpr(alloc, "s64") },
.{ .name = "b", .name_span = .{ .start = 0, .end = 0 }, .type_expr = typeExpr(alloc, "s64"), .default_expr = intLit(alloc, 0) },
.{ .name = "a", .name_span = .{ .start = 0, .end = 0 }, .type_expr = typeExpr(alloc, "i64") },
.{ .name = "b", .name_span = .{ .start = 0, .end = 0 }, .type_expr = typeExpr(alloc, "i64"), .default_expr = intLit(alloc, 0) },
};
const fd = ast.FnDecl{ .name = "greet", .params = &params, .return_type = typeExpr(alloc, "s64"), .body = emptyBody(alloc) };
const fd = ast.FnDecl{ .name = "greet", .params = &params, .return_type = typeExpr(alloc, "i64"), .body = emptyBody(alloc) };
l.program_index.fn_ast_map.put("greet", &fd) catch unreachable;
// greet(1) — omits `b`, so its default is spliced in.
@@ -206,7 +206,7 @@ test "plan: lazy free fn classifies as direct_fn and flags default-arg expansion
const p = cr.plan(&call.data.call);
try std.testing.expectEqual(CallPlan.Kind.direct_fn, p.kind);
try std.testing.expectEqualStrings("greet", p.target.named);
try std.testing.expectEqual(TypeId.s64, p.return_type);
try std.testing.expectEqual(TypeId.i64, p.return_type);
try std.testing.expect(p.expands_defaults);
try std.testing.expect(!p.prepends_receiver);
}
@@ -271,19 +271,19 @@ test "plan: closure and fn-pointer callees, __sx_ctx by calling convention" {
try std.testing.expect(p.prepends_ctx);
}
// fp : () -> s32 (default conv) — sx fn-pointer, carries ctx.
const fp_ty = module.types.functionType(&.{}, .s32);
// fp : () -> i32 (default conv) — sx fn-pointer, carries ctx.
const fp_ty = module.types.functionType(&.{}, .i32);
scope.put("fp", .{ .ref = Ref.none, .ty = fp_ty, .is_alloca = false });
{
const call = callNode(alloc, ident(alloc, "fp"), &.{});
const p = cr.plan(&call.data.call);
try std.testing.expectEqual(CallPlan.Kind.fn_pointer, p.kind);
try std.testing.expectEqual(TypeId.s32, p.return_type);
try std.testing.expectEqual(TypeId.i32, p.return_type);
try std.testing.expect(p.prepends_ctx);
}
// cfp : () -> s32 (C conv) — C fn-pointer, NO implicit ctx.
const cfp_ty = module.types.functionTypeCC(&.{}, .s32, .c);
// cfp : () -> i32 (C conv) — C fn-pointer, NO implicit ctx.
const cfp_ty = module.types.functionTypeCC(&.{}, .i32, .c);
scope.put("cfp", .{ .ref = Ref.none, .ty = cfp_ty, .is_alloca = false });
{
const call = callNode(alloc, ident(alloc, "cfp"), &.{});
@@ -302,9 +302,9 @@ test "plan: protocol dispatch selects method index + prepends receiver" {
var l = Lowering.init(&module);
const cr = CallResolver{ .l = &l };
// Drawable :: protocol { measure :: () -> s64; draw :: () -> bool; }
// Drawable :: protocol { measure :: () -> i64; draw :: () -> bool; }
const methods = [_]ast.ProtocolMethodDecl{
.{ .name = "measure", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "s64"), .default_body = null },
.{ .name = "measure", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "i64"), .default_body = null },
.{ .name = "draw", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "bool"), .default_body = null },
};
const pd = ast.ProtocolDecl{ .name = "Drawable", .methods = &methods };
@@ -329,12 +329,12 @@ test "plan: struct (UFCS) method via #compiler dispatch + prepends receiver" {
var l = Lowering.init(&module);
const cr = CallResolver{ .l = &l };
// struct Point, with a `#compiler` method Point.scale(self) -> s64.
// struct Point, with a `#compiler` method Point.scale(self) -> i64.
_ = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("Point"), .fields = &.{} } });
const self_param = ast.Param{ .name = "self", .name_span = .{ .start = 0, .end = 0 }, .type_expr = typeExpr(alloc, "Point") };
const params = [_]ast.Param{self_param};
const compiler_body = mk(alloc, .{ .compiler_expr = {} });
const method_fd = ast.FnDecl{ .name = "Point.scale", .params = &params, .return_type = typeExpr(alloc, "s64"), .body = compiler_body };
const method_fd = ast.FnDecl{ .name = "Point.scale", .params = &params, .return_type = typeExpr(alloc, "i64"), .body = compiler_body };
l.program_index.fn_ast_map.put("Point.scale", &method_fd) catch unreachable;
const recv = callNode(alloc, ident(alloc, "cast"), &[_]*Node{ typeExpr(alloc, "Point"), intLit(alloc, 0) });
@@ -342,7 +342,7 @@ test "plan: struct (UFCS) method via #compiler dispatch + prepends receiver" {
const p = cr.plan(&call.data.call);
try std.testing.expectEqual(CallPlan.Kind.struct_method, p.kind);
try std.testing.expectEqualStrings("Point.scale", p.target.named);
try std.testing.expectEqual(TypeId.s64, p.return_type);
try std.testing.expectEqual(TypeId.i64, p.return_type);
try std.testing.expect(p.prepends_receiver);
}
@@ -356,8 +356,8 @@ test "plan: foreign-class instance vs static dispatch" {
const cr = CallResolver{ .l = &l };
const members = [_]ast.ForeignClassMember{
.{ .method = .{ .name = "length", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "s64"), .is_static = false } },
.{ .method = .{ .name = "stringWithUTF8String", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "s64"), .is_static = true } },
.{ .method = .{ .name = "length", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "i64"), .is_static = false } },
.{ .method = .{ .name = "stringWithUTF8String", .params = &.{}, .param_names = &.{}, .return_type = typeExpr(alloc, "i64"), .is_static = true } },
};
var fcd = ast.ForeignClassDecl{ .name = "NSString", .foreign_path = "NSString", .runtime = .objc_class, .members = &members };
l.program_index.foreign_class_map.put("NSString", &fcd) catch unreachable;
@@ -371,7 +371,7 @@ test "plan: foreign-class instance vs static dispatch" {
try std.testing.expectEqual(CallPlan.Kind.foreign_instance, p.kind);
try std.testing.expectEqualStrings("length", p.target.foreign_method.name);
try std.testing.expect(!p.target.foreign_method.is_static);
try std.testing.expectEqual(TypeId.s64, p.return_type);
try std.testing.expectEqual(TypeId.i64, p.return_type);
try std.testing.expect(p.prepends_receiver);
}
// Static: `NSString.stringWithUTF8String(...)` — no receiver.
@@ -430,7 +430,7 @@ test "plan: free-function UFCS prepends receiver, distinct from namespace_fn" {
const cr = CallResolver{ .l = &l };
// struct Counter, and a FREE ufcs function `bump :: ufcs (c: Counter) ->
// s32` — NOT registered as `Counter.bump`, so it can only be reached via
// i32` — NOT registered as `Counter.bump`, so it can only be reached via
// UFCS. Dot-dispatch is OPT-IN: the fn carries `is_ufcs` and is
// registered in `fn_ast_map`, where the plan's opt-in gate reads it.
const counter = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("Counter"), .fields = &.{} } });
@@ -438,7 +438,7 @@ test "plan: free-function UFCS prepends receiver, distinct from namespace_fn" {
const params = [_]ast.Param{c_param};
const ret_stmt = mk(alloc, .{ .return_stmt = .{ .value = intLit(alloc, 7) } });
const body = mk(alloc, .{ .block = .{ .stmts = &[_]*Node{ret_stmt} } });
const fd = ast.FnDecl{ .name = "bump", .params = &params, .return_type = typeExpr(alloc, "s32"), .body = body, .is_ufcs = true };
const fd = ast.FnDecl{ .name = "bump", .params = &params, .return_type = typeExpr(alloc, "i32"), .body = body, .is_ufcs = true };
l.program_index.fn_ast_map.put("bump", &fd) catch unreachable;
l.lowerFunction(&fd, "bump", false);
const fid = l.resolveFuncByName("bump").?;
@@ -457,7 +457,7 @@ test "plan: free-function UFCS prepends receiver, distinct from namespace_fn" {
try std.testing.expectEqual(fid, p.target.func);
try std.testing.expect(p.prepends_receiver);
try std.testing.expect(p.prepends_ctx);
try std.testing.expectEqual(TypeId.s32, p.return_type);
try std.testing.expectEqual(TypeId.i32, p.return_type);
}
test "plan: qualified namespace function" {
@@ -469,13 +469,13 @@ test "plan: qualified namespace function" {
var l = Lowering.init(&module);
const cr = CallResolver{ .l = &l };
// mathlib.square :: () -> s64 — registered under its qualified name, lazy.
const fd = ast.FnDecl{ .name = "mathlib.square", .params = &.{}, .return_type = typeExpr(alloc, "s64"), .body = emptyBody(alloc) };
// mathlib.square :: () -> i64 — registered under its qualified name, lazy.
const fd = ast.FnDecl{ .name = "mathlib.square", .params = &.{}, .return_type = typeExpr(alloc, "i64"), .body = emptyBody(alloc) };
l.program_index.fn_ast_map.put("mathlib.square", &fd) catch unreachable;
const call = callNode(alloc, fieldAccess(alloc, ident(alloc, "mathlib"), "square"), &.{});
const p = cr.plan(&call.data.call);
try std.testing.expectEqual(CallPlan.Kind.namespace_fn, p.kind);
try std.testing.expectEqualStrings("mathlib.square", p.target.named);
try std.testing.expectEqual(TypeId.s64, p.return_type);
try std.testing.expectEqual(TypeId.i64, p.return_type);
}