mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: pkg() functions *should* work now.
This commit is contained in:
parent
d09bd13f42
commit
7bc98514bf
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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))))?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user