Implement set! resolves #3

master
Felix Martin 2021-05-30 12:44:25 -04:00
parent 1da08c0a43
commit 3b3ab96f7d
3 changed files with 33 additions and 2 deletions

View File

@ -63,6 +63,26 @@ pub fn define_variable(var: &Datum, val: Datum, env: &mut Env) -> Datum {
var.clone()
}
pub fn set_variable(var: &Datum, val: Datum, env: &mut Env) -> Datum {
if let Datum::Symbol(symbol_name) = var {
for mapping in &mut env.mappings {
if let (Datum::Symbol(current_name), _) = mapping {
if symbol_name == current_name {
mapping.1 = val;
return var.clone();
}
}
}
match env.outer {
// XXX: search outer environments here
// Some(outer_env) => set_variable(var, val, outer_env),
_ => panic!("SET-VARIABLE -- unbound-var {:?}", var),
}
} else {
panic!("DEFINE-VARIABLE -- not-a-symbol {:?}", var)
}
}
pub fn extend<'a>(vars: Datum, vals: Datum, env: &'a Env) -> Env<'a> {
let mut mappings = vec![];
if let (Datum::List(mut vars), Datum::List(mut vals)) = (vars, vals) {

View File

@ -42,6 +42,17 @@ fn interpret_if(args: &Vec<Datum>, env: &mut Env) -> Datum {
}
}
fn interpret_set(args: &Vec<Datum>, env: &mut Env) -> Datum {
match &args[1] {
Symbol(_) => {
let var = &args[1];
let val = interpret(&args[2], env);
environment::set_variable(var, val, env)
}
_ => panic!("INTERPRET-SET -- cannot set {:?}", args),
}
}
fn interpret_define(args: &Vec<Datum>, env: &mut Env) -> Datum {
match &args[1] {
Symbol(_) => {
@ -119,7 +130,7 @@ pub fn interpret(exp: &Datum, env: &mut Env) -> Datum {
Unspecified => Unspecified,
Symbol(_) => environment::lookup_variable_value(exp, env),
List(v) if has_tag(v, "if") => interpret_if(v, env),
List(v) if has_tag(v, "set!") => panic!("assignment-not-supported"),
List(v) if has_tag(v, "set!") => interpret_set(v, env),
List(v) if has_tag(v, "define") => interpret_define(v, env),
List(v) if has_tag(v, "cond") => panic!("cond-not-supported"),
List(v) if has_tag(v, "let") => panic!("let-not-supported"),

View File

@ -135,4 +135,4 @@ const SPECIAL_INITIAL: &[char] = &[
'!', '$', '%', '&', '*', '/', ':', '<', '=', '>', '?', '^', '_', '~', '+', '-',
];
const SPECIAL_SUBSEQUENT: &[char] = &['+', '-', '.', '@'];
const SPECIAL_SUBSEQUENT: &[char] = &['+', '-', '.', '@', '!'];