use crate::parser::Datum; use crate::parser::Datum::*; use crate::primitives::*; use std::mem; fn is_true(exp: &Datum) -> bool { match exp { Boolean(b) => *b, Number(_) => true, List(_) => true, _ => panic!("IS-TRUE -- unknown-truth-value {:?}", exp), } } fn lookup_variable_value(exp: &Datum) -> Datum { if let Symbol(string) = exp { match string.as_str() { "+" => Procedure(add), "*" => Procedure(mul), "-" => Procedure(sub), _ => panic!("LOOKUP-VARIABLE-VALUE -- unbound-variable {:?}", string), } } else { panic!("LOOKUP-VARIABLE-VALUE -- not-a-symbol {:?}", exp) } } fn application(exp: Datum) -> Datum { if let List(vector) = exp { if vector.len() == 0 { panic!("APPLICATION -- no-procedure") } let mut args: Vec = vector.into_iter().map(interpret).collect(); if let Procedure(proc) = mem::take(&mut args[0]) { // FIXME: call procedures with args only proc(args) } else { panic!("APPLICATION -- not-aplicable {:?}", args[0]) } } else { panic!("APPLICATION -- cannot-apply {:?}", exp) } } fn has_tag(exp: &Datum, tag: &str) -> bool { if let List(l) = exp { if l.len() == 0 { return false; } if let Symbol(s) = &l[0] { if s == tag { return true; } } } false } fn interpret_if(mut args: Vec) -> Datum { let predicate = mem::take(&mut args[1]); let alternative = mem::take(&mut args[2]); if is_true(&predicate) { interpret(alternative) } else { if args.len() == 4 { let consequent = mem::take(&mut args[3]); interpret(consequent) } else { Unspecified } } } pub fn interpret(exp: Datum) -> Datum { match exp { Boolean(_) => exp, Number(_) => exp, Symbol(_) => lookup_variable_value(&exp), List(v) if has_tag(&exp, "if") => interpret_if(v), List(_) if has_tag(&exp, "set!") => panic!("assignment-not-supported"), List(_) if has_tag(&exp, "define") => panic!("define-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, "begin") => panic!("begin-not-supported"), List(_) => application(exp), // TODO: quoted _ => panic!("unknown-expression {:?}", exp), } }