DEV: Better file path handling through pointers.

This commit is contained in:
Jeremy Wall 2019-08-17 17:41:49 -05:00
parent 7bc98514bf
commit ceb98244c7
4 changed files with 43 additions and 60 deletions

View File

@ -13,8 +13,8 @@
// limitations under the License.
use std::collections::btree_map;
use std::collections::BTreeMap;
use std::rc::Rc;
use std::path::PathBuf;
use std::rc::Rc;
use super::{Op, OpPointer};
@ -38,7 +38,11 @@ impl Ops {
pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<Vec<Op>>>);
impl<'a> Entry<'a> {
pub fn get_pointer_or_else<F: FnOnce() -> Vec<Op>, P: Into<PathBuf>>(self, f: F, path: P) -> OpPointer {
pub fn get_pointer_or_else<F: FnOnce() -> Vec<Op>, P: Into<PathBuf>>(
self,
f: F,
path: P,
) -> OpPointer {
let cached = self.0.or_insert_with(|| Rc::new(f())).clone();
OpPointer::new(cached).with_path(path.into())
}

View File

@ -62,7 +62,7 @@ impl Builtins {
pub fn handle<P: AsRef<Path>, O, E>(
&mut self,
path: P,
path: Option<P>,
h: Hook,
stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>,
@ -77,9 +77,9 @@ impl Builtins {
Hook::Assert => self.assert(stack),
Hook::Convert => self.convert(stack, env),
Hook::Out => self.out(path, stack, env),
Hook::Map => self.map(path, stack, env),
Hook::Filter => self.filter(path, stack, env),
Hook::Reduce => self.reduce(path, stack, env),
Hook::Map => self.map(stack, env),
Hook::Filter => self.filter(stack, env),
Hook::Reduce => self.reduce(stack, env),
Hook::Regex => self.regex(stack),
Hook::Range => self.range(stack),
Hook::Trace(pos) => self.trace(stack, pos, env),
@ -168,7 +168,7 @@ impl Builtins {
},
&path,
);
let mut vm = VM::with_pointer(path, op_pointer, env.clone());
let mut vm = VM::with_pointer(op_pointer, env.clone());
vm.run()?;
let result = Rc::new(vm.symbols_to_tuple(true));
val_cache.insert(path.clone(), result.clone());
@ -269,7 +269,7 @@ impl Builtins {
fn out<P: AsRef<Path>, O, E>(
&self,
path: P,
path: Option<P>,
stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>,
) -> Result<(), Error>
@ -277,6 +277,11 @@ impl Builtins {
O: std::io::Write,
E: std::io::Write,
{
let path = if let Some(path) = path {
path
} else {
return Err(dbg!(Error {}));
};
let val = stack.pop();
if let Some(val) = val {
let val = val.try_into()?;
@ -330,9 +335,8 @@ impl Builtins {
return Err(dbg!(Error {}));
}
fn map<P: AsRef<Path>, O, E>(
fn map<O, E>(
&self,
path: P,
stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>,
) -> Result<(), Error>
@ -366,12 +370,7 @@ impl Builtins {
// push function argument on the stack.
stack.push(e.clone());
// call function and push it's result on the stack.
result_elems.push(VM::fcall_impl(
path.as_ref().to_owned(),
f,
stack,
env.clone(),
)?);
result_elems.push(VM::fcall_impl(f, stack, env.clone())?);
}
stack.push(Rc::new(C(List(result_elems))));
}
@ -380,7 +379,7 @@ impl Builtins {
for (ref name, ref val) in _flds {
stack.push(val.clone());
stack.push(Rc::new(P(Str(name.clone()))));
let result = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
let result = VM::fcall_impl(f, stack, env.clone())?;
if let &C(List(ref fval)) = result.as_ref() {
// we expect them to be a list of exactly 2 items.
if fval.len() != 2 {
@ -400,7 +399,7 @@ impl Builtins {
for c in s.chars() {
stack.push(Rc::new(P(Str(c.to_string()))));
// call function and push it's result on the stack.
let result = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
let result = VM::fcall_impl(f, stack, env.clone())?;
if let &P(Str(ref s)) = result.as_ref() {
buf.push_str(s);
} else {
@ -414,9 +413,8 @@ impl Builtins {
Ok(())
}
fn filter<P: AsRef<Path>, O, E>(
fn filter<O, E>(
&self,
path: P,
stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>,
) -> Result<(), Error>
@ -450,8 +448,7 @@ impl Builtins {
// push function argument on the stack.
stack.push(e.clone());
// call function and push it's result on the stack.
let condition =
VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
let condition = VM::fcall_impl(f, stack, env.clone())?;
// Check for empty or boolean results and only push e back in
// if they are non empty and true
match condition.as_ref() {
@ -468,8 +465,7 @@ impl Builtins {
for (ref name, ref val) in _flds {
stack.push(val.clone());
stack.push(Rc::new(P(Str(name.clone()))));
let condition =
VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
let condition = VM::fcall_impl(f, stack, env.clone())?;
// Check for empty or boolean results and only push e back in
// if they are non empty and true
match condition.as_ref() {
@ -486,8 +482,7 @@ impl Builtins {
for c in s.chars() {
stack.push(Rc::new(P(Str(c.to_string()))));
// call function and push it's result on the stack.
let condition =
VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
let condition = VM::fcall_impl(f, stack, env.clone())?;
// Check for empty or boolean results and only push c back in
// if they are non empty and true
match condition.as_ref() {
@ -533,9 +528,8 @@ impl Builtins {
Ok(())
}
fn reduce<P: AsRef<Path>, O, E>(
fn reduce<O, E>(
&self,
path: P,
stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>,
) -> Result<(), Error>
@ -575,7 +569,7 @@ impl Builtins {
stack.push(dbg!(e.clone()));
stack.push(dbg!(acc.clone()));
// call function and push it's result on the stack.
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
acc = VM::fcall_impl(f, stack, env.clone())?;
}
}
&C(Tuple(ref _flds)) => {
@ -585,7 +579,7 @@ impl Builtins {
stack.push(Rc::new(P(Str(name.clone()))));
stack.push(dbg!(acc.clone()));
// call function and push it's result on the stack.
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
acc = VM::fcall_impl(f, stack, env.clone())?;
}
}
&P(Str(ref _s)) => {
@ -594,7 +588,7 @@ impl Builtins {
stack.push(dbg!(Rc::new(P(Str(c.to_string())))));
stack.push(dbg!(acc.clone()));
// call function and push it's result on the stack.
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
acc = VM::fcall_impl(f, stack, env.clone())?;
}
}
_ => return Err(dbg!(Error {})),

View File

@ -30,7 +30,7 @@ macro_rules! assert_cases {
(__impl__ $cases:expr) => {
for case in $cases.drain(0..) {
let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new())));
let mut vm = VM::new("foo.ucg", Rc::new(case.0), env);
let mut vm = VM::new(Rc::new(case.0), env);
vm.run().unwrap();
assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1));
}
@ -120,7 +120,7 @@ fn bind_op() {
for case in cases.drain(0..) {
let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new())));
let mut vm = VM::new("bar.ucg", Rc::new(case.0), env);
let mut vm = VM::new(Rc::new(case.0), env);
vm.run().unwrap();
let (name, result) = case.1;
let v = vm.get_binding(name).unwrap();
@ -578,7 +578,7 @@ macro_rules! assert_parse_cases {
let ops = Rc::new(translate::AST::translate(stmts, &root));
assert!(ops.len() > 0);
let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new())));
let mut vm = VM::new("foo.ucg", ops.clone(), env);
let mut vm = VM::new(ops.clone(), env);
vm.run().unwrap();
assert_eq!(vm.pop().unwrap(), Rc::new(case.1));
}
@ -763,7 +763,7 @@ fn simple_trace() {
let ops = Rc::new(translate::AST::translate(stmts, &root));
assert!(ops.len() > 0);
let env = Rc::new(RefCell::new(Environment::new(Vec::new(), Vec::new())));
let mut vm = VM::new("foo.ucg", ops.clone(), env);
let mut vm = VM::new(ops.clone(), env);
vm.run().unwrap();
assert_eq!(vm.pop().unwrap(), Rc::new(P(Int(2))));
let err_out = &vm.env.borrow().stderr;

View File

@ -35,8 +35,6 @@ where
symbols: Stack,
runtime: runtime::Builtins,
ops: OpPointer,
// TODO(jwall): This should be optional
path: PathBuf,
pub env: Rc<RefCell<Environment<O, E>>>,
}
@ -45,25 +43,16 @@ where
O: std::io::Write,
E: std::io::Write,
{
pub fn new<P: Into<PathBuf>>(
path: P,
ops: Rc<Vec<Op>>,
env: Rc<RefCell<Environment<O, E>>>,
) -> Self {
Self::with_pointer(path, OpPointer::new(ops), env)
pub fn new(ops: Rc<Vec<Op>>, env: Rc<RefCell<Environment<O, E>>>) -> Self {
Self::with_pointer(OpPointer::new(ops), env)
}
pub fn with_pointer<P: Into<PathBuf>>(
path: P,
ops: OpPointer,
env: Rc<RefCell<Environment<O, E>>>,
) -> Self {
pub fn with_pointer(ops: OpPointer, env: Rc<RefCell<Environment<O, E>>>) -> Self {
Self {
stack: Vec::new(),
symbols: Stack::new(),
runtime: runtime::Builtins::new(),
ops: ops,
path: path.into(),
env: env,
}
}
@ -74,7 +63,6 @@ where
symbols: symbols,
runtime: self.runtime.clone(),
ops: self.ops.clone(),
path: self.path.clone(),
env: self.env.clone(),
}
}
@ -327,8 +315,7 @@ where
self.op_jump(jptr)
}
pub fn fcall_impl<P: Into<PathBuf>>(
path: P,
pub fn fcall_impl(
f: &Func,
stack: &mut Vec<Rc<Value>>,
env: Rc<RefCell<Environment<O, E>>>,
@ -339,7 +326,7 @@ where
ref snapshot,
} = f;
// use the captured scope snapshot for the function.
let mut vm = Self::with_pointer(path, ptr.clone(), env).to_scoped(snapshot.clone());
let mut vm = Self::with_pointer(ptr.clone(), env).to_scoped(snapshot.clone());
for nm in bindings.iter() {
// now put each argument on our scope stack as a binding.
// TODO(jwall): This should do a better error if there is
@ -355,8 +342,7 @@ where
fn op_new_scope(&mut self, jp: i32, ptr: OpPointer) -> Result<(), Error> {
let scope_snapshot = self.symbols.snapshot();
dbg!(&ptr);
let mut vm =
Self::with_pointer(&self.path, ptr, self.env.clone()).to_scoped(scope_snapshot);
let mut vm = Self::with_pointer(ptr, self.env.clone()).to_scoped(scope_snapshot);
dbg!(&vm.stack);
vm.run()?;
dbg!(&vm.stack);
@ -368,7 +354,7 @@ where
fn op_fcall(&mut self) -> Result<(), Error> {
let f = dbg!(self.pop())?;
if let &F(ref f) = f.as_ref() {
let val = Self::fcall_impl(&self.path, f, &mut self.stack, self.env.clone())?;
let val = Self::fcall_impl(f, &mut self.stack, self.env.clone())?;
self.push(dbg!(val))?;
}
Ok(())
@ -673,14 +659,13 @@ where
}
self.merge_field_into_tuple(&mut flds, "this".to_owned(), Rc::new(this))?;
if let Some(ptr) = pkg_ptr {
let mut pkg_vm =
Self::with_pointer(self.path.clone(), ptr.clone(), self.env.clone());
let mut pkg_vm = Self::with_pointer(ptr.clone(), self.env.clone());
pkg_vm.run()?;
let pkg_func = pkg_vm.pop()?;
self.merge_field_into_tuple(&mut flds, "pkg".to_owned(), pkg_func)?;
}
let mut vm = Self::with_pointer(self.path.clone(), ptr.clone(), self.env.clone());
let mut vm = Self::with_pointer(ptr.clone(), self.env.clone());
vm.push(Rc::new(S("mod".to_owned())))?;
vm.push(Rc::new(C(Tuple(flds))))?;
vm.run()?;
@ -806,7 +791,7 @@ where
fn op_runtime(&mut self, h: Hook) -> Result<(), Error> {
self.runtime
.handle(&self.path, h, &mut self.stack, self.env.clone())
.handle(self.ops.path.as_ref(), h, &mut self.stack, self.env.clone())
}
fn op_render(&mut self) -> Result<(), Error> {