Implement lambda support
parent
f8b8019682
commit
b3181602d6
|
@ -1,6 +1,5 @@
|
|||
use crate::environment;
|
||||
use crate::environment::Env;
|
||||
use crate::parser::make_symbol;
|
||||
use crate::parser::Datum;
|
||||
use crate::parser::Datum::*;
|
||||
|
||||
|
@ -72,11 +71,14 @@ fn interpret_define(args: &Vec<Datum>, env: &mut Env) -> Datum {
|
|||
panic!("INTERPRET-DEFINE -- parameter not a symbol {:?}", p);
|
||||
}
|
||||
}
|
||||
// FIXME: we need to keep the current environment here otherwise closures will not work
|
||||
// FIXME: also create a dedicated enum-type for procedures instead of putting it into a vector
|
||||
let lambda_parameters = Datum::List(parameters);
|
||||
let lambda_body = Datum::List(args[2..].to_vec());
|
||||
let lambda = Datum::List(vec![make_symbol("lambda"), lambda_parameters, lambda_body]);
|
||||
|
||||
// XXX: A procedure is clearly not a lambda. We have to keep the
|
||||
// scope of the definition. Otherwise, closures won't work.
|
||||
let lambda_body = args[2..].to_vec();
|
||||
let lambda = Lambda {
|
||||
parameters: parameters,
|
||||
body: lambda_body,
|
||||
};
|
||||
environment::define_variable(definition_var, lambda, env)
|
||||
}
|
||||
_ => panic!("INTERPRET-DEFINE -- cannot define {:?}", args),
|
||||
|
@ -96,6 +98,30 @@ fn interpret_cond(vec: &Vec<Datum>, env: &mut Env) -> Datum {
|
|||
panic!("INTERPRET-COND -- missing else statement? {:?}", vec)
|
||||
}
|
||||
|
||||
fn interpret_lambda(vec: &Vec<Datum>, _env: &mut Env) -> Datum {
|
||||
let mut parameters = vec![];
|
||||
if let List(params) = &vec[1] {
|
||||
for p in params {
|
||||
if let Symbol(_) = p {
|
||||
parameters.push(p.clone());
|
||||
} else {
|
||||
panic!("INTERPRET-LAMBDA - not a symbol {:?}", p);
|
||||
}
|
||||
}
|
||||
}
|
||||
let body;
|
||||
if let List(insts) = &vec[2] {
|
||||
body = insts.to_vec();
|
||||
} else {
|
||||
panic!("INTERPRET-LAMBDA - body not a list {:?}", vec[1]);
|
||||
}
|
||||
|
||||
Lambda {
|
||||
parameters: parameters,
|
||||
body: body,
|
||||
}
|
||||
}
|
||||
|
||||
fn interpret_begin(vec: &Vec<Datum>, env: &mut Env) -> Datum {
|
||||
let mut r = Datum::Unspecified;
|
||||
for i in 1..vec.len() {
|
||||
|
@ -117,21 +143,14 @@ fn interpret_application(vec: &Vec<Datum>, env: &mut Env) -> Datum {
|
|||
|
||||
match &args[0] {
|
||||
Procedure(proc) => proc(args),
|
||||
List(v) if has_tag(v, "lambda") => {
|
||||
let lambda_parameters = v[1].clone();
|
||||
let lambda_body = &v[2];
|
||||
Lambda { parameters, body } => {
|
||||
let lambda_args = args[1..].to_vec();
|
||||
|
||||
let mut new_env = environment::extend(lambda_parameters, List(lambda_args), env);
|
||||
if let List(seq) = lambda_body {
|
||||
for i in 0..(seq.len() - 1) {
|
||||
interpret(&seq[i], &mut new_env);
|
||||
}
|
||||
// XXX: not tail-call optimized
|
||||
interpret(&seq[seq.len() - 1], &mut new_env)
|
||||
} else {
|
||||
panic!("INTERPRET-APPLICATION -- no-list {:?}", lambda_body)
|
||||
let mut new_env =
|
||||
environment::extend(List(parameters.to_vec()), List(lambda_args), env);
|
||||
for i in 0..(body.len() - 1) {
|
||||
interpret(&body[i], &mut new_env);
|
||||
}
|
||||
interpret(&body[body.len() - 1], &mut new_env)
|
||||
}
|
||||
_ => panic!("INTERPRET-APPLICATION -- not-aplicable {:?}", args[0]),
|
||||
}
|
||||
|
@ -147,6 +166,7 @@ pub fn interpret(exp: &Datum, env: &mut Env) -> Datum {
|
|||
List(v) if has_tag(v, "set!") => interpret_set(v, env),
|
||||
List(v) if has_tag(v, "define") => interpret_define(v, env),
|
||||
List(v) if has_tag(v, "cond") => interpret_cond(v, env),
|
||||
List(v) if has_tag(v, "lambda") => interpret_lambda(v, env),
|
||||
List(v) if has_tag(v, "let") => panic!("let-not-supported"),
|
||||
List(v) if has_tag(v, "begin") => interpret_begin(v, env),
|
||||
List(v) if has_tag(v, "quote") => v[1].clone(),
|
||||
|
|
|
@ -12,6 +12,10 @@ pub enum Datum {
|
|||
Pair(Box<(Datum, Datum)>),
|
||||
List(Vec<Datum>),
|
||||
Procedure(fn(Vec<Datum>) -> Datum),
|
||||
Lambda {
|
||||
parameters: Vec<Datum>,
|
||||
body: Vec<Datum>,
|
||||
},
|
||||
Unspecified,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue