haku2: rest of functionality (hopefully) & Rust->Zig FFI
This commit is contained in:
parent
01d4514a65
commit
550227da34
7 changed files with 716 additions and 38 deletions
|
@ -1,8 +1,10 @@
|
|||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const debug = std.debug;
|
||||
const testAllocator = std.testing.allocator;
|
||||
|
||||
const bytecode = @import("bytecode.zig");
|
||||
const Canvas = @import("canvas.zig");
|
||||
const system = @import("system.zig");
|
||||
const value = @import("value.zig");
|
||||
const Value = value.Value;
|
||||
|
@ -15,7 +17,6 @@ call_stack: []CallFrame,
|
|||
call_stack_top: u32 = 0,
|
||||
defs: []Value,
|
||||
fuel: u32,
|
||||
exception_buffer: [1024]u8 = [_]u8{0} ** 1024, // buffer for exception message
|
||||
exception: ?Exception = null,
|
||||
|
||||
pub const Limits = struct {
|
||||
|
@ -31,7 +32,9 @@ pub const CallFrame = struct {
|
|||
};
|
||||
|
||||
pub const Exception = struct {
|
||||
message: []const u8,
|
||||
len: usize,
|
||||
format: *const fn (buf: []u8, args: *align(64) const anyopaque) []u8,
|
||||
args: [40]u8 align(64), // increase the size if we ever throw a larger exception
|
||||
};
|
||||
|
||||
/// All errors coming from inside the VM get turned into a single Exception type, which signals
|
||||
|
@ -51,11 +54,28 @@ pub fn init(a: mem.Allocator, defs: *const bytecode.Defs, limits: *const Limits)
|
|||
}
|
||||
|
||||
pub fn throw(vm: *Vm, comptime fmt: []const u8, args: anytype) Error {
|
||||
const message = std.fmt.bufPrint(vm.exception_buffer[0..], fmt, args) catch {
|
||||
vm.exception = .{ .message = "[exception message is too long; format string: " ++ fmt ++ "]" };
|
||||
return error.Exception;
|
||||
const Args = @TypeOf(args);
|
||||
const max_args_size = @sizeOf(@TypeOf(vm.exception.?.args));
|
||||
if (@sizeOf(Args) > max_args_size) {
|
||||
@compileError(std.fmt.comptimePrint(
|
||||
"format arguments are too large; size={}, max={}",
|
||||
.{ @sizeOf(Args), max_args_size },
|
||||
));
|
||||
}
|
||||
|
||||
const Formatter = struct {
|
||||
fn format(buf: []u8, erased_args: *align(64) const anyopaque) []u8 {
|
||||
return std.fmt.bufPrint(buf, fmt, @as(*const Args, @ptrCast(erased_args)).*) catch unreachable;
|
||||
}
|
||||
};
|
||||
vm.exception = .{ .message = message };
|
||||
|
||||
var exn = Exception{
|
||||
.len = @truncate(std.fmt.count(fmt, args)),
|
||||
.format = Formatter.format,
|
||||
.args = undefined,
|
||||
};
|
||||
@memcpy(exn.args[0..@sizeOf(Args)], mem.asBytes(&args));
|
||||
|
||||
return error.Exception;
|
||||
}
|
||||
|
||||
|
@ -452,7 +472,43 @@ pub fn run(
|
|||
try vm.consumeFuel(&fuel, 1);
|
||||
// NOTE: Not a validateBytecode call because this is zero-cost on the happy path,
|
||||
// so we don't need to disable it on release builds.
|
||||
return vm.throw("corrupted bytecode (invalid opcode {})", .{invalid_opcode});
|
||||
return vm.throw("corrupted bytecode: invalid opcode {}", .{invalid_opcode});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const Dotter = struct {
|
||||
from: value.Vec4,
|
||||
to: value.Vec4,
|
||||
num: f32,
|
||||
};
|
||||
|
||||
/// NOTE: Assumes the value at the top is a dotter reticle.
|
||||
pub fn runDotter(
|
||||
vm: *Vm,
|
||||
allocator: mem.Allocator,
|
||||
from: value.Vec4,
|
||||
to: value.Vec4,
|
||||
num: f32,
|
||||
) Error!void {
|
||||
const reticle = try vm.pop();
|
||||
const draw = reticle.ref.reticle.dotter.draw; // parameter count checked on construction
|
||||
|
||||
const data = allocator.dupe(Value, &[_]Value{
|
||||
.{ .vec4 = from },
|
||||
.{ .vec4 = to },
|
||||
.{ .number = num },
|
||||
}) catch return vm.outOfMemory();
|
||||
const ref = allocator.create(value.Ref) catch return vm.outOfMemory();
|
||||
ref.* = value.Ref{ .closure = .{
|
||||
.chunk = &system.record_dotter,
|
||||
.start = 0,
|
||||
.param_count = 1,
|
||||
.local_count = 0,
|
||||
.captures = data,
|
||||
} };
|
||||
|
||||
const bottom = vm.stack_top;
|
||||
try vm.push(.{ .ref = ref });
|
||||
try vm.run(allocator, draw, bottom);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue