DEV: pkg() functions *should* work now.

This commit is contained in:
Jeremy Wall 2019-08-17 16:57:45 -05:00
parent d09bd13f42
commit 7bc98514bf
7 changed files with 186 additions and 135 deletions

View File

@ -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<Vec<Op>>>);
impl<'a> Entry<'a> {
pub fn get_pointer_or_else<F: FnOnce() -> Vec<Op>>(self, f: F) -> 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)
OpPointer::new(cached).with_path(path.into())
}
}

View File

@ -104,6 +104,7 @@ pub struct Module {
ptr: OpPointer,
result_ptr: Option<usize>,
flds: Vec<(String, Rc<Value>)>,
pkg_ptr: Option<OpPointer>,
}
#[derive(Debug, PartialEq, Clone)]

View File

@ -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<Vec<Op>>,
pub ptr: Option<usize>,
pub path: Option<PathBuf>,
}
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(),
}
}
}

View File

@ -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() {

View File

@ -395,23 +395,19 @@ fn module_call() {
Sym("two".to_owned()), // 9
Val(Int(2)), // 10
Field, // 11
Module(5), // 12 // Module body definition
Module(7), // 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
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
@ -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);

View File

@ -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<Statement>) -> Vec<Op> {
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> Vec<Op> {
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<Statement>, mut ops: &mut Vec<Op>) {
fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut Vec<Op>, 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<Op>) {
fn translate_expr(expr: Expression, mut ops: &mut Vec<Op>, 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<Op>,
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<Op>) {
fn translate_value(value: Value, mut ops: &mut Vec<Op>, 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);
}
}

View File

@ -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))))?;