mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Function calls work. Also wired up some of the bang opcode.
This commit is contained in:
parent
f9c3ebeb50
commit
e998e582ae
@ -195,8 +195,8 @@ pub enum Op {
|
||||
Noop,
|
||||
// Pending Computation
|
||||
InitThunk(i32), // Basically just used for module return expressions
|
||||
Module(usize),
|
||||
Func(usize),
|
||||
Module(i32),
|
||||
Func(i32),
|
||||
Return,
|
||||
// Calls
|
||||
FCall,
|
||||
|
@ -346,7 +346,7 @@ fn function_definition_and_call() {
|
||||
InitList, // 1
|
||||
Sym("arg".to_owned()), // 2
|
||||
Element, // 3
|
||||
Func(6), // 4
|
||||
Func(2), // 4
|
||||
DeRef("arg".to_owned()), // 5
|
||||
Return, // 6
|
||||
Bind, // 7
|
||||
@ -362,7 +362,7 @@ fn function_definition_and_call() {
|
||||
InitList, // 4
|
||||
Sym("arg".to_owned()), // 5
|
||||
Element, // 6
|
||||
Func(11), // 7
|
||||
Func(4), // 7
|
||||
DeRef("arg".to_owned()), // 8
|
||||
DeRef("closed".to_owned()), // 9
|
||||
Add, // 10
|
||||
@ -391,7 +391,7 @@ fn module_call() {
|
||||
Sym("two".to_owned()), // 9
|
||||
Val(Int(2)), // 10
|
||||
Field, // 11
|
||||
Module(17), // 12 // Module body definition
|
||||
Module(5), // 12 // Module body definition
|
||||
Bind, // 13 // bind the mod tuple
|
||||
Sym("foo".to_owned()), // 14
|
||||
DeRef("mod".to_owned()), // 15
|
||||
@ -425,7 +425,7 @@ fn module_call() {
|
||||
InitThunk(2), // 12 // Module Return expression
|
||||
Val(Int(1)), // 13
|
||||
Return, // 14
|
||||
Module(20), // 15 // Module definition
|
||||
Module(5), // 15 // Module definition
|
||||
Bind, // 16
|
||||
Sym("foo".to_owned()), // 17
|
||||
DeRef("mod".to_owned()), // 18
|
||||
@ -708,3 +708,11 @@ fn simple_format_expressions() {
|
||||
"\"@{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)),
|
||||
];
|
||||
}
|
||||
|
@ -15,8 +15,7 @@ use crate::ast::{BinaryExprType, Expression, FormatArgs, Statement, Value};
|
||||
use crate::ast::{Position, TemplatePart};
|
||||
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
|
||||
use crate::build::opcode::Primitive;
|
||||
use crate::build::opcode::Value::{C, F, M, P, T};
|
||||
use crate::build::opcode::{Hook, Op};
|
||||
use crate::build::opcode::{Func, Hook, Op};
|
||||
|
||||
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::Import(_) => unimplemented!("Import 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::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::Debug(_) => unimplemented!("Debug expressions are not implmented yet"),
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ impl<'a> VM {
|
||||
Op::SafeIndex => self.op_index(true)?,
|
||||
Op::Cp => self.op_copy()?,
|
||||
//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::Noop => {
|
||||
// Do nothing
|
||||
@ -234,7 +234,7 @@ impl<'a> VM {
|
||||
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 (result_ptr, flds) = match mod_val.as_ref() {
|
||||
&C(Tuple(ref flds)) => (None, flds.clone()),
|
||||
@ -257,10 +257,10 @@ impl<'a> VM {
|
||||
result_ptr: result_ptr,
|
||||
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
|
||||
let mut scope_snapshot = self.symbols.snapshot();
|
||||
scope_snapshot.push();
|
||||
@ -289,7 +289,7 @@ impl<'a> VM {
|
||||
snapshot: scope_snapshot,
|
||||
})))?;
|
||||
eprintln!("Jumping to {} past the function body", jptr);
|
||||
self.ops.jump(jptr)
|
||||
self.op_jump(jptr)
|
||||
}
|
||||
|
||||
pub fn fcall_impl<P: Into<PathBuf>>(
|
||||
@ -329,10 +329,10 @@ impl<'a> VM {
|
||||
}
|
||||
|
||||
fn op_fcall(&mut self) -> Result<(), Error> {
|
||||
let f = self.pop()?;
|
||||
let f = dbg!(self.pop())?;
|
||||
if let &F(ref f) = f.as_ref() {
|
||||
let val = Self::fcall_impl(&self.path, f, &mut self.stack)?;
|
||||
self.push(val)?;
|
||||
self.push(dbg!(val))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -505,10 +505,10 @@ impl<'a> VM {
|
||||
|
||||
fn op_element(&mut self) -> Result<(), Error> {
|
||||
// get element from stack.
|
||||
let val = self.pop()?;
|
||||
let val = dbg!(self.pop()?);
|
||||
// get next value. It should be a Composite list.
|
||||
let tpl = self.pop()?;
|
||||
if let &C(List(ref elems)) = tpl.as_ref() {
|
||||
let list = dbg!(self.pop()?);
|
||||
if let &C(List(ref elems)) = list.as_ref() {
|
||||
// add value to list
|
||||
// TODO(jwall): This is probably memory inefficient and we should
|
||||
// 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> {
|
||||
// left and then right
|
||||
let right = self.pop()?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user