Function application working again
This commit is contained in:
parent
16164c2235
commit
7282a38a08
@ -118,7 +118,13 @@ impl<'a> Reducer<'a> {
|
|||||||
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
|
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
|
||||||
PrefixExp(op, arg) => self.prefix(op, arg),
|
PrefixExp(op, arg) => self.prefix(op, arg),
|
||||||
Value(qualified_name) => self.value(qualified_name),
|
Value(qualified_name) => self.value(qualified_name),
|
||||||
Call { f, arguments } => Unimplemented, // self.reduce_call_expression(f, arguments),
|
Call { f, arguments } => Expression::Call {
|
||||||
|
f: Box::new(self.expression(f)),
|
||||||
|
args: arguments
|
||||||
|
.iter()
|
||||||
|
.map(|arg| self.invocation_argument(arg))
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
TupleLiteral(exprs) => Expression::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
|
TupleLiteral(exprs) => Expression::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
|
||||||
IfExpression {
|
IfExpression {
|
||||||
discriminator,
|
discriminator,
|
||||||
@ -133,6 +139,15 @@ impl<'a> Reducer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invocation_argument(&mut self, invoc: &ast::InvocationArgument) -> Expression {
|
||||||
|
use crate::ast::InvocationArgument::*;
|
||||||
|
match invoc {
|
||||||
|
Positional(ex) => self.expression(ex),
|
||||||
|
Keyword { .. } => Expression::ReductionError("Keyword arguments not supported".to_string()),
|
||||||
|
Ignored => Expression::ReductionError("Ignored arguments not supported".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn function(&mut self, statements: &ast::Block) -> Vec<Statement> {
|
fn function(&mut self, statements: &ast::Block) -> Vec<Statement> {
|
||||||
statements.iter().filter_map(|stmt| self.function_internal_statement(stmt)).collect()
|
statements.iter().filter_map(|stmt| self.function_internal_statement(stmt)).collect()
|
||||||
}
|
}
|
||||||
@ -201,7 +216,7 @@ impl<'a> Reducer<'a> {
|
|||||||
Func(_) => Expression::Lookup { id: def_id.clone(), kind: Lookup::Function },
|
Func(_) => Expression::Lookup { id: def_id.clone(), kind: Lookup::Function },
|
||||||
GlobalBinding => Expression::Lookup { id: def_id.clone(), kind: Lookup::GlobalVar },
|
GlobalBinding => Expression::Lookup { id: def_id.clone(), kind: Lookup::GlobalVar },
|
||||||
LocalVariable => Expression::Lookup { id: def_id.clone(), kind: Lookup::LocalVar },
|
LocalVariable => Expression::Lookup { id: def_id.clone(), kind: Lookup::LocalVar },
|
||||||
FunctionParam(_) => Expression::Lookup { id: def_id.clone(), kind: Lookup::Param },
|
FunctionParam(n) => Expression::Lookup { id: def_id.clone(), kind: Lookup::Param(*n) },
|
||||||
DataConstructor { index, arity, .. } => {
|
DataConstructor { index, arity, .. } => {
|
||||||
Expression::Unimplemented
|
Expression::Unimplemented
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,10 @@ use std::collections::HashMap;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::builtin::Builtin;
|
use crate::builtin::Builtin;
|
||||||
use crate::symbol_table::{DefId, Symbol, SymbolSpec, SymbolTable};
|
use crate::symbol_table::{DefId, SymbolTable};
|
||||||
|
|
||||||
|
//TODO most of these Clone impls only exist to support function application, because the
|
||||||
|
//tree-walking evaluator moves the reduced IR members.
|
||||||
|
|
||||||
/// The reduced intermediate representation consists of a list of function definitions, and a block
|
/// The reduced intermediate representation consists of a list of function definitions, and a block
|
||||||
/// of entrypoint statements. In a repl or script context this can be an arbitrary list of
|
/// of entrypoint statements. In a repl or script context this can be an arbitrary list of
|
||||||
@ -14,7 +17,7 @@ pub struct ReducedIR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ReducedIR {
|
impl ReducedIR {
|
||||||
fn debug(&self, symbol_table: &SymbolTable) {
|
pub fn debug(&self, symbol_table: &SymbolTable) {
|
||||||
println!("Reduced IR:");
|
println!("Reduced IR:");
|
||||||
println!("Functions:");
|
println!("Functions:");
|
||||||
println!("-----------");
|
println!("-----------");
|
||||||
@ -32,7 +35,7 @@ impl ReducedIR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
Binding {
|
Binding {
|
||||||
@ -42,7 +45,7 @@ pub enum Statement {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Tuple(Vec<Expression>),
|
Tuple(Vec<Expression>),
|
||||||
@ -80,12 +83,12 @@ pub enum Function {
|
|||||||
UserDefined(DefId)
|
UserDefined(DefId)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Lookup {
|
pub enum Lookup {
|
||||||
LocalVar,
|
LocalVar,
|
||||||
GlobalVar,
|
GlobalVar,
|
||||||
Function,
|
Function,
|
||||||
Param,
|
Param(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::symbol_table::{Fqsn, Scope, SymbolTable, Symbol, SymbolSpec, DefId};
|
use crate::symbol_table::{Fqsn, Scope, SymbolTable, SymbolSpec};
|
||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
|
|
||||||
type FqsnPrefix = Vec<Scope>;
|
type FqsnPrefix = Vec<Scope>;
|
||||||
|
@ -21,6 +21,13 @@ enum Memory {
|
|||||||
Index(u32)
|
Index(u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is for function param lookups, and is a hack
|
||||||
|
impl From<u8> for Memory {
|
||||||
|
fn from(n: u8) -> Self {
|
||||||
|
Memory::Index(4_000_000 + (n as u32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&DefId> for Memory {
|
impl From<&DefId> for Memory {
|
||||||
fn from(id: &DefId) -> Self {
|
fn from(id: &DefId) -> Self {
|
||||||
Self::Index(id.as_u32())
|
Self::Index(id.as_u32())
|
||||||
@ -159,6 +166,21 @@ impl<'a> State<'a> {
|
|||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn block(&mut self, statements: Vec<Statement>) -> EvalResult<Primitive> {
|
||||||
|
//TODO need to handle breaks, returns, etc.
|
||||||
|
let mut ret = None;
|
||||||
|
for stmt in statements.into_iter() {
|
||||||
|
if let Some(RuntimeValue::Primitive(prim)) = self.statement(stmt)? {
|
||||||
|
ret = Some(prim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(if let Some(ret) = ret {
|
||||||
|
ret
|
||||||
|
} else {
|
||||||
|
self.expression(Expression::unit())?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn statement(&mut self, stmt: Statement) -> EvalResult<Option<RuntimeValue>> {
|
fn statement(&mut self, stmt: Statement) -> EvalResult<Option<RuntimeValue>> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Statement::Binding { ref id, expr, constant } => {
|
Statement::Binding { ref id, expr, constant } => {
|
||||||
@ -179,14 +201,25 @@ impl<'a> State<'a> {
|
|||||||
Expression::Literal(lit) => Primitive::Literal(lit),
|
Expression::Literal(lit) => Primitive::Literal(lit),
|
||||||
Expression::Tuple(items) => Primitive::Tuple(items.into_iter().map(|expr| self.expression(expr)).collect::<EvalResult<Vec<Primitive>>>()?),
|
Expression::Tuple(items) => Primitive::Tuple(items.into_iter().map(|expr| self.expression(expr)).collect::<EvalResult<Vec<Primitive>>>()?),
|
||||||
Expression::Lookup { ref id, kind } => {
|
Expression::Lookup { ref id, kind } => {
|
||||||
let mem = id.into();
|
|
||||||
match kind {
|
match kind {
|
||||||
Lookup::Function => match self.environments.lookup(&mem) {
|
Lookup::Function => {
|
||||||
//TODO is this right? not sure
|
let mem = id.into();
|
||||||
Some(RuntimeValue::Primitive(prim)) => prim.clone(),
|
match self.environments.lookup(&mem) {
|
||||||
_ => return Err(format!("Function not found for id: {}", id)),
|
// This just checks that the function exists in "memory" by ID, we don't
|
||||||
|
// actually retrieve it until `apply_function()`
|
||||||
|
Some(RuntimeValue::Function(_)) => Primitive::Callable(Function::UserDefined(id.clone())),
|
||||||
|
x => return Err(format!("Function not found for id: {} : {:?}", id, x)),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
kind @ Lookup::LocalVar | kind @ Lookup::GlobalVar | kind @ Lookup::Param => {
|
Lookup::Param(n) => {
|
||||||
|
let mem = n.into();
|
||||||
|
match self.environments.lookup(&mem) {
|
||||||
|
Some(RuntimeValue::Primitive(prim)) => prim.clone(),
|
||||||
|
e => return Err(format!("Param lookup error, got {:?}", e)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
kind @ Lookup::LocalVar | kind @ Lookup::GlobalVar => {
|
||||||
|
let mem = id.into();
|
||||||
match self.environments.lookup(&mem) {
|
match self.environments.lookup(&mem) {
|
||||||
Some(RuntimeValue::Primitive(expr)) => expr.clone(),
|
Some(RuntimeValue::Primitive(expr)) => expr.clone(),
|
||||||
_ => return Err(format!("Nothing found for variable lookup {} of kind {:?}", id, kind)),
|
_ => return Err(format!("Nothing found for variable lookup {} of kind {:?}", id, kind)),
|
||||||
@ -302,7 +335,24 @@ impl<'a> State<'a> {
|
|||||||
let mem = (&def_id).into();
|
let mem = (&def_id).into();
|
||||||
Ok(match self.environments.lookup(&mem) {
|
Ok(match self.environments.lookup(&mem) {
|
||||||
Some(RuntimeValue::Function(FunctionDefinition { body })) => {
|
Some(RuntimeValue::Function(FunctionDefinition { body })) => {
|
||||||
return Err("unimplemented apply-function".to_string());
|
let body = body.clone(); //TODO ideally this clone would not happen
|
||||||
|
|
||||||
|
let mut evaluated_args: Vec<Primitive> = vec![];
|
||||||
|
for arg in args.into_iter() {
|
||||||
|
evaluated_args.push(self.expression(arg)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut frame_state = State {
|
||||||
|
environments: self.environments.new_scope(None)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (n, evaled) in evaluated_args.into_iter().enumerate() {
|
||||||
|
let n = n as u8;
|
||||||
|
let mem = n.into();
|
||||||
|
frame_state.environments.insert(mem, RuntimeValue::Primitive(evaled));
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_state.block(body)?
|
||||||
},
|
},
|
||||||
e => return Err(format!("Error looking up function with id {}: {:?}", def_id, e)),
|
e => return Err(format!("Error looking up function with id {}: {:?}", def_id, e)),
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user