This commit is contained in:
agra
2026-02-14 23:05:57 +02:00
parent 3fd14bafac
commit da1a69ade8
3 changed files with 583 additions and 742 deletions

View File

@@ -190,7 +190,7 @@ void main() {
} }
GLSL; GLSL;
program : u32 = create_program(vert_src, frag_src); program := create_program(vert_src, frag_src);
glUseProgram(program); glUseProgram(program);
mvp_loc : s32 = glGetUniformLocation(program, "uMVP"); mvp_loc : s32 = glGetUniformLocation(program, "uMVP");
@@ -200,7 +200,7 @@ GLSL;
// Cube vertices: pos(vec4 w=1) + normal(vec4 w=0), 36 vertices × 2 vec4s = 72 // Cube vertices: pos(vec4 w=1) + normal(vec4 w=0), 36 vertices × 2 vec4s = 72
vertices : []Vector(4, f32) = .[ vertices : []Vector(4, f32) = .[
// Front face (z = +0.5) // Front face (z = +0.5)
vec4(-0.5, -0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0), .[-0.5, -0.5, 0.5, 1.0], vec4( 0.0, 0.0, 1.0, 0.0),
vec4( 0.5, -0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0), vec4( 0.5, -0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0),
vec4( 0.5, 0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0), vec4( 0.5, 0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0),
vec4(-0.5, -0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0), vec4(-0.5, -0.5, 0.5, 1.0), vec4( 0.0, 0.0, 1.0, 0.0),
@@ -246,6 +246,7 @@ GLSL;
// Create VAO and VBO // Create VAO and VBO
vao : u32 = 0; vao : u32 = 0;
vbo : u32 = 0; vbo : u32 = 0;
glGenVertexArrays(1, vao); glGenVertexArrays(1, vao);
glGenBuffers(1, vbo); glGenBuffers(1, vbo);
@@ -276,6 +277,7 @@ GLSL;
case .key_up: (e) { case .key_up: (e) {
if e.key == { if e.key == {
case .escape: running = false; case .escape: running = false;
//case .
} }
} }
case .window_exposed: (e) { case .window_exposed: (e) {

File diff suppressed because it is too large Load Diff

View File

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