From f1180dbc5f317c0ca089c8632f13d19434216787 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Sun, 18 Aug 2019 15:40:23 -0500 Subject: [PATCH] DEV: Positions are tracked on the stack now too. --- src/build/opcode/error.rs | 13 +- src/build/opcode/mod.rs | 14 +- src/build/opcode/runtime.rs | 258 +++++++++++++------------- src/build/opcode/scope.rs | 136 +------------- src/build/opcode/test.rs | 26 +-- src/build/opcode/vm.rs | 350 ++++++++++++++++++------------------ 6 files changed, 343 insertions(+), 454 deletions(-) diff --git a/src/build/opcode/error.rs b/src/build/opcode/error.rs index 139e8ad..7ee54d6 100644 --- a/src/build/opcode/error.rs +++ b/src/build/opcode/error.rs @@ -18,14 +18,14 @@ use crate::ast::Position; #[derive(Debug)] pub struct Error { message: String, - pos: Position, + pos: Option, } impl Error { pub fn new(msg: String, pos: Position) -> Self { Self { - message: String::new(), - pos: pos, + message: msg, + pos: Some(pos), } } } @@ -34,11 +34,10 @@ impl From for Error where E: std::error::Error + Sized, { - fn from(_e: E) -> Self { - // FIXME(jwall): This should really have more information for debugging + fn from(e: E) -> Self { Error { - message: _e.description().to_owned(), - pos: Position::new(0, 0, 0), + message: e.description().to_owned(), + pos: None, } } } diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index 41facb2..3cad9d6 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -250,9 +250,10 @@ impl TryFrom<&Value> for Val { Val::List(els) } S(_) | F(_) | M(_) | T(_) => { - return Err(dbg!( - Error::new(format!("Invalid Value {:?} to Val translation", val), - Position::new(0, 0, 0)))); + return Err(dbg!(Error::new( + format!("Invalid Value {:?} to Val translation", val), + Position::new(0, 0, 0) + ))); } }) } @@ -301,7 +302,12 @@ impl TryFrom<&Val> for Value { } // TODO(jwall): These can go away eventually when we replace the tree // walking interpreter. - Val::Module(_) | Val::Func(_) => return Err(dbg!(Error::new(format!("Invalid Translation from Val {} to Value", val), Position::new(0, 0, 0)))), + Val::Module(_) | Val::Func(_) => { + return Err(dbg!(Error::new( + format!("Invalid Translation from Val {} to Value", val), + Position::new(0, 0, 0) + ))) + } }) } } diff --git a/src/build/opcode/runtime.rs b/src/build/opcode/runtime.rs index 8b33027..546cea7 100644 --- a/src/build/opcode/runtime.rs +++ b/src/build/opcode/runtime.rs @@ -63,9 +63,9 @@ impl Builtins { &mut self, path: Option

, h: Hook, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, @@ -90,7 +90,7 @@ impl Builtins { &self, path: P, use_import_path: bool, - pos: &Position, + pos: Position, ) -> Result { // Try a relative path first. let path = path.into(); @@ -122,7 +122,7 @@ impl Builtins { } } - fn get_file_as_string(&self, path: &str, pos: &Position) -> Result { + fn get_file_as_string(&self, path: &str, pos: Position) -> Result { let sep = format!("{}", std::path::MAIN_SEPARATOR); let raw_path = path.replace("/", &sep); let normalized = self.find_file(raw_path, false, pos)?; @@ -136,21 +136,21 @@ impl Builtins { fn import( &mut self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { let path = stack.pop(); - if let Some(val) = path { + if let Some((val, path_pos)) = path { if let &Value::P(Str(ref path)) = val.as_ref() { let mut borrowed_env = env.borrow_mut(); let val_cache = &mut borrowed_env.val_cache; if val_cache.contains_key(path) { - stack.push(val_cache[path].clone()); + stack.push((val_cache[path].clone(), path_pos)); } else { let op_pointer = env.borrow_mut().op_cache.entry(path).get_pointer_or_else( || { @@ -174,23 +174,20 @@ impl Builtins { vm.run()?; let result = Rc::new(vm.symbols_to_tuple(true)); val_cache.insert(path.clone(), result.clone()); - stack.push(result); + stack.push((result, pos)); } return Ok(()); } - return Err(dbg!(Error::new( - format!("Invalid Path {:?}", val), - pos.clone(), - ))); + return Err(dbg!(Error::new(format!("Invalid Path {:?}", val), pos,))); } unreachable!(); } fn include( &self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, @@ -198,64 +195,66 @@ impl Builtins { { let path = stack.pop(); let typ = stack.pop(); - let path = if let Some(val) = path { + let path = if let Some((val, path_pos)) = path { if let &Value::P(Str(ref path)) = val.as_ref() { path.clone() } else { return Err(dbg!(Error::new( format!("Invalid Path {:?}", val), - pos.clone(), + path_pos, ))); } } else { unreachable!(); }; - let typ = if let Some(val) = typ.as_ref() { + let typ = if let Some((val, typ_pos)) = typ { if let &Value::P(Str(ref typ)) = val.as_ref() { typ.clone() } else { return Err(dbg!(Error::new( - format!("Expected conversion type but got {:?}", typ), - pos.clone(), + format!("Expected conversion type but got {:?}", val), + typ_pos, ))); } } else { unreachable!(); }; if typ == "str" { - stack.push(Rc::new(P(Str(self.get_file_as_string(&path, pos)?)))); + stack.push(( + Rc::new(P(Str(self.get_file_as_string(&path, pos.clone())?))), + pos.clone(), + )); } else { - stack.push(Rc::new( - match env.borrow().importer_registry.get_importer(&typ) { + stack.push(( + Rc::new(match env.borrow().importer_registry.get_importer(&typ) { Some(importer) => { - let contents = self.get_file_as_string(&path, pos)?; + let contents = self.get_file_as_string(&path, pos.clone())?; if contents.len() == 0 { eprintln!("including an empty file. Use NULL as the result"); P(Empty) } else { match importer.import(contents.as_bytes()) { Ok(v) => v.try_into()?, - Err(e) => { - return Err(dbg!(Error::new(format!("{}", e), pos.clone(),))) - } + Err(e) => return Err(dbg!(Error::new(format!("{}", e), pos,))), } } } None => { return Err(dbg!(Error::new( format!("No such conversion type {}", &typ), - pos.clone(), + pos, ))) } - }, + }), + pos, )); } Ok(()) } - fn assert(&mut self, stack: &mut Vec>) -> Result<(), Error> { + fn assert(&mut self, stack: &mut Vec<(Rc, Position)>) -> Result<(), Error> { let tuple = stack.pop(); - if let Some(val) = tuple.clone() { + if let Some((val, tpl_pos)) = tuple.clone() { if let &Value::C(Tuple(ref tuple)) = val.as_ref() { // look for the description field let mut desc = None; @@ -278,21 +277,23 @@ impl Builtins { } } } + let msg = format!( + "TYPE FAIL - Expected tuple with ok and desc fields got {:?} at {}\n", + tuple, tpl_pos + ); + self.assert_results.record_assert_result(&msg, false); + } else { + unreachable!(); } - let msg = format!( - "TYPE FAIL - Expected tuple with ok and desc fields got {:?} at line: {} column: {}\n", - tuple, "TODO", "TODO" - ); - self.assert_results.record_assert_result(&msg, false); return Ok(()); } fn out, O, E>( &self, path: Option

, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, @@ -304,9 +305,9 @@ impl Builtins { Box::new(std::io::stdout()) }; let val = stack.pop(); - if let Some(val) = val { + if let Some((val, val_pos)) = val { let val = val.try_into()?; - if let Some(c_type_val) = stack.pop() { + if let Some((c_type_val, c_type_pos)) = stack.pop() { if let &Value::S(ref c_type) = c_type_val.as_ref() { if let Some(c) = env.borrow().converter_registry.get_converter(c_type) { if let Err(e) = c.convert(Rc::new(val), &mut writer) { @@ -316,14 +317,14 @@ impl Builtins { } else { return Err(dbg!(Error::new( format!("No such conversion type {:?}", c_type), - pos.clone() + c_type_pos, ))); } } } return Err(dbg!(Error::new( format!("Not a conversion type {:?}", val), - pos.clone() + val_pos, ))); } unreachable!(); @@ -331,32 +332,34 @@ impl Builtins { fn convert( &self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { let val = stack.pop(); - if let Some(val) = val { + if let Some((val, val_pos)) = val { let val = val.try_into()?; - if let Some(c_type_val) = stack.pop() { + if let Some((c_type_val, c_typ_pos)) = stack.pop() { if let &Value::S(ref c_type) = c_type_val.as_ref() { if let Some(c) = env.borrow().converter_registry.get_converter(c_type) { let mut buf: Vec = Vec::new(); match c.convert(Rc::new(val), &mut buf) { Ok(_) => { - stack - .push(Rc::new(P(Str( + stack.push(( + Rc::new(P(Str( String::from_utf8_lossy(buf.as_slice()).to_string() - )))); + ))), + pos, + )); } Err(_e) => { return Err(dbg!(Error::new( format!("No such conversion type {:?}", c_type), - pos.clone() + c_typ_pos, ))); } } @@ -366,7 +369,7 @@ impl Builtins { } return Err(dbg!(Error::new( format!("Not a conversion type {:?}", val), - pos.clone() + val_pos, ))); } unreachable!() @@ -374,22 +377,22 @@ impl Builtins { fn map( &self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { // get the list from the stack - let list = if let Some(list) = stack.pop() { + let (list, list_pos) = if let Some(list) = stack.pop() { list } else { unreachable!(); }; // get the func ptr from the stack - let fptr = if let Some(ptr) = stack.pop() { + let (fptr, fptr_pos) = if let Some(ptr) = stack.pop() { ptr } else { unreachable!(); @@ -398,7 +401,7 @@ impl Builtins { let f = if let &F(ref f) = fptr.as_ref() { f } else { - return Err(dbg!(Error::new(format!("Not a function!!"), pos.clone(),))); + return Err(dbg!(Error::new(format!("Not a function!!"), fptr_pos))); }; match list.as_ref() { @@ -406,18 +409,19 @@ impl Builtins { let mut result_elems = Vec::new(); for e in elems.iter() { // push function argument on the stack. - stack.push(e.clone()); + stack.push((e.clone(), list_pos.clone())); // call function and push it's result on the stack. - result_elems.push(VM::fcall_impl(f, stack, env.clone(), pos)?); + let (result, _) = VM::fcall_impl(f, stack, env.clone(), &pos)?; + result_elems.push(result); } - stack.push(Rc::new(C(List(result_elems)))); + stack.push((Rc::new(C(List(result_elems))), list_pos)); } &C(Tuple(ref _flds)) => { let mut new_fields = Vec::new(); for (ref name, ref val) in _flds { - stack.push(val.clone()); - stack.push(Rc::new(P(Str(name.clone())))); - let result = VM::fcall_impl(f, stack, env.clone(), pos)?; + stack.push((val.clone(), list_pos.clone())); + stack.push((Rc::new(P(Str(name.clone()))), list_pos.clone())); + let (result, result_pos) = VM::fcall_impl(f, stack, env.clone(), &fptr_pos)?; if let &C(List(ref fval)) = result.as_ref() { // we expect them to be a list of exactly 2 items. if fval.len() != 2 { @@ -425,42 +429,42 @@ impl Builtins { format!( "Map Functions over tuples must return a list of two items" ), - pos.clone(), + result_pos, ))); } let name = match fval[0].as_ref() { &P(Str(ref name)) => name.clone(), _ => return Err(dbg!(Error::new( - format!("Map functionss over tuples must return a String as the first list item"), - pos.clone(), + format!("Map functions over tuples must return a String as the first list item"), + result_pos, ))), }; new_fields.push((name, fval[1].clone())); } } - stack.push(Rc::new(C(Tuple(dbg!(new_fields))))); + stack.push((Rc::new(C(Tuple(dbg!(new_fields)))), pos)); } &P(Str(ref s)) => { let mut buf = String::new(); for c in s.chars() { - stack.push(Rc::new(P(Str(c.to_string())))); + stack.push((Rc::new(P(Str(c.to_string()))), list_pos.clone())); // call function and push it's result on the stack. - let result = VM::fcall_impl(f, stack, env.clone(), pos)?; + let (result, result_pos) = VM::fcall_impl(f, stack, env.clone(), &fptr_pos)?; if let &P(Str(ref s)) = result.as_ref() { buf.push_str(s); } else { return Err(dbg!(Error::new( format!("Map functions over string should return strings"), - pos.clone() + result_pos ))); } } - stack.push(Rc::new(P(Str(buf)))); + stack.push((Rc::new(P(Str(buf))), pos)); } _ => { return Err(dbg!(Error::new( format!("You can only map over lists, tuples, or strings"), - pos.clone(), + pos, ))) } }; @@ -469,22 +473,22 @@ impl Builtins { fn filter( &self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { // get the list from the stack - let list = if let Some(list) = stack.pop() { + let (list, list_pos) = if let Some(list) = stack.pop() { list } else { unreachable!(); }; // get the func ptr from the stack - let fptr = if let Some(ptr) = stack.pop() { + let (fptr, fptr_pos) = if let Some(ptr) = stack.pop() { ptr } else { unreachable!(); @@ -493,7 +497,7 @@ impl Builtins { let f = if let &F(ref f) = fptr.as_ref() { f } else { - return Err(dbg!(Error::new(format!("Not a function!!"), pos.clone(),))); + return Err(dbg!(Error::new(format!("Not a function!!"), fptr_pos))); }; match list.as_ref() { @@ -501,9 +505,9 @@ impl Builtins { let mut result_elems = Vec::new(); for e in elems.iter() { // push function argument on the stack. - stack.push(e.clone()); + stack.push((e.clone(), list_pos.clone())); // call function and push it's result on the stack. - let condition = VM::fcall_impl(f, stack, env.clone(), pos)?; + let (condition, _) = VM::fcall_impl(f, stack, env.clone(), &fptr_pos)?; // Check for empty or boolean results and only push e back in // if they are non empty and true match condition.as_ref() { @@ -513,14 +517,14 @@ impl Builtins { _ => result_elems.push(e.clone()), } } - stack.push(Rc::new(C(List(result_elems)))); + stack.push((Rc::new(C(List(result_elems))), pos)); } &C(Tuple(ref _flds)) => { let mut new_fields = Vec::new(); for (ref name, ref val) in _flds { - stack.push(val.clone()); - stack.push(Rc::new(P(Str(name.clone())))); - let condition = VM::fcall_impl(f, stack, env.clone(), pos)?; + stack.push((val.clone(), list_pos.clone())); + stack.push((Rc::new(P(Str(name.clone()))), list_pos.clone())); + let (condition, _) = VM::fcall_impl(f, stack, env.clone(), &pos)?; // Check for empty or boolean results and only push e back in // if they are non empty and true match condition.as_ref() { @@ -530,14 +534,14 @@ impl Builtins { _ => new_fields.push((name.clone(), val.clone())), } } - stack.push(Rc::new(C(Tuple(dbg!(new_fields))))); + stack.push((Rc::new(C(Tuple(dbg!(new_fields)))), pos)); } &P(Str(ref s)) => { let mut buf = String::new(); for c in s.chars() { - stack.push(Rc::new(P(Str(c.to_string())))); + stack.push((Rc::new(P(Str(c.to_string()))), list_pos.clone())); // call function and push it's result on the stack. - let condition = VM::fcall_impl(f, stack, env.clone(), pos)?; + let (condition, _) = VM::fcall_impl(f, stack, env.clone(), &pos)?; // Check for empty or boolean results and only push c back in // if they are non empty and true match condition.as_ref() { @@ -547,27 +551,27 @@ impl Builtins { _ => buf.push(c), } } - stack.push(Rc::new(P(Str(buf)))); + stack.push((Rc::new(P(Str(buf))), pos)); } _ => { return Err(dbg!(Error::new( format!("You can only filter over lists, tuples, or strings"), - pos.clone(), + pos, ))) } } Ok(()) } - fn regex(&self, stack: &mut Vec>, pos: &Position) -> Result<(), Error> { + fn regex(&self, stack: &mut Vec<(Rc, Position)>, pos: Position) -> Result<(), Error> { // 1. get left side (string) - let left_str = if let Some(val) = stack.pop() { + let left_str = if let Some((val, val_pos)) = stack.pop() { if let &P(Str(ref s)) = val.as_ref() { s.clone() } else { return dbg!(Err(Error::new( format!("Expected string bug got {:?}", val), - pos.clone(), + val_pos, ))); } } else { @@ -575,13 +579,13 @@ impl Builtins { }; // 2. get right side (string) - let right_str = if let Some(val) = stack.pop() { + let right_str = if let Some((val, val_pos)) = stack.pop() { if let &P(Str(ref s)) = val.as_ref() { s.clone() } else { return dbg!(Err(Error::new( format!("Expected string bug got {:?}", val), - pos.clone(), + val_pos, ))); } } else { @@ -590,34 +594,34 @@ impl Builtins { // 3. compare via regex let rex = Regex::new(&right_str)?; - stack.push(Rc::new(P(Bool(rex.find(&left_str).is_some())))); + stack.push((Rc::new(P(Bool(rex.find(&left_str).is_some()))), pos)); Ok(()) } fn reduce( &self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, - pos: &Position, + pos: Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { // get the list from the stack - let list = if let Some(list) = stack.pop() { + let (list, list_pos) = if let Some(list) = stack.pop() { list } else { unreachable!(); }; // Get the accumulator from the stack - let mut acc = if let Some(acc) = stack.pop() { + let (mut acc, mut acc_pos) = if let Some(acc) = stack.pop() { acc } else { unreachable!(); }; // get the func ptr from the stack - let fptr = if let Some(ptr) = stack.pop() { + let (fptr, fptr_pos) = if let Some(ptr) = stack.pop() { ptr } else { unreachable!(); @@ -626,36 +630,42 @@ impl Builtins { let f = if let &F(ref f) = fptr.as_ref() { f } else { - return dbg!(Err(Error::new(format!("Not a function!"), pos.clone(),))); + return dbg!(Err(Error::new(format!("Not a function!"), fptr_pos))); }; match list.as_ref() { &C(List(ref elems)) => { for e in dbg!(elems).iter() { // push function arguments on the stack. - stack.push(dbg!(e.clone())); - stack.push(dbg!(acc.clone())); + stack.push((dbg!(e.clone()), list_pos.clone())); + stack.push((dbg!(acc.clone()), acc_pos.clone())); // call function and push it's result on the stack. - acc = VM::fcall_impl(f, stack, env.clone(), pos)?; + let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone(), &fptr_pos)?; + acc = new_acc; + acc_pos = new_acc_pos; } } &C(Tuple(ref _flds)) => { for (ref name, ref val) in _flds.iter() { // push function arguments on the stack. - stack.push(val.clone()); - stack.push(Rc::new(P(Str(name.clone())))); - stack.push(dbg!(acc.clone())); + stack.push((val.clone(), list_pos.clone())); + stack.push((Rc::new(P(Str(name.clone()))), list_pos.clone())); + stack.push((dbg!(acc.clone()), acc_pos.clone())); // call function and push it's result on the stack. - acc = VM::fcall_impl(f, stack, env.clone(), pos)?; + let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone(), &fptr_pos)?; + acc = new_acc; + acc_pos = new_acc_pos; } } &P(Str(ref _s)) => { for c in _s.chars() { // push function arguments on the stack. - stack.push(dbg!(Rc::new(P(Str(c.to_string()))))); - stack.push(dbg!(acc.clone())); + stack.push((dbg!(Rc::new(P(Str(c.to_string())))), list_pos.clone())); + stack.push((dbg!(acc.clone()), acc_pos.clone())); // call function and push it's result on the stack. - acc = VM::fcall_impl(f, stack, env.clone(), pos)?; + let (new_acc, new_acc_pos) = VM::fcall_impl(f, stack, env.clone(), &fptr_pos)?; + acc = new_acc; + acc_pos = new_acc_pos; } } _ => { @@ -667,26 +677,26 @@ impl Builtins { }; // push the acc on the stack as our result - stack.push(dbg!(acc)); + stack.push((dbg!(acc), pos)); Ok(()) } - fn range(&self, stack: &mut Vec>, pos: &Position) -> Result<(), Error> { - let start = if let Some(start) = stack.pop() { + fn range(&self, stack: &mut Vec<(Rc, Position)>, pos: Position) -> Result<(), Error> { + let (start, _) = if let Some(start) = stack.pop() { start } else { unreachable!(); }; - let step = if let Some(step) = stack.pop() { + let (step, _) = if let Some((step, step_pos)) = stack.pop() { if let &P(Empty) = step.as_ref() { - Rc::new(P(Int(1))) + (Rc::new(P(Int(1))), step_pos) } else { - step + (step, step_pos) } } else { unreachable!(); }; - let end = if let Some(end) = stack.pop() { + let (end, _) = if let Some(end) = stack.pop() { end } else { unreachable!(); @@ -707,17 +717,17 @@ impl Builtins { _ => { return dbg!(Err(Error::new( format!("Ranges can only be created with Ints"), - pos.clone(), + pos, ))); } } - stack.push(Rc::new(C(List(elems)))); + stack.push((Rc::new(C(List(elems))), pos)); Ok(()) } fn trace( &mut self, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, pos: Position, env: Rc>>, ) -> Result<(), Error> @@ -725,14 +735,14 @@ impl Builtins { O: std::io::Write, E: std::io::Write, { - let val = if let Some(val) = dbg!(stack.pop()) { + let (val, val_pos) = if let Some(val) = dbg!(stack.pop()) { val } else { unreachable!(); }; let expr = stack.pop(); let expr_pretty = match expr { - Some(ref expr) => match dbg!(expr.as_ref()) { + Some((ref expr, _)) => match dbg!(expr.as_ref()) { &P(Str(ref expr)) => expr.clone(), _ => unreachable!(), }, @@ -744,11 +754,11 @@ impl Builtins { "TRACE: {} = {} at {}", expr_pretty, writable_val, - pos + &val_pos ) { - return Err(dbg!(Error::new(format!("{}", e), pos.clone(),))); + return Err(dbg!(Error::new(format!("{}", e), pos))); }; - stack.push(val); + stack.push((val, val_pos)); Ok(()) } } diff --git a/src/build/opcode/scope.rs b/src/build/opcode/scope.rs index c495c4f..616d742 100644 --- a/src/build/opcode/scope.rs +++ b/src/build/opcode/scope.rs @@ -17,159 +17,37 @@ use std::rc::Rc; use super::Value; -#[derive(Clone, PartialEq, Debug)] -pub enum Bindings { - Sealed(BTreeMap>), - Open(BTreeMap>), -} -use Bindings::{Open, Sealed}; - -impl Bindings { - pub fn new() -> Self { - Sealed(BTreeMap::new()) - } - - pub fn into_open(self) -> Self { - match self { - Open(flds) => Open(flds), - Sealed(flds) => Open(flds), - } - } - - pub fn into_sealed(self) -> Self { - match self { - Open(flds) => Sealed(flds), - Sealed(flds) => Sealed(flds), - } - } - - pub fn get(&self, name: &str) -> Option> { - match self { - Open(flds) => flds.get(name).cloned(), - Sealed(flds) => flds.get(name).cloned(), - } - } - - pub fn add(&mut self, name: String, val: Rc) { - match self { - Sealed(flds) => flds.insert(name, val), - Open(flds) => flds.insert(name, val), - }; - } - - pub fn symbol_list(&self) -> Vec<&String> { - match self { - Sealed(flds) => flds.keys().collect(), - Open(flds) => flds.keys().collect(), - } - } -} - #[derive(Clone, PartialEq, Debug)] pub struct Stack { - curr: Bindings, - prev: Vec, + curr: BTreeMap>, } impl Stack { pub fn new() -> Self { Stack { - curr: Bindings::new(), - prev: Vec::new(), + curr: BTreeMap::new(), } } pub fn get(&self, name: &str) -> Option> { - match &self.curr { - Sealed(flds) => flds.get(name).cloned(), - Open(flds) => { - if let Some(v) = flds.get(name) { - return Some(v.clone()); - } else { - for b in self.prev.iter() { - match b { - Sealed(bflds) => return bflds.get(name).cloned(), - Open(bflds) => return bflds.get(name).cloned(), - } - } - } - return None; - } - } + self.curr.get(name).cloned() } pub fn is_bound(&self, name: &str) -> bool { self.curr.get(name).is_some() } - pub fn push(&mut self) { - let mut nb = Bindings::new(); - std::mem::swap(&mut nb, &mut self.curr); - self.prev.push(nb); - } - - pub fn to_open(&mut self) { - let mut tmp = Bindings::new(); - std::mem::swap(&mut tmp, &mut self.curr); - tmp = tmp.into_open(); - std::mem::swap(&mut tmp, &mut self.curr); - } - - pub fn pop(&mut self) -> Result<(), String> { - if let Some(parent) = self.prev.pop() { - self.curr = parent; - Ok(()) - } else { - dbg!(Err(format!("Exceeded Stack depth!!"))) - } - } - pub fn add(&mut self, name: String, val: Rc) { - self.curr.add(name, val); + self.curr.insert(name, val); } pub fn symbol_list(&self) -> Vec<&String> { - match &self.curr { - Sealed(flds) => flds.keys().collect(), - Open(flds) => { - let mut keys = BTreeSet::new(); - keys.extend(flds.keys()); - for b in self.prev.iter() { - match b { - Sealed(bflds) => { - keys.extend(bflds.keys()); - return Vec::from_iter(keys.iter().cloned()); - } - Open(bflds) => { - keys.extend(bflds.keys()); - } - } - } - return Vec::from_iter(keys.iter().cloned()); - } - } + self.curr.keys().collect() } pub fn snapshot(&self) -> Self { - let curr = self.curr.clone(); - match curr { - Sealed(_) => Self { - curr: curr, - prev: Vec::new(), - }, - Open(_) => { - let mut prev = Vec::new(); - for b in self.prev.iter() { - match b { - Sealed(_) => { - prev.push(b.clone()); - break; - } - Open(_) => prev.push(b.clone()), - } - } - Self { curr, prev } - } + Self { + curr: self.curr.clone(), } } } diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 01a36f0..5a792ef 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -15,7 +15,6 @@ use std::cell::RefCell; use std::rc::Rc; use super::environment::Environment; -use super::scope::Stack; use super::translate::PositionMap; use super::Composite::{List, Tuple}; use super::Op::{ @@ -33,7 +32,7 @@ macro_rules! assert_cases { for case in $cases.drain(0..) { let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); let mut positions = Vec::with_capacity(case.0.len()); - for i in 0..case.0.len() { + for _ in 0..case.0.len() { positions.push(Position::new(0, 0, 0)); } let map = PositionMap{ @@ -42,7 +41,7 @@ macro_rules! assert_cases { }; let mut vm = VM::new(Rc::new(map), env); vm.run().unwrap(); - assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1)); + assert_eq!(dbg!(vm.pop()).unwrap().0, Rc::new(case.1)); } }; @@ -131,7 +130,7 @@ fn bind_op() { for case in cases.drain(0..) { let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); let mut positions = Vec::with_capacity(case.0.len()); - for i in 0..case.0.len() { + for _ in 0..case.0.len() { positions.push(Position::new(0, 0, 0)); } let map = PositionMap { @@ -570,19 +569,6 @@ fn type_comparisons() { ]; } -#[test] -fn scope_stacks() { - let mut stack = Stack::new(); - stack.add("one".to_owned(), Rc::new(P(Int(1)))); - let mut val = stack.get("one").unwrap(); - assert_eq!(val.as_ref(), &P(Int(1))); - stack.push(); - assert!(stack.get("one").is_none()); - stack.to_open(); - val = stack.get("one").unwrap(); - assert_eq!(val.as_ref(), &P(Int(1))); -} - use super::translate; use crate::iter::OffsetStrIter; use crate::parse::parse; @@ -598,7 +584,7 @@ macro_rules! assert_parse_cases { let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); let mut vm = VM::new(ops.clone(), env); vm.run().unwrap(); - assert_eq!(vm.pop().unwrap(), Rc::new(case.1)); + assert_eq!(vm.pop().unwrap().0, Rc::new(case.1)); } }; @@ -783,11 +769,11 @@ fn simple_trace() { let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); let mut vm = VM::new(ops.clone(), env); vm.run().unwrap(); - assert_eq!(vm.pop().unwrap(), Rc::new(P(Int(2)))); + assert_eq!(vm.pop().unwrap().0, Rc::new(P(Int(2)))); let err_out = &vm.env.borrow().stderr; assert_eq!( String::from_utf8_lossy(err_out).to_owned(), - "TRACE: 1 + 1 = 2 at line: 1 column: 1\n" + "TRACE: 1 + 1 = 2 at line: 1 column: 7\n" ); } diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index 0f5d600..1a7d6bd 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -33,7 +33,7 @@ where O: std::io::Write, E: std::io::Write, { - stack: Vec>, + stack: Vec<(Rc, Position)>, symbols: Stack, runtime: runtime::Builtins, ops: OpPointer, @@ -89,46 +89,46 @@ where let pos = self.ops.pos().unwrap().clone(); let idx = self.ops.idx()?; match op { - Op::Val(p) => self.push(Rc::new(P(p.clone())))?, - Op::Sym(s) => self.push(Rc::new(S(s.clone())))?, + Op::Val(p) => self.push(Rc::new(P(p.clone())), pos)?, + Op::Sym(s) => self.push(Rc::new(S(s.clone())), pos)?, Op::DeRef(s) => self.op_deref(s.clone(), &pos)?, - Op::Add => self.op_add(&pos)?, - Op::Mod => self.op_mod(&pos)?, - Op::Sub => self.op_sub(&pos)?, - Op::Mul => self.op_mul(&pos)?, - Op::Div => self.op_div(&pos)?, - Op::Bind => self.op_bind(true, &pos)?, - Op::BindOver => self.op_bind(false, &pos)?, - Op::Equal => self.op_equal()?, + Op::Add => self.op_add(pos)?, + Op::Mod => self.op_mod(pos)?, + Op::Sub => self.op_sub(pos)?, + Op::Mul => self.op_mul(pos)?, + Op::Div => self.op_div(pos)?, + Op::Bind => self.op_bind(true)?, + Op::BindOver => self.op_bind(false)?, + Op::Equal => self.op_equal(pos)?, Op::Not => self.op_not(&pos)?, Op::Gt => self.op_gt(&pos)?, Op::Lt => self.op_lt(&pos)?, - Op::GtEq => self.op_gteq(&pos)?, - Op::LtEq => self.op_lteq(&pos)?, + Op::GtEq => self.op_gteq(pos)?, + Op::LtEq => self.op_lteq(pos)?, // Add a Composite list value to the stack - Op::InitList => self.push(Rc::new(C(List(Vec::new()))))?, + Op::InitList => self.push(Rc::new(C(List(Vec::new()))), pos)?, // Add a composite tuple value to the stack - Op::InitTuple => self.push(Rc::new(C(Tuple(Vec::new()))))?, + Op::InitTuple => self.push(Rc::new(C(Tuple(Vec::new()))), pos)?, Op::Field => self.op_field()?, Op::Element => self.op_element()?, - Op::Index => self.op_index(false, &pos)?, - Op::SafeIndex => self.op_index(true, &pos)?, - Op::Cp => self.op_copy(&pos)?, + Op::Index => self.op_index(false, pos)?, + Op::SafeIndex => self.op_index(true, pos)?, + Op::Cp => self.op_copy(pos)?, //FIXME(jwall): Should this take a user provided message? Op::Bang => self.op_bang()?, - Op::InitThunk(jp) => self.op_thunk(idx, jp)?, + Op::InitThunk(jp) => self.op_thunk(idx, jp, pos)?, Op::Noop => { // Do nothing } Op::Jump(jp) => self.op_jump(jp)?, - Op::JumpIfTrue(jp) => self.op_jump_if_true(jp, &pos)?, - Op::JumpIfFalse(jp) => self.op_jump_if_false(jp, &pos)?, + Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?, + Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?, Op::SelectJump(jp) => self.op_select_jump(jp)?, - Op::And(jp) => self.op_and(jp, &pos)?, - Op::Or(jp) => self.op_or(jp, &pos)?, - Op::Module(mptr) => self.op_module(idx, mptr, &pos)?, - Op::Func(jptr) => self.op_func(idx, jptr, &pos)?, - Op::FCall => self.op_fcall(&pos)?, + Op::And(jp) => self.op_and(jp, pos)?, + Op::Or(jp) => self.op_or(jp, pos)?, + Op::Module(mptr) => self.op_module(idx, mptr, pos)?, + Op::Func(jptr) => self.op_func(idx, jptr, pos)?, + Op::FCall => self.op_fcall(pos)?, Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone())?, Op::Return => { dbg!(&self.stack); @@ -138,7 +138,7 @@ where self.pop()?; } Op::Typ => self.op_typ()?, - Op::Runtime(h) => self.op_runtime(h, &pos)?, + Op::Runtime(h) => self.op_runtime(h, pos)?, Op::Render => self.op_render()?, }; } @@ -146,7 +146,7 @@ where } fn op_typ(&mut self) -> Result<(), Error> { - let val = self.pop()?; + let (val, pos) = self.pop()?; let typ_name = match val.as_ref() { P(Int(_)) => "int", P(Float(_)) => "float", @@ -161,13 +161,13 @@ where T(_) => "thunk", } .to_owned(); - self.push(Rc::new(P(Str(typ_name))))?; + self.push(Rc::new(P(Str(typ_name))), pos)?; Ok(()) } fn op_deref(&mut self, name: String, pos: &Position) -> Result<(), Error> { let val = self.get_binding(&name, pos)?.clone(); - self.push(val) + self.push(val, pos.clone()) } fn op_jump(&mut self, jp: i32) -> Result<(), Error> { @@ -180,42 +180,48 @@ where Ok(()) } - fn op_and(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { - let cond = self.pop()?; + fn op_and(&mut self, jp: i32, pos: Position) -> Result<(), Error> { + let (cond, cond_pos) = self.pop()?; let cc = cond.clone(); if let &P(Bool(cond)) = cond.as_ref() { if !cond { - self.push(cc)?; + self.push(cc, cond_pos)?; self.op_jump(jp)?; } } else { return Err(dbg!(Error::new( - format!("Not a boolean condition {:?} in && expression!", cond), - pos.clone(), + format!( + "Not a boolean condition {:?} in && expression at {}", + cond, pos + ), + cond_pos.clone(), ))); } Ok(()) } - fn op_or(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { - let cond = self.pop()?; + fn op_or(&mut self, jp: i32, pos: Position) -> Result<(), Error> { + let (cond, cond_pos) = self.pop()?; let cc = dbg!(cond.clone()); if let &P(Bool(cond)) = cond.as_ref() { if dbg!(cond) { - self.push(cc)?; + self.push(cc, cond_pos)?; self.op_jump(jp)?; } } else { return Err(dbg!(Error::new( - format!("Not a boolean condition {:?} in || expression!", cond), - pos.clone(), + format!( + "Not a boolean condition {:?} in || expression at {}!", + cond, pos + ), + cond_pos.clone(), ))); } Ok(()) } - fn op_jump_if_true(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { - let cond = self.pop()?; + fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> { + let (cond, cond_pos) = self.pop()?; if let &P(Bool(cond)) = cond.as_ref() { if cond { self.op_jump(jp)?; @@ -223,14 +229,14 @@ where } else { return Err(dbg!(Error::new( format!("Expected boolean but got {:?}!", cond), - pos.clone(), + cond_pos.clone(), ))); } Ok(()) } - fn op_jump_if_false(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { - let cond = self.pop()?; + fn op_jump_if_false(&mut self, jp: i32) -> Result<(), Error> { + let (cond, pos) = self.pop()?; if let &P(Bool(cond)) = cond.as_ref() { if !cond { self.op_jump(jp)?; @@ -246,9 +252,9 @@ where fn op_select_jump(&'a mut self, jp: i32) -> Result<(), Error> { // pop field value off - let field_name = dbg!(self.pop())?; + let (field_name, _) = dbg!(self.pop())?; // pop search value off - let search = dbg!(self.pop())?; + let (search, srch_pos) = dbg!(self.pop())?; // compare them. let matched = match (field_name.as_ref(), search.as_ref()) { (&S(ref fname), &P(Str(ref sname))) | (&S(ref fname), &S(ref sname)) => fname == sname, @@ -256,31 +262,31 @@ where }; if !matched { // if they aren't equal then push search value back on and jump - self.push(dbg!(search))?; + self.push(dbg!(search), srch_pos)?; self.op_jump(dbg!(jp))?; } Ok(()) } - fn op_module(&'a mut self, idx: usize, jptr: i32, pos: &Position) -> Result<(), Error> { - let mod_val = dbg!(self.pop())?; + fn op_module(&'a mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> { + let (mod_val, mod_val_pos) = dbg!(self.pop())?; let (result_ptr, flds) = match mod_val.as_ref() { &C(Tuple(ref flds)) => (None, flds.clone()), &T(ptr) => { - let tpl_val = self.pop()?; + let (tpl_val, tpl_val_pos) = self.pop()?; if let &C(Tuple(ref flds)) = tpl_val.as_ref() { (Some(ptr), flds.clone()) } else { return dbg!(Err(Error::new( format!("Expected tuple but got {:?}", tpl_val), - pos.clone(), + tpl_val_pos, ))); } } _ => { return dbg!(Err(Error::new( format!("Expected tuple but got {:?}", mod_val), - pos.clone(), + mod_val_pos, ))); } }; @@ -300,7 +306,7 @@ where pkg_pos.clone(), pkg_pos.clone(), pkg_pos.clone(), - pkg_pos.clone(), + pkg_pos, ]; Some(OpPointer::new(Rc::new(PositionMap { ops: pkg_ops, @@ -309,24 +315,24 @@ where } else { None }; - self.push(Rc::new(M(Module { - ptr: ops, - result_ptr: result_ptr, - flds: flds, - pkg_ptr: pkg_ptr, - })))?; + self.push( + Rc::new(M(Module { + ptr: ops, + result_ptr: result_ptr, + flds: flds, + pkg_ptr: pkg_ptr, + })), + pos, + )?; self.op_jump(jptr) } - fn op_func(&mut self, idx: usize, jptr: i32, pos: &Position) -> Result<(), Error> { + fn op_func(&mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> { // get arity from stack - let mut scope_snapshot = self.symbols.snapshot(); - scope_snapshot.push(); - scope_snapshot.to_open(); - eprintln!("Defining a new function"); + let scope_snapshot = self.symbols.snapshot(); let mut bindings = Vec::new(); // get imported symbols from stack - let list_val = self.pop()?; + let (list_val, args_pos) = self.pop()?; if let &C(List(ref elems)) = list_val.as_ref() { for e in elems { if let &S(ref sym) = e.as_ref() { @@ -334,33 +340,35 @@ where } else { return dbg!(Err(Error::new( format!("Not an argument name {:?}", e), - pos.clone(), + args_pos, ))); } } } else { return dbg!(Err(Error::new( format!("Fault!!! Bad Argument List"), - pos.clone(), + args_pos, ))); } let mut ops = self.ops.clone(); ops.jump(idx)?; - self.push(Rc::new(F(Func { - ptr: ops, // where the function starts. - bindings: bindings, - snapshot: scope_snapshot, - })))?; - eprintln!("Jumping to {} past the function body", jptr); + self.push( + Rc::new(F(Func { + ptr: ops, // where the function starts. + bindings: bindings, + snapshot: scope_snapshot, + })), + pos, + )?; self.op_jump(jptr) } pub fn fcall_impl( f: &Func, - stack: &mut Vec>, + stack: &mut Vec<(Rc, Position)>, env: Rc>>, pos: &Position, - ) -> Result, Error> { + ) -> Result<(Rc, Position), Error> { let Func { ref ptr, ref bindings, @@ -372,8 +380,8 @@ where // now put each argument on our scope stack as a binding. // TODO(jwall): This should do a better error if there is // nothing on the stack. - let val = stack.pop().unwrap(); - vm.binding_push(nm.clone(), val, false, pos)?; + let (val, pos) = stack.pop().unwrap(); + vm.binding_push(nm.clone(), val, false, &pos)?; } // proceed to the function body vm.run()?; @@ -382,58 +390,59 @@ where fn op_new_scope(&mut self, jp: i32, ptr: OpPointer) -> Result<(), Error> { let scope_snapshot = self.symbols.snapshot(); - dbg!(&ptr); let mut vm = Self::with_pointer(ptr, self.env.clone()).to_scoped(scope_snapshot); - dbg!(&vm.stack); vm.run()?; - dbg!(&vm.stack); - self.push(vm.pop()?)?; + let result = vm.pop()?; + self.push(result.0, result.1)?; self.op_jump(jp)?; Ok(()) } - fn op_fcall(&mut self, pos: &Position) -> Result<(), Error> { - let f = dbg!(self.pop())?; + fn op_fcall(&mut self, pos: Position) -> Result<(), Error> { + let (f, _) = dbg!(self.pop())?; if let &F(ref f) = f.as_ref() { - let val = Self::fcall_impl(f, &mut self.stack, self.env.clone(), pos)?; - self.push(dbg!(val))?; + let (val, _) = Self::fcall_impl(f, &mut self.stack, self.env.clone(), &pos)?; + self.push(dbg!(val), pos.clone())?; } Ok(()) } - fn op_thunk(&mut self, idx: usize, jp: i32) -> Result<(), Error> { - self.push(Rc::new(T(idx)))?; + fn op_thunk(&mut self, idx: usize, jp: i32, pos: Position) -> Result<(), Error> { + self.push(Rc::new(T(idx)), pos)?; self.op_jump(jp) } fn op_not(&mut self, pos: &Position) -> Result<(), Error> { - let operand = self.pop()?; + let (operand, operand_pos) = self.pop()?; if let P(Bool(val)) = operand.as_ref() { - self.push(Rc::new(P(Bool(!val))))?; + self.push(Rc::new(P(Bool(!val))), operand_pos)?; return Ok(()); } return Err(dbg!(Error::new( - format!("Expected Boolean but got {:?}", operand), - pos.clone(), + format!( + "Expected Boolean but got {:?} in expression at {}", + operand, pos + ), + operand_pos, ))); } - fn op_equal(&mut self) -> Result<(), Error> { - let left = self.pop()?; - let right = self.pop()?; - self.push(Rc::new(P(Bool(left == right))))?; + fn op_equal(&mut self, pos: Position) -> Result<(), Error> { + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; + self.push(Rc::new(P(Bool(left == right))), pos)?; Ok(()) } fn op_gt(&mut self, pos: &Position) -> Result<(), Error> { - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { - self.push(Rc::new(P(Bool(i > ii))))?; + self.push(Rc::new(P(Bool(i > ii))), pos.clone())?; } (&P(Float(f)), &P(Float(ff))) => { - self.push(Rc::new(P(Bool(f > ff))))?; + self.push(Rc::new(P(Bool(f > ff))), pos.clone())?; } _ => { return Err(dbg!(Error::new( @@ -449,14 +458,14 @@ where } fn op_lt(&mut self, pos: &Position) -> Result<(), Error> { - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { - self.push(Rc::new(P(Bool(i < ii))))?; + self.push(Rc::new(P(Bool(i < ii))), pos.clone())?; } (&P(Float(f)), &P(Float(ff))) => { - self.push(Rc::new(P(Bool(f < ff))))?; + self.push(Rc::new(P(Bool(f < ff))), pos.clone())?; } _ => { return Err(dbg!(Error::new( @@ -471,15 +480,15 @@ where Ok(()) } - fn op_lteq(&mut self, pos: &Position) -> Result<(), Error> { - let left = self.pop()?; - let right = self.pop()?; + fn op_lteq(&mut self, pos: Position) -> Result<(), Error> { + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { - self.push(Rc::new(P(Bool(i <= ii))))?; + self.push(Rc::new(P(Bool(i <= ii))), pos)?; } (&P(Float(f)), &P(Float(ff))) => { - self.push(Rc::new(P(Bool(f <= ff))))?; + self.push(Rc::new(P(Bool(f <= ff))), pos)?; } _ => { return Err(dbg!(Error::new( @@ -487,22 +496,22 @@ where "Expected Numeric values of the same type but got {:?} and {:?}", left, right ), - pos.clone(), + pos, ))); } } Ok(()) } - fn op_gteq(&mut self, pos: &Position) -> Result<(), Error> { - let left = self.pop()?; - let right = self.pop()?; + fn op_gteq(&mut self, pos: Position) -> Result<(), Error> { + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; match (left.as_ref(), right.as_ref()) { (&P(Int(i)), &P(Int(ii))) => { - self.push(Rc::new(P(Bool(i >= ii))))?; + self.push(Rc::new(P(Bool(i >= ii))), pos)?; } (&P(Float(f)), &P(Float(ff))) => { - self.push(Rc::new(P(Bool(f >= ff))))?; + self.push(Rc::new(P(Bool(f >= ff))), pos)?; } _ => { return Err(dbg!(Error::new( @@ -510,65 +519,65 @@ where "Expected Numeric values of the same type but got {:?} and {:?}", left, right ), - pos.clone(), + pos, ))); } } Ok(()) } - fn op_mod(&mut self, pos: &Position) -> Result<(), Error> { + fn op_mod(&mut self, pos: Position) -> Result<(), Error> { // Adds the previous two items in the stack. - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.modulus(&left, &right, pos)?)))?; + self.push(Rc::new(P(self.modulus(&left, &right, &pos)?)), pos)?; Ok(()) } - fn op_add(&mut self, pos: &Position) -> Result<(), Error> { + fn op_add(&mut self, pos: Position) -> Result<(), Error> { // Adds the previous two items in the stack. - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; // Then pushes the result onto the stack. - self.push(Rc::new(self.add(&left, &right, pos)?))?; + self.push(Rc::new(self.add(&left, &right, &pos)?), pos)?; Ok(()) } - fn op_sub(&mut self, pos: &Position) -> Result<(), Error> { + fn op_sub(&mut self, pos: Position) -> Result<(), Error> { // Subtracts the previous two items in the stack. - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.sub(&left, &right, pos)?)))?; + self.push(Rc::new(P(self.sub(&left, &right, &pos)?)), pos)?; Ok(()) } - fn op_mul(&mut self, pos: &Position) -> Result<(), Error> { + fn op_mul(&mut self, pos: Position) -> Result<(), Error> { // Multiplies the previous two items in the stack. - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.mul(&left, &right, pos)?)))?; + self.push(Rc::new(P(self.mul(&left, &right, &pos)?)), pos)?; Ok(()) } - fn op_div(&mut self, pos: &Position) -> Result<(), Error> { + fn op_div(&mut self, pos: Position) -> Result<(), Error> { // Divides the previous two items in the stack. - let left = self.pop()?; - let right = self.pop()?; + let (left, _) = self.pop()?; + let (right, _) = self.pop()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.div(&left, &right, pos)?)))?; + self.push(Rc::new(P(self.div(&left, &right, &pos)?)), pos)?; Ok(()) } - fn op_bind(&mut self, strict: bool, pos: &Position) -> Result<(), Error> { + fn op_bind(&mut self, strict: bool) -> Result<(), Error> { // pop val off stack. - let val = self.pop()?; + let (val, val_pos) = self.pop()?; // pop name off stack. - let name = self.pop()?; + let (name, _) = self.pop()?; if let &S(ref name) = name.as_ref() { - self.binding_push(name.clone(), val, strict, pos)?; + self.binding_push(name.clone(), val, strict, &val_pos)?; } else { unreachable!(); } @@ -578,22 +587,22 @@ where fn op_field(&mut self) -> Result<(), Error> { // Add a Composite field value to a tuple on the stack // get value from stack - let val = self.pop()?; + let (val, _) = self.pop()?; // get name from stack. - let name_val = self.pop()?; + let (name_val, _) = self.pop()?; let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() { s } else { unreachable!(); }; // get composite tuple from stack - let tpl = self.pop()?; + let (tpl, tpl_pos) = self.pop()?; if let &C(Tuple(ref flds)) = tpl.as_ref() { // add name and value to tuple let mut flds = flds.clone(); self.merge_field_into_tuple(&mut flds, name.clone(), val)?; // place composite tuple back on stack - self.push(Rc::new(C(Tuple(flds))))?; + self.push(Rc::new(C(Tuple(flds))), tpl_pos)?; } else { unreachable!(); }; @@ -602,15 +611,15 @@ where fn op_element(&mut self) -> Result<(), Error> { // get element from stack. - let val = dbg!(self.pop()?); + let (val, _) = dbg!(self.pop()?); // get next value. It should be a Composite list. - let list = dbg!(self.pop()?); + let (list, pos) = dbg!(self.pop()?); if let &C(List(ref elems)) = list.as_ref() { // add value to list let mut elems = elems.clone(); elems.push(val); // Add that value to the list and put list back on stack. - self.push(Rc::new(C(List(elems))))?; + self.push(Rc::new(C(List(elems))), pos)?; } else { unreachable!(); }; @@ -621,15 +630,15 @@ where Ok(()) } - fn op_index(&mut self, safe: bool, pos: &Position) -> Result<(), Error> { + fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> { // left and then right - let right = dbg!(self.pop()?); - let left = dbg!(self.pop()?); + let (right, right_pos) = dbg!(self.pop()?); + let (left, _) = dbg!(self.pop()?); match right.as_ref() { &P(Int(i)) => { if let &C(List(ref elems)) = left.as_ref() { if i < (elems.len() as i64) && i >= 0 { - self.push(elems[i as usize].clone())?; + self.push(elems[i as usize].clone(), right_pos)?; return Ok(()); } } @@ -638,7 +647,7 @@ where if let &C(Tuple(ref flds)) = left.as_ref() { for &(ref key, ref val) in flds.iter() { if key == s { - self.push(val.clone())?; + self.push(val.clone(), right_pos)?; return Ok(()); } } @@ -649,20 +658,20 @@ where } }; if safe { - self.push(Rc::new(P(Empty)))?; + self.push(Rc::new(P(Empty)), pos)?; return Ok(()); } return Err(dbg!(Error::new( format!("Invalid selector index: {:?} target: {:?}", right, left), - pos.clone(), + pos, ))); } - fn op_copy(&mut self, pos: &Position) -> Result<(), Error> { + fn op_copy(&mut self, pos: Position) -> Result<(), Error> { // get next value. It should be a Module or Tuple. - let tgt = dbg!(self.pop()?); + let (tgt, tgt_pos) = dbg!(self.pop()?); // This value should always be a tuple - let override_val = dbg!(self.pop()?); + let (override_val, _) = dbg!(self.pop()?); let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { oflds.clone() } else { @@ -675,7 +684,7 @@ where self.merge_field_into_tuple(&mut flds, name, val)?; } // Put the copy on the Stack - self.push(Rc::new(C(Tuple(flds))))?; + self.push(Rc::new(C(Tuple(flds))), tgt_pos)?; } &M(Module { ref ptr, @@ -698,27 +707,28 @@ where if let Some(ptr) = pkg_ptr { let mut pkg_vm = Self::with_pointer(ptr.clone(), self.env.clone()); pkg_vm.run()?; - let pkg_func = pkg_vm.pop()?; + let (pkg_func, _) = pkg_vm.pop()?; self.merge_field_into_tuple(&mut flds, "pkg".to_owned(), pkg_func)?; } let mut vm = Self::with_pointer(ptr.clone(), self.env.clone()); - vm.push(Rc::new(S("mod".to_owned())))?; - vm.push(Rc::new(C(Tuple(flds))))?; + vm.push(Rc::new(S("mod".to_owned())), pos.clone())?; + vm.push(Rc::new(C(Tuple(flds))), pos.clone())?; vm.run()?; if let Some(ptr) = result_ptr { vm.ops.jump(ptr.clone())?; vm.run()?; - self.push(dbg!(vm.pop())?)?; + let (result_val, result_pos) = vm.pop()?; + self.push(dbg!(result_val), result_pos)?; } else { dbg!(&vm.symbols); - self.push(Rc::new(dbg!(vm.symbols_to_tuple(false))))?; + self.push(Rc::new(dbg!(vm.symbols_to_tuple(false))), pos)?; } } _ => { return Err(dbg!(Error::new( format!("Expected a Tuple or a Module but got {:?}", tgt), - pos.clone(), + pos, ))); } } @@ -741,8 +751,8 @@ where Ok(()) } - fn push(&mut self, p: Rc) -> Result<(), Error> { - self.stack.push(p); + fn push(&mut self, val: Rc, pos: Position) -> Result<(), Error> { + self.stack.push((val, pos)); Ok(()) } @@ -773,7 +783,7 @@ where } } - pub fn pop(&mut self) -> Result, Error> { + pub fn pop(&mut self) -> Result<(Rc, Position), Error> { match self.stack.pop() { Some(v) => Ok(v), None => unreachable!(), @@ -873,7 +883,7 @@ where }) } - fn op_runtime(&mut self, h: Hook, pos: &Position) -> Result<(), Error> { + fn op_runtime(&mut self, h: Hook, pos: Position) -> Result<(), Error> { self.runtime.handle( self.ops.path.as_ref(), h, @@ -884,8 +894,8 @@ where } fn op_render(&mut self) -> Result<(), Error> { - let val = self.pop()?; - self.push(Rc::new(P(Str(val.as_ref().into()))))?; + let (val, pos) = self.pop()?; + self.push(Rc::new(P(Str(val.as_ref().into()))), pos)?; Ok(()) } }