Implement begin and define

This commit is contained in:
2021-05-29 11:29:27 -04:00
parent 794cad2219
commit b0968ba498
3 changed files with 88 additions and 47 deletions

View File

@@ -13,29 +13,6 @@ fn is_true(exp: &Datum) -> bool {
}
}
fn application(exp: &Datum, env: &Env) -> Datum {
if let List(vector) = exp {
if vector.len() == 0 {
panic!("APPLICATION -- no-procedure")
}
let mut args = vec![];
for v in vector {
let a = interpret(v, env);
args.push(a)
}
// let mut args: Vec<Datum> = vector.into_iter().map(interpret).collect();
if let Procedure(proc) = mem::take(&mut args[0]) {
proc(args)
} else {
panic!("APPLICATION -- not-aplicable {:?}", args[0])
}
} else {
panic!("APPLICATION -- cannot-apply {:?}", exp)
}
}
fn has_tag(exp: &Datum, tag: &str) -> bool {
if let List(l) = exp {
if l.len() == 0 {
@@ -50,39 +27,76 @@ fn has_tag(exp: &Datum, tag: &str) -> bool {
false
}
fn interpret_if(args: &Vec<Datum>, env: &Env) -> Datum {
fn interpret_if(args: &Vec<Datum>, env: &mut Env) -> Datum {
let predicate = &args[1];
let alternative = &args[2];
if is_true(&predicate) {
interpret(&alternative, env)
if is_true(predicate) {
interpret(alternative, env)
} else {
if args.len() == 4 {
let consequent = &args[3];
interpret(&consequent, env)
interpret(consequent, env)
} else {
Unspecified
}
}
}
fn interpret_define(_args: &Vec<Datum>) -> Datum {
Number(42)
fn interpret_define(args: &Vec<Datum>, env: &mut Env) -> Datum {
match args[1] {
Symbol(_) => {
let var = &args[1];
let val = interpret(&args[2], env);
environment::define_variable(var, val, env)
},
List(_) => {
println!("procedure definition");
Number(42)
}
_ => panic!("INTERPRET-DEFINE -- cannot define {:?}", args)
}
}
pub fn interpret(exp: &Datum, env: &Env) -> Datum {
fn interpret_begin(vec: &Vec<Datum>, env: &mut Env) -> Datum {
let mut r = Datum::Unspecified;
for i in 1..vec.len() {
r = interpret(&vec[i], env);
}
r
}
fn interpret_application(vec: &Vec<Datum>, env: &mut Env) -> Datum {
if vec.len() == 0 {
panic!("APPLICATION -- no-procedure")
}
let mut args = vec![];
for v in vec {
let a = interpret(v, env);
args.push(a)
}
if let Procedure(proc) = mem::take(&mut args[0]) {
proc(args)
} else {
panic!("APPLICATION -- not-aplicable {:?}", args[0])
}
}
pub fn interpret(exp: &Datum, env: &mut Env) -> Datum {
match exp {
Boolean(b) => Boolean(*b),
Number(n) => Number(*n),
Symbol(_) => environment::lookup_variable_value(&exp, &env),
List(v) if has_tag(&exp, "if") => interpret_if(v, &env),
Boolean(_) => exp.clone(),
Number(_) => exp.clone(),
Unspecified => Unspecified,
Symbol(_) => environment::lookup_variable_value(exp, env),
List(v) if has_tag(&exp, "if") => interpret_if(v, env),
List(_) if has_tag(&exp, "set!") => panic!("assignment-not-supported"),
List(v) if has_tag(&exp, "define") => interpret_define(v),
List(v) if has_tag(&exp, "define") => interpret_define(v, env),
List(_) if has_tag(&exp, "cond") => panic!("cond-not-supported"),
List(_) if has_tag(&exp, "let") => panic!("let-not-supported"),
List(_) if has_tag(&exp, "begin") => panic!("begin-not-supported"),
List(_) => application(exp, env),
List(v) if has_tag(&exp, "begin") => interpret_begin(v, env),
List(v) => interpret_application(v, env),
// TODO: quoted
_ => panic!("unknown-expression {:?}", exp),
}