Implement booleans

This commit is contained in:
greg 2015-08-13 22:46:46 -07:00
parent 9a4760d44f
commit ddb09b453d
2 changed files with 17 additions and 12 deletions

View File

@ -9,7 +9,10 @@ type EvalResult = (AST, Environment);
impl Environment { impl Environment {
pub fn new() -> Environment { pub fn new() -> Environment {
Environment(HashMap::new()) let mut map = HashMap::new();
map.insert("true".to_string(), LangTrue);
map.insert("false".to_string(), LangFalse);
Environment(map)
} }
fn add_binding(&mut self, name: String, binding: AST) { fn add_binding(&mut self, name: String, binding: AST) {
@ -45,7 +48,9 @@ pub fn evaluate(ast: AST, env: Environment) -> (String, Environment) {
Number(n) => format!("{}", n), Number(n) => format!("{}", n),
LangString(s) => format!("\"{}\"", s), LangString(s) => format!("\"{}\"", s),
Null => "null".to_string(), Null => "null".to_string(),
_ => "not implemented".to_string() LangFalse => "false".to_string(),
LangTrue => "true".to_string(),
other => format!("reducing {:?} not implemented", other)
}; };
(output, final_env) (output, final_env)
@ -59,7 +64,7 @@ fn reduce(evr: EvalResult) -> EvalResult {
IfStatement(if_clause, then_clause, else_clause) => { IfStatement(if_clause, then_clause, else_clause) => {
let (condition, new_env) = reduce((*if_clause, env)); let (condition, new_env) = reduce((*if_clause, env));
match condition { match condition {
Null => match else_clause { Null | LangFalse => match else_clause {
Some(cl) => reduce((*cl, new_env)), Some(cl) => reduce((*cl, new_env)),
None => (DoNothing, new_env) None => (DoNothing, new_env)
}, },
@ -71,7 +76,7 @@ fn reduce(evr: EvalResult) -> EvalResult {
WhileStatement(condition, body) => { WhileStatement(condition, body) => {
let (continue_loop, env) = reduce((*condition.clone(), env)); let (continue_loop, env) = reduce((*condition.clone(), env));
match continue_loop { match continue_loop {
Null => (DoNothing, env), Null | LangFalse => (DoNothing, env),
_ => { _ => {
let (_, new_env) = reduce((*body.clone(), env)); let (_, new_env) = reduce((*body.clone(), env));
reduce((WhileStatement(condition, body), new_env)) reduce((WhileStatement(condition, body), new_env))
@ -83,13 +88,15 @@ fn reduce(evr: EvalResult) -> EvalResult {
let (reduced_lhs, new_env) = reduce((*lhs, env)); let (reduced_lhs, new_env) = reduce((*lhs, env));
let (reduced_rhs, new_env2) = reduce((*rhs, new_env)); let (reduced_rhs, new_env2) = reduce((*rhs, new_env));
let result: AST = reduce_binop(*op, reduced_lhs, reduced_rhs); let result: AST = reduce_binop(*op, reduced_lhs, reduced_rhs);
(result, new_env2) reduce((result, new_env2))
}, },
Name(name) => { Name(name) => {
let result = match env.lookup_binding(&name) { let result = match env.lookup_binding(&name) {
Some(binding) => match binding { Some(binding) => match binding {
&DoNothing => DoNothing, &DoNothing => DoNothing,
&LangTrue => LangTrue,
&LangFalse => LangFalse,
&Number(n) => Number(n), &Number(n) => Number(n),
&LangString(ref s) => LangString(s.clone()), &LangString(ref s) => LangString(s.clone()),
&Null => Null, &Null => Null,
@ -126,10 +133,6 @@ fn reduce(evr: EvalResult) -> EvalResult {
} }
fn reduce_binop(op: AST, lhs: AST, rhs: AST) -> AST { fn reduce_binop(op: AST, lhs: AST, rhs: AST) -> AST {
macro_rules! LangBool {
(true) => [Name("true".to_string())];
(false) => [Name("false".to_string())];
}
match (lhs, rhs) { match (lhs, rhs) {
(Number(l), Number(r)) => match op { (Number(l), Number(r)) => match op {
@ -137,9 +140,9 @@ fn reduce_binop(op: AST, lhs: AST, rhs: AST) -> AST {
Name(ref s) if *s == "-" => Number(l - r), Name(ref s) if *s == "-" => Number(l - r),
Name(ref s) if *s == "*" => Number(l * r), Name(ref s) if *s == "*" => Number(l * r),
Name(ref s) if *s == "/" => if r == 0.0 { Null } else { Number(l / r) }, Name(ref s) if *s == "/" => if r == 0.0 { Null } else { Number(l / r) },
Name(ref s) if *s == "==" => if l == r { LangBool!(true) } else { LangBool!(false) }, Name(ref s) if *s == "==" => if l == r { LangTrue } else { LangFalse },
Name(ref s) if *s == ">" => if l > r { LangBool!(true) } else { LangBool!(false) }, Name(ref s) if *s == ">" => if l > r { LangTrue } else { LangFalse },
Name(ref s) if *s == "<" => if l < r { LangBool!(true) } else { LangBool!(false) }, Name(ref s) if *s == "<" => if l < r { LangTrue } else { LangFalse },
_ => Null _ => Null
}, },

View File

@ -7,6 +7,8 @@ use tokenizer::Token::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum AST { pub enum AST {
Null, Null,
LangTrue,
LangFalse,
Name(String), Name(String),
LangString(String), LangString(String),
Number(f64), Number(f64),