DEV: Function calls work. Also wired up some of the bang opcode.

This commit is contained in:
Jeremy Wall 2019-08-14 19:52:41 -05:00
parent f9c3ebeb50
commit e998e582ae
4 changed files with 54 additions and 20 deletions

View File

@ -195,8 +195,8 @@ pub enum Op {
Noop, Noop,
// Pending Computation // Pending Computation
InitThunk(i32), // Basically just used for module return expressions InitThunk(i32), // Basically just used for module return expressions
Module(usize), Module(i32),
Func(usize), Func(i32),
Return, Return,
// Calls // Calls
FCall, FCall,

View File

@ -346,7 +346,7 @@ fn function_definition_and_call() {
InitList, // 1 InitList, // 1
Sym("arg".to_owned()), // 2 Sym("arg".to_owned()), // 2
Element, // 3 Element, // 3
Func(6), // 4 Func(2), // 4
DeRef("arg".to_owned()), // 5 DeRef("arg".to_owned()), // 5
Return, // 6 Return, // 6
Bind, // 7 Bind, // 7
@ -362,7 +362,7 @@ fn function_definition_and_call() {
InitList, // 4 InitList, // 4
Sym("arg".to_owned()), // 5 Sym("arg".to_owned()), // 5
Element, // 6 Element, // 6
Func(11), // 7 Func(4), // 7
DeRef("arg".to_owned()), // 8 DeRef("arg".to_owned()), // 8
DeRef("closed".to_owned()), // 9 DeRef("closed".to_owned()), // 9
Add, // 10 Add, // 10
@ -391,7 +391,7 @@ fn module_call() {
Sym("two".to_owned()), // 9 Sym("two".to_owned()), // 9
Val(Int(2)), // 10 Val(Int(2)), // 10
Field, // 11 Field, // 11
Module(17), // 12 // Module body definition Module(5), // 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
@ -425,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(20), // 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
@ -708,3 +708,11 @@ fn simple_format_expressions() {
"\"@{item.num}\" % {num=1};" => P(Str("1".to_owned())), "\"@{item.num}\" % {num=1};" => P(Str("1".to_owned())),
]; ];
} }
#[test]
fn simple_functions() {
assert_parse_cases![
"let f = func(val) => val; f(1);" => P(Int(1)),
"let f = func(val1, val2) => val1 + val2; f(1, 1);" => P(Int(2)),
];
}

View File

@ -15,8 +15,7 @@ use crate::ast::{BinaryExprType, Expression, FormatArgs, Statement, Value};
use crate::ast::{Position, TemplatePart}; use crate::ast::{Position, TemplatePart};
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
use crate::build::opcode::Primitive; use crate::build::opcode::Primitive;
use crate::build::opcode::Value::{C, F, M, P, T}; use crate::build::opcode::{Func, Hook, Op};
use crate::build::opcode::{Hook, Op};
pub struct AST(); pub struct AST();
@ -252,7 +251,19 @@ impl AST {
} }
} }
} }
Expression::Func(_) => unimplemented!("Func expressions are not implmented yet"), Expression::Func(def) => {
ops.push(Op::InitList);
for b in def.argdefs {
ops.push(Op::Sym(b.val));
ops.push(Op::Element);
}
ops.push(Op::Noop);
let idx = ops.len() - 1;
Self::translate_expr(*def.fields, &mut ops);
ops.push(Op::Return);
let jptr = ops.len() - 1 - idx;
ops[idx] = Op::Func(jptr as i32);
}
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"),
@ -263,7 +274,16 @@ impl AST {
} }
Expression::Range(_) => unimplemented!("Range expressions are not implmented yet"), Expression::Range(_) => unimplemented!("Range expressions are not implmented yet"),
Expression::Select(_) => unimplemented!("Select expressions are not implmented yet"), Expression::Select(_) => unimplemented!("Select expressions are not implmented yet"),
Expression::Call(_) => unimplemented!("Call expressions are not implmented yet"), Expression::Call(def) => {
// first push our arguments.
for e in def.arglist {
Self::translate_expr(e, &mut ops);
}
// then push the func reference
Self::translate_value(def.funcref, &mut ops);
ops.push(Op::FCall);
dbg!(ops);
}
Expression::Copy(_) => unimplemented!("Copy expressions are not implmented yet"), Expression::Copy(_) => unimplemented!("Copy expressions are not implmented yet"),
Expression::Debug(_) => unimplemented!("Debug expressions are not implmented yet"), Expression::Debug(_) => unimplemented!("Debug expressions are not implmented yet"),
} }

View File

@ -104,7 +104,7 @@ impl<'a> VM {
Op::SafeIndex => self.op_index(true)?, Op::SafeIndex => self.op_index(true)?,
Op::Cp => self.op_copy()?, Op::Cp => self.op_copy()?,
//TODO(jwall): Should this take a user provided message? //TODO(jwall): Should this take a user provided message?
Op::Bang => return dbg!(Err(Error {})), Op::Bang => self.op_bang()?,
Op::InitThunk(jp) => self.op_thunk(idx, jp)?, Op::InitThunk(jp) => self.op_thunk(idx, jp)?,
Op::Noop => { Op::Noop => {
// Do nothing // Do nothing
@ -234,7 +234,7 @@ impl<'a> VM {
Ok(()) Ok(())
} }
fn op_module(&'a mut self, idx: usize, jptr: usize) -> Result<(), Error> { fn op_module(&'a mut self, idx: usize, jptr: i32) -> Result<(), Error> {
let mod_val = self.pop()?; let mod_val = 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()),
@ -257,10 +257,10 @@ impl<'a> VM {
result_ptr: result_ptr, result_ptr: result_ptr,
flds: flds, flds: flds,
})))?; })))?;
self.ops.jump(jptr) self.op_jump(jptr)
} }
fn op_func(&mut self, idx: usize, jptr: usize) -> Result<(), Error> { fn op_func(&mut self, idx: usize, jptr: i32) -> Result<(), Error> {
// get arity from stack // get arity from stack
let mut scope_snapshot = self.symbols.snapshot(); let mut scope_snapshot = self.symbols.snapshot();
scope_snapshot.push(); scope_snapshot.push();
@ -289,7 +289,7 @@ impl<'a> VM {
snapshot: scope_snapshot, snapshot: scope_snapshot,
})))?; })))?;
eprintln!("Jumping to {} past the function body", jptr); eprintln!("Jumping to {} past the function body", jptr);
self.ops.jump(jptr) self.op_jump(jptr)
} }
pub fn fcall_impl<P: Into<PathBuf>>( pub fn fcall_impl<P: Into<PathBuf>>(
@ -329,10 +329,10 @@ impl<'a> VM {
} }
fn op_fcall(&mut self) -> Result<(), Error> { fn op_fcall(&mut self) -> Result<(), Error> {
let f = self.pop()?; let f = dbg!(self.pop())?;
if let &F(ref f) = f.as_ref() { if let &F(ref f) = f.as_ref() {
let val = Self::fcall_impl(&self.path, f, &mut self.stack)?; let val = Self::fcall_impl(&self.path, f, &mut self.stack)?;
self.push(val)?; self.push(dbg!(val))?;
} }
Ok(()) Ok(())
} }
@ -505,10 +505,10 @@ impl<'a> VM {
fn op_element(&mut self) -> Result<(), Error> { fn op_element(&mut self) -> Result<(), Error> {
// get element from stack. // get element from stack.
let val = self.pop()?; let val = dbg!(self.pop()?);
// get next value. It should be a Composite list. // get next value. It should be a Composite list.
let tpl = self.pop()?; let list = dbg!(self.pop()?);
if let &C(List(ref elems)) = tpl.as_ref() { if let &C(List(ref elems)) = list.as_ref() {
// add value to list // add value to list
// TODO(jwall): This is probably memory inefficient and we should // TODO(jwall): This is probably memory inefficient and we should
// optimize it a bit. // optimize it a bit.
@ -559,6 +559,12 @@ impl<'a> VM {
} }
} }
fn op_bang(&mut self) -> Result<(), Error> {
let msg = self.pop()?;
// TODO(jwall): record an error here.
Ok(())
}
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 = self.pop()?;