Object field order matters!

This commit is contained in:
Mark 2023-11-30 17:48:24 +01:00
parent 3d1ce384d0
commit 48c1381194
2 changed files with 74 additions and 56 deletions

View File

@ -28,14 +28,8 @@ pub fn assign(from: &Data, target: &Data) {
.as_any() .as_any()
.downcast_ref::<crate::data::object::Object>(), .downcast_ref::<crate::data::object::Object>(),
) { ) {
for (field, target) in target.0.iter() { for ((_, from), (_, target)) in from.0.iter().zip(target.0.iter()) {
for (name, from) in from.0.iter() { assign(from, target);
// TODO: do string comparison at compile-time instead!
if field == name {
assign(from, target);
break;
}
}
} }
} else { } else {
unreachable!("invalid assignment") unreachable!("invalid assignment")

View File

@ -21,57 +21,81 @@ impl MersStatement for Object {
init_to: Option<&Type>, init_to: Option<&Type>,
) -> Result<data::Type, super::CheckError> { ) -> Result<data::Type, super::CheckError> {
let mut assign_types = if let Some(init_to) = init_to { let mut assign_types = if let Some(init_to) = init_to {
let mut acc = (0..self.elems.len())
.map(|_| Type::empty())
.collect::<VecDeque<_>>();
let print_is_part_of = init_to.types.len() > 1; let print_is_part_of = init_to.types.len() > 1;
Some( for t in init_to.types.iter() {
self.elems if let Some(t) = t.as_any().downcast_ref::<ObjectT>() {
.iter() if self.elems.len() == t.0.len() {
.map(|(field, _)| -> Result<_, CheckError> { for (i, ((sn, _), (tn, t))) in self.elems.iter().zip(t.0.iter()).enumerate()
let mut acc = Type::empty(); {
for t in init_to.types.iter() { if sn != tn {
if let Some(t) = t.as_any().downcast_ref::<ObjectT>() { return Err(format!("can't init an {} with type {}{} - field mismatch: {sn} != {tn}", "object".color(error_colors::InitTo),
let mut found = false; t.to_string().color(error_colors::InitFrom),
for (name, assign_to) in t.0.iter() { if print_is_part_of {
if name == field { format!(
acc.add(Arc::new(assign_to.clone())); ", which is part of {}",
found = true; init_to.to_string().color(error_colors::InitFrom)
break; )
} } else {
} format!("")
if !found { }
return Err(format!( ).into());
"can't init an {} with type {}{} - field {field} not found",
"object".color(error_colors::InitTo),
t.to_string().color(error_colors::InitFrom),
if print_is_part_of {
format!(
", which is part of {}",
init_to.to_string().color(error_colors::InitFrom)
)
} else {
format!("")
}
).into());
}
} else {
return Err(format!(
"can't init an {} with type {}{} - only objects can be assigned to objects",
"object".color(error_colors::InitTo),
t.to_string().color(error_colors::InitFrom),
if print_is_part_of {
format!(
", which is part of {}",
init_to.to_string().color(error_colors::InitFrom)
)
} else {
format!("")
}
).into());
} }
acc[i].add(Arc::new(t.clone()));
} }
Ok(acc) } else {
}) return Err(format!(
.collect::<Result<VecDeque<Type>, CheckError>>()?, "can't init an {} with type {}{} - source has {}",
) "object".color(error_colors::InitTo),
t.to_string().color(error_colors::InitFrom),
if print_is_part_of {
format!(
", which is part of {}",
init_to.to_string().color(error_colors::InitFrom)
)
} else {
format!("")
},
if self.elems.len() > t.0.len() {
format!("less fields ({}, not {})", t.0.len(), self.elems.len())
} else {
format!(
"more fields. Either ignore those fields (`{}`) - or remove them from the type (`... := [{}] ...`)",
t.0.iter()
.skip(self.elems.len())
.enumerate()
.map(|(i, (n, _))| if i == 0 {
format!("{n}: _")
} else {
format!(", {n}: _")
})
.collect::<String>(),
data::object::ObjectT(t.0.iter().take(self.elems.len()).cloned().collect())
)
}
)
.into());
}
} else {
return Err(format!(
"can't init an {} with type {}{} - only objects can be assigned to objects",
"object".color(error_colors::InitTo),
t.to_string().color(error_colors::InitFrom),
if print_is_part_of {
format!(
", which is part of {}",
init_to.to_string().color(error_colors::InitFrom)
)
} else {
format!("")
}
)
.into());
}
}
Some(acc)
} else { } else {
None None
}; };