Handle lambdas in reduced IR

This commit is contained in:
Greg Shuflin 2021-10-24 18:59:00 -07:00
parent 7282a38a08
commit 4193971303
3 changed files with 42 additions and 24 deletions

View File

@ -130,7 +130,12 @@ impl<'a> Reducer<'a> {
discriminator,
body,
} => Unimplemented, //self.reduce_if_expression(deref_optional_box(discriminator), body),
Lambda { params, body, .. } => Unimplemented, //self.reduce_lambda(params, body),
Lambda { params, body, .. } => {
Expression::Callable(Function::Lambda {
arity: params.len() as u8,
body: self.function(body),
})
},
NamedStruct { name, fields } => Unimplemented, //self.reduce_named_struct(name, fields),
Index { .. } => Unimplemented,
WhileExpression { .. } => Unimplemented,

View File

@ -80,7 +80,11 @@ pub struct FunctionDefinition {
#[derive(Debug, Clone)]
pub enum Function {
Builtin(Builtin),
UserDefined(DefId)
UserDefined(DefId),
Lambda {
arity: u8,
body: Vec<Statement>
}
}
#[derive(Debug, Clone)]

View File

@ -246,7 +246,23 @@ impl<'a> State<'a> {
};
match func {
Function::Builtin(builtin) => self.apply_builtin(builtin, args),
Function::UserDefined(def_id) => self.apply_function(def_id, args),
Function::UserDefined(def_id) => {
let mem = (&def_id).into();
match self.environments.lookup(&mem) {
Some(RuntimeValue::Function(FunctionDefinition { body })) => {
let body = body.clone(); //TODO ideally this clone would not happen
self.apply_function(body, args)
},
e => Err(format!("Error looking up function with id {}: {:?}", def_id, e))
}
},
Function::Lambda { arity, body } => {
if arity as usize != args.len() {
return Err(format!("Lambda expression requries {} arguments, only {} provided", arity, args.len()));
}
let body = body.clone(); //TODO again ideally, no cloning here
self.apply_function(body, args)
}
}
}
@ -331,31 +347,24 @@ impl<'a> State<'a> {
})
}
fn apply_function(&mut self, def_id: DefId, args: Vec<Expression>) -> EvalResult<Primitive> {
let mem = (&def_id).into();
Ok(match self.environments.lookup(&mem) {
Some(RuntimeValue::Function(FunctionDefinition { body })) => {
let body = body.clone(); //TODO ideally this clone would not happen
fn apply_function(&mut self, body: Vec<Statement>, args: Vec<Expression>) -> EvalResult<Primitive> {
let mut evaluated_args: Vec<Primitive> = vec![];
for arg in args.into_iter() {
evaluated_args.push(self.expression(arg)?);
}
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)
};
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));
}
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)),
})
frame_state.block(body)
}
}