Implement begin and define
This commit is contained in:
@@ -13,8 +13,8 @@ pub fn get_global_environment() -> Env {
|
|||||||
(make_symbol("-"), Procedure(primitives::sub))]]
|
(make_symbol("-"), Procedure(primitives::sub))]]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_variable_value(exp: &Datum, env: &Env) -> Datum {
|
pub fn lookup_variable_value(var: &Datum, env: &Env) -> Datum {
|
||||||
if let Symbol(symbol_name) = exp {
|
if let Symbol(symbol_name) = var {
|
||||||
for frame in env {
|
for frame in env {
|
||||||
for mapping in frame {
|
for mapping in frame {
|
||||||
if let (Symbol(current_name), datum) = mapping {
|
if let (Symbol(current_name), datum) = mapping {
|
||||||
@@ -25,7 +25,34 @@ pub fn lookup_variable_value(exp: &Datum, env: &Env) -> Datum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("LOOKUP-VARIABLE-VALUE -- not-a-symbol {:?}", exp)
|
panic!("LOOKUP-VARIABLE-VALUE -- not-a-symbol {:?}", var)
|
||||||
}
|
}
|
||||||
panic!("LOOKUP-VARIABLE-VALUE -- unbound-variable-error {:?}", exp)
|
panic!("LOOKUP-VARIABLE-VALUE -- unbound-variable-error {:?}", var)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn define_variable(var: &Datum, val: Datum, env: &mut Env) -> Datum {
|
||||||
|
if let Symbol(symbol_name) = var {
|
||||||
|
// Assign to variable if it already exits
|
||||||
|
if let Some(frame) = env.last_mut() {
|
||||||
|
for mapping in frame {
|
||||||
|
if let (Symbol(current_name), _) = mapping {
|
||||||
|
if symbol_name == current_name {
|
||||||
|
mapping.1 = val;
|
||||||
|
return Datum::Unspecified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("DEFINE-VARIABLE -- no-frames {:?}", env)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create variable because it does not exist yet
|
||||||
|
if let Some(frame) = env.last_mut() {
|
||||||
|
let pair = (var.clone(), val);
|
||||||
|
frame.push(pair);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("DEFINE-VARIABLE -- not-a-symbol {:?}", var)
|
||||||
|
}
|
||||||
|
Datum::Unspecified
|
||||||
}
|
}
|
||||||
@@ -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 {
|
fn has_tag(exp: &Datum, tag: &str) -> bool {
|
||||||
if let List(l) = exp {
|
if let List(l) = exp {
|
||||||
if l.len() == 0 {
|
if l.len() == 0 {
|
||||||
@@ -50,39 +27,76 @@ fn has_tag(exp: &Datum, tag: &str) -> bool {
|
|||||||
false
|
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 predicate = &args[1];
|
||||||
let alternative = &args[2];
|
let alternative = &args[2];
|
||||||
|
|
||||||
if is_true(&predicate) {
|
if is_true(predicate) {
|
||||||
interpret(&alternative, env)
|
interpret(alternative, env)
|
||||||
} else {
|
} else {
|
||||||
if args.len() == 4 {
|
if args.len() == 4 {
|
||||||
let consequent = &args[3];
|
let consequent = &args[3];
|
||||||
interpret(&consequent, env)
|
interpret(consequent, env)
|
||||||
} else {
|
} else {
|
||||||
Unspecified
|
Unspecified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_define(_args: &Vec<Datum>) -> Datum {
|
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)
|
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 {
|
match exp {
|
||||||
Boolean(b) => Boolean(*b),
|
Boolean(_) => exp.clone(),
|
||||||
Number(n) => Number(*n),
|
Number(_) => exp.clone(),
|
||||||
Symbol(_) => environment::lookup_variable_value(&exp, &env),
|
Unspecified => Unspecified,
|
||||||
List(v) if has_tag(&exp, "if") => interpret_if(v, &env),
|
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(_) 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, "cond") => panic!("cond-not-supported"),
|
||||||
List(_) if has_tag(&exp, "let") => panic!("let-not-supported"),
|
List(_) if has_tag(&exp, "let") => panic!("let-not-supported"),
|
||||||
List(_) if has_tag(&exp, "begin") => panic!("begin-not-supported"),
|
List(v) if has_tag(&exp, "begin") => interpret_begin(v, env),
|
||||||
List(_) => application(exp, env),
|
List(v) => interpret_application(v, env),
|
||||||
// TODO: quoted
|
// TODO: quoted
|
||||||
_ => panic!("unknown-expression {:?}", exp),
|
_ => panic!("unknown-expression {:?}", exp),
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/main.rs
10
src/main.rs
@@ -5,12 +5,12 @@ mod primitives;
|
|||||||
mod environment;
|
mod environment;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let scm_code = "(if #f (+ 1 1) (* 2 3 4))";
|
// let scm_code = "(if #t (+ 1 1) (* 2 3 4))";
|
||||||
// let scm_code = "(define a (+ 3 3)";
|
// let scm_code = "(begin (define a (+ 2 2)) (* 3 2) (* a a a))";
|
||||||
// let scm_code = "(- (* 3 3) 4)";
|
let scm_code = "(begin (define (f n) (* n n)) (* 3 2))";
|
||||||
let env = environment::get_global_environment();
|
|
||||||
let tokens = lexer::read(scm_code);
|
let tokens = lexer::read(scm_code);
|
||||||
let datum = parser::parse(tokens);
|
let datum = parser::parse(tokens);
|
||||||
let result = interpreter::interpret(&datum, &env);
|
let mut env = environment::get_global_environment();
|
||||||
|
let result = interpreter::interpret(&datum, &mut env);
|
||||||
println!("{:?}", result);
|
println!("{:?}", result);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user