Implement let-expressions resolves #2
parent
b3181602d6
commit
7b5435141a
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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>,
|
||||
|
|
Loading…
Reference in New Issue