Checkpoint source 7 workflows and in-progress diagram authoring redesign
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s
Preserve current core, source, REST, desktop, recovery, documentation and validation work, including AGENTS.md and the development summary. This is a work-in-progress checkpoint: the new compact palette has outstanding compilation errors and native acceptance; earlier passing gates retain their documented scope.
This commit is contained in:
@@ -1,6 +1,109 @@
|
||||
//! One address for a carried value, shared by scenario creation and property editing.
|
||||
use oa_core::*;
|
||||
|
||||
fn resolve_operation(
|
||||
project: &Project,
|
||||
message: &Element,
|
||||
) -> Result<operations::OperationResolution, operations::OperationError> {
|
||||
if project.elements.get(&message.id) == Some(message) {
|
||||
return operations::resolve(project, message.id);
|
||||
}
|
||||
let active = matches!(
|
||||
message.shared(),
|
||||
Some(SharedBody::Occurrence {
|
||||
body: OccurrenceBody::Exchange {
|
||||
operation: Some(_),
|
||||
..
|
||||
},
|
||||
..
|
||||
})
|
||||
) || matches!(message.shared(),Some(SharedBody::Occurrence { body:OccurrenceBody::Exchange { message_kind:MessageKind::Reply,reply_to:Some(call),..},.. }) if matches!(project.elements.get(call).and_then(|e|e.shared()),Some(SharedBody::Occurrence {body:OccurrenceBody::Exchange {operation:Some(_),..},..})));
|
||||
if !active {
|
||||
return Ok(operations::OperationResolution::Ordinary);
|
||||
}
|
||||
let mut candidate = project.clone();
|
||||
candidate.elements.insert(message.id, message.clone());
|
||||
operations::resolve(&candidate, message.id)
|
||||
}
|
||||
|
||||
/// The same exact signature used by core admission, evaluated with the authored
|
||||
/// message in place. Unresolved operation intent never falls back to channel union.
|
||||
pub(crate) fn message_signature(
|
||||
project: &Project,
|
||||
message: &Element,
|
||||
) -> Result<Option<Relation>, String> {
|
||||
match resolve_operation(project, message).map_err(|e| e.to_string())? {
|
||||
operations::OperationResolution::Selected(operation) => {
|
||||
Ok(Some(operations::signature_relation(&operation)))
|
||||
}
|
||||
operations::OperationResolution::Unresolved { reason, .. } => Err(reason),
|
||||
operations::OperationResolution::Ordinary => Ok(match message.shared() {
|
||||
Some(SharedBody::Occurrence {
|
||||
body: OccurrenceBody::Exchange { exchange, .. },
|
||||
..
|
||||
}) => exchange.and_then(|id| project.relations.get(&id)).cloned(),
|
||||
_ => None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn operation_choices(project: &Project, message: &Element) -> Vec<crate::app::Choice> {
|
||||
let mut candidate = project.clone();
|
||||
candidate.elements.insert(message.id, message.clone());
|
||||
let mut choices: Vec<_> = operations::eligible_allocations(&candidate, message.id)
|
||||
.into_iter()
|
||||
.map(|id| crate::app::Choice {
|
||||
id,
|
||||
label: operation_identity(project, id),
|
||||
})
|
||||
.collect();
|
||||
choices.sort_by(|a, b| a.label.cmp(&b.label).then(a.id.cmp(&b.id)));
|
||||
choices
|
||||
}
|
||||
|
||||
pub(crate) fn operation_identity(project: &Project, allocation: Id) -> String {
|
||||
if let Some(r) = project.relations.get(&allocation) {
|
||||
format!(
|
||||
"{} / {} · {} (@{})",
|
||||
project.named(r.source()),
|
||||
project.named(r.target()),
|
||||
r.name,
|
||||
r.alias
|
||||
)
|
||||
} else {
|
||||
format!("Unavailable operation allocation · {allocation}")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn operation_label(project: &Project, message: &Element) -> Option<String> {
|
||||
let reply = matches!(
|
||||
message.shared(),
|
||||
Some(SharedBody::Occurrence {
|
||||
body: OccurrenceBody::Exchange {
|
||||
message_kind: MessageKind::Reply,
|
||||
..
|
||||
},
|
||||
..
|
||||
})
|
||||
);
|
||||
let prefix = if reply {
|
||||
"Reply operation from Call"
|
||||
} else {
|
||||
"Operation"
|
||||
};
|
||||
match resolve_operation(project, message) {
|
||||
Ok(operations::OperationResolution::Ordinary) => None,
|
||||
Ok(operations::OperationResolution::Unresolved { reason, .. }) => {
|
||||
Some(format!("{prefix}: unresolved · {reason}"))
|
||||
}
|
||||
Ok(operations::OperationResolution::Selected(operation)) => Some(format!(
|
||||
"{prefix}: {}",
|
||||
operation_identity(project, operation.allocation)
|
||||
)),
|
||||
Err(error) => Some(format!("{prefix}: {error}")),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct FieldPathKey {
|
||||
pub path: Vec<Id>,
|
||||
@@ -38,6 +141,18 @@ fn phase_allows(project: &Project, entry: &data::CarriedFieldPath, phase: &Messa
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
/// Selected asynchronous operations carry request parameters. Ordinary channel
|
||||
/// messages retain their existing phase rules; unresolved intent has no signature.
|
||||
pub(crate) fn operation_value_phase(
|
||||
kind: &MessageKind,
|
||||
operation: Option<&OperationUse>,
|
||||
) -> MessageKind {
|
||||
if *kind == MessageKind::Asynchronous && operation.is_some() {
|
||||
MessageKind::Call
|
||||
} else {
|
||||
kind.clone()
|
||||
}
|
||||
}
|
||||
fn named_choice(project: &Project, entry: data::CarriedFieldPath) -> FieldPathChoice {
|
||||
let qualified = entry
|
||||
.path
|
||||
|
||||
Reference in New Issue
Block a user