2025-09-11 02:49:14 +02:00
|
|
|
use std::collections::HashMap;
|
2025-08-24 03:35:32 +02:00
|
|
|
|
2025-09-12 16:34:58 +02:00
|
|
|
use rsprocess::translator::PrintableWithTranslator;
|
2025-09-17 00:34:18 +02:00
|
|
|
use rsprocess::{graph, label, set, system, translator};
|
2025-10-20 17:04:00 +02:00
|
|
|
use serde::{Deserialize, Serialize};
|
2025-09-17 00:34:18 +02:00
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
use super::{dsl, positivedsl};
|
2025-08-17 03:19:50 +02:00
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
// -----------------------------------------------------------------------------
|
2025-08-17 03:19:50 +02:00
|
|
|
// Specific Assert Implementation
|
2025-10-27 21:12:43 +01:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
// System
|
2025-08-17 03:19:50 +02:00
|
|
|
|
2025-09-10 22:41:40 +02:00
|
|
|
/// Module that has all types and structures for bisimilarity relabeler.
|
2025-08-18 20:39:43 +02:00
|
|
|
pub mod useful_types_edge_relabeler {
|
|
|
|
|
macro_rules! export_types {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::dsl::$x<super::EdgeRelablerInput>;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! export_types_no_parameter {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::dsl::$x;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-24 03:35:32 +02:00
|
|
|
export_types!(Assert, Tree, Variable, Expression, Range);
|
2025-08-18 20:39:43 +02:00
|
|
|
|
2025-09-07 17:55:53 +02:00
|
|
|
export_types_no_parameter!(
|
|
|
|
|
Unary,
|
|
|
|
|
QualifierRestricted,
|
|
|
|
|
QualifierLabel,
|
|
|
|
|
QualifierSystem,
|
|
|
|
|
QualifierEdge,
|
|
|
|
|
QualifierNode,
|
|
|
|
|
Qualifier,
|
|
|
|
|
Binary,
|
|
|
|
|
AssertReturnValue
|
|
|
|
|
);
|
2025-08-18 20:39:43 +02:00
|
|
|
|
|
|
|
|
pub type Special = super::EdgeRelablerInput;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-17 03:19:50 +02:00
|
|
|
// Implementation for graph labeling in bisimulation.
|
|
|
|
|
|
2025-10-17 19:45:20 +02:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
2025-08-17 03:19:50 +02:00
|
|
|
pub enum EdgeRelablerInput {
|
|
|
|
|
Label,
|
|
|
|
|
Edge,
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-17 19:45:20 +02:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
2025-08-18 20:39:43 +02:00
|
|
|
enum EdgeRelablerInputValues {
|
2025-08-24 02:01:24 +02:00
|
|
|
Label(label::Label),
|
2025-08-17 03:19:50 +02:00
|
|
|
Edge(petgraph::graph::EdgeIndex),
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
impl dsl::SpecialVariables<EdgeRelablerInputValues> for EdgeRelablerInput {
|
|
|
|
|
fn type_of(&self) -> dsl::AssertionTypes {
|
2025-09-07 17:55:53 +02:00
|
|
|
match self {
|
2025-10-27 21:12:43 +01:00
|
|
|
| Self::Edge => dsl::AssertionTypes::Edge,
|
|
|
|
|
| Self::Label => dsl::AssertionTypes::Label,
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
fn type_qualified(&self, q: &dsl::Qualifier) -> Result<dsl::AssertionTypes, String> {
|
2025-09-07 17:55:53 +02:00
|
|
|
match (self, q) {
|
2025-10-27 21:12:43 +01:00
|
|
|
| (Self::Label, dsl::Qualifier::Label(_))
|
|
|
|
|
| (Self::Label, dsl::Qualifier::Restricted(_)) =>
|
|
|
|
|
Ok(dsl::AssertionTypes::Set),
|
2025-09-11 02:49:14 +02:00
|
|
|
| (s, q) =>
|
|
|
|
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2025-09-07 17:55:53 +02:00
|
|
|
fn new_context(
|
|
|
|
|
input: HashMap<Self, EdgeRelablerInputValues>,
|
2025-10-27 21:12:43 +01:00
|
|
|
) -> HashMap<Self, dsl::AssertReturnValue> {
|
2025-09-07 17:55:53 +02:00
|
|
|
input
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|(key, value)| match value {
|
2025-09-11 02:49:14 +02:00
|
|
|
| EdgeRelablerInputValues::Edge(e) =>
|
2025-10-27 21:12:43 +01:00
|
|
|
(*key, dsl::AssertReturnValue::Edge(*e)),
|
2025-09-11 02:49:14 +02:00
|
|
|
| EdgeRelablerInputValues::Label(l) =>
|
2025-10-27 21:12:43 +01:00
|
|
|
(*key, dsl::AssertReturnValue::Label(l.clone())),
|
2025-09-07 17:55:53 +02:00
|
|
|
})
|
2025-10-27 21:12:43 +01:00
|
|
|
.collect::<HashMap<Self, dsl::AssertReturnValue>>()
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
fn correct_type(&self, other: &dsl::AssertReturnValue) -> bool {
|
2025-09-07 17:55:53 +02:00
|
|
|
match (self, other) {
|
2025-10-27 21:12:43 +01:00
|
|
|
| (Self::Edge, dsl::AssertReturnValue::Edge(_))
|
|
|
|
|
| (Self::Label, dsl::AssertReturnValue::Label(_)) => true,
|
2025-09-11 02:49:14 +02:00
|
|
|
| (_, _) => false,
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-24 03:35:32 +02:00
|
|
|
impl std::fmt::Debug for EdgeRelablerInput {
|
2025-08-17 03:19:50 +02:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2025-09-07 17:55:53 +02:00
|
|
|
match self {
|
2025-09-11 02:49:14 +02:00
|
|
|
| Self::Label => write!(f, "label"),
|
|
|
|
|
| Self::Edge => write!(f, "edge"),
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-24 03:35:32 +02:00
|
|
|
impl PrintableWithTranslator for EdgeRelablerInput {
|
2025-09-07 17:55:53 +02:00
|
|
|
fn print(
|
|
|
|
|
&self,
|
|
|
|
|
f: &mut std::fmt::Formatter,
|
|
|
|
|
_translator: &translator::Translator,
|
|
|
|
|
) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{self:?}")
|
2025-08-24 03:35:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
impl dsl::Assert<EdgeRelablerInput> {
|
2025-08-17 03:19:50 +02:00
|
|
|
pub fn typecheck(&self) -> Result<(), String> {
|
2025-10-27 21:12:43 +01:00
|
|
|
let mut context = dsl::TypeContext::new();
|
|
|
|
|
let ty = dsl::typecheck(&self.tree, &mut context)?;
|
2025-09-07 17:55:53 +02:00
|
|
|
match ty {
|
2025-10-27 21:12:43 +01:00
|
|
|
| dsl::AssertionTypes::Boolean
|
|
|
|
|
| dsl::AssertionTypes::Integer
|
|
|
|
|
| dsl::AssertionTypes::String
|
|
|
|
|
| dsl::AssertionTypes::Label
|
|
|
|
|
| dsl::AssertionTypes::Set
|
|
|
|
|
| dsl::AssertionTypes::Element
|
|
|
|
|
| dsl::AssertionTypes::Edge
|
|
|
|
|
| dsl::AssertionTypes::Node
|
|
|
|
|
| dsl::AssertionTypes::System
|
|
|
|
|
| dsl::AssertionTypes::Context => Ok(()),
|
|
|
|
|
| dsl::AssertionTypes::NoType =>
|
2025-09-10 22:41:40 +02:00
|
|
|
Err("No return type, at least one return statement required."
|
2025-09-11 02:49:14 +02:00
|
|
|
.into()),
|
2025-10-27 21:12:43 +01:00
|
|
|
| dsl::AssertionTypes::RangeInteger
|
|
|
|
|
| dsl::AssertionTypes::RangeSet
|
|
|
|
|
| dsl::AssertionTypes::RangeNeighbours =>
|
2025-09-11 02:49:14 +02:00
|
|
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn execute(
|
2025-09-07 17:55:53 +02:00
|
|
|
&self,
|
|
|
|
|
graph: &graph::SystemGraph,
|
|
|
|
|
edge: &<graph::SystemGraph as petgraph::visit::GraphBase>::EdgeId,
|
|
|
|
|
translator: &mut translator::Translator,
|
2025-10-27 21:12:43 +01:00
|
|
|
) -> Result<dsl::AssertReturnValue, String> {
|
2025-09-07 17:55:53 +02:00
|
|
|
let label = graph
|
|
|
|
|
.edge_weight(*edge)
|
|
|
|
|
.ok_or("Missing edge {{debug: {edge:?}}}")?;
|
|
|
|
|
|
|
|
|
|
let mut input_vals = HashMap::new();
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
EdgeRelablerInput::Edge,
|
|
|
|
|
EdgeRelablerInputValues::Edge(*edge),
|
|
|
|
|
);
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
EdgeRelablerInput::Label,
|
|
|
|
|
EdgeRelablerInputValues::Label(label.clone()),
|
|
|
|
|
);
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
let mut context = dsl::Context::new(input_vals);
|
|
|
|
|
if let Some(v) = dsl::execute(&self.tree, &mut context, translator, graph)? {
|
2025-09-07 17:55:53 +02:00
|
|
|
Ok(v)
|
|
|
|
|
} else {
|
|
|
|
|
Err("No value returned.".into())
|
|
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-18 20:39:43 +02:00
|
|
|
// -----------------------------------------------------------------------------
|
2025-08-17 03:19:50 +02:00
|
|
|
// Implementation for node grouping.
|
2025-08-18 20:39:43 +02:00
|
|
|
// -----------------------------------------------------------------------------
|
2025-08-17 03:19:50 +02:00
|
|
|
|
2025-09-10 22:41:40 +02:00
|
|
|
/// Module that has all types and structures for bisimilarity relabeler.
|
|
|
|
|
pub mod useful_types_node_relabeler {
|
|
|
|
|
macro_rules! export_types {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::dsl::$x<super::NodeRelablerInput>;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! export_types_no_parameter {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::dsl::$x;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export_types!(Assert, Tree, Variable, Expression, Range);
|
|
|
|
|
|
|
|
|
|
export_types_no_parameter!(
|
|
|
|
|
Unary,
|
|
|
|
|
QualifierRestricted,
|
|
|
|
|
QualifierLabel,
|
|
|
|
|
QualifierSystem,
|
|
|
|
|
QualifierEdge,
|
|
|
|
|
QualifierNode,
|
|
|
|
|
Qualifier,
|
|
|
|
|
Binary,
|
|
|
|
|
AssertReturnValue
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
pub type Special = super::NodeRelablerInput;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-17 19:45:20 +02:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
2025-08-17 03:19:50 +02:00
|
|
|
pub enum NodeRelablerInput {
|
|
|
|
|
Entities,
|
|
|
|
|
Node,
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-17 19:45:20 +02:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
2025-08-18 20:39:43 +02:00
|
|
|
enum NodeRelablerInputValues {
|
2025-08-24 02:01:24 +02:00
|
|
|
Entities(set::Set),
|
2025-08-17 03:19:50 +02:00
|
|
|
Node(petgraph::graph::NodeIndex),
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
impl dsl::SpecialVariables<NodeRelablerInputValues> for NodeRelablerInput {
|
|
|
|
|
fn type_of(&self) -> dsl::AssertionTypes {
|
2025-09-07 17:55:53 +02:00
|
|
|
match self {
|
2025-10-27 21:12:43 +01:00
|
|
|
| Self::Entities => dsl::AssertionTypes::Set,
|
|
|
|
|
| Self::Node => dsl::AssertionTypes::Node,
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
fn type_qualified(&self, q: &dsl::Qualifier) -> Result<dsl::AssertionTypes, String> {
|
2025-09-07 17:55:53 +02:00
|
|
|
match (self, q) {
|
2025-10-27 21:12:43 +01:00
|
|
|
| (Self::Node, dsl::Qualifier::Node(dsl::QualifierNode::System)) =>
|
|
|
|
|
Ok(dsl::AssertionTypes::System),
|
|
|
|
|
| (Self::Node, dsl::Qualifier::Node(dsl::QualifierNode::Neighbours)) =>
|
|
|
|
|
Ok(dsl::AssertionTypes::RangeNeighbours),
|
2025-09-11 02:49:14 +02:00
|
|
|
| (s, q) =>
|
|
|
|
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2025-09-07 17:55:53 +02:00
|
|
|
fn new_context(
|
|
|
|
|
input: HashMap<Self, NodeRelablerInputValues>,
|
2025-10-27 21:12:43 +01:00
|
|
|
) -> HashMap<Self, dsl::AssertReturnValue> {
|
2025-09-07 17:55:53 +02:00
|
|
|
input
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|(key, value)| match value {
|
2025-09-11 02:49:14 +02:00
|
|
|
| NodeRelablerInputValues::Entities(e) =>
|
2025-10-27 21:12:43 +01:00
|
|
|
(*key, dsl::AssertReturnValue::Set(e.clone())),
|
2025-09-11 02:49:14 +02:00
|
|
|
| NodeRelablerInputValues::Node(n) =>
|
2025-10-27 21:12:43 +01:00
|
|
|
(*key, dsl::AssertReturnValue::Node(*n)),
|
2025-09-07 17:55:53 +02:00
|
|
|
})
|
2025-10-27 21:12:43 +01:00
|
|
|
.collect::<HashMap<Self, dsl::AssertReturnValue>>()
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
fn correct_type(&self, other: &dsl::AssertReturnValue) -> bool {
|
2025-09-07 17:55:53 +02:00
|
|
|
match (self, other) {
|
2025-10-27 21:12:43 +01:00
|
|
|
| (Self::Entities, dsl::AssertReturnValue::Set(_))
|
|
|
|
|
| (Self::Node, dsl::AssertReturnValue::Node(_)) => true,
|
2025-09-11 02:49:14 +02:00
|
|
|
| (_, _) => false,
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-24 03:35:32 +02:00
|
|
|
impl std::fmt::Debug for NodeRelablerInput {
|
2025-08-17 03:19:50 +02:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2025-09-07 17:55:53 +02:00
|
|
|
match self {
|
2025-09-11 02:49:14 +02:00
|
|
|
| Self::Entities => write!(f, "entities"),
|
|
|
|
|
| Self::Node => write!(f, "node"),
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-24 03:35:32 +02:00
|
|
|
impl PrintableWithTranslator for NodeRelablerInput {
|
2025-09-07 17:55:53 +02:00
|
|
|
fn print(
|
|
|
|
|
&self,
|
|
|
|
|
f: &mut std::fmt::Formatter,
|
|
|
|
|
_translator: &translator::Translator,
|
|
|
|
|
) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{self:?}")
|
2025-08-24 03:35:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
impl dsl::Assert<NodeRelablerInput> {
|
2025-08-17 03:19:50 +02:00
|
|
|
pub fn typecheck(&self) -> Result<(), String> {
|
2025-10-27 21:12:43 +01:00
|
|
|
let mut context = dsl::TypeContext::new();
|
|
|
|
|
let ty = dsl::typecheck(&self.tree, &mut context)?;
|
2025-09-07 17:55:53 +02:00
|
|
|
match ty {
|
2025-10-27 21:12:43 +01:00
|
|
|
| dsl::AssertionTypes::Boolean
|
|
|
|
|
| dsl::AssertionTypes::Integer
|
|
|
|
|
| dsl::AssertionTypes::String
|
|
|
|
|
| dsl::AssertionTypes::Label
|
|
|
|
|
| dsl::AssertionTypes::Set
|
|
|
|
|
| dsl::AssertionTypes::Element
|
|
|
|
|
| dsl::AssertionTypes::Edge
|
|
|
|
|
| dsl::AssertionTypes::Node
|
|
|
|
|
| dsl::AssertionTypes::System
|
|
|
|
|
| dsl::AssertionTypes::Context => Ok(()),
|
|
|
|
|
| dsl::AssertionTypes::NoType =>
|
2025-09-10 22:41:40 +02:00
|
|
|
Err("No return type, at least one return statement required."
|
2025-09-11 02:49:14 +02:00
|
|
|
.into()),
|
2025-10-27 21:12:43 +01:00
|
|
|
| dsl::AssertionTypes::RangeInteger
|
|
|
|
|
| dsl::AssertionTypes::RangeSet
|
|
|
|
|
| dsl::AssertionTypes::RangeNeighbours =>
|
2025-09-11 02:49:14 +02:00
|
|
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
2025-09-07 17:55:53 +02:00
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn execute(
|
2025-09-07 17:55:53 +02:00
|
|
|
&self,
|
|
|
|
|
graph: &graph::SystemGraph,
|
|
|
|
|
node: &<graph::SystemGraph as petgraph::visit::GraphBase>::NodeId,
|
|
|
|
|
translator: &mut translator::Translator,
|
2025-10-27 21:12:43 +01:00
|
|
|
) -> Result<dsl::AssertReturnValue, String> {
|
2025-09-07 17:55:53 +02:00
|
|
|
let system::System {
|
|
|
|
|
available_entities: entities,
|
|
|
|
|
..
|
|
|
|
|
} = graph
|
|
|
|
|
.node_weight(*node)
|
|
|
|
|
.ok_or("Missing node {{debug: {node:?}}}")?;
|
|
|
|
|
|
|
|
|
|
let mut input_vals = HashMap::new();
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
NodeRelablerInput::Entities,
|
|
|
|
|
NodeRelablerInputValues::Entities(entities.clone()),
|
|
|
|
|
);
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
NodeRelablerInput::Node,
|
|
|
|
|
NodeRelablerInputValues::Node(*node),
|
|
|
|
|
);
|
|
|
|
|
|
2025-10-27 21:12:43 +01:00
|
|
|
let mut context = dsl::Context::new(input_vals);
|
|
|
|
|
if let Some(v) = dsl::execute(&self.tree, &mut context, translator, graph)? {
|
|
|
|
|
Ok(v)
|
|
|
|
|
} else {
|
|
|
|
|
Err("No value returned.".into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
// Positive System
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Module that has all types and structures for bisimilarity relabeler.
|
|
|
|
|
pub mod useful_types_positive_edge_relabeler {
|
|
|
|
|
macro_rules! export_types {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::positivedsl::$x<super::PositiveEdgeRelablerInput>;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! export_types_no_parameter {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::positivedsl::$x;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export_types!(
|
|
|
|
|
PositiveAssert,
|
|
|
|
|
PositiveTree,
|
|
|
|
|
PositiveVariable,
|
|
|
|
|
PositiveExpression,
|
|
|
|
|
PositiveRange
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export_types_no_parameter!(
|
|
|
|
|
PositiveUnary,
|
|
|
|
|
QualifierRestricted,
|
|
|
|
|
QualifierLabel,
|
|
|
|
|
QualifierSystem,
|
|
|
|
|
QualifierEdge,
|
|
|
|
|
QualifierNode,
|
|
|
|
|
PositiveQualifier,
|
|
|
|
|
PositiveBinary,
|
|
|
|
|
PositiveAssertReturnValue
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
pub type Special = super::PositiveEdgeRelablerInput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
|
pub enum PositiveEdgeRelablerInput {
|
|
|
|
|
Label,
|
|
|
|
|
Edge,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
|
enum PositiveEdgeRelablerInputValues {
|
|
|
|
|
Label(label::PositiveLabel),
|
|
|
|
|
Edge(petgraph::graph::EdgeIndex),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl positivedsl::SpecialVariables<PositiveEdgeRelablerInputValues> for PositiveEdgeRelablerInput {
|
|
|
|
|
fn type_of(&self) -> positivedsl::PositiveAssertionTypes {
|
|
|
|
|
match self {
|
|
|
|
|
| Self::Edge => positivedsl::PositiveAssertionTypes::Edge,
|
|
|
|
|
| Self::Label => positivedsl::PositiveAssertionTypes::Label,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn type_qualified(&self, q: &positivedsl::PositiveQualifier) -> Result<positivedsl::PositiveAssertionTypes, String> {
|
|
|
|
|
match (self, q) {
|
|
|
|
|
| (Self::Label, positivedsl::PositiveQualifier::Label(_))
|
|
|
|
|
| (Self::Label, positivedsl::PositiveQualifier::Restricted(_)) =>
|
|
|
|
|
Ok(positivedsl::PositiveAssertionTypes::Set),
|
|
|
|
|
| (s, q) =>
|
|
|
|
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_context(
|
|
|
|
|
input: HashMap<Self, PositiveEdgeRelablerInputValues>,
|
|
|
|
|
) -> HashMap<Self, positivedsl::PositiveAssertReturnValue> {
|
|
|
|
|
input
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|(key, value)| match value {
|
|
|
|
|
| PositiveEdgeRelablerInputValues::Edge(e) =>
|
|
|
|
|
(*key, positivedsl::PositiveAssertReturnValue::Edge(*e)),
|
|
|
|
|
| PositiveEdgeRelablerInputValues::Label(l) =>
|
|
|
|
|
(*key, positivedsl::PositiveAssertReturnValue::Label(l.clone())),
|
|
|
|
|
})
|
|
|
|
|
.collect::<HashMap<Self, positivedsl::PositiveAssertReturnValue>>()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn correct_type(&self, other: &positivedsl::PositiveAssertReturnValue) -> bool {
|
|
|
|
|
match (self, other) {
|
|
|
|
|
| (Self::Edge, positivedsl::PositiveAssertReturnValue::Edge(_))
|
|
|
|
|
| (Self::Label, positivedsl::PositiveAssertReturnValue::Label(_)) => true,
|
|
|
|
|
| (_, _) => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Debug for PositiveEdgeRelablerInput {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
| Self::Label => write!(f, "label"),
|
|
|
|
|
| Self::Edge => write!(f, "edge"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PrintableWithTranslator for PositiveEdgeRelablerInput {
|
|
|
|
|
fn print(
|
|
|
|
|
&self,
|
|
|
|
|
f: &mut std::fmt::Formatter,
|
|
|
|
|
_translator: &translator::Translator,
|
|
|
|
|
) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{self:?}")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl positivedsl::PositiveAssert<PositiveEdgeRelablerInput> {
|
|
|
|
|
pub fn typecheck(&self) -> Result<(), String> {
|
|
|
|
|
let mut context = positivedsl::TypeContext::new();
|
|
|
|
|
let ty = positivedsl::typecheck(&self.tree, &mut context)?;
|
|
|
|
|
match ty {
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Boolean
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Integer
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::String
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Label
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Set
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::PositiveElement
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Edge
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Node
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::System
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Context => Ok(()),
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::NoType =>
|
|
|
|
|
Err("No return type, at least one return statement required."
|
|
|
|
|
.into()),
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::RangeInteger
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::RangeSet
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::RangeNeighbours =>
|
|
|
|
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn execute(
|
|
|
|
|
&self,
|
|
|
|
|
graph: &graph::PositiveSystemGraph,
|
|
|
|
|
edge: &<graph::PositiveSystemGraph as petgraph::visit::GraphBase>::EdgeId,
|
|
|
|
|
translator: &mut translator::Translator,
|
|
|
|
|
) -> Result<positivedsl::PositiveAssertReturnValue, String> {
|
|
|
|
|
let label = graph
|
|
|
|
|
.edge_weight(*edge)
|
|
|
|
|
.ok_or("Missing edge {{debug: {edge:?}}}")?;
|
|
|
|
|
|
|
|
|
|
let mut input_vals = HashMap::new();
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
PositiveEdgeRelablerInput::Edge,
|
|
|
|
|
PositiveEdgeRelablerInputValues::Edge(*edge),
|
|
|
|
|
);
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
PositiveEdgeRelablerInput::Label,
|
|
|
|
|
PositiveEdgeRelablerInputValues::Label(label.clone()),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let mut context = positivedsl::Context::new(input_vals);
|
|
|
|
|
if let Some(v) = positivedsl::execute(&self.tree, &mut context, translator, graph)? {
|
|
|
|
|
Ok(v)
|
|
|
|
|
} else {
|
|
|
|
|
Err("No value returned.".into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
// Positive node grouping
|
|
|
|
|
|
|
|
|
|
pub mod useful_types_positive_node_relabeler {
|
|
|
|
|
macro_rules! export_types {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::positivedsl::$x<super::PositiveNodeRelablerInput>;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! export_types_no_parameter {
|
|
|
|
|
( $( $x:ident ),* ) => {
|
|
|
|
|
$(
|
|
|
|
|
pub type $x = super::super::positivedsl::$x;
|
|
|
|
|
)*
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export_types!(
|
|
|
|
|
PositiveAssert,
|
|
|
|
|
PositiveTree,
|
|
|
|
|
PositiveVariable,
|
|
|
|
|
PositiveExpression,
|
|
|
|
|
PositiveRange
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export_types_no_parameter!(
|
|
|
|
|
PositiveUnary,
|
|
|
|
|
QualifierRestricted,
|
|
|
|
|
QualifierLabel,
|
|
|
|
|
QualifierSystem,
|
|
|
|
|
QualifierEdge,
|
|
|
|
|
QualifierNode,
|
|
|
|
|
PositiveQualifier,
|
|
|
|
|
PositiveBinary,
|
|
|
|
|
PositiveAssertReturnValue
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
pub type Special = super::PositiveNodeRelablerInput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
|
pub enum PositiveNodeRelablerInput {
|
|
|
|
|
Entities,
|
|
|
|
|
Node,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
|
enum PositiveNodeRelablerInputValues {
|
|
|
|
|
Entities(set::PositiveSet),
|
|
|
|
|
Node(petgraph::graph::NodeIndex),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl positivedsl::SpecialVariables<PositiveNodeRelablerInputValues> for PositiveNodeRelablerInput {
|
|
|
|
|
fn type_of(&self) -> positivedsl::PositiveAssertionTypes {
|
|
|
|
|
match self {
|
|
|
|
|
| Self::Entities => positivedsl::PositiveAssertionTypes::Set,
|
|
|
|
|
| Self::Node => positivedsl::PositiveAssertionTypes::Node,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn type_qualified(&self, q: &positivedsl::PositiveQualifier) -> Result<positivedsl::PositiveAssertionTypes, String> {
|
|
|
|
|
match (self, q) {
|
|
|
|
|
| (Self::Node, positivedsl::PositiveQualifier::Node(positivedsl::QualifierNode::System)) =>
|
|
|
|
|
Ok(positivedsl::PositiveAssertionTypes::System),
|
|
|
|
|
| (Self::Node, positivedsl::PositiveQualifier::Node(positivedsl::QualifierNode::Neighbours)) =>
|
|
|
|
|
Ok(positivedsl::PositiveAssertionTypes::RangeNeighbours),
|
|
|
|
|
| (s, q) =>
|
|
|
|
|
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_context(
|
|
|
|
|
input: HashMap<Self, PositiveNodeRelablerInputValues>,
|
|
|
|
|
) -> HashMap<Self, positivedsl::PositiveAssertReturnValue> {
|
|
|
|
|
input
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|(key, value)| match value {
|
|
|
|
|
| PositiveNodeRelablerInputValues::Entities(e) =>
|
|
|
|
|
(*key, positivedsl::PositiveAssertReturnValue::Set(e.clone())),
|
|
|
|
|
| PositiveNodeRelablerInputValues::Node(n) =>
|
|
|
|
|
(*key, positivedsl::PositiveAssertReturnValue::Node(*n)),
|
|
|
|
|
})
|
|
|
|
|
.collect::<HashMap<Self, positivedsl::PositiveAssertReturnValue>>()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn correct_type(&self, other: &positivedsl::PositiveAssertReturnValue) -> bool {
|
|
|
|
|
match (self, other) {
|
|
|
|
|
| (Self::Entities, positivedsl::PositiveAssertReturnValue::Set(_))
|
|
|
|
|
| (Self::Node, positivedsl::PositiveAssertReturnValue::Node(_)) => true,
|
|
|
|
|
| (_, _) => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Debug for PositiveNodeRelablerInput {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
| Self::Entities => write!(f, "entities"),
|
|
|
|
|
| Self::Node => write!(f, "node"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PrintableWithTranslator for PositiveNodeRelablerInput {
|
|
|
|
|
fn print(
|
|
|
|
|
&self,
|
|
|
|
|
f: &mut std::fmt::Formatter,
|
|
|
|
|
_translator: &translator::Translator,
|
|
|
|
|
) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{self:?}")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl positivedsl::PositiveAssert<PositiveNodeRelablerInput> {
|
|
|
|
|
pub fn typecheck(&self) -> Result<(), String> {
|
|
|
|
|
let mut context = positivedsl::TypeContext::new();
|
|
|
|
|
let ty = positivedsl::typecheck(&self.tree, &mut context)?;
|
|
|
|
|
match ty {
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Boolean
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Integer
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::String
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Label
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Set
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::PositiveElement
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Edge
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Node
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::System
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::Context => Ok(()),
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::NoType =>
|
|
|
|
|
Err("No return type, at least one return statement required."
|
|
|
|
|
.into()),
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::RangeInteger
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::RangeSet
|
|
|
|
|
| positivedsl::PositiveAssertionTypes::RangeNeighbours =>
|
|
|
|
|
Err(format!("Returned type {ty:?} is not a valid return type.")),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn execute(
|
|
|
|
|
&self,
|
|
|
|
|
graph: &graph::PositiveSystemGraph,
|
|
|
|
|
node: &<graph::PositiveSystemGraph as petgraph::visit::GraphBase>::NodeId,
|
|
|
|
|
translator: &mut translator::Translator,
|
|
|
|
|
) -> Result<positivedsl::PositiveAssertReturnValue, String> {
|
|
|
|
|
let system::PositiveSystem {
|
|
|
|
|
available_entities: entities,
|
|
|
|
|
..
|
|
|
|
|
} = graph
|
|
|
|
|
.node_weight(*node)
|
|
|
|
|
.ok_or("Missing node {{debug: {node:?}}}")?;
|
|
|
|
|
|
|
|
|
|
let mut input_vals = HashMap::new();
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
PositiveNodeRelablerInput::Entities,
|
|
|
|
|
PositiveNodeRelablerInputValues::Entities(entities.clone()),
|
|
|
|
|
);
|
|
|
|
|
input_vals.insert(
|
|
|
|
|
PositiveNodeRelablerInput::Node,
|
|
|
|
|
PositiveNodeRelablerInputValues::Node(*node),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let mut context = positivedsl::Context::new(input_vals);
|
|
|
|
|
if let Some(v) = positivedsl::execute(&self.tree, &mut context, translator, graph)? {
|
2025-09-07 17:55:53 +02:00
|
|
|
Ok(v)
|
|
|
|
|
} else {
|
|
|
|
|
Err("No value returned.".into())
|
|
|
|
|
}
|
2025-08-17 03:19:50 +02:00
|
|
|
}
|
|
|
|
|
}
|