diff --git a/demo/test.py b/demo/test.py index b39061e..ab3cf4d 100644 --- a/demo/test.py +++ b/demo/test.py @@ -1,3 +1,2 @@ -a = [1, 2] -a.append(3) +a = 1 print(a) \ No newline at end of file diff --git a/src/Manager.zig b/src/Manager.zig index 8980f40..43bc49e 100644 --- a/src/Manager.zig +++ b/src/Manager.zig @@ -12,7 +12,6 @@ const tracer = @import("tracer"); const Marshal = @import("compiler/Marshal.zig"); const Vm = @import("vm/Vm.zig"); -const Compiler = @import("compiler/Compiler.zig"); const log = std.log.scoped(.manager); @@ -46,12 +45,8 @@ pub fn run_pyc(manager: *Manager, file_name: []const u8) !void { // Parse the code object const object = try Marshal.load(manager.allocator, source); - // Convert into the nice Instruction format - var compiler = Compiler.init(manager.allocator); - const instructions = try compiler.compile(object); - var vm = try Vm.init(); - try vm.run(manager.allocator, instructions); + try vm.run(manager.allocator, object); } pub fn run_file(manager: *Manager, file_name: []const u8) !void { diff --git a/src/compiler/CodeObject.zig b/src/compiler/CodeObject.zig index 76ebc4c..8cd3bb4 100644 --- a/src/compiler/CodeObject.zig +++ b/src/compiler/CodeObject.zig @@ -1,11 +1,15 @@ -//! A 3.11 CodeObject +//! A 3.10 CodeObject const std = @import("std"); const Marshal = @import("Marshal.zig"); +const Instruction = @import("Instruction.zig"); +const OpCode = @import("opcodes.zig").OpCode; const Result = Marshal.Result; const Reference = Marshal.Reference; const FlagRef = Marshal.FlagRef; +const CodeObject = @This(); + /// File name filename: []const u8, @@ -22,7 +26,7 @@ names: []const Result, name: []const u8, /// Stack Size -stacksize: u32, +stack_size: u32, /// ByteCode code: []const u8, @@ -30,8 +34,14 @@ code: []const u8, // Interal reference table. flag_refs: []const ?FlagRef, +/// Only exist after `co.process()` is run. +instructions: []Instruction = undefined, + +/// Where the VM is at in running this CodeObject +index: usize = 0, + pub fn format( - self: @This(), + self: CodeObject, comptime fmt: []const u8, _: std.fmt.FormatOptions, writer: anytype, @@ -41,7 +51,7 @@ pub fn format( try writer.print("Name: {s}\n", .{self.name}); try writer.print("Filename: {s}\n", .{self.filename}); try writer.print("Argument count: {d}\n", .{self.argcount}); - try writer.print("Stack size: {d}\n", .{self.stacksize}); + try writer.print("Stack size: {d}\n", .{self.stack_size}); try writer.print("Consts:\n", .{}); for (self.consts) |con| { @@ -53,3 +63,40 @@ pub fn format( try writer.print("\t{}\n", .{name.fmt(self)}); } } + +pub fn process( + co: *CodeObject, + allocator: std.mem.Allocator, +) !void { + var instructions = std.ArrayList(Instruction).init(allocator); + + const bytes = co.code; + + var cursor: u32 = 0; + while (cursor < bytes.len) { + const byte = bytes[cursor]; + const op: OpCode = @enumFromInt(byte); + + const has_arg = byte >= 90; + + const inst: Instruction = .{ + .op = op, + .extra = if (has_arg) bytes[cursor + 1] else undefined, + }; + try instructions.append(inst); + cursor += 2; + continue; + } + + co.instructions = try instructions.toOwnedSlice(); + co.index = 0; +} + +// Helper functions + +pub fn getName( + co: *const CodeObject, + namei: u8, +) []const u8 { + return co.names[namei].String; +} diff --git a/src/compiler/Compiler.zig b/src/compiler/Compiler.zig deleted file mode 100644 index a7188df..0000000 --- a/src/compiler/Compiler.zig +++ /dev/null @@ -1,349 +0,0 @@ -//! Compiler that converts python bytecode into Instructions - -const std = @import("std"); -const CodeObject = @import("CodeObject.zig"); -const tracer = @import("tracer"); - -const Vm = @import("../vm/Vm.zig"); - -const Marshal = @import("Marshal.zig"); - -const OpCodes = @import("opcodes.zig"); -const OpCode = OpCodes.OpCode; - -const Compiler = @This(); -const log = std.log.scoped(.compiler); - -cursor: u32, -allocator: std.mem.Allocator, - -pub fn init(allocator: std.mem.Allocator) Compiler { - const t = tracer.trace(@src(), "", .{}); - defer t.end(); - - return .{ - .cursor = 0, - .allocator = allocator, - }; -} - -pub fn compile(compiler: *Compiler, co: *CodeObject) ![]Instruction { - const t = tracer.trace(@src(), "", .{}); - defer t.end(); - - var instructions = std.ArrayList(Instruction).init(compiler.allocator); - - log.debug("\n{}", .{co}); - - const bytes = co.code; - - var cursor: u32 = 0; - while (cursor < bytes.len) { - const byte = bytes[cursor]; - const op: OpCode = @enumFromInt(byte); - log.debug("Op: {s}", .{@tagName(op)}); - - const has_arg = byte > 90; - - if (!has_arg) { - const maybe_inst: ?Instruction = switch (op) { - .POP_TOP => .PopTop, - .RETURN_VALUE => .ReturnValue, - .STORE_SUBSCR => .StoreSubScr, - .ROT_TWO => .RotTwo, - .BINARY_SUBSCR => .BinarySubScr, - else => null, - }; - if (maybe_inst) |inst| { - try instructions.append(inst); - cursor += 2; - continue; - } - } - - switch (op) { - .LOAD_CONST => { - const index = bytes[cursor + 1]; - const inst = switch (co.consts[index]) { - .Int => |int| Instruction{ - .LoadConst = .{ .Integer = int }, - }, - .None => Instruction{ .LoadConst = .None }, - .String => |string| Instruction{ - .LoadConst = .{ .String = string }, - }, - .Tuple => |tuple| blk: { - var tuple_list = std.ArrayList(Instruction.Constant).init( - compiler.allocator, - ); - for (tuple) |tup| { - const constant = result2Const(tup); - try tuple_list.append(constant); - } - break :blk Instruction{ - .LoadConst = .{ - .Tuple = try tuple_list.toOwnedSlice(), - }, - }; - }, - .Bool => |boolean| Instruction{ - .LoadConst = .{ .Boolean = boolean }, - }, - .Float => |float| Instruction{ - .LoadConst = .{ .Float = float }, - }, - .CodeObject => unreachable, - else => |panic_op| std.debug.panic( - "cannot load inst {s}", - .{@tagName(panic_op)}, - ), - }; - try instructions.append(inst); - cursor += 2; - }, - - .LOAD_GLOBAL => { - const index = bytes[cursor + 1]; - const name = co.names[index]; - - // Just LoadConst the string. In theory it should be - // on the stack already. - - const inst = Instruction{ .LoadConst = .{ .String = name.String } }; - try instructions.append(inst); - cursor += 2; - }, - - .STORE_NAME => { - const index = bytes[cursor + 1]; - const name = co.names[index].String; - const inst = Instruction{ .StoreName = name }; - try instructions.append(inst); - cursor += 2; - }, - - .LOAD_NAME => { - const index = bytes[cursor + 1]; - const name = co.names[index].String; - const inst = Instruction{ .LoadName = name }; - try instructions.append(inst); - cursor += 2; - }, - - .CALL_FUNCTION => { - // Number of arguments above this object on the stack. - const argc = bytes[cursor + 1]; - const inst = Instruction{ .CallFunction = argc }; - try instructions.append(inst); - cursor += 2; - }, - - .CALL_FUNCTION_KW => { - // Number of arguments above this object on the stack. - const argc = bytes[cursor + 1]; - const inst = Instruction{ .CallFunctionKW = argc }; - try instructions.append(inst); - cursor += 2; - }, - - .MAKE_FUNCTION => { - const flags = bytes[cursor + 1]; - const inst = Instruction{ .MakeFunction = flags }; - try instructions.append(inst); - cursor += 2; - }, - - // Used for optimizations, literally does nothing. - .NOP => cursor += 2, - - .POP_JUMP_IF_FALSE => { - const target = bytes[cursor + 1]; - const inst = Instruction{ - .PopJump = .{ .case = false, .target = target }, - }; - try instructions.append(inst); - cursor += 2; - }, - - .POP_JUMP_IF_TRUE => { - const target = bytes[cursor + 1]; - const inst = Instruction{ - .PopJump = .{ .case = true, .target = target }, - }; - try instructions.append(inst); - cursor += 2; - }, - - .COMPARE_OP => { - const cmp_op: Instruction.CompareOp = @enumFromInt(bytes[cursor + 1]); - const inst = Instruction{ .CompareOperation = cmp_op }; - try instructions.append(inst); - cursor += 2; - }, - - .INPLACE_ADD => { - const inst = Instruction{ .BinaryOperation = .Add }; - try instructions.append(inst); - cursor += 2; - }, - - .BUILD_LIST => { - const len = bytes[cursor + 1]; - const inst = Instruction{ .BuildList = len }; - try instructions.append(inst); - cursor += 2; - }, - - .BINARY_ADD, .BINARY_SUBTRACT, .BINARY_MULTIPLY => { - const binOp: Instruction.BinaryOp = switch (op) { - .BINARY_ADD => .Add, - .BINARY_SUBTRACT => .Subtract, - .BINARY_MULTIPLY => .Multiply, - else => unreachable, - }; - - const inst = Instruction{ .BinaryOperation = binOp }; - try instructions.append(inst); - cursor += 2; - }, - - .JUMP_FORWARD => { - const delta = bytes[cursor + 1]; - const inst = Instruction{ .JumpForward = delta }; - try instructions.append(inst); - cursor += 2; - }, - - .LOAD_METHOD => { - const index = bytes[cursor + 1]; - const name = co.names[index].String; - const inst = Instruction{ .LoadMethod = name }; - try instructions.append(inst); - cursor += 2; - }, - - .CALL_METHOD => { - const argc = bytes[cursor + 1]; - const inst = Instruction{ .CallMethod = argc }; - try instructions.append(inst); - cursor += 2; - }, - - else => std.debug.panic("Unhandled opcode: {s}", .{@tagName(op)}), - } - } - - const inst_slice = try instructions.toOwnedSlice(); - - for (inst_slice) |inst| { - log.debug("Inst: {}", .{inst}); - } - - return inst_slice; -} - -fn result2Const(result: Marshal.Result) Instruction.Constant { - switch (result) { - .Int => |int| return .{ - .Integer = int, - }, - .Bool => |boolean| return .{ - .Boolean = boolean, - }, - .String => |string| return .{ - .String = string, - }, - else => std.debug.panic( - "cannot reify tuple that contains type: {s}", - .{ - @tagName(result), - }, - ), - } -} - -pub const Instruction = union(enum) { - LoadName: []const u8, - StoreName: []const u8, - LoadConst: Constant, - - PopTop: void, - Pass: void, - Continue: void, - Break: void, - - // < 90 - StoreSubScr: void, - RotTwo: void, - BinarySubScr: void, - - // Jump - PopJump: struct { case: bool, target: u32 }, - JumpForward: u32, - - LoadMethod: []const u8, - CallFunction: usize, - CallFunctionKW: usize, - CallMethod: usize, - MakeFunction: u8, - - BinaryOperation: BinaryOp, - UnaryOperation: UnaryOp, - CompareOperation: CompareOp, - - ReturnValue: void, - - // These happen at runtime - BuildList: u32, - - // Types - pub const Constant = union(enum) { - String: []const u8, - Integer: i32, - Float: f64, - Tuple: []const Constant, - Boolean: bool, - None: void, - }; - - pub const BinaryOp = enum { - Power, - Multiply, - MatrixMultiply, - Divide, - FloorDivide, - Modulo, - Add, - Subtract, - Lshift, - Rshift, - And, - Xor, - Or, - }; - - pub const CompareOp = enum(u8) { - Less = 0, - LessEqual = 1, - Equal = 2, - NotEqual = 3, - Greater = 4, - GreaterEqual = 5, - }; - - pub const UnaryOp = enum { - Not, - Minus, - }; - - pub fn format( - self: Instruction, - comptime fmt: []const u8, - _: std.fmt.FormatOptions, - writer: anytype, - ) !void { - std.debug.assert(fmt.len == 0); - - try writer.print("{s}", .{@tagName(self)}); - } -}; diff --git a/src/compiler/Instruction.zig b/src/compiler/Instruction.zig new file mode 100644 index 0000000..5f43ef0 --- /dev/null +++ b/src/compiler/Instruction.zig @@ -0,0 +1,24 @@ +//! A thin wrapper around the 2 bytes that makeup the bytecode + +const Instruction = @This(); + +op: OpCode, +extra: u8, + +const OpCode = @import("../compiler/opcodes.zig").OpCode; + +pub const BinaryOp = enum { + add, + sub, + mul, +}; + +/// WARNING: The order matters! +pub const CompareOp = enum(u8) { + Less = 0, + LessEqual = 1, + Equal = 2, + NotEqual = 3, + Greater = 4, + GreaterEqual = 5, +}; diff --git a/src/compiler/Marshal.zig b/src/compiler/Marshal.zig index 301fb26..4ffdd9b 100644 --- a/src/compiler/Marshal.zig +++ b/src/compiler/Marshal.zig @@ -199,7 +199,7 @@ fn read_codeobject(marshal: *Marshal) Result { co.filename = filename.String; co.consts = dict.get("consts").?.Tuple; - co.stacksize = @intCast(dict.get("stacksize").?.Int); + co.stack_size = @intCast(dict.get("stacksize").?.Int); co.code = dict.get("code").?.String; co.names = dict.get("names").?.Tuple; diff --git a/src/vm/Object.zig b/src/vm/Object.zig index 5966384..f089d46 100644 --- a/src/vm/Object.zig +++ b/src/vm/Object.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Vm = @import("Vm.zig"); -const Compiler = @import("../compiler/Compiler.zig"); const builtins = @import("../builtins.zig"); const BigIntConst = std.math.big.int.Const; diff --git a/src/vm/Vm.zig b/src/vm/Vm.zig index 0187fea..7c32294 100644 --- a/src/vm/Vm.zig +++ b/src/vm/Vm.zig @@ -10,7 +10,8 @@ const BigIntManaged = std.math.big.int.Managed; const tracer = @import("tracer"); const CodeObject = @import("../compiler/CodeObject.zig"); -const Instruction = @import("../compiler/Compiler.zig").Instruction; +const Instruction = @import("../compiler/Instruction.zig"); +const Marshal = @import("../compiler/Marshal.zig"); const Object = @import("Object.zig"); const Vm = @This(); @@ -19,12 +20,11 @@ const builtins = @import("../builtins.zig"); const log = std.log.scoped(.vm); -/// A raw program counter for jumping around. -program_counter: usize, - /// The VM's arena. All allocations during runtime should be made using this. allocator: Allocator, +current_co: *CodeObject, + /// VM State is_running: bool, @@ -37,8 +37,8 @@ pub fn init() !Vm { return .{ .allocator = undefined, - .program_counter = 0, .is_running = false, + .current_co = undefined, .stack = .{}, .scope = .{}, }; @@ -48,7 +48,7 @@ pub fn init() !Vm { pub fn run( vm: *Vm, alloc: Allocator, - instructions: []Instruction, + co: *CodeObject, ) !void { const t = tracer.trace(@src(), "", .{}); defer t.end(); @@ -62,6 +62,10 @@ pub fn run( vm.scope = .{}; vm.stack = .{}; + // Generate instruction wrapper. + try co.process(vm.allocator); + vm.current_co = co; + // Add the builtin functions to the scope. inline for (builtins.builtin_fns) |builtin_fn| { const name, const fn_ptr = builtin_fn; @@ -76,65 +80,73 @@ pub fn run( vm.is_running = true; while (vm.is_running) { - const instruction = instructions[vm.program_counter]; + const instruction = co.instructions[vm.current_co.index]; log.debug( "Executing Instruction: {} (stacksize={}, pc={}/{}, mem={s})", .{ - instruction, + instruction.op, vm.stack.items.len, - vm.program_counter, - instructions.len, + co.index, + co.instructions.len, std.fmt.fmtIntSizeDec(arena.state.end_index), }, ); - vm.program_counter += 1; + vm.current_co.index += 1; try vm.exec(instruction); } } -fn exec(vm: *Vm, i: Instruction) !void { - const t = tracer.trace(@src(), "{s}", .{@tagName(i)}); +fn exec(vm: *Vm, inst: Instruction) !void { + const t = tracer.trace(@src(), "{s}", .{@tagName(inst.op)}); defer t.end(); - switch (i) { - .LoadConst => |constant| try vm.execLoadConst(constant), - .LoadName => |name| try vm.execLoadName(name), - .LoadMethod => |name| try vm.execLoadMethod(name), - .BuildList => |argc| try vm.execBuildList(argc), + switch (inst.op) { + .LOAD_CONST => try vm.execLoadConst(inst), + .LOAD_NAME => try vm.execLoadName(inst), + .LOAD_METHOD => try vm.execLoadMethod(inst), + .BUILD_LIST => try vm.execBuildList(inst), + + .STORE_NAME => try vm.execStoreName(inst), + .STORE_SUBSCR => try vm.execStoreSubScr(), - .StoreName => |name| try vm.execStoreName(name), - .StoreSubScr => try vm.execStoreSubScr(), + .RETURN_VALUE => try vm.execReturnValue(), - .ReturnValue => try vm.execReturnValue(), + .POP_TOP => try vm.execPopTop(), + .POP_JUMP_IF_TRUE => try vm.execPopJump(inst, true), + .POP_JUMP_IF_FALSE => try vm.execPopJump(inst, false), - .PopTop => try vm.execPopTop(), - .PopJump => |s| try vm.execPopJump(s), + .INPLACE_ADD, .BINARY_ADD => try vm.execBinaryOperation(.add), + .INPLACE_SUBTRACT, .BINARY_SUBTRACT => try vm.execBinaryOperation(.sub), + .INPLACE_MULTIPLY, .BINARY_MULTIPLY => try vm.execBinaryOperation(.mul), - .BinaryOperation => |operation| try vm.execBinaryOperation(operation), - .CompareOperation => |operation| try vm.execCompareOperation(operation), + .COMPARE_OP => try vm.execCompareOperation(inst), - .CallFunction => |argc| try vm.execCallFunction(argc), - .CallFunctionKW => |argc| try vm.execCallFunctionKW(argc), - .CallMethod => |argc| try vm.execCallMethod(argc), + .CALL_FUNCTION => try vm.execCallFunction(inst), + .CALL_FUNCTION_KW => try vm.execCallFunctionKW(inst), + .CALL_METHOD => try vm.execCallMethod(inst), - else => std.debug.panic("TODO: exec{s}", .{@tagName(i)}), + else => std.debug.panic("TODO: {s}", .{@tagName(inst.op)}), } } /// Stores an immediate Constant on the stack. -fn execLoadConst(vm: *Vm, load_const: Instruction.Constant) !void { - const val = try vm.loadConst(load_const); +fn execLoadConst(vm: *Vm, inst: Instruction) !void { + const constant = vm.current_co.consts[inst.extra]; + const val = try vm.loadConst(constant); try vm.stack.append(vm.allocator, val); } -fn execLoadName(vm: *Vm, name: []const u8) !void { +fn execLoadName(vm: *Vm, inst: Instruction) !void { + const name = vm.current_co.getName(inst.extra); const val = vm.scope.get(name) orelse std.debug.panic("couldn't find '{s}' on the scope", .{name}); try vm.stack.append(vm.allocator, val); } -fn execLoadMethod(vm: *Vm, name: []const u8) !void { +fn execLoadMethod(vm: *Vm, inst: Instruction) !void { + const name = vm.current_co.getName(inst.extra); + const tos = vm.stack.pop(); const func = try tos.getMemberFunction(name, vm) orelse std.debug.panic( @@ -146,8 +158,10 @@ fn execLoadMethod(vm: *Vm, name: []const u8) !void { try vm.stack.append(vm.allocator, tos); } -fn execStoreName(vm: *Vm, name: []const u8) !void { +fn execStoreName(vm: *Vm, inst: Instruction) !void { + const name = vm.current_co.getName(inst.extra); const tos = vm.stack.pop(); + // TODO: don't want to clobber here, make it more controlled. // i know i will forget why variables are being overwritten correctly. try vm.scope.put(vm.allocator, name, tos); @@ -158,16 +172,16 @@ fn execReturnValue(vm: *Vm) !void { vm.is_running = false; } -fn execBuildList(vm: *Vm, count: u32) !void { - const objects = try vm.popNObjects(count); +fn execBuildList(vm: *Vm, inst: Instruction) !void { + const objects = try vm.popNObjects(inst.extra); const list = std.ArrayListUnmanaged(Object).fromOwnedSlice(objects); const val = try Object.create(.list, vm.allocator, .{ .list = list }); try vm.stack.append(vm.allocator, val); } -fn execCallFunction(vm: *Vm, argc: usize) !void { - const args = try vm.popNObjects(argc); +fn execCallFunction(vm: *Vm, inst: Instruction) !void { + const args = try vm.popNObjects(inst.extra); const func = vm.stack.pop(); const func_ptr = func.get(.zig_function); @@ -175,7 +189,7 @@ fn execCallFunction(vm: *Vm, argc: usize) !void { try @call(.auto, func_ptr.*, .{ vm, args, null }); } -fn execCallFunctionKW(vm: *Vm, argc: usize) !void { +fn execCallFunctionKW(vm: *Vm, inst: Instruction) !void { const kw_tuple = vm.stack.pop(); const kw_tuple_slice = if (kw_tuple.tag == .tuple) kw_tuple.get(.tuple).* @@ -191,7 +205,7 @@ fn execCallFunctionKW(vm: *Vm, argc: usize) !void { try kw_args.put(name, val); } - const positional_args = try vm.popNObjects(argc - tuple_len); + const positional_args = try vm.popNObjects(inst.extra - tuple_len); const func = vm.stack.pop(); const func_ptr = func.get(.zig_function); @@ -199,8 +213,8 @@ fn execCallFunctionKW(vm: *Vm, argc: usize) !void { try @call(.auto, func_ptr.*, .{ vm, positional_args, kw_args }); } -fn execCallMethod(vm: *Vm, argc: usize) !void { - const args = try vm.popNObjects(argc); +fn execCallMethod(vm: *Vm, inst: Instruction) !void { + const args = try vm.popNObjects(inst.extra); const self = vm.stack.pop(); const func = vm.stack.pop(); @@ -228,18 +242,17 @@ fn execBinaryOperation(vm: *Vm, op: Instruction.BinaryOp) !void { var result = try BigIntManaged.init(vm.allocator); switch (op) { - .Add => try result.add(&x_int, &y_int), - .Subtract => try result.sub(&x_int, &y_int), - .Multiply => try result.mul(&x_int, &y_int), - // .Divide => try result.div(&rem, &x_int, &y_int), - else => std.debug.panic("TOOD: execBinaryOperation '{s}'", .{@tagName(op)}), + .add => try result.add(&x_int, &y_int), + .sub => try result.sub(&x_int, &y_int), + .mul => try result.mul(&x_int, &y_int), + // TODO: more } const result_val = try Object.create(.int, vm.allocator, .{ .int = result }); try vm.stack.append(vm.allocator, result_val); } -fn execCompareOperation(vm: *Vm, op: Instruction.CompareOp) !void { +fn execCompareOperation(vm: *Vm, inst: Instruction) !void { const x = vm.stack.pop(); const y = vm.stack.pop(); @@ -251,6 +264,8 @@ fn execCompareOperation(vm: *Vm, op: Instruction.CompareOp) !void { const order = y_int.order(x_int); + const op: Instruction.CompareOp = @enumFromInt(inst.extra); + const boolean = switch (op) { // zig fmt: off .Less => (order == .lt), @@ -303,7 +318,7 @@ fn execStoreSubScr(vm: *Vm) !void { } } -fn execPopJump(vm: *Vm, case: anytype) !void { +fn execPopJump(vm: *Vm, inst: Instruction, case: bool) !void { const tos = vm.stack.pop(); const tos_bool = if (tos.tag == .boolean) @@ -311,8 +326,8 @@ fn execPopJump(vm: *Vm, case: anytype) !void { else @panic("PopJump TOS not bool"); - if (tos_bool == case.case) { - vm.program_counter = case.target; + if (tos_bool == case) { + vm.current_co.index = inst.extra; } } @@ -331,16 +346,16 @@ fn popNObjects(vm: *Vm, n: usize) ![]Object { return objects; } -fn loadConst(vm: *Vm, load_const: Instruction.Constant) !Object { - switch (load_const) { - .Integer => |int| { +fn loadConst(vm: *Vm, inst: Marshal.Result) !Object { + switch (inst) { + .Int => |int| { const big_int = try BigIntManaged.initSet(vm.allocator, int); return Object.create(.int, vm.allocator, .{ .int = big_int }); }, .String => |string| { return Object.create(.string, vm.allocator, .{ .string = string }); }, - .Boolean => |boolean| { + .Bool => |boolean| { return Object.create(.boolean, vm.allocator, .{ .boolean = boolean }); }, .None => return Object.init(.none), @@ -351,6 +366,6 @@ fn loadConst(vm: *Vm, load_const: Instruction.Constant) !Object { } return Object.create(.tuple, vm.allocator, items); }, - else => std.debug.panic("TODO: loadConst {s}", .{@tagName(load_const)}), + else => std.debug.panic("TODO: loadConst {s}", .{@tagName(inst)}), } }