Implement let-expressions resolves #2

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

View File

@@ -109,16 +109,30 @@ fn interpret_lambda(vec: &Vec<Datum>, _env: &mut Env) -> Datum {
} }
} }
} }
let body; let body = vec[2..].to_vec();
if let List(insts) = &vec[2] { Lambda { parameters, body }
body = insts.to_vec(); }
} else {
panic!("INTERPRET-LAMBDA - body not a list {:?}", vec[1]);
}
Lambda { fn transform_let_to_lambda(vec: &Vec<Datum>) -> Datum {
parameters: parameters, let mut args = vec![];
body: body, 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] { match &args[0] {
Procedure(proc) => proc(args), Primitive(proc) => proc(args),
Lambda { parameters, body } => { Lambda { parameters, body } => {
let lambda_args = args[1..].to_vec(); let lambda_args = args[1..].to_vec();
let mut new_env = 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, "define") => interpret_define(v, env),
List(v) if has_tag(v, "cond") => interpret_cond(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, "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, "begin") => interpret_begin(v, env),
List(v) if has_tag(v, "quote") => v[1].clone(), List(v) if has_tag(v, "quote") => v[1].clone(),
List(v) => interpret_application(v, env), List(v) => interpret_application(v, env),
Lambda { .. } => exp.clone(),
Unspecified => Unspecified, Unspecified => Unspecified,
_ => panic!("unknown-expression {:?}", exp), _ => panic!("unknown-expression {:?}", exp),
} }

View File

@@ -52,7 +52,7 @@ fn interpret_file(filename: &Path) {
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); 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 = "(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 { if args.len() == 2 {
let arg_path = Path::new(&args[1]); let arg_path = Path::new(&args[1]);

View File

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