rkgk/crates/haku2/src/haku2.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;
}