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, discriminator,
body, body,
} => Unimplemented, //self.reduce_if_expression(deref_optional_box(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), NamedStruct { name, fields } => Unimplemented, //self.reduce_named_struct(name, fields),
Index { .. } => Unimplemented, Index { .. } => Unimplemented,
WhileExpression { .. } => Unimplemented, WhileExpression { .. } => Unimplemented,

View File

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

View File

@ -246,7 +246,23 @@ impl<'a> State<'a> {
}; };
match func { match func {
Function::Builtin(builtin) => self.apply_builtin(builtin, args), 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> { fn apply_function(&mut self, body: Vec<Statement>, 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
let mut evaluated_args: Vec<Primitive> = vec![]; let mut evaluated_args: Vec<Primitive> = vec![];
for arg in args.into_iter() { for arg in args.into_iter() {
evaluated_args.push(self.expression(arg)?); evaluated_args.push(self.expression(arg)?);
} }
let mut frame_state = State { let mut frame_state = State {
environments: self.environments.new_scope(None) environments: self.environments.new_scope(None)
}; };
for (n, evaled) in evaluated_args.into_iter().enumerate() { for (n, evaled) in evaluated_args.into_iter().enumerate() {
let n = n as u8; let n = n as u8;
let mem = n.into(); let mem = n.into();
frame_state.environments.insert(mem, RuntimeValue::Primitive(evaled)); frame_state.environments.insert(mem, RuntimeValue::Primitive(evaled));
} }
frame_state.block(body)? frame_state.block(body)
},
e => return Err(format!("Error looking up function with id {}: {:?}", def_id, e)),
})
} }
} }