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:
parent
8356b6c750
commit
5b7d9586ea
26 changed files with 1113 additions and 351 deletions
|
@ -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,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue