diff --git a/src/lib.rs b/src/lib.rs index 1a38f56..97ac9f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,22 +13,40 @@ mod tasks; #[cfg(test)] mod tests { use crate::vm::Machine; - use deimos::gc::Allocates; + use crate::{RunError, Needle}; - #[test] - fn simple() { - let mut machine = match Machine::new(|_| ()) { - Err(error) => panic!("{}", error), - Ok(machine) => machine, - }; - let closure = match machine.load(include_str!("tests/script.lua")) { - Err(error) => panic!("{}", error), - Ok(closure) => closure, - }; - println!("{:?}", machine.freelist().get(&closure).prototype); - match machine.enter(closure) { - Err(error) => panic!("{}", error), - _ => {} + macro_rules! unwrap { + ($e:expr) => { + match $e { + Err(error) => panic!("{}", error), + Ok(result) => result, + } }; } + + fn output(machine: &mut Machine, mut needle: Needle) -> Result<(),RunError> { + let arg = needle.pop().ok_or(RunError::new("Expected string, got nil."))?; + let str = arg.try_string().ok_or(RunError::new("Expected string."))?; + machine.state.push_str(str.as_str()); + println!("{}",str.as_str()); + Ok(()) + } + + fn output_test(file: &str) -> Result,Box> { + let mut machine = Machine::new(|_| String::new())?; + machine.set_global_function("output",output)?; + let closure = machine.load(file)?; + machine.enter(closure)?; + Ok(machine) + } + + #[test] + fn hello() { + assert_eq!(unwrap!(output_test(include_str!("tests/hello.lua"))).state,"hello") + } + + #[test] + fn many() { + println!("{}",unwrap!(output_test(include_str!("tests/script.lua"))).state) + } } diff --git a/src/table.rs b/src/table.rs index 71cc1cc..9359720 100644 --- a/src/table.rs +++ b/src/table.rs @@ -85,9 +85,6 @@ impl Traverse for Table where C: MarsAllocator, { - fn collect(self) { - todo!() - } fn traverse(id: &Id, context: &mut C) { for i in 0..context.freelist().get(id).table.map.len() { let entry = context.freelist().get(id).table.map[i].entry.clone(); diff --git a/src/tests/hello.lua b/src/tests/hello.lua new file mode 100644 index 0000000..4835649 --- /dev/null +++ b/src/tests/hello.lua @@ -0,0 +1 @@ +output "hello" \ No newline at end of file diff --git a/src/tests/script.lua b/src/tests/script.lua index 13baf8a..8535bbd 100644 --- a/src/tests/script.lua +++ b/src/tests/script.lua @@ -2,4 +2,4 @@ local tab = {} for i = 1, 1000000 do tab[i] = true end -debug(tab) \ No newline at end of file +output(#tab) \ No newline at end of file diff --git a/src/vm.rs b/src/vm.rs index d50323a..fe3cbc9 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -91,10 +91,6 @@ where object.traverse(context); } } - - fn collect(self) { - todo!() - } } #[derive(Clone)] @@ -126,10 +122,6 @@ where Upvalue::traverse(&context.freelist().get(id).upvalues[i].clone(), context); } } - - fn collect(self) { - todo!() - } } impl PartialEq for Callable { @@ -236,8 +228,12 @@ impl TableEntry for CachedStringEntry { } impl Equivalent<&str> for CachedStringEntry { - fn matches(&self, string: &&str) -> bool { - self.0.as_ref().unwrap().0.as_ref().eq(*string) + fn matches(&self, other: &&str) -> bool { + if let Some(ref string) = self.0 { + string.as_str() == *other + } else { + false + } } } @@ -286,7 +282,7 @@ impl Value { _ => true, } } - pub(crate) fn unwrap_str(&mut self) -> Rc { + pub fn unwrap_str(&mut self) -> Rc { match self { Value::CachedString(hashed) => hashed.0.clone(), Value::String(hashed) => hashed.0.clone(), @@ -392,64 +388,12 @@ impl Equivalent for MapEntry<&str,V> { // For the constant maps } } -#[macro_export] -macro_rules! getter { - (@$state:ident,$index:literal=>$f:expr,$($x:literal=>$y:expr),*) => { - let temp: MetaOutFn<$state> = $f; - $crate::getter!(@$($x=>$y)*) - }; - (@$state:ident,$index:literal=>$f:expr) => { - let temp: MetaOutFn<$state> = $f; - }; - (@) => { - - }; - ($ident:tt,$state:ident,{$($map:tt)*}) => { - |machine,id,index,needle| { - use $crate::deimos::map::Entry; - use $crate::deimos::map::MapEntry; - $crate::getter!(@$state,$($map)*); - static MAP: &[ - $crate::deimos::map::Entry< - $crate::deimos::map::MapEntry<&'static str,$crate::MetaOutFn<$state>> - >] = &$crate::deimos::macros::map!{$($map)*}; - if let Some(string) = index.clone().try_string() { - if let Some(func) = $crate::deimos::map::get(MAP,string) { - (func.0.unwrap().1)(machine,id,needle) - } else { - Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident)))) - } - } else { - Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident)))) - } - } - } -} - -#[macro_export] -macro_rules! setter { - ($ident:tt,$state:tt,$($map:tt)*) => { - |machine,id,index,value,needle| { - static MAP: &[Entry>>] = &$($map)*; - if let Some(string) = index.clone().try_string() { - if let Some(func) = $crate::deimos::map::get(MAP,string) { - (func.0.unwrap().1)(machine,id,value,needle) - } else { - Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident)))) - } - } else { - Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident)))) - } - } - } -} - +// Metas are a faster alternative to metatables for foreign objects pub type MetaGetFn = fn(&mut Machine, AnyId, Value, Needle) -> Result; pub type MetaSetFn = fn(&mut Machine, AnyId, Value, Value, Needle) -> Result<(), RunError>; pub type MetaInFn = fn(&mut Machine, AnyId, Value, Needle) -> Result<(), RunError>; pub type MetaOutFn = fn(&mut Machine, AnyId, Needle) -> Result; pub type MetaTraverseFn = fn(&mut Machine, AnyId) -> Result<(), RunError>; - pub struct Meta { pub string: MetaOutFn, pub number: MetaOutFn, @@ -457,7 +401,6 @@ pub struct Meta { pub set: MetaSetFn, pub traverse: MetaTraverseFn, } - impl Default for Meta { fn default() -> Self { Meta { @@ -488,10 +431,6 @@ pub struct Machine { impl MarsAllocator for Machine {} impl Allocates> for Machine { - fn collect() { - todo!() - } - fn freelist(&mut self) -> &mut FreeList> { &mut self.natives } @@ -502,35 +441,19 @@ where Machine: MarsAllocator, { fn traverse(id: &Id>, _context: &mut Machine) {} - - fn collect(self) { - todo!() - } } impl Allocates
for Machine { - fn collect() { - todo!() - } - fn freelist(&mut self) -> &mut FreeList
{ &mut self.tables } } impl Allocates for Machine { - fn collect() { - todo!() - } - fn freelist(&mut self) -> &mut FreeList { &mut self.closures } } impl Allocates for Machine { - fn collect() { - todo!() - } - fn freelist(&mut self) -> &mut FreeList { &mut self.upvalues } @@ -1351,6 +1274,11 @@ impl Machine { #[derive(Debug, Clone)] pub struct MarsError(String); + +impl std::error::Error for MarsError { + +} + impl Display for MarsError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0)