Implement let-expressions resolves #2
This commit is contained in:
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
Reference in New Issue
Block a user