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::btree_map;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::rc::Rc; use std::rc::Rc;
use std::path::PathBuf;
use super::{Op, OpPointer}; use super::{Op, OpPointer};
@ -37,8 +38,8 @@ impl Ops {
pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<Vec<Op>>>); pub struct Entry<'a>(btree_map::Entry<'a, String, Rc<Vec<Op>>>);
impl<'a> Entry<'a> { 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(); 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, ptr: OpPointer,
result_ptr: Option<usize>, result_ptr: Option<usize>,
flds: Vec<(String, Rc<Value>)>, flds: Vec<(String, Rc<Value>)>,
pkg_ptr: Option<OpPointer>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use super::{Error, Op}; use super::{Error, Op};
@ -19,6 +20,7 @@ use super::{Error, Op};
pub struct OpPointer { pub struct OpPointer {
pub ops: Rc<Vec<Op>>, pub ops: Rc<Vec<Op>>,
pub ptr: Option<usize>, pub ptr: Option<usize>,
pub path: Option<PathBuf>,
} }
impl OpPointer { impl OpPointer {
@ -27,9 +29,15 @@ impl OpPointer {
Self { Self {
ops: ops, ops: ops,
ptr: None, 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> { 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;
@ -70,6 +78,7 @@ impl OpPointer {
Self { Self {
ops: self.ops.clone(), ops: self.ops.clone(),
ptr: None, ptr: None,
path: self.path.clone(),
} }
} }
} }

View File

@ -21,12 +21,15 @@ 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, S}; 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;
use crate::build::ir::Val; use crate::build::ir::Val;
use crate::build::AssertCollector; use crate::build::AssertCollector;
use crate::iter::OffsetStrIter;
use crate::parse::parse;
use Composite::{List, Tuple}; use Composite::{List, Tuple};
use Primitive::{Bool, Empty, Int, Str}; use Primitive::{Bool, Empty, Int, Str};
@ -147,14 +150,24 @@ impl Builtins {
if val_cache.contains_key(path) { if val_cache.contains_key(path) {
stack.push(val_cache[path].clone()); stack.push(val_cache[path].clone());
} else { } else {
let op_pointer = let op_pointer = env.borrow_mut().op_cache.entry(path).get_pointer_or_else(
env.borrow_mut() || {
.op_cache // FIXME(jwall): We need to do proper error handling here.
.entry(path) let p = PathBuf::from(&path);
.get_pointer_or_else(|| { let root = p.parent().unwrap();
// FIXME(jwall): import // first we read in the file
unimplemented!("Compiling paths are not implemented yet"); 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()); let mut vm = VM::with_pointer(path, op_pointer, env.clone());
vm.run()?; vm.run()?;
let result = Rc::new(vm.symbols_to_tuple(true)); let result = Rc::new(vm.symbols_to_tuple(true));
@ -176,7 +189,6 @@ impl Builtins {
O: std::io::Write, O: std::io::Write,
E: std::io::Write, E: std::io::Write,
{ {
// TODO(jwall): include
let path = stack.pop(); let path = stack.pop();
let typ = stack.pop(); let typ = stack.pop();
let path = if let Some(val) = path { let path = if let Some(val) = path {
@ -347,7 +359,6 @@ impl Builtins {
return Err(dbg!(Error {})); return Err(dbg!(Error {}));
}; };
// TODO(jwall): This can also be tuples or strings.
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();
@ -432,7 +443,6 @@ impl Builtins {
return dbg!(Err(Error {})); return dbg!(Err(Error {}));
}; };
// TODO(jwall): This can also be tuples or strings.
let elems = match list.as_ref() { let elems = match list.as_ref() {
&C(List(ref elems)) => { &C(List(ref elems)) => {
let mut result_elems = Vec::new(); let mut result_elems = Vec::new();
@ -558,7 +568,6 @@ impl Builtins {
return dbg!(Err(Error {})); return dbg!(Err(Error {}));
}; };
// TODO(jwall): This can also be tuples or strings.
match list.as_ref() { match list.as_ref() {
&C(List(ref elems)) => { &C(List(ref elems)) => {
for e in dbg!(elems).iter() { for e in dbg!(elems).iter() {

View File

@ -384,34 +384,30 @@ fn module_call() {
assert_cases![ assert_cases![
vec![ vec![
InitTuple, // 0 // override tuple InitTuple, // 0 // override tuple
Sym("one".to_owned()), // 1 Sym("one".to_owned()), // 1
Val(Int(11)), // 2 Val(Int(11)), // 2
Field, // 3 Field, // 3
Sym("m".to_owned()), // 4 // binding name for module Sym("m".to_owned()), // 4 // binding name for module
InitTuple, // 5 // Module tuple bindings InitTuple, // 5 // Module tuple bindings
Sym("one".to_owned()), // 6 Sym("one".to_owned()), // 6
Val(Int(1)), // 7 Val(Int(1)), // 7
Field, // 8 Field, // 8
Sym("two".to_owned()), // 9 Sym("two".to_owned()), // 9
Val(Int(2)), // 10 Val(Int(2)), // 10
Field, // 11 Field, // 11
Module(5), // 12 // Module body definition Module(7), // 12 // Module body definition
Bind, // 13 // bind the mod tuple Bind, // 13 // bind the mod tuple
Sym("foo".to_owned()), // 14 Sym("foo".to_owned()), // 14
DeRef("mod".to_owned()), // 15 DeRef("mod".to_owned()), // 15
Bind, // 16 // bind mod tuple to foo Val(Str("one".to_owned())), // 16
Return, // 17 // end the module Index, // 17
Bind, // 18 // bind module to the binding name Bind, // 18 // bind mod tuple to foo
DeRef("m".to_owned()), // 19 Return, // 19 // end the module
Cp, // 20 // Call the module Bind, // 20 // bind module to the binding name
DeRef("m".to_owned()), // 21
Cp, // 22 // Call the module
] => C(Tuple(vec![ ] => C(Tuple(vec![
( ("foo".to_owned(), Rc::new(P(Int(11)))),
"foo".to_owned(),
Rc::new(C(Tuple(vec![
("one".to_owned(), Rc::new(P(Int(11)))),
("two".to_owned(), Rc::new(P(Int(2)))),
])))
),
])), ])),
vec![ vec![
InitTuple, // 0 // override tuple InitTuple, // 0 // override tuple
@ -429,7 +425,7 @@ fn module_call() {
InitThunk(2), // 12 // Module Return expression InitThunk(2), // 12 // Module Return expression
Val(Int(1)), // 13 Val(Int(1)), // 13
Return, // 14 Return, // 14
Module(5), // 15 // Module definition Module(5), // 15 // Module definition
Bind, // 16 Bind, // 16
Sym("foo".to_owned()), // 17 Sym("foo".to_owned()), // 17
DeRef("mod".to_owned()), // 18 DeRef("mod".to_owned()), // 18
@ -577,8 +573,9 @@ macro_rules! assert_parse_cases {
(__impl__ $cases:expr) => { (__impl__ $cases:expr) => {
for case in $cases.drain(0..) { for case in $cases.drain(0..) {
let stmts = parse(OffsetStrIter::from(dbg!(case.0)), None).unwrap(); let stmts = parse(OffsetStrIter::from(dbg!(case.0)), None).unwrap();
let root = std::env::current_dir().unwrap();
// TODO(jwall): preprocessor // TODO(jwall): preprocessor
let ops = Rc::new(translate::AST::translate(stmts)); let ops = Rc::new(translate::AST::translate(stmts, &root));
assert!(ops.len() > 0); assert!(ops.len() > 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("foo.ucg", ops.clone(), env); let mut vm = VM::new("foo.ucg", ops.clone(), env);
@ -762,7 +759,8 @@ fn simple_selects() {
#[test] #[test]
fn simple_trace() { fn simple_trace() {
let stmts = parse(OffsetStrIter::from(dbg!("TRACE 1+1;")), None).unwrap(); 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); assert!(ops.len() > 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("foo.ucg", ops.clone(), env); 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. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::path::Path;
use crate::ast::{BinaryExprType, Expression, FormatArgs, Statement, Value}; use crate::ast::{BinaryExprType, Expression, FormatArgs, 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};
@ -20,23 +22,23 @@ use crate::build::opcode::{Hook, Op};
pub struct AST(); pub struct AST();
impl 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(); let mut ops = Vec::new();
Self::translate_stmts(stmts, &mut ops); Self::translate_stmts(stmts, &mut ops, root.as_ref());
return ops; 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 { for stmt in stmts {
match stmt { match stmt {
Statement::Expression(expr) => Self::translate_expr(expr, &mut ops), Statement::Expression(expr) => Self::translate_expr(expr, &mut ops, root),
Statement::Assert(_, _) => { Statement::Assert(_, _) => {
unimplemented!("Assert statements are not implmented yet") unimplemented!("Assert statements are not implmented yet")
} }
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));
Self::translate_expr(def.value, &mut ops); Self::translate_expr(def.value, &mut ops, root);
ops.push(Op::Bind); ops.push(Op::Bind);
} }
Statement::Output(_, _, _) => { 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 { match expr {
Expression::Simple(v) => { Expression::Simple(v) => {
Self::translate_value(v, &mut ops); Self::translate_value(v, &mut ops, root);
} }
Expression::Binary(def) => { Expression::Binary(def) => {
match def.kind { match def.kind {
BinaryExprType::Add => { BinaryExprType::Add => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Add); ops.push(Op::Add);
} }
BinaryExprType::Sub => { BinaryExprType::Sub => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Sub); ops.push(Op::Sub);
} }
BinaryExprType::Div => { BinaryExprType::Div => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Div); ops.push(Op::Div);
} }
BinaryExprType::Mul => { BinaryExprType::Mul => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Mul); ops.push(Op::Mul);
} }
BinaryExprType::Equal => { BinaryExprType::Equal => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Equal); ops.push(Op::Equal);
} }
BinaryExprType::GT => { BinaryExprType::GT => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Gt); ops.push(Op::Gt);
} }
BinaryExprType::LT => { BinaryExprType::LT => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Lt); ops.push(Op::Lt);
} }
BinaryExprType::GTEqual => { BinaryExprType::GTEqual => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::GtEq); ops.push(Op::GtEq);
} }
BinaryExprType::LTEqual => { BinaryExprType::LTEqual => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::LtEq); ops.push(Op::LtEq);
} }
BinaryExprType::NotEqual => { BinaryExprType::NotEqual => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Equal); ops.push(Op::Equal);
ops.push(Op::Not); ops.push(Op::Not);
} }
BinaryExprType::REMatch => { BinaryExprType::REMatch => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Runtime(Hook::Regex)); ops.push(Op::Runtime(Hook::Regex));
} }
BinaryExprType::NotREMatch => { BinaryExprType::NotREMatch => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Runtime(Hook::Regex)); ops.push(Op::Runtime(Hook::Regex));
ops.push(Op::Not); ops.push(Op::Not);
} }
BinaryExprType::IS => { BinaryExprType::IS => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Typ); ops.push(Op::Typ);
ops.push(Op::Equal); ops.push(Op::Equal);
} }
BinaryExprType::AND => { BinaryExprType::AND => {
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Noop); ops.push(Op::Noop);
let idx = ops.len() - 1; 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; let jptr = (ops.len() - 1 - idx) as i32;
ops[idx] = Op::And(dbg!(jptr)); ops[idx] = Op::And(dbg!(jptr));
dbg!(ops); dbg!(ops);
} }
BinaryExprType::OR => { BinaryExprType::OR => {
// FIXME(jwall): This needs to be handled very differently Self::translate_expr(*def.left, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); ops.push(Op::Noop); // Placeholder
ops.push(Op::Noop); // Placeholder used for
let idx = ops.len() - 1; 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; let jptr = (ops.len() - 1 - idx) as i32;
ops[idx] = Op::Or(jptr); ops[idx] = Op::Or(jptr);
} }
BinaryExprType::Mod => { BinaryExprType::Mod => {
Self::translate_expr(*def.right, &mut ops); Self::translate_expr(*def.right, &mut ops, root);
Self::translate_expr(*def.left, &mut ops); Self::translate_expr(*def.left, &mut ops, root);
ops.push(Op::Mod); ops.push(Op::Mod);
} }
BinaryExprType::IN => { BinaryExprType::IN => {
// Dot expressions expect the left side to be pushed first // 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 // Symbols on the right side should be converted to strings to satisfy
// the Index operation contract. // the Index operation contract.
match *def.left { match *def.left {
@ -157,10 +158,11 @@ impl AST {
Self::translate_expr( Self::translate_expr(
Expression::Simple(Value::Str(name)), Expression::Simple(Value::Str(name)),
&mut ops, &mut ops,
root,
); );
} }
expr => { expr => {
Self::translate_expr(expr, &mut ops); Self::translate_expr(expr, &mut ops, root);
} }
} }
ops.push(Op::SafeIndex); ops.push(Op::SafeIndex);
@ -170,7 +172,7 @@ impl AST {
} }
BinaryExprType::DOT => { BinaryExprType::DOT => {
// Dot expressions expect the left side to be pushed first // 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 // Symbols on the right side should be converted to strings to satisfy
// the Index operation contract. // the Index operation contract.
match *def.right { match *def.right {
@ -178,10 +180,11 @@ impl AST {
Self::translate_expr( Self::translate_expr(
Expression::Simple(Value::Str(name)), Expression::Simple(Value::Str(name)),
&mut ops, &mut ops,
root,
); );
} }
expr => { expr => {
Self::translate_expr(expr, &mut ops); Self::translate_expr(expr, &mut ops, root);
} }
} }
ops.push(Op::Index); ops.push(Op::Index);
@ -189,15 +192,13 @@ impl AST {
}; };
} }
Expression::Grouped(expr, _) => { Expression::Grouped(expr, _) => {
Self::translate_expr(*expr, &mut ops); Self::translate_expr(*expr, &mut ops, root);
} }
Expression::Fail(def) => { Expression::Fail(def) => {
Self::translate_expr(*def.message, &mut ops); Self::translate_expr(*def.message, &mut ops, root);
ops.push(Op::Bang); ops.push(Op::Bang);
} }
Expression::Format(def) => { 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 { match def.args {
FormatArgs::List(mut elems) => { FormatArgs::List(mut elems) => {
let formatter = SimpleTemplate::new(); let formatter = SimpleTemplate::new();
@ -215,9 +216,10 @@ impl AST {
&mut elems_iter, &mut elems_iter,
&mut ops, &mut ops,
true, true,
root,
); );
for p in parts_iter { 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); ops.push(Op::Add);
} }
} }
@ -228,14 +230,13 @@ 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..);
// TODO(jwall): We need to assume there is a new scope introduced now
ops.push(Op::Noop); ops.push(Op::Noop);
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())); ops.push(Op::Sym("item".to_owned()));
Self::translate_expr(*expr, &mut ops); Self::translate_expr(*expr, &mut ops, root);
ops.push(Op::BindOver); ops.push(Op::BindOver);
let mut elems = Vec::new(); let mut elems = Vec::new();
let mut elems_iter = elems.drain(0..); let mut elems_iter = elems.drain(0..);
@ -244,9 +245,16 @@ impl AST {
&mut elems_iter, &mut elems_iter,
&mut ops, &mut ops,
false, false,
root,
); );
for p in parts_iter { 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::Add);
} }
ops.push(Op::Return); ops.push(Op::Return);
@ -263,7 +271,7 @@ impl AST {
} }
ops.push(Op::Noop); ops.push(Op::Noop);
let idx = ops.len() - 1; let idx = ops.len() - 1;
Self::translate_expr(*def.fields, &mut ops); Self::translate_expr(*def.fields, &mut ops, root);
ops.push(Op::Return); ops.push(Op::Return);
let jptr = ops.len() - 1 - idx; let jptr = ops.len() - 1 - idx;
ops[idx] = Op::Func(jptr as i32); ops[idx] = Op::Func(jptr as i32);
@ -272,27 +280,27 @@ impl AST {
match def { match def {
FuncOpDef::Map(def) => { FuncOpDef::Map(def) => {
// push the function on the stack first. // 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 // 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 // finally push the Hook::Map opcode
ops.push(Op::Runtime(Hook::Map)); ops.push(Op::Runtime(Hook::Map));
} }
FuncOpDef::Filter(def) => { FuncOpDef::Filter(def) => {
// push the function on the stack first. // 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 // 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 // finally push the Hook::Map opcode
ops.push(Op::Runtime(Hook::Filter)); ops.push(Op::Runtime(Hook::Filter));
} }
FuncOpDef::Reduce(def) => { FuncOpDef::Reduce(def) => {
// push the function on the stack first. // 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 // 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 // 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 // finally push the Hook::Map opcode
ops.push(Op::Runtime(Hook::Reduce)); ops.push(Op::Runtime(Hook::Reduce));
} }
@ -307,7 +315,8 @@ impl AST {
ops.push(Op::Val(Primitive::Str(def.path.fragment))); ops.push(Op::Val(Primitive::Str(def.path.fragment)));
ops.push(Op::Runtime(Hook::Include)); 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 argset = def.arg_set;
let out_expr = def.out_expr; let out_expr = def.out_expr;
let stmts = def.statements; let stmts = def.statements;
@ -315,7 +324,7 @@ impl AST {
ops.push(Op::InitTuple); ops.push(Op::InitTuple);
for (t, e) in argset { for (t, e) in argset {
ops.push(Op::Sym(t.fragment)); ops.push(Op::Sym(t.fragment));
Self::translate_expr(e, &mut ops); Self::translate_expr(e, &mut ops, root);
ops.push(Op::Field); ops.push(Op::Field);
} }
// If there is one then emit our return expression // If there is one then emit our return expression
@ -323,7 +332,7 @@ impl AST {
// Insert placeholder until we know jptr for this thunk // Insert placeholder until we know jptr for this thunk
ops.push(Op::Noop); ops.push(Op::Noop);
let idx = ops.len() - 1; let idx = ops.len() - 1;
Self::translate_expr(*expr, &mut ops); Self::translate_expr(*expr, &mut ops, root);
ops.push(Op::Return); ops.push(Op::Return);
let jptr = ops.len() - idx - 1; let jptr = ops.len() - idx - 1;
ops[idx] = Op::InitThunk(jptr as i32); ops[idx] = Op::InitThunk(jptr as i32);
@ -335,34 +344,34 @@ impl AST {
// Bind our mod tuple. // Bind our mod tuple.
ops.push(Op::Bind); ops.push(Op::Bind);
// emit all of our statements; // emit all of our statements;
Self::translate_stmts(stmts, &mut ops); Self::translate_stmts(stmts, &mut ops, root);
// Return from the module // Return from the module
ops.push(Op::Return); ops.push(Op::Return);
let jptr = ops.len() - idx - 1; let jptr = ops.len() - idx - 1;
ops[idx] = Op::Module(jptr as i32); ops[idx] = Op::Module(jptr as i32);
} }
Expression::Not(def) => { Expression::Not(def) => {
Self::translate_expr(*def.expr, &mut ops); Self::translate_expr(*def.expr, &mut ops, root);
ops.push(Op::Not); ops.push(Op::Not);
} }
Expression::Range(def) => { Expression::Range(def) => {
Self::translate_expr(*def.end, &mut ops); 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); Self::translate_expr(*expr, &mut ops, root);
} else { } else {
ops.push(Op::Val(Primitive::Empty)); 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)); ops.push(Op::Runtime(Hook::Range));
} }
Expression::Select(def) => { Expression::Select(def) => {
Self::translate_expr(*def.val, &mut ops); 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));
ops.push(Op::Noop); ops.push(Op::Noop);
let idx = ops.len() - 1; let idx = ops.len() - 1;
Self::translate_expr(val, &mut ops); Self::translate_expr(val, &mut ops, root);
ops.push(Op::Noop); ops.push(Op::Noop);
jumps.push(ops.len() - 1); jumps.push(ops.len() - 1);
let jptr = ops.len() - idx - 1; let jptr = ops.len() - idx - 1;
@ -375,7 +384,7 @@ impl AST {
ops[i] = Op::Jump(idx as i32); ops[i] = Op::Jump(idx as i32);
} }
if let Some(default) = def.default { if let Some(default) = def.default {
Self::translate_expr(*default, &mut ops); Self::translate_expr(*default, &mut ops, root);
} else { } else {
ops.push(Op::Bang); ops.push(Op::Bang);
} }
@ -384,10 +393,10 @@ impl AST {
Expression::Call(def) => { Expression::Call(def) => {
// first push our arguments. // first push our arguments.
for e in def.arglist { for e in def.arglist {
Self::translate_expr(e, &mut ops); Self::translate_expr(e, &mut ops, root);
} }
// then push the func reference // then push the func reference
Self::translate_value(def.funcref, &mut ops); Self::translate_value(def.funcref, &mut ops, root);
ops.push(Op::FCall); ops.push(Op::FCall);
dbg!(ops); dbg!(ops);
} }
@ -395,10 +404,10 @@ impl AST {
ops.push(Op::InitTuple); ops.push(Op::InitTuple);
for (t, e) in def.fields { for (t, e) in def.fields {
ops.push(Op::Sym(t.fragment)); ops.push(Op::Sym(t.fragment));
Self::translate_expr(e, &mut ops); Self::translate_expr(e, &mut ops, root);
ops.push(Op::Field); ops.push(Op::Field);
} }
Self::translate_value(def.selector, &mut ops); Self::translate_value(def.selector, &mut ops, root);
ops.push(Op::Cp); ops.push(Op::Cp);
} }
Expression::Debug(def) => { Expression::Debug(def) => {
@ -409,7 +418,7 @@ impl AST {
} }
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)));
Self::translate_expr(*def.expr, &mut ops); Self::translate_expr(*def.expr, &mut ops, root);
ops.push(Op::Runtime(Hook::Trace(def.pos))); ops.push(Op::Runtime(Hook::Trace(def.pos)));
} }
} }
@ -420,6 +429,7 @@ impl AST {
elems: &mut EI, elems: &mut EI,
mut ops: &mut Vec<Op>, mut ops: &mut Vec<Op>,
place_holder: bool, place_holder: bool,
root: &Path,
) { ) {
match part { match part {
TemplatePart::Str(s) => { TemplatePart::Str(s) => {
@ -430,7 +440,7 @@ impl AST {
// In theory this should never be reachable // In theory this should never be reachable
unreachable!(); unreachable!();
} else { } else {
Self::translate_expr(elems.next().unwrap(), &mut ops); Self::translate_expr(elems.next().unwrap(), &mut ops, root);
ops.push(Op::Render); ops.push(Op::Render);
} }
} }
@ -438,14 +448,14 @@ impl AST {
if place_holder { if place_holder {
unreachable!(); unreachable!();
} else { } else {
Self::translate_expr(expr, &mut ops); Self::translate_expr(expr, &mut ops, root);
ops.push(Op::Render); 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 { match value {
Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))), Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))),
Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))),
@ -459,14 +469,14 @@ impl AST {
ops.push(Op::InitTuple); ops.push(Op::InitTuple);
for (k, v) in flds.val { for (k, v) in flds.val {
ops.push(Op::Sym(k.fragment)); ops.push(Op::Sym(k.fragment));
Self::translate_expr(v, &mut ops); Self::translate_expr(v, &mut ops, root);
ops.push(Op::Field); ops.push(Op::Field);
} }
} }
Value::List(els) => { Value::List(els) => {
ops.push(Op::InitList); ops.push(Op::InitList);
for el in els.elems { for el in els.elems {
Self::translate_expr(el, &mut ops); Self::translate_expr(el, &mut ops, root);
ops.push(Op::Element); ops.push(Op::Element);
} }
} }

View File

@ -274,10 +274,23 @@ where
}; };
let mut ops = self.ops.clone(); let mut ops = self.ops.clone();
ops.jump(idx)?; 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 { self.push(Rc::new(M(Module {
ptr: ops, ptr: ops,
result_ptr: result_ptr, result_ptr: result_ptr,
flds: flds, flds: flds,
pkg_ptr: pkg_ptr,
})))?; })))?;
self.op_jump(jptr) self.op_jump(jptr)
} }
@ -589,8 +602,8 @@ where
fn op_index(&mut self, safe: bool) -> Result<(), Error> { fn op_index(&mut self, safe: bool) -> Result<(), Error> {
// left and then right // left and then right
let right = self.pop()?; let right = dbg!(self.pop()?);
let left = self.pop()?; let left = dbg!(self.pop()?);
match right.as_ref() { match right.as_ref() {
&P(Int(i)) => { &P(Int(i)) => {
if let &C(List(ref elems)) = left.as_ref() { if let &C(List(ref elems)) = left.as_ref() {
@ -645,18 +658,28 @@ where
ref ptr, ref ptr,
ref result_ptr, ref result_ptr,
ref flds, ref flds,
ref pkg_ptr,
}) => { }) => {
//let this = M(Module { let this = M(Module {
// ptr: ptr.clone(), ptr: ptr.clone(),
// result_ptr: result_ptr.clone(), result_ptr: result_ptr.clone(),
// flds: flds.clone(), flds: flds.clone(),
//}); pkg_ptr: pkg_ptr.clone(),
});
let mut flds = flds.clone(); let mut flds = flds.clone();
for (name, val) in overrides { for (name, val) in overrides {
self.merge_field_into_tuple(&mut flds, name, val)?; 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(), Rc::new(this))?;
//self.merge_field_into_tuple(&mut flds, "this".to_owned(), 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()); 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(S("mod".to_owned())))?;
vm.push(Rc::new(C(Tuple(flds))))?; vm.push(Rc::new(C(Tuple(flds))))?;