Implement small tests. Failing on parse.

This commit is contained in:
Christian Lincoln 2026-10-13 02:15:16 +01:00
parent c818e462b8
commit 9aaabb4c07
7 changed files with 49 additions and 143 deletions

38
Cargo.lock generated
View file

@ -21,9 +21,6 @@ name = "macros"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"map", "map",
"proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
@ -37,38 +34,3 @@ dependencies = [
"deimos", "deimos",
"glam", "glam",
] ]
[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"

2
deimos

@ -1 +1 @@
Subproject commit f3922ff84da34746f845f5b817573944f8991fa4 Subproject commit 385a08b094e43ff12b60a41a90ab99b4b18cea0c

View file

@ -13,22 +13,40 @@ mod tasks;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::vm::Machine; use crate::vm::Machine;
use deimos::gc::Allocates; use crate::{RunError, Needle};
#[test] macro_rules! unwrap {
fn simple() { ($e:expr) => {
let mut machine = match Machine::new(|_| ()) { match $e {
Err(error) => panic!("{}", error), Err(error) => panic!("{}", error),
Ok(machine) => machine, Ok(result) => result,
}; }
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),
_ => {}
}; };
} }
fn output(machine: &mut Machine<String>, 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<Machine<String>,Box<dyn std::error::Error>> {
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)
}
} }

View file

@ -85,9 +85,6 @@ impl<C> Traverse<C> for Table
where where
C: MarsAllocator, C: MarsAllocator,
{ {
fn collect(self) {
todo!()
}
fn traverse(id: &Id<Table>, context: &mut C) { fn traverse(id: &Id<Table>, context: &mut C) {
for i in 0..context.freelist().get(id).table.map.len() { for i in 0..context.freelist().get(id).table.map.len() {
let entry = context.freelist().get(id).table.map[i].entry.clone(); let entry = context.freelist().get(id).table.map[i].entry.clone();

1
src/tests/hello.lua Normal file
View file

@ -0,0 +1 @@
output "hello"

View file

@ -2,4 +2,4 @@ local tab = {}
for i = 1, 1000000 do for i = 1, 1000000 do
tab[i] = true tab[i] = true
end end
debug(tab) output(#tab)

View file

@ -91,10 +91,6 @@ where
object.traverse(context); object.traverse(context);
} }
} }
fn collect(self) {
todo!()
}
} }
#[derive(Clone)] #[derive(Clone)]
@ -126,10 +122,6 @@ where
Upvalue::traverse(&context.freelist().get(id).upvalues[i].clone(), context); Upvalue::traverse(&context.freelist().get(id).upvalues[i].clone(), context);
} }
} }
fn collect(self) {
todo!()
}
} }
impl PartialEq for Callable { impl PartialEq for Callable {
@ -236,8 +228,12 @@ impl TableEntry for CachedStringEntry {
} }
impl Equivalent<&str> for CachedStringEntry { impl Equivalent<&str> for CachedStringEntry {
fn matches(&self, string: &&str) -> bool { fn matches(&self, other: &&str) -> bool {
self.0.as_ref().unwrap().0.as_ref().eq(*string) if let Some(ref string) = self.0 {
string.as_str() == *other
} else {
false
}
} }
} }
@ -286,7 +282,7 @@ impl Value {
_ => true, _ => true,
} }
} }
pub(crate) fn unwrap_str(&mut self) -> Rc<str> { pub fn unwrap_str(&mut self) -> Rc<str> {
match self { match self {
Value::CachedString(hashed) => hashed.0.clone(), Value::CachedString(hashed) => hashed.0.clone(),
Value::String(hashed) => hashed.0.clone(), Value::String(hashed) => hashed.0.clone(),
@ -392,64 +388,12 @@ impl<V> Equivalent<HashedString> for MapEntry<&str,V> { // For the constant maps
} }
} }
#[macro_export] // Metas are a faster alternative to metatables for foreign objects
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<MapEntry<&'static str,$crate::MetaInFn<$state>>>] = &$($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))))
}
}
}
}
pub type MetaGetFn<S> = fn(&mut Machine<S>, AnyId, Value, Needle) -> Result<Value, RunError>; pub type MetaGetFn<S> = fn(&mut Machine<S>, AnyId, Value, Needle) -> Result<Value, RunError>;
pub type MetaSetFn<S> = fn(&mut Machine<S>, AnyId, Value, Value, Needle) -> Result<(), RunError>; pub type MetaSetFn<S> = fn(&mut Machine<S>, AnyId, Value, Value, Needle) -> Result<(), RunError>;
pub type MetaInFn<S> = fn(&mut Machine<S>, AnyId, Value, Needle) -> Result<(), RunError>; pub type MetaInFn<S> = fn(&mut Machine<S>, AnyId, Value, Needle) -> Result<(), RunError>;
pub type MetaOutFn<S> = fn(&mut Machine<S>, AnyId, Needle) -> Result<Value, RunError>; pub type MetaOutFn<S> = fn(&mut Machine<S>, AnyId, Needle) -> Result<Value, RunError>;
pub type MetaTraverseFn<S> = fn(&mut Machine<S>, AnyId) -> Result<(), RunError>; pub type MetaTraverseFn<S> = fn(&mut Machine<S>, AnyId) -> Result<(), RunError>;
pub struct Meta<S> { pub struct Meta<S> {
pub string: MetaOutFn<S>, pub string: MetaOutFn<S>,
pub number: MetaOutFn<S>, pub number: MetaOutFn<S>,
@ -457,7 +401,6 @@ pub struct Meta<S> {
pub set: MetaSetFn<S>, pub set: MetaSetFn<S>,
pub traverse: MetaTraverseFn<S>, pub traverse: MetaTraverseFn<S>,
} }
impl<S> Default for Meta<S> { impl<S> Default for Meta<S> {
fn default() -> Self { fn default() -> Self {
Meta { Meta {
@ -488,10 +431,6 @@ pub struct Machine<S> {
impl<S> MarsAllocator for Machine<S> {} impl<S> MarsAllocator for Machine<S> {}
impl<S> Allocates<ForeignFunction<S>> for Machine<S> { impl<S> Allocates<ForeignFunction<S>> for Machine<S> {
fn collect() {
todo!()
}
fn freelist(&mut self) -> &mut FreeList<ForeignFunction<S>> { fn freelist(&mut self) -> &mut FreeList<ForeignFunction<S>> {
&mut self.natives &mut self.natives
} }
@ -502,35 +441,19 @@ where
Machine<S>: MarsAllocator, Machine<S>: MarsAllocator,
{ {
fn traverse(id: &Id<ForeignFunction<S>>, _context: &mut Machine<S>) {} fn traverse(id: &Id<ForeignFunction<S>>, _context: &mut Machine<S>) {}
fn collect(self) {
todo!()
}
} }
impl<S> Allocates<Table> for Machine<S> { impl<S> Allocates<Table> for Machine<S> {
fn collect() {
todo!()
}
fn freelist(&mut self) -> &mut FreeList<Table> { fn freelist(&mut self) -> &mut FreeList<Table> {
&mut self.tables &mut self.tables
} }
} }
impl<S> Allocates<Closure> for Machine<S> { impl<S> Allocates<Closure> for Machine<S> {
fn collect() {
todo!()
}
fn freelist(&mut self) -> &mut FreeList<Closure> { fn freelist(&mut self) -> &mut FreeList<Closure> {
&mut self.closures &mut self.closures
} }
} }
impl<S> Allocates<Upvalue> for Machine<S> { impl<S> Allocates<Upvalue> for Machine<S> {
fn collect() {
todo!()
}
fn freelist(&mut self) -> &mut FreeList<Upvalue> { fn freelist(&mut self) -> &mut FreeList<Upvalue> {
&mut self.upvalues &mut self.upvalues
} }
@ -1351,6 +1274,11 @@ impl<S> Machine<S> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MarsError(String); pub struct MarsError(String);
impl std::error::Error for MarsError {
}
impl Display for MarsError { impl Display for MarsError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0) write!(f, "{}", self.0)