haku2: make server use haku2 (and make it work!)

This commit is contained in:
りき萌 2025-06-13 20:11:52 +02:00
parent c5e2892def
commit 48d03699bd
16 changed files with 329 additions and 174 deletions

View file

@ -7,6 +7,8 @@ use std::{
slice,
};
use log::{debug, trace};
#[unsafe(no_mangle)]
unsafe extern "C" fn __haku2_alloc(size: usize, align: usize) -> *mut u8 {
if let Ok(layout) = Layout::from_size_align(size, align) {
@ -121,7 +123,6 @@ extern "C" {
fn haku2_limits_destroy(limits: *mut LimitsC);
fn haku2_limits_set_stack_capacity(limits: *mut LimitsC, new: usize);
fn haku2_limits_set_call_stack_capacity(limits: *mut LimitsC, new: usize);
fn haku2_limits_set_fuel(limits: *mut LimitsC, new: u32);
fn haku2_defs_parse(
defs_string: *const u8,
@ -133,6 +134,7 @@ extern "C" {
fn haku2_vm_new(s: *mut ScratchC, defs: *const DefsC, limits: *const LimitsC) -> *mut VmC;
fn haku2_vm_destroy(vm: *mut VmC);
fn haku2_vm_reset(vm: *mut VmC, fuel: u32);
fn haku2_vm_run_main(
vm: *mut VmC,
scratch: *mut ScratchC,
@ -167,13 +169,14 @@ pub struct Scratch {
impl Scratch {
pub fn new(max: usize) -> Scratch {
Scratch {
// SAFETY: haku2_scratch_new does not have any safety invariants.
raw: NonNull::new(unsafe { haku2_scratch_new(max) }).expect("out of memory"),
}
// SAFETY: haku2_scratch_new does not have any safety invariants.
let raw = NonNull::new(unsafe { haku2_scratch_new(max) }).expect("out of memory");
trace!("Scratch::new -> {raw:?}");
Scratch { raw }
}
pub fn reset(&mut self) {
trace!("Scratch::reset({:?})", self.raw);
// SAFETY: The pointer passed is non-null.
unsafe {
haku2_scratch_reset(self.raw.as_ptr());
@ -183,6 +186,7 @@ impl Scratch {
impl Drop for Scratch {
fn drop(&mut self) {
trace!("Scratch::drop({:?})", self.raw);
// SAFETY: The pointer passed is non-null.
unsafe {
haku2_scratch_destroy(self.raw.as_ptr());
@ -194,7 +198,6 @@ impl Drop for Scratch {
pub struct LimitsSpec {
pub stack_capacity: usize,
pub call_stack_capacity: usize,
pub fuel: u32,
}
#[derive(Debug)]
@ -216,7 +219,6 @@ impl Limits {
unsafe {
haku2_limits_set_stack_capacity(limits.as_ptr(), spec.stack_capacity);
haku2_limits_set_call_stack_capacity(limits.as_ptr(), spec.call_stack_capacity);
haku2_limits_set_fuel(limits.as_ptr(), spec.fuel);
}
Self { raw: limits }
@ -315,21 +317,21 @@ pub struct Dotter {
impl Vm {
pub fn new(scratch: Scratch, code: Code, limits: &Limits) -> Self {
let raw = NonNull::new(unsafe {
haku2_vm_new(
scratch.raw.as_ptr(),
code.defs.raw.as_ptr(),
limits.raw.as_ptr(),
)
})
.expect("out of memory");
trace!("Vm::new({scratch:?}, {code:?}, {limits:?}) -> {raw:?}");
Self {
// SAFETY:
// - Ownership of scratch is passed to the VM, so the VM cannot outlive the scratch space.
// - The VM never gives you any references back, so this is safe to do.
// - The other arguments are only borrowed immutably for construction.
inner: VmInner {
raw: NonNull::new(unsafe {
haku2_vm_new(
scratch.raw.as_ptr(),
code.defs.raw.as_ptr(),
limits.raw.as_ptr(),
)
})
.expect("out of memory"),
},
inner: VmInner { raw },
scratch,
code,
}
@ -340,8 +342,10 @@ impl Vm {
///
/// Calling `begin` again during this process will work correctly, and result in another
/// continuation being stack on top of the old one---at the expense of a stack slot.
pub fn begin(&mut self) -> Result<(), Exception> {
pub fn begin(&mut self, fuel: u32) -> Result<(), Exception> {
trace!("Vm::begin({self:?}, {fuel})");
let ok = unsafe {
haku2_vm_reset(self.inner.raw.as_ptr(), fuel);
haku2_vm_run_main(
self.inner.raw.as_ptr(),
self.scratch.raw.as_ptr(),
@ -411,6 +415,7 @@ impl Vm {
/// Take the `Scratch` out of the VM for reuse in another one.
/// The scratch memory will be reset (no bytes will be consumed.)
pub fn into_scratch(self) -> Scratch {
trace!("Vm::into_scratch({self:?})");
let Vm {
mut scratch,
code: _,
@ -423,6 +428,8 @@ impl Vm {
impl ContDotter<'_> {
pub fn run(self, dotter: &Dotter) -> Result<(), Exception> {
trace!("ContDotter::run({self:?}, {dotter:?})");
let Dotter {
from: (from_x, from_y),
to: (to_x, to_y),
@ -455,6 +462,7 @@ struct VmInner {
impl Drop for VmInner {
fn drop(&mut self) {
trace!("VmInner::drop({:?})", self.raw);
// SAFETY: The pointer passed is non-null.
unsafe {
haku2_vm_destroy(self.raw.as_ptr());