clean
This commit is contained in:
280
src/comptime.zig
280
src/comptime.zig
@@ -57,6 +57,18 @@ pub const Value = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn asIndex(self: Value) !usize {
|
||||
return @intCast(self.asInt() orelse return error.TypeError);
|
||||
}
|
||||
|
||||
pub fn isTruthy(self: Value) bool {
|
||||
return switch (self) {
|
||||
.bool_val => |bv| bv,
|
||||
.int_val => |iv| iv != 0,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn asFloat(self: Value) ?f64 {
|
||||
return switch (self) {
|
||||
.float_val => |v| v,
|
||||
@@ -312,6 +324,18 @@ pub const Compiler = struct {
|
||||
try self.instructions.append(self.allocator, instruction);
|
||||
}
|
||||
|
||||
fn patchJump(self: *Compiler, idx: usize) void {
|
||||
self.instructions.items[idx] = .{ .jump = @intCast(@as(i64, @intCast(self.instructions.items.len)) - @as(i64, @intCast(idx)) - 1) };
|
||||
}
|
||||
|
||||
fn patchJumpIfFalse(self: *Compiler, idx: usize) void {
|
||||
self.instructions.items[idx] = .{ .jump_if_false = @intCast(@as(i64, @intCast(self.instructions.items.len)) - @as(i64, @intCast(idx)) - 1) };
|
||||
}
|
||||
|
||||
fn patchJumpIfTrue(self: *Compiler, idx: usize) void {
|
||||
self.instructions.items[idx] = .{ .jump_if_true = @intCast(@as(i64, @intCast(self.instructions.items.len)) - @as(i64, @intCast(idx)) - 1) };
|
||||
}
|
||||
|
||||
fn addString(self: *Compiler, str: []const u8) !u32 {
|
||||
const idx: u32 = @intCast(self.strings.items.len);
|
||||
try self.strings.append(self.allocator, str);
|
||||
@@ -399,9 +423,7 @@ pub const Compiler = struct {
|
||||
try self.emit(.{ .jump_if_false = 0 });
|
||||
try self.emit(.pop);
|
||||
try self.compileNode(binop.rhs);
|
||||
self.instructions.items[jump_idx] = .{
|
||||
.jump_if_false = @intCast(@as(i64, @intCast(self.instructions.items.len)) - @as(i64, @intCast(jump_idx)) - 1),
|
||||
};
|
||||
self.patchJumpIfFalse(jump_idx);
|
||||
} else if (binop.op == .or_op) {
|
||||
// Short-circuit OR: LHS, dup, jump_if_true +N, pop, RHS
|
||||
try self.compileNode(binop.lhs);
|
||||
@@ -410,9 +432,7 @@ pub const Compiler = struct {
|
||||
try self.emit(.{ .jump_if_true = 0 });
|
||||
try self.emit(.pop);
|
||||
try self.compileNode(binop.rhs);
|
||||
self.instructions.items[jump_idx] = .{
|
||||
.jump_if_true = @intCast(@as(i64, @intCast(self.instructions.items.len)) - @as(i64, @intCast(jump_idx)) - 1),
|
||||
};
|
||||
self.patchJumpIfTrue(jump_idx);
|
||||
} else {
|
||||
try self.compileNode(binop.lhs);
|
||||
try self.compileNode(binop.rhs);
|
||||
@@ -465,9 +485,7 @@ pub const Compiler = struct {
|
||||
.neq => .neq,
|
||||
else => unreachable,
|
||||
});
|
||||
self.instructions.items[jump_idx] = .{
|
||||
.jump_if_false = @intCast(@as(i64, @intCast(self.instructions.items.len)) - @as(i64, @intCast(jump_idx)) - 1),
|
||||
};
|
||||
self.patchJumpIfFalse(jump_idx);
|
||||
}
|
||||
},
|
||||
.unary_op => |unop| {
|
||||
@@ -608,14 +626,11 @@ pub const Compiler = struct {
|
||||
if (ie.else_branch) |eb| {
|
||||
const jump_end_idx = self.instructions.items.len;
|
||||
try self.emit(.{ .jump = 0 }); // placeholder
|
||||
// Patch jump_if_false to here
|
||||
self.instructions.items[jump_false_idx] = .{ .jump_if_false = @intCast(self.instructions.items.len - jump_false_idx - 1) };
|
||||
self.patchJumpIfFalse(jump_false_idx);
|
||||
try self.compileNode(eb);
|
||||
// Patch jump to end
|
||||
self.instructions.items[jump_end_idx] = .{ .jump = @intCast(self.instructions.items.len - jump_end_idx - 1) };
|
||||
self.patchJump(jump_end_idx);
|
||||
} else {
|
||||
// Patch jump_if_false to here
|
||||
self.instructions.items[jump_false_idx] = .{ .jump_if_false = @intCast(self.instructions.items.len - jump_false_idx - 1) };
|
||||
self.patchJumpIfFalse(jump_false_idx);
|
||||
}
|
||||
},
|
||||
.call => |call_node| {
|
||||
@@ -637,18 +652,8 @@ pub const Compiler = struct {
|
||||
if (callee_name) |name| {
|
||||
// Check if it's a builtin
|
||||
const base = if (std.mem.lastIndexOfScalar(u8, name, '.')) |idx| name[idx + 1 ..] else name;
|
||||
if (std.mem.eql(u8, base, "print")) {
|
||||
try self.emit(.{ .call_builtin = .{ .id = .print, .arg_count = @intCast(call_node.args.len) } });
|
||||
} else if (std.mem.eql(u8, base, "write")) {
|
||||
try self.emit(.{ .call_builtin = .{ .id = .write, .arg_count = @intCast(call_node.args.len) } });
|
||||
} else if (std.mem.eql(u8, base, "sqrt")) {
|
||||
try self.emit(.{ .call_builtin = .{ .id = .sqrt, .arg_count = @intCast(call_node.args.len) } });
|
||||
} else if (std.mem.eql(u8, base, "size_of")) {
|
||||
try self.emit(.{ .call_builtin = .{ .id = .size_of, .arg_count = @intCast(call_node.args.len) } });
|
||||
} else if (std.mem.eql(u8, base, "cast")) {
|
||||
try self.emit(.{ .call_builtin = .{ .id = .cast, .arg_count = @intCast(call_node.args.len) } });
|
||||
} else if (std.mem.eql(u8, base, "alloc")) {
|
||||
try self.emit(.{ .call_builtin = .{ .id = .alloc, .arg_count = @intCast(call_node.args.len) } });
|
||||
if (std.meta.stringToEnum(BuiltinId, base)) |id| {
|
||||
try self.emit(.{ .call_builtin = .{ .id = id, .arg_count = @intCast(call_node.args.len) } });
|
||||
} else {
|
||||
try self.emit(.{ .call = .{ .func_name = name, .arg_count = @intCast(call_node.args.len) } });
|
||||
}
|
||||
@@ -670,8 +675,7 @@ pub const Compiler = struct {
|
||||
try self.compileNode(arm.body);
|
||||
try end_jumps.append(self.allocator, self.instructions.items.len);
|
||||
try self.emit(.{ .jump = 0 }); // placeholder jump to end
|
||||
// Patch jump_if_false
|
||||
self.instructions.items[jump_next_idx] = .{ .jump_if_false = @intCast(self.instructions.items.len - jump_next_idx - 1) };
|
||||
self.patchJumpIfFalse(jump_next_idx);
|
||||
} else {
|
||||
// else arm: unconditionally execute body
|
||||
try self.emit(.pop); // pop the subject copy
|
||||
@@ -683,7 +687,7 @@ pub const Compiler = struct {
|
||||
try self.emit(.pop); // pop remaining subject
|
||||
// Patch all end jumps
|
||||
for (end_jumps.items) |idx| {
|
||||
self.instructions.items[idx] = .{ .jump = @intCast(self.instructions.items.len - idx - 1) };
|
||||
self.patchJump(idx);
|
||||
}
|
||||
},
|
||||
.struct_literal => |sl| {
|
||||
@@ -772,12 +776,11 @@ pub const Compiler = struct {
|
||||
try self.emit(.{ .jump = back_offset });
|
||||
|
||||
// Patch jump_if_false to after the loop
|
||||
const after_loop = self.instructions.items.len;
|
||||
self.instructions.items[jump_false_idx] = .{ .jump_if_false = @intCast(after_loop - jump_false_idx - 1) };
|
||||
self.patchJumpIfFalse(jump_false_idx);
|
||||
|
||||
// Patch all break jumps to after the loop
|
||||
for (self.break_patches.items) |patch_idx| {
|
||||
self.instructions.items[patch_idx] = .{ .jump = @as(i32, @intCast(after_loop)) - @as(i32, @intCast(patch_idx)) - 1 };
|
||||
self.patchJump(patch_idx);
|
||||
}
|
||||
|
||||
// Restore outer loop context
|
||||
@@ -942,7 +945,7 @@ pub const VM = struct {
|
||||
.address_of_index => {
|
||||
const idx_val = try self.pop();
|
||||
const arr = try self.pop();
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
if (arr == .array_val) {
|
||||
if (idx >= arr.array_val.elements.len) return error.IndexOutOfBounds;
|
||||
try self.push(.{ .pointer_val = .{ .target = arr.array_val.elements.ptr + idx } });
|
||||
@@ -980,31 +983,11 @@ pub const VM = struct {
|
||||
},
|
||||
|
||||
// Arithmetic
|
||||
.add => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(try self.arith(a, b, .add_op));
|
||||
},
|
||||
.sub => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(try self.arith(a, b, .sub_op));
|
||||
},
|
||||
.mul => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(try self.arith(a, b, .mul_op));
|
||||
},
|
||||
.div => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(try self.arith(a, b, .div_op));
|
||||
},
|
||||
.mod => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(try self.arith(a, b, .mod_op));
|
||||
},
|
||||
.add => try self.execArith(.add_op),
|
||||
.sub => try self.execArith(.sub_op),
|
||||
.mul => try self.execArith(.mul_op),
|
||||
.div => try self.execArith(.div_op),
|
||||
.mod => try self.execArith(.mod_op),
|
||||
.bit_and => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
@@ -1030,44 +1013,15 @@ pub const VM = struct {
|
||||
},
|
||||
|
||||
// Comparison
|
||||
.eq => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(.{ .bool_val = self.valEqual(a, b) });
|
||||
},
|
||||
.neq => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(.{ .bool_val = !self.valEqual(a, b) });
|
||||
},
|
||||
.lt => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(.{ .bool_val = self.valLess(a, b) });
|
||||
},
|
||||
.lte => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(.{ .bool_val = self.valLess(a, b) or self.valEqual(a, b) });
|
||||
},
|
||||
.gt => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(.{ .bool_val = self.valLess(b, a) });
|
||||
},
|
||||
.gte => {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(.{ .bool_val = self.valLess(b, a) or self.valEqual(a, b) });
|
||||
},
|
||||
.eq => try self.execComparison(.eq),
|
||||
.neq => try self.execComparison(.neq),
|
||||
.lt => try self.execComparison(.lt),
|
||||
.lte => try self.execComparison(.lte),
|
||||
.gt => try self.execComparison(.gt),
|
||||
.gte => try self.execComparison(.gte),
|
||||
.not => {
|
||||
const v = try self.pop();
|
||||
const b = switch (v) {
|
||||
.bool_val => |bv| bv,
|
||||
.int_val => |iv| iv != 0,
|
||||
else => true,
|
||||
};
|
||||
try self.push(.{ .bool_val = !b });
|
||||
try self.push(.{ .bool_val = !v.isTruthy() });
|
||||
},
|
||||
|
||||
// Control flow
|
||||
@@ -1076,23 +1030,13 @@ pub const VM = struct {
|
||||
},
|
||||
.jump_if_false => |offset| {
|
||||
const v = try self.pop();
|
||||
const is_true = switch (v) {
|
||||
.bool_val => |bv| bv,
|
||||
.int_val => |iv| iv != 0,
|
||||
else => true,
|
||||
};
|
||||
if (!is_true) {
|
||||
if (!v.isTruthy()) {
|
||||
frame.ip = @intCast(@as(i64, frame.ip) + offset);
|
||||
}
|
||||
},
|
||||
.jump_if_true => |offset| {
|
||||
const v = try self.pop();
|
||||
const is_true = switch (v) {
|
||||
.bool_val => |bv| bv,
|
||||
.int_val => |iv| iv != 0,
|
||||
else => true,
|
||||
};
|
||||
if (is_true) {
|
||||
if (v.isTruthy()) {
|
||||
frame.ip = @intCast(@as(i64, frame.ip) + offset);
|
||||
}
|
||||
},
|
||||
@@ -1187,7 +1131,7 @@ pub const VM = struct {
|
||||
const idx_val = try self.pop();
|
||||
const arr = try self.pop();
|
||||
if (arr == .array_val) {
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
if (idx < arr.array_val.elements.len) {
|
||||
try self.push(arr.array_val.elements[idx]);
|
||||
} else {
|
||||
@@ -1195,7 +1139,7 @@ pub const VM = struct {
|
||||
}
|
||||
} else if (arr == .string_val) {
|
||||
// String indexing: return byte as int
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
if (idx < arr.string_val.len) {
|
||||
try self.push(.{ .int_val = @intCast(arr.string_val[idx]) });
|
||||
} else {
|
||||
@@ -1203,7 +1147,7 @@ pub const VM = struct {
|
||||
}
|
||||
} else if (arr == .pointer_val) {
|
||||
// Many-pointer indexing: ptr[i]
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
try self.push(arr.pointer_val.target[idx]);
|
||||
} else {
|
||||
return error.TypeError;
|
||||
@@ -1214,14 +1158,14 @@ pub const VM = struct {
|
||||
const idx_val = try self.pop();
|
||||
const arr = try self.pop();
|
||||
if (arr == .array_val) {
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
if (idx < arr.array_val.elements.len) {
|
||||
arr.array_val.elements[idx] = val;
|
||||
}
|
||||
try self.push(arr);
|
||||
} else if (arr == .string_val) {
|
||||
// String index assignment: mutate byte
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
const byte_val: u8 = @intCast(val.asInt() orelse return error.TypeError);
|
||||
if (idx < arr.string_val.len) {
|
||||
const mutable = @constCast(arr.string_val);
|
||||
@@ -1230,7 +1174,7 @@ pub const VM = struct {
|
||||
try self.push(arr);
|
||||
} else if (arr == .pointer_val) {
|
||||
// Many-pointer index assignment: ptr[i] = val
|
||||
const idx: usize = @intCast(idx_val.asInt() orelse return error.TypeError);
|
||||
const idx: usize = try idx_val.asIndex();
|
||||
arr.pointer_val.target[idx] = val;
|
||||
try self.push(arr);
|
||||
} else {
|
||||
@@ -1260,6 +1204,28 @@ pub const VM = struct {
|
||||
|
||||
const ArithOp = enum { add_op, sub_op, mul_op, div_op, mod_op };
|
||||
|
||||
fn execArith(self: *VM, op: ArithOp) !void {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
try self.push(try self.arith(a, b, op));
|
||||
}
|
||||
|
||||
const CmpOp = enum { eq, neq, lt, lte, gt, gte };
|
||||
|
||||
fn execComparison(self: *VM, comptime op: CmpOp) !void {
|
||||
const b = try self.pop();
|
||||
const a = try self.pop();
|
||||
const result = switch (op) {
|
||||
.eq => self.valEqual(a, b),
|
||||
.neq => !self.valEqual(a, b),
|
||||
.lt => self.valLess(a, b),
|
||||
.lte => self.valLess(a, b) or self.valEqual(a, b),
|
||||
.gt => self.valLess(b, a),
|
||||
.gte => self.valLess(b, a) or self.valEqual(a, b),
|
||||
};
|
||||
try self.push(.{ .bool_val = result });
|
||||
}
|
||||
|
||||
fn arith(self: *VM, a: Value, b: Value, op: ArithOp) !Value {
|
||||
_ = self;
|
||||
// Both int
|
||||
@@ -1357,27 +1323,13 @@ pub const VM = struct {
|
||||
for (self.root_decls) |decl| {
|
||||
switch (decl.data) {
|
||||
.fn_decl => |fd| {
|
||||
if (std.mem.eql(u8, fd.name, name)) {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = try compiler.compileFunction(fd);
|
||||
try self.functions.put(name, chunk);
|
||||
if (self.functions.getPtr(name)) |ptr| {
|
||||
return self.invokeChunk(ptr, arg_count);
|
||||
}
|
||||
}
|
||||
if (std.mem.eql(u8, fd.name, name))
|
||||
return self.compileFunctionAndInvoke(name, fd, arg_count);
|
||||
},
|
||||
.namespace_decl => |ns| {
|
||||
for (ns.decls) |d| {
|
||||
if (d.data == .fn_decl) {
|
||||
if (std.mem.eql(u8, d.data.fn_decl.name, name)) {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = try compiler.compileFunction(d.data.fn_decl);
|
||||
try self.functions.put(name, chunk);
|
||||
if (self.functions.getPtr(name)) |ptr| {
|
||||
return self.invokeChunk(ptr, arg_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (d.data == .fn_decl and std.mem.eql(u8, d.data.fn_decl.name, name))
|
||||
return self.compileFunctionAndInvoke(name, d.data.fn_decl, arg_count);
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
@@ -1553,6 +1505,29 @@ pub const VM = struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
fn cacheTypeGlobal(self: *VM, name: []const u8, ty: Type) VMError!Value {
|
||||
const val = Value{ .type_val = ty };
|
||||
try self.globals.put(name, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
fn compileAndEvalGlobal(self: *VM, name: []const u8, expr: *Node) VMError!Value {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = compiler.compile(expr) catch return error.CompileError;
|
||||
const result = self.evalInFreshVM(&chunk) catch return error.CompileError;
|
||||
try self.globals.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn compileFunctionAndInvoke(self: *VM, name: []const u8, fd: ast.FnDecl, arg_count: u8) !void {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = try compiler.compileFunction(fd);
|
||||
try self.functions.put(name, chunk);
|
||||
if (self.functions.getPtr(name)) |ptr| {
|
||||
return self.invokeChunk(ptr, arg_count);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolveGlobal(self: *VM, name: []const u8) VMError!Value {
|
||||
// Check cache first
|
||||
if (self.globals.get(name)) |val| return val;
|
||||
@@ -1562,21 +1537,13 @@ pub const VM = struct {
|
||||
switch (decl.data) {
|
||||
.const_decl => |cd| {
|
||||
if (std.mem.eql(u8, cd.name, name)) {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = compiler.compile(cd.value) catch return error.CompileError;
|
||||
const result = self.evalInFreshVM(&chunk) catch return error.CompileError;
|
||||
try self.globals.put(name, result);
|
||||
return result;
|
||||
return self.compileAndEvalGlobal(name, cd.value);
|
||||
}
|
||||
},
|
||||
.var_decl => |vd| {
|
||||
if (std.mem.eql(u8, vd.name, name)) {
|
||||
if (vd.value) |val_expr| {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = compiler.compile(val_expr) catch return error.CompileError;
|
||||
const result = self.evalInFreshVM(&chunk) catch return error.CompileError;
|
||||
try self.globals.put(name, result);
|
||||
return result;
|
||||
return self.compileAndEvalGlobal(name, val_expr);
|
||||
}
|
||||
return .{ .void_val = {} };
|
||||
}
|
||||
@@ -1585,11 +1552,7 @@ pub const VM = struct {
|
||||
// Check inside namespace for matching declarations
|
||||
for (ns.decls) |d| {
|
||||
if (d.data == .const_decl and std.mem.eql(u8, d.data.const_decl.name, name)) {
|
||||
var compiler = Compiler.init(self.allocator, self.sema_result, self.root_decls, self.codegen);
|
||||
const chunk = compiler.compile(d.data.const_decl.value) catch return error.CompileError;
|
||||
const result = self.evalInFreshVM(&chunk) catch return error.CompileError;
|
||||
try self.globals.put(name, result);
|
||||
return result;
|
||||
return self.compileAndEvalGlobal(name, d.data.const_decl.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1601,37 +1564,26 @@ pub const VM = struct {
|
||||
for (self.root_decls) |decl| {
|
||||
switch (decl.data) {
|
||||
.struct_decl => |sd| {
|
||||
if (std.mem.eql(u8, sd.name, name)) {
|
||||
const val = Value{ .type_val = .{ .struct_type = name } };
|
||||
try self.globals.put(name, val);
|
||||
return val;
|
||||
}
|
||||
if (std.mem.eql(u8, sd.name, name))
|
||||
return self.cacheTypeGlobal(name, .{ .struct_type = name });
|
||||
},
|
||||
.enum_decl => |ed| {
|
||||
if (std.mem.eql(u8, ed.name, name)) {
|
||||
const ty: Type = if (ed.variant_types.len > 0) .{ .union_type = name } else .{ .enum_type = name };
|
||||
const val = Value{ .type_val = ty };
|
||||
try self.globals.put(name, val);
|
||||
return val;
|
||||
return self.cacheTypeGlobal(name, ty);
|
||||
}
|
||||
},
|
||||
.union_decl => |ud| {
|
||||
if (std.mem.eql(u8, ud.name, name)) {
|
||||
const val = Value{ .type_val = .{ .union_type = name } };
|
||||
try self.globals.put(name, val);
|
||||
return val;
|
||||
}
|
||||
if (std.mem.eql(u8, ud.name, name))
|
||||
return self.cacheTypeGlobal(name, .{ .union_type = name });
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it's a primitive type name (s32, f64, bool, etc.)
|
||||
if (Type.fromName(name)) |ty| {
|
||||
const val = Value{ .type_val = ty };
|
||||
try self.globals.put(name, val);
|
||||
return val;
|
||||
}
|
||||
if (Type.fromName(name)) |ty|
|
||||
return self.cacheTypeGlobal(name, ty);
|
||||
|
||||
return error.UndefinedVariable;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user