From f95ecddea2d1a75b0bfe08b48529c69121fee360 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Thu, 21 Sep 2017 00:06:43 -0500 Subject: [PATCH] Refactored Binary Expressions to a common type and cleaned it up --- src/ast.rs | 70 +++++++------- src/build.rs | 256 ++++++++++++++++++++++++++++++--------------------- src/parse.rs | 120 ++++++++++++++---------- 3 files changed, 259 insertions(+), 187 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index e784ea9..71c0ab9 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -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); +pub struct BinaryExpression { + pub kind: BinaryExprType, + pub left: Value, + pub right: Box +} #[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(); diff --git a/src/build.rs b/src/build.rs index 1327966..c1172f0 100644 --- a/src/build.rs +++ b/src/build.rs @@ -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); } diff --git a/src/parse.rs b/src/parse.rs index 0bc0977..f1ef257 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -199,8 +199,12 @@ named!(simple_expression, ) ); -fn tuple_to_add_expression(tpl: (Value, Expression)) -> ParseResult { - Ok(Expression::Add(BinaryExpression(tpl.0, Box::new(tpl.1)))) +fn tuple_to_binary_expression(tpl: (BinaryExprType, Value, Expression)) -> ParseResult { + Ok(Expression::Binary(BinaryExpression{ + kind: tpl.0, + left: tpl.1, + right: Box::new(tpl.2), + })) } named!(add_expression, @@ -209,57 +213,45 @@ named!(add_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 { - Ok(Expression::Sub(BinaryExpression(tpl.0, Box::new(tpl.1)))) -} - named!(sub_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 { - Ok(Expression::Mul(BinaryExpression(tpl.0, Box::new(tpl.1)))) -} - named!(mul_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 { - Ok(Expression::Div(BinaryExpression(tpl.0, Box::new(tpl.1)))) -} - named!(div_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)))), + }) ) ]); }