diff --git a/src/ir/module.zig b/src/ir/module.zig index 031731b..49a9701 100644 --- a/src/ir/module.zig +++ b/src/ir/module.zig @@ -321,9 +321,11 @@ pub const Builder = struct { blk.first_ref = self.inst_counter; } - /// Get the type of a previously emitted instruction Ref. + /// Get the type of a previously emitted instruction Ref. A ref that can't + /// be located (no active function, or an out-of-range ref) has no knowable + /// type — return the `.unresolved` sentinel rather than a fabricated `.s64`. pub fn getRefType(self: *Builder, ref: Ref) TypeId { - if (self.func == null) return .s64; + if (self.func == null) return .unresolved; const func = self.currentFunc(); const ref_idx = @intFromEnum(ref); // Check function parameters first (refs 0..N-1) @@ -336,7 +338,7 @@ pub const Builder = struct { return block.insts.items[ref_idx - first].ty; } } - return .s64; + return .unresolved; } // ── Emit helpers ──────────────────────────────────────────────── diff --git a/src/ir/type_bridge.zig b/src/ir/type_bridge.zig index 64e4531..fbb2129 100644 --- a/src/ir/type_bridge.zig +++ b/src/ir/type_bridge.zig @@ -163,6 +163,7 @@ pub fn bridgeType(ty: sx_types.Type, table: *TypeTable) TypeId { } }); }, .meta_type => .any, // meta types map to Any for now + .unresolved => .unresolved, }; } diff --git a/src/sema.zig b/src/sema.zig index 5a7d174..2a06d73 100644 --- a/src/sema.zig +++ b/src/sema.zig @@ -136,11 +136,16 @@ pub const Analyzer = struct { var param_types = std.ArrayList(Type).empty; var has_variadic = false; for (fd.params) |param| { - const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64); + const pt = Type.fromTypeExpr(param.type_expr) orelse Type.unresolved; if (param.is_variadic) { has_variadic = true; // Variadic param becomes a slice type - const elem_name = if (param.type_expr.data == .type_expr) param.type_expr.data.type_expr.name else "s32"; + const elem_name = switch (param.type_expr.data) { + .type_expr => |te| te.name, + // `..xs: []T` — the element is T, not a guessed s32. + .slice_type_expr => |st| if (st.element_type.data == .type_expr) st.element_type.data.type_expr.name else "", + else => "", + }; try param_types.append(self.allocator, .{ .slice_type = .{ .element_name = elem_name } }); } else { try param_types.append(self.allocator, pt); @@ -169,7 +174,7 @@ pub const Analyzer = struct { const lam = cd.value.data.lambda; var param_types = std.ArrayList(Type).empty; for (lam.params) |param| { - const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64); + const pt = Type.fromTypeExpr(param.type_expr) orelse Type.unresolved; try param_types.append(self.allocator, pt); } const ret = if (lam.return_type) |rt| @@ -222,7 +227,7 @@ pub const Analyzer = struct { } if (i < sd.field_names.len) { try all_names.append(self.allocator, sd.field_names[i]); - const resolved = Type.fromTypeExpr(sd.field_types[i]) orelse Type.s(64); + const resolved = Type.fromTypeExpr(sd.field_types[i]) orelse Type.unresolved; try all_types.append(self.allocator, resolved); } } @@ -233,7 +238,7 @@ pub const Analyzer = struct { } else { var field_types = std.ArrayList(Type).empty; for (sd.field_types) |ft| { - const resolved = Type.fromTypeExpr(ft) orelse Type.s(64); + const resolved = Type.fromTypeExpr(ft) orelse Type.unresolved; try field_types.append(self.allocator, resolved); } try self.struct_types.put(sd.name, .{ @@ -369,11 +374,11 @@ pub const Analyzer = struct { j -= 1; const sym = self.symbols.items[indices.items[j]]; if (sym.scope_depth <= self.scope_depth) { - return sym.ty orelse Type.s(64); + return sym.ty orelse Type.unresolved; } } } - return Type.s(64); + return Type.unresolved; }, .if_expr => |ie| { return self.inferExprType(ie.then_branch); @@ -391,7 +396,7 @@ pub const Analyzer = struct { return .void_type; }, .call => |call_node| { - const callee_name = self.resolveCalleeName(call_node) orelse return Type.s(64); + const callee_name = self.resolveCalleeName(call_node) orelse return Type.unresolved; // Check fn_signatures registry if (self.fn_signatures.get(callee_name)) |sig| { return sig.return_type; @@ -405,7 +410,7 @@ pub const Analyzer = struct { if (call_node.args.len > 0) return self.inferExprType(call_node.args[0]); return .f32; } - return Type.s(64); + return Type.unresolved; }, .unary_op => |unop| { return self.inferExprType(unop.operand); @@ -426,17 +431,17 @@ pub const Analyzer = struct { } } if (obj_ty.isArray()) { - return Type.fromName(obj_ty.array_type.element_name) orelse Type.s(64); + return Type.fromName(obj_ty.array_type.element_name) orelse Type.unresolved; } - return Type.s(64); + return Type.unresolved; }, .index_expr => |ie| { const obj_ty = self.inferExprType(ie.object); if (obj_ty == .string_type) return Type.u(8); if (obj_ty.isArray()) { - return Type.fromName(obj_ty.array_type.element_name) orelse Type.s(64); + return Type.fromName(obj_ty.array_type.element_name) orelse Type.unresolved; } - return Type.s(64); + return Type.unresolved; }, .slice_expr => |se| { const obj_ty = self.inferExprType(se.object); @@ -677,7 +682,7 @@ pub const Analyzer = struct { { var param_types = std.ArrayList(Type).empty; for (fd.params) |param| { - const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64); + const pt = Type.fromTypeExpr(param.type_expr) orelse Type.unresolved; try param_types.append(self.allocator, pt); } try self.fn_signatures.put(fd.name, .{ @@ -1026,7 +1031,7 @@ pub const Analyzer = struct { fn inferFnReturnType(self: *Analyzer, params: []const ast.Param, body: *const Node) ?Type { self.pushScope() catch return null; for (params) |param| { - const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64); + const pt = Type.fromTypeExpr(param.type_expr) orelse Type.unresolved; self.addSymbol(param.name, .param, pt, param.name_span) catch {}; } // Arrow fn_decl wraps body in block{[expr]} — unwrap to inner expression diff --git a/src/types.zig b/src/types.zig index 0522d36..08d661b 100644 --- a/src/types.zig +++ b/src/types.zig @@ -29,6 +29,11 @@ pub const Type = union(enum) { optional_type: OptionalTypeInfo, meta_type: MetaTypeInfo, tuple_type: TupleTypeInfo, + /// Type resolution failed (sema couldn't infer/resolve). A dedicated + /// sentinel — never a legitimate type — so callers can't mistake it for a + /// real result the way a fabricated `s(64)` would be. Mirrors + /// `ir.TypeId.unresolved`. + unresolved, pub const SliceTypeInfo = struct { element_name: []const u8, @@ -84,7 +89,7 @@ pub const Type = union(enum) { return switch (self) { .signed => |w| w == other.signed, .unsigned => |w| w == other.unsigned, - .f32, .f64, .void_type, .boolean, .string_type, .any_type, .usize_type, .isize_type => true, + .f32, .f64, .void_type, .boolean, .string_type, .any_type, .usize_type, .isize_type, .unresolved => true, .enum_type => |n| std.mem.eql(u8, n, other.enum_type), .struct_type => |n| std.mem.eql(u8, n, other.struct_type), .union_type => |n| std.mem.eql(u8, n, other.union_type), @@ -555,6 +560,7 @@ pub const Type = union(enum) { .any_type => "Any", .usize_type => "usize", .isize_type => "isize", + .unresolved => "", .enum_type => |name| name, .struct_type => |name| name, .union_type => |name| name,