DEV: Modules work now.

This commit is contained in:
Jeremy Wall 2019-08-15 18:11:54 -05:00
parent e998e582ae
commit 100d963f41
3 changed files with 66 additions and 9 deletions

View File

@ -579,7 +579,7 @@ macro_rules! assert_parse_cases {
assert!(ops.len() > 0); assert!(ops.len() > 0);
let mut vm = VM::new("foo.ucg", ops.clone()); let mut vm = VM::new("foo.ucg", ops.clone());
vm.run().unwrap(); vm.run().unwrap();
assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1)); assert_eq!(vm.pop().unwrap(), Rc::new(case.1));
} }
}; };
@ -716,3 +716,13 @@ fn simple_functions() {
"let f = func(val1, val2) => val1 + val2; f(1, 1);" => P(Int(2)), "let f = func(val1, val2) => val1 + val2; f(1, 1);" => P(Int(2)),
]; ];
} }
#[test]
fn simple_modules() {
assert_parse_cases![
"let m = module{} => { let v = 1; }; m{};" => C(Tuple(vec![("v".to_owned(), Rc::new(P(Int(1))))])),
"let m = module{} => (v) { let v = 1; }; m{};" => P(Int(1)),
"let m = module{val=NULL} => (v) { let v = mod.val; }; m{val=1};" => P(Int(1)),
"let m = module{val=NULL} => (v) { let v = mod.val + 1; }; m{val=1};" => P(Int(2)),
];
}

View File

@ -22,6 +22,11 @@ pub struct AST();
impl AST { impl AST {
pub fn translate(stmts: Vec<Statement>) -> Vec<Op> { pub fn translate(stmts: Vec<Statement>) -> Vec<Op> {
let mut ops = Vec::new(); let mut ops = Vec::new();
Self::translate_stmts(stmts, &mut ops);
return ops;
}
fn translate_stmts(stmts: Vec<Statement>, mut ops: &mut Vec<Op>) {
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),
@ -42,7 +47,6 @@ impl AST {
} }
} }
} }
return ops;
} }
fn translate_expr(expr: Expression, mut ops: &mut Vec<Op>) { fn translate_expr(expr: Expression, mut ops: &mut Vec<Op>) {
@ -267,7 +271,40 @@ impl AST {
Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"), Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"),
Expression::Import(_) => unimplemented!("Import expressions are not implmented yet"), Expression::Import(_) => unimplemented!("Import expressions are not implmented yet"),
Expression::Include(_) => unimplemented!("Include expressions are not implmented yet"), Expression::Include(_) => unimplemented!("Include expressions are not implmented yet"),
Expression::Module(_) => unimplemented!("Module expressions are not implmented yet"), Expression::Module(def) => {
let argset = def.arg_set;
let out_expr = def.out_expr;
let stmts = def.statements;
// Init our module tuple bindings
ops.push(Op::InitTuple);
for (t, e) in argset {
ops.push(Op::Sym(t.fragment));
Self::translate_expr(e, &mut ops);
ops.push(Op::Field);
}
// If there is one then emit our return expression
if let Some(expr) = out_expr {
// Insert placeholder until we know jptr for this thunk
ops.push(Op::Noop);
let idx = ops.len() - 1;
Self::translate_expr(*expr, &mut ops);
ops.push(Op::Return);
let jptr = ops.len() - idx - 1;
ops[idx] = Op::InitThunk(jptr as i32);
}
// Insert a placeholder Opcode until we know jptr for the
// module.
ops.push(Op::Noop);
let idx = ops.len() - 1;
// Bind our mod tuple.
ops.push(Op::Bind);
// emit all of our statements;
Self::translate_stmts(stmts, &mut ops);
// Return from the module
ops.push(Op::Return);
let jptr = ops.len() - idx - 1;
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);
ops.push(Op::Not); ops.push(Op::Not);
@ -284,7 +321,16 @@ impl AST {
ops.push(Op::FCall); ops.push(Op::FCall);
dbg!(ops); dbg!(ops);
} }
Expression::Copy(_) => unimplemented!("Copy expressions are not implmented yet"), Expression::Copy(def) => {
ops.push(Op::InitTuple);
for (t, e) in def.fields {
ops.push(Op::Sym(t.fragment));
Self::translate_expr(e, &mut ops);
ops.push(Op::Field);
}
Self::translate_value(def.selector, &mut ops);
ops.push(Op::Cp);
}
Expression::Debug(_) => unimplemented!("Debug expressions are not implmented yet"), Expression::Debug(_) => unimplemented!("Debug expressions are not implmented yet"),
} }
} }

View File

@ -235,7 +235,7 @@ impl<'a> VM {
} }
fn op_module(&'a mut self, idx: usize, jptr: i32) -> Result<(), Error> { fn op_module(&'a mut self, idx: usize, jptr: i32) -> Result<(), Error> {
let mod_val = self.pop()?; let mod_val = dbg!(self.pop())?;
let (result_ptr, flds) = match mod_val.as_ref() { let (result_ptr, flds) = match mod_val.as_ref() {
&C(Tuple(ref flds)) => (None, flds.clone()), &C(Tuple(ref flds)) => (None, flds.clone()),
&T(ptr) => { &T(ptr) => {
@ -602,9 +602,9 @@ impl<'a> VM {
fn op_copy(&mut self) -> Result<(), Error> { fn op_copy(&mut self) -> Result<(), Error> {
// TODO Use Cow pointers for this? // TODO Use Cow pointers for this?
// get next value. It should be a Module or Tuple. // get next value. It should be a Module or Tuple.
let tgt = self.pop()?; let tgt = dbg!(self.pop()?);
// This value should always be a tuple // This value should always be a tuple
let override_val = self.pop()?; let override_val = dbg!(self.pop()?);
let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() {
oflds.clone() oflds.clone()
} else { } else {
@ -642,9 +642,10 @@ impl<'a> VM {
if let Some(ptr) = result_ptr { if let Some(ptr) = result_ptr {
vm.ops.jump(ptr.clone())?; vm.ops.jump(ptr.clone())?;
vm.run()?; vm.run()?;
self.push(vm.pop()?)?; self.push(dbg!(vm.pop())?)?;
} else { } else {
self.push(Rc::new(vm.symbols_to_tuple(false)))?; dbg!(&vm.symbols);
self.push(Rc::new(dbg!(vm.symbols_to_tuple(false))))?;
} }
} }
_ => { _ => {