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);
}
},
&Expression::Copy(_, ref fields) => {
&Expression::Copy(ref def) => {
let fields = &def.fields;
for &(_, ref expr) in fields.iter() {
stack.push(expr);
}
@ -236,6 +237,12 @@ impl MacroDef {
#[derive(Debug,PartialEq,Clone)]
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.
#[derive(Debug,PartialEq,Clone)]
pub enum Expression {
@ -250,7 +257,7 @@ pub enum Expression {
Div(BinaryExpression),
// Complex Expressions
Copy(SelectorList, FieldList),
Copy(CopyDef),
Grouped(Box<Expression>),
Format(String, Vec<Expression>),

View File

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