diff --git a/src/lib.rs b/src/lib.rs index 6c2bbd8..2ff46b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ struct Reader<'a> { // 'cursor' states that follow through parsed source white: bool, // Is the previous 'thing' whitespace? } +type Error = String; + pub struct LoadError(String, Piece<()>); // Any error returned by a machine loading code impl LoadError { @@ -25,8 +27,27 @@ impl LoadError { fn from(message: &str, piece: &Piece) -> LoadError { LoadError(message.to_string(), piece.unit()) } - fn msg(&self, reader: &Reader) -> String { - self.0.clone().add(reader.slice) + fn msg(&self, reader: &str) -> String { + let mut roll = format!("Error: {} {}",self.1.index,self.0); + let mut begin = self.1.index; + let mut end = self.1.index + self.1.width; + let mut count = 0; + for line in reader.lines() { // todo: improve this + count += 1; + if line.len() >= begin { + begin = 0; + roll = roll.add(format!("\n{}\t",count).as_str()); + roll = roll.add(line); + } else { + begin -= line.len(); + } + if line.len() > end { + break; + } else { + end -= line.len() + } + } + roll } } @@ -928,9 +949,12 @@ impl Parse for Statement { )) } else { let names = reader.take::>>()?.it; - reader.consume_white("=")?; - let expressions = reader.take::>>()?.it; - *reader = *reader; + let expressions = if reader.consume_white("=").is_ok() { + reader.take::>>()?.it + } else { + Vec::new() + }; + *reader = *reader; // todo: what are these Ok(Piece::from( Statement::Declaration(names, expressions), &start, @@ -2354,7 +2378,12 @@ impl Code { } impl Machine { - fn load(&mut self, source: &str) -> Result { + fn load(&mut self, source: &str) -> Result { + let parsed = match parse(source) { + Ok(parsed) => parsed, + Err(error) => return Err(error.msg(source)) + }; + let mut traversal = Traversal{contexts: vec![Context { scopes: vec![Scope { // Dummy initial scope so the rest can start from index = 0 index: 0, @@ -2376,12 +2405,21 @@ impl Machine { code: vec![], }, }]}; - parse(source)?.compile(&mut traversal)?; + + match parsed.compile(&mut traversal) { + Ok(compiled) => compiled, + Err(error) => return Err(error.msg(source)) + }; + + let prototype = match traversal.close_context() { + Ok(compiled) => compiled, + Err(error) => return Err(error.msg(source)) + }; let global = self.global.clone(); let upvalues = vec![self.allocator.alloc(Upvalue::Heap(Value::Table(global)))]; Ok(Callable::Mars(self.allocator.alloc(Closure { - prototype: Rc::new(traversal.close_context()?), + prototype: Rc::new(prototype), upvalues, }))) } @@ -2624,18 +2662,17 @@ impl Machine { } Code::IteratorLoop(offset) => { let len = needle.stack.len(); - let function_index = len - 2; - let state_index = len - 1; - let var_index = len; - let function = needle.stack[function_index].value.clone(); - let state = needle.stack[state_index].value.clone(); - let var = needle.stack[var_index].value.clone(); + let function = needle.stack[len - 2].value.clone(); + let state = needle.stack[len - 1].value.clone(); + let var = needle.stack[len].value.clone(); needle.push(function); - needle.push(var); needle.push(state); - let offset = frame.offset; - frame = call(self, needle,frame,Index::try_from(needle.stack.len() - offset - 2).unwrap())?; - needle.stack.get(len + 2).unwrap_or(&Register::NIL); + needle.push(var); + let frame_offset = frame.offset; + frame = call(self, needle,frame,Index::try_from(needle.stack.len() - frame_offset - 2).unwrap())?; + if needle.stack.get(len + 1).unwrap_or(&Register::NIL).value == Value::Nil { + jump(&mut frame, offset); + }; } } frame.counter += 1; @@ -2670,6 +2707,9 @@ mod tests { fn simple() { let mut machine = Machine::new(); let result = machine.load(include_str!("tests/script.lua")); - println!("{:#?}", result); + match result { + Err(error) => println!("{}",error), + Ok(result) => println!("{:?}",result) + } } } \ No newline at end of file diff --git a/src/tests/script.lua b/src/tests/script.lua index 092709f..ace0f14 100644 --- a/src/tests/script.lua +++ b/src/tests/script.lua @@ -1,15 +1 @@ -local two -do - local one - if something then - local three - print(something) - end - local four - if something2 then - - end -end -local function bricked(hello, there) - -end \ No newline at end of file +do end \ No newline at end of file