diff --git a/src/build/opcode/cache.rs b/src/build/opcode/cache.rs index fec5b04..4cf8037 100644 --- a/src/build/opcode/cache.rs +++ b/src/build/opcode/cache.rs @@ -14,6 +14,7 @@ use std::collections::btree_map; use std::collections::BTreeMap; use std::rc::Rc; +use std::path::PathBuf; use super::{Op, OpPointer}; @@ -37,8 +38,8 @@ impl Ops { pub struct Entry<'a>(btree_map::Entry<'a, String, Rc>>); impl<'a> Entry<'a> { - pub fn get_pointer_or_else Vec>(self, f: F) -> OpPointer { + pub fn get_pointer_or_else Vec, P: Into>(self, f: F, path: P) -> OpPointer { let cached = self.0.or_insert_with(|| Rc::new(f())).clone(); - OpPointer::new(cached) + OpPointer::new(cached).with_path(path.into()) } } diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index 6618549..4d9bde7 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -104,6 +104,7 @@ pub struct Module { ptr: OpPointer, result_ptr: Option, flds: Vec<(String, Rc)>, + pkg_ptr: Option, } #[derive(Debug, PartialEq, Clone)] diff --git a/src/build/opcode/pointer.rs b/src/build/opcode/pointer.rs index 79abb90..7794b48 100644 --- a/src/build/opcode/pointer.rs +++ b/src/build/opcode/pointer.rs @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +use std::path::PathBuf; use std::rc::Rc; use super::{Error, Op}; @@ -19,6 +20,7 @@ use super::{Error, Op}; pub struct OpPointer { pub ops: Rc>, pub ptr: Option, + pub path: Option, } impl OpPointer { @@ -27,9 +29,15 @@ impl OpPointer { Self { ops: ops, ptr: None, + path: None, } } + pub fn with_path(mut self, path: PathBuf) -> Self { + self.path = Some(path); + self + } + pub fn next(&mut self) -> Option<&Op> { if let Some(i) = self.ptr { let nxt = i + 1; @@ -70,6 +78,7 @@ impl OpPointer { Self { ops: self.ops.clone(), ptr: None, + path: self.path.clone(), } } } diff --git a/src/build/opcode/runtime.rs b/src/build/opcode/runtime.rs index f706e33..9b1a9b7 100644 --- a/src/build/opcode/runtime.rs +++ b/src/build/opcode/runtime.rs @@ -21,12 +21,15 @@ use std::rc::Rc; use regex::Regex; use super::environment::Environment; +use super::pointer::OpPointer; use super::Value::{C, F, P, S}; use super::VM; use super::{Composite, Error, Hook, Primitive, Value}; use crate::ast::Position; use crate::build::ir::Val; use crate::build::AssertCollector; +use crate::iter::OffsetStrIter; +use crate::parse::parse; use Composite::{List, Tuple}; use Primitive::{Bool, Empty, Int, Str}; @@ -147,14 +150,24 @@ impl Builtins { if val_cache.contains_key(path) { stack.push(val_cache[path].clone()); } else { - let op_pointer = - env.borrow_mut() - .op_cache - .entry(path) - .get_pointer_or_else(|| { - // FIXME(jwall): import - unimplemented!("Compiling paths are not implemented yet"); - }); + let op_pointer = env.borrow_mut().op_cache.entry(path).get_pointer_or_else( + || { + // FIXME(jwall): We need to do proper error handling here. + let p = PathBuf::from(&path); + let root = p.parent().unwrap(); + // first we read in the file + let mut f = File::open(&path).unwrap(); + // then we parse it + let mut contents = String::new(); + f.read_to_string(&mut contents).unwrap(); + let iter = OffsetStrIter::new(&contents).with_src_file(&p); + let stmts = parse(iter, None).unwrap(); + // then we create an ops from it + let ops = super::translate::AST::translate(stmts, &root); + ops + }, + &path, + ); let mut vm = VM::with_pointer(path, op_pointer, env.clone()); vm.run()?; let result = Rc::new(vm.symbols_to_tuple(true)); @@ -176,7 +189,6 @@ impl Builtins { O: std::io::Write, E: std::io::Write, { - // TODO(jwall): include let path = stack.pop(); let typ = stack.pop(); let path = if let Some(val) = path { @@ -347,7 +359,6 @@ impl Builtins { return Err(dbg!(Error {})); }; - // TODO(jwall): This can also be tuples or strings. match list.as_ref() { &C(List(ref elems)) => { let mut result_elems = Vec::new(); @@ -432,7 +443,6 @@ impl Builtins { return dbg!(Err(Error {})); }; - // TODO(jwall): This can also be tuples or strings. let elems = match list.as_ref() { &C(List(ref elems)) => { let mut result_elems = Vec::new(); @@ -558,7 +568,6 @@ impl Builtins { return dbg!(Err(Error {})); }; - // TODO(jwall): This can also be tuples or strings. match list.as_ref() { &C(List(ref elems)) => { for e in dbg!(elems).iter() { diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 6d52092..60df14b 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -384,34 +384,30 @@ fn module_call() { assert_cases![ vec![ InitTuple, // 0 // override tuple - Sym("one".to_owned()), // 1 - Val(Int(11)), // 2 - Field, // 3 - Sym("m".to_owned()), // 4 // binding name for module - InitTuple, // 5 // Module tuple bindings - Sym("one".to_owned()), // 6 - Val(Int(1)), // 7 - Field, // 8 - Sym("two".to_owned()), // 9 - Val(Int(2)), // 10 - Field, // 11 - Module(5), // 12 // Module body definition - Bind, // 13 // bind the mod tuple - Sym("foo".to_owned()), // 14 - DeRef("mod".to_owned()), // 15 - Bind, // 16 // bind mod tuple to foo - Return, // 17 // end the module - Bind, // 18 // bind module to the binding name - DeRef("m".to_owned()), // 19 - Cp, // 20 // Call the module + Sym("one".to_owned()), // 1 + Val(Int(11)), // 2 + Field, // 3 + Sym("m".to_owned()), // 4 // binding name for module + InitTuple, // 5 // Module tuple bindings + Sym("one".to_owned()), // 6 + Val(Int(1)), // 7 + Field, // 8 + Sym("two".to_owned()), // 9 + Val(Int(2)), // 10 + Field, // 11 + Module(7), // 12 // Module body definition + Bind, // 13 // bind the mod tuple + Sym("foo".to_owned()), // 14 + DeRef("mod".to_owned()), // 15 + Val(Str("one".to_owned())), // 16 + Index, // 17 + Bind, // 18 // bind mod tuple to foo + Return, // 19 // end the module + Bind, // 20 // bind module to the binding name + DeRef("m".to_owned()), // 21 + Cp, // 22 // Call the module ] => C(Tuple(vec![ - ( - "foo".to_owned(), - Rc::new(C(Tuple(vec![ - ("one".to_owned(), Rc::new(P(Int(11)))), - ("two".to_owned(), Rc::new(P(Int(2)))), - ]))) - ), + ("foo".to_owned(), Rc::new(P(Int(11)))), ])), vec![ InitTuple, // 0 // override tuple @@ -429,7 +425,7 @@ fn module_call() { InitThunk(2), // 12 // Module Return expression Val(Int(1)), // 13 Return, // 14 - Module(5), // 15 // Module definition + Module(5), // 15 // Module definition Bind, // 16 Sym("foo".to_owned()), // 17 DeRef("mod".to_owned()), // 18 @@ -577,8 +573,9 @@ macro_rules! assert_parse_cases { (__impl__ $cases:expr) => { for case in $cases.drain(0..) { let stmts = parse(OffsetStrIter::from(dbg!(case.0)), None).unwrap(); + let root = std::env::current_dir().unwrap(); // TODO(jwall): preprocessor - let ops = Rc::new(translate::AST::translate(stmts)); + 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); @@ -762,7 +759,8 @@ fn simple_selects() { #[test] fn simple_trace() { let stmts = parse(OffsetStrIter::from(dbg!("TRACE 1+1;")), None).unwrap(); - let ops = Rc::new(translate::AST::translate(stmts)); + let root = std::env::current_dir().unwrap(); + 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); diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 2372155..3c2d037 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -11,6 +11,8 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +use std::path::Path; + use crate::ast::{BinaryExprType, Expression, FormatArgs, Statement, Value}; use crate::ast::{FuncOpDef, TemplatePart}; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; @@ -20,23 +22,23 @@ use crate::build::opcode::{Hook, Op}; pub struct AST(); impl AST { - pub fn translate(stmts: Vec) -> Vec { + pub fn translate>(stmts: Vec, root: &P) -> Vec { let mut ops = Vec::new(); - Self::translate_stmts(stmts, &mut ops); + Self::translate_stmts(stmts, &mut ops, root.as_ref()); return ops; } - fn translate_stmts(stmts: Vec, mut ops: &mut Vec) { + fn translate_stmts(stmts: Vec, mut ops: &mut Vec, root: &Path) { for stmt in stmts { match stmt { - Statement::Expression(expr) => Self::translate_expr(expr, &mut ops), + Statement::Expression(expr) => Self::translate_expr(expr, &mut ops, root), Statement::Assert(_, _) => { unimplemented!("Assert statements are not implmented yet") } Statement::Let(def) => { let binding = def.name.fragment; ops.push(Op::Sym(binding)); - Self::translate_expr(def.value, &mut ops); + Self::translate_expr(def.value, &mut ops, root); ops.push(Op::Bind); } Statement::Output(_, _, _) => { @@ -49,107 +51,106 @@ impl AST { } } - fn translate_expr(expr: Expression, mut ops: &mut Vec) { + fn translate_expr(expr: Expression, mut ops: &mut Vec, root: &Path) { match expr { Expression::Simple(v) => { - Self::translate_value(v, &mut ops); + Self::translate_value(v, &mut ops, root); } Expression::Binary(def) => { match def.kind { BinaryExprType::Add => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Add); } BinaryExprType::Sub => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Sub); } BinaryExprType::Div => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Div); } BinaryExprType::Mul => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Mul); } BinaryExprType::Equal => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Equal); } BinaryExprType::GT => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Gt); } BinaryExprType::LT => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Lt); } BinaryExprType::GTEqual => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::GtEq); } BinaryExprType::LTEqual => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::LtEq); } BinaryExprType::NotEqual => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Equal); ops.push(Op::Not); } BinaryExprType::REMatch => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Runtime(Hook::Regex)); } BinaryExprType::NotREMatch => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Runtime(Hook::Regex)); ops.push(Op::Not); } BinaryExprType::IS => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Typ); ops.push(Op::Equal); } BinaryExprType::AND => { - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Noop); let idx = ops.len() - 1; - Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); let jptr = (ops.len() - 1 - idx) as i32; ops[idx] = Op::And(dbg!(jptr)); dbg!(ops); } BinaryExprType::OR => { - // FIXME(jwall): This needs to be handled very differently - Self::translate_expr(*def.left, &mut ops); - ops.push(Op::Noop); // Placeholder used for + Self::translate_expr(*def.left, &mut ops, root); + ops.push(Op::Noop); // Placeholder let idx = ops.len() - 1; - Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); let jptr = (ops.len() - 1 - idx) as i32; ops[idx] = Op::Or(jptr); } BinaryExprType::Mod => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); + Self::translate_expr(*def.left, &mut ops, root); ops.push(Op::Mod); } BinaryExprType::IN => { // Dot expressions expect the left side to be pushed first - Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.right, &mut ops, root); // Symbols on the right side should be converted to strings to satisfy // the Index operation contract. match *def.left { @@ -157,10 +158,11 @@ impl AST { Self::translate_expr( Expression::Simple(Value::Str(name)), &mut ops, + root, ); } expr => { - Self::translate_expr(expr, &mut ops); + Self::translate_expr(expr, &mut ops, root); } } ops.push(Op::SafeIndex); @@ -170,7 +172,7 @@ impl AST { } BinaryExprType::DOT => { // Dot expressions expect the left side to be pushed first - Self::translate_expr(*def.left, &mut ops); + Self::translate_expr(*def.left, &mut ops, root); // Symbols on the right side should be converted to strings to satisfy // the Index operation contract. match *def.right { @@ -178,10 +180,11 @@ impl AST { Self::translate_expr( Expression::Simple(Value::Str(name)), &mut ops, + root, ); } expr => { - Self::translate_expr(expr, &mut ops); + Self::translate_expr(expr, &mut ops, root); } } ops.push(Op::Index); @@ -189,15 +192,13 @@ impl AST { }; } Expression::Grouped(expr, _) => { - Self::translate_expr(*expr, &mut ops); + Self::translate_expr(*expr, &mut ops, root); } Expression::Fail(def) => { - Self::translate_expr(*def.message, &mut ops); + Self::translate_expr(*def.message, &mut ops, root); ops.push(Op::Bang); } Expression::Format(def) => { - // TODO(jwall): It would actually be safer if this was happening - // when we create the format def instead of here. match def.args { FormatArgs::List(mut elems) => { let formatter = SimpleTemplate::new(); @@ -215,9 +216,10 @@ impl AST { &mut elems_iter, &mut ops, true, + root, ); for p in parts_iter { - Self::translate_template_part(p, &mut elems_iter, &mut ops, true); + Self::translate_template_part(p, &mut elems_iter, &mut ops, true, root); ops.push(Op::Add); } } @@ -228,14 +230,13 @@ impl AST { let mut parts = formatter.parse(&def.template).unwrap(); parts.reverse(); let mut parts_iter = parts.drain(0..); - // TODO(jwall): We need to assume there is a new scope introduced now ops.push(Op::Noop); let scope_idx = ops.len() - 1; // Add our item binding shadowing any binding that already // existed. ops.push(Op::Sym("item".to_owned())); - Self::translate_expr(*expr, &mut ops); + Self::translate_expr(*expr, &mut ops, root); ops.push(Op::BindOver); let mut elems = Vec::new(); let mut elems_iter = elems.drain(0..); @@ -244,9 +245,16 @@ impl AST { &mut elems_iter, &mut ops, false, + root, ); for p in parts_iter { - Self::translate_template_part(p, &mut elems_iter, &mut ops, false); + Self::translate_template_part( + p, + &mut elems_iter, + &mut ops, + false, + root, + ); ops.push(Op::Add); } ops.push(Op::Return); @@ -263,7 +271,7 @@ impl AST { } ops.push(Op::Noop); let idx = ops.len() - 1; - Self::translate_expr(*def.fields, &mut ops); + Self::translate_expr(*def.fields, &mut ops, root); ops.push(Op::Return); let jptr = ops.len() - 1 - idx; ops[idx] = Op::Func(jptr as i32); @@ -272,27 +280,27 @@ impl AST { match def { FuncOpDef::Map(def) => { // push the function on the stack first. - Self::translate_expr(*def.func, &mut ops); + Self::translate_expr(*def.func, &mut ops, root); // push the target on the stack third - Self::translate_expr(*def.target, &mut ops); + Self::translate_expr(*def.target, &mut ops, root); // finally push the Hook::Map opcode ops.push(Op::Runtime(Hook::Map)); } FuncOpDef::Filter(def) => { // push the function on the stack first. - Self::translate_expr(*def.func, &mut ops); + Self::translate_expr(*def.func, &mut ops, root); // push the target on the stack third - Self::translate_expr(*def.target, &mut ops); + Self::translate_expr(*def.target, &mut ops, root); // finally push the Hook::Map opcode ops.push(Op::Runtime(Hook::Filter)); } FuncOpDef::Reduce(def) => { // push the function on the stack first. - Self::translate_expr(*def.func, &mut ops); + Self::translate_expr(*def.func, &mut ops, root); // push the accumulator on the stack third - Self::translate_expr(*def.acc, &mut ops); + Self::translate_expr(*def.acc, &mut ops, root); // push the target on the stack third - Self::translate_expr(*def.target, &mut ops); + Self::translate_expr(*def.target, &mut ops, root); // finally push the Hook::Map opcode ops.push(Op::Runtime(Hook::Reduce)); } @@ -307,7 +315,8 @@ impl AST { ops.push(Op::Val(Primitive::Str(def.path.fragment))); ops.push(Op::Runtime(Hook::Include)); } - Expression::Module(def) => { + Expression::Module(mut def) => { + def.imports_to_absolute(root.to_path_buf()); let argset = def.arg_set; let out_expr = def.out_expr; let stmts = def.statements; @@ -315,7 +324,7 @@ impl AST { ops.push(Op::InitTuple); for (t, e) in argset { ops.push(Op::Sym(t.fragment)); - Self::translate_expr(e, &mut ops); + Self::translate_expr(e, &mut ops, root); ops.push(Op::Field); } // If there is one then emit our return expression @@ -323,7 +332,7 @@ impl AST { // Insert placeholder until we know jptr for this thunk ops.push(Op::Noop); let idx = ops.len() - 1; - Self::translate_expr(*expr, &mut ops); + Self::translate_expr(*expr, &mut ops, root); ops.push(Op::Return); let jptr = ops.len() - idx - 1; ops[idx] = Op::InitThunk(jptr as i32); @@ -335,34 +344,34 @@ impl AST { // Bind our mod tuple. ops.push(Op::Bind); // emit all of our statements; - Self::translate_stmts(stmts, &mut ops); + Self::translate_stmts(stmts, &mut ops, root); // Return from the module ops.push(Op::Return); let jptr = ops.len() - idx - 1; ops[idx] = Op::Module(jptr as i32); } Expression::Not(def) => { - Self::translate_expr(*def.expr, &mut ops); + Self::translate_expr(*def.expr, &mut ops, root); ops.push(Op::Not); } Expression::Range(def) => { - Self::translate_expr(*def.end, &mut ops); + Self::translate_expr(*def.end, &mut ops, root); if let Some(expr) = def.step { - Self::translate_expr(*expr, &mut ops); + Self::translate_expr(*expr, &mut ops, root); } else { ops.push(Op::Val(Primitive::Empty)); } - Self::translate_expr(*def.start, &mut ops); + Self::translate_expr(*def.start, &mut ops, root); ops.push(Op::Runtime(Hook::Range)); } Expression::Select(def) => { - Self::translate_expr(*def.val, &mut ops); + Self::translate_expr(*def.val, &mut ops, root); let mut jumps = Vec::new(); for (key, val) in def.tuple { ops.push(Op::Sym(key.fragment)); ops.push(Op::Noop); let idx = ops.len() - 1; - Self::translate_expr(val, &mut ops); + Self::translate_expr(val, &mut ops, root); ops.push(Op::Noop); jumps.push(ops.len() - 1); let jptr = ops.len() - idx - 1; @@ -375,7 +384,7 @@ impl AST { ops[i] = Op::Jump(idx as i32); } if let Some(default) = def.default { - Self::translate_expr(*default, &mut ops); + Self::translate_expr(*default, &mut ops, root); } else { ops.push(Op::Bang); } @@ -384,10 +393,10 @@ impl AST { Expression::Call(def) => { // first push our arguments. for e in def.arglist { - Self::translate_expr(e, &mut ops); + Self::translate_expr(e, &mut ops, root); } // then push the func reference - Self::translate_value(def.funcref, &mut ops); + Self::translate_value(def.funcref, &mut ops, root); ops.push(Op::FCall); dbg!(ops); } @@ -395,10 +404,10 @@ impl AST { ops.push(Op::InitTuple); for (t, e) in def.fields { ops.push(Op::Sym(t.fragment)); - Self::translate_expr(e, &mut ops); + Self::translate_expr(e, &mut ops, root); ops.push(Op::Field); } - Self::translate_value(def.selector, &mut ops); + Self::translate_value(def.selector, &mut ops, root); ops.push(Op::Cp); } Expression::Debug(def) => { @@ -409,7 +418,7 @@ impl AST { } let expr_pretty = String::from_utf8(buffer).unwrap(); ops.push(Op::Val(Primitive::Str(expr_pretty))); - Self::translate_expr(*def.expr, &mut ops); + Self::translate_expr(*def.expr, &mut ops, root); ops.push(Op::Runtime(Hook::Trace(def.pos))); } } @@ -420,6 +429,7 @@ impl AST { elems: &mut EI, mut ops: &mut Vec, place_holder: bool, + root: &Path, ) { match part { TemplatePart::Str(s) => { @@ -430,7 +440,7 @@ impl AST { // In theory this should never be reachable unreachable!(); } else { - Self::translate_expr(elems.next().unwrap(), &mut ops); + Self::translate_expr(elems.next().unwrap(), &mut ops, root); ops.push(Op::Render); } } @@ -438,14 +448,14 @@ impl AST { if place_holder { unreachable!(); } else { - Self::translate_expr(expr, &mut ops); + Self::translate_expr(expr, &mut ops, root); ops.push(Op::Render); } } } } - fn translate_value(value: Value, mut ops: &mut Vec) { + fn translate_value(value: Value, mut ops: &mut Vec, root: &Path) { match value { Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))), @@ -459,14 +469,14 @@ impl AST { ops.push(Op::InitTuple); for (k, v) in flds.val { ops.push(Op::Sym(k.fragment)); - Self::translate_expr(v, &mut ops); + Self::translate_expr(v, &mut ops, root); ops.push(Op::Field); } } Value::List(els) => { ops.push(Op::InitList); for el in els.elems { - Self::translate_expr(el, &mut ops); + Self::translate_expr(el, &mut ops, root); ops.push(Op::Element); } } diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index 5bbad74..72e0be9 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -274,10 +274,23 @@ where }; let mut ops = self.ops.clone(); ops.jump(idx)?; + let pkg_ptr = if let Some(ref path) = self.ops.path { + let pkg_ops = vec![ + Op::InitList, + Op::Func(3), + Op::Val(Str(path.to_string_lossy().to_string())), + Op::Runtime(Hook::Import), + Op::Return, + ]; + Some(OpPointer::new(Rc::new(pkg_ops))) + } else { + None + }; self.push(Rc::new(M(Module { ptr: ops, result_ptr: result_ptr, flds: flds, + pkg_ptr: pkg_ptr, })))?; self.op_jump(jptr) } @@ -589,8 +602,8 @@ where fn op_index(&mut self, safe: bool) -> Result<(), Error> { // left and then right - let right = self.pop()?; - let left = self.pop()?; + let right = dbg!(self.pop()?); + let left = dbg!(self.pop()?); match right.as_ref() { &P(Int(i)) => { if let &C(List(ref elems)) = left.as_ref() { @@ -645,18 +658,28 @@ where ref ptr, ref result_ptr, ref flds, + ref pkg_ptr, }) => { - //let this = M(Module { - // ptr: ptr.clone(), - // result_ptr: result_ptr.clone(), - // flds: flds.clone(), - //}); + let this = M(Module { + ptr: ptr.clone(), + result_ptr: result_ptr.clone(), + flds: flds.clone(), + pkg_ptr: pkg_ptr.clone(), + }); + let mut flds = flds.clone(); for (name, val) in overrides { self.merge_field_into_tuple(&mut flds, name, val)?; } - // FIXME(jwall): We need to populate the pkg key for modules. - //self.merge_field_into_tuple(&mut flds, "this".to_owned(), this)?; + 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()); + 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()); vm.push(Rc::new(S("mod".to_owned())))?; vm.push(Rc::new(C(Tuple(flds))))?;