Implement let-expressions resolves #2

master
Felix Martin 2021-06-01 20:54:05 -04:00
parent b3181602d6
commit 7b5435141a
4 changed files with 42 additions and 29 deletions

View File

@ -1,6 +1,5 @@
use crate::parser::make_symbol;
use crate::parser::Datum;
use crate::primitives;
use std::mem;
type Mapping = (Datum, Datum);
@ -14,23 +13,22 @@ pub struct Frame<'a> {
pub type Env<'a> = Frame<'a>;
pub fn get_global_environment<'a>() -> Env<'a> {
use crate::parser::Datum::Primitive;
use crate::primitives::*;
Frame {
mappings: vec![
(make_symbol("+"), Datum::Procedure(primitives::add)),
(make_symbol("*"), Datum::Procedure(primitives::mul)),
(make_symbol("-"), Datum::Procedure(primitives::sub)),
(make_symbol("="), Datum::Procedure(primitives::eq)),
(make_symbol("<"), Datum::Procedure(primitives::lt)),
(make_symbol("list"), Datum::Procedure(primitives::list)),
(make_symbol("cons"), Datum::Procedure(primitives::cons)),
(make_symbol("car"), Datum::Procedure(primitives::car)),
(make_symbol("cdr"), Datum::Procedure(primitives::cdr)),
(make_symbol("pair?"), Datum::Procedure(primitives::pair)),
(make_symbol("null?"), Datum::Procedure(primitives::null)),
(
make_symbol("display"),
Datum::Procedure(primitives::display),
),
(make_symbol("+"), Primitive(add)),
(make_symbol("*"), Primitive(mul)),
(make_symbol("-"), Primitive(sub)),
(make_symbol("="), Primitive(eq)),
(make_symbol("<"), Primitive(lt)),
(make_symbol("list"), Primitive(list)),
(make_symbol("cons"), Primitive(cons)),
(make_symbol("car"), Primitive(car)),
(make_symbol("cdr"), Primitive(cdr)),
(make_symbol("pair?"), Primitive(pair)),
(make_symbol("null?"), Primitive(null)),
(make_symbol("display"), Primitive(display)),
],
outer: None,
}

View File

@ -109,16 +109,30 @@ fn interpret_lambda(vec: &Vec<Datum>, _env: &mut Env) -> Datum {
}
}
}
let body;
if let List(insts) = &vec[2] {
body = insts.to_vec();
} else {
panic!("INTERPRET-LAMBDA - body not a list {:?}", vec[1]);
}
let body = vec[2..].to_vec();
Lambda { parameters, body }
}
Lambda {
parameters: parameters,
body: body,
fn transform_let_to_lambda(vec: &Vec<Datum>) -> Datum {
let mut args = vec![];
let mut parameters = vec![];
let body = vec[2..].to_vec();
if let List(bindings) = &vec[1] {
for binding in bindings {
if let List(binding) = binding {
parameters.push(binding[0].clone());
args.push(binding[1].clone());
} else {
panic!("TRANSFORM-LET-TO-LAMBDA -- invalid binding {:?}", binding);
}
}
let lambda = Lambda { parameters, body };
let mut result = vec![lambda];
result.append(&mut args);
List(result)
} else {
panic!("TRANSFORM-LET-TO-LAMBDA -- invalid bindings {:?}", vec[1]);
}
}
@ -142,7 +156,7 @@ fn interpret_application(vec: &Vec<Datum>, env: &mut Env) -> Datum {
}
match &args[0] {
Procedure(proc) => proc(args),
Primitive(proc) => proc(args),
Lambda { parameters, body } => {
let lambda_args = args[1..].to_vec();
let mut new_env =
@ -167,10 +181,11 @@ pub fn interpret(exp: &Datum, env: &mut Env) -> Datum {
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, "let") => interpret(&transform_let_to_lambda(v), env),
List(v) if has_tag(v, "begin") => interpret_begin(v, env),
List(v) if has_tag(v, "quote") => v[1].clone(),
List(v) => interpret_application(v, env),
Lambda { .. } => exp.clone(),
Unspecified => Unspecified,
_ => panic!("unknown-expression {:?}", exp),
}

View File

@ -52,7 +52,7 @@ fn interpret_file(filename: &Path) {
fn main() {
let args: Vec<String> = env::args().collect();
// let scm_code = "(begin (define (f n) (if (= n 1) 1 (* n (f (- n 1))))) (f 10))";
let scm_code = "";
let scm_code = "(let ((a 3) (b 4)) (define c (+ a b)) (* c c))";
if args.len() == 2 {
let arg_path = Path::new(&args[1]);

View File

@ -11,7 +11,7 @@ pub enum Datum {
Symbol(String),
Pair(Box<(Datum, Datum)>),
List(Vec<Datum>),
Procedure(fn(Vec<Datum>) -> Datum),
Primitive(fn(Vec<Datum>) -> Datum),
Lambda {
parameters: Vec<Datum>,
body: Vec<Datum>,