DEV: The great Error message explosion.

This commit is contained in:
Jeremy Wall 2019-08-18 08:40:30 -05:00
parent 7a2a99b859
commit 33a5694aad
9 changed files with 596 additions and 316 deletions

View File

@ -16,11 +16,12 @@ use std::collections::BTreeMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use super::{Op, OpPointer}; use super::translate::PositionMap;
use super::OpPointer;
/// A Cache of Op codes. /// A Cache of Op codes.
pub struct Ops { pub struct Ops {
ops: BTreeMap<String, Rc<Vec<Op>>>, ops: BTreeMap<String, Rc<PositionMap>>,
} }
impl Ops { impl Ops {
@ -35,10 +36,10 @@ impl Ops {
} }
} }
pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<Vec<Op>>>); pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<PositionMap>>);
impl<'a> Entry<'a> { impl<'a> Entry<'a> {
pub fn get_pointer_or_else<F: FnOnce() -> Vec<Op>, P: Into<PathBuf>>( pub fn get_pointer_or_else<F: FnOnce() -> PositionMap, P: Into<PathBuf>>(
self, self,
f: F, f: F,
path: P, path: P,

View File

@ -13,8 +13,22 @@
// limitations under the License. // limitations under the License.
use std::convert::From; use std::convert::From;
use crate::ast::Position;
#[derive(Debug)] #[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<E> From<E> for Error impl<E> From<E> for Error
where where
@ -22,6 +36,9 @@ where
{ {
fn from(_e: E) -> Self { fn from(_e: E) -> Self {
// FIXME(jwall): This should really have more information for debugging // FIXME(jwall): This should really have more information for debugging
Error {} Error {
message: _e.description().to_owned(),
pos: Position::new(0, 0, 0),
}
} }
} }

View File

@ -250,7 +250,9 @@ impl TryFrom<&Value> for Val {
Val::List(els) Val::List(els)
} }
S(_) | F(_) | M(_) | T(_) => { 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 // TODO(jwall): These can go away eventually when we replace the tree
// walking interpreter. // 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)))),
}) })
} }
} }

View File

@ -14,20 +14,23 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use crate::ast::Position;
use super::translate::PositionMap;
use super::{Error, Op}; use super::{Error, Op};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct OpPointer { pub struct OpPointer {
pub ops: Rc<Vec<Op>>, pub pos_map: Rc<PositionMap>,
pub ptr: Option<usize>, pub ptr: Option<usize>,
pub path: Option<PathBuf>, pub path: Option<PathBuf>,
} }
impl OpPointer { impl OpPointer {
pub fn new(ops: Rc<Vec<Op>>) -> Self { pub fn new(ops: Rc<PositionMap>) -> Self {
// If we load an empty program what happens? // If we load an empty program what happens?
Self { Self {
ops: ops, pos_map: ops,
ptr: None, ptr: None,
path: None, path: None,
} }
@ -41,28 +44,41 @@ impl OpPointer {
pub fn next(&mut self) -> Option<&Op> { pub fn next(&mut self) -> Option<&Op> {
if let Some(i) = self.ptr { if let Some(i) = self.ptr {
let nxt = i + 1; let nxt = i + 1;
if nxt < self.ops.len() { if nxt < self.pos_map.len() {
self.ptr = Some(nxt); self.ptr = Some(nxt);
} else { } else {
return None; return None;
} }
} else if self.ops.len() != 0 { } else if self.pos_map.len() != 0 {
self.ptr = Some(0); self.ptr = Some(0);
} }
self.op() self.op()
} }
pub fn jump(&mut self, ptr: usize) -> Result<(), Error> { pub fn jump(&mut self, ptr: usize) -> Result<(), Error> {
if ptr < self.ops.len() { if ptr < self.pos_map.len() {
self.ptr = Some(ptr); self.ptr = Some(ptr);
return Ok(()); 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> { pub fn op(&self) -> Option<&Op> {
if let Some(i) = self.ptr { 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 None
} }
@ -70,13 +86,16 @@ impl OpPointer {
pub fn idx(&self) -> Result<usize, Error> { pub fn idx(&self) -> Result<usize, Error> {
match self.ptr { match self.ptr {
Some(ptr) => Ok(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 { pub fn snapshot(&self) -> Self {
Self { Self {
ops: self.ops.clone(), pos_map: self.pos_map.clone(),
ptr: None, ptr: None,
path: self.path.clone(), path: self.path.clone(),
} }

View File

@ -21,8 +21,7 @@ use std::rc::Rc;
use regex::Regex; use regex::Regex;
use super::environment::Environment; use super::environment::Environment;
use super::pointer::OpPointer; use super::Value::{C, F, P};
use super::Value::{C, F, P, S};
use super::VM; use super::VM;
use super::{Composite, Error, Hook, Primitive, Value}; use super::{Composite, Error, Hook, Primitive, Value};
use crate::ast::Position; use crate::ast::Position;
@ -66,22 +65,23 @@ impl Builtins {
h: Hook, h: Hook,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
E: std::io::Write, E: std::io::Write,
{ {
match h { match h {
Hook::Import => self.import(stack, env), Hook::Import => self.import(stack, env, pos),
Hook::Include => self.include(stack, env), Hook::Include => self.include(stack, env, pos),
Hook::Assert => self.assert(stack), Hook::Assert => self.assert(stack),
Hook::Convert => self.convert(stack, env), Hook::Convert => self.convert(stack, env, pos),
Hook::Out => self.out(path, stack, env), Hook::Out => self.out(path, stack, env, pos),
Hook::Map => self.map(stack, env), Hook::Map => self.map(stack, env, pos),
Hook::Filter => self.filter(stack, env), Hook::Filter => self.filter(stack, env, pos),
Hook::Reduce => self.reduce(stack, env), Hook::Reduce => self.reduce(stack, env, pos),
Hook::Regex => self.regex(stack), Hook::Regex => self.regex(stack, pos),
Hook::Range => self.range(stack), Hook::Range => self.range(stack, pos),
Hook::Trace(pos) => self.trace(stack, pos, env), Hook::Trace(pos) => self.trace(stack, pos, env),
} }
} }
@ -90,6 +90,7 @@ impl Builtins {
&self, &self,
path: P, path: P,
use_import_path: bool, use_import_path: bool,
pos: &Position,
) -> Result<PathBuf, Error> { ) -> Result<PathBuf, Error> {
// Try a relative path first. // Try a relative path first.
let path = path.into(); let path = path.into();
@ -114,22 +115,22 @@ impl Builtins {
} }
match normalized.canonicalize() { match normalized.canonicalize() {
Ok(p) => Ok(p), 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<String, Error> { fn get_file_as_string(&self, path: &str, pos: &Position) -> Result<String, Error> {
let sep = format!("{}", std::path::MAIN_SEPARATOR); let sep = format!("{}", std::path::MAIN_SEPARATOR);
let raw_path = path.replace("/", &sep); let raw_path = path.replace("/", &sep);
let normalized = match self.find_file(raw_path, false) { let normalized = self.find_file(raw_path, false, pos)?;
Ok(p) => p, // TODO(jwall): Proper error here
Err(_e) => { let mut f = File::open(normalized)?;
return Err(dbg!(Error {}));
}
};
let mut f = File::open(normalized).unwrap();
let mut contents = String::new(); 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) Ok(contents)
} }
@ -137,6 +138,7 @@ impl Builtins {
&mut self, &mut self,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
@ -176,14 +178,19 @@ impl Builtins {
} }
return Ok(()); return Ok(());
} }
return Err(dbg!(Error::new(
format!("Invalid Path {:?}", val),
pos.clone(),
)));
} }
return Err(dbg!(Error {})); unreachable!();
} }
fn include<O, E>( fn include<O, E>(
&self, &self,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
@ -195,42 +202,55 @@ impl Builtins {
if let &Value::P(Str(ref path)) = val.as_ref() { if let &Value::P(Str(ref path)) = val.as_ref() {
path.clone() path.clone()
} else { } else {
return Err(dbg!(Error {})); return Err(dbg!(Error::new(
format!("Invalid Path {:?}", val),
pos.clone(),
)));
} }
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
let typ = if let Some(val) = typ.as_ref() { let typ = if let Some(val) = typ.as_ref() {
if let &Value::P(Str(ref typ)) = val.as_ref() { if let &Value::P(Str(ref typ)) = val.as_ref() {
typ.clone() typ.clone()
} else { } else {
return Err(dbg!(Error {})); return Err(dbg!(Error::new(
format!("Expected conversion type but got {:?}", typ),
pos.clone(),
)));
} }
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
if typ == "str" { 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 { } else {
stack.push(Rc::new( stack.push(Rc::new(
match env.borrow().importer_registry.get_importer(&typ) { match env.borrow().importer_registry.get_importer(&typ) {
Some(importer) => { Some(importer) => {
let contents = self.get_file_as_string(&path)?; let contents = self.get_file_as_string(&path, pos)?;
if contents.len() == 0 { if contents.len() == 0 {
eprintln!("including an empty file. Use NULL as the result"); eprintln!("including an empty file. Use NULL as the result");
P(Empty) P(Empty)
} else { } else {
match importer.import(contents.as_bytes()) { match importer.import(contents.as_bytes()) {
Ok(v) => v.try_into()?, 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<Rc<Value>>) -> Result<(), Error> { fn assert(&mut self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> {
@ -272,15 +292,16 @@ impl Builtins {
path: Option<P>, path: Option<P>,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
E: std::io::Write, E: std::io::Write,
{ {
let path = if let Some(path) = path { let mut writer: Box<dyn std::io::Write> = if let Some(path) = path {
path Box::new(File::create(path)?)
} else { } else {
return Err(dbg!(Error {})); Box::new(std::io::stdout())
}; };
let val = stack.pop(); let val = stack.pop();
if let Some(val) = val { if let Some(val) = val {
@ -288,24 +309,31 @@ impl Builtins {
if let Some(c_type_val) = stack.pop() { if let Some(c_type_val) = stack.pop() {
if let &Value::S(ref c_type) = c_type_val.as_ref() { 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 Some(c) = env.borrow().converter_registry.get_converter(c_type) {
match c.convert(Rc::new(val), &mut File::create(path)?) { if let Err(e) = c.convert(Rc::new(val), &mut writer) {
Ok(_) => { return Err(dbg!(Error::new(format!("{}", e), pos.clone(),)));
// noop
}
Err(_e) => return Err(dbg!(Error {})),
} }
return Ok(()); 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<O, E>( fn convert<O, E>(
&self, &self,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
@ -325,20 +353,30 @@ impl Builtins {
String::from_utf8_lossy(buf.as_slice()).to_string() 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 Ok(());
} }
} }
} }
return Err(dbg!(Error::new(
format!("Not a conversion type {:?}", val),
pos.clone()
)));
} }
return Err(dbg!(Error {})); unreachable!()
} }
fn map<O, E>( fn map<O, E>(
&self, &self,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
@ -348,19 +386,19 @@ impl Builtins {
let list = if let Some(list) = stack.pop() { let list = if let Some(list) = stack.pop() {
list list
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
// get the func ptr from the stack // get the func ptr from the stack
let fptr = if let Some(ptr) = stack.pop() { let fptr = if let Some(ptr) = stack.pop() {
ptr ptr
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
let f = if let &F(ref f) = fptr.as_ref() { let f = if let &F(ref f) = fptr.as_ref() {
f f
} else { } else {
return Err(dbg!(Error {})); return Err(dbg!(Error::new(format!("Not a function!!"), pos.clone(),)));
}; };
match list.as_ref() { match list.as_ref() {
@ -370,7 +408,7 @@ impl Builtins {
// push function argument on the stack. // push function argument on the stack.
stack.push(e.clone()); stack.push(e.clone());
// call function and push it's result on the stack. // 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)))); stack.push(Rc::new(C(List(result_elems))));
} }
@ -379,15 +417,23 @@ impl Builtins {
for (ref name, ref val) in _flds { for (ref name, ref val) in _flds {
stack.push(val.clone()); stack.push(val.clone());
stack.push(Rc::new(P(Str(name.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() { if let &C(List(ref fval)) = result.as_ref() {
// we expect them to be a list of exactly 2 items. // we expect them to be a list of exactly 2 items.
if fval.len() != 2 { 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() { let name = match fval[0].as_ref() {
&P(Str(ref name)) => name.clone(), &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())); new_fields.push((name, fval[1].clone()));
} }
@ -399,16 +445,24 @@ impl Builtins {
for c in s.chars() { for c in s.chars() {
stack.push(Rc::new(P(Str(c.to_string())))); stack.push(Rc::new(P(Str(c.to_string()))));
// call function and push it's result on the stack. // 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() { if let &P(Str(ref s)) = result.as_ref() {
buf.push_str(s); buf.push_str(s);
} else { } 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)))); 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(()) Ok(())
} }
@ -417,6 +471,7 @@ impl Builtins {
&self, &self,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
@ -426,29 +481,29 @@ impl Builtins {
let list = if let Some(list) = stack.pop() { let list = if let Some(list) = stack.pop() {
list list
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
// get the func ptr from the stack // get the func ptr from the stack
let fptr = if let Some(ptr) = stack.pop() { let fptr = if let Some(ptr) = stack.pop() {
ptr ptr
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
let f = if let &F(ref f) = fptr.as_ref() { let f = if let &F(ref f) = fptr.as_ref() {
f f
} else { } 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)) => { &C(List(ref elems)) => {
let mut result_elems = Vec::new(); let mut result_elems = Vec::new();
for e in elems.iter() { for e in elems.iter() {
// push function argument on the stack. // push function argument on the stack.
stack.push(e.clone()); stack.push(e.clone());
// call function and push it's result on the stack. // 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 // Check for empty or boolean results and only push e back in
// if they are non empty and true // if they are non empty and true
match condition.as_ref() { match condition.as_ref() {
@ -465,7 +520,7 @@ impl Builtins {
for (ref name, ref val) in _flds { for (ref name, ref val) in _flds {
stack.push(val.clone()); stack.push(val.clone());
stack.push(Rc::new(P(Str(name.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 // Check for empty or boolean results and only push e back in
// if they are non empty and true // if they are non empty and true
match condition.as_ref() { match condition.as_ref() {
@ -482,7 +537,7 @@ impl Builtins {
for c in s.chars() { for c in s.chars() {
stack.push(Rc::new(P(Str(c.to_string())))); stack.push(Rc::new(P(Str(c.to_string()))));
// call function and push it's result on the stack. // 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 // Check for empty or boolean results and only push c back in
// if they are non empty and true // if they are non empty and true
match condition.as_ref() { match condition.as_ref() {
@ -494,21 +549,29 @@ impl Builtins {
} }
stack.push(Rc::new(P(Str(buf)))); 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(()) Ok(())
} }
fn regex(&self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> { fn regex(&self, stack: &mut Vec<Rc<Value>>, pos: &Position) -> Result<(), Error> {
// 1. get left side (string) // 1. get left side (string)
let left_str = if let Some(val) = stack.pop() { let left_str = if let Some(val) = stack.pop() {
if let &P(Str(ref s)) = val.as_ref() { if let &P(Str(ref s)) = val.as_ref() {
s.clone() s.clone()
} else { } else {
return dbg!(Err(Error {})); return dbg!(Err(Error::new(
format!("Expected string bug got {:?}", val),
pos.clone(),
)));
} }
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
// 2. get right side (string) // 2. get right side (string)
@ -516,10 +579,13 @@ impl Builtins {
if let &P(Str(ref s)) = val.as_ref() { if let &P(Str(ref s)) = val.as_ref() {
s.clone() s.clone()
} else { } else {
return dbg!(Err(Error {})); return dbg!(Err(Error::new(
format!("Expected string bug got {:?}", val),
pos.clone(),
)));
} }
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
// 3. compare via regex // 3. compare via regex
@ -532,6 +598,7 @@ impl Builtins {
&self, &self,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<(), Error> ) -> Result<(), Error>
where where
O: std::io::Write, O: std::io::Write,
@ -541,25 +608,25 @@ impl Builtins {
let list = if let Some(list) = stack.pop() { let list = if let Some(list) = stack.pop() {
list list
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
// Get the accumulator from the stack // Get the accumulator from the stack
let mut acc = if let Some(acc) = stack.pop() { let mut acc = if let Some(acc) = stack.pop() {
acc acc
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
// get the func ptr from the stack // get the func ptr from the stack
let fptr = if let Some(ptr) = stack.pop() { let fptr = if let Some(ptr) = stack.pop() {
ptr ptr
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
let f = if let &F(ref f) = fptr.as_ref() { let f = if let &F(ref f) = fptr.as_ref() {
f f
} else { } else {
return dbg!(Err(Error {})); return dbg!(Err(Error::new(format!("Not a function!"), pos.clone(),)));
}; };
match list.as_ref() { match list.as_ref() {
@ -569,7 +636,7 @@ impl Builtins {
stack.push(dbg!(e.clone())); stack.push(dbg!(e.clone()));
stack.push(dbg!(acc.clone())); stack.push(dbg!(acc.clone()));
// call function and push it's result on the stack. // 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)) => { &C(Tuple(ref _flds)) => {
@ -579,7 +646,7 @@ impl Builtins {
stack.push(Rc::new(P(Str(name.clone())))); stack.push(Rc::new(P(Str(name.clone()))));
stack.push(dbg!(acc.clone())); stack.push(dbg!(acc.clone()));
// call function and push it's result on the stack. // 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)) => { &P(Str(ref _s)) => {
@ -588,10 +655,15 @@ impl Builtins {
stack.push(dbg!(Rc::new(P(Str(c.to_string()))))); stack.push(dbg!(Rc::new(P(Str(c.to_string())))));
stack.push(dbg!(acc.clone())); stack.push(dbg!(acc.clone()));
// call function and push it's result on the stack. // 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 // push the acc on the stack as our result
@ -599,11 +671,11 @@ impl Builtins {
Ok(()) Ok(())
} }
fn range(&self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> { fn range(&self, stack: &mut Vec<Rc<Value>>, pos: &Position) -> Result<(), Error> {
let start = if let Some(start) = stack.pop() { let start = if let Some(start) = stack.pop() {
start start
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
let step = if let Some(step) = stack.pop() { let step = if let Some(step) = stack.pop() {
if let &P(Empty) = step.as_ref() { if let &P(Empty) = step.as_ref() {
@ -612,12 +684,12 @@ impl Builtins {
step step
} }
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
let end = if let Some(end) = stack.pop() { let end = if let Some(end) = stack.pop() {
end end
} else { } else {
return dbg!(Err(Error {})); unreachable!();
}; };
let mut elems = Vec::new(); 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)))); stack.push(Rc::new(C(List(elems))));
@ -653,25 +728,25 @@ impl Builtins {
let val = if let Some(val) = dbg!(stack.pop()) { let val = if let Some(val) = dbg!(stack.pop()) {
val val
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
let expr = stack.pop(); let expr = stack.pop();
let expr_pretty = match expr { 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(), &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())?; let writable_val: Val = TryFrom::try_from(val.clone())?;
if let Err(_) = writeln!( if let Err(e) = writeln!(
&mut env.borrow_mut().stderr, &mut env.borrow_mut().stderr,
"TRACE: {} = {} at {}", "TRACE: {} = {} at {}",
expr_pretty, expr_pretty,
writable_val, writable_val,
pos pos
) { ) {
return Err(dbg!(Error {})); return Err(dbg!(Error::new(format!("{}", e), pos.clone(),)));
}; };
stack.push(val); stack.push(val);
Ok(()) Ok(())

View File

@ -15,7 +15,7 @@ use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator; use std::iter::FromIterator;
use std::rc::Rc; use std::rc::Rc;
use super::{Error, Value}; use super::Value;
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum Bindings { pub enum Bindings {
@ -115,12 +115,12 @@ impl Stack {
std::mem::swap(&mut tmp, &mut self.curr); 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() { if let Some(parent) = self.prev.pop() {
self.curr = parent; self.curr = parent;
Ok(()) Ok(())
} else { } else {
dbg!(Err(Error {})) dbg!(Err(format!("Exceeded Stack depth!!")))
} }
} }

View File

@ -16,6 +16,7 @@ use std::rc::Rc;
use super::environment::Environment; use super::environment::Environment;
use super::scope::Stack; use super::scope::Stack;
use super::translate::PositionMap;
use super::Composite::{List, Tuple}; use super::Composite::{List, Tuple};
use super::Op::{ use super::Op::{
Add, Bang, Bind, BindOver, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, Index, InitList, 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::Primitive::{Bool, Empty, Float, Int, Str};
use super::Value::{C, P}; use super::Value::{C, P};
use super::VM; use super::VM;
use crate::ast::Position;
macro_rules! assert_cases { macro_rules! assert_cases {
(__impl__ $cases:expr) => { (__impl__ $cases:expr) => {
for case in $cases.drain(0..) { for case in $cases.drain(0..) {
let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); 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(); vm.run().unwrap();
assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1)); assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1));
} }
@ -120,10 +130,18 @@ fn bind_op() {
for case in cases.drain(0..) { for case in cases.drain(0..) {
let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new()))); 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(); vm.run().unwrap();
let (name, result) = case.1; 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()); assert_eq!(&result, v.as_ref());
} }
} }

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
use std::path::Path; 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::ast::{FuncOpDef, TemplatePart};
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
use crate::build::opcode::Primitive; use crate::build::opcode::Primitive;
@ -21,14 +21,38 @@ use crate::build::opcode::{Hook, Op};
pub struct AST(); pub struct AST();
#[derive(Debug, PartialEq)]
pub struct PositionMap {
pub ops: Vec<Op>,
pub pos: Vec<Position>,
}
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 { impl AST {
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> Vec<Op> { pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> PositionMap {
let mut ops = Vec::new(); let mut ops = PositionMap {
ops: Vec::new(),
pos: Vec::new(),
};
Self::translate_stmts(stmts, &mut ops, root.as_ref()); Self::translate_stmts(stmts, &mut ops, root.as_ref());
return ops; return ops;
} }
fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut Vec<Op>, root: &Path) { fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut PositionMap, root: &Path) {
for stmt in stmts { for stmt in stmts {
match stmt { match stmt {
Statement::Expression(expr) => Self::translate_expr(expr, &mut ops, root), Statement::Expression(expr) => Self::translate_expr(expr, &mut ops, root),
@ -37,9 +61,9 @@ impl AST {
} }
Statement::Let(def) => { Statement::Let(def) => {
let binding = def.name.fragment; 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); Self::translate_expr(def.value, &mut ops, root);
ops.push(Op::Bind); ops.push(Op::Bind, def.pos);
} }
Statement::Output(_, _, _) => { Statement::Output(_, _, _) => {
unimplemented!("Out statements are not implmented yet") unimplemented!("Out statements are not implmented yet")
@ -51,7 +75,7 @@ impl AST {
} }
} }
fn translate_expr(expr: Expression, mut ops: &mut Vec<Op>, root: &Path) { fn translate_expr(expr: Expression, mut ops: &mut PositionMap, root: &Path) {
match expr { match expr {
Expression::Simple(v) => { Expression::Simple(v) => {
Self::translate_value(v, &mut ops, root); Self::translate_value(v, &mut ops, root);
@ -61,92 +85,91 @@ impl AST {
BinaryExprType::Add => { BinaryExprType::Add => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Add); ops.push(Op::Add, def.pos);
} }
BinaryExprType::Sub => { BinaryExprType::Sub => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Sub); ops.push(Op::Sub, def.pos);
} }
BinaryExprType::Div => { BinaryExprType::Div => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Div); ops.push(Op::Div, def.pos);
} }
BinaryExprType::Mul => { BinaryExprType::Mul => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Mul); ops.push(Op::Mul, def.pos);
} }
BinaryExprType::Equal => { BinaryExprType::Equal => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Equal); ops.push(Op::Equal, def.pos);
} }
BinaryExprType::GT => { BinaryExprType::GT => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Gt); ops.push(Op::Gt, def.pos);
} }
BinaryExprType::LT => { BinaryExprType::LT => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Lt); ops.push(Op::Lt, def.pos);
} }
BinaryExprType::GTEqual => { BinaryExprType::GTEqual => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::GtEq); ops.push(Op::GtEq, def.pos);
} }
BinaryExprType::LTEqual => { BinaryExprType::LTEqual => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::LtEq); ops.push(Op::LtEq, def.pos);
} }
BinaryExprType::NotEqual => { BinaryExprType::NotEqual => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Equal); ops.push(Op::Equal, def.pos.clone());
ops.push(Op::Not); ops.push(Op::Not, def.pos);
} }
BinaryExprType::REMatch => { BinaryExprType::REMatch => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &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 => { BinaryExprType::NotREMatch => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &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.clone());
ops.push(Op::Not); ops.push(Op::Not, def.pos);
} }
BinaryExprType::IS => { BinaryExprType::IS => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Typ); ops.push(Op::Typ, def.pos.clone());
ops.push(Op::Equal); ops.push(Op::Equal, def.pos);
} }
BinaryExprType::AND => { BinaryExprType::AND => {
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Noop); ops.push(Op::Noop, def.pos);
let idx = ops.len() - 1; let idx = ops.len() - 1;
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
let jptr = (ops.len() - 1 - idx) as i32; let jptr = (ops.len() - 1 - idx) as i32;
ops[idx] = Op::And(dbg!(jptr)); ops.replace(idx, Op::And(dbg!(jptr)));
dbg!(ops);
} }
BinaryExprType::OR => { BinaryExprType::OR => {
Self::translate_expr(*def.left, &mut ops, root); 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; let idx = ops.len() - 1;
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
let jptr = (ops.len() - 1 - idx) as i32; let jptr = (ops.len() - 1 - idx) as i32;
ops[idx] = Op::Or(jptr); ops.replace(idx, Op::Or(dbg!(jptr)));
} }
BinaryExprType::Mod => { BinaryExprType::Mod => {
Self::translate_expr(*def.right, &mut ops, root); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops, root); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Mod); ops.push(Op::Mod, def.pos);
} }
BinaryExprType::IN => { BinaryExprType::IN => {
// Dot expressions expect the left side to be pushed first // Dot expressions expect the left side to be pushed first
@ -165,10 +188,10 @@ impl AST {
Self::translate_expr(expr, &mut ops, root); Self::translate_expr(expr, &mut ops, root);
} }
} }
ops.push(Op::SafeIndex); ops.push(Op::SafeIndex, def.pos.clone());
ops.push(Op::Val(Primitive::Empty)); ops.push(Op::Val(Primitive::Empty), def.pos.clone());
ops.push(Op::Equal); ops.push(Op::Equal, def.pos.clone());
ops.push(Op::Not); ops.push(Op::Not, def.pos);
} }
BinaryExprType::DOT => { BinaryExprType::DOT => {
// Dot expressions expect the left side to be pushed first // Dot expressions expect the left side to be pushed first
@ -187,7 +210,7 @@ impl AST {
Self::translate_expr(expr, &mut ops, root); 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) => { Expression::Fail(def) => {
Self::translate_expr(*def.message, &mut ops, root); Self::translate_expr(*def.message, &mut ops, root);
ops.push(Op::Bang); ops.push(Op::Bang, def.pos);
} }
Expression::Format(def) => { Expression::Format(def) => {
match def.args { match def.args {
@ -212,6 +235,7 @@ impl AST {
let mut elems_iter = elems.drain(0..); let mut elems_iter = elems.drain(0..);
let mut parts_iter = parts.drain(0..); let mut parts_iter = parts.drain(0..);
Self::translate_template_part( Self::translate_template_part(
def.pos.clone(),
parts_iter.next().unwrap(), parts_iter.next().unwrap(),
&mut elems_iter, &mut elems_iter,
&mut ops, &mut ops,
@ -219,8 +243,17 @@ impl AST {
root, root,
); );
for p in parts_iter { for p in parts_iter {
Self::translate_template_part(p, &mut elems_iter, &mut ops, true, root); Self::translate_template_part(
ops.push(Op::Add); 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) => { FormatArgs::Single(expr) => {
@ -230,17 +263,19 @@ impl AST {
let mut parts = formatter.parse(&def.template).unwrap(); let mut parts = formatter.parse(&def.template).unwrap();
parts.reverse(); parts.reverse();
let mut parts_iter = parts.drain(0..); let mut parts_iter = parts.drain(0..);
ops.push(Op::Noop); ops.push(Op::Noop, expr.pos().clone());
let scope_idx = ops.len() - 1; let scope_idx = ops.len() - 1;
// Add our item binding shadowing any binding that already // Add our item binding shadowing any binding that already
// existed. // 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); 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 = Vec::new();
let mut elems_iter = elems.drain(0..); let mut elems_iter = elems.drain(0..);
Self::translate_template_part( Self::translate_template_part(
def.pos.clone(),
parts_iter.next().unwrap(), parts_iter.next().unwrap(),
&mut elems_iter, &mut elems_iter,
&mut ops, &mut ops,
@ -249,32 +284,33 @@ impl AST {
); );
for p in parts_iter { for p in parts_iter {
Self::translate_template_part( Self::translate_template_part(
def.pos.clone(),
p, p,
&mut elems_iter, &mut elems_iter,
&mut ops, &mut ops,
false, false,
root, 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; 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) => { Expression::Func(def) => {
ops.push(Op::InitList); ops.push(Op::InitList, def.pos.clone());
for b in def.argdefs { for b in def.argdefs {
ops.push(Op::Sym(b.val)); ops.push(Op::Sym(b.val), b.pos.clone());
ops.push(Op::Element); ops.push(Op::Element, b.pos);
} }
ops.push(Op::Noop); ops.push(Op::Noop, def.pos.clone());
let idx = ops.len() - 1; let idx = ops.len() - 1;
Self::translate_expr(*def.fields, &mut ops, root); Self::translate_expr(*def.fields, &mut ops, root);
ops.push(Op::Return); ops.push(Op::Return, def.pos);
let jptr = ops.len() - 1 - idx; let jptr = ops.len() - 1 - idx;
ops[idx] = Op::Func(jptr as i32); ops.replace(idx, Op::Func(jptr as i32));
} }
Expression::FuncOp(def) => { Expression::FuncOp(def) => {
match def { match def {
@ -284,7 +320,7 @@ impl AST {
// push the target on the stack third // push the target on the stack third
Self::translate_expr(*def.target, &mut ops, root); Self::translate_expr(*def.target, &mut ops, root);
// finally push the Hook::Map opcode // finally push the Hook::Map opcode
ops.push(Op::Runtime(Hook::Map)); ops.push(Op::Runtime(Hook::Map), def.pos);
} }
FuncOpDef::Filter(def) => { FuncOpDef::Filter(def) => {
// push the function on the stack first. // push the function on the stack first.
@ -292,7 +328,7 @@ impl AST {
// push the target on the stack third // push the target on the stack third
Self::translate_expr(*def.target, &mut ops, root); Self::translate_expr(*def.target, &mut ops, root);
// finally push the Hook::Map opcode // finally push the Hook::Map opcode
ops.push(Op::Runtime(Hook::Filter)); ops.push(Op::Runtime(Hook::Filter), def.pos);
} }
FuncOpDef::Reduce(def) => { FuncOpDef::Reduce(def) => {
// push the function on the stack first. // push the function on the stack first.
@ -302,18 +338,18 @@ impl AST {
// push the target on the stack third // push the target on the stack third
Self::translate_expr(*def.target, &mut ops, root); Self::translate_expr(*def.target, &mut ops, root);
// finally push the Hook::Map opcode // finally push the Hook::Map opcode
ops.push(Op::Runtime(Hook::Reduce)); ops.push(Op::Runtime(Hook::Reduce), def.pos);
} }
} }
} }
Expression::Import(def) => { Expression::Import(def) => {
ops.push(Op::Val(Primitive::Str(def.path.fragment))); ops.push(Op::Val(Primitive::Str(def.path.fragment)), def.path.pos);
ops.push(Op::Runtime(Hook::Import)); ops.push(Op::Runtime(Hook::Import), def.pos);
} }
Expression::Include(def) => { Expression::Include(def) => {
ops.push(Op::Val(Primitive::Str(def.typ.fragment))); ops.push(Op::Val(Primitive::Str(def.typ.fragment)), def.typ.pos);
ops.push(Op::Val(Primitive::Str(def.path.fragment))); ops.push(Op::Val(Primitive::Str(def.path.fragment)), def.path.pos);
ops.push(Op::Runtime(Hook::Include)); ops.push(Op::Runtime(Hook::Include), def.pos);
} }
Expression::Module(mut def) => { Expression::Module(mut def) => {
def.imports_to_absolute(root.to_path_buf()); def.imports_to_absolute(root.to_path_buf());
@ -321,74 +357,75 @@ impl AST {
let out_expr = def.out_expr; let out_expr = def.out_expr;
let stmts = def.statements; let stmts = def.statements;
// Init our module tuple bindings // Init our module tuple bindings
ops.push(Op::InitTuple); ops.push(Op::InitTuple, def.pos.clone());
for (t, e) in argset { 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); 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 there is one then emit our return expression
if let Some(expr) = out_expr { if let Some(expr) = out_expr {
// Insert placeholder until we know jptr for this thunk // 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; let idx = ops.len() - 1;
Self::translate_expr(*expr, &mut ops, root); Self::translate_expr(*expr, &mut ops, root);
ops.push(Op::Return); ops.push(Op::Return, expr_pos.clone());
let jptr = ops.len() - idx - 1; 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 // Insert a placeholder Opcode until we know jptr for the
// module. // module.
ops.push(Op::Noop); ops.push(Op::Noop, def.pos.clone());
let idx = ops.len() - 1; let idx = ops.len() - 1;
// Bind our mod tuple. // Bind our mod tuple.
ops.push(Op::Bind); ops.push(Op::Bind, def.pos.clone());
// emit all of our statements; // emit all of our statements;
Self::translate_stmts(stmts, &mut ops, root); Self::translate_stmts(stmts, &mut ops, root);
// Return from the module // Return from the module
ops.push(Op::Return); ops.push(Op::Return, def.pos);
let jptr = ops.len() - idx - 1; let jptr = ops.len() - idx - 1;
ops[idx] = Op::Module(jptr as i32); ops.replace(idx, Op::Module(jptr as i32));
} }
Expression::Not(def) => { Expression::Not(def) => {
Self::translate_expr(*def.expr, &mut ops, root); Self::translate_expr(*def.expr, &mut ops, root);
ops.push(Op::Not); ops.push(Op::Not, def.pos);
} }
Expression::Range(def) => { Expression::Range(def) => {
Self::translate_expr(*def.end, &mut ops, root); Self::translate_expr(*def.end, &mut ops, root);
if let Some(expr) = def.step { if let Some(expr) = def.step {
Self::translate_expr(*expr, &mut ops, root); Self::translate_expr(*expr, &mut ops, root);
} else { } else {
ops.push(Op::Val(Primitive::Empty)); ops.push(Op::Val(Primitive::Empty), def.pos.clone());
} }
Self::translate_expr(*def.start, &mut ops, root); 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) => { Expression::Select(def) => {
Self::translate_expr(*def.val, &mut ops, root); Self::translate_expr(*def.val, &mut ops, root);
let mut jumps = Vec::new(); let mut jumps = Vec::new();
for (key, val) in def.tuple { for (key, val) in def.tuple {
ops.push(Op::Sym(key.fragment)); ops.push(Op::Sym(key.fragment), key.pos.clone());
ops.push(Op::Noop); ops.push(Op::Noop, key.pos);
let idx = ops.len() - 1; let idx = ops.len() - 1;
let expr_pos = val.pos().clone();
Self::translate_expr(val, &mut ops, root); Self::translate_expr(val, &mut ops, root);
ops.push(Op::Noop); ops.push(Op::Noop, expr_pos);
jumps.push(ops.len() - 1); jumps.push(ops.len() - 1);
let jptr = ops.len() - idx - 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; let end = ops.len() - 1;
for i in jumps { for i in jumps {
let idx = end - i; 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 { if let Some(default) = def.default {
Self::translate_expr(*default, &mut ops, root); Self::translate_expr(*default, &mut ops, root);
} else { } else {
ops.push(Op::Bang); ops.push(Op::Bang, def.pos);
} }
dbg!(&ops);
} }
Expression::Call(def) => { Expression::Call(def) => {
// first push our arguments. // first push our arguments.
@ -396,19 +433,19 @@ impl AST {
Self::translate_expr(e, &mut ops, root); Self::translate_expr(e, &mut ops, root);
} }
// then push the func reference // then push the func reference
let func_pos = def.funcref.pos().clone();
Self::translate_value(def.funcref, &mut ops, root); Self::translate_value(def.funcref, &mut ops, root);
ops.push(Op::FCall); ops.push(Op::FCall, func_pos);
dbg!(ops);
} }
Expression::Copy(def) => { Expression::Copy(def) => {
ops.push(Op::InitTuple); ops.push(Op::InitTuple, def.pos.clone());
for (t, e) in def.fields { 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); 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); Self::translate_value(def.selector, &mut ops, root);
ops.push(Op::Cp); ops.push(Op::Cp, def.pos);
} }
Expression::Debug(def) => { Expression::Debug(def) => {
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();
@ -417,23 +454,24 @@ impl AST {
let _ = printer.render_expr(&def.expr); let _ = printer.render_expr(&def.expr);
} }
let expr_pretty = String::from_utf8(buffer).unwrap(); 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); 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<EI: Iterator<Item = Expression>>( fn translate_template_part<EI: Iterator<Item = Expression>>(
pos: Position,
part: TemplatePart, part: TemplatePart,
elems: &mut EI, elems: &mut EI,
mut ops: &mut Vec<Op>, mut ops: &mut PositionMap,
place_holder: bool, place_holder: bool,
root: &Path, root: &Path,
) { ) {
match part { match part {
TemplatePart::Str(s) => { 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) => { TemplatePart::PlaceHolder(_idx) => {
if !place_holder { if !place_holder {
@ -441,7 +479,7 @@ impl AST {
unreachable!(); unreachable!();
} else { } else {
Self::translate_expr(elems.next().unwrap(), &mut ops, root); Self::translate_expr(elems.next().unwrap(), &mut ops, root);
ops.push(Op::Render); ops.push(Op::Render, pos);
} }
} }
TemplatePart::Expression(expr) => { TemplatePart::Expression(expr) => {
@ -449,35 +487,36 @@ impl AST {
unreachable!(); unreachable!();
} else { } else {
Self::translate_expr(expr, &mut ops, root); 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<Op>, root: &Path) { fn translate_value(value: Value, mut ops: &mut PositionMap, root: &Path) {
match value { match value {
Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.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))), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val)), f.pos),
Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))), Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val)), s.pos),
Value::Empty(_pos) => ops.push(Op::Val(Primitive::Empty)), Value::Empty(pos) => ops.push(Op::Val(Primitive::Empty), pos),
Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val))), Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val)), b.pos),
Value::Symbol(s) => { Value::Symbol(s) => {
ops.push(Op::DeRef(s.val)); ops.push(Op::DeRef(s.val), s.pos);
} }
Value::Tuple(flds) => { Value::Tuple(flds) => {
ops.push(Op::InitTuple); ops.push(Op::InitTuple, flds.pos);
for (k, v) in flds.val { 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); Self::translate_expr(v, &mut ops, root);
ops.push(Op::Field); ops.push(Op::Field, k.pos.clone());
} }
} }
Value::List(els) => { Value::List(els) => {
ops.push(Op::InitList); ops.push(Op::InitList, els.pos);
for el in els.elems { for el in els.elems {
let el_pos = el.pos().clone();
Self::translate_expr(el, &mut ops, root); Self::translate_expr(el, &mut ops, root);
ops.push(Op::Element); ops.push(Op::Element, el_pos);
} }
} }
} }

View File

@ -15,10 +15,13 @@ use std::cell::RefCell;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use crate::ast::Position;
use super::environment::Environment; use super::environment::Environment;
use super::pointer::OpPointer; use super::pointer::OpPointer;
use super::runtime; use super::runtime;
use super::scope::Stack; use super::scope::Stack;
use super::translate::PositionMap;
use super::Composite::{List, Tuple}; use super::Composite::{List, Tuple};
use super::Hook; use super::Hook;
use super::Primitive::{Bool, Empty, Float, Int, Str}; use super::Primitive::{Bool, Empty, Float, Int, Str};
@ -43,7 +46,7 @@ where
O: std::io::Write, O: std::io::Write,
E: std::io::Write, E: std::io::Write,
{ {
pub fn new(ops: Rc<Vec<Op>>, env: Rc<RefCell<Environment<O, E>>>) -> Self { pub fn new(ops: Rc<PositionMap>, env: Rc<RefCell<Environment<O, E>>>) -> Self {
Self::with_pointer(OpPointer::new(ops), env) Self::with_pointer(OpPointer::new(ops), env)
} }
@ -79,38 +82,39 @@ where
pub fn run(&mut self) -> Result<(), Error> { pub fn run(&mut self) -> Result<(), Error> {
loop { loop {
let op = if let Some(op) = self.ops.next() { let op = if let Some(op) = dbg!(self.ops.next()) {
op.clone() op.clone()
} else { } else {
break; break;
}; };
let pos = self.ops.pos().unwrap().clone();
let idx = self.ops.idx()?; let idx = self.ops.idx()?;
match op { match op {
Op::Val(p) => self.push(Rc::new(P(p.clone())))?, Op::Val(p) => self.push(Rc::new(P(p.clone())))?,
Op::Sym(s) => self.push(Rc::new(S(s.clone())))?, Op::Sym(s) => self.push(Rc::new(S(s.clone())))?,
Op::DeRef(s) => self.op_deref(s.clone())?, Op::DeRef(s) => self.op_deref(s.clone(), &pos)?,
Op::Add => self.op_add()?, Op::Add => self.op_add(&pos)?,
Op::Mod => self.op_mod()?, Op::Mod => self.op_mod(&pos)?,
Op::Sub => self.op_sub()?, Op::Sub => self.op_sub(&pos)?,
Op::Mul => self.op_mul()?, Op::Mul => self.op_mul(&pos)?,
Op::Div => self.op_div()?, Op::Div => self.op_div(&pos)?,
Op::Bind => self.op_bind(true)?, Op::Bind => self.op_bind(true, &pos)?,
Op::BindOver => self.op_bind(false)?, Op::BindOver => self.op_bind(false, &pos)?,
Op::Equal => self.op_equal()?, Op::Equal => self.op_equal()?,
Op::Not => self.op_not()?, Op::Not => self.op_not(&pos)?,
Op::Gt => self.op_gt()?, Op::Gt => self.op_gt(&pos)?,
Op::Lt => self.op_lt()?, Op::Lt => self.op_lt(&pos)?,
Op::GtEq => self.op_gteq()?, Op::GtEq => self.op_gteq(&pos)?,
Op::LtEq => self.op_lteq()?, Op::LtEq => self.op_lteq(&pos)?,
// Add a Composite list value to the stack // 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()))))?,
// Add a composite tuple value to the stack // 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()))))?,
Op::Field => self.op_field()?, Op::Field => self.op_field()?,
Op::Element => self.op_element()?, Op::Element => self.op_element()?,
Op::Index => self.op_index(false)?, Op::Index => self.op_index(false, &pos)?,
Op::SafeIndex => self.op_index(true)?, Op::SafeIndex => self.op_index(true, &pos)?,
Op::Cp => self.op_copy()?, Op::Cp => self.op_copy(&pos)?,
//FIXME(jwall): Should this take a user provided message? //FIXME(jwall): Should this take a user provided message?
Op::Bang => self.op_bang()?, Op::Bang => self.op_bang()?,
Op::InitThunk(jp) => self.op_thunk(idx, jp)?, Op::InitThunk(jp) => self.op_thunk(idx, jp)?,
@ -118,14 +122,14 @@ where
// Do nothing // Do nothing
} }
Op::Jump(jp) => self.op_jump(jp)?, Op::Jump(jp) => self.op_jump(jp)?,
Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?, Op::JumpIfTrue(jp) => self.op_jump_if_true(jp, &pos)?,
Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?, Op::JumpIfFalse(jp) => self.op_jump_if_false(jp, &pos)?,
Op::SelectJump(jp) => self.op_select_jump(jp)?, Op::SelectJump(jp) => self.op_select_jump(jp)?,
Op::And(jp) => self.op_and(jp)?, Op::And(jp) => self.op_and(jp, &pos)?,
Op::Or(jp) => self.op_or(jp)?, Op::Or(jp) => self.op_or(jp, &pos)?,
Op::Module(mptr) => self.op_module(idx, mptr)?, Op::Module(mptr) => self.op_module(idx, mptr, &pos)?,
Op::Func(jptr) => self.op_func(idx, jptr)?, Op::Func(jptr) => self.op_func(idx, jptr, &pos)?,
Op::FCall => self.op_fcall()?, Op::FCall => self.op_fcall(&pos)?,
Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone())?, Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone())?,
Op::Return => { Op::Return => {
dbg!(&self.stack); dbg!(&self.stack);
@ -135,7 +139,7 @@ where
self.pop()?; self.pop()?;
} }
Op::Typ => self.op_typ()?, 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()?, Op::Render => self.op_render()?,
}; };
} }
@ -154,17 +158,16 @@ where
C(List(_)) => "list", C(List(_)) => "list",
F(_) => "func", F(_) => "func",
M(_) => "module", M(_) => "module",
S(_) | T(_) => { S(_) => "sym",
return Err(dbg!(Error {})); T(_) => "thunk",
}
} }
.to_owned(); .to_owned();
self.push(Rc::new(P(Str(typ_name))))?; self.push(Rc::new(P(Str(typ_name))))?;
Ok(()) Ok(())
} }
fn op_deref(&mut self, name: String) -> Result<(), Error> { fn op_deref(&mut self, name: String, pos: &Position) -> Result<(), Error> {
let val = self.get_binding(&name)?.clone(); let val = self.get_binding(&name, pos)?.clone();
self.push(val) self.push(val)
} }
@ -178,7 +181,7 @@ where
Ok(()) 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 cond = self.pop()?;
let cc = cond.clone(); let cc = cond.clone();
if let &P(Bool(cond)) = cond.as_ref() { if let &P(Bool(cond)) = cond.as_ref() {
@ -187,41 +190,57 @@ where
self.op_jump(jp)?; self.op_jump(jp)?;
} }
} else { } else {
return Err(dbg!(Error {})); return Err(dbg!(Error::new(
format!("Not a boolean condition {:?} in && expression!", cond),
pos.clone(),
)));
} }
Ok(()) 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 cond = self.pop()?;
let cc = cond.clone(); let cc = dbg!(cond.clone());
if let &P(Bool(cond)) = cond.as_ref() { if let &P(Bool(cond)) = cond.as_ref() {
if cond { if dbg!(cond) {
self.push(cc)?; self.push(cc)?;
self.op_jump(jp)?; self.op_jump(jp)?;
} }
} else {
return Err(dbg!(Error::new(
format!("Not a boolean condition {:?} in || expression!", cond),
pos.clone(),
)));
} }
Ok(()) 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()?; let cond = self.pop()?;
if let &P(Bool(cond)) = cond.as_ref() { if let &P(Bool(cond)) = cond.as_ref() {
if cond { if cond {
self.op_jump(jp)?; self.op_jump(jp)?;
} }
} else { } else {
return Err(dbg!(Error {})); return Err(dbg!(Error::new(
format!("Expected boolean but got {:?}!", cond),
pos.clone(),
)));
} }
Ok(()) 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()?; let cond = self.pop()?;
if let &P(Bool(cond)) = cond.as_ref() { if let &P(Bool(cond)) = cond.as_ref() {
if !cond { if !cond {
self.op_jump(jp)?; self.op_jump(jp)?;
} }
} else {
return Err(dbg!(Error::new(
format!("Expected boolean but got {:?}!", cond),
pos.clone(),
)));
} }
Ok(()) Ok(())
} }
@ -244,7 +263,7 @@ where
Ok(()) 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 mod_val = dbg!(self.pop())?;
let (result_ptr, flds) = match mod_val.as_ref() { let (result_ptr, flds) = match mod_val.as_ref() {
&C(Tuple(ref flds)) => (None, flds.clone()), &C(Tuple(ref flds)) => (None, flds.clone()),
@ -253,14 +272,21 @@ where
if let &C(Tuple(ref flds)) = tpl_val.as_ref() { if let &C(Tuple(ref flds)) = tpl_val.as_ref() {
(Some(ptr), flds.clone()) (Some(ptr), flds.clone())
} else { } 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 mut ops = self.ops.clone();
let pkg_pos = self.ops.pos().unwrap().clone();
ops.jump(idx)?; ops.jump(idx)?;
let pkg_ptr = if let Some(ref path) = self.ops.path { let pkg_ptr = if let Some(ref path) = self.ops.path {
let pkg_ops = vec![ let pkg_ops = vec![
@ -270,7 +296,17 @@ where
Op::Runtime(Hook::Import), Op::Runtime(Hook::Import),
Op::Return, 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 { } else {
None None
}; };
@ -283,7 +319,7 @@ where
self.op_jump(jptr) 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 // get arity from stack
let mut scope_snapshot = self.symbols.snapshot(); let mut scope_snapshot = self.symbols.snapshot();
scope_snapshot.push(); scope_snapshot.push();
@ -297,13 +333,18 @@ where
if let &S(ref sym) = e.as_ref() { if let &S(ref sym) = e.as_ref() {
bindings.push(sym.clone()); bindings.push(sym.clone());
} else { } else {
return dbg!(Err(Error {})); return dbg!(Err(Error::new(
format!("Not an argument name {:?}", e),
pos.clone(),
)));
} }
} }
} else { } 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(); let mut ops = self.ops.clone();
ops.jump(idx)?; ops.jump(idx)?;
self.push(Rc::new(F(Func { self.push(Rc::new(F(Func {
@ -319,6 +360,7 @@ where
f: &Func, f: &Func,
stack: &mut Vec<Rc<Value>>, stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>, env: Rc<RefCell<Environment<O, E>>>,
pos: &Position,
) -> Result<Rc<Value>, Error> { ) -> Result<Rc<Value>, Error> {
let Func { let Func {
ref ptr, ref ptr,
@ -332,7 +374,7 @@ where
// TODO(jwall): This should do a better error if there is // TODO(jwall): This should do a better error if there is
// nothing on the stack. // nothing on the stack.
let val = stack.pop().unwrap(); 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 // proceed to the function body
vm.run()?; vm.run()?;
@ -351,10 +393,10 @@ where
Ok(()) Ok(())
} }
fn op_fcall(&mut self) -> Result<(), Error> { fn op_fcall(&mut self, pos: &Position) -> Result<(), Error> {
let f = dbg!(self.pop())?; let f = dbg!(self.pop())?;
if let &F(ref f) = f.as_ref() { 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))?; self.push(dbg!(val))?;
} }
Ok(()) Ok(())
@ -365,13 +407,16 @@ where
self.op_jump(jp) self.op_jump(jp)
} }
fn op_not(&mut self) -> Result<(), Error> { fn op_not(&mut self, pos: &Position) -> Result<(), Error> {
let operand = self.pop()?; let operand = self.pop()?;
if let P(Bool(val)) = operand.as_ref() { if let P(Bool(val)) = operand.as_ref() {
self.push(Rc::new(P(Bool(!val))))?; self.push(Rc::new(P(Bool(!val))))?;
return Ok(()); 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> { fn op_equal(&mut self) -> Result<(), Error> {
@ -381,7 +426,7 @@ where
Ok(()) Ok(())
} }
fn op_gt(&mut self) -> Result<(), Error> { fn op_gt(&mut self, pos: &Position) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left.as_ref(), right.as_ref()) { match (left.as_ref(), right.as_ref()) {
@ -391,12 +436,17 @@ where
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f > 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(()) Ok(())
} }
fn op_lt(&mut self) -> Result<(), Error> { fn op_lt(&mut self, pos: &Position) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left.as_ref(), right.as_ref()) { match (left.as_ref(), right.as_ref()) {
@ -406,12 +456,17 @@ where
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f < 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(()) Ok(())
} }
fn op_lteq(&mut self) -> Result<(), Error> { fn op_lteq(&mut self, pos: &Position) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left.as_ref(), right.as_ref()) { match (left.as_ref(), right.as_ref()) {
@ -421,12 +476,17 @@ where
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f <= 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(()) Ok(())
} }
fn op_gteq(&mut self) -> Result<(), Error> { fn op_gteq(&mut self, pos: &Position) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left.as_ref(), right.as_ref()) { match (left.as_ref(), right.as_ref()) {
@ -436,65 +496,70 @@ where
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f >= 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(()) 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. // Adds the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
// Then pushes the result onto the stack. // 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(()) 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. // Adds the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
// Then pushes the result onto the stack. // 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(()) 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. // Subtracts the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
// Then pushes the result onto the stack. // 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(()) 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. // Multiplies the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
// Then pushes the result onto the stack. // 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(()) 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. // Divides the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
// Then pushes the result onto the stack. // 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(()) 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. // pop val off stack.
let val = self.pop()?; let val = self.pop()?;
// pop name off stack. // pop name off stack.
let name = self.pop()?; let name = self.pop()?;
if let &S(ref name) = name.as_ref() { if let &S(ref name) = name.as_ref() {
self.binding_push(name.clone(), val, strict)?; self.binding_push(name.clone(), val, strict, pos)?;
} else { } else {
return Err(dbg!(Error {})); unreachable!();
} }
Ok(()) Ok(())
} }
@ -508,7 +573,7 @@ where
let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() { let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() {
s s
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
// get composite tuple from stack // get composite tuple from stack
let tpl = self.pop()?; let tpl = self.pop()?;
@ -519,7 +584,7 @@ where
// place composite tuple back on stack // place composite tuple back on stack
self.push(Rc::new(C(Tuple(flds))))?; self.push(Rc::new(C(Tuple(flds))))?;
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
Ok(()) Ok(())
} }
@ -536,19 +601,25 @@ where
// Add that value to the list and put list back on stack. // 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))))?;
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
Ok(()) Ok(())
} }
fn find_in_list(&self, index: &Value, elems: &Vec<Rc<Value>>) -> Result<Rc<Value>, Error> { fn find_in_list(&self, index: &Value, elems: &Vec<Rc<Value>>, pos: &Position) -> Result<Rc<Value>, Error> {
let idx = match index { let idx = match index {
P(Int(i)) => i.clone(), 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) { match elems.get(idx as usize) {
Some(v) => Ok(v.clone()), 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, &self,
index: &Value, index: &Value,
flds: &Vec<(String, Rc<Value>)>, flds: &Vec<(String, Rc<Value>)>,
pos: &Position,
) -> Result<Rc<Value>, Error> { ) -> Result<Rc<Value>, Error> {
let idx = match index { let idx = match index {
S(p) => p, S(p) => p,
P(Str(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() { for f in flds.iter() {
if idx == &f.0 { if idx == &f.0 {
return Ok(f.1.clone()); 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<Rc<Value>, Error> { fn find_in_value(&self, index: &Value, target: &Value, pos: &Position) -> Result<Rc<Value>, Error> {
match target { match target {
C(Tuple(flds)) => self.find_in_flds(index, flds), C(Tuple(flds)) => self.find_in_flds(index, flds, pos),
C(List(elements)) => self.find_in_list(index, elements), C(List(elements)) => self.find_in_list(index, elements, pos),
_ => return Err(dbg!(Error {})), _ => return Err(dbg!(Error::new(
format!("Expected tuple for list but got {:?}", target),
pos.clone(),
))),
} }
} }
@ -582,7 +663,7 @@ where
Ok(()) 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 // left and then right
let right = dbg!(self.pop()?); let right = dbg!(self.pop()?);
let left = dbg!(self.pop()?); let left = dbg!(self.pop()?);
@ -613,10 +694,13 @@ where
self.push(Rc::new(P(Empty)))?; self.push(Rc::new(P(Empty)))?;
return Ok(()); 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. // get next value. It should be a Module or Tuple.
let tgt = dbg!(self.pop()?); let tgt = dbg!(self.pop()?);
// This value should always be a tuple // This value should always be a tuple
@ -624,7 +708,7 @@ where
let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() {
oflds.clone() oflds.clone()
} else { } else {
return Err(dbg!(Error {})); unreachable!();
}; };
match tgt.as_ref() { match tgt.as_ref() {
&C(Tuple(ref flds)) => { &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(()) Ok(())
@ -706,61 +793,80 @@ where
name: String, name: String,
val: Rc<Value>, val: Rc<Value>,
strict: bool, strict: bool,
pos: &Position,
) -> Result<(), Error> { ) -> Result<(), Error> {
if self.symbols.is_bound(&name) && strict { 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); self.symbols.add(name, val);
Ok(()) Ok(())
} }
pub fn get_binding(&'a self, name: &str) -> Result<Rc<Value>, Error> { pub fn get_binding(&'a self, name: &str, pos: &Position) -> Result<Rc<Value>, Error> {
match self.symbols.get(name) { match self.symbols.get(name) {
Some(v) => Ok(v), 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<Rc<Value>, Error> { pub fn pop(&mut self) -> Result<Rc<Value>, Error> {
match self.stack.pop() { match self.stack.pop() {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(dbg!(Error {})), None => unreachable!(),
} }
} }
fn mul(&self, left: &Value, right: &Value) -> Result<Primitive, Error> { fn mul(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), P(Int(ii))) => Int(i * ii), (P(Int(i)), P(Int(ii))) => Int(i * ii),
(P(Float(f)), P(Float(ff))) => Float(f * ff), (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<Primitive, Error> { fn div(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), P(Int(ii))) => Int(i / ii), (P(Int(i)), P(Int(ii))) => Int(i / ii),
(P(Float(f)), P(Float(ff))) => Float(f / ff), (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<Primitive, Error> { fn sub(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), Value::P(Int(ii))) => Int(i - ii), (P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
(P(Float(f)), Value::P(Float(ff))) => Float(f - ff), (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<Primitive, Error> { fn modulus(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), Value::P(Int(ii))) => Int(i % ii), (P(Int(i)), Value::P(Int(ii))) => Int(i % ii),
(P(Float(f)), Value::P(Float(ff))) => Float(f % ff), (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<Value, Error> { fn add(&self, left: &Value, right: &Value, pos: &Position) -> Result<Value, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), Value::P(Int(ii))) => P(Int(i + ii)), (P(Int(i)), Value::P(Int(ii))) => P(Int(i + ii)),
(P(Float(f)), Value::P(Float(ff))) => P(Float(f + ff)), (P(Float(f)), Value::P(Float(ff))) => P(Float(f + ff)),
@ -780,13 +886,16 @@ where
} }
C(List(new_list)) 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 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> { fn op_render(&mut self) -> Result<(), Error> {