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