mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: The great Error message explosion.
This commit is contained in:
parent
7a2a99b859
commit
33a5694aad
@ -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<String, Rc<Vec<Op>>>,
|
||||
ops: BTreeMap<String, Rc<PositionMap>>,
|
||||
}
|
||||
|
||||
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> {
|
||||
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,
|
||||
f: F,
|
||||
path: P,
|
||||
|
@ -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<E> From<E> 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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<Vec<Op>>,
|
||||
pub pos_map: Rc<PositionMap>,
|
||||
pub ptr: Option<usize>,
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
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?
|
||||
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<usize, Error> {
|
||||
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(),
|
||||
}
|
||||
|
@ -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<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<PathBuf, Error> {
|
||||
// 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<String, Error> {
|
||||
fn get_file_as_string(&self, path: &str, pos: &Position) -> Result<String, Error> {
|
||||
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<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<O, E>(
|
||||
&self,
|
||||
stack: &mut Vec<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<Rc<Value>>) -> Result<(), Error> {
|
||||
@ -272,15 +292,16 @@ impl Builtins {
|
||||
path: Option<P>,
|
||||
stack: &mut Vec<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<dyn std::io::Write> = 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<O, E>(
|
||||
&self,
|
||||
stack: &mut Vec<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<O, E>(
|
||||
&self,
|
||||
stack: &mut Vec<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<Rc<Value>>) -> Result<(), Error> {
|
||||
fn regex(&self, stack: &mut Vec<Rc<Value>>, 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<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
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<Rc<Value>>) -> Result<(), Error> {
|
||||
fn range(&self, stack: &mut Vec<Rc<Value>>, 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(())
|
||||
|
@ -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!!")))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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<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 {
|
||||
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> Vec<Op> {
|
||||
let mut ops = Vec::new();
|
||||
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, 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<Statement>, mut ops: &mut Vec<Op>, root: &Path) {
|
||||
fn translate_stmts(stmts: Vec<Statement>, 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<Op>, 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<u8> = 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<EI: Iterator<Item = Expression>>(
|
||||
pos: Position,
|
||||
part: TemplatePart,
|
||||
elems: &mut EI,
|
||||
mut ops: &mut Vec<Op>,
|
||||
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<Op>, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<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)
|
||||
}
|
||||
|
||||
@ -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<Rc<Value>>,
|
||||
env: Rc<RefCell<Environment<O, E>>>,
|
||||
pos: &Position,
|
||||
) -> Result<Rc<Value>, 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<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 {
|
||||
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<Value>)>,
|
||||
pos: &Position,
|
||||
) -> Result<Rc<Value>, 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<Rc<Value>, Error> {
|
||||
fn find_in_value(&self, index: &Value, target: &Value, pos: &Position) -> Result<Rc<Value>, 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<Value>,
|
||||
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<Rc<Value>, Error> {
|
||||
pub fn get_binding(&'a self, name: &str, pos: &Position) -> Result<Rc<Value>, 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<Rc<Value>, Error> {
|
||||
match self.stack.pop() {
|
||||
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) {
|
||||
(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<Primitive, Error> {
|
||||
fn div(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
|
||||
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<Primitive, Error> {
|
||||
fn sub(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
|
||||
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<Primitive, Error> {
|
||||
fn modulus(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
|
||||
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<Value, Error> {
|
||||
fn add(&self, left: &Value, right: &Value, pos: &Position) -> Result<Value, Error> {
|
||||
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> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user