Implement bounded typed data and identified interface contracts

This commit is contained in:
2026-09-06 03:44:09 +03:00
parent 1230ab8a3e
commit 0b58107097
15 changed files with 3127 additions and 177 deletions
+43 -10
View File
@@ -33,8 +33,13 @@ pub fn visit_element_refs(e: &mut Element, mut visit: impl FnMut(&mut Id)) {
type_ref: TypeRef::Named(id),
..
} => visit(id),
SharedBody::Interface { items } => {
for id in items {
SharedBody::Interface { supertype }
| SharedBody::ExchangeItem { supertype, .. }
| SharedBody::DataType {
definition: DataTypeDefinition::Record { supertype },
..
} => {
if let Some(id) = supertype {
visit(id);
}
}
@@ -83,6 +88,9 @@ pub fn visit_element_refs(e: &mut Element, mut visit: impl FnMut(&mut Id)) {
visit(id);
}
for value in values {
for id in &mut value.path {
visit(id);
}
visit(&mut value.field);
}
}
@@ -377,7 +385,12 @@ fn remove_objects(p: &mut Project, removed: BTreeSet<Id>) {
}
if let Some(shared) = e.shared_mut() {
match shared {
SharedBody::Interface { items } => items.retain(|id| !removed.contains(id)),
SharedBody::Interface { supertype }
| SharedBody::ExchangeItem { supertype, .. }
| SharedBody::DataType {
definition: DataTypeDefinition::Record { supertype },
..
} => clear(supertype),
SharedBody::Event {
body: EventBody::Signal { items },
} => items.retain(|id| !removed.contains(id)),
@@ -413,7 +426,10 @@ fn remove_objects(p: &mut Project, removed: BTreeSet<Id>) {
clear(sender);
clear(receiver);
clear(reply_to);
values.retain(|value| !removed.contains(&value.field));
values.retain(|value| {
!removed.contains(&value.field)
&& value.path.iter().all(|id| !removed.contains(id))
});
}
OccurrenceBody::Action { action, lifeline } => {
clear(action);
@@ -485,20 +501,37 @@ fn remove_objects(p: &mut Project, removed: BTreeSet<Id>) {
exchange: Some(id), ..
},
..
}) => p
.relations
.get(id)
.map(|r| (e.id, crate::validation::carried_fields(p, r))),
}) => p.relations.get(id).map(|r| {
let Some(SharedBody::Occurrence {
body: OccurrenceBody::Exchange { values, .. },
..
}) = e.shared()
else {
unreachable!()
};
let retained: Vec<_> = values
.iter()
.filter(|value| {
crate::data::carried_value_path(p, r, &value.path, value.field).is_some()
|| (value.path.is_empty()
&& crate::data::carried_field_paths(p, r)
.iter()
.any(|f| f.field == value.field))
})
.cloned()
.collect();
(e.id, retained)
}),
_ => None,
})
.collect();
for (id, fields) in allowed {
for (id, retained) in allowed {
if let Some(SharedBody::Occurrence {
body: OccurrenceBody::Exchange { values, .. },
..
}) = p.elements.get_mut(&id).and_then(Element::shared_mut)
{
values.retain(|value| fields.contains(&value.field));
*values = retained;
}
}
}