Refactor the Copy expression to use a CopyDef struct.

This commit is contained in:
Jeremy Wall 2017-09-20 19:40:19 -05:00
parent b3677861c6
commit 42fe368dae
3 changed files with 28 additions and 21 deletions

View File

@ -204,7 +204,8 @@ impl MacroDef {
stack.push(expr); stack.push(expr);
} }
}, },
&Expression::Copy(_, ref fields) => { &Expression::Copy(ref def) => {
let fields = &def.fields;
for &(_, ref expr) in fields.iter() { for &(_, ref expr) in fields.iter() {
stack.push(expr); stack.push(expr);
} }
@ -236,6 +237,12 @@ impl MacroDef {
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
pub struct BinaryExpression(pub Value, pub Box<Expression>); pub struct BinaryExpression(pub Value, pub Box<Expression>);
#[derive(Debug,PartialEq,Clone)]
pub struct CopyDef {
pub selector: SelectorList,
pub fields: FieldList
}
/// Expression encodes an expression. Expressions compute a value from operands. /// Expression encodes an expression. Expressions compute a value from operands.
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
pub enum Expression { pub enum Expression {
@ -250,7 +257,7 @@ pub enum Expression {
Div(BinaryExpression), Div(BinaryExpression),
// Complex Expressions // Complex Expressions
Copy(SelectorList, FieldList), Copy(CopyDef),
Grouped(Box<Expression>), Grouped(Box<Expression>),
Format(String, Vec<Expression>), Format(String, Vec<Expression>),

View File

@ -496,8 +496,8 @@ impl Builder {
} }
} }
}, },
Expression::Copy(sel, mut fields) => { Expression::Copy(mut def) => {
let v = try!(self.lookup_selector(sel)); let v = try!(self.lookup_selector(def.selector));
if let Val::Tuple(ref src_fields) = *v { if let Val::Tuple(ref src_fields) = *v {
let mut m = HashMap::<String, Rc<Val>>::new(); let mut m = HashMap::<String, Rc<Val>>::new();
// loop through fields and build up a hasmap // loop through fields and build up a hasmap
@ -510,7 +510,7 @@ impl Builder {
format!("Duplicate field: {} in tuple", *key)))); format!("Duplicate field: {} in tuple", *key))));
} }
} }
for (key, val) in fields.drain(0..) { for (key, val) in def.fields.drain(0..) {
let expr_result = try!(self.eval_expr(val)); let expr_result = try!(self.eval_expr(val));
match m.entry(key.clone()) { match m.entry(key.clone()) {
Entry::Vacant(v) => { Entry::Vacant(v) => {
@ -793,7 +793,7 @@ mod test {
fn test_expr_copy_no_such_tuple() { fn test_expr_copy_no_such_tuple() {
let b = Builder::new(); let b = Builder::new();
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy(vec!["tpl1".to_string()], Vec::new()), (Expression::Copy(CopyDef{selector: vec!["tpl1".to_string()], fields: Vec::new()}),
Val::Tuple(Vec::new())), Val::Tuple(Vec::new())),
], b); ], b);
} }
@ -804,7 +804,7 @@ mod test {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Int(1))); b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Int(1)));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy(vec!["tpl1".to_string()], Vec::new()), (Expression::Copy(CopyDef{selector: vec!["tpl1".to_string()], fields: Vec::new()}),
Val::Tuple(Vec::new())), Val::Tuple(Vec::new())),
], b); ], b);
} }
@ -817,9 +817,9 @@ mod test {
("fld1".to_string(), Rc::new(Val::Int(1))), ("fld1".to_string(), Rc::new(Val::Int(1))),
]))); ])));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy(vec!["tpl1".to_string()], (Expression::Copy(CopyDef{selector: vec!["tpl1".to_string()],
vec![("fld1".to_string(), fields: vec![("fld1".to_string(),
Expression::Simple(Value::String(make_value_node("2".to_string()))))]), Expression::Simple(Value::String(make_value_node("2".to_string()))))]}),
Val::Tuple( Val::Tuple(
vec![ vec![
("fld1".to_string(), Rc::new(Val::String("2".to_string()))), ("fld1".to_string(), Rc::new(Val::String("2".to_string()))),
@ -838,9 +838,9 @@ mod test {
("fld1".to_string(), Rc::new(Val::Int(1))), ("fld1".to_string(), Rc::new(Val::Int(1))),
]))); ])));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy(vec!["tpl1".to_string()], (Expression::Copy(CopyDef{selector: vec!["tpl1".to_string()],
vec![("fld2".to_string(), fields: vec![("fld2".to_string(),
Expression::Simple(Value::String(make_value_node("2".to_string()))))]), Expression::Simple(Value::String(make_value_node("2".to_string()))))]}),
// Add a new field to the copy // Add a new field to the copy
Val::Tuple( Val::Tuple(
// NOTE(jwall): The order of these is important in order to ensure // NOTE(jwall): The order of these is important in order to ensure
@ -852,13 +852,13 @@ mod test {
], ],
)), )),
// Overwrite a field in the copy // Overwrite a field in the copy
(Expression::Copy(vec!["tpl1".to_string()], (Expression::Copy(CopyDef{selector: vec!["tpl1".to_string()],
vec![ fields: vec![
("fld1".to_string(), ("fld1".to_string(),
Expression::Simple(Value::Int(make_value_node(3)))), Expression::Simple(Value::Int(make_value_node(3)))),
("fld2".to_string(), ("fld2".to_string(),
Expression::Simple(Value::String(make_value_node("2".to_string())))), Expression::Simple(Value::String(make_value_node("2".to_string())))),
]), ]}),
Val::Tuple( Val::Tuple(
vec![ vec![
("fld1".to_string(), Rc::new(Val::Int(3))), ("fld1".to_string(), Rc::new(Val::Int(3))),

View File

@ -277,7 +277,7 @@ named!(grouped_expression<Expression>,
named!(selector_list<SelectorList>, separated_nonempty_list!(dot, field)); named!(selector_list<SelectorList>, separated_nonempty_list!(dot, field));
fn tuple_to_copy(t: (SelectorList, FieldList)) -> ParseResult<Expression> { fn tuple_to_copy(t: (SelectorList, FieldList)) -> ParseResult<Expression> {
Ok(Expression::Copy(t.0, t.1)) Ok(Expression::Copy(CopyDef{selector: t.0, fields: t.1}))
} }
named!(copy_expression<Expression>, named!(copy_expression<Expression>,
@ -824,14 +824,14 @@ mod test {
assert!(copy_expression(&b"foo{"[..]).is_incomplete() ); assert!(copy_expression(&b"foo{"[..]).is_incomplete() );
assert_eq!(copy_expression(&b"foo{}"[..]), assert_eq!(copy_expression(&b"foo{}"[..]),
IResult::Done(&b""[..], IResult::Done(&b""[..],
Expression::Copy(vec!["foo".to_string()], Expression::Copy(CopyDef{selector: vec!["foo".to_string()],
Vec::new()) fields: Vec::new()})
) )
); );
assert_eq!(copy_expression(&b"foo{bar=1}"[..]), assert_eq!(copy_expression(&b"foo{bar=1}"[..]),
IResult::Done(&b""[..], IResult::Done(&b""[..],
Expression::Copy(vec!["foo".to_string()], Expression::Copy(CopyDef{selector: vec!["foo".to_string()],
vec![("bar".to_string(), Expression::Simple(Value::Int(make_value_node(1))))]) fields: vec![("bar".to_string(), Expression::Simple(Value::Int(make_value_node(1))))]})
) )
); );
} }