Model typed SA ports and atomic exchange allocation workflows

This commit is contained in:
2026-09-05 18:22:00 +03:00
parent c20a2073d7
commit 0d14438b7b
13 changed files with 2402 additions and 256 deletions
+53 -10
View File
@@ -334,11 +334,29 @@ fn items_ports_interfaces_and_exchange_allocation_are_typed() {
.shared_mut()
.unwrap() = SharedBody::Interface { items: vec![item] };
let port = |p: &mut Project, name: &str, parent, direction| {
let id = add(p, Kind::Port, Layer::Sa, name, Some(parent));
*p.elements.get_mut(&id).unwrap().shared_mut().unwrap() = SharedBody::Port {
direction,
interface: Some(interface),
let id = Id::new_v4();
let contract = if p.elements[&parent].kind() == Kind::Function {
if direction == PortDirection::Out {
PortContract::FunctionOutput {
outgoing_items: vec![item],
}
} else {
PortContract::FunctionInput {
incoming_items: vec![item],
}
}
} else {
PortContract::Component {
kind: ComponentPortKind::Flow,
orientation: if direction == PortDirection::Out {
ComponentPortOrientation::Out
} else {
ComponentPortOrientation::In
},
}
};
p.elements
.insert(id, make_port(p, id, parent, name, contract).unwrap());
id
};
let out = port(&mut p, "System output", system, PortDirection::Out);
@@ -355,10 +373,14 @@ fn items_ports_interfaces_and_exchange_allocation_are_typed() {
p.relations.get_mut(&exchange).unwrap().body = RelationBody::FunctionalExchange {
source: f1,
target: f2,
source_port: Some(fp1),
target_port: Some(fp2),
source_port: fp1,
target_port: fp2,
items: vec![item],
};
p.relate(RelationKind::Allocation, "Send allocation", system, f1);
p.relate(RelationKind::Allocation, "Receive allocation", actor, f2);
p.relate(RelationKind::PortAllocation, "Output allocation", out, fp1);
p.relate(RelationKind::PortAllocation, "Input allocation", input, fp2);
p.relate(
RelationKind::ExchangeAllocation,
"Carried on",
@@ -381,7 +403,7 @@ fn items_ports_interfaces_and_exchange_allocation_are_typed() {
if let RelationBody::FunctionalExchange { source_port, .. } =
&mut p.relations.get_mut(&exchange).unwrap().body
{
*source_port = Some(input);
*source_port = input;
}
rejected(&p, "functional_port");
}
@@ -721,15 +743,36 @@ fn reidentifying_data_types_and_function_ports_updates_every_typed_reference() {
};
let function = add(&mut p, Kind::Function, Layer::Sa, "Function", None);
let other = add(&mut p, Kind::Function, Layer::Sa, "Other", None);
let port = add(&mut p, Kind::Port, Layer::Sa, "Output", Some(function));
let port = Id::new_v4();
p.elements.insert(
port,
make_port(
&p,
port,
function,
"Output",
PortContract::FunctionOutput {
outgoing_items: vec![item],
},
)
.unwrap(),
);
let rel = p.relate(RelationKind::FunctionalExchange, "Data", function, other);
if let RelationBody::FunctionalExchange {
source_port, items, ..
} = &mut p.relations.get_mut(&rel).unwrap().body
{
*source_port = Some(port);
*source_port = port;
items.push(item);
}
if let RelationBody::FunctionalExchange { target_port, .. } = p.relations[&rel].body
&& let Some(SharedBody::Port {
contract: PortContract::FunctionInput { incoming_items },
..
}) = p.elements.get_mut(&target_port).unwrap().shared_mut()
{
incoming_items.push(item);
}
let dtype_new = Id::new_v4();
let port_new = Id::new_v4();
let result = execute_batch(
@@ -744,7 +787,7 @@ fn reidentifying_data_types_and_function_ports_updates_every_typed_reference() {
matches!(result.elements[&field].shared(),Some(SharedBody::DataField{type_ref:TypeRef::Named(id),..})if *id==dtype_new)
);
assert!(
matches!(&result.relations[&rel].body,RelationBody::FunctionalExchange{source_port:Some(id),..}if *id==port_new)
matches!(&result.relations[&rel].body,RelationBody::FunctionalExchange{source_port:id,..}if *id==port_new)
);
}