now workspaces for modular compilation (maybe faster)

This commit is contained in:
elvis
2025-09-12 16:34:58 +02:00
parent fa1127358d
commit e41d92ac36
44 changed files with 318 additions and 227 deletions

1209
assert/src/dsl.rs Normal file

File diff suppressed because it is too large Load Diff

616
assert/src/fmt.rs Normal file
View File

@ -0,0 +1,616 @@
// -----------------------------------------------------------------------------
// Display Implementation for all types
// -----------------------------------------------------------------------------
use std::fmt;
use rsprocess::translator::{
Formatter, PrintableWithTranslator, Translator,
};
use super::dsl::*;
impl<S> fmt::Debug for Assert<S>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "label {{\n{:?}\n}}", self.tree)
}
}
impl<S> fmt::Debug for Tree<S>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::Concat(t1, t2) => {
write!(f, "{t1:?};\n{t2:?}")
},
| Self::If(exp, t) => {
write!(f, "if {exp:?} {{\n{t:?}\n}}")
},
| Self::IfElse(exp, t1, t2) => {
write!(f, "if {exp:?} {{\n{t1:?}\n}} else {{\n{t2:?}\n}}")
},
| Self::Assignment(v, q, exp) =>
if let Some(q) = q {
write!(f, "{v:?}.{q:?} = {exp:?}")
} else {
write!(f, "{v:?} = {exp:?}")
},
| Self::Return(exp) => {
write!(f, "return {exp:?}")
},
| Self::For(v, r, t) => {
write!(f, "for {v:?} in {r:?} {{\n{t:?}\n}}")
},
}
}
}
impl<S> fmt::Debug for Variable<S>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::Special(s) => {
write!(f, "{s:?}")
},
| Self::Id(s) => {
write!(f, "{s:?}")
},
}
}
}
impl<S> fmt::Debug for Expression<S>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::True => {
write!(f, "True")
},
| Self::False => {
write!(f, "False")
},
| Self::Integer(i) => {
write!(f, "{i}")
},
| Self::Label(rslabel) => {
write!(f, "{{debug: {rslabel:?}}}")
},
| Self::Set(set) => {
write!(f, "{{debug: {set:?}}}")
},
| Self::Element(el) => {
write!(f, "'{{debug: {el:?}}}'")
},
| Self::String(s) => {
write!(f, r#""{s:?}""#)
},
| Self::Var(v) => {
write!(f, "{v:?}")
},
| Self::Unary(u, exp) =>
if u.is_prefix() {
write!(f, "{u:?}({exp:?})")
} else if u.is_suffix() {
write!(f, "{exp:?}{u:?}")
} else {
unreachable!()
},
| Self::Binary(b, exp1, exp2) =>
if b.is_prefix() {
write!(f, "{b:?}({exp1:?}, {exp2:?})")
} else if b.is_suffix() {
write!(f, "({exp1:?}, {exp2:?}){b:?}")
} else if b.is_infix() {
write!(f, "({exp1:?} {b:?} {exp2:?})")
} else {
unreachable!()
},
}
}
}
impl<S> fmt::Debug for Range<S>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::IterateOverSet(exp) => write!(f, "{{{exp:?}}}"),
| Self::IterateInRange(exp1, exp2) => {
write!(f, "{exp1:?}..{exp2:?}")
},
}
}
}
impl fmt::Debug for Unary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::Not => write!(f, "not"),
| Self::Rand => write!(f, "rand"),
| Self::Empty => write!(f, ".empty"),
| Self::Length => write!(f, ".length"),
| Self::ToStr => write!(f, ".tostr"),
| Self::ToEl => write!(f, ".toel"),
| Self::Qualifier(q) => write!(f, ".{q:?}"),
}
}
}
impl fmt::Debug for QualifierRestricted {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::Entities => write!(f, "Entities"),
| Self::Context => write!(f, "Context"),
| Self::Reactants => write!(f, "Reactants"),
| Self::ReactantsAbsent => write!(f, "ReactantsAbsent"),
| Self::Inhibitors => write!(f, "Inhibitors"),
| Self::InhibitorsPresent => write!(f, "InhibitorsPresent"),
| Self::Products => write!(f, "Products"),
}
}
}
impl fmt::Debug for QualifierLabel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::AvailableEntities => write!(f, "AvailableEntities"),
| Self::AllReactants => write!(f, "AllReactants"),
| Self::AllInhibitors => write!(f, "AllInhibitors"),
}
}
}
impl fmt::Debug for QualifierSystem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
| Self::Context => write!(f, "context"),
| Self::Entities => write!(f, "entities"),
}
}
}
impl fmt::Debug for QualifierEdge {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
| Self::Source => write!(f, "source"),
| Self::Target => write!(f, "target"),
}
}
}
impl fmt::Debug for QualifierNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
| Self::Neighbours => write!(f, "neighbours"),
| Self::System => write!(f, "system"),
}
}
}
impl fmt::Debug for Qualifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
| Self::Label(q) => write!(f, "{q:?}"),
| Self::Restricted(q) => write!(f, "{q:?}"),
| Self::System(q) => write!(f, "{q:?}"),
| Self::Edge(q) => write!(f, "{q:?}"),
| Self::Node(q) => write!(f, "{q:?}"),
}
}
}
impl fmt::Debug for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::And => write!(f, "&&"),
| Self::Or => write!(f, "||"),
| Self::Xor => write!(f, "^^"),
| Self::Less => write!(f, "<"),
| Self::LessEq => write!(f, "<="),
| Self::More => write!(f, ">"),
| Self::MoreEq => write!(f, ">="),
| Self::Eq => write!(f, "=="),
| Self::NotEq => write!(f, "!="),
| Self::Plus => write!(f, "+"),
| Self::Minus => write!(f, "-"),
| Self::Times => write!(f, "*"),
| Self::Exponential => write!(f, "^"),
| Self::Quotient => write!(f, "/"),
| Self::Reminder => write!(f, "%"),
| Self::Concat => write!(f, "::"),
| Self::SubStr => write!(f, "substr"),
| Self::Min => write!(f, "min"),
| Self::Max => write!(f, "max"),
| Self::CommonSubStr => write!(f, "commonsubstr"),
}
}
}
impl fmt::Debug for AssertReturnValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::Boolean(b) => write!(f, "{b:?}"),
| Self::Integer(i) => write!(f, "{i:?}"),
| Self::String(s) => write!(f, r#""{s:?}""#),
| Self::Label(l) => write!(f, "{{debug: {l:?}}}"),
| Self::Set(set) => write!(f, "{{debug: {set:?}}}"),
| Self::Element(el) => write!(f, "{{debug: {el:?}}}"),
| Self::Edge(edge) => write!(f, "{{debug: {edge:?}}}"),
| Self::Node(node) => write!(f, "{{debug: {node:?}}}"),
| Self::Neighbours(node) => {
write!(f, "{{debug: {node:?}}}.neighbours")
},
| Self::System(sys) => write!(f, "{{debug: {sys:?}}}"),
| Self::Context(ctx) => write!(f, "{{debug: {ctx:?}}}"),
}
}
}
impl fmt::Debug for AssertionTypes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
| Self::Boolean => write!(f, "boolean"),
| Self::Integer => write!(f, "integer"),
| Self::String => write!(f, "string"),
| Self::Label => write!(f, "label"),
| Self::Set => write!(f, "set"),
| Self::Element => write!(f, "element"),
| Self::System => write!(f, "system"),
| Self::Context => write!(f, "context"),
| Self::NoType => write!(f, "no type"),
| Self::RangeInteger => write!(f, "range of integers"),
| Self::RangeSet => write!(f, "range of set"),
| Self::RangeNeighbours => write!(f, "range of edges"),
| Self::Edge => write!(f, "edge"),
| Self::Node => write!(f, "node"),
}
}
}
// -----------------------------------------------------------------------------
impl<S> PrintableWithTranslator for Assert<S>
where
S: PrintableWithTranslator,
{
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
write!(
f,
"label {{\n{}\n}}",
Formatter::from(translator, &self.tree)
)
}
}
impl<S> PrintableWithTranslator for Tree<S>
where
S: PrintableWithTranslator,
{
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::Concat(t1, t2) => write!(
f,
"{};\n{}",
Formatter::from(translator, &**t1),
Formatter::from(translator, &**t2)
),
| Self::If(exp, t) => write!(
f,
"if {} {{\n{}\n}}",
Formatter::from(translator, &**exp),
Formatter::from(translator, &**t)
),
| Self::IfElse(exp, t1, t2) => {
write!(
f,
"if {} {{\n{}\n}} else {{\n{}\n}}",
Formatter::from(translator, &**exp),
Formatter::from(translator, &**t1),
Formatter::from(translator, &**t2)
)
},
| Self::Assignment(v, q, exp) =>
if let Some(q) = q {
write!(
f,
"{}.{} = {}",
Formatter::from(translator, v),
Formatter::from(translator, q),
Formatter::from(translator, &**exp)
)
} else {
write!(
f,
"{} = {}",
Formatter::from(translator, v),
Formatter::from(translator, &**exp)
)
},
| Self::Return(exp) => {
write!(f, "return {}", Formatter::from(translator, &**exp))
},
| Self::For(v, r, t) => {
write!(
f,
"for {} in {} {{\n{}\n}}",
Formatter::from(translator, v),
Formatter::from(translator, r),
Formatter::from(translator, &**t)
)
},
}
}
}
impl<S> PrintableWithTranslator for Variable<S>
where
S: PrintableWithTranslator,
{
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::Special(s) => {
write!(f, "{}", Formatter::from(translator, s))
},
| Self::Id(s) => write!(f, "{s}"),
}
}
}
impl<S> PrintableWithTranslator for Expression<S>
where
S: PrintableWithTranslator,
{
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::True => write!(f, "True"),
| Self::False => write!(f, "False"),
| Self::Integer(i) => write!(f, "{i}"),
| Self::Label(l) => {
write!(f, "{}", Formatter::from(translator, &**l))
},
| Self::Set(set) => {
write!(f, "{}", Formatter::from(translator, set))
},
| Self::Element(el) => {
write!(f, "'{}'", Formatter::from(translator, el))
},
| Self::String(s) => write!(f, r#""{s}""#),
| Self::Var(v) => write!(f, "{}", Formatter::from(translator, v)),
| Self::Unary(u, exp) =>
if u.is_prefix() {
write!(
f,
"{}({})",
Formatter::from(translator, u),
Formatter::from(translator, &**exp)
)
} else if u.is_suffix() {
write!(
f,
"{}{}",
Formatter::from(translator, &**exp),
Formatter::from(translator, u)
)
} else {
unreachable!()
},
| Self::Binary(b, exp1, exp2) =>
if b.is_prefix() {
write!(
f,
"{}({}, {})",
Formatter::from(translator, b),
Formatter::from(translator, &**exp1),
Formatter::from(translator, &**exp2)
)
} else if b.is_suffix() {
write!(
f,
"({}, {}){}",
Formatter::from(translator, &**exp1),
Formatter::from(translator, &**exp2),
Formatter::from(translator, b)
)
} else if b.is_infix() {
write!(
f,
"({} {} {})",
Formatter::from(translator, &**exp1),
Formatter::from(translator, b),
Formatter::from(translator, &**exp2)
)
} else {
unreachable!()
},
}
}
}
impl<S> PrintableWithTranslator for Range<S>
where
S: PrintableWithTranslator,
{
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::IterateOverSet(exp) => {
write!(f, "{}", Formatter::from(translator, &**exp))
},
| Self::IterateInRange(exp1, exp2) => write!(
f,
"{}..{}",
Formatter::from(translator, &**exp1),
Formatter::from(translator, &**exp2)
),
}
}
}
impl PrintableWithTranslator for Unary {
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::Not => write!(f, "not"),
| Self::Rand => write!(f, "rand"),
| Self::Empty => write!(f, ".empty"),
| Self::Length => write!(f, ".length"),
| Self::ToStr => write!(f, ".tostr"),
| Self::ToEl => write!(f, ".toel"),
| Self::Qualifier(q) => {
write!(f, ".{}", Formatter::from(translator, q))
},
}
}
}
impl PrintableWithTranslator for QualifierRestricted {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl PrintableWithTranslator for QualifierLabel {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl PrintableWithTranslator for QualifierSystem {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl PrintableWithTranslator for QualifierEdge {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl PrintableWithTranslator for QualifierNode {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl PrintableWithTranslator for Qualifier {
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::Label(q) => write!(f, "{}", Formatter::from(translator, q)),
| Self::Restricted(q) => {
write!(f, "{}", Formatter::from(translator, q))
},
| Self::System(q) => {
write!(f, "{}", Formatter::from(translator, q))
},
| Self::Edge(q) => write!(f, "{}", Formatter::from(translator, q)),
| Self::Node(q) => write!(f, "{}", Formatter::from(translator, q)),
}
}
}
impl PrintableWithTranslator for Binary {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl PrintableWithTranslator for AssertReturnValue {
fn print(
&self,
f: &mut fmt::Formatter,
translator: &Translator,
) -> fmt::Result {
match self {
| Self::Boolean(b) => write!(f, "{b}"),
| Self::Integer(i) => write!(f, "{i}"),
| Self::String(s) => write!(f, r#""{s}""#),
| Self::Label(l) => write!(f, "{}", Formatter::from(translator, l)),
| Self::Set(set) => {
write!(f, "{}", Formatter::from(translator, set))
},
| Self::Element(el) => {
write!(f, "{}", Formatter::from(translator, el))
},
| Self::Edge(edge) => write!(f, "{{edge: {edge:?}}}"),
| Self::Node(node) => write!(f, "{{node: {node:?}}}"),
| Self::Neighbours(node) => {
write!(f, "{{node: {node:?}}}.neighbours")
},
| Self::System(sys) => {
write!(f, "{}", Formatter::from(translator, sys))
},
| Self::Context(ctx) => {
write!(f, "{}", Formatter::from(translator, ctx))
},
}
}
}
impl PrintableWithTranslator for AssertionTypes {
fn print(
&self,
f: &mut fmt::Formatter,
_translator: &Translator,
) -> fmt::Result {
write!(f, "{self:?}")
}
}

15
assert/src/lib.rs Normal file
View File

@ -0,0 +1,15 @@
pub mod dsl;
pub mod rsassert;
pub mod relabel {
pub use super::rsassert::useful_types_edge_relabeler::*;
}
pub mod grouping {
pub use super::rsassert::useful_types_node_relabeler::*;
}
mod fmt;
#[cfg(test)]
mod tests;

341
assert/src/rsassert.rs Normal file
View File

@ -0,0 +1,341 @@
use std::collections::HashMap;
use super::dsl::*;
use rsprocess::{graph, label, set, system, translator};
use rsprocess::translator::PrintableWithTranslator;
// ----------------------------------------------------------------------------
// Specific Assert Implementation
// ----------------------------------------------------------------------------
/// Module that has all types and structures for bisimilarity relabeler.
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;
)*
};
}
export_types!(Assert, Tree, Variable, Expression, Range);
export_types_no_parameter!(
Unary,
QualifierRestricted,
QualifierLabel,
QualifierSystem,
QualifierEdge,
QualifierNode,
Qualifier,
Binary,
AssertReturnValue
);
pub type Special = super::EdgeRelablerInput;
}
// Implementation for graph labeling in bisimulation.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum EdgeRelablerInput {
Label,
Edge,
}
#[derive(Clone)]
enum EdgeRelablerInputValues {
Label(label::Label),
Edge(petgraph::graph::EdgeIndex),
}
impl SpecialVariables<EdgeRelablerInputValues> for EdgeRelablerInput {
fn type_of(&self) -> AssertionTypes {
match self {
| Self::Edge => AssertionTypes::Edge,
| Self::Label => AssertionTypes::Label,
}
}
fn type_qualified(&self, q: &Qualifier) -> Result<AssertionTypes, String> {
match (self, q) {
| (Self::Label, Qualifier::Label(_))
| (Self::Label, Qualifier::Restricted(_)) =>
Ok(AssertionTypes::Set),
| (s, q) =>
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
}
}
fn new_context(
input: HashMap<Self, EdgeRelablerInputValues>,
) -> HashMap<Self, AssertReturnValue> {
input
.iter()
.map(|(key, value)| match value {
| EdgeRelablerInputValues::Edge(e) =>
(*key, AssertReturnValue::Edge(*e)),
| EdgeRelablerInputValues::Label(l) =>
(*key, AssertReturnValue::Label(l.clone())),
})
.collect::<HashMap<Self, AssertReturnValue>>()
}
fn correct_type(&self, other: &AssertReturnValue) -> bool {
match (self, other) {
| (Self::Edge, AssertReturnValue::Edge(_))
| (Self::Label, AssertReturnValue::Label(_)) => true,
| (_, _) => false,
}
}
}
impl std::fmt::Debug for EdgeRelablerInput {
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 EdgeRelablerInput {
fn print(
&self,
f: &mut std::fmt::Formatter,
_translator: &translator::Translator,
) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
impl Assert<EdgeRelablerInput> {
pub fn typecheck(&self) -> Result<(), String> {
let mut context = TypeContext::new();
let ty = typecheck(&self.tree, &mut context)?;
match ty {
| AssertionTypes::Boolean
| AssertionTypes::Integer
| AssertionTypes::String
| AssertionTypes::Label
| AssertionTypes::Set
| AssertionTypes::Element
| AssertionTypes::Edge
| AssertionTypes::Node
| AssertionTypes::System
| AssertionTypes::Context => Ok(()),
| AssertionTypes::NoType =>
Err("No return type, at least one return statement required."
.into()),
| AssertionTypes::RangeInteger
| AssertionTypes::RangeSet
| AssertionTypes::RangeNeighbours =>
Err(format!("Returned type {ty:?} is not a valid return type.")),
}
}
pub fn execute(
&self,
graph: &graph::SystemGraph,
edge: &<graph::SystemGraph as petgraph::visit::GraphBase>::EdgeId,
translator: &mut translator::Translator,
) -> Result<AssertReturnValue, String> {
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()),
);
let mut context = Context::new(input_vals);
if let Some(v) = execute(&self.tree, &mut context, translator, graph)? {
Ok(v)
} else {
Err("No value returned.".into())
}
}
}
// -----------------------------------------------------------------------------
// Implementation for node grouping.
// -----------------------------------------------------------------------------
/// 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;
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NodeRelablerInput {
Entities,
Node,
}
#[derive(Clone)]
enum NodeRelablerInputValues {
Entities(set::Set),
Node(petgraph::graph::NodeIndex),
}
impl SpecialVariables<NodeRelablerInputValues> for NodeRelablerInput {
fn type_of(&self) -> AssertionTypes {
match self {
| Self::Entities => AssertionTypes::Set,
| Self::Node => AssertionTypes::Node,
}
}
fn type_qualified(&self, q: &Qualifier) -> Result<AssertionTypes, String> {
match (self, q) {
| (Self::Node, Qualifier::Node(QualifierNode::System)) =>
Ok(AssertionTypes::System),
| (Self::Node, Qualifier::Node(QualifierNode::Neighbours)) =>
Ok(AssertionTypes::RangeNeighbours),
| (s, q) =>
Err(format!("Wrong use of qualifier {q:?} on variable {s:?}.")),
}
}
fn new_context(
input: HashMap<Self, NodeRelablerInputValues>,
) -> HashMap<Self, AssertReturnValue> {
input
.iter()
.map(|(key, value)| match value {
| NodeRelablerInputValues::Entities(e) =>
(*key, AssertReturnValue::Set(e.clone())),
| NodeRelablerInputValues::Node(n) =>
(*key, AssertReturnValue::Node(*n)),
})
.collect::<HashMap<Self, AssertReturnValue>>()
}
fn correct_type(&self, other: &AssertReturnValue) -> bool {
match (self, other) {
| (Self::Entities, AssertReturnValue::Set(_))
| (Self::Node, AssertReturnValue::Node(_)) => true,
| (_, _) => false,
}
}
}
impl std::fmt::Debug for NodeRelablerInput {
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 NodeRelablerInput {
fn print(
&self,
f: &mut std::fmt::Formatter,
_translator: &translator::Translator,
) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
impl Assert<NodeRelablerInput> {
pub fn typecheck(&self) -> Result<(), String> {
let mut context = TypeContext::new();
let ty = typecheck(&self.tree, &mut context)?;
match ty {
| AssertionTypes::Boolean
| AssertionTypes::Integer
| AssertionTypes::String
| AssertionTypes::Label
| AssertionTypes::Set
| AssertionTypes::Element
| AssertionTypes::Edge
| AssertionTypes::Node
| AssertionTypes::System
| AssertionTypes::Context => Ok(()),
| AssertionTypes::NoType =>
Err("No return type, at least one return statement required."
.into()),
| AssertionTypes::RangeInteger
| AssertionTypes::RangeSet
| AssertionTypes::RangeNeighbours =>
Err(format!("Returned type {ty:?} is not a valid return type.")),
}
}
pub fn execute(
&self,
graph: &graph::SystemGraph,
node: &<graph::SystemGraph as petgraph::visit::GraphBase>::NodeId,
translator: &mut translator::Translator,
) -> Result<AssertReturnValue, String> {
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),
);
let mut context = Context::new(input_vals);
if let Some(v) = execute(&self.tree, &mut context, translator, graph)? {
Ok(v)
} else {
Err("No value returned.".into())
}
}
}

1336
assert/src/tests.rs Normal file

File diff suppressed because it is too large Load Diff