diff --git a/src/lib.rs b/src/lib.rs index 195bd8e..eef63a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1321,7 +1321,7 @@ impl Traversal<'_> { self.consume_scope(2); // Value, Table } Code::Return(index) | Code::Call(index) => { - let diff = self.last_scope().index - index; + let diff = self.index().unwrap() - index; self.consume_scope(diff + 1); //assert_eq!(self.last_scope().index, index); /* So note that Code::Call here doesn't do any temp_scope() magic, this is an edge-case for @@ -1389,11 +1389,9 @@ impl Traversal<'_> { Ok(string) => Ok(self.push_literal(string, piece)), } } - fn new_scope(&mut self) { - let context = &mut self.contexts.last_mut().unwrap(); - let scopes = &mut context.scopes; - let index = scopes.last().unwrap().index; - scopes.push(Scope { + fn new_scope(&mut self) { // Make some new scope + let index = self.last_scope().index; + self.contexts.last_mut().unwrap().scopes.push(Scope { index, jumps: vec![], labels: vec![], @@ -1401,15 +1399,23 @@ impl Traversal<'_> { upvalue: false, }); } - fn temp_scope(&mut self) -> Index { + fn temp_scope(&mut self) -> Index { // Make a new scope with index++ self.new_scope(); - let index = self.last_scope().index + 1; - self.last_scope().index = index; - index + if self.last_context().scopes.len() > 2 { // For the dummy scope + self.last_scope().index += 1; + } + self.last_scope().index } fn last_scope(&mut self) -> &mut Scope { self.last_context().scopes.last_mut().unwrap() } + fn index(&mut self) -> Option { + if self.last_context().scopes.len() == 1 { + None + } else { + Some(self.last_context().scopes.last_mut().unwrap().index) + } + } fn code_length(&mut self) -> usize { self.last_context().prototype.code.len() } @@ -1436,7 +1442,10 @@ impl Traversal<'_> { self.contexts.last_mut().unwrap() } fn close_context(&mut self) -> Result { - let context = self.contexts.pop().unwrap(); + let mut context = self.contexts.pop().unwrap(); + for jump in context.scopes.pop().unwrap().jumps { // Get back the dummy one and error any jumps + return Err(LoadError::from(format!("{:?}",jump).as_str(), &Piece::<()>::null())) // todo: we need Vec or some append in LoadError and also BlindJumps need pieces! + } Ok(context.prototype) } } @@ -1483,7 +1492,7 @@ fn compile_function( .map(|it| it.swap(it.clone().it.0.map(|string| string.0.clone()))), scopes: argument_scopes, prototype: Prototype { - args: this.it.0.len() as Index, + args: this.it.0.len().try_into().unwrap(), vararg: this.it.1.is_some(), prototypes: vec![], constants: vec![], @@ -1496,7 +1505,7 @@ fn compile_function( traversal.compile(&this.it.2.inner_ref())?; // compile the block let prototype = traversal.close_context()?; let prototypes = &mut traversal.last_context().prototype.prototypes; // add this to the upper function's prototypes list - let index = prototypes.len() as Index; + let index = prototypes.len().try_into().unwrap(); prototypes.push(Rc::new(prototype)); traversal.push_code(this.swap(Code::Closure(index))); // reference this closure Ok(()) @@ -1567,12 +1576,12 @@ fn compile_identifier( .iter() .position(|it| *it == reference) { - Some(index) => Reference::Upvalue(index as Index), + Some(index) => Reference::Upvalue(index.try_into().unwrap()), None => { // we don't even have a reference to this in our upvalues so add it let length = traversal.contexts[k].prototype.upvalues.len(); traversal.contexts[k].prototype.upvalues.push(reference); - Reference::Upvalue(length as Index) // Reference (child) to this reference to that reference (parent) for next context + Reference::Upvalue(length.try_into().unwrap()) // Reference (child) to this reference to that reference (parent) for next context } } } @@ -1673,7 +1682,7 @@ impl Compile for Piece<&Call> { } None => {} } - let index = traversal.last_scope().index; + let index = traversal.index().unwrap(); traversal.compile(&self.it.2.inner_ref())?; // arguments traversal.push_code(self.it.0.unit().end().swap(Code::Call(index))); // Our responsibility to discard here Ok(()) @@ -1684,7 +1693,7 @@ impl Compile for Piece<&Prefix> { fn compile<'a, 'b>(&self, traversal: &mut Traversal) -> Result<(), LoadError> { match &self.it { Prefix::Call(call) => { - let index = traversal.last_scope().index; + let index = traversal.index().unwrap(); traversal.compile(&self.swap(call))?; traversal.push_code(self.swap(Code::Discard(index + 1)).end()); // produce 1 return value, or pad nil } @@ -1836,8 +1845,7 @@ fn jump_from(here: usize, there: usize) -> Result { } fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result<(), LoadError> { - let mut jumps = Vec::new(); - for jump in traversal.last_scope().jumps.clone() { + for jump in std::mem::replace(&mut traversal.last_scope().jumps,Vec::new()) { // ? match jump { BlindJump::Continue(index) => { @@ -1846,10 +1854,9 @@ fn resolve_break(traversal: &mut Traversal, begin: usize, end: usize) -> Result< BlindJump::Break(index) => { traversal.insert_code(index, Code::Jump(jump_from(index, end)?)); } - _ => jumps.push(jump), + _ => traversal.last_scope().jumps.push(jump), } } - traversal.last_scope().jumps = jumps; Ok(()) } @@ -1866,7 +1873,7 @@ fn compile_assignment( variable: Option<&Piece>, expression: &Piece<&Expression>| -> Result<(), LoadError> { - let index = traversal.last_scope().index; + let index = traversal.index().unwrap(); traversal.compile(expression)?; if let Some(variable) = variable { compile_variable(variable.inner_ref(), traversal, Access::Set)?; @@ -1882,14 +1889,14 @@ fn compile_assignment( match &**prefix { Prefix::Call(call) => { // multiple - let mut index = traversal.last_scope().index; + let mut index = traversal.index().unwrap(); traversal.compile(&expression.swap(call))?; let index_discard = traversal.push_code(expression.swap(Code::UNSURE)); while let Some(variable) = variables_iter.next() { index += 1; // The index we would need to pad nil to or restrict to compile_variable(variable.inner_ref(), traversal, Access::Set)?; // Pops each return value off the stack } - traversal.insert_code(index_discard, Code::Discard(index as Index)); + traversal.insert_code(index_discard, Code::Discard(index.try_into().unwrap())); } prefix => { if let Some(variable) = variables_iter.next() { @@ -1908,7 +1915,7 @@ fn compile_assignment( count += 1; compile_variable(variable.inner_ref(), traversal, Access::Set)?; } - traversal.insert_code(index_vararg, Code::VarArg(count as Index)); + traversal.insert_code(index_vararg, Code::VarArg(count.try_into().unwrap())); } } _ => { @@ -1934,7 +1941,7 @@ fn compile_assignment( impl Compile for Piece<&Block> { fn compile(&self, traversal: &mut Traversal) -> Result<(), LoadError> { - let last_scope_index = traversal.last_scope().index; + let last_scope_index = traversal.index().unwrap_or(0); let mut depth = 0; // Counter for 'dangling' scopes produced by any declarations to be closed. let mut var_scope = |traversal: &mut Traversal, symbol: String| -> Index { let index = traversal.temp_scope(); @@ -1951,7 +1958,7 @@ impl Compile for Piece<&Block> { compile_assignment(traversal, variables, expressions)?; } Statement::Call(call) => { - let index = traversal.last_scope().index; + let index = traversal.index().unwrap_or(0); traversal.compile(&self.swap(call))?; traversal.push_code(self.swap(Code::Discard(index))); } @@ -2109,7 +2116,7 @@ impl Compile for Piece<&Block> { traversal.new_scope(); iterator_variables.push( block - .swap(Variable::Register(traversal.last_scope().index)) + .swap(Variable::Register(traversal.index().unwrap())) .start(), ); } @@ -2117,10 +2124,10 @@ impl Compile for Piece<&Block> { compile_assignment(traversal, &iterator_variables, expressions)?; let index_loop = traversal.push_code(block.swap(Code::UNSURE)); // Discard to fill all names - let index = traversal.last_scope().index; + let index = traversal.index().unwrap(); traversal.push_code( block - .swap(Code::Discard(index + names.len() as Index)) + .swap(Code::Discard((index as usize + names.len()).try_into().unwrap())) .start(), ); for name in names.iter() { @@ -2175,7 +2182,7 @@ impl Compile for Piece<&Block> { } Statement::LocalFunction(name, function) => { var_scope(traversal, name.it.0.clone()); - let index = traversal.last_scope().index; + let index = traversal.index().unwrap(); traversal.compile(&self.swap(function))?; traversal.push_code(name.swap(Code::RegisterSet(index)).end()); } @@ -2201,10 +2208,7 @@ impl Compile for Piece<&Block> { for _ in 0..depth { traversal.close_scope(); } - if traversal.last_scope().index != last_scope_index { - println!("{:?}", traversal.last_scope()) - } - assert_eq!(traversal.last_scope().index, last_scope_index); + assert_eq!(traversal.index().unwrap_or(0), last_scope_index); Ok(()) } } @@ -2470,6 +2474,13 @@ impl Value { _ => true, } } + fn unwrap_str(&mut self) -> Rc { + match self { + Value::CachedString(cached) => cached.0.clone(), + Value::String(string,_hash) => string.clone(), + _ => panic!() + } + } } impl PartialEq for Value { @@ -2674,12 +2685,12 @@ impl Machine { _ => Ok(Value::Nil), } } - /*fn try_string(&mut self, machine: &mut Machine) -> Result { - Ok(match self { - Value::Nil => machine.new_string("nil".to_string().as_str())?, - Value::Bool(bool) => machine.new_string(format!("{}", bool).as_str())?, - Value::Integer(integer) => machine.new_string(format!("{}", integer).as_str())?, - Value::Number(number) => machine.new_string(format!("{}", number).as_str())?, + fn try_string(&mut self, value: &mut Value) -> Result { + Ok(match value { + Value::Nil => self.new_string("nil".to_string().as_str())?, + Value::Bool(bool) => self.new_string(format!("{}", bool).as_str())?, + Value::Integer(integer) => self.new_string(format!("{}", integer).as_str())?, + Value::Number(number) => self.new_string(format!("{}", number).as_str())?, it @ Value::String(..) => return Ok(it.clone()), it @ Value::CachedString(..) => return Ok(it.clone()), #[cfg(feature = "vector3")] @@ -2689,16 +2700,16 @@ impl Machine { if let Some(_metatable) = &table.meta { return Err(RunError("Metatables unimplemented".to_string())); } else { - machine.new_string("{...}".to_string().as_str())? + self.new_string("{...}".to_string().as_str())? } } Value::Object(object) => match object.borrow_mut().0.meta_string()? { string @ Value::String(..) => return Ok(string), it => return Err(RunError(format!("Expected string but got {:?}", it))), }, - Value::Function(callable) => machine.new_string(format!("{:?}", callable).as_str())?, + Value::Function(callable) => self.new_string(format!("{:?}", callable).as_str())?, }) - }*/ + } fn set(&mut self, subject: Value, index: Value, value: Value) -> Result<(), RunError> { match subject { Value::Nil => Err(RunError("Cannot get from nil".to_string())), @@ -2817,8 +2828,7 @@ impl Machine { let mut traversal = Traversal { machine: self, contexts: vec![Context { - scopes: vec![Scope { - // Dummy initial scope so the rest can start from index = 0 + scopes: vec![Scope { // Dummy scope index: 0, jumps: vec![], labels: vec![], @@ -2900,7 +2910,7 @@ impl Machine { }; let mut jump = |frame: &mut Frame, offset: Offset| { if offset < 0 { - frame.counter -= (-offset) as usize + frame.counter -= -(offset) as usize } else { frame.counter += offset as usize } @@ -3195,8 +3205,8 @@ impl Machine { fn enter(&mut self, closure: Gc) -> Result<(), RunError> { let mut needle = Needle { frames: vec![Frame { - vararg: 0, - offset: 0, + vararg: 1, // Both 1 since there is a single NIL on the stack + offset: 1, counter: 0, closure, }], @@ -3216,7 +3226,7 @@ impl Machine { string, Value::Function(Callable::Rust(Rc::from(Native(|machine: &mut Machine, needle: &mut Needle, index: usize| -> Result<(), RunError> { for i in index..needle.stack.len() { - println!("{:?}",needle.pop()) + println!("{}",machine.try_string(&mut needle.pop())?.unwrap_str()) } Ok(()) })))) diff --git a/src/tests/script.lua b/src/tests/script.lua index 6b01721..1c5d56f 100644 --- a/src/tests/script.lua +++ b/src/tests/script.lua @@ -1,5 +1,3 @@ -if true then - print("whats good") -else - print("oh no") +while true do + print("i am a loop!") end \ No newline at end of file