diff --git a/src/build/opcode/cache.rs b/src/build/opcode/cache.rs index 953cb25..f0527dc 100644 --- a/src/build/opcode/cache.rs +++ b/src/build/opcode/cache.rs @@ -16,11 +16,12 @@ use std::collections::BTreeMap; use std::path::PathBuf; use std::rc::Rc; -use super::{Op, OpPointer}; +use super::translate::PositionMap; +use super::OpPointer; /// A Cache of Op codes. pub struct Ops { - ops: BTreeMap>>, + ops: BTreeMap>, } impl Ops { @@ -35,10 +36,10 @@ impl Ops { } } -pub struct Entry<'a>(btree_map::Entry<'a, String, Rc>>); +pub struct Entry<'a>(btree_map::Entry<'a, String, Rc>); impl<'a> Entry<'a> { - pub fn get_pointer_or_else Vec, P: Into>( + pub fn get_pointer_or_else PositionMap, P: Into>( self, f: F, path: P, diff --git a/src/build/opcode/error.rs b/src/build/opcode/error.rs index 634e0f4..139e8ad 100644 --- a/src/build/opcode/error.rs +++ b/src/build/opcode/error.rs @@ -13,8 +13,22 @@ // limitations under the License. use std::convert::From; +use crate::ast::Position; + #[derive(Debug)] -pub struct Error {} +pub struct Error { + message: String, + pos: Position, +} + +impl Error { + pub fn new(msg: String, pos: Position) -> Self { + Self { + message: String::new(), + pos: pos, + } + } +} impl From for Error where @@ -22,6 +36,9 @@ where { fn from(_e: E) -> Self { // FIXME(jwall): This should really have more information for debugging - Error {} + Error { + message: _e.description().to_owned(), + pos: Position::new(0, 0, 0), + } } } diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index c17d0b1..41facb2 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -250,7 +250,9 @@ impl TryFrom<&Value> for Val { Val::List(els) } S(_) | F(_) | M(_) | T(_) => { - return Err(dbg!(Error {})); + return Err(dbg!( + Error::new(format!("Invalid Value {:?} to Val translation", val), + Position::new(0, 0, 0)))); } }) } @@ -299,7 +301,7 @@ 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 {})), + 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/pointer.rs b/src/build/opcode/pointer.rs index 7794b48..9095b90 100644 --- a/src/build/opcode/pointer.rs +++ b/src/build/opcode/pointer.rs @@ -14,20 +14,23 @@ use std::path::PathBuf; use std::rc::Rc; +use crate::ast::Position; + +use super::translate::PositionMap; use super::{Error, Op}; #[derive(Debug, PartialEq, Clone)] pub struct OpPointer { - pub ops: Rc>, + pub pos_map: Rc, pub ptr: Option, pub path: Option, } impl OpPointer { - pub fn new(ops: Rc>) -> Self { + pub fn new(ops: Rc) -> Self { // If we load an empty program what happens? Self { - ops: ops, + pos_map: ops, ptr: None, path: None, } @@ -41,28 +44,41 @@ impl OpPointer { pub fn next(&mut self) -> Option<&Op> { if let Some(i) = self.ptr { let nxt = i + 1; - if nxt < self.ops.len() { + if nxt < self.pos_map.len() { self.ptr = Some(nxt); } else { return None; } - } else if self.ops.len() != 0 { + } else if self.pos_map.len() != 0 { self.ptr = Some(0); } self.op() } pub fn jump(&mut self, ptr: usize) -> Result<(), Error> { - if ptr < self.ops.len() { + if ptr < self.pos_map.len() { self.ptr = Some(ptr); return Ok(()); } - Err(dbg!(Error {})) + Err(dbg!(Error::new( + format!("FAULT!!! Invalid Jump!"), + match self.pos() { + Some(pos) => pos.clone(), + None => Position::new(0, 0, 0), + }, + ))) } pub fn op(&self) -> Option<&Op> { if let Some(i) = self.ptr { - return self.ops.get(i); + return self.pos_map.ops.get(i); + } + None + } + + pub fn pos(&self) -> Option<&Position> { + if let Some(i) = self.ptr { + return self.pos_map.pos.get(i); } None } @@ -70,13 +86,16 @@ impl OpPointer { pub fn idx(&self) -> Result { match self.ptr { Some(ptr) => Ok(ptr), - None => dbg!(Err(Error {})), + None => dbg!(Err(Error::new( + format!("FAULT!!! Position Check failure!"), + Position::new(0, 0, 0), + ))), } } pub fn snapshot(&self) -> Self { Self { - ops: self.ops.clone(), + pos_map: self.pos_map.clone(), ptr: None, path: self.path.clone(), } diff --git a/src/build/opcode/runtime.rs b/src/build/opcode/runtime.rs index 2d5ac15..8b33027 100644 --- a/src/build/opcode/runtime.rs +++ b/src/build/opcode/runtime.rs @@ -21,8 +21,7 @@ use std::rc::Rc; use regex::Regex; use super::environment::Environment; -use super::pointer::OpPointer; -use super::Value::{C, F, P, S}; +use super::Value::{C, F, P}; use super::VM; use super::{Composite, Error, Hook, Primitive, Value}; use crate::ast::Position; @@ -66,22 +65,23 @@ impl Builtins { h: Hook, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { match h { - Hook::Import => self.import(stack, env), - Hook::Include => self.include(stack, env), + Hook::Import => self.import(stack, env, pos), + Hook::Include => self.include(stack, env, pos), Hook::Assert => self.assert(stack), - Hook::Convert => self.convert(stack, env), - Hook::Out => self.out(path, stack, env), - Hook::Map => self.map(stack, env), - Hook::Filter => self.filter(stack, env), - Hook::Reduce => self.reduce(stack, env), - Hook::Regex => self.regex(stack), - Hook::Range => self.range(stack), + Hook::Convert => self.convert(stack, env, pos), + Hook::Out => self.out(path, stack, env, pos), + Hook::Map => self.map(stack, env, pos), + Hook::Filter => self.filter(stack, env, pos), + Hook::Reduce => self.reduce(stack, env, pos), + Hook::Regex => self.regex(stack, pos), + Hook::Range => self.range(stack, pos), Hook::Trace(pos) => self.trace(stack, pos, env), } } @@ -90,6 +90,7 @@ impl Builtins { &self, path: P, use_import_path: bool, + pos: &Position, ) -> Result { // Try a relative path first. let path = path.into(); @@ -114,22 +115,22 @@ impl Builtins { } match normalized.canonicalize() { Ok(p) => Ok(p), - Err(_e) => Err(dbg!(Error {})), + Err(_e) => Err(dbg!(Error::new( + format!("Invalid path: {}", normalized.to_string_lossy()), + pos.clone(), + ))), } } - fn get_file_as_string(&self, path: &str) -> 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 = match self.find_file(raw_path, false) { - Ok(p) => p, - Err(_e) => { - return Err(dbg!(Error {})); - } - }; - let mut f = File::open(normalized).unwrap(); + let normalized = self.find_file(raw_path, false, pos)?; + // TODO(jwall): Proper error here + let mut f = File::open(normalized)?; let mut contents = String::new(); - f.read_to_string(&mut contents).unwrap(); + // TODO(jwall): Proper error here + f.read_to_string(&mut contents)?; Ok(contents) } @@ -137,6 +138,7 @@ impl Builtins { &mut self, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, @@ -176,14 +178,19 @@ impl Builtins { } return Ok(()); } + return Err(dbg!(Error::new( + format!("Invalid Path {:?}", val), + pos.clone(), + ))); } - return Err(dbg!(Error {})); + unreachable!(); } fn include( &self, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, @@ -195,42 +202,55 @@ impl Builtins { if let &Value::P(Str(ref path)) = val.as_ref() { path.clone() } else { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Invalid Path {:?}", val), + pos.clone(), + ))); } } else { - return Err(dbg!(Error {})); + unreachable!(); }; let typ = if let Some(val) = typ.as_ref() { if let &Value::P(Str(ref typ)) = val.as_ref() { typ.clone() } else { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Expected conversion type but got {:?}", typ), + pos.clone(), + ))); } } else { - return Err(dbg!(Error {})); + unreachable!(); }; if typ == "str" { - stack.push(Rc::new(P(Str(self.get_file_as_string(&path)?)))); + stack.push(Rc::new(P(Str(self.get_file_as_string(&path, pos)?)))); } else { stack.push(Rc::new( match env.borrow().importer_registry.get_importer(&typ) { Some(importer) => { - let contents = self.get_file_as_string(&path)?; + let contents = self.get_file_as_string(&path, pos)?; 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 {})), + Err(e) => { + return Err(dbg!(Error::new(format!("{}", e), pos.clone(),))) + } } } } - None => return Err(dbg!(Error {})), + None => { + return Err(dbg!(Error::new( + format!("No such conversion type {}", &typ), + pos.clone(), + ))) + } }, )); } - return Err(dbg!(Error {})); + Ok(()) } fn assert(&mut self, stack: &mut Vec>) -> Result<(), Error> { @@ -272,15 +292,16 @@ impl Builtins { path: Option

, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, E: std::io::Write, { - let path = if let Some(path) = path { - path + let mut writer: Box = if let Some(path) = path { + Box::new(File::create(path)?) } else { - return Err(dbg!(Error {})); + Box::new(std::io::stdout()) }; let val = stack.pop(); if let Some(val) = val { @@ -288,24 +309,31 @@ impl Builtins { if let Some(c_type_val) = 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) { - match c.convert(Rc::new(val), &mut File::create(path)?) { - Ok(_) => { - // noop - } - Err(_e) => return Err(dbg!(Error {})), + if let Err(e) = c.convert(Rc::new(val), &mut writer) { + return Err(dbg!(Error::new(format!("{}", e), pos.clone(),))); } return Ok(()); + } else { + return Err(dbg!(Error::new( + format!("No such conversion type {:?}", c_type), + pos.clone() + ))); } } } + return Err(dbg!(Error::new( + format!("Not a conversion type {:?}", val), + pos.clone() + ))); } - return Err(dbg!(Error {})); + unreachable!(); } fn convert( &self, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, @@ -325,20 +353,30 @@ impl Builtins { String::from_utf8_lossy(buf.as_slice()).to_string() )))); } - Err(_e) => return Err(dbg!(Error {})), + Err(_e) => { + return Err(dbg!(Error::new( + format!("No such conversion type {:?}", c_type), + pos.clone() + ))); + } } return Ok(()); } } } + return Err(dbg!(Error::new( + format!("Not a conversion type {:?}", val), + pos.clone() + ))); } - return Err(dbg!(Error {})); + unreachable!() } fn map( &self, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, @@ -348,19 +386,19 @@ impl Builtins { let list = if let Some(list) = stack.pop() { list } else { - return Err(dbg!(Error {})); + unreachable!(); }; // get the func ptr from the stack let fptr = if let Some(ptr) = stack.pop() { ptr } else { - return Err(dbg!(Error {})); + unreachable!(); }; let f = if let &F(ref f) = fptr.as_ref() { f } else { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new(format!("Not a function!!"), pos.clone(),))); }; match list.as_ref() { @@ -370,7 +408,7 @@ impl Builtins { // push function argument on the stack. stack.push(e.clone()); // call function and push it's result on the stack. - result_elems.push(VM::fcall_impl(f, stack, env.clone())?); + result_elems.push(VM::fcall_impl(f, stack, env.clone(), pos)?); } stack.push(Rc::new(C(List(result_elems)))); } @@ -379,15 +417,23 @@ impl Builtins { 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())?; + let result = VM::fcall_impl(f, stack, env.clone(), 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 { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!( + "Map Functions over tuples must return a list of two items" + ), + pos.clone(), + ))); } let name = match fval[0].as_ref() { &P(Str(ref name)) => name.clone(), - _ => return Err(dbg!(Error {})), + _ => return Err(dbg!(Error::new( + format!("Map functionss over tuples must return a String as the first list item"), + pos.clone(), + ))), }; new_fields.push((name, fval[1].clone())); } @@ -399,16 +445,24 @@ impl Builtins { for c in s.chars() { stack.push(Rc::new(P(Str(c.to_string())))); // call function and push it's result on the stack. - let result = VM::fcall_impl(f, stack, env.clone())?; + let result = VM::fcall_impl(f, stack, env.clone(), pos)?; if let &P(Str(ref s)) = result.as_ref() { buf.push_str(s); } else { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Map functions over string should return strings"), + pos.clone() + ))); } } stack.push(Rc::new(P(Str(buf)))); } - _ => return Err(dbg!(Error {})), + _ => { + return Err(dbg!(Error::new( + format!("You can only map over lists, tuples, or strings"), + pos.clone(), + ))) + } }; Ok(()) } @@ -417,6 +471,7 @@ impl Builtins { &self, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, @@ -426,29 +481,29 @@ impl Builtins { let list = if let Some(list) = stack.pop() { list } else { - return Err(dbg!(Error {})); + unreachable!(); }; // get the func ptr from the stack let fptr = if let Some(ptr) = stack.pop() { ptr } else { - return Err(dbg!(Error {})); + unreachable!(); }; let f = if let &F(ref f) = fptr.as_ref() { f } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error::new(format!("Not a function!!"), pos.clone(),))); }; - let elems = match list.as_ref() { + match list.as_ref() { &C(List(ref elems)) => { let mut result_elems = Vec::new(); for e in elems.iter() { // push function argument on the stack. stack.push(e.clone()); // call function and push it's result on the stack. - let condition = VM::fcall_impl(f, stack, env.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() { @@ -465,7 +520,7 @@ impl Builtins { 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())?; + 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() { @@ -482,7 +537,7 @@ impl Builtins { for c in s.chars() { stack.push(Rc::new(P(Str(c.to_string())))); // call function and push it's result on the stack. - let condition = VM::fcall_impl(f, stack, env.clone())?; + 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() { @@ -494,21 +549,29 @@ impl Builtins { } stack.push(Rc::new(P(Str(buf)))); } - _ => return Err(dbg!(Error {})), - }; + _ => { + return Err(dbg!(Error::new( + format!("You can only filter over lists, tuples, or strings"), + pos.clone(), + ))) + } + } Ok(()) } - fn regex(&self, stack: &mut Vec>) -> Result<(), Error> { + fn regex(&self, stack: &mut Vec>, pos: &Position) -> Result<(), Error> { // 1. get left side (string) let left_str = if let Some(val) = stack.pop() { if let &P(Str(ref s)) = val.as_ref() { s.clone() } else { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Expected string bug got {:?}", val), + pos.clone(), + ))); } } else { - return dbg!(Err(Error {})); + unreachable!(); }; // 2. get right side (string) @@ -516,10 +579,13 @@ impl Builtins { if let &P(Str(ref s)) = val.as_ref() { s.clone() } else { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Expected string bug got {:?}", val), + pos.clone(), + ))); } } else { - return dbg!(Err(Error {})); + unreachable!(); }; // 3. compare via regex @@ -532,6 +598,7 @@ impl Builtins { &self, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result<(), Error> where O: std::io::Write, @@ -541,25 +608,25 @@ impl Builtins { let list = if let Some(list) = stack.pop() { list } else { - return dbg!(Err(Error {})); + unreachable!(); }; // Get the accumulator from the stack let mut acc = if let Some(acc) = stack.pop() { acc } else { - return dbg!(Err(Error {})); + unreachable!(); }; // get the func ptr from the stack let fptr = if let Some(ptr) = stack.pop() { ptr } else { - return dbg!(Err(Error {})); + unreachable!(); }; let f = if let &F(ref f) = fptr.as_ref() { f } else { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new(format!("Not a function!"), pos.clone(),))); }; match list.as_ref() { @@ -569,7 +636,7 @@ impl Builtins { stack.push(dbg!(e.clone())); stack.push(dbg!(acc.clone())); // call function and push it's result on the stack. - acc = VM::fcall_impl(f, stack, env.clone())?; + acc = VM::fcall_impl(f, stack, env.clone(), pos)?; } } &C(Tuple(ref _flds)) => { @@ -579,7 +646,7 @@ impl Builtins { stack.push(Rc::new(P(Str(name.clone())))); stack.push(dbg!(acc.clone())); // call function and push it's result on the stack. - acc = VM::fcall_impl(f, stack, env.clone())?; + acc = VM::fcall_impl(f, stack, env.clone(), pos)?; } } &P(Str(ref _s)) => { @@ -588,10 +655,15 @@ impl Builtins { stack.push(dbg!(Rc::new(P(Str(c.to_string()))))); stack.push(dbg!(acc.clone())); // call function and push it's result on the stack. - acc = VM::fcall_impl(f, stack, env.clone())?; + acc = VM::fcall_impl(f, stack, env.clone(), pos)?; } } - _ => return Err(dbg!(Error {})), + _ => { + return Err(dbg!(Error::new( + format!("You can only reduce over lists, tuples, or strings"), + pos.clone() + ))) + } }; // push the acc on the stack as our result @@ -599,11 +671,11 @@ impl Builtins { Ok(()) } - fn range(&self, stack: &mut Vec>) -> Result<(), Error> { + fn range(&self, stack: &mut Vec>, pos: &Position) -> Result<(), Error> { let start = if let Some(start) = stack.pop() { start } else { - return dbg!(Err(Error {})); + unreachable!(); }; let step = if let Some(step) = stack.pop() { if let &P(Empty) = step.as_ref() { @@ -612,12 +684,12 @@ impl Builtins { step } } else { - return dbg!(Err(Error {})); + unreachable!(); }; let end = if let Some(end) = stack.pop() { end } else { - return dbg!(Err(Error {})); + unreachable!(); }; let mut elems = Vec::new(); @@ -633,7 +705,10 @@ impl Builtins { } } _ => { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Ranges can only be created with Ints"), + pos.clone(), + ))); } } stack.push(Rc::new(C(List(elems)))); @@ -653,25 +728,25 @@ impl Builtins { let val = if let Some(val) = dbg!(stack.pop()) { val } else { - return Err(dbg!(Error {})); + unreachable!(); }; let expr = stack.pop(); let expr_pretty = match expr { Some(ref expr) => match dbg!(expr.as_ref()) { &P(Str(ref expr)) => expr.clone(), - _ => return Err(dbg!(Error {})), + _ => unreachable!(), }, - _ => return Err(dbg!(Error {})), + _ => unreachable!(), }; let writable_val: Val = TryFrom::try_from(val.clone())?; - if let Err(_) = writeln!( + if let Err(e) = writeln!( &mut env.borrow_mut().stderr, "TRACE: {} = {} at {}", expr_pretty, writable_val, pos ) { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new(format!("{}", e), pos.clone(),))); }; stack.push(val); Ok(()) diff --git a/src/build/opcode/scope.rs b/src/build/opcode/scope.rs index 2ea6f93..c495c4f 100644 --- a/src/build/opcode/scope.rs +++ b/src/build/opcode/scope.rs @@ -15,7 +15,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; use std::rc::Rc; -use super::{Error, Value}; +use super::Value; #[derive(Clone, PartialEq, Debug)] pub enum Bindings { @@ -115,12 +115,12 @@ impl Stack { std::mem::swap(&mut tmp, &mut self.curr); } - pub fn pop(&mut self) -> Result<(), Error> { + pub fn pop(&mut self) -> Result<(), String> { if let Some(parent) = self.prev.pop() { self.curr = parent; Ok(()) } else { - dbg!(Err(Error {})) + dbg!(Err(format!("Exceeded Stack depth!!"))) } } diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index e64e451..01a36f0 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -16,6 +16,7 @@ use std::rc::Rc; use super::environment::Environment; use super::scope::Stack; +use super::translate::PositionMap; use super::Composite::{List, Tuple}; use super::Op::{ Add, Bang, Bind, BindOver, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, Index, InitList, @@ -25,12 +26,21 @@ use super::Op::{ use super::Primitive::{Bool, Empty, Float, Int, Str}; use super::Value::{C, P}; use super::VM; +use crate::ast::Position; macro_rules! assert_cases { (__impl__ $cases:expr) => { for case in $cases.drain(0..) { let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); - let mut vm = VM::new(Rc::new(case.0), env); + let mut positions = Vec::with_capacity(case.0.len()); + for i in 0..case.0.len() { + positions.push(Position::new(0, 0, 0)); + } + let map = PositionMap{ + ops: case.0, + pos: positions, + }; + let mut vm = VM::new(Rc::new(map), env); vm.run().unwrap(); assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1)); } @@ -120,10 +130,18 @@ fn bind_op() { for case in cases.drain(0..) { let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); - let mut vm = VM::new(Rc::new(case.0), env); + let mut positions = Vec::with_capacity(case.0.len()); + for i in 0..case.0.len() { + positions.push(Position::new(0, 0, 0)); + } + let map = PositionMap { + ops: case.0, + pos: positions, + }; + let mut vm = VM::new(Rc::new(map), env); vm.run().unwrap(); let (name, result) = case.1; - let v = vm.get_binding(name).unwrap(); + let v = vm.get_binding(name, &Position::new(0, 0, 0)).unwrap(); assert_eq!(&result, v.as_ref()); } } diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 3c2d037..4700e57 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::path::Path; -use crate::ast::{BinaryExprType, Expression, FormatArgs, Statement, Value}; +use crate::ast::{BinaryExprType, Expression, FormatArgs, Position, Statement, Value}; use crate::ast::{FuncOpDef, TemplatePart}; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; use crate::build::opcode::Primitive; @@ -21,14 +21,38 @@ use crate::build::opcode::{Hook, Op}; pub struct AST(); +#[derive(Debug, PartialEq)] +pub struct PositionMap { + pub ops: Vec, + pub pos: Vec, +} + +impl PositionMap { + pub fn len(&self) -> usize { + self.ops.len() + } + + pub fn push(&mut self, op: Op, pos: Position) { + self.ops.push(op); + self.pos.push(pos); + } + + pub fn replace(&mut self, idx: usize, op: Op) { + self.ops[idx] = op; + } +} + impl AST { - pub fn translate>(stmts: Vec, root: &P) -> Vec { - let mut ops = Vec::new(); + pub fn translate>(stmts: Vec, root: &P) -> PositionMap { + let mut ops = PositionMap { + ops: Vec::new(), + pos: Vec::new(), + }; Self::translate_stmts(stmts, &mut ops, root.as_ref()); return ops; } - fn translate_stmts(stmts: Vec, mut ops: &mut Vec, root: &Path) { + fn translate_stmts(stmts: Vec, mut ops: &mut PositionMap, root: &Path) { for stmt in stmts { match stmt { Statement::Expression(expr) => Self::translate_expr(expr, &mut ops, root), @@ -37,9 +61,9 @@ impl AST { } Statement::Let(def) => { let binding = def.name.fragment; - ops.push(Op::Sym(binding)); + ops.push(Op::Sym(binding), def.name.pos); Self::translate_expr(def.value, &mut ops, root); - ops.push(Op::Bind); + ops.push(Op::Bind, def.pos); } Statement::Output(_, _, _) => { unimplemented!("Out statements are not implmented yet") @@ -51,7 +75,7 @@ impl AST { } } - fn translate_expr(expr: Expression, mut ops: &mut Vec, root: &Path) { + fn translate_expr(expr: Expression, mut ops: &mut PositionMap, root: &Path) { match expr { Expression::Simple(v) => { Self::translate_value(v, &mut ops, root); @@ -61,92 +85,91 @@ impl AST { BinaryExprType::Add => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Add); + ops.push(Op::Add, def.pos); } BinaryExprType::Sub => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Sub); + ops.push(Op::Sub, def.pos); } BinaryExprType::Div => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Div); + ops.push(Op::Div, def.pos); } BinaryExprType::Mul => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Mul); + ops.push(Op::Mul, def.pos); } BinaryExprType::Equal => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Equal); + ops.push(Op::Equal, def.pos); } BinaryExprType::GT => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Gt); + ops.push(Op::Gt, def.pos); } BinaryExprType::LT => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Lt); + ops.push(Op::Lt, def.pos); } BinaryExprType::GTEqual => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::GtEq); + ops.push(Op::GtEq, def.pos); } BinaryExprType::LTEqual => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::LtEq); + ops.push(Op::LtEq, def.pos); } BinaryExprType::NotEqual => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Equal); - ops.push(Op::Not); + ops.push(Op::Equal, def.pos.clone()); + ops.push(Op::Not, def.pos); } BinaryExprType::REMatch => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Runtime(Hook::Regex)); + ops.push(Op::Runtime(Hook::Regex), def.pos); } BinaryExprType::NotREMatch => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Runtime(Hook::Regex)); - ops.push(Op::Not); + ops.push(Op::Runtime(Hook::Regex), def.pos.clone()); + ops.push(Op::Not, def.pos); } BinaryExprType::IS => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Typ); - ops.push(Op::Equal); + ops.push(Op::Typ, def.pos.clone()); + ops.push(Op::Equal, def.pos); } BinaryExprType::AND => { Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Noop); + ops.push(Op::Noop, def.pos); let idx = ops.len() - 1; Self::translate_expr(*def.right, &mut ops, root); let jptr = (ops.len() - 1 - idx) as i32; - ops[idx] = Op::And(dbg!(jptr)); - dbg!(ops); + ops.replace(idx, Op::And(dbg!(jptr))); } BinaryExprType::OR => { Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Noop); // Placeholder + ops.push(Op::Noop, def.pos); // Placeholder let idx = ops.len() - 1; Self::translate_expr(*def.right, &mut ops, root); let jptr = (ops.len() - 1 - idx) as i32; - ops[idx] = Op::Or(jptr); + ops.replace(idx, Op::Or(dbg!(jptr))); } BinaryExprType::Mod => { Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root); - ops.push(Op::Mod); + ops.push(Op::Mod, def.pos); } BinaryExprType::IN => { // Dot expressions expect the left side to be pushed first @@ -165,10 +188,10 @@ impl AST { Self::translate_expr(expr, &mut ops, root); } } - ops.push(Op::SafeIndex); - ops.push(Op::Val(Primitive::Empty)); - ops.push(Op::Equal); - ops.push(Op::Not); + ops.push(Op::SafeIndex, def.pos.clone()); + ops.push(Op::Val(Primitive::Empty), def.pos.clone()); + ops.push(Op::Equal, def.pos.clone()); + ops.push(Op::Not, def.pos); } BinaryExprType::DOT => { // Dot expressions expect the left side to be pushed first @@ -187,7 +210,7 @@ impl AST { Self::translate_expr(expr, &mut ops, root); } } - ops.push(Op::Index); + ops.push(Op::Index, def.pos); } }; } @@ -196,7 +219,7 @@ impl AST { } Expression::Fail(def) => { Self::translate_expr(*def.message, &mut ops, root); - ops.push(Op::Bang); + ops.push(Op::Bang, def.pos); } Expression::Format(def) => { match def.args { @@ -212,6 +235,7 @@ impl AST { let mut elems_iter = elems.drain(0..); let mut parts_iter = parts.drain(0..); Self::translate_template_part( + def.pos.clone(), parts_iter.next().unwrap(), &mut elems_iter, &mut ops, @@ -219,8 +243,17 @@ impl AST { root, ); for p in parts_iter { - Self::translate_template_part(p, &mut elems_iter, &mut ops, true, root); - ops.push(Op::Add); + Self::translate_template_part( + def.pos.clone(), + p, + &mut elems_iter, + &mut ops, + true, + root, + ); + // TODO(jwall): We could get a little more helpful about where + // these positions are. + ops.push(Op::Add, def.pos.clone()); } } FormatArgs::Single(expr) => { @@ -230,17 +263,19 @@ impl AST { let mut parts = formatter.parse(&def.template).unwrap(); parts.reverse(); let mut parts_iter = parts.drain(0..); - ops.push(Op::Noop); + ops.push(Op::Noop, expr.pos().clone()); let scope_idx = ops.len() - 1; // Add our item binding shadowing any binding that already // existed. - ops.push(Op::Sym("item".to_owned())); + let expr_pos = expr.pos().clone(); + ops.push(Op::Sym("item".to_owned()), expr.pos().clone()); Self::translate_expr(*expr, &mut ops, root); - ops.push(Op::BindOver); + ops.push(Op::BindOver, expr_pos.clone()); let mut elems = Vec::new(); let mut elems_iter = elems.drain(0..); Self::translate_template_part( + def.pos.clone(), parts_iter.next().unwrap(), &mut elems_iter, &mut ops, @@ -249,32 +284,33 @@ impl AST { ); for p in parts_iter { Self::translate_template_part( + def.pos.clone(), p, &mut elems_iter, &mut ops, false, root, ); - ops.push(Op::Add); + ops.push(Op::Add, expr_pos.clone()); } - ops.push(Op::Return); + ops.push(Op::Return, expr_pos); let jump_idx = (ops.len() - 1 - scope_idx) as i32; - ops[scope_idx] = Op::NewScope(jump_idx); + ops.replace(scope_idx, Op::NewScope(jump_idx)); } } } Expression::Func(def) => { - ops.push(Op::InitList); + ops.push(Op::InitList, def.pos.clone()); for b in def.argdefs { - ops.push(Op::Sym(b.val)); - ops.push(Op::Element); + ops.push(Op::Sym(b.val), b.pos.clone()); + ops.push(Op::Element, b.pos); } - ops.push(Op::Noop); + ops.push(Op::Noop, def.pos.clone()); let idx = ops.len() - 1; Self::translate_expr(*def.fields, &mut ops, root); - ops.push(Op::Return); + ops.push(Op::Return, def.pos); let jptr = ops.len() - 1 - idx; - ops[idx] = Op::Func(jptr as i32); + ops.replace(idx, Op::Func(jptr as i32)); } Expression::FuncOp(def) => { match def { @@ -284,7 +320,7 @@ impl AST { // push the target on the stack third Self::translate_expr(*def.target, &mut ops, root); // finally push the Hook::Map opcode - ops.push(Op::Runtime(Hook::Map)); + ops.push(Op::Runtime(Hook::Map), def.pos); } FuncOpDef::Filter(def) => { // push the function on the stack first. @@ -292,7 +328,7 @@ impl AST { // push the target on the stack third Self::translate_expr(*def.target, &mut ops, root); // finally push the Hook::Map opcode - ops.push(Op::Runtime(Hook::Filter)); + ops.push(Op::Runtime(Hook::Filter), def.pos); } FuncOpDef::Reduce(def) => { // push the function on the stack first. @@ -302,18 +338,18 @@ impl AST { // push the target on the stack third Self::translate_expr(*def.target, &mut ops, root); // finally push the Hook::Map opcode - ops.push(Op::Runtime(Hook::Reduce)); + ops.push(Op::Runtime(Hook::Reduce), def.pos); } } } Expression::Import(def) => { - ops.push(Op::Val(Primitive::Str(def.path.fragment))); - ops.push(Op::Runtime(Hook::Import)); + ops.push(Op::Val(Primitive::Str(def.path.fragment)), def.path.pos); + ops.push(Op::Runtime(Hook::Import), def.pos); } Expression::Include(def) => { - ops.push(Op::Val(Primitive::Str(def.typ.fragment))); - ops.push(Op::Val(Primitive::Str(def.path.fragment))); - ops.push(Op::Runtime(Hook::Include)); + ops.push(Op::Val(Primitive::Str(def.typ.fragment)), def.typ.pos); + ops.push(Op::Val(Primitive::Str(def.path.fragment)), def.path.pos); + ops.push(Op::Runtime(Hook::Include), def.pos); } Expression::Module(mut def) => { def.imports_to_absolute(root.to_path_buf()); @@ -321,74 +357,75 @@ impl AST { let out_expr = def.out_expr; let stmts = def.statements; // Init our module tuple bindings - ops.push(Op::InitTuple); + ops.push(Op::InitTuple, def.pos.clone()); for (t, e) in argset { - ops.push(Op::Sym(t.fragment)); + ops.push(Op::Sym(t.fragment), t.pos.clone()); Self::translate_expr(e, &mut ops, root); - ops.push(Op::Field); + ops.push(Op::Field, t.pos); } // If there is one then emit our return expression if let Some(expr) = out_expr { // Insert placeholder until we know jptr for this thunk - ops.push(Op::Noop); + let expr_pos = expr.pos().clone(); + ops.push(Op::Noop, expr.pos().clone()); let idx = ops.len() - 1; Self::translate_expr(*expr, &mut ops, root); - ops.push(Op::Return); + ops.push(Op::Return, expr_pos.clone()); let jptr = ops.len() - idx - 1; - ops[idx] = Op::InitThunk(jptr as i32); + ops.replace(idx, Op::InitThunk(jptr as i32)); } // Insert a placeholder Opcode until we know jptr for the // module. - ops.push(Op::Noop); + ops.push(Op::Noop, def.pos.clone()); let idx = ops.len() - 1; // Bind our mod tuple. - ops.push(Op::Bind); + ops.push(Op::Bind, def.pos.clone()); // emit all of our statements; Self::translate_stmts(stmts, &mut ops, root); // Return from the module - ops.push(Op::Return); + ops.push(Op::Return, def.pos); let jptr = ops.len() - idx - 1; - ops[idx] = Op::Module(jptr as i32); + ops.replace(idx, Op::Module(jptr as i32)); } Expression::Not(def) => { Self::translate_expr(*def.expr, &mut ops, root); - ops.push(Op::Not); + ops.push(Op::Not, def.pos); } Expression::Range(def) => { Self::translate_expr(*def.end, &mut ops, root); if let Some(expr) = def.step { Self::translate_expr(*expr, &mut ops, root); } else { - ops.push(Op::Val(Primitive::Empty)); + ops.push(Op::Val(Primitive::Empty), def.pos.clone()); } Self::translate_expr(*def.start, &mut ops, root); - ops.push(Op::Runtime(Hook::Range)); + ops.push(Op::Runtime(Hook::Range), def.pos); } Expression::Select(def) => { Self::translate_expr(*def.val, &mut ops, root); let mut jumps = Vec::new(); for (key, val) in def.tuple { - ops.push(Op::Sym(key.fragment)); - ops.push(Op::Noop); + ops.push(Op::Sym(key.fragment), key.pos.clone()); + ops.push(Op::Noop, key.pos); let idx = ops.len() - 1; + let expr_pos = val.pos().clone(); Self::translate_expr(val, &mut ops, root); - ops.push(Op::Noop); + ops.push(Op::Noop, expr_pos); jumps.push(ops.len() - 1); let jptr = ops.len() - idx - 1; - ops[idx] = Op::SelectJump(jptr as i32); + ops.replace(idx, Op::SelectJump(jptr as i32)); } - ops.push(Op::Pop); + ops.push(Op::Pop, def.pos.clone()); let end = ops.len() - 1; for i in jumps { let idx = end - i; - ops[i] = Op::Jump(idx as i32); + ops.replace(i, Op::Jump(idx as i32)); } if let Some(default) = def.default { Self::translate_expr(*default, &mut ops, root); } else { - ops.push(Op::Bang); + ops.push(Op::Bang, def.pos); } - dbg!(&ops); } Expression::Call(def) => { // first push our arguments. @@ -396,19 +433,19 @@ impl AST { Self::translate_expr(e, &mut ops, root); } // then push the func reference + let func_pos = def.funcref.pos().clone(); Self::translate_value(def.funcref, &mut ops, root); - ops.push(Op::FCall); - dbg!(ops); + ops.push(Op::FCall, func_pos); } Expression::Copy(def) => { - ops.push(Op::InitTuple); + ops.push(Op::InitTuple, def.pos.clone()); for (t, e) in def.fields { - ops.push(Op::Sym(t.fragment)); + ops.push(Op::Sym(t.fragment), t.pos.clone()); Self::translate_expr(e, &mut ops, root); - ops.push(Op::Field); + ops.push(Op::Field, t.pos.clone()); } Self::translate_value(def.selector, &mut ops, root); - ops.push(Op::Cp); + ops.push(Op::Cp, def.pos); } Expression::Debug(def) => { let mut buffer: Vec = Vec::new(); @@ -417,23 +454,24 @@ impl AST { let _ = printer.render_expr(&def.expr); } let expr_pretty = String::from_utf8(buffer).unwrap(); - ops.push(Op::Val(Primitive::Str(expr_pretty))); + ops.push(Op::Val(Primitive::Str(expr_pretty)), def.pos.clone()); Self::translate_expr(*def.expr, &mut ops, root); - ops.push(Op::Runtime(Hook::Trace(def.pos))); + ops.push(Op::Runtime(Hook::Trace(def.pos.clone())), def.pos); } } } fn translate_template_part>( + pos: Position, part: TemplatePart, elems: &mut EI, - mut ops: &mut Vec, + mut ops: &mut PositionMap, place_holder: bool, root: &Path, ) { match part { TemplatePart::Str(s) => { - ops.push(Op::Val(Primitive::Str(s.into_iter().collect()))); + ops.push(Op::Val(Primitive::Str(s.into_iter().collect())), pos); } TemplatePart::PlaceHolder(_idx) => { if !place_holder { @@ -441,7 +479,7 @@ impl AST { unreachable!(); } else { Self::translate_expr(elems.next().unwrap(), &mut ops, root); - ops.push(Op::Render); + ops.push(Op::Render, pos); } } TemplatePart::Expression(expr) => { @@ -449,35 +487,36 @@ impl AST { unreachable!(); } else { Self::translate_expr(expr, &mut ops, root); - ops.push(Op::Render); + ops.push(Op::Render, pos); } } } } - fn translate_value(value: Value, mut ops: &mut Vec, root: &Path) { + fn translate_value(value: Value, mut ops: &mut PositionMap, root: &Path) { match value { - Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))), - Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))), - Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))), - Value::Empty(_pos) => ops.push(Op::Val(Primitive::Empty)), - Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val))), + Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val)), i.pos), + Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val)), f.pos), + Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val)), s.pos), + Value::Empty(pos) => ops.push(Op::Val(Primitive::Empty), pos), + Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val)), b.pos), Value::Symbol(s) => { - ops.push(Op::DeRef(s.val)); + ops.push(Op::DeRef(s.val), s.pos); } Value::Tuple(flds) => { - ops.push(Op::InitTuple); + ops.push(Op::InitTuple, flds.pos); for (k, v) in flds.val { - ops.push(Op::Sym(k.fragment)); + ops.push(Op::Sym(k.fragment), k.pos.clone()); Self::translate_expr(v, &mut ops, root); - ops.push(Op::Field); + ops.push(Op::Field, k.pos.clone()); } } Value::List(els) => { - ops.push(Op::InitList); + ops.push(Op::InitList, els.pos); for el in els.elems { + let el_pos = el.pos().clone(); Self::translate_expr(el, &mut ops, root); - ops.push(Op::Element); + ops.push(Op::Element, el_pos); } } } diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index f54151d..e552742 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -15,10 +15,13 @@ use std::cell::RefCell; use std::path::PathBuf; use std::rc::Rc; +use crate::ast::Position; + use super::environment::Environment; use super::pointer::OpPointer; use super::runtime; use super::scope::Stack; +use super::translate::PositionMap; use super::Composite::{List, Tuple}; use super::Hook; use super::Primitive::{Bool, Empty, Float, Int, Str}; @@ -43,7 +46,7 @@ where O: std::io::Write, E: std::io::Write, { - pub fn new(ops: Rc>, env: Rc>>) -> Self { + pub fn new(ops: Rc, env: Rc>>) -> Self { Self::with_pointer(OpPointer::new(ops), env) } @@ -79,38 +82,39 @@ where pub fn run(&mut self) -> Result<(), Error> { loop { - let op = if let Some(op) = self.ops.next() { + let op = if let Some(op) = dbg!(self.ops.next()) { op.clone() } else { break; }; + 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::DeRef(s) => self.op_deref(s.clone())?, - Op::Add => self.op_add()?, - Op::Mod => self.op_mod()?, - Op::Sub => self.op_sub()?, - Op::Mul => self.op_mul()?, - Op::Div => self.op_div()?, - Op::Bind => self.op_bind(true)?, - Op::BindOver => self.op_bind(false)?, + 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::Not => self.op_not()?, - Op::Gt => self.op_gt()?, - Op::Lt => self.op_lt()?, - Op::GtEq => self.op_gteq()?, - Op::LtEq => self.op_lteq()?, + 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)?, // Add a Composite list value to the stack Op::InitList => self.push(Rc::new(C(List(Vec::new()))))?, // Add a composite tuple value to the stack Op::InitTuple => self.push(Rc::new(C(Tuple(Vec::new()))))?, Op::Field => self.op_field()?, Op::Element => self.op_element()?, - Op::Index => self.op_index(false)?, - Op::SafeIndex => self.op_index(true)?, - Op::Cp => self.op_copy()?, + 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)?, @@ -118,14 +122,14 @@ where // Do nothing } Op::Jump(jp) => self.op_jump(jp)?, - Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?, - Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?, + Op::JumpIfTrue(jp) => self.op_jump_if_true(jp, &pos)?, + Op::JumpIfFalse(jp) => self.op_jump_if_false(jp, &pos)?, Op::SelectJump(jp) => self.op_select_jump(jp)?, - Op::And(jp) => self.op_and(jp)?, - Op::Or(jp) => self.op_or(jp)?, - Op::Module(mptr) => self.op_module(idx, mptr)?, - Op::Func(jptr) => self.op_func(idx, jptr)?, - Op::FCall => self.op_fcall()?, + 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); @@ -135,7 +139,7 @@ where self.pop()?; } Op::Typ => self.op_typ()?, - Op::Runtime(h) => self.op_runtime(h)?, + Op::Runtime(h) => self.op_runtime(h, &pos)?, Op::Render => self.op_render()?, }; } @@ -154,17 +158,16 @@ where C(List(_)) => "list", F(_) => "func", M(_) => "module", - S(_) | T(_) => { - return Err(dbg!(Error {})); - } + S(_) => "sym", + T(_) => "thunk", } .to_owned(); self.push(Rc::new(P(Str(typ_name))))?; Ok(()) } - fn op_deref(&mut self, name: String) -> Result<(), Error> { - let val = self.get_binding(&name)?.clone(); + fn op_deref(&mut self, name: String, pos: &Position) -> Result<(), Error> { + let val = self.get_binding(&name, pos)?.clone(); self.push(val) } @@ -178,7 +181,7 @@ where Ok(()) } - fn op_and(&mut self, jp: i32) -> Result<(), Error> { + fn op_and(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { let cond = self.pop()?; let cc = cond.clone(); if let &P(Bool(cond)) = cond.as_ref() { @@ -187,41 +190,57 @@ where self.op_jump(jp)?; } } else { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Not a boolean condition {:?} in && expression!", cond), + pos.clone(), + ))); } Ok(()) } - fn op_or(&mut self, jp: i32) -> Result<(), Error> { + fn op_or(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { let cond = self.pop()?; - let cc = cond.clone(); + let cc = dbg!(cond.clone()); if let &P(Bool(cond)) = cond.as_ref() { - if cond { + if dbg!(cond) { self.push(cc)?; self.op_jump(jp)?; } + } else { + return Err(dbg!(Error::new( + format!("Not a boolean condition {:?} in || expression!", cond), + pos.clone(), + ))); } Ok(()) } - fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> { + fn op_jump_if_true(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { let cond = self.pop()?; if let &P(Bool(cond)) = cond.as_ref() { if cond { self.op_jump(jp)?; } } else { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Expected boolean but got {:?}!", cond), + pos.clone(), + ))); } Ok(()) } - fn op_jump_if_false(&mut self, jp: i32) -> Result<(), Error> { + fn op_jump_if_false(&mut self, jp: i32, pos: &Position) -> Result<(), Error> { let cond = self.pop()?; if let &P(Bool(cond)) = cond.as_ref() { if !cond { self.op_jump(jp)?; } + } else { + return Err(dbg!(Error::new( + format!("Expected boolean but got {:?}!", cond), + pos.clone(), + ))); } Ok(()) } @@ -244,7 +263,7 @@ where Ok(()) } - fn op_module(&'a mut self, idx: usize, jptr: i32) -> Result<(), Error> { + fn op_module(&'a mut self, idx: usize, jptr: i32, pos: &Position) -> Result<(), Error> { let mod_val = dbg!(self.pop())?; let (result_ptr, flds) = match mod_val.as_ref() { &C(Tuple(ref flds)) => (None, flds.clone()), @@ -253,14 +272,21 @@ where if let &C(Tuple(ref flds)) = tpl_val.as_ref() { (Some(ptr), flds.clone()) } else { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Expected tuple but got {:?}", tpl_val), + pos.clone(), + ))); } } _ => { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Expected tuple but got {:?}", mod_val), + pos.clone(), + ))); } }; let mut ops = self.ops.clone(); + let pkg_pos = self.ops.pos().unwrap().clone(); ops.jump(idx)?; let pkg_ptr = if let Some(ref path) = self.ops.path { let pkg_ops = vec![ @@ -270,7 +296,17 @@ where Op::Runtime(Hook::Import), Op::Return, ]; - Some(OpPointer::new(Rc::new(pkg_ops))) + let pos_list = vec![ + pkg_pos.clone(), + pkg_pos.clone(), + pkg_pos.clone(), + pkg_pos.clone(), + pkg_pos.clone(), + ]; + Some(OpPointer::new(Rc::new(PositionMap { + ops: pkg_ops, + pos: pos_list, + }))) } else { None }; @@ -283,7 +319,7 @@ where self.op_jump(jptr) } - fn op_func(&mut self, idx: usize, jptr: i32) -> 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(); @@ -297,13 +333,18 @@ where if let &S(ref sym) = e.as_ref() { bindings.push(sym.clone()); } else { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Not an argument name {:?}", e), + pos.clone(), + ))); } } } else { - return dbg!(Err(Error {})); + return dbg!(Err(Error::new( + format!("Fault!!! Bad Argument List"), + pos.clone(), + ))); } - eprintln!("Pushing function definition on stack"); let mut ops = self.ops.clone(); ops.jump(idx)?; self.push(Rc::new(F(Func { @@ -319,6 +360,7 @@ where f: &Func, stack: &mut Vec>, env: Rc>>, + pos: &Position, ) -> Result, Error> { let Func { ref ptr, @@ -332,7 +374,7 @@ where // 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)?; + vm.binding_push(nm.clone(), val, false, pos)?; } // proceed to the function body vm.run()?; @@ -351,10 +393,10 @@ where Ok(()) } - fn op_fcall(&mut self) -> Result<(), Error> { + 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())?; + let val = Self::fcall_impl(f, &mut self.stack, self.env.clone(), pos)?; self.push(dbg!(val))?; } Ok(()) @@ -365,13 +407,16 @@ where self.op_jump(jp) } - fn op_not(&mut self) -> Result<(), Error> { + fn op_not(&mut self, pos: &Position) -> Result<(), Error> { let operand = self.pop()?; if let P(Bool(val)) = operand.as_ref() { self.push(Rc::new(P(Bool(!val))))?; return Ok(()); } - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Expected Boolean but got {:?}", operand), + pos.clone(), + ))); } fn op_equal(&mut self) -> Result<(), Error> { @@ -381,7 +426,7 @@ where Ok(()) } - fn op_gt(&mut self) -> Result<(), Error> { + fn op_gt(&mut self, pos: &Position) -> Result<(), Error> { let left = self.pop()?; let right = self.pop()?; match (left.as_ref(), right.as_ref()) { @@ -391,12 +436,17 @@ where (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f > ff))))?; } - _ => return Err(dbg!(Error {})), + _ => { + return Err(dbg!(Error::new( + format!("Expected Numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))); + }, } Ok(()) } - fn op_lt(&mut self) -> Result<(), Error> { + fn op_lt(&mut self, pos: &Position) -> Result<(), Error> { let left = self.pop()?; let right = self.pop()?; match (left.as_ref(), right.as_ref()) { @@ -406,12 +456,17 @@ where (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f < ff))))?; } - _ => return Err(dbg!(Error {})), + _ => { + return Err(dbg!(Error::new( + format!("Expected Numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))); + }, } Ok(()) } - fn op_lteq(&mut self) -> Result<(), Error> { + fn op_lteq(&mut self, pos: &Position) -> Result<(), Error> { let left = self.pop()?; let right = self.pop()?; match (left.as_ref(), right.as_ref()) { @@ -421,12 +476,17 @@ where (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f <= ff))))?; } - _ => return Err(dbg!(Error {})), + _ => { + return Err(dbg!(Error::new( + format!("Expected Numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))); + }, } Ok(()) } - fn op_gteq(&mut self) -> Result<(), Error> { + fn op_gteq(&mut self, pos: &Position) -> Result<(), Error> { let left = self.pop()?; let right = self.pop()?; match (left.as_ref(), right.as_ref()) { @@ -436,65 +496,70 @@ where (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f >= ff))))?; } - _ => return Err(dbg!(Error {})), + _ => { + return Err(dbg!(Error::new( + format!("Expected Numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))); + }, } Ok(()) } - fn op_mod(&mut self) -> 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()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.modulus(&left, &right)?)))?; + self.push(Rc::new(P(self.modulus(&left, &right, pos)?)))?; Ok(()) } - fn op_add(&mut self) -> 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()?; // Then pushes the result onto the stack. - self.push(Rc::new(self.add(&left, &right)?))?; + self.push(Rc::new(self.add(&left, &right, pos)?))?; Ok(()) } - fn op_sub(&mut self) -> 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()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.sub(&left, &right)?)))?; + self.push(Rc::new(P(self.sub(&left, &right, pos)?)))?; Ok(()) } - fn op_mul(&mut self) -> 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()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.mul(&left, &right)?)))?; + self.push(Rc::new(P(self.mul(&left, &right, pos)?)))?; Ok(()) } - fn op_div(&mut self) -> 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()?; // Then pushes the result onto the stack. - self.push(Rc::new(P(self.div(&left, &right)?)))?; + self.push(Rc::new(P(self.div(&left, &right, pos)?)))?; Ok(()) } - fn op_bind(&mut self, strict: bool) -> Result<(), Error> { + fn op_bind(&mut self, strict: bool, pos: &Position) -> Result<(), Error> { // pop val off stack. let val = self.pop()?; // pop name off stack. let name = self.pop()?; if let &S(ref name) = name.as_ref() { - self.binding_push(name.clone(), val, strict)?; + self.binding_push(name.clone(), val, strict, pos)?; } else { - return Err(dbg!(Error {})); + unreachable!(); } Ok(()) } @@ -508,7 +573,7 @@ where let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() { s } else { - return Err(dbg!(Error {})); + unreachable!(); }; // get composite tuple from stack let tpl = self.pop()?; @@ -519,7 +584,7 @@ where // place composite tuple back on stack self.push(Rc::new(C(Tuple(flds))))?; } else { - return Err(dbg!(Error {})); + unreachable!(); }; Ok(()) } @@ -536,19 +601,25 @@ where // Add that value to the list and put list back on stack. self.push(Rc::new(C(List(elems))))?; } else { - return Err(dbg!(Error {})); + unreachable!(); }; Ok(()) } - fn find_in_list(&self, index: &Value, elems: &Vec>) -> Result, Error> { + fn find_in_list(&self, index: &Value, elems: &Vec>, pos: &Position) -> Result, Error> { let idx = match index { P(Int(i)) => i.clone(), - _ => return dbg!(Err(Error {})), + _ => return Err(dbg!(Error::new( + format!("Expected int for index but got {:?}", index), + pos.clone(), + ))), }; match elems.get(idx as usize) { Some(v) => Ok(v.clone()), - None => Err(dbg!(Error {})), + None => return Err(dbg!(Error::new( + format!("No such index {}", idx), + pos.clone(), + ))), } } @@ -556,25 +627,35 @@ where &self, index: &Value, flds: &Vec<(String, Rc)>, + pos: &Position, ) -> Result, Error> { let idx = match index { S(p) => p, P(Str(p)) => p, - _ => return dbg!(Err(Error {})), + _ => return Err(dbg!(Error::new( + format!("Expected String or Symbol for index but got {:?}", index), + pos.clone(), + ))), }; for f in flds.iter() { if idx == &f.0 { return Ok(f.1.clone()); } } - Err(dbg!(Error {})) + Err(dbg!(Error::new( + format!("No such field {}", idx), + pos.clone() + ))) } - fn find_in_value(&self, index: &Value, target: &Value) -> Result, Error> { + fn find_in_value(&self, index: &Value, target: &Value, pos: &Position) -> Result, Error> { match target { - C(Tuple(flds)) => self.find_in_flds(index, flds), - C(List(elements)) => self.find_in_list(index, elements), - _ => return Err(dbg!(Error {})), + C(Tuple(flds)) => self.find_in_flds(index, flds, pos), + C(List(elements)) => self.find_in_list(index, elements, pos), + _ => return Err(dbg!(Error::new( + format!("Expected tuple for list but got {:?}", target), + pos.clone(), + ))), } } @@ -582,7 +663,7 @@ where Ok(()) } - fn op_index(&mut self, safe: bool) -> 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()?); @@ -613,10 +694,13 @@ where self.push(Rc::new(P(Empty)))?; return Ok(()); } - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Invalid selector index: {:?} target: {:?}", right, left), + pos.clone(), + ))); } - fn op_copy(&mut self) -> 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()?); // This value should always be a tuple @@ -624,7 +708,7 @@ where let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { oflds.clone() } else { - return Err(dbg!(Error {})); + unreachable!(); }; match tgt.as_ref() { &C(Tuple(ref flds)) => { @@ -674,7 +758,10 @@ where } } _ => { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Expected a Tuple or a Module but got {:?}", tgt), + pos.clone(), + ))); } } Ok(()) @@ -706,61 +793,80 @@ where name: String, val: Rc, strict: bool, + pos: &Position, ) -> Result<(), Error> { if self.symbols.is_bound(&name) && strict { - return Err(dbg!(Error {})); + return Err(dbg!(Error::new( + format!("Binding {} already exists", name), + pos.clone(), + ))); } self.symbols.add(name, val); Ok(()) } - pub fn get_binding(&'a self, name: &str) -> Result, Error> { + pub fn get_binding(&'a self, name: &str, pos: &Position) -> Result, Error> { match self.symbols.get(name) { Some(v) => Ok(v), - None => Err(dbg!(Error {})), + None => Err(dbg!(Error::new( + format!("No such binding {}", name), + pos.clone() + ))), } } pub fn pop(&mut self) -> Result, Error> { match self.stack.pop() { Some(v) => Ok(v), - None => Err(dbg!(Error {})), + None => unreachable!(), } } - fn mul(&self, left: &Value, right: &Value) -> Result { + fn mul(&self, left: &Value, right: &Value, pos: &Position) -> Result { Ok(match (left, right) { (P(Int(i)), P(Int(ii))) => Int(i * ii), (P(Float(f)), P(Float(ff))) => Float(f * ff), - _ => return Err(dbg!(Error {})), + _ => return Err(dbg!(Error::new( + format!("Expected numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))), }) } - fn div(&self, left: &Value, right: &Value) -> Result { + fn div(&self, left: &Value, right: &Value, pos: &Position) -> Result { Ok(match (left, right) { (P(Int(i)), P(Int(ii))) => Int(i / ii), (P(Float(f)), P(Float(ff))) => Float(f / ff), - _ => return Err(dbg!(Error {})), + _ => return Err(dbg!(Error::new( + format!("Expected numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))), }) } - fn sub(&self, left: &Value, right: &Value) -> Result { + fn sub(&self, left: &Value, right: &Value, pos: &Position) -> Result { Ok(match (left, right) { (P(Int(i)), Value::P(Int(ii))) => Int(i - ii), (P(Float(f)), Value::P(Float(ff))) => Float(f - ff), - _ => return Err(dbg!(Error {})), + _ => return Err(dbg!(Error::new( + format!("Expected numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))), }) } - fn modulus(&self, left: &Value, right: &Value) -> Result { + fn modulus(&self, left: &Value, right: &Value, pos: &Position) -> Result { Ok(match (left, right) { (P(Int(i)), Value::P(Int(ii))) => Int(i % ii), (P(Float(f)), Value::P(Float(ff))) => Float(f % ff), - _ => return Err(dbg!(Error {})), + _ => return Err(dbg!(Error::new( + format!("Expected numeric values of the same type but got {:?} and {:?}", left, right), + pos.clone(), + ))), }) } - fn add(&self, left: &Value, right: &Value) -> Result { + fn add(&self, left: &Value, right: &Value, pos: &Position) -> Result { Ok(match (left, right) { (P(Int(i)), Value::P(Int(ii))) => P(Int(i + ii)), (P(Float(f)), Value::P(Float(ff))) => P(Float(f + ff)), @@ -780,13 +886,16 @@ where } C(List(new_list)) } - _ => return Err(dbg!(Error {})), + _ => return Err(dbg!(Error::new( + format!("You can not add {:?} and {:?}", left, right), + pos.clone() + ))), }) } - fn op_runtime(&mut self, h: Hook) -> Result<(), Error> { + fn op_runtime(&mut self, h: Hook, pos: &Position) -> Result<(), Error> { self.runtime - .handle(self.ops.path.as_ref(), h, &mut self.stack, self.env.clone()) + .handle(self.ops.path.as_ref(), h, &mut self.stack, self.env.clone(), pos) } fn op_render(&mut self) -> Result<(), Error> {