Finish support for assignment operators

This commit is contained in:
greg 2017-01-06 00:58:47 -08:00
parent 23d2209d8b
commit 298194c42d
2 changed files with 34 additions and 11 deletions

View File

@ -106,6 +106,14 @@ impl Expression {
} }
} }
fn is_assignment(op: &str) -> bool {
match op {
"=" | "+=" | "-=" |
"*=" | "/=" => true,
_ => false,
}
}
impl<'a> Evaluator<'a> { impl<'a> Evaluator<'a> {
fn reduction_loop(&mut self, mut node: Statement) -> Statement { fn reduction_loop(&mut self, mut node: Statement) -> Statement {
loop { loop {
@ -118,6 +126,7 @@ impl<'a> Evaluator<'a> {
} }
fn step(&mut self, node: Statement) -> Statement { fn step(&mut self, node: Statement) -> Statement {
println!("Step: {:?}", node);
let (new_node, side_effect) = self.reduce_astnode(node); let (new_node, side_effect) = self.reduce_astnode(node);
if let Some(s) = side_effect { if let Some(s) = side_effect {
self.perform_side_effect(s); self.perform_side_effect(s);
@ -176,15 +185,32 @@ impl<'a> Evaluator<'a> {
return (BinExp(op, left, right), side_effect); return (BinExp(op, left, right), side_effect);
} }
// special case for variable assignment
if *op == "=" { if *op == "=" {
match *left { return match *left {
Variable(var) => { Variable(var) => {
let binding = SideEffect::AddBinding(var, *right); let binding = SideEffect::AddBinding(var, *right);
return (Null, Some(binding)); (Null, Some(binding))
} },
_ => return (Null, None), _ => (Null, None)
};
} }
if is_assignment(&*op) {
let new_op = Rc::new(String::from(match &op[..] {
"+=" => "+",
"-=" => "-",
"*=" => "*",
"/=" => "/",
_ => unreachable!(),
}));
let reduction =
BinExp(Rc::new(String::from("=")),
Box::new(*left.clone()),
Box::new(BinExp(new_op, left, right))
);
return (reduction, None);
} }
if left.is_reducible() { if left.is_reducible() {
@ -254,6 +280,7 @@ impl<'a> Evaluator<'a> {
} }
fn reduce_binop(&mut self, op: Rc<String>, left: Expression, right: Expression) -> Expression { fn reduce_binop(&mut self, op: Rc<String>, left: Expression, right: Expression) -> Expression {
println!("Got op {:?}, l: {:?}, r: {:?}", op, left, right);
let truthy = Number(1.0); let truthy = Number(1.0);
let falsy = Null; let falsy = Null;
match (&op[..], left, right) { match (&op[..], left, right) {
@ -273,10 +300,6 @@ impl<'a> Evaluator<'a> {
("==", Null, Null) => truthy, ("==", Null, Null) => truthy,
("==", StringLiteral(s1), StringLiteral(s2)) => if s1 == s2 { truthy } else { falsy }, ("==", StringLiteral(s1), StringLiteral(s2)) => if s1 == s2 { truthy } else { falsy },
("==", _, _) => falsy, ("==", _, _) => falsy,
("+=", l, r) => BinExp("=", l, BinExp("+", l, r)),
("-=", l, r) => BinExp("=", l, BinExp("-", l, r)),
("*=", l, r) => BinExp("=", l, BinExp("*", l, r)),
("/=", l, r) => BinExp("=", l, BinExp("/", l, r)),
_ => falsy, _ => falsy,
} }
} }

View File

@ -127,7 +127,7 @@ impl Parser {
"*" => 20, "*" => 20,
"/" => 20, "/" => 20,
"%" => 20, "%" => 20,
"==" => 40 "==" => 40,
"=" | "+=" | "-=" | "*=" | "/=" => 1, "=" | "+=" | "-=" | "*=" | "/=" => 1,
">" | ">=" | "<" | "<=" => 30, ">" | ">=" | "<" | "<=" => 30,
_ => 255, _ => 255,