diff --git a/src/compiler.rs b/src/compiler.rs index aa617ec..557d23f 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -5,12 +5,12 @@ use crate::parser::{ Statement, VarArg, Variable, }; use crate::vm::{Code, Index, Machine, Offset, Prototype, Reference, Value}; +use deimos::map::Map; use std::cmp::PartialEq; use std::ops::Deref; use std::rc::Rc; -use deimos::map::{Equivalent, Hashed, Hashes, Map, TableEntry}; -pub(crate) struct Traversal<'a,S> { +pub(crate) struct Traversal<'a, S> { // A 'cursor' of where we are in assumed execution machine: &'a mut Machine, contexts: Vec, // Stack of function prototypes being compiled @@ -20,40 +20,10 @@ pub(crate) struct Context { // Everything known about a closure at a time scopes: Vec, vararg: Option>>, - constants: Map, // map some constant value to an index for not repeating constants + constants: Map, // map some constant value to an index for not repeating constants prototype: Prototype, } -#[derive(Clone, Debug)] -struct ConstantEntry(Value, Index); - -impl Equivalent for ConstantEntry { - fn matches(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl Equivalent for ConstantEntry { - fn matches(&self, other: &Value) -> bool { - self.0 == *other - } -} - -impl Hashes for ConstantEntry { - fn hashed(&self) -> Hashed { - self.0.hashed() - } -} - -impl TableEntry for ConstantEntry { - fn new_vacant() -> Self { - ConstantEntry(Value::Nil, 0) - } - fn is_vacant(&self) -> bool { - matches!(self.0, Value::Nil) - } -} - #[derive(Clone, Debug)] enum BlindJump { Break(usize), @@ -70,7 +40,7 @@ pub(crate) struct Scope { upvalue: bool, } -impl Traversal<'_,S> { +impl Traversal<'_, S> { fn compile(&mut self, it: &T) -> Result<(), LoadError> where T: Compile, @@ -147,14 +117,8 @@ impl Traversal<'_,S> { fn push_constant(&mut self, it: Value) -> Index { // todo: constants need pieces too!!! // don't use constants that already exist - if let Some(entry) = &mut self - .contexts - .last_mut() - .unwrap() - .constants - .get_table(it.clone()) - { - entry.1 + if let Some(entry) = self.contexts.last_mut().unwrap().constants.get(it.clone()) { + *entry } else { let index = { let constants = &mut self.contexts.last_mut().unwrap().prototype.constants; @@ -163,11 +127,7 @@ impl Traversal<'_,S> { } .try_into() .unwrap(); - self.contexts - .last_mut() - .unwrap() - .constants - .set_table(ConstantEntry(it, index)); + self.contexts.last_mut().unwrap().constants.set(it, index); index } } @@ -684,7 +644,11 @@ fn jump_from(here: usize, there: usize) -> Result { Ok((there as i64 - here as i64) as Offset) } -fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result<(), LoadError> { +fn resolve_break( + traversal: &mut Traversal, + begin: usize, + end: usize, +) -> Result<(), LoadError> { for jump in std::mem::replace(&mut traversal.last_scope().jumps, Vec::new()) { // ? match jump { @@ -1132,7 +1096,12 @@ impl Compile for Piece<&Block> { traversal.compile(&return_expression.inner_ref())?; } if !return_expressions.is_empty() { - traversal.push_code(return_expressions.first().unwrap().swap(Code::Return(return_index))); + traversal.push_code( + return_expressions + .first() + .unwrap() + .swap(Code::Return(return_index)), + ); } } for _ in 0..depth { diff --git a/src/vm.rs b/src/vm.rs index 366180b..f52ffc2 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -2,7 +2,7 @@ use crate::parser::{BinaryOp, Piece, UnaryOp, parse}; use deimos::gc::{Allocates, AnyId, FreeList, Id, MaybeId, Traverse}; -use deimos::map::{Equivalent, Hashed, Hashes, Map, TableEntry}; +use deimos::map::{Equivalent, Hashed, Hashes, Map, Set}; use std::fmt::{Debug, Display, Formatter}; use std::ops::Deref; use std::rc::Rc; @@ -77,9 +77,15 @@ impl std::fmt::Debug for Closure { } } -pub trait MarsAllocator: Allocates + Allocates + Allocates + Allocates {} +pub trait MarsAllocator: + Allocates
+ Allocates + Allocates + Allocates +{ +} -impl Traverse for Upvalue where C: MarsAllocator { +impl Traverse for Upvalue +where + C: MarsAllocator, +{ fn traverse(id: &Id, context: &mut C) { if let Upvalue::Heap(object) = context.freelist().get(id).clone() { object.traverse(context); @@ -98,17 +104,23 @@ pub enum Callable { } impl Callable { - fn traverse(&self, context: &mut C) where C: MarsAllocator { + fn traverse(&self, context: &mut C) + where + C: MarsAllocator, + { match self { Callable::Rust(_) => {} Callable::Mars(closure) => { - Closure::traverse(closure,context); + Closure::traverse(closure, context); } } } } -impl Traverse for Closure where C: MarsAllocator { +impl Traverse for Closure +where + C: MarsAllocator, +{ fn traverse(id: &Id, context: &mut C) { for i in 0..context.freelist().get(id).upvalues.len() { Upvalue::traverse(&context.freelist().get(id).upvalues[i].clone(), context); @@ -159,18 +171,23 @@ impl Display for RunError { } } - use crate::compiler::compile; -#[cfg(feature = "vector3")] -use glam::Vec3; use crate::core::load; use crate::table::Table; +#[cfg(feature = "vector3")] +use glam::Vec3; // Any value in the language const SHORT_STRING_LEN: usize = 40; #[derive(Clone, Debug)] pub(crate) struct CachedString(Rc, pub(crate) Hashed); -#[derive(Clone, Debug)] + +impl PartialEq for CachedString { + fn eq(&self, other: &Self) -> bool { + self.1 == other.1 && self.0 == other.0 + } +} +/*#[derive(Clone, Debug)] struct CachedStringEntry(Option); impl Hashes for CachedStringEntry { fn hashed(&self) -> Hashed { @@ -189,23 +206,11 @@ impl Equivalent for CachedStringEntry { None => false, } } -} +}*/ -impl TableEntry for CachedStringEntry { - fn new_vacant() -> Self { - CachedStringEntry(None) - } - fn is_vacant(&self) -> bool { - self.0.is_none() - } -} - -impl Equivalent<&str> for CachedStringEntry { +impl Equivalent<&str> for CachedString { fn matches(&self, string: &&str) -> bool { - match self.0 { - Some(ref entry) => entry.0.deref() == *string, - None => false, - } + self.0.as_ref().eq(*string) } } @@ -217,9 +222,9 @@ pub enum Value { Number(f64), Integer(u64), // 64 maybe we should use signed integers... CachedString(CachedString), - String(Rc,Hashed), + String(Rc, Hashed), Table(Id
), - Object(AnyId,AnyId), + Object(AnyId, AnyId), Function(Callable), #[cfg(feature = "vector3")] Vector(Vec3), @@ -234,15 +239,15 @@ impl Default for Value { impl Debug for Value { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - Value::Nil => write!(f,"nil"), - Value::Bool(boolean) => write!(f,"{}",boolean), - Value::Number(number) => write!(f,"{}",number), - Value::Integer(integer) => write!(f,"{}",integer), - Value::CachedString(string) => write!(f,"{}",string.0.deref()), + Value::Nil => write!(f, "nil"), + Value::Bool(boolean) => write!(f, "{}", boolean), + Value::Number(number) => write!(f, "{}", number), + Value::Integer(integer) => write!(f, "{}", integer), + Value::CachedString(string) => write!(f, "{}", string.0.deref()), Value::String(string, _hash) => write!(f, "{}", string.deref()), - Value::Table(it) => write!(f,"{:?}",it), - Value::Object(it,meta) => write!(f,"{:?}:{:?}",it,meta), - Value::Function(it) => write!(f,"{:?}",it) + Value::Table(it) => write!(f, "{:?}", it), + Value::Object(it, meta) => write!(f, "{:?}:{:?}", it, meta), + Value::Function(it) => write!(f, "{:?}", it), } } } @@ -262,10 +267,13 @@ impl Value { _ => panic!(), } } - pub(crate) fn traverse(&self, context: &mut C) where C: MarsAllocator { + pub(crate) fn traverse(&self, context: &mut C) + where + C: MarsAllocator, + { match self { - Value::Table(id) => {}, - Value::Object(id,meta_id) => {} + Value::Table(id) => {} + Value::Object(id, meta_id) => {} _ => {} } } @@ -324,8 +332,8 @@ impl PartialEq for Value { Value::Table(other) => other == this, _ => false, }, - Value::Object(this,..) => match other { - Value::Object(other,..) => other == this, + Value::Object(this, ..) => match other { + Value::Object(other, ..) => other == this, _ => false, }, Value::Function(this) => match other { @@ -347,24 +355,31 @@ pub struct Frame { macro_rules! read_only { () => { - |machine,id,needle| Err(RunError(format!("Field {} is read only",needle.pop()))) + |machine, id, needle| Err(RunError(format!("Field {} is read only", needle.pop()))) }; } pub struct MetaField { - set: fn(&mut Machine, id: AnyId, index: Value, value: Value, needle: Needle) -> Result, - get: fn(&mut Machine, id: AnyId, index: Value, needle: Needle) -> Result<(),RunError>, + set: fn( + &mut Machine, + id: AnyId, + index: Value, + value: Value, + needle: Needle, + ) -> Result, + get: fn(&mut Machine, id: AnyId, index: Value, needle: Needle) -> Result<(), RunError>, } pub struct Meta { - pub string: fn(&mut Machine, id: AnyId, needle: Needle) -> Result, - pub number: fn(&mut Machine, id: AnyId, needle: Needle) -> Result, - pub fields: Map>, - pub constants: Map, id: AnyId, needle: Needle) -> Result>, - pub traverse: fn(id: AnyId) -> Result<(),RunError>, + pub string: fn(&mut Machine, id: AnyId, needle: Needle) -> Result, + pub number: fn(&mut Machine, id: AnyId, needle: Needle) -> Result, + pub fields: Map>, + pub constants: + Map, id: AnyId, needle: Needle) -> Result>, + pub traverse: fn(id: AnyId) -> Result<(), RunError>, } -pub type ForeignFunction = fn(&mut Machine, needle: Needle) -> Result<(),RunError>; +pub type ForeignFunction = fn(&mut Machine, needle: Needle) -> Result<(), RunError>; // Machine for executing functions pub struct Machine { @@ -375,8 +390,8 @@ pub struct Machine { upvalues: FreeList, natives: FreeList>, metas: FreeList>, - cache: Map, // todo: better to use a generic version of Map - meta_strings: MetaStrings + cache: Set, + meta_strings: MetaStrings, } impl MarsAllocator for Machine {} @@ -391,7 +406,10 @@ impl Allocates> for Machine { } } -impl Traverse> for ForeignFunction where Machine: MarsAllocator { +impl Traverse> for ForeignFunction +where + Machine: MarsAllocator, +{ fn traverse(id: &Id>, _context: &mut Machine) {} fn collect(self) { @@ -504,7 +522,7 @@ pub(crate) type Stack = u16; // Stack index; pub(crate) type Count = u16; // Number of arguments pub(crate) type Offset = i16; // Jump to offset -const COMMENTS: [&'static str;1] = ["comment"]; +const COMMENTS: [&'static str; 1] = ["comment"]; // Bytecode for execution in a procedure #[derive(Debug, Clone, Copy)] @@ -523,12 +541,12 @@ pub(crate) enum Code { Discard(Stack), // consume: R[I...] (used with above to cull results or pad nil) VarArg(Count), // push: VA[1 -> count] OR VA[all] Jump(Offset), // PC += offset - Close(Stack), // Raise R[I...].upvalue from Upvalue::Stack to Upvalue::Heap, 'closing' the register, same effect as Discard for None upvalues - Skip, // consume: condition; if condition then PC++ (and naturally ++ again) - Return(Stack), // consume: R[I...] (move arguments back to start of frame and finish) - Binary(BinaryOp), // consume: fst, snd; push: result TODO: just use direct instructions? - Unary(UnaryOp), // consume: value; push: result - Closure(Index), // push: closure constructed from prototypes[I] + Close(Stack), // Raise R[I...].upvalue from Upvalue::Stack to Upvalue::Heap, 'closing' the register, same effect as Discard for None upvalues + Skip, // consume: condition; if condition then PC++ (and naturally ++ again) + Return(Stack), // consume: R[I...] (move arguments back to start of frame and finish) + Binary(BinaryOp), // consume: fst, snd; push: result TODO: just use direct instructions? + Unary(UnaryOp), // consume: value; push: result + Closure(Index), // push: closure constructed from prototypes[I] IteratorLoop(Offset), RangeBegin, RangeLoop(Offset), @@ -563,7 +581,7 @@ impl MetaStrings { } impl Machine { - fn init_meta_strings(&mut self) -> Result<(),RunError> { + fn init_meta_strings(&mut self) -> Result<(), RunError> { self.meta_strings = MetaStrings { number: self.new_string(MetaStrings::TO_NUMBER)?, string: self.new_string(MetaStrings::TO_STRING)?, @@ -578,14 +596,15 @@ impl Machine { pub fn new_number(&mut self, number: f64) -> Value { Value::Number(number) } - pub fn new_table(&mut self) -> Result { + pub fn new_table(&mut self) -> Result { Ok(Value::Table(self.tables.make(Table::new()).id)) } // todo: maybe use a trait to make S provide Id> through T, e.g. 'State' pub fn new_object(&mut self, id: Id, meta: Id>) -> Value { - Value::Object(id.any(),meta.any()) + Value::Object(id.any(), meta.any()) } - pub fn new_string(&mut self, string: &str) -> Result { // todo: why Result of RunError? + pub fn new_string(&mut self, string: &str) -> Result { + // todo: why Result of RunError? if string.len() < SHORT_STRING_LEN { let existing = self.cache.get_table(string); match existing { @@ -601,27 +620,44 @@ impl Machine { Ok(Value::String(Rc::from(string), string.hashed())) } } - fn meta_call(&mut self, dispatch: &mut Dispatch, value: Value, index: usize) -> Result<(),RunError> { + fn meta_call( + &mut self, + dispatch: &mut Dispatch, + value: Value, + index: usize, + ) -> Result<(), RunError> { match value { Value::Function(callable) => { - self.call(dispatch,callable,index)?; - }, - Value::Object(_,meta) => match self.tables.get(&meta.into()).get(self.meta_strings.call.clone())? { - Value::Function(callable) => self.call(dispatch,callable,index)?, - _ => return Err(RunError("Expected function for __call metatable entry".to_string())) + self.call(dispatch, callable, index)?; + } + Value::Object(_, meta) => match self + .tables + .get(&meta.into()) + .get(self.meta_strings.call.clone())? + { + Value::Function(callable) => self.call(dispatch, callable, index)?, + _ => { + return Err(RunError( + "Expected function for __call metatable entry".to_string(), + )); + } }, Value::Table(table) => { let mut table = self.tables.get(&table); if let Some(meta) = table.meta.exists() { match self.tables.get(&meta).get(self.meta_strings.call.clone())? { - Value::Function(callable) => self.call(dispatch,callable,index)?, - _ => return Err(RunError("Expected function for __call metatable entry".to_string())) + Value::Function(callable) => self.call(dispatch, callable, index)?, + _ => { + return Err(RunError( + "Expected function for __call metatable entry".to_string(), + )); + } } } else { - return Err(RunError("Expected metatable to call table".to_string())) + return Err(RunError("Expected metatable to call table".to_string())); }; } - _ => return Err(RunError("Cannot call primitive".to_string())) + _ => return Err(RunError("Cannot call primitive".to_string())), } Ok(()) } @@ -630,27 +666,35 @@ impl Machine { match value { integer @ Value::Integer(_) => Ok(integer.clone()), number @ Value::Number(_) => Ok(number.clone()), - Value::Object(_,meta) => { - match self.tables.get(&meta.into()).get(self.meta_strings.number.clone())? { + Value::Object(_, meta) => { + match self + .tables + .get(&meta.into()) + .get(self.meta_strings.number.clone())? + { Value::Function(callable) => { let mut needle = dispatch.needle(); needle.push(clone); - self.call(needle.dispatch,callable,1)?; + self.call(needle.dispatch, callable, 1)?; Ok(needle.pop().unwrap_or(Value::Nil)) - }, + } it => Ok(it), } - }, + } Value::Table(table) => { let table = self.tables.get(&table); if let Some(meta) = table.meta.exists() { - match self.tables.get(&meta).get(self.meta_strings.number.clone())? { + match self + .tables + .get(&meta) + .get(self.meta_strings.number.clone())? + { Value::Function(callable) => { let mut needle = dispatch.needle(); needle.push(clone); - self.call(needle.dispatch,callable,1)?; + self.call(needle.dispatch, callable, 1)?; Ok(needle.pop().unwrap_or(Value::Nil)) - }, + } it => Ok(it), } } else { @@ -660,7 +704,11 @@ impl Machine { _ => Ok(Value::Nil), } } - pub(crate) fn meta_to_string(&mut self, dispatch: &mut Dispatch, value: Value) -> Result { + pub(crate) fn meta_to_string( + &mut self, + dispatch: &mut Dispatch, + value: Value, + ) -> Result { let cloned = value.clone(); Ok(match value { Value::Nil => self.new_string("nil".to_string().as_str())?, @@ -679,21 +727,31 @@ impl Machine { self.new_string("{...}".to_string().as_str())? } } - Value::Object(_,meta) => { - match self.tables.get(&meta.into()).get(self.meta_strings.number.clone())? { + Value::Object(_, meta) => { + match self + .tables + .get(&meta.into()) + .get(self.meta_strings.number.clone())? + { Value::Function(callable) => { let mut needle = dispatch.needle(); needle.push(cloned); - self.call(needle.dispatch,callable,1)?; + self.call(needle.dispatch, callable, 1)?; needle.pop().unwrap_or(Value::Nil) - }, + } it => it, } - }, + } Value::Function(callable) => self.new_string(format!("{:?}", callable).as_str())?, }) } - fn meta_set(&mut self, dispatch: &mut Dispatch, subject: Value, index: Value, value: Value) -> Result<(), RunError> { + fn meta_set( + &mut self, + dispatch: &mut Dispatch, + subject: Value, + index: Value, + value: Value, + ) -> Result<(), RunError> { match subject { Value::Nil => Err(RunError("Cannot set to nil".to_string())), Value::Bool(bool) => Err(RunError("Cannot set to boolean".to_string())), @@ -712,11 +770,18 @@ impl Machine { table.set(index, value) } } - Value::Object(id,meta) => (self.metas.get(&meta.into()).set)(self, id, index, value, dispatch.needle()), + Value::Object(id, meta) => { + (self.metas.get(&meta.into()).set)(self, id, index, value, dispatch.needle()) + } Value::Function(_callable) => Err(RunError("Function index unimplemented".to_string())), } } - fn meta_get(&mut self, dispatch: &mut Dispatch, mut subject: Value, index: Value) -> Result { + fn meta_get( + &mut self, + dispatch: &mut Dispatch, + mut subject: Value, + index: Value, + ) -> Result { match subject { Value::Nil => Err(RunError("Cannot set to nil".to_string())), Value::Bool(bool) => Err(RunError("Cannot index boolean".to_string())), @@ -735,46 +800,51 @@ impl Machine { table.get(index.clone()) } } - Value::Object(mut object,..) => Err(RunError("Object index unimplemented".to_string())), + Value::Object(mut object, ..) => { + Err(RunError("Object index unimplemented".to_string())) + } Value::Function(_callable) => Err(RunError("Function index unimplemented".to_string())), } } // todo: object-table equality - fn meta_equal(&mut self, lhs: &mut Value, rhs: &mut Value) -> Result { // with respect to metamethods + fn meta_equal(&mut self, lhs: &mut Value, rhs: &mut Value) -> Result { + // with respect to metamethods Ok(match lhs { Value::Nil => match rhs { Value::Nil => true, _ => false, - } + }, Value::Bool(this) => match rhs { Value::Bool(other) => this == other, _ => false, - } + }, Value::Number(this) => match rhs { Value::Number(other) => this == other, Value::Integer(other) => *this == *other as f64, _ => false, - } + }, Value::Integer(this) => match rhs { Value::Number(other) => *this as f64 == *other, // are these conversions ok? Value::Integer(other) => this == other, _ => false, - } + }, Value::String(string, hash) => match rhs { - Value::CachedString(other) => + Value::CachedString(other) => { if *hash == other.1 { other.0.deref() == (*string).deref() } else { false - }, - Value::String(other_string, other_hash) => + } + } + Value::String(other_string, other_hash) => { if hash == other_hash { string == other_string } else { false - }, - _ => false - } + } + } + _ => false, + }, Value::CachedString(string) => match rhs { Value::CachedString(other) => other.0 == string.0, // pointer equality Value::String(other_string, other_hash) => { @@ -784,20 +854,20 @@ impl Machine { false } } - _ => false - } + _ => false, + }, Value::Table(this) => match rhs { Value::Table(other) => other == this, - _ => false - } - Value::Object(this,meta) => match rhs { - Value::Object(other,meta) => other == this, - _ => false - } + _ => false, + }, + Value::Object(this, meta) => match rhs { + Value::Object(other, meta) => other == this, + _ => false, + }, Value::Function(this) => match rhs { Value::Function(other) => other == this, - _ => false - } + _ => false, + }, }) } pub(crate) fn load(&mut self, source: &str) -> Result, MarsError> { @@ -815,12 +885,20 @@ impl Machine { let global = self.global.clone(); let upvalues = vec![self.freelist().make(Upvalue::Heap(Value::Table(global))).id]; - Ok(self.freelist().make(Closure { - prototype: Rc::new(prototype), - upvalues, - }).id) + Ok(self + .freelist() + .make(Closure { + prototype: Rc::new(prototype), + upvalues, + }) + .id) } - fn call(&mut self, dispatch: &mut Dispatch, callable: Callable, n_args: usize) -> Result<(),RunError> { + fn call( + &mut self, + dispatch: &mut Dispatch, + callable: Callable, + n_args: usize, + ) -> Result<(), RunError> { self.dispatch_call(dispatch, callable, dispatch.stack.len() - n_args - 1)?; self.dispatch(dispatch)?; Ok(()) @@ -828,19 +906,19 @@ impl Machine { // Call a callable in a dispatch. // For Rust functions, this calls it immediately. // For Mars functions it will set up the dispatch to execute this function, so there must be a dispatch in progress already. - fn dispatch_call(&mut self, dispatch: &mut Dispatch, callable: Callable, index: usize) -> Result<(),RunError> { + fn dispatch_call( + &mut self, + dispatch: &mut Dispatch, + callable: Callable, + index: usize, + ) -> Result<(), RunError> { match callable { Callable::Rust(function) => { - self.natives.get(&function.into())(self, Needle { - dispatch, - index, - })?; + self.natives.get(&function.into())(self, Needle { dispatch, index })?; } Callable::Mars(closure) => { let nargs = self.freelist().get(&closure).prototype.args; - dispatch - .stack - .resize(index + nargs as usize, Register::NIL); + dispatch.stack.resize(index + nargs as usize, Register::NIL); dispatch.frames.push(Frame { // where to find the function, what about missing arguments?, vararg: index, // start of frame points to the register after the function @@ -862,11 +940,17 @@ impl Machine { } }; loop { - let frame = dispatch.frames.last_mut().ok_or(RunError("No frames in needle!".to_string()))?.clone(); + let frame = dispatch + .frames + .last_mut() + .ok_or(RunError("No frames in needle!".to_string()))? + .clone(); if dispatch.stack.len() > Stack::MAX as usize { return Err(RunError("Soft stack limit of 65536 reached".to_string())); } - let code = self.freelist().get(&frame.closure) + let code = self + .freelist() + .get(&frame.closure) .prototype .code .get(frame.counter) @@ -891,7 +975,9 @@ impl Machine { Code::Message(number) => { eprintln!("{}", COMMENTS[number as usize]) } - Code::TableNew => dispatch.push(Value::Table(self.freelist().make(Table::new()).id)), + Code::TableNew => { + dispatch.push(Value::Table(self.freelist().make(Table::new()).id)) + } Code::TableSet => { let table = dispatch.pop(); let index = dispatch.pop(); @@ -919,16 +1005,24 @@ impl Machine { } } Code::UpvalueGet(index) => { - match self.upvalues.get(&self.closures.get(&frame.closure).upvalues[index as usize]) + match self + .upvalues + .get(&self.closures.get(&frame.closure).upvalues[index as usize]) { - Upvalue::Stack(stack) => dispatch.push(dispatch.stack[*stack].value.clone()), + Upvalue::Stack(stack) => { + dispatch.push(dispatch.stack[*stack].value.clone()) + } Upvalue::Heap(object) => dispatch.push(object.clone()), } } Code::UpvalueSet(index) => { - match self.upvalues.get(&self.closures.get(&frame.closure).upvalues[index as usize]) + match self + .upvalues + .get(&self.closures.get(&frame.closure).upvalues[index as usize]) { - Upvalue::Stack(register) => dispatch.stack[*register].value = dispatch.pop(), + Upvalue::Stack(register) => { + dispatch.stack[*register].value = dispatch.pop() + } Upvalue::Heap(it) => *it = dispatch.pop(), } } @@ -940,19 +1034,16 @@ impl Machine { } Code::Constant(constant) => { dispatch.push( - self.closures.get(&frame.closure).prototype.constants[constant as usize].clone(), + self.closures.get(&frame.closure).prototype.constants[constant as usize] + .clone(), ); } - Code::Call(index) => { - match dispatch.pop() { - Value::Function(callable) => { - self.dispatch_call(dispatch, callable, frame.offset + index as usize)?; - }, - _ => { - return Err(RunError("Could not call value".to_string())) - } + Code::Call(index) => match dispatch.pop() { + Value::Function(callable) => { + self.dispatch_call(dispatch, callable, frame.offset + index as usize)?; } - } + _ => return Err(RunError("Could not call value".to_string())), + }, Code::Discard(index) => { dispatch .stack @@ -990,9 +1081,9 @@ impl Machine { } dispatch.frames.pop(); if dispatch.frames.last_mut().is_some() { - continue + continue; } else { - break + break; } } Code::Binary(op) => { @@ -1007,8 +1098,10 @@ impl Machine { for i in frame.offset + index as usize..dispatch.stack.len() { if let Some(upvalue) = dispatch.stack[i].upvalue.exists() { match self.upvalues.get(&upvalue) { - it@Upvalue::Stack(_) => *it = Upvalue::Heap(dispatch.stack[i].value.clone()), - _ => panic!() + it @ Upvalue::Stack(_) => { + *it = Upvalue::Heap(dispatch.stack[i].value.clone()) + } + _ => panic!(), } } } @@ -1016,15 +1109,21 @@ impl Machine { .stack .resize(frame.offset + index as usize, Register::NIL); // As with Code::Discard } - Code::Closure(index) => { // Make a new closure from a prototype inside this closure and push to the stack - let prototype = - self.freelist().get(&frame.closure).prototype.prototypes[index as usize].clone(); // Get the prototype of this closure that the instruction is referring to + Code::Closure(index) => { + // Make a new closure from a prototype inside this closure and push to the stack + let prototype = self.freelist().get(&frame.closure).prototype.prototypes + [index as usize] + .clone(); // Get the prototype of this closure that the instruction is referring to let mut upvalues = Vec::new(); // List of upvalues for this new closure - for reference in prototype.upvalues.iter() { // For every reference in it - upvalues.push(match reference { // Push it based on what the reference was - Reference::Closing(index) => { // It's actually alive inside this function already + for reference in prototype.upvalues.iter() { + // For every reference in it + upvalues.push(match reference { + // Push it based on what the reference was + Reference::Closing(index) => { + // It's actually alive inside this function already let index = frame.offset + *index as usize; // Get its actual index - match &mut dispatch.stack[index].upvalue.exists() { // Does the upvalue in that register exist? + match &mut dispatch.stack[index].upvalue.exists() { + // Does the upvalue in that register exist? Some(upvalue) => upvalue.clone(), _ => { let upvalue = self.freelist().make(Upvalue::Stack(index)); @@ -1034,25 +1133,31 @@ impl Machine { } } Reference::Upvalue(index) => { - self.freelist().get(&frame.closure).upvalues[*index as usize].clone() + self.freelist().get(&frame.closure).upvalues[*index as usize] + .clone() } }); } - dispatch.push(Value::Function(Callable::Mars(self.freelist().make( - Closure { - prototype, - upvalues, - }, - ).id))); + dispatch.push(Value::Function(Callable::Mars( + self.freelist() + .make(Closure { + prototype, + upvalues, + }) + .id, + ))); } Code::RangeBegin => { let len = dispatch.stack.len(); let init = len - 3; let limit = len - 2; let step = len - 1; - let init_value = self.meta_to_number(dispatch, dispatch.stack[init].value.clone())?; - let limit_value = self.meta_to_number(dispatch, dispatch.stack[limit].value.clone())?; - let step_value = self.meta_to_number(dispatch, dispatch.stack[step].value.clone())?; + let init_value = + self.meta_to_number(dispatch, dispatch.stack[init].value.clone())?; + let limit_value = + self.meta_to_number(dispatch, dispatch.stack[limit].value.clone())?; + let step_value = + self.meta_to_number(dispatch, dispatch.stack[step].value.clone())?; if matches!(init_value, Value::Integer(_)) && matches!(limit_value, Value::Integer(_)) && matches!(step_value, Value::Integer(_)) @@ -1133,7 +1238,7 @@ impl Machine { let len = dispatch.stack.len(); let callable = match dispatch.stack[len - 2].value.clone() { Value::Function(callable) => callable, - _ => return Err(RunError("Could not call value".to_string())) + _ => return Err(RunError("Could not call value".to_string())), }; let state = dispatch.stack[len - 1].value.clone(); let var = dispatch.stack[len].value.clone(); @@ -1143,7 +1248,9 @@ impl Machine { self.dispatch_call( dispatch, callable, - frame.offset + Index::try_from(dispatch.stack.len() - frame_offset - 2).unwrap() as usize, + frame.offset + + Index::try_from(dispatch.stack.len() - frame_offset - 2).unwrap() + as usize, )?; if matches!( dispatch.stack.get(len + 1).unwrap_or(&Register::NIL).value, @@ -1171,18 +1278,29 @@ impl Machine { } pub fn set_global(&mut self, name: &str, value: Value) -> Result<(), RunError> { let name = self.new_string(name)?; - self.tables.get(&self.global).set(name,value) + self.tables.get(&self.global).set(name, value) } - pub fn set_global_object(&mut self, name: &str, object: Id, meta: Id>) -> Result<(), RunError> { - let value = self.new_object(object,meta); - self.set_global(name,value) + pub fn set_global_object( + &mut self, + name: &str, + object: Id, + meta: Id>, + ) -> Result<(), RunError> { + let value = self.new_object(object, meta); + self.set_global(name, value) } - pub fn set_global_function(&mut self, name: &str, function: ForeignFunction) -> Result<(),RunError> { + pub fn set_global_function( + &mut self, + name: &str, + function: ForeignFunction, + ) -> Result<(), RunError> { let fun = self.new_foreign(function)?; - self.set_global(name,fun) + self.set_global(name, fun) } - pub fn new_foreign(&mut self, function: ForeignFunction) -> Result { - Ok(Value::Function(Callable::Rust(self.natives.make(function).id.any()))) + pub fn new_foreign(&mut self, function: ForeignFunction) -> Result { + Ok(Value::Function(Callable::Rust( + self.natives.make(function).id.any(), + ))) } pub fn new(state: impl FnOnce(&mut FreeList>) -> S) -> Result, RunError> { let mut tables = FreeList::
::new(); @@ -1197,7 +1315,7 @@ impl Machine { upvalues: FreeList::new(), natives: FreeList::new(), meta_strings: MetaStrings::new(), - cache: Map::new(), + cache: Set::new(), }; machine.init_meta_strings()?; load(&mut machine)?;