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