diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 6cd47d6..64e1fcd 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -579,7 +579,7 @@ macro_rules! assert_parse_cases { assert!(ops.len() > 0); let mut vm = VM::new("foo.ucg", ops.clone()); 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)), ]; } + +#[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)), + ]; +} diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 2d6d3ca..eaeabe0 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -22,6 +22,11 @@ pub struct AST(); impl AST { pub fn translate(stmts: Vec) -> Vec { let mut ops = Vec::new(); + Self::translate_stmts(stmts, &mut ops); + return ops; + } + + fn translate_stmts(stmts: Vec, mut ops: &mut Vec) { for stmt in stmts { match stmt { 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) { @@ -267,7 +271,40 @@ impl AST { Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"), Expression::Import(_) => unimplemented!("Import 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) => { Self::translate_expr(*def.expr, &mut ops); ops.push(Op::Not); @@ -284,7 +321,16 @@ impl AST { ops.push(Op::FCall); 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"), } } diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index a0b424a..ad1bee5 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -235,7 +235,7 @@ impl<'a> VM { } 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() { &C(Tuple(ref flds)) => (None, flds.clone()), &T(ptr) => { @@ -602,9 +602,9 @@ impl<'a> VM { fn op_copy(&mut self) -> Result<(), Error> { // TODO Use Cow pointers for this? // 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 - let override_val = self.pop()?; + let override_val = dbg!(self.pop()?); let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { oflds.clone() } else { @@ -642,9 +642,10 @@ impl<'a> VM { if let Some(ptr) = result_ptr { vm.ops.jump(ptr.clone())?; vm.run()?; - self.push(vm.pop()?)?; + self.push(dbg!(vm.pop())?)?; } else { - self.push(Rc::new(vm.symbols_to_tuple(false)))?; + dbg!(&vm.symbols); + self.push(Rc::new(dbg!(vm.symbols_to_tuple(false))))?; } } _ => {