add lists & VM memory limits

This commit is contained in:
りき萌 2024-08-20 23:00:39 +02:00
parent 1c0fa7197c
commit 50094c3872
9 changed files with 54 additions and 6 deletions

View file

@ -71,12 +71,17 @@ impl<'a> Renderer<'a> {
let (_id, scribble) = vm
.get_ref_value(value)
.ok_or_else(|| Self::create_exception(vm, value, NOT_A_SCRIBBLE))?;
let Ref::Scribble(scribble) = scribble else {
return Err(Self::create_exception(vm, value, NOT_A_SCRIBBLE));
};
match scribble {
Scribble::Stroke(stroke) => self.render_stroke(vm, value, stroke)?,
match &scribble {
Ref::List(list) => {
for element in &list.elements {
self.render(vm, *element)?;
}
}
Ref::Scribble(scribble) => match scribble {
Scribble::Stroke(stroke) => self.render_stroke(vm, value, stroke)?,
},
_ => return Err(Self::create_exception(vm, value, NOT_A_SCRIBBLE))?,
}
Ok(())

View file

@ -99,8 +99,10 @@ impl Display for ChunkError {
impl Error for ChunkError {}
pub mod fns {
use alloc::vec::Vec;
use crate::{
value::{Ref, Rgba, Scribble, Shape, Stroke, Value, Vec4},
value::{List, Ref, Rgba, Scribble, Shape, Stroke, Value, Vec4},
vm::{Exception, FnArgs, Vm},
};
@ -133,6 +135,8 @@ pub mod fns {
0x88 ".b" => rgba_b,
0x89 ".a" => rgba_a,
0x90 "list" => list,
0xc0 "to-shape" => to_shape_f,
0xc1 "line" => line,
0xe0 "stroke" => stroke,
@ -389,6 +393,13 @@ pub mod fns {
Ok(Value::Number(rgba.r))
}
pub fn list(vm: &mut Vm, args: FnArgs) -> Result<Value, Exception> {
let elements: Vec<_> = (0..args.num()).map(|i| args.get(vm, i)).collect();
vm.track_array(&elements)?;
let id = vm.create_ref(Ref::List(List { elements }))?;
Ok(Value::Ref(id))
}
fn to_shape(value: Value, vm: &Vm) -> Option<Shape> {
match value {
Value::Nil | Value::False | Value::True | Value::Number(_) | Value::Rgba(_) => None,

View file

@ -105,6 +105,7 @@ impl RefId {
#[derive(Debug, Clone)]
pub enum Ref {
Closure(Closure),
List(List),
Shape(Shape),
Scribble(Scribble),
}
@ -143,6 +144,11 @@ pub struct Closure {
pub captures: Vec<Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct List {
pub elements: Vec<Value>,
}
#[derive(Debug, Clone)]
pub enum Shape {
Point(Vec4),

View file

@ -17,6 +17,7 @@ pub struct VmLimits {
pub call_stack_capacity: usize,
pub ref_capacity: usize,
pub fuel: usize,
pub memory: usize,
}
#[derive(Debug, Clone)]
@ -26,6 +27,7 @@ pub struct Vm {
refs: Vec<Ref>,
defs: Vec<Value>,
fuel: usize,
memory: usize,
}
#[derive(Debug, Clone, Copy)]
@ -33,6 +35,7 @@ pub struct VmImage {
refs: usize,
defs: usize,
fuel: usize,
memory: usize,
}
#[derive(Debug, Clone)]
@ -55,6 +58,7 @@ impl Vm {
refs: Vec::with_capacity(limits.ref_capacity),
defs: Vec::from_iter(iter::repeat(Value::Nil).take(defs.len() as usize)),
fuel: limits.fuel,
memory: limits.memory,
}
}
@ -75,6 +79,7 @@ impl Vm {
refs: self.refs.len(),
defs: self.defs.len(),
fuel: self.fuel,
memory: self.memory,
}
}
@ -398,6 +403,14 @@ impl Vm {
pub fn create_exception(&self, message: &'static str) -> Exception {
Exception { message }
}
pub fn track_array<T>(&mut self, array: &[T]) -> Result<(), Exception> {
self.memory = self
.memory
.checked_sub(core::mem::size_of_val(array))
.ok_or_else(|| self.create_exception("out of heap memory"))?;
Ok(())
}
}
pub struct FnArgs {

View file

@ -44,6 +44,7 @@ fn eval(code: &str) -> Result<Value, Box<dyn Error>> {
call_stack_capacity: 256,
ref_capacity: 256,
fuel: 32768,
memory: 1024,
};
let mut vm = Vm::new(defs, &limits);
let chunk_id = system.add_chunk(chunk)?;