Maintain tuple field order both while copying and not.

This commit is contained in:
Jeremy Wall 2018-02-05 08:43:10 -06:00
parent 5fba06d71f
commit a8a320fe91

View File

@ -208,13 +208,13 @@ macro_rules! eval_binary_expr {
} }
impl Builder { impl Builder {
// TODO(jwall): Maintain order for tuples.
fn tuple_to_val(&self, fields: &Vec<(Token, Expression)>) -> Result<Rc<Val>, Box<Error>> { fn tuple_to_val(&self, fields: &Vec<(Token, Expression)>) -> Result<Rc<Val>, Box<Error>> {
let mut new_fields = Vec::<(Positioned<String>, Rc<Val>)>::new(); let mut new_fields = Vec::<(Positioned<String>, Rc<Val>)>::new();
for &(ref name, ref expr) in fields.iter() { for &(ref name, ref expr) in fields.iter() {
let val = try!(self.eval_expr(expr)); let val = try!(self.eval_expr(expr));
new_fields.push((name.into(), val)); new_fields.push((name.into(), val));
} }
new_fields.sort_by(|a, b| a.0.cmp(&b.0));
Ok(Rc::new(Val::Tuple(new_fields))) Ok(Rc::new(Val::Tuple(new_fields)))
} }
@ -636,47 +636,57 @@ impl Builder {
fn eval_copy(&self, def: &CopyDef) -> Result<Rc<Val>, Box<Error>> { fn eval_copy(&self, def: &CopyDef) -> Result<Rc<Val>, Box<Error>> {
let v = try!(self.lookup_selector(&def.selector.sel)); let v = try!(self.lookup_selector(&def.selector.sel));
if let Val::Tuple(ref src_fields) = *v { if let Val::Tuple(ref src_fields) = *v {
let mut m = HashMap::<Positioned<String>, Rc<Val>>::new(); let mut m = HashMap::<Positioned<String>, (i32, Rc<Val>)>::new();
// loop through fields and build up a hahsmap // loop through fields and build up a hashmap
// TODO(jwall): Maintain field order here.
let mut count = 0;
for &(ref key, ref val) in src_fields.iter() { for &(ref key, ref val) in src_fields.iter() {
if let Entry::Vacant(v) = m.entry(key.clone()) { if let Entry::Vacant(v) = m.entry(key.clone()) {
v.insert(val.clone()); v.insert((count, val.clone()));
count += 1;
} else { } else {
return Err(Box::new(error::Error::new(format!("Duplicate \ return Err(Box::new(error::Error::new(format!("Duplicate \
field: {} in \ field: {} in \
tuple", tuple",
key.val), key.val),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.pos.clone()))); key.pos.clone())));
} }
} }
for &(ref key, ref val) in def.fields.iter() { for &(ref key, ref val) in def.fields.iter() {
let expr_result = try!(self.eval_expr(val)); let expr_result = try!(self.eval_expr(val));
match m.entry(key.into()) { // TODO(jwall): Maintain field order here.
match m.entry(key.into()) { // brand new field here.
Entry::Vacant(v) => { Entry::Vacant(v) => {
v.insert(expr_result); v.insert((count, expr_result));
count += 1;
} }
Entry::Occupied(mut v) => { Entry::Occupied(mut v) => { // overriding field here.
// Ensure that the new type matches the old type. // Ensure that the new type matches the old type.
let src_val = v.get().clone(); let src_val = v.get().clone();
if src_val.type_equal(&expr_result) { if src_val.1.type_equal(&expr_result) {
v.insert(expr_result); v.insert((src_val.0, expr_result));
} else { } else {
return Err(Box::new( return Err(Box::new(
error::Error::new( error::Error::new(
format!("Expected type {} for field {} but got {}", format!("Expected type {} for field {} but got {}",
src_val.type_name(), key.fragment, expr_result.type_name()), src_val.1.type_name(), key.fragment, expr_result.type_name()),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
key.pos.clone()))); key.pos.clone())));
} }
} }
}; };
} }
let mut new_fields: Vec<(Positioned<String>, Rc<Val>)> = m.drain().collect(); let mut new_fields: Vec<(Positioned<String>, (i32, Rc<Val>))> = m.drain().collect();
// We want a stable order for the fields to make comparing tuples // We want to maintain our order for the fields to make comparing tuples
// easier in later code. So we sort by the field name before constructing a new tuple. // easier in later code. So we sort by the field order before constructing a new tuple.
new_fields.sort_by(|a, b| a.0.cmp(&b.0)); new_fields.sort_by(|a, b| {
return Ok(Rc::new(Val::Tuple(new_fields))); let ta = a.1.clone(); let tb = b.1.clone(); ta.0.cmp(&tb.0)
});
return Ok(Rc::new(Val::Tuple(new_fields.iter().map(|a| {
let first = a.0.clone(); let t = a.1.clone();
(first, t.1)
}).collect())));
} }
Err(Box::new(error::Error::new(format!("Expected Tuple got {}", v), Err(Box::new(error::Error::new(format!("Expected Tuple got {}", v),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,