introduce tags, structs, and reticles

this was meant to be split into smaller changes, but I realised I edited my existing revision too late.
This commit is contained in:
りき萌 2024-09-08 13:53:29 +02:00
parent 8356b6c750
commit 5b7d9586ea
26 changed files with 1113 additions and 351 deletions

View file

@ -7,19 +7,20 @@ use core::{alloc::Layout, slice};
use alloc::{boxed::Box, vec::Vec};
use haku::{
ast::Ast,
bytecode::{Chunk, Defs, DefsImage},
bytecode::{Chunk, Defs, DefsImage, DefsLimits},
compiler::{compile_expr, ClosureSpec, CompileError, Compiler, Source},
diagnostic::Diagnostic,
lexer::{lex, Lexer},
parser::{self, IntoAstError, Parser},
render::{
tiny_skia::{Pixmap, PremultipliedColorU8},
Renderer, RendererLimits,
RendererLimits,
},
source::SourceCode,
system::{ChunkId, System, SystemImage},
token::Lexis,
value::{Closure, Ref, Value},
trampoline::{Cont, Trampoline},
value::{Closure, Ref, Vec2},
vm::{Exception, Vm, VmImage, VmLimits},
};
use log::{debug, info};
@ -46,6 +47,7 @@ struct Limits {
max_source_code_len: usize,
max_chunks: usize,
max_defs: usize,
max_tags: usize,
max_tokens: usize,
max_parser_events: usize,
ast_capacity: usize,
@ -65,6 +67,7 @@ impl Default for Limits {
max_source_code_len: 65536,
max_chunks: 2,
max_defs: 256,
max_tags: 256,
max_tokens: 1024,
max_parser_events: 1024,
ast_capacity: 1024,
@ -110,6 +113,7 @@ macro_rules! limit_setter {
limit_setter!(max_source_code_len);
limit_setter!(max_chunks);
limit_setter!(max_defs);
limit_setter!(max_tags);
limit_setter!(max_tokens);
limit_setter!(max_parser_events);
limit_setter!(ast_capacity);
@ -133,10 +137,22 @@ struct Instance {
vm: Vm,
vm_image: VmImage,
value: Value,
trampoline: Option<Trampoline>,
exception: Option<Exception>,
}
impl Instance {
fn set_exception(&mut self, exn: Exception) {
debug!("setting exception = {exn:?}");
self.exception = Some(exn);
}
fn reset_exception(&mut self) {
debug!("resetting exception");
self.exception = None;
}
}
#[no_mangle]
unsafe extern "C" fn haku_instance_new(limits: *const Limits) -> *mut Instance {
let limits = *limits;
@ -144,7 +160,10 @@ unsafe extern "C" fn haku_instance_new(limits: *const Limits) -> *mut Instance {
let system = System::new(limits.max_chunks);
let defs = Defs::new(limits.max_defs);
let defs = Defs::new(&DefsLimits {
max_defs: limits.max_defs,
max_tags: limits.max_tags,
});
let vm = Vm::new(
&defs,
&VmLimits {
@ -168,7 +187,7 @@ unsafe extern "C" fn haku_instance_new(limits: *const Limits) -> *mut Instance {
defs_image,
vm,
vm_image,
value: Value::Nil,
trampoline: None,
exception: None,
});
@ -191,13 +210,6 @@ unsafe extern "C" fn haku_reset(instance: *mut Instance) {
instance.defs.restore_image(&instance.defs_image);
}
#[no_mangle]
unsafe extern "C" fn haku_reset_vm(instance: *mut Instance) {
debug!("resetting instance VM: {instance:?}");
let instance = &mut *instance;
instance.vm.restore_image(&instance.vm_image);
}
#[no_mangle]
unsafe extern "C" fn haku_has_exception(instance: *mut Instance) -> bool {
(*instance).exception.is_some()
@ -426,39 +438,35 @@ unsafe extern "C" fn haku_compile_brush(
StatusCode::Ok
}
struct PixmapLock {
pixmap: Pixmap,
}
#[no_mangle]
extern "C" fn haku_pixmap_new(width: u32, height: u32) -> *mut PixmapLock {
let ptr = Box::leak(Box::new(PixmapLock {
pixmap: Pixmap::new(width, height).expect("invalid pixmap size"),
})) as *mut _;
extern "C" fn haku_pixmap_new(width: u32, height: u32) -> *mut Pixmap {
let ptr = Box::leak(Box::new(
Pixmap::new(width, height).expect("invalid pixmap size"),
)) as *mut _;
debug!("created pixmap with size {width}x{height}: {ptr:?}");
ptr
}
#[no_mangle]
unsafe extern "C" fn haku_pixmap_destroy(pixmap: *mut PixmapLock) {
unsafe extern "C" fn haku_pixmap_destroy(pixmap: *mut Pixmap) {
debug!("destroying pixmap: {pixmap:?}");
drop(Box::from_raw(pixmap))
}
#[no_mangle]
unsafe extern "C" fn haku_pixmap_data(pixmap: *mut PixmapLock) -> *mut u8 {
let pixmap = &mut (*pixmap).pixmap;
unsafe extern "C" fn haku_pixmap_data(pixmap: *mut Pixmap) -> *mut u8 {
let pixmap = &mut *pixmap;
pixmap.pixels_mut().as_mut_ptr() as *mut u8
}
#[no_mangle]
unsafe extern "C" fn haku_pixmap_clear(pixmap: *mut PixmapLock) {
let pixmap = &mut (*pixmap).pixmap;
unsafe extern "C" fn haku_pixmap_clear(pixmap: *mut Pixmap) {
let pixmap = &mut *pixmap;
pixmap.pixels_mut().fill(PremultipliedColorU8::TRANSPARENT);
}
#[no_mangle]
unsafe extern "C" fn haku_eval_brush(instance: *mut Instance, brush: *const Brush) -> StatusCode {
unsafe extern "C" fn haku_begin_brush(instance: *mut Instance, brush: *const Brush) -> StatusCode {
let instance = &mut *instance;
let brush = &*brush;
@ -466,8 +474,10 @@ unsafe extern "C" fn haku_eval_brush(instance: *mut Instance, brush: *const Brus
panic!("brush is not compiled and ready to be used");
};
debug!("applying defs");
instance.vm.restore_image(&instance.vm_image);
instance.vm.apply_defs(&instance.defs);
instance.reset_exception();
instance.trampoline = None;
let Ok(closure_id) = instance
.vm
@ -476,51 +486,91 @@ unsafe extern "C" fn haku_eval_brush(instance: *mut Instance, brush: *const Brus
return StatusCode::OutOfRefSlots;
};
debug!("resetting exception");
instance.exception = None;
instance.value = match instance.vm.run(&instance.system, closure_id) {
instance.reset_exception();
let value = match instance.vm.run(&instance.system, closure_id, &[]) {
Ok(value) => value,
Err(exn) => {
debug!("setting exception {exn:?}");
instance.exception = Some(exn);
instance.set_exception(exn);
return StatusCode::EvalException;
}
};
instance.trampoline = Some(Trampoline::new(value));
StatusCode::Ok
}
#[no_mangle]
unsafe extern "C" fn haku_render_value(
unsafe extern "C" fn haku_cont_kind(instance: *mut Instance) -> Cont {
let instance = &mut *instance;
instance.trampoline.as_ref().unwrap().cont(&instance.vm)
}
fn wrap_exception(
instance: &mut Instance,
error_code: StatusCode,
f: impl FnOnce(&mut Instance) -> Result<(), Exception>,
) -> StatusCode {
match f(instance) {
Ok(_) => StatusCode::Ok,
Err(exn) => {
instance.set_exception(exn);
error_code
}
}
}
#[no_mangle]
unsafe extern "C" fn haku_cont_scribble(
instance: *mut Instance,
pixmap: *mut PixmapLock,
pixmap: *mut Pixmap,
translation_x: f32,
translation_y: f32,
) -> StatusCode {
let instance = &mut *instance;
debug!("resetting exception");
instance.exception = None;
instance.reset_exception();
debug!("will render value: {:?}", instance.value);
debug!("cont_scribble: pixmap={pixmap:?} translation_x={translation_x:?} translation_y={translation_y:?} trampoline={:?}", instance.trampoline);
let pixmap_locked = &mut (*pixmap).pixmap;
let mut renderer = Renderer::new(
pixmap_locked,
&RendererLimits {
pixmap_stack_capacity: instance.limits.pixmap_stack_capacity,
transform_stack_capacity: instance.limits.transform_stack_capacity,
},
);
renderer.translate(translation_x, translation_y);
match renderer.render(&instance.vm, instance.value) {
Ok(()) => (),
Err(exn) => {
instance.exception = Some(exn);
instance.vm.restore_image(&instance.vm_image);
return StatusCode::RenderException;
}
}
StatusCode::Ok
wrap_exception(instance, StatusCode::RenderException, |instance| {
instance.trampoline.as_mut().unwrap().scribble(
&instance.vm,
&mut *pixmap,
Vec2 {
x: translation_x,
y: translation_y,
},
&RendererLimits {
pixmap_stack_capacity: instance.limits.pixmap_stack_capacity,
transform_stack_capacity: instance.limits.transform_stack_capacity,
},
)
})
}
#[no_mangle]
unsafe extern "C" fn haku_cont_dotter(
instance: *mut Instance,
from_x: f32,
from_y: f32,
to_x: f32,
to_y: f32,
num: f32,
) -> StatusCode {
let instance = &mut *instance;
instance.reset_exception();
debug!(
"cont_dotter: from_x={from_x} from_y={from_y} to_x={to_x} to_y={to_y} trampoline={:?}",
instance.trampoline
);
wrap_exception(instance, StatusCode::RenderException, |instance| {
instance.trampoline.as_mut().unwrap().dotter(
&mut instance.vm,
&instance.system,
Vec2::new(from_x, from_y),
Vec2::new(to_x, to_y),
num,
)
})
}