147 lines
3.5 KiB
Zig
147 lines
3.5 KiB
Zig
const std = @import("std");
|
|
const mem = std.mem;
|
|
const builtin = @import("builtin");
|
|
|
|
const bytecode = @import("bytecode.zig");
|
|
const Canvas = @import("canvas.zig").Canvas;
|
|
const render = @import("render.zig");
|
|
const Scratch = @import("scratch.zig");
|
|
const value = @import("value.zig");
|
|
const Vm = @import("vm.zig");
|
|
|
|
const allocator = if (builtin.cpu.arch == .wasm32) std.heap.wasm_allocator else @import("allocator.zig").hostAllocator;
|
|
|
|
// Scratch
|
|
|
|
export fn haku2_scratch_new(max: usize) ?*Scratch {
|
|
return Scratch.create(allocator, max) catch return null;
|
|
}
|
|
|
|
export fn haku2_scratch_destroy(scratch: *Scratch) void {
|
|
scratch.destroy(allocator);
|
|
}
|
|
|
|
export fn haku2_scratch_reset(scratch: *Scratch) void {
|
|
scratch.fixedBuffer = std.heap.FixedBufferAllocator.init(scratch.buffer);
|
|
}
|
|
|
|
// Limits
|
|
|
|
export fn haku2_limits_new() ?*Vm.Limits {
|
|
return allocator.create(Vm.Limits) catch null;
|
|
}
|
|
|
|
export fn haku2_limits_destroy(limits: *Vm.Limits) void {
|
|
allocator.destroy(limits);
|
|
}
|
|
|
|
export fn haku2_limits_set_stack_capacity(limits: *Vm.Limits, new: usize) void {
|
|
limits.stack_capacity = new;
|
|
}
|
|
|
|
export fn haku2_limits_set_call_stack_capacity(limits: *Vm.Limits, new: usize) void {
|
|
limits.call_stack_capacity = new;
|
|
}
|
|
|
|
export fn haku2_limits_set_fuel(limits: *Vm.Limits, new: u32) void {
|
|
limits.fuel = new;
|
|
}
|
|
|
|
// Defs
|
|
|
|
export fn haku2_defs_parse(
|
|
defs_string: [*]const u8,
|
|
defs_len: usize,
|
|
tags_string: [*]const u8,
|
|
tags_len: usize,
|
|
) ?*bytecode.Defs {
|
|
return bytecode.Defs.parse(
|
|
allocator,
|
|
defs_string[0..defs_len],
|
|
tags_string[0..tags_len],
|
|
) catch null;
|
|
}
|
|
|
|
export fn haku2_defs_destroy(defs: *bytecode.Defs) void {
|
|
defs.destroy(allocator);
|
|
}
|
|
|
|
// VM
|
|
|
|
export fn haku2_vm_new(s: *Scratch, defs: *const bytecode.Defs, limits: *const Vm.Limits) ?*Vm {
|
|
const vm = allocator.create(Vm) catch return null;
|
|
errdefer allocator.destroy(vm);
|
|
|
|
vm.* = Vm.init(s.allocator(), defs, limits) catch return null;
|
|
|
|
return vm;
|
|
}
|
|
|
|
export fn haku2_vm_destroy(vm: *Vm) void {
|
|
allocator.destroy(vm);
|
|
}
|
|
|
|
export fn haku2_vm_run_main(
|
|
vm: *Vm,
|
|
scratch: *Scratch,
|
|
code: [*]const u8,
|
|
code_len: usize,
|
|
local_count: u8,
|
|
) bool {
|
|
const chunk = bytecode.Chunk{
|
|
.bytecode = code[0..code_len],
|
|
};
|
|
const closure = value.Closure{
|
|
.chunk = &chunk,
|
|
.start = 0,
|
|
.param_count = 0,
|
|
.local_count = local_count,
|
|
.captures = &[_]value.Value{},
|
|
};
|
|
vm.run(scratch.allocator(), &closure, vm.stack_top) catch return false;
|
|
return true;
|
|
}
|
|
|
|
export fn haku2_vm_is_dotter(vm: *const Vm) bool {
|
|
if (vm.stack.len == 0) return false;
|
|
const top = vm.stack[vm.stack_top];
|
|
return top == .ref and top.ref.* == .reticle and top.ref.reticle == .dotter;
|
|
}
|
|
|
|
export fn haku2_vm_run_dotter(
|
|
vm: *Vm,
|
|
scratch: *Scratch,
|
|
from_x: f32,
|
|
from_y: f32,
|
|
to_x: f32,
|
|
to_y: f32,
|
|
num: f32,
|
|
) bool {
|
|
vm.runDotter(
|
|
scratch.allocator(),
|
|
.{ from_x, from_y, 0, 0 },
|
|
.{ to_x, to_y, 0, 0 },
|
|
num,
|
|
) catch return false;
|
|
return true;
|
|
}
|
|
|
|
export fn haku2_vm_exception_len(vm: *const Vm) usize {
|
|
if (vm.exception) |exn| {
|
|
return exn.len;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
export fn haku2_vm_exception_render(vm: *const Vm, buffer: [*]u8) void {
|
|
const exn = vm.exception.?;
|
|
_ = exn.format(buffer[0..exn.len], &exn.args);
|
|
}
|
|
|
|
// Renderer
|
|
|
|
export fn haku2_render(vm: *Vm, canvas: *Canvas, max_depth: usize) bool {
|
|
render.render(vm, canvas, max_depth) catch return false;
|
|
return true;
|
|
}
|