Model typed SA ports and atomic exchange allocation workflows
This commit is contained in:
@@ -45,10 +45,20 @@ pub fn visit_element_refs(e: &mut Element, mut visit: impl FnMut(&mut Id)) {
|
||||
visit(id);
|
||||
}
|
||||
}
|
||||
SharedBody::Port {
|
||||
interface: Some(id),
|
||||
..
|
||||
} => visit(id),
|
||||
SharedBody::Port { contract, legacy } => {
|
||||
match contract {
|
||||
PortContract::FunctionInput { incoming_items } => {
|
||||
incoming_items.iter_mut().for_each(&mut visit)
|
||||
}
|
||||
PortContract::FunctionOutput { outgoing_items } => {
|
||||
outgoing_items.iter_mut().for_each(&mut visit)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(id) = legacy.as_mut().and_then(|old| old.interface.as_mut()) {
|
||||
visit(id);
|
||||
}
|
||||
}
|
||||
SharedBody::Scenario { context, steps, .. } => {
|
||||
if let Some(id) = context {
|
||||
visit(id);
|
||||
@@ -145,7 +155,7 @@ pub fn visit_relation_refs(r: &mut Relation, mut visit: impl FnMut(&mut Id)) {
|
||||
items,
|
||||
..
|
||||
} => {
|
||||
for id in [source_port, target_port].into_iter().flatten() {
|
||||
for id in [source_port, target_port] {
|
||||
visit(id);
|
||||
}
|
||||
for id in items {
|
||||
@@ -207,7 +217,49 @@ pub fn deletion_impact(p: &Project, id: Id) -> BTreeSet<Id> {
|
||||
}
|
||||
}
|
||||
for r in p.relations.values() {
|
||||
if removed.contains(&r.source()) || removed.contains(&r.target()) {
|
||||
let port_removed = matches!(&r.body, RelationBody::FunctionalExchange { source_port, target_port, .. } if removed.contains(source_port) || removed.contains(target_port));
|
||||
let work_allocation_removed = r.kind() == RelationKind::PortAllocation
|
||||
&& p.relations.values().any(|allocation| {
|
||||
allocation.kind() == RelationKind::Allocation
|
||||
&& removed.contains(&allocation.id)
|
||||
&& p.elements.get(&r.source()).and_then(|e| e.parent)
|
||||
== Some(allocation.source())
|
||||
&& p.elements.get(&r.target()).and_then(|e| e.parent)
|
||||
== Some(allocation.target())
|
||||
});
|
||||
if removed.contains(&r.source())
|
||||
|| removed.contains(&r.target())
|
||||
|| port_removed
|
||||
|| work_allocation_removed
|
||||
{
|
||||
removed.insert(r.id);
|
||||
}
|
||||
}
|
||||
// Exchange allocation depends on both explicit endpoint allocations.
|
||||
for r in p
|
||||
.relations
|
||||
.values()
|
||||
.filter(|r| r.kind() == RelationKind::ExchangeAllocation)
|
||||
{
|
||||
let (Some(boundary), Some(work)) =
|
||||
(p.relations.get(&r.source()), p.relations.get(&r.target()))
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let RelationBody::FunctionalExchange {
|
||||
source_port,
|
||||
target_port,
|
||||
..
|
||||
} = &work.body
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if p.relations.values().any(|allocation| {
|
||||
allocation.kind() == RelationKind::PortAllocation
|
||||
&& removed.contains(&allocation.id)
|
||||
&& [boundary.source(), boundary.target()].contains(&allocation.source())
|
||||
&& [*source_port, *target_port].contains(&allocation.target())
|
||||
}) {
|
||||
removed.insert(r.id);
|
||||
}
|
||||
}
|
||||
@@ -263,7 +315,20 @@ pub fn delete_cascade(p: &mut Project, id: Id) {
|
||||
SharedBody::Event {
|
||||
body: EventBody::Signal { items },
|
||||
} => items.retain(|id| !removed.contains(id)),
|
||||
SharedBody::Port { interface, .. } => clear(interface),
|
||||
SharedBody::Port { contract, legacy } => {
|
||||
match contract {
|
||||
PortContract::FunctionInput { incoming_items } => {
|
||||
incoming_items.retain(|id| !removed.contains(id))
|
||||
}
|
||||
PortContract::FunctionOutput { outgoing_items } => {
|
||||
outgoing_items.retain(|id| !removed.contains(id))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(old) = legacy {
|
||||
clear(&mut old.interface);
|
||||
}
|
||||
}
|
||||
SharedBody::Scenario { context, .. } => clear(context),
|
||||
SharedBody::Lifeline { represented } => clear(represented),
|
||||
SharedBody::Constraint { constrained, .. } => {
|
||||
@@ -336,15 +401,8 @@ pub fn delete_cascade(p: &mut Project, id: Id) {
|
||||
| RelationBody::BoundaryExchange { items, .. } => {
|
||||
items.retain(|id| !removed.contains(id))
|
||||
}
|
||||
RelationBody::FunctionalExchange {
|
||||
items,
|
||||
source_port,
|
||||
target_port,
|
||||
..
|
||||
} => {
|
||||
RelationBody::FunctionalExchange { items, .. } => {
|
||||
items.retain(|id| !removed.contains(id));
|
||||
clear(source_port);
|
||||
clear(target_port);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user