Refactored Binary Expressions to a common type and cleaned it up

This commit is contained in:
Jeremy Wall 2017-09-21 00:06:43 -05:00
parent a8b6e7f851
commit f95ecddea2
3 changed files with 259 additions and 187 deletions

View File

@ -169,25 +169,10 @@ impl MacroDef {
stack.push(expr);
while stack.len() > 0 {
match stack.pop().unwrap() {
&Expression::Add(ref bexpr) => {
let mut syms_set = self.validate_value_symbols(&mut stack, &bexpr.0);
&Expression::Binary(ref bexpr) => {
let mut syms_set = self.validate_value_symbols(&mut stack, &bexpr.left);
bad_symbols.extend(syms_set.drain());
stack.push(&bexpr.1);
},
&Expression::Sub(ref bexpr) => {
let mut syms_set = self.validate_value_symbols(&mut stack, &bexpr.0);
bad_symbols.extend(syms_set.drain());
stack.push(&bexpr.1);
},
&Expression::Mul(ref bexpr) => {
let mut syms_set = self.validate_value_symbols(&mut stack, &bexpr.0);
bad_symbols.extend(syms_set.drain());
stack.push(&bexpr.1);
},
&Expression::Div(ref bexpr) => {
let mut syms_set = self.validate_value_symbols(&mut stack, &bexpr.0);
bad_symbols.extend(syms_set.drain());
stack.push(&bexpr.1);
stack.push(&bexpr.right);
},
&Expression::Grouped(ref expr) => {
stack.push(expr);
@ -234,9 +219,21 @@ impl MacroDef {
}
}
#[derive(Debug,PartialEq,Clone)]
pub enum BinaryExprType {
Add,
Sub,
Mul,
Div,
}
/// BinaryExpression represents an expression with a left and a right side.
#[derive(Debug,PartialEq,Clone)]
pub struct BinaryExpression(pub Value, pub Box<Expression>);
pub struct BinaryExpression {
pub kind: BinaryExprType,
pub left: Value,
pub right: Box<Expression>
}
#[derive(Debug,PartialEq,Clone)]
pub struct CopyDef {
@ -256,12 +253,7 @@ pub enum Expression {
// Base Expression
Simple(Value),
// TODO(jwall): This should probably be all one type :-p
// Binary Expressions
Add(BinaryExpression),
Sub(BinaryExpression),
Mul(BinaryExpression),
Div(BinaryExpression),
Binary(BinaryExpression),
// Complex Expressions
Copy(CopyDef),
@ -305,9 +297,10 @@ mod ast_test {
"foo".to_string()
],
fields: vec![
("f1".to_string(), Expression::Add(BinaryExpression(
Value::Symbol(make_value_node("foo".to_string())),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))),
("f1".to_string(), Expression::Binary(BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Symbol(make_value_node("foo".to_string())),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1))))})),
],
};
assert!(def.validate_symbols().unwrap() == ());
@ -320,9 +313,10 @@ mod ast_test {
"foo".to_string()
],
fields: vec![
("f1".to_string(), Expression::Add(BinaryExpression(
Value::Symbol(make_value_node("bar".to_string())),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))),
("f1".to_string(), Expression::Binary(BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Symbol(make_value_node("bar".to_string())),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1))))})),
],
};
@ -338,9 +332,10 @@ mod ast_test {
"foo".to_string()
],
fields: vec![
("f1".to_string(), Expression::Add(BinaryExpression(
Value::Selector(make_value_node(vec!["foo".to_string(), "quux".to_string()])),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))),
("f1".to_string(), Expression::Binary(BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Selector(make_value_node(vec!["foo".to_string(), "quux".to_string()])),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1))))})),
],
};
assert!(def.validate_symbols().unwrap() == ());
@ -353,9 +348,10 @@ mod ast_test {
"foo".to_string()
],
fields: vec![
("f1".to_string(), Expression::Add(BinaryExpression(
Value::Selector(make_value_node(vec!["bar".to_string(), "quux".to_string()])),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))),
("f1".to_string(), Expression::Binary(BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Selector(make_value_node(vec!["bar".to_string(), "quux".to_string()])),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1))))})),
],
};
let mut expected = HashSet::new();

View File

@ -407,93 +407,91 @@ impl Builder {
Expression::Simple(val) => {
self.value_to_val(val)
},
Expression::Add(BinaryExpression(v, expr)) => {
Expression::Binary(BinaryExpression{kind, left: v, right: expr}) => {
let expr_result = try!(self.eval_expr(*expr));
let v = try!(self.value_to_val(v));
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i + ii), "Integer")
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f + ff), "Float")
},
Val::String(ref s) => {
match expr_result.as_ref() {
&Val::String(ref ss) => {
return Ok(Rc::new(
Val::String([s.to_string(), ss.clone()].concat())))
match kind {
BinaryExprType::Add => {
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i + ii), "Integer")
},
val => {
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f + ff), "Float")
},
Val::String(ref s) => {
match expr_result.as_ref() {
&Val::String(ref ss) => {
return Ok(Rc::new(
Val::String([s.to_string(), ss.clone()].concat())))
},
val => {
return Err(Box::new(
BuildError::TypeFail(
format!("Expected String but got {:?}", val))))
}
}
},
ref expr => {
return Err(Box::new(
BuildError::TypeFail(
format!("Expected String but got {:?}", val))))
BuildError::Unsupported(
format!("{} does not support the '+' operation", expr.type_name()))))
}
}
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '+' operation", expr.type_name()))))
}
}
},
Expression::Sub(BinaryExpression(v, expr)) => {
let expr_result = try!(self.eval_expr(*expr));
let v = try!(self.value_to_val(v));
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i - ii), "Integer")
BinaryExprType::Sub => {
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i - ii), "Integer")
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f - ff), "Float")
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '-' operation", expr.type_name()))))
}
}
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f - ff), "Float")
BinaryExprType::Mul => {
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i * ii), "Integer")
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f * ff), "Float")
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '*' operation", expr.type_name()))))
}
}
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '-' operation", expr.type_name()))))
}
}
},
Expression::Mul(BinaryExpression(v, expr)) => {
let expr_result = try!(self.eval_expr(*expr));
let v = try!(self.value_to_val(v));
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i * ii), "Integer")
BinaryExprType::Div => {
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i / ii), "Integer")
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f / ff), "Float")
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '*' operation", expr.type_name()))))
}
}
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f * ff), "Float")
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '*' operation", expr.type_name()))))
}
}
},
Expression::Div(BinaryExpression(v, expr)) => {
let expr_result = try!(self.eval_expr(*expr));
let v = try!(self.value_to_val(v));
match *v {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), expr_result,
Val::Int(i / ii), "Integer")
},
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), expr_result,
Val::Float(f / ff), "Float")
},
ref expr => {
return Err(Box::new(
BuildError::Unsupported(
format!("{} does not support the '*' operation", expr.type_name()))))
}
}
},
Expression::Copy(mut def) => {
@ -622,11 +620,19 @@ mod test {
fn test_eval_div_expr() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Div(BinaryExpression(Value::Int(make_value_node(2)),
Box::new(Expression::Simple(Value::Int(make_value_node(2)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Div,
left: Value::Int(make_value_node(2)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
}),
Val::Int(1)),
(Expression::Div(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Div,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))),
}),
Val::Float(1.0)),
], b);
}
@ -636,8 +642,12 @@ mod test {
fn test_eval_div_expr_fail() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Div(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Int(make_value_node(2)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Div,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2))))
}),
Val::Float(1.0)),
], b);
}
@ -646,11 +656,19 @@ mod test {
fn test_eval_mul_expr() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Mul(BinaryExpression(Value::Int(make_value_node(2)),
Box::new(Expression::Simple(Value::Int(make_value_node(2)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Mul,
left: Value::Int(make_value_node(2)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2))))
}),
Val::Int(4)),
(Expression::Mul(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Mul,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0))))
}),
Val::Float(4.0)),
], b);
}
@ -660,8 +678,12 @@ mod test {
fn test_eval_mul_expr_fail() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Mul(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Int(make_value_node(20)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Mul,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(20))))
}),
Val::Float(1.0)),
], b);
}
@ -670,11 +692,19 @@ mod test {
fn test_eval_subtract_expr() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Sub(BinaryExpression(Value::Int(make_value_node(2)),
Box::new(Expression::Simple(Value::Int(make_value_node(1)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Sub,
left: Value::Int(make_value_node(2)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
}),
Val::Int(1)),
(Expression::Sub(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Sub,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0))))
}),
Val::Float(1.0)),
], b);
}
@ -684,8 +714,12 @@ mod test {
fn test_eval_subtract_expr_fail() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Sub(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Int(make_value_node(2)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Sub,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2))))
}),
Val::Float(1.0)),
], b);
}
@ -694,14 +728,26 @@ mod test {
fn test_eval_add_expr() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Add(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1))))
}),
Val::Int(2)),
(Expression::Add(BinaryExpression(Value::Float(make_value_node(1.0)),
Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Float(make_value_node(1.0)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))),
}),
Val::Float(2.0)),
(Expression::Add(BinaryExpression(Value::String(make_value_node("foo".to_string())),
Box::new(Expression::Simple(Value::String(make_value_node("bar".to_string())))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::String(make_value_node("foo".to_string())),
right: Box::new(Expression::Simple(Value::String(make_value_node("bar".to_string())))),
}),
Val::String("foobar".to_string())),
], b);
}
@ -711,8 +757,12 @@ mod test {
fn test_eval_add_expr_fail() {
let b = Builder::new();
test_expr_to_val(vec![
(Expression::Add(BinaryExpression(Value::Float(make_value_node(2.0)),
Box::new(Expression::Simple(Value::Int(make_value_node(2)))))),
(Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Float(make_value_node(2.0)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))),
}),
Val::Float(1.0)),
], b);
}

View File

@ -199,8 +199,12 @@ named!(simple_expression<Expression>,
)
);
fn tuple_to_add_expression(tpl: (Value, Expression)) -> ParseResult<Expression> {
Ok(Expression::Add(BinaryExpression(tpl.0, Box::new(tpl.1))))
fn tuple_to_binary_expression(tpl: (BinaryExprType, Value, Expression)) -> ParseResult<Expression> {
Ok(Expression::Binary(BinaryExpression{
kind: tpl.0,
left: tpl.1,
right: Box::new(tpl.2),
}))
}
named!(add_expression<Expression>,
@ -209,57 +213,45 @@ named!(add_expression<Expression>,
left: value >>
ws!(plus) >>
right: expression >>
(left, right)
(BinaryExprType::Add, left, right)
),
tuple_to_add_expression
tuple_to_binary_expression
)
);
fn tuple_to_sub_expression(tpl: (Value, Expression)) -> ParseResult<Expression> {
Ok(Expression::Sub(BinaryExpression(tpl.0, Box::new(tpl.1))))
}
named!(sub_expression<Expression>,
map_res!(
do_parse!(
left: value >>
ws!(minus) >>
right: expression >>
(left, right)
(BinaryExprType::Sub, left, right)
),
tuple_to_sub_expression
tuple_to_binary_expression
)
);
fn tuple_to_mul_expression(tpl: (Value, Expression)) -> ParseResult<Expression> {
Ok(Expression::Mul(BinaryExpression(tpl.0, Box::new(tpl.1))))
}
named!(mul_expression<Expression>,
map_res!(
do_parse!(
left: value >>
ws!(mul) >>
right: expression >>
(left, right)
(BinaryExprType::Mul, left, right)
),
tuple_to_mul_expression
tuple_to_binary_expression
)
);
fn tuple_to_div_expression(tpl: (Value, Expression)) -> ParseResult<Expression> {
Ok(Expression::Div(BinaryExpression(tpl.0, Box::new(tpl.1))))
}
named!(div_expression<Expression>,
map_res!(
do_parse!(
left: value >>
ws!(div) >>
right: expression >>
(left, right)
(BinaryExprType::Div, left, right)
),
tuple_to_div_expression
tuple_to_binary_expression
)
);
@ -623,37 +615,61 @@ mod test {
IResult::Done(&b""[..], Expression::Simple(Value::Symbol(make_value_node("foo".to_string())))));
assert_eq!(expression(&b"1 + 1"[..]),
IResult::Done(&b""[..],
Expression::Add(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1 - 1"[..]),
IResult::Done(&b""[..],
Expression::Sub(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Sub,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1 * 1"[..]),
IResult::Done(&b""[..],
Expression::Mul(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Mul,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1 / 1"[..]),
IResult::Done(&b""[..],
Expression::Div(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Div,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1+1"[..]),
IResult::Done(&b""[..],
Expression::Add(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1-1"[..]),
IResult::Done(&b""[..],
Expression::Sub(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Sub,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1*1"[..]),
IResult::Done(&b""[..],
Expression::Mul(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Mul,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"1/1"[..]),
IResult::Done(&b""[..],
Expression::Div(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))));
Expression::Binary(BinaryExpression{
kind: BinaryExprType::Div,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})));
assert_eq!(expression(&b"macro (arg1, arg2) => { foo = arg1 }"[..]),
IResult::Done(&b""[..],
Expression::Macro(MacroDef{
@ -693,9 +709,12 @@ mod test {
IResult::Done(&b""[..],
Expression::Grouped(
Box::new(
Expression::Add(
BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1)))))
Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
}
)
)
)
@ -851,10 +870,13 @@ mod test {
IResult::Done(&b""[..],
Expression::Grouped(
Box::new(
Expression::Add(
BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(
Value::Int(make_value_node(1)))))
Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(
Value::Int(make_value_node(1)))),
}
)
)
)
@ -963,8 +985,12 @@ mod test {
value: Expression::Simple(Value::Int(make_value_node(1)))
},
Statement::Expression(
Expression::Add(BinaryExpression(Value::Int(make_value_node(1)),
Box::new(Expression::Simple(Value::Int(make_value_node(1))))))
Expression::Binary(
BinaryExpression{
kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))),
})
)
]);
}