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

@@ -82,7 +82,7 @@ pub fn lowerStructLiteral(self: *Lowering, sl: *const ast.StructLiteral, span: a
// `.ambiguous`/`.not_visible` surface their loud diagnostic + poison.
self.resolveNominalLeaf(name, false, span)
else if (sl.type_expr) |te|
// Generic struct literal: Pair(s32).{ ... } — resolve type from type_expr
// Generic struct literal: Pair(i32).{ ... } — resolve type from type_expr
self.resolveTypeWithBindings(te)
else self.target_type orelse .unresolved;
@@ -315,7 +315,7 @@ pub fn fixupMethodReceiver(self: *Lowering, method_args: *std.ArrayList(Ref), fu
/// Get the name of a struct type (dereferencing pointers). Returns null for non-struct types.
pub fn getStructTypeName(self: *Lowering, ty: TypeId) ?[]const u8 {
if (ty.isBuiltin()) {
// Map builtin types to their names for method resolution (e.g., s64.eq)
// Map builtin types to their names for method resolution (e.g., i64.eq)
return builtinTypeName(ty);
}
var resolved = ty;
@@ -333,10 +333,10 @@ pub fn getStructTypeName(self: *Lowering, ty: TypeId) ?[]const u8 {
pub fn builtinTypeName(ty: TypeId) ?[]const u8 {
return switch (ty) {
.s8 => "s8",
.s16 => "s16",
.s32 => "s32",
.s64 => "s64",
.i8 => "i8",
.i16 => "i16",
.i32 => "i32",
.i64 => "i64",
.u8 => "u8",
.u16 => "u16",
.u32 => "u32",
@@ -351,7 +351,7 @@ pub fn builtinTypeName(ty: TypeId) ?[]const u8 {
/// Resolve the type of a named field on a given type.
pub fn resolveFieldType(self: *Lowering, ty: TypeId, field: []const u8) TypeId {
if (std.mem.eql(u8, field, "len")) return .s64;
if (std.mem.eql(u8, field, "len")) return .i64;
if (std.mem.eql(u8, field, "ptr")) {
const elem_ty = self.getElementType(ty);
return self.module.types.manyPtrTo(elem_ty);
@@ -497,7 +497,7 @@ pub fn lowerFieldAccess(self: *Lowering, fa: *const ast.FieldAccess, span: ast.S
if (self.pack_param_count) |ppc| {
if (fa.object.data == .identifier and std.mem.eql(u8, fa.field, "len")) {
if (ppc.get(fa.object.data.identifier.name)) |n| {
return self.builder.constInt(@as(i64, @intCast(n)), .s64);
return self.builder.constInt(@as(i64, @intCast(n)), .i64);
}
}
}
@@ -606,7 +606,7 @@ pub fn lowerFieldAccess(self: *Lowering, fa: *const ast.FieldAccess, span: ast.S
if (is_special) {
if (std.mem.eql(u8, fa.field, "len")) {
return self.builder.emit(.{ .length = .{ .operand = obj } }, .s64);
return self.builder.emit(.{ .length = .{ .operand = obj } }, .i64);
}
{
const elem_ty = self.getElementType(obj_ty);
@@ -658,7 +658,7 @@ pub fn identifierBindsValue(self: *Lowering, name: []const u8) bool {
/// a builtin type (a user struct → ordinary field lowering reports
/// field-not-found). Two clean diagnostics (then a placeholder, so lowering
/// finishes and `hasErrors()` aborts the build):
/// - a FLOAT-only accessor on an integer type (`s32.epsilon`, `u8.inf`);
/// - a FLOAT-only accessor on an integer type (`i32.epsilon`, `u8.inf`);
/// - any accessor on a builtin NON-numeric receiver
/// (`bool`/`string`/`void`/`Any`/`noreturn`).
pub fn lowerNumericLimit(self: *Lowering, fa: *const ast.FieldAccess, span: ast.Span) ?Ref {
@@ -704,7 +704,7 @@ pub fn lowerStructConstant(self: *Lowering, info: StructConstInfo) Ref {
return switch (val_node.data) {
.int_literal => |lit| blk: {
if (info.ty) |t| self.checkIntLiteralFits(lit.value, t, val_node.span);
break :blk self.builder.constInt(lit.value, info.ty orelse .s64);
break :blk self.builder.constInt(lit.value, info.ty orelse .i64);
},
.float_literal => |lit| self.builder.constFloat(lit.value, info.ty orelse .f64),
.bool_literal => |lit| self.builder.constBool(lit.value),
@@ -1199,9 +1199,9 @@ pub fn resolveArrayLiteralType(self: *Lowering, te: *const Node) TypeId {
return self.module.types.vectorOf(elem, length);
}
}
// Generic-struct typed-literal head (`Box(s64).[...]`): route
// Generic-struct typed-literal head (`Box(i64).[...]`): route
// through the single layout choke-point (CP-1). A qualified head
// `a.Box(s64).[...]` selects a's OWN template via the namespace edge
// `a.Box(i64).[...]` selects a's OWN template via the namespace edge
// (Counter-1: was the global last-wins map); a bare head selects the
// single bare-VISIBLE author.
if (headNameOfCallee(cl.callee)) |hn| {
@@ -1258,7 +1258,7 @@ pub fn lowerIndexExpr(self: *Lowering, ie: *const ast.IndexExpr) Ref {
// bounds" instead of the generic "unresolved 'args'" that the
// fall-through scope-lookup would produce.
if (self.diagPackIndexOOB(ie)) {
return self.builder.constInt(0, .s64);
return self.builder.constInt(0, .i64);
}
// Runtime index into a comptime-only pack (Decision 1): a pack has no
// runtime representation, so the index must be a compile-time constant.
@@ -1271,7 +1271,7 @@ pub fn lowerIndexExpr(self: *Lowering, ie: *const ast.IndexExpr) Ref {
if (self.diagnostics) |diags| {
diags.addFmt(.err, ie.index.span, "pack '{s}' must be indexed by a compile-time constant — a pack is comptime-only and has no runtime value", .{pname});
}
return self.builder.constInt(0, .s64);
return self.builder.constInt(0, .i64);
}
}
}
@@ -1306,10 +1306,10 @@ pub fn lowerIndexExpr(self: *Lowering, ie: *const ast.IndexExpr) Ref {
pub fn lowerSliceExpr(self: *Lowering, se: *const ast.SliceExpr) Ref {
const obj = self.lowerExpr(se.object);
var lo = if (se.start) |s| self.lowerExpr(s) else self.builder.constInt(0, .s64);
if (se.start_exclusive) lo = self.builder.add(lo, self.builder.constInt(1, .s64), .s64);
var hi = if (se.end) |e| self.lowerExpr(e) else self.builder.emit(.{ .length = .{ .operand = obj } }, .s64);
if (se.end_inclusive) hi = self.builder.add(hi, self.builder.constInt(1, .s64), .s64);
var lo = if (se.start) |s| self.lowerExpr(s) else self.builder.constInt(0, .i64);
if (se.start_exclusive) lo = self.builder.add(lo, self.builder.constInt(1, .i64), .i64);
var hi = if (se.end) |e| self.lowerExpr(e) else self.builder.emit(.{ .length = .{ .operand = obj } }, .i64);
if (se.end_inclusive) hi = self.builder.add(hi, self.builder.constInt(1, .i64), .i64);
// Infer result slice type from the object
const obj_ty = self.inferExprType(se.object);
// Subslice of string stays string (same {ptr, i64} layout, correct type category)
@@ -1598,8 +1598,8 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
}
}
const ty = if (self.target_type) |tt| blk: {
break :blk if (self.isIntEx(tt)) tt else .s64;
} else .s64;
break :blk if (self.isIntEx(tt)) tt else .i64;
} else .i64;
self.checkIntLiteralFits(lit.value, ty, node.span);
return self.builder.constInt(lit.value, ty);
},
@@ -1645,7 +1645,7 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
// Check compile-time constants (OS, ARCH, POINTER_SIZE) before globals
if (self.comptime_constants.get(id.name)) |cv| {
switch (cv) {
.int_val => |iv| break :blk self.builder.constInt(iv, .s64),
.int_val => |iv| break :blk self.builder.constInt(iv, .i64),
.enum_tag => |et| break :blk self.builder.constInt(@intCast(et.tag), et.ty),
}
}
@@ -1683,7 +1683,7 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
.untracked => break :blk self.builder.emit(.{ .global_get = gi.id }, gi.ty),
}
}
// Check module-level value constants (e.g. AF_INET :s32: 2)
// Check module-level value constants (e.g. AF_INET :i32: 2)
if (self.program_index.module_const_map.get(id.name)) |ci_global| {
if (!self.isNameVisible(id.name)) {
if (self.diagnostics) |d|
@@ -1820,7 +1820,7 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
// examples/50-smoke.sx has both shapes.
}
}
break :blk self.builder.emit(.{ .func_ref = fid }, .s64);
break :blk self.builder.emit(.{ .func_ref = fid }, .i64);
}
}
// Type-as-value: a name that resolves to a TypeId
@@ -1927,7 +1927,7 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
break :blk self.builder.constFloat(@floatFromInt(v), tt);
}
}
const nty = if (self.target_type) |tt| (if (self.isIntEx(tt)) tt else TypeId.s64) else TypeId.s64;
const nty = if (self.target_type) |tt| (if (self.isIntEx(tt)) tt else TypeId.i64) else TypeId.i64;
self.checkIntLiteralFits(v, nty, node.span);
break :blk self.builder.constInt(v, nty);
}
@@ -2031,7 +2031,7 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
},
// type_expr can appear as a variable reference when the name collides
// with a builtin type name (e.g. s2, u8). Check scope first.
// with a builtin type name (e.g. i2, u8). Check scope first.
.type_expr => |te| blk: {
if (self.scope) |scope| {
if (scope.lookup(te.name)) |binding| {
@@ -2057,8 +2057,8 @@ pub fn lowerExpr(self: *Lowering, node: *const Node) Ref {
// Compound type literals (`*T`, `[]T`, `[*]T`, `?T`, `[N]T`, fn types)
// in expression position are first-class `Type` values, exactly like
// the named form above (`t : Type = *s64;` ↔ `t : Type = f64;`). Also
// the path a static `cast(*s64) v` type argument takes — call args are
// the named form above (`t : Type = *i64;` ↔ `t : Type = f64;`). Also
// the path a static `cast(*i64) v` type argument takes — call args are
// lowered before the cast handler inspects the AST (issue 0118).
.pointer_type_expr,
.many_pointer_type_expr,
@@ -2128,7 +2128,7 @@ pub fn lowerBinaryOp(self: *Lowering, bop: *const ast.BinaryOp) Ref {
}
// Type-literal comparison fold: when both sides are type-shaped
// AST nodes (`s64`, `*u8`, `?T`, `[3]f64`, etc.) OR resolve to
// AST nodes (`i64`, `*u8`, `?T`, `[3]f64`, etc.) OR resolve to
// a static TypeId at lower time (`type_of(x)` for any
// statically-typed `x`), resolve each and emit a `const_bool`.
// Same semantic as `type_eq(A, B)` but using the standard `==`
@@ -2144,11 +2144,11 @@ pub fn lowerBinaryOp(self: *Lowering, bop: *const ast.BinaryOp) Ref {
}
}
// Any-shaped `==` (e.g. `t == s64` where `t: Type`): both
// Any-shaped `==` (e.g. `t == i64` where `t: Type`): both
// operands are 16-byte `{tag, value}` aggregates. LLVM
// doesn't accept `icmp` on aggregates directly. Decompose
// via `unbox_any` (which extracts the value field at
// `.s64`) and compare the i64s. Tag fields are stable
// `.i64`) and compare the i64s. Tag fields are stable
// across compilations of the same source so value-only
// identity is enough.
if (bop.op == .eq or bop.op == .neq) {
@@ -2157,8 +2157,8 @@ pub fn lowerBinaryOp(self: *Lowering, bop: *const ast.BinaryOp) Ref {
if (lhs_ty == .any and rhs_ty == .any) {
const lhs = self.lowerExpr(bop.lhs);
const rhs = self.lowerExpr(bop.rhs);
const lhs_val = self.builder.emit(.{ .unbox_any = .{ .operand = lhs } }, .s64);
const rhs_val = self.builder.emit(.{ .unbox_any = .{ .operand = rhs } }, .s64);
const lhs_val = self.builder.emit(.{ .unbox_any = .{ .operand = lhs } }, .i64);
const rhs_val = self.builder.emit(.{ .unbox_any = .{ .operand = rhs } }, .i64);
if (bop.op == .eq) {
return self.builder.emit(.{ .cmp_eq = .{ .lhs = lhs_val, .rhs = rhs_val } }, .bool);
} else {
@@ -2249,7 +2249,7 @@ pub fn lowerBinaryOp(self: *Lowering, bop: *const ast.BinaryOp) Ref {
if (rhs_ref_pointee) |p| rhs = self.builder.load(rhs, p);
self.target_type = saved_tt;
// Result type follows the shared promotion rule: an int LHS with a
// float RHS promotes to the float (`s64 * f32` → `f32`); vectors /
// float RHS promotes to the float (`i64 * f32` → `f32`); vectors /
// structs keep the LHS type. `inferExprType` reuses the same helper
// so static typing agrees with the value produced here.
const rhs_inferred = rhs_ref_pointee orelse self.inferExprType(bop.rhs);
@@ -2298,7 +2298,7 @@ pub fn lowerBinaryOp(self: *Lowering, bop: *const ast.BinaryOp) Ref {
}
// Reject scalar ops on incompatible operand types (e.g.
// `s64 + string`, `s64 < string`, `s64 & string`). The result type
// `i64 + string`, `i64 < string`, `i64 & string`). The result type
// `ty` is derived from the LHS, so without this the op lowers as
// `<op> : <lhs>` and either reinterprets the RHS bytes (arithmetic
// / bitwise → garbage) or feeds mismatched LLVM types to `icmp`
@@ -2448,7 +2448,7 @@ pub fn lowerTupleOp(self: *Lowering, bop: *const ast.BinaryOp, lhs: Ref, rhs: Re
// Lexicographic comparison
return self.lowerTupleLexCompare(bop.op, lhs, rhs, lhs_fields);
},
else => return self.builder.constInt(0, .s64),
else => return self.builder.constInt(0, .i64),
}
}