From a0a2f01c300ab5f38e7c3830d0067005b727b83f Mon Sep 17 00:00:00 2001 From: elvis Date: Sat, 16 Aug 2025 21:52:36 +0200 Subject: [PATCH] Refactoring --- src/rsprocess/assert.rs | 2177 +++++---------------------------- src/rsprocess/assert_fmt.rs | 212 ++++ src/rsprocess/assert_tests.rs | 1442 ++++++++++++++++++++++ src/rsprocess/grammar.lalrpop | 291 ++--- 4 files changed, 2102 insertions(+), 2020 deletions(-) create mode 100644 src/rsprocess/assert_fmt.rs create mode 100644 src/rsprocess/assert_tests.rs diff --git a/src/rsprocess/assert.rs b/src/rsprocess/assert.rs index b23b177..88afd07 100644 --- a/src/rsprocess/assert.rs +++ b/src/rsprocess/assert.rs @@ -13,7 +13,7 @@ pub enum Tree { Concat(Box, Box), If(Box, Box), IfElse(Box, Box, Box), - Assignment(AssignmentVariable, Box), + Assignment(Variable, Option, Box), Return(Box), For(Variable, Range, Box), } @@ -25,12 +25,6 @@ pub enum Variable { Edge, // special edge that is the input of the function } -#[derive(Debug, Clone)] -pub enum AssignmentVariable { - Var(Variable), - QualifiedVar(Variable, QualifierRestricted) -} - #[derive(Debug, Clone)] pub enum Expression { True, @@ -40,7 +34,7 @@ pub enum Expression { Set(super::structure::RSset), Element(super::translator::IdType), String(String), - Var(AssignmentVariable), + Var(Variable), Unary(Unary, Box), Binary(Binary, Box, Box), @@ -60,8 +54,7 @@ pub enum Unary { Empty, Length, ToStr, - QualifierLabel(QualifierLabel), - QualifierSystem(QualifierSystem), + Qualifier(Qualifier), ToEl, Source, Target, @@ -69,6 +62,145 @@ pub enum Unary { System, } +#[derive(Debug, Clone, Copy)] +pub enum QualifierRestricted { + Entities, + Context, + Reactants, + ReactantsAbsent, + Inhibitors, + InhibitorsPresent, + Products, +} + +#[derive(Debug, Clone, Copy)] +pub enum QualifierLabel { + AvailableEntities, + AllReactants, + AllInhibitors, +} + +#[derive(Debug, Clone, Copy)] +pub enum QualifierSystem { + Entities, + Context, +} + +#[derive(Debug, Clone, Copy)] +pub enum Qualifier { + System(QualifierSystem), + Label(QualifierLabel), + Restricted(QualifierRestricted), +} + +#[derive(Debug, Clone, Copy)] +pub enum Binary { + And, + Or, + Xor, + Less, + LessEq, + More, + MoreEq, + Eq, + NotEq, + Plus, + Minus, + Times, + Exponential, + Quotient, + Reminder, + Concat, + + SubStr, + Min, + Max, + CommonSubStr, +} + + + + + +// ----------------------------------------------------------------------------- +// Implementations for types +// ----------------------------------------------------------------------------- + +impl QualifierRestricted { + pub(super) fn referenced_mut<'a>( + &self, + label: &'a mut super::structure::RSlabel, + ) -> &'a mut super::structure::RSset { + match self { + Self::Entities => {&mut label.available_entities}, + Self::Context => {&mut label.context}, + Self::Reactants => {&mut label.reactants}, + Self::ReactantsAbsent => {&mut label.reactants_absent}, + Self::Inhibitors => {&mut label.inhibitors}, + Self::InhibitorsPresent => {&mut label.inhibitors_present}, + Self::Products => {&mut label.products}, + } + } + + pub(super) fn referenced<'a>( + &self, + label: &'a super::structure::RSlabel, + ) -> &'a super::structure::RSset { + match self { + Self::Entities => {&label.available_entities}, + Self::Context => {&label.context}, + Self::Reactants => {&label.reactants}, + Self::ReactantsAbsent => {&label.reactants_absent}, + Self::Inhibitors => {&label.inhibitors}, + Self::InhibitorsPresent => {&label.inhibitors_present}, + Self::Products => {&label.products}, + } + } + + pub(super) fn get( + &self, + label: &super::structure::RSlabel, + ) -> AssertReturnValue { + AssertReturnValue::Set(self.referenced(label).clone()) + } +} + +impl QualifierLabel { + pub(super) fn get( + &self, + l: &super::structure::RSlabel, + ) -> AssertReturnValue { + match self { + QualifierLabel::AvailableEntities => { + AssertReturnValue::Set(l.t.clone()) + }, + QualifierLabel::AllReactants => { + AssertReturnValue::Set(l.reactants.union(&l.reactants_absent)) + }, + QualifierLabel::AllInhibitors => { + AssertReturnValue::Set( + l.inhibitors.union(&l.inhibitors_present)) + }, + } + } +} + +impl QualifierSystem { + pub(super) fn get( + &self, + l: &super::structure::RSsystem, + ) -> AssertReturnValue { + match self { + Self::Context => { + AssertReturnValue::Context(l.context_process.clone()) + }, + Self::Entities => { + AssertReturnValue::Set(l.available_entities.clone()) + } + } + } +} + impl Unary { fn is_prefix(&self) -> bool { match self { @@ -77,8 +209,7 @@ impl Unary { Self::Empty | Self::Length | Self::ToStr | - Self::QualifierLabel(_) | - Self::QualifierSystem(_) | + Self::Qualifier(_) | Self::ToEl | Self::Source | Self::Target | @@ -114,7 +245,11 @@ impl Unary { (Self::ToStr, AssertionTypes::Integer) => { Ok(AssertionTypes::String) }, - (Self::QualifierLabel(_), AssertionTypes::Label) => { + (Self::Qualifier(Qualifier::Label(_)), AssertionTypes::Label) => { + Ok(AssertionTypes::Set) + }, + (Self::Qualifier(Qualifier::Restricted(_)), + AssertionTypes::Label) => { Ok(AssertionTypes::Set) }, (Self::ToEl, AssertionTypes::String) => { @@ -129,11 +264,13 @@ impl Unary { (Self::Neighbours, AssertionTypes::Node) => { Ok(AssertionTypes::RangeNeighbours) }, - (Self::QualifierSystem(QualifierSystem::Entities), + (Self::Qualifier( + Qualifier::System(QualifierSystem::Entities)), AssertionTypes::System) => { Ok(AssertionTypes::Set) }, - (Self::QualifierSystem(QualifierSystem::Context), + (Self::Qualifier( + Qualifier::System(QualifierSystem::Context)), AssertionTypes::System) => { Ok(AssertionTypes::Context) }, @@ -148,127 +285,6 @@ impl Unary { } } -#[derive(Debug, Clone, Copy)] -pub enum QualifierRestricted { - Entities, - Context, - Reactants, - ReactantsAbsent, - Inhibitors, - InhibitorsPresent, - Products, -} - -impl QualifierRestricted { - pub(super) fn referenced_mut<'a>( - &self, - label: &'a mut super::structure::RSlabel, - ) -> &'a mut super::structure::RSset { - match self { - Self::Entities => {&mut label.available_entities}, - Self::Context => {&mut label.context}, - Self::Reactants => {&mut label.reactants}, - Self::ReactantsAbsent => {&mut label.reactants_absent}, - Self::Inhibitors => {&mut label.inhibitors}, - Self::InhibitorsPresent => {&mut label.inhibitors_present}, - Self::Products => {&mut label.products}, - } - } - - pub(super) fn referenced<'a>( - &self, - label: &'a super::structure::RSlabel, - ) -> &'a super::structure::RSset { - match self { - Self::Entities => {&label.available_entities}, - Self::Context => {&label.context}, - Self::Reactants => {&label.reactants}, - Self::ReactantsAbsent => {&label.reactants_absent}, - Self::Inhibitors => {&label.inhibitors}, - Self::InhibitorsPresent => {&label.inhibitors_present}, - Self::Products => {&label.products}, - } - } -} - -#[derive(Debug, Clone, Copy)] -pub enum QualifierLabel { - AvailableEntities, - AllReactants, - AllInhibitors, - Restricted(QualifierRestricted), -} - -impl QualifierLabel { - pub(super) fn get( - &self, - l: &super::structure::RSlabel, - ) -> AssertReturnValue { - match self { - QualifierLabel::AvailableEntities => { - AssertReturnValue::Set(l.t.clone()) - }, - QualifierLabel::AllReactants => { - AssertReturnValue::Set(l.reactants.union(&l.reactants_absent)) - }, - QualifierLabel::AllInhibitors => { - AssertReturnValue::Set( - l.inhibitors.union(&l.inhibitors_present)) - }, - QualifierLabel::Restricted(q) => { - AssertReturnValue::Set(q.referenced(l).clone()) - } - } - } -} - -#[derive(Debug, Clone, Copy)] -pub enum QualifierSystem { - Entities, - Context, -} - -impl QualifierSystem { - pub(super) fn get( - &self, - l: &super::structure::RSsystem, - ) -> AssertReturnValue { - match self { - Self::Context => { - AssertReturnValue::Context(l.context_process.clone()) - }, - Self::Entities => { - AssertReturnValue::Set(l.available_entities.clone()) - } - } - } -} - -#[derive(Debug, Clone, Copy)] -pub enum Binary { - And, - Or, - Xor, - Less, - LessEq, - More, - MoreEq, - Eq, - NotEq, - Plus, - Minus, - Times, - Exponential, - Quotient, - Reminder, - Concat, - - SubStr, - Min, - Max, - CommonSubStr, -} - impl Binary { fn is_prefix(&self) -> bool { match self { @@ -401,6 +417,7 @@ impl Binary { } + // ----------------------------------------------------------------------------- use std::collections::HashMap; use std::fmt; @@ -422,33 +439,71 @@ impl TypeContext { fn assign( &mut self, - v: &AssignmentVariable, + v: &Variable, + q: Option<&Qualifier>, ty: AssertionTypes ) -> Result<(), String> { - match v { - AssignmentVariable::Var(Variable::Id(v)) => { + match (v, q) { + (Variable::Id(v), None) => { self.data.insert(v.clone(), ty); Ok(()) }, - AssignmentVariable::Var(Variable::Label) | - AssignmentVariable::Var(Variable::Edge) => { - Ok(()) - } - AssignmentVariable::QualifiedVar(Variable::Label, _) => { - Ok(()) + (Variable::Id(v), Some(q)) => { + match self.data.entry(v.clone()) { + std::collections::hash_map::Entry::Vacant(_ve) => { + Err(format!("Variable {v} as no assignment while \ + trying to assign to qualification {q}, \ + assign first a value.")) + }, + std::collections::hash_map::Entry::Occupied(oe) => { + match (oe.get(), q, ty) { + (AssertionTypes::Label, + Qualifier::Restricted(_), + AssertionTypes::Set) => { + Ok(()) + }, + (t, q, ty) => { + Err(format!("Variable {v} has type {t}, but \ + was assigned with qualifier {q} \ + value with type {ty}")) + } + } + } + } }, - AssignmentVariable::QualifiedVar(Variable::Edge, q) => - Err(format!("Variable does not have type label while trying to \ - assign to qualification {q}, it's an edge instead.\ - ")), - AssignmentVariable::QualifiedVar(Variable::Id(v), q) => { - if let Some(AssertionTypes::Label) = self.data.get(v) { + (Variable::Label, None) => { + if let AssertionTypes::Label = ty { Ok(()) } else { - Err(format!("Variable {v} does not have type label while \ - trying to assign to qualification {q}")) + Err(format!("Variable label has type label but was \ + assigned a value of type {ty}.")) } } + (Variable::Label, Some(q)) => { + match (q, ty) { + (Qualifier::Restricted(_), + AssertionTypes::Set) => { + Ok(()) + }, + (q, ty) => { + Err(format!("Variable label has type label, but \ + was assigned with qualifier {q} \ + value with type {ty}")) + } + } + } + (Variable::Edge, None) => { + if let AssertionTypes::Edge = ty { + Ok(()) + } else { + Err(format!("Variable egde has type edge but was \ + assigned a value of type {ty}.")) + } + } + (Variable::Edge, Some(q)) => { + Err(format!("Variable egde has type edge but was qualified \ + with qualifier {q}.")) + } } } @@ -501,149 +556,126 @@ impl TypeContext { fn get( &self, - v: &AssignmentVariable, + v: &Variable, ) -> Result { match v { - AssignmentVariable::Var(Variable::Label) => { + Variable::Label => { Ok(AssertionTypes::Label) }, - AssignmentVariable::Var(Variable::Edge) => { + Variable::Edge => { Ok(AssertionTypes::Edge) }, - AssignmentVariable::Var(Variable::Id(v)) => { + Variable::Id(v) => { if let Some(ty) = self.data.get(v) { Ok(*ty) } else { Err(format!("Could not find variable {v}.")) } }, - AssignmentVariable::QualifiedVar(Variable::Label, _) => { - Ok(AssertionTypes::Set) - }, - AssignmentVariable::QualifiedVar(Variable::Edge, _) => { - Err("Variable edge is not a label.".into()) - }, - AssignmentVariable::QualifiedVar(Variable::Id(var), _) => { - if let Some(ty) = self.data.get(var) { - if *ty == AssertionTypes::Label { - Ok(AssertionTypes::Set) - } else { - Err(format!("Variable {var} is not a label.")) - } - } else { - Err(format!("Could not find variable {v}.")) - } - } } } } -struct Context<'a> { +struct Context { data: HashMap, - label: &'a super::structure::RSlabel, - edge: &'a petgraph::graph::EdgeIndex, + label: super::structure::RSlabel, + edge: petgraph::graph::EdgeIndex, } -impl<'a> Context<'a> { +impl Context { fn new( - label: &'a super::structure::RSlabel, - edge: &'a petgraph::graph::EdgeIndex, + label: &super::structure::RSlabel, + edge: &petgraph::graph::EdgeIndex, ) -> Self { - Self { data: HashMap::new(), label, edge } + Self { data: HashMap::new(), + label: label.clone(), + edge: *edge } } fn assign( &mut self, - v: &AssignmentVariable, + v: &Variable, + q: Option<&Qualifier>, val: AssertReturnValue, ) -> Result<(), String> { - match v { - AssignmentVariable::Var(v) => { - if let Variable::Id(v) = v { - self.data.insert(v.clone(), val); - } + match (v, q) { + (Variable::Id(v), None) => { + self.data.insert(v.clone(), val); Ok(()) }, - AssignmentVariable::QualifiedVar(Variable::Label, _) => Ok(()), - AssignmentVariable::QualifiedVar(Variable::Edge, q) => - Err(format!("Variable edge does not have type label while \ - trying to assign to qualification {q}")), - AssignmentVariable::QualifiedVar(Variable::Id(v), q) => { + (Variable::Id(v), Some(q)) => { match self.data.entry(v.clone()) { - std::collections::hash_map::Entry::Vacant(_ve) => - Err(format!("Variable {v} has no value while trying to \ - assign a value to the field {q} of a label\ - ")), + std::collections::hash_map::Entry::Vacant(_ve) => { + Err(format!("Variable {v} as no assignment while \ + trying to assign to qualification {q}, \ + assign first a value.")) + }, std::collections::hash_map::Entry::Occupied(mut oe) => { - if let AssertReturnValue::Set(s) = val { - let l = oe.get_mut(); - match l { - AssertReturnValue::Label(l) => { - *q.referenced_mut(l) = s; - // if we modified available entities or the - // context we need to sync it with t - match q { - QualifierRestricted::Context | - QualifierRestricted::Entities => { - l.t = l.available_entities.union( - &l.context - ); - }, - _ => {}, - } - Ok(()) - }, - _ => { - Err(format!("Variable {v} does not have \ - type label while trying to \ - assign to qualification {q}")) - } + match (oe.get_mut(), q, val) { + (&mut AssertReturnValue::Label(ref mut l), + Qualifier::Restricted(q), + AssertReturnValue::Set(set)) => { + *q.referenced_mut(l) = set; + Ok(()) + }, + (val, q, newval) => { + Err(format!("Variable {v} has value {val}, but \ + was assigned with qualifier {q} \ + new value {newval}.")) } - } else { - Err(format!("Value {val} is not a set while trying \ - to assign to qualification {q} of \ - variable {v}")) } } } + }, + (Variable::Edge, None) => { + if let AssertReturnValue::Edge(e) = val { + self.edge = e; + Ok(()) + } else { + Err(format!("Trying to assign {val} to variable edge.")) + } + } + (Variable::Edge, Some(q)) => { + Err(format!("No assignment on {q} for variable edge.")) + } + (Variable::Label, None) => { + if let AssertReturnValue::Label(l) = val { + self.label = l.clone(); + Ok(()) + } else { + Err(format!("Trying to assign {val} to variable label.")) + } + } + (Variable::Label, Some(q)) => { + match (q, val) { + (Qualifier::Restricted(q), AssertReturnValue::Set(set)) => { + *q.referenced_mut(&mut self.label) = set; + Ok(()) + }, + (q, newval) => { + Err(format!("Variable label could not be assigned with \ + qualifier {q} new value {newval}.")) + } + } } } } fn get( &self, - v: &AssignmentVariable + v: &Variable, ) -> Result { match v { - AssignmentVariable::Var(Variable::Id(var)) => { + Variable::Id(var) => { self.data.get(var) .cloned() .ok_or(format!("Variable {v} used, but no value assigned.")) }, - AssignmentVariable::QualifiedVar(Variable::Id(var), q) => { - let val = self.data.get(var) - .ok_or(format!("Variable {v} used, but no value assigned." - ))?; - match val { - AssertReturnValue::Label(l) => { - Ok(AssertReturnValue::Set(q.referenced(l).clone())) - }, - _ => {Err(format!("Variable {v} is not a label but was \ - quantified with {q}."))} - } - }, - AssignmentVariable::Var(Variable::Label) => { + Variable::Label => { Ok(AssertReturnValue::Label(self.label.clone())) }, - AssignmentVariable::QualifiedVar(Variable::Label, q) => { - Ok(AssertReturnValue::Set(q.referenced(self.label).clone())) - }, - AssignmentVariable::Var(Variable::Edge) => { - Ok(AssertReturnValue::Edge(*self.edge)) - }, - AssignmentVariable::QualifiedVar(Variable::Edge, q) => { - Err(format!("Variable edge is not a label but was quantified \ - with {q}.")) + Variable::Edge => { + Ok(AssertReturnValue::Edge(self.edge)) }, } } @@ -722,7 +754,12 @@ impl AssertReturnValue { )? )) }, - (AssertReturnValue::Label(l), Unary::QualifierLabel(q)) => { + (AssertReturnValue::Label(l), + Unary::Qualifier(Qualifier::Label(q))) => { + Ok(q.get(&l)) + }, + (AssertReturnValue::Label(l), + Unary::Qualifier(Qualifier::Restricted(q))) => { Ok(q.get(&l)) }, (AssertReturnValue::String(s), Unary::ToEl) => { @@ -744,7 +781,8 @@ impl AssertReturnValue { graph.node_weight(node).unwrap().clone() )) }, - (AssertReturnValue::System(sys), Unary::QualifierSystem(q)) => { + (AssertReturnValue::System(sys), + Unary::Qualifier(Qualifier::System(q))) => { Ok(q.get(&sys)) } (val, u) => { @@ -872,9 +910,9 @@ fn typecheck( Err("Branches of if statement do not match.".into()) } }, - Tree::Assignment(assignvar, exp) => { + Tree::Assignment(assignvar, q, exp) => { let type_exp = typecheck_expression(exp, c)?; - c.assign(assignvar, type_exp)?; + c.assign(assignvar, q.into(), type_exp)?; Ok(AssertionTypes::NoType) }, Tree::Return(exp) => { @@ -979,9 +1017,9 @@ fn execute( execute(t2, c, translator, graph) } }, - Tree::Assignment(v, exp) => { + Tree::Assignment(v, q, exp) => { let val = execute_exp(exp, c, translator, graph)?; - c.assign(v, val)?; + c.assign(v, q.into(), val)?; Ok(None) }, Tree::Return(exp) => { @@ -990,7 +1028,7 @@ fn execute( Tree::For(v, r, t) => { let range = range_into_iter(r, c, translator, graph)?; for val in range { - c.assign(&AssignmentVariable::Var(v.clone()), val)?; + c.assign(v, None, val)?; if let Some(v) = execute(t, c, translator, graph)? { return Ok(Some(v)) } @@ -1114,1633 +1152,6 @@ impl RSassert { } } +include!("assert_fmt.rs"); -// ----------------------------------------------------------------------------- -// Display Implementation for all types -// ----------------------------------------------------------------------------- - -impl fmt::Display for RSassert { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "label {{\n{}\n}}", self.tree) - } -} - -impl fmt::Display for Tree { - 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, exp) => {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 fmt::Display for Variable { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Label => {write!(f, "label")}, - Self::Edge => {write!(f, "edge")}, - Self::Id(s) => {write!(f, "{s}")} - } - } -} - -impl fmt::Display for AssignmentVariable { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Var(v) => write!(f, "{v}"), - Self::QualifiedVar(v, q) => write!(f, "{v}.{q}"), - } - } -} - -impl fmt::Display for Expression { - 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 fmt::Display for Range { - 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::Display 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::QualifierLabel(q) => write!(f, ".{q}"), - Self::QualifierSystem(q) => write!(f, ".{q}"), - Self::ToEl => write!(f, ".toel"), - Self::Source => write!(f, ".source"), - Self::Target => write!(f, ".target"), - Self::Neighbours => write!(f, ".neighbours"), - Self::System => write!(f, ".system"), - } - } -} - -impl fmt::Display 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::Display 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"), - Self::Restricted(q) => write!(f, "{q}"), - } - } -} - -impl fmt::Display 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::Display 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::Display 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::Display 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"), - } - } -} - -// ----------------------------------------------------------------------------- -// Testing -// ----------------------------------------------------------------------------- - -#[test] -fn assert_tycheck_true() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert {tree: Tree::Return(Box::new(Expression::True))}; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_concat_1() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::True))), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_concat_2() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)))), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_return_1() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new(Tree::Return(Box::new(Expression::False))), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_return_incompatible_1() { - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new(Tree::Return(Box::new(Expression::Integer(10)))), - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_return_incompatible_2() { - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new( - Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)))), - Box::new(Tree::Return( - Box::new( - Expression::Var(AssignmentVariable::Var( - Variable::Id("a".into()) - )) - ) - ))), - ) - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_return_2() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new( - Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::False))), - Box::new(Tree::Return( - Box::new( - Expression::Var(AssignmentVariable::Var( - Variable::Id("a".into()) - )) - ) - ))), - ) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - - -#[test] -fn assert_tycheck_return_3() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::False))), - Box::new(Tree::Return( - Box::new( - Expression::Var(AssignmentVariable::Var( - Variable::Id("a".into()) - )) - ) - ))), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(false)))); -} - -#[test] -fn assert_tycheck_if_1() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new( - Tree::If( - Box::new( - Expression::True - ), - Box::new(Tree::Return( - Box::new( - Expression::True) - ) - ) - ), - ) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_if_2() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::If( - Box::new( - Expression::True - ), - Box::new(Tree::Return( - Box::new( - Expression::False) - ) - ) - ), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_ok()); - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(false)))); -} - -#[test] -fn assert_tycheck_if_3() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::If( - Box::new( - Expression::False - ), - Box::new(Tree::Return( - Box::new( - Expression::False) - ) - ) - ), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_if_4() { - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::If( - Box::new( - Expression::Integer(10) - ), - Box::new(Tree::Return( - Box::new( - Expression::True) - ) - ) - ), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_if_else_1() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Return(Box::new(Expression::True))), - Box::new( - Tree::IfElse( - Box::new( - Expression::True - ), - Box::new(Tree::Return( - Box::new( - Expression::True) - )), - Box::new(Tree::Return( - Box::new( - Expression::False) - )), - ), - ) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_if_else_2() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::IfElse( - Box::new( - Expression::False - ), - Box::new(Tree::Return( - Box::new( - Expression::True) - )), - Box::new(Tree::Return( - Box::new( - Expression::False) - )), - ), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(false)))); -} - -#[test] -fn assert_tycheck_if_else_3() { - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::IfElse( - Box::new( - Expression::Integer(10) - ), - Box::new(Tree::Return( - Box::new( - Expression::True) - )), - Box::new(Tree::Return( - Box::new( - Expression::False) - )), - ), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_if_else_4() { - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::IfElse( - Box::new( - Expression::True - ), - Box::new(Tree::Return( - Box::new( - Expression::True) - )), - Box::new(Tree::Return( - Box::new( - Expression::Integer(10)) - )), - ), - ), - Box::new(Tree::Return(Box::new(Expression::True))), - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_assignment_1() { - let tree = RSassert { - tree: Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::True) - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_assignment_2() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::True) - ) - ), - Box::new( - Tree::Return( - Box::new( - Expression::True - ) - ) - ), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_assignment_3() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::False) - ) - ), - Box::new( - Tree::Return( - Box::new( - Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - ) - ) - ) - ), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(false)))); -} - -#[test] -fn assert_tycheck_assignment_4() { - let tree = RSassert { - tree: Tree::Concat( - Box::new( - Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::True) - ) - ), - Box::new( - Tree::Return( - Box::new( - Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - ) - ) - ) - ), - ) - }; - assert!(tree.typecheck().is_err()); -} - -#[test] -fn assert_tycheck_assignment_5() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)) - )), - Box::new(Tree::Concat( - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(10)))); -} - -#[test] -fn assert_tycheck_assignment_6() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Integer(200)) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(10)))); -} - -#[test] -fn assert_tycheck_assignment_7() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::True) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - Box::new(Tree::Return( - Box::new(Expression::False) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} - -#[test] -fn assert_tycheck_assignment_8() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(10)))); -} - -#[test] -fn assert_tycheck_assignment_9() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )), - Box::new(Tree::Return( - Box::new(Expression::Integer(200)) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(10)))); -} - -#[test] -fn assert_tycheck_assignment_10() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(10)) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(200)) - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(10)))); -} - - -#[test] -fn assert_tycheck_for_1() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Set(RSset::new())) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Set(RSset::new())) - )), - )), - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateOverSet( - Box::new( - Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - ) - ) - ), - Box::new(Tree::Return( - Box::new(Expression::Integer(200)) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(tree.execute(&graph, &edge, &mut translator).is_err()); -} - - -#[test] -fn assert_tycheck_for_2() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Set(RSset::from([1, 2]))) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Set(RSset::new())) - )), - )), - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateOverSet( - Box::new( - Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - ) - ) - ), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - translator.encode("one"); - translator.encode("two"); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Set(_)))); -} - -#[test] -fn assert_tycheck_for_3() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Label( - Box::new(RSlabel::from(RSset::from([1, 2]), - RSset::new(), - RSset::from([1, 2]), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new())) - )) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Set(RSset::new())) - )), - )), - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateOverSet( - Box::new( - Expression::Var( - AssignmentVariable::QualifiedVar( - Variable::Id("a".into()), - QualifierRestricted::Entities - ) - ) - ) - ), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - translator.encode("one"); - translator.encode("two"); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Set(_)))); -} - -#[test] -fn assert_tycheck_for_4() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Label( - Box::new(RSlabel::from(RSset::from([1, 2]), - RSset::from([3]), - RSset::from([1, 2, 3]), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new())) - )) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Set(RSset::new())) - )), - )), - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateOverSet( - Box::new( - Expression::Unary( - Unary::QualifierLabel(QualifierLabel::AvailableEntities), - Box::new(Expression::Var( - AssignmentVariable::Var( - Variable::Id("a".into()) - ) - )) - ) - ) - ), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("c".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - translator.encode("one"); - translator.encode("two"); - translator.encode("three"); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Element(_)))); -} - -#[test] -fn assert_tycheck_for_5() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Label( - Box::new(RSlabel::from(RSset::from([1, 2]), - RSset::from([3]), - RSset::from([1, 2, 3]), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new())) - )) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Integer(0)) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateOverSet( - Box::new( - Expression::Unary( - Unary::QualifierLabel(QualifierLabel::AvailableEntities), - Box::new(Expression::Var( - AssignmentVariable::Var( - Variable::Id("a".into()) - ) - )) - ) - ) - ), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Binary( - Binary::Plus, - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )), - Box::new(Expression::Integer(1)) - )) - )), - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )) - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - translator.encode("one"); - translator.encode("two"); - translator.encode("three"); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(3)))); -} - -#[test] -fn assert_tycheck_for_6() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Label( - Box::new(RSlabel::from(RSset::from([1, 2]), - RSset::from([3]), - RSset::from([1, 2, 3]), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new(), - RSset::new())) - )) - )), - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Set(RSset::from([2]))) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("c".into())), - Box::new(Expression::Integer(0)) - )), - )) - )), - Box::new(Tree::Concat( - Box::new(Tree::For( - Variable::Id("d".into()), - Range::IterateOverSet( - Box::new( - Expression::Binary( - Binary::Plus, - Box::new(Expression::Var( - AssignmentVariable::QualifiedVar( - Variable::Id("a".into()), - QualifierRestricted::Context - ) - )), - Box::new(Expression::Var( - AssignmentVariable::Var( - Variable::Id("b".into()) - ) - )) - ) - ) - ), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("c".into())), - Box::new(Expression::Binary( - Binary::Plus, - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("c".into())) - )), - Box::new(Expression::Integer(1)) - )) - )), - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("c".into())) - )) - )) - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - translator.encode("one"); - translator.encode("two"); - translator.encode("three"); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(2)))); -} - -#[test] -fn assert_tycheck_for_7() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Integer(0)) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Integer(10)) - )), - )), - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateInRange( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )), - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())), - )), - ), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("c".into())) - )) - )), - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(0)))); -} - -#[test] -fn assert_tycheck_for_8() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel}; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Unary( - Unary::Neighbours, - Box::new(Expression::Unary( - Unary::Source, - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Edge) - )) - )) - )) - )), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Integer(0)) - )), - )), - Box::new(Tree::Concat( - Box::new(Tree::For( - Variable::Id("c".into()), - Range::IterateOverSet( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )), - ), - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("b".into())), - Box::new(Expression::Binary( - Binary::Plus, - Box::new(Expression::Var( - AssignmentVariable::Var( - Variable::Id("b".into()) - ) - )), - Box::new(Expression::Integer(1)) - )) - )), - )), - Box::new(Tree::Return( - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("b".into())) - )) - )) - )) - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(1)))); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node(RSsystem::new()); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - let node_3 = graph.add_node(RSsystem::new()); - graph.add_edge(node_1, node_3, RSlabel::new()); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Integer(2)))); -} - -#[test] -fn assert_tycheck_system() { - use super::translator::Translator; - use super::structure::{RSsystem, RSlabel, RSset, RSenvironment, RSprocess}; - use std::rc::Rc; - - let tree = RSassert { - tree: Tree::Concat( - Box::new(Tree::Assignment( - AssignmentVariable::Var(Variable::Id("a".into())), - Box::new(Expression::Unary( - Unary::QualifierSystem(QualifierSystem::Entities), - Box::new(Expression::Unary( - Unary::System, - Box::new(Expression::Unary( - Unary::Target, - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Edge) - )) - )) - )) - )) - )), - Box::new(Tree::Return( - Box::new(Expression::Binary( - Binary::Less, - Box::new(Expression::Var( - AssignmentVariable::Var(Variable::Id("a".into())) - )), - Box::new(Expression::Set(RSset::from([1, 2]))) - )) - )), - ) - }; - assert!(tree.typecheck().is_ok()); - - - let mut translator = Translator::new(); - - let mut graph = petgraph::Graph::new(); - let node_1 = graph.add_node(RSsystem::new()); - let node_2 = graph.add_node( - RSsystem::from( - Rc::new(RSenvironment::new()), - RSset::from([2]), - RSprocess::Nill, - Rc::new(vec![]) - ) - ); - let edge = graph.add_edge(node_1, node_2, RSlabel::new()); - - println!("{:?}", tree.execute(&graph, &edge, &mut translator)); - - assert!(matches!(tree.execute(&graph, &edge, &mut translator), - Ok(AssertReturnValue::Boolean(true)))); -} +include!("assert_tests.rs"); diff --git a/src/rsprocess/assert_fmt.rs b/src/rsprocess/assert_fmt.rs new file mode 100644 index 0000000..fdcd952 --- /dev/null +++ b/src/rsprocess/assert_fmt.rs @@ -0,0 +1,212 @@ +// ----------------------------------------------------------------------------- +// Display Implementation for all types +// ----------------------------------------------------------------------------- + +impl fmt::Display for RSassert { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "label {{\n{}\n}}", self.tree) + } +} + +impl fmt::Display for Tree { + 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 fmt::Display for Variable { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Label => {write!(f, "label")}, + Self::Edge => {write!(f, "edge")}, + Self::Id(s) => {write!(f, "{s}")} + } + } +} + +impl fmt::Display for Expression { + 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 fmt::Display for Range { + 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::Display 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::Qualifier(q) => write!(f, ".{q}"), + Self::ToEl => write!(f, ".toel"), + Self::Source => write!(f, ".source"), + Self::Target => write!(f, ".target"), + Self::Neighbours => write!(f, ".neighbours"), + Self::System => write!(f, ".system"), + } + } +} + +impl fmt::Display 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::Display 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::Display 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::Display 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}"), + } + } +} + +impl fmt::Display 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::Display 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::Display 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"), + } + } +} diff --git a/src/rsprocess/assert_tests.rs b/src/rsprocess/assert_tests.rs new file mode 100644 index 0000000..7426ad4 --- /dev/null +++ b/src/rsprocess/assert_tests.rs @@ -0,0 +1,1442 @@ +// ----------------------------------------------------------------------------- +// Testing +// ----------------------------------------------------------------------------- + +#[test] +fn assert_tycheck_true() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert {tree: Tree::Return(Box::new(Expression::True))}; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_concat_1() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::True))), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_concat_2() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)))), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_return_1() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new(Tree::Return(Box::new(Expression::False))), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_return_incompatible_1() { + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new(Tree::Return(Box::new(Expression::Integer(10)))), + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_return_incompatible_2() { + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new( + Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)))), + Box::new(Tree::Return( + Box::new(Expression::Var(Variable::Id("a".into()))) + ))), + ) + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_return_2() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new( + Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::False))), + Box::new(Tree::Return( + Box::new(Expression::Var(Variable::Id("a".into()))) + ))), + ) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + + +#[test] +fn assert_tycheck_return_3() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::False))), + Box::new(Tree::Return( + Box::new(Expression::Var(Variable::Id("a".into()))) + ))), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(false)))); +} + +#[test] +fn assert_tycheck_if_1() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new( + Tree::If( + Box::new( + Expression::True + ), + Box::new(Tree::Return( + Box::new( + Expression::True) + ) + ) + ), + ) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_if_2() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::If( + Box::new( + Expression::True + ), + Box::new(Tree::Return( + Box::new( + Expression::False) + ) + ) + ), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_ok()); + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(false)))); +} + +#[test] +fn assert_tycheck_if_3() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::If( + Box::new( + Expression::False + ), + Box::new(Tree::Return( + Box::new( + Expression::False) + ) + ) + ), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_if_4() { + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::If( + Box::new( + Expression::Integer(10) + ), + Box::new(Tree::Return( + Box::new( + Expression::True) + ) + ) + ), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_if_else_1() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Return(Box::new(Expression::True))), + Box::new( + Tree::IfElse( + Box::new( + Expression::True + ), + Box::new(Tree::Return( + Box::new( + Expression::True) + )), + Box::new(Tree::Return( + Box::new( + Expression::False) + )), + ), + ) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_if_else_2() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::IfElse( + Box::new( + Expression::False + ), + Box::new(Tree::Return( + Box::new( + Expression::True) + )), + Box::new(Tree::Return( + Box::new( + Expression::False) + )), + ), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(false)))); +} + +#[test] +fn assert_tycheck_if_else_3() { + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::IfElse( + Box::new( + Expression::Integer(10) + ), + Box::new(Tree::Return( + Box::new( + Expression::True) + )), + Box::new(Tree::Return( + Box::new( + Expression::False) + )), + ), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_if_else_4() { + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::IfElse( + Box::new( + Expression::True + ), + Box::new(Tree::Return( + Box::new( + Expression::True) + )), + Box::new(Tree::Return( + Box::new( + Expression::Integer(10)) + )), + ), + ), + Box::new(Tree::Return(Box::new(Expression::True))), + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_assignment_1() { + let tree = RSassert { + tree: Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::True) + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_assignment_2() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::True) + ) + ), + Box::new( + Tree::Return( + Box::new( + Expression::True + ) + ) + ), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_assignment_3() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::False) + ) + ), + Box::new( + Tree::Return( + Box::new( + Expression::Var( + Variable::Id("a".into()) + ) + ) + ) + ), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(false)))); +} + +#[test] +fn assert_tycheck_assignment_4() { + let tree = RSassert { + tree: Tree::Concat( + Box::new( + Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::True) + ) + ), + Box::new( + Tree::Return( + Box::new( + Expression::Var( + Variable::Id("b".into()) + ) + ) + ) + ), + ) + }; + assert!(tree.typecheck().is_err()); +} + +#[test] +fn assert_tycheck_assignment_5() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)) + )), + Box::new(Tree::Concat( + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(10)))); +} + +#[test] +fn assert_tycheck_assignment_6() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Integer(200)) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(10)))); +} + +#[test] +fn assert_tycheck_assignment_7() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)) + )), + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::True) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + Box::new(Tree::Return( + Box::new(Expression::False) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} + +#[test] +fn assert_tycheck_assignment_8() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(10)))); +} + +#[test] +fn assert_tycheck_assignment_9() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )), + Box::new(Tree::Return( + Box::new(Expression::Integer(200)) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(10)))); +} + +#[test] +fn assert_tycheck_assignment_10() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(10)) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(200)) + )), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(10)))); +} + + +#[test] +fn assert_tycheck_for_1() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Set(RSset::new())) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Set(RSset::new())) + )), + )), + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateOverSet( + Box::new( + Expression::Var( + Variable::Id("a".into()), + ) + ) + ), + Box::new(Tree::Return( + Box::new(Expression::Integer(200)) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(tree.execute(&graph, &edge, &mut translator).is_err()); +} + + +#[test] +fn assert_tycheck_for_2() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Set(RSset::from([1, 2]))) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Set(RSset::new())) + )), + )), + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateOverSet( + Box::new( + Expression::Var( + Variable::Id("a".into()) + ) + ) + ), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + translator.encode("one"); + translator.encode("two"); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Set(_)))); +} + +#[test] +fn assert_tycheck_for_3() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Label( + Box::new(RSlabel::from(RSset::from([1, 2]), + RSset::new(), + RSset::from([1, 2]), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new())) + )) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Set(RSset::new())) + )), + )), + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateOverSet( + Box::new( + Expression::Unary( + Unary::Qualifier(Qualifier::Restricted( + QualifierRestricted::Entities + )), + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + ) + ) + ), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + translator.encode("one"); + translator.encode("two"); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Set(_)))); +} + +#[test] +fn assert_tycheck_for_4() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Label( + Box::new(RSlabel::from(RSset::from([1, 2]), + RSset::from([3]), + RSset::from([1, 2, 3]), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new())) + )) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Set(RSset::new())) + )), + )), + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateOverSet( + Box::new( + Expression::Unary( + Unary::Qualifier(Qualifier::Label( + QualifierLabel::AvailableEntities + )), + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + ) + ) + ), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("c".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + translator.encode("one"); + translator.encode("two"); + translator.encode("three"); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Element(_)))); +} + +#[test] +fn assert_tycheck_for_5() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Label( + Box::new(RSlabel::from(RSset::from([1, 2]), + RSset::from([3]), + RSset::from([1, 2, 3]), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new())) + )) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Integer(0)) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateOverSet( + Box::new( + Expression::Unary( + Unary::Qualifier(Qualifier::Label( + QualifierLabel::AvailableEntities + )), + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + ) + ) + ), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Binary( + Binary::Plus, + Box::new(Expression::Var( + Variable::Id("b".into()) + )), + Box::new(Expression::Integer(1)) + )) + )), + )), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + )) + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + translator.encode("one"); + translator.encode("two"); + translator.encode("three"); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(3)))); +} + +#[test] +fn assert_tycheck_for_6() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Label( + Box::new(RSlabel::from(RSset::from([1, 2]), + RSset::from([3]), + RSset::from([1, 2, 3]), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new(), + RSset::new())) + )) + )), + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Set(RSset::from([2]))) + )), + Box::new(Tree::Assignment( + Variable::Id("c".into()), + None, + Box::new(Expression::Integer(0)) + )), + )) + )), + Box::new(Tree::Concat( + Box::new(Tree::For( + Variable::Id("d".into()), + Range::IterateOverSet( + Box::new( + Expression::Binary( + Binary::Plus, + Box::new(Expression::Unary( + Unary::Qualifier(Qualifier::Restricted( + QualifierRestricted::Context + )), + Box::new(Expression::Var( + Variable::Id("a".into()) + )) + ) + ), + Box::new(Expression::Var( + Variable::Id("b".into()) + )) + ) + ) + ), + Box::new(Tree::Assignment( + Variable::Id("c".into()), + None, + Box::new(Expression::Binary( + Binary::Plus, + Box::new(Expression::Var(Variable::Id("c".into()))), + Box::new(Expression::Integer(1)) + )) + )), + )), + Box::new(Tree::Return( + Box::new(Expression::Var(Variable::Id("c".into()))) + )) + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + translator.encode("one"); + translator.encode("two"); + translator.encode("three"); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(2)))); +} + +#[test] +fn assert_tycheck_for_7() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Integer(0)) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Integer(10)) + )), + )), + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateInRange( + Box::new(Expression::Var( + Variable::Id("a".into()) + )), + Box::new(Expression::Var( + Variable::Id("b".into()), + )), + ), + Box::new(Tree::Return( + Box::new(Expression::Var( + Variable::Id("c".into()) + )) + )), + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(0)))); +} + +#[test] +fn assert_tycheck_for_8() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel}; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Unary( + Unary::Neighbours, + Box::new(Expression::Unary( + Unary::Source, + Box::new(Expression::Var(Variable::Edge)) + )) + )) + )), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Integer(0)) + )), + )), + Box::new(Tree::Concat( + Box::new(Tree::For( + Variable::Id("c".into()), + Range::IterateOverSet( + Box::new(Expression::Var( + Variable::Id("a".into()) + )), + ), + Box::new(Tree::Assignment( + Variable::Id("b".into()), + None, + Box::new(Expression::Binary( + Binary::Plus, + Box::new(Expression::Var(Variable::Id("b".into()))), + Box::new(Expression::Integer(1)) + )) + )), + )), + Box::new(Tree::Return( + Box::new(Expression::Var(Variable::Id("b".into()))) + )) + )) + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(1)))); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node(RSsystem::new()); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + let node_3 = graph.add_node(RSsystem::new()); + graph.add_edge(node_1, node_3, RSlabel::new()); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Integer(2)))); +} + +#[test] +fn assert_tycheck_system() { + use super::translator::Translator; + use super::structure::{RSsystem, RSlabel, RSset, RSenvironment, RSprocess}; + use std::rc::Rc; + + let tree = RSassert { + tree: Tree::Concat( + Box::new(Tree::Assignment( + Variable::Id("a".into()), + None, + Box::new(Expression::Unary( + Unary::Qualifier( + Qualifier::System(QualifierSystem::Entities) + ), + Box::new(Expression::Unary( + Unary::System, + Box::new(Expression::Unary( + Unary::Target, + Box::new(Expression::Var(Variable::Edge)) + )) + )) + )) + )), + Box::new(Tree::Return( + Box::new(Expression::Binary( + Binary::Less, + Box::new(Expression::Var( + Variable::Id("a".into()) + )), + Box::new(Expression::Set(RSset::from([1, 2]))) + )) + )), + ) + }; + assert!(tree.typecheck().is_ok()); + + + let mut translator = Translator::new(); + + let mut graph = petgraph::Graph::new(); + let node_1 = graph.add_node(RSsystem::new()); + let node_2 = graph.add_node( + RSsystem::from( + Rc::new(RSenvironment::new()), + RSset::from([2]), + RSprocess::Nill, + Rc::new(vec![]) + ) + ); + let edge = graph.add_edge(node_1, node_2, RSlabel::new()); + + println!("{:?}", tree.execute(&graph, &edge, &mut translator)); + + assert!(matches!(tree.execute(&graph, &edge, &mut translator), + Ok(AssertReturnValue::Boolean(true)))); +} diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index 613d856..f063697 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -5,7 +5,7 @@ use crate::rsprocess::structure::{RSset, RSprocess, RSenvironment, RSsystem, - RSlabel, +// RSlabel, RSreaction}; use crate::rsprocess::structure::assert; use crate::rsprocess::translator::{Translator, IdType}; @@ -180,164 +180,174 @@ Env_term: (IdType, RSprocess) = { // ----------------------------------------------------------------------------- // AssertParser // ----------------------------------------------------------------------------- -pub Assert: Box = { - "label" "{" "}" => - Box::new(assert::RSassert{tree: f}), -}; +// pub Assert: Box = { +// "label" "{" "}" => +// Box::new(assert::RSassert{tree: f}), +// }; -AssertTree: assert::Tree = { - ";" => - assert::Tree::Concat(Box::new(t1), Box::new(t2)), - => t, -} +// AssertTree: assert::Tree = { +// ";" => +// assert::Tree::Concat(Box::new(t1), Box::new(t2)), +// => t, +// } -AssertTree2: assert::Tree = { - "if" - "then" "{" "}" => - assert::Tree::If(Box::new(e), Box::new(t)), +// AssertTree2: assert::Tree = { +// "if" +// "then" "{" "}" => +// assert::Tree::If(Box::new(e), Box::new(t)), - "if" - "then" "{" "}" - "else" "{" "}" => - assert::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), +// "if" +// "then" "{" "}" +// "else" "{" "}" => +// assert::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)), - "let" "=" => - assert::Tree::Assignment(v, Box::new(e)), +// "let" "=" => +// assert::Tree::Assignment(v, q, Box::new(e)), - "return" => - assert::Tree::Return(Box::new(e)), +// "return" => +// assert::Tree::Return(Box::new(e)), - "for" "in" "{" "}" => - assert::Tree::For(v, r, Box::new(t)), -} +// "for" "in" "{" "}" => +// assert::Tree::For(v, r, Box::new(t)), +// } -AssertAssignmentVar: assert::AssignmentVariable = { - => assert::AssignmentVariable::Var(v), - "." => - assert::AssignmentVariable::QualifiedVar(v, q), -} +// AssertQualifierLet: assert::Qualifier { +// "Entities" => assert::QualifierRestricted::Entities, +// "Context" => assert::QualifierRestricted::Context, +// "Reactants" => assert::QualifierRestricted::Reactants, +// "ReactantsAbsent" => assert::QualifierRestricted::ReactantsAbsent, +// "Inhibitors" => assert::QualifierRestricted::Inhibitors, +// "InhibitorsPresent" => assert::QualifierRestricted::InhibitorsPresent, +// "Products" => assert::QualifierRestricted::Products, +// } -AssertVariable: assert::Variable = { - "label" => assert::Variable::Label, - "edge" => assert::Variable::Edge, - => assert::Variable::Id(v), -} +// AssertAssignmentVar: assert::AssignmentVariable = { +// => assert::AssignmentVariable::Var(v), +// "." => +// assert::AssignmentVariable::QualifiedVar(v, q), +// } -AssertExpression: assert::Expression = { - => - assert::Expression::Unary(unp, Box::new(e)), - "(" ")" => - assert::Expression::Unary(uns, Box::new(e)), +// AssertVariable: assert::Variable = { +// "label" => assert::Variable::Label, +// "edge" => assert::Variable::Edge, +// => assert::Variable::Id(v), +// } - "(" ")" => - assert::Expression::Binary(b, Box::new(e1), Box::new(e2)), - - "(" "," ")" => - assert::Expression::Binary(b, Box::new(e1), Box::new(e2)), +// AssertExpression: assert::Expression = { +// => +// assert::Expression::Unary(unp, Box::new(e)), +// "(" ")" => +// assert::Expression::Unary(uns, Box::new(e)), - "(" ")" => e, - "true" => assert::Expression::True, - "false" => assert::Expression::False, +// "(" ")" => +// assert::Expression::Binary(b, Box::new(e1), Box::new(e2)), +// +// "(" "," ")" => +// assert::Expression::Binary(b, Box::new(e1), Box::new(e2)), - => assert::Expression::Var(v), +// "(" ")" => e, +// "true" => assert::Expression::True, +// "false" => assert::Expression::False, - // If changing IntegerType in assert.rs, also change from Num to another - // similar parser with different return type - => assert::Expression::Integer(i), +// => assert::Expression::Var(v), - => assert::Expression::Label(Box::new(lab)), - => assert::Expression::Set(set), - "'" "'" => assert::Expression::Element(translator.encode(el)), +// // If changing IntegerType in assert.rs, also change from Num to another +// // similar parser with different return type +// => assert::Expression::Integer(i), - // strings - PATH => assert::Expression::String(<>.trim_end_matches("\"") - .trim_start_matches("\"") - .to_string()), -} +// => assert::Expression::Label(Box::new(lab)), +// => assert::Expression::Set(set), +// "'" "'" => assert::Expression::Element(translator.encode(el)), -AssertUnaryPrefix: assert::Unary = { - "not" => assert::Unary::Not, - "rand" => assert::Unary::Rand, -} +// // strings +// PATH => assert::Expression::String(<>.trim_end_matches("\"") +// .trim_start_matches("\"") +// .to_string()), +// } -AssertUnarySuffix: assert::Unary = { - ".empty" => assert::Unary::Empty, - ".length" => assert::Unary::Length, - ".tostr" => assert::Unary::ToStr, - ".toel" => assert::Unary::ToEl, - ".source" => assert::Unary::Source, - ".target" => assert::Unary::Target, - ".neighbours" => assert::Unary::Neighbours, - ".system" => assert::Unary::System, - "." => assert::Unary::QualifierLabel(q), - "." => assert::Unary::QualifierSystem(q), -} +// AssertUnaryPrefix: assert::Unary = { +// "not" => assert::Unary::Not, +// "rand" => assert::Unary::Rand, +// } -AssertBinary: assert::Binary = { - "&&" => assert::Binary::And, - "||" => assert::Binary::Or, - "^^" => assert::Binary::Xor, - "<" => assert::Binary::Less, - "<=" => assert::Binary::LessEq, - ">" => assert::Binary::More, - ">=" => assert::Binary::MoreEq, - "==" => assert::Binary::Eq, - "!=" => assert::Binary::NotEq, - "+" => assert::Binary::Plus, - "-" => assert::Binary::Minus, - "*" => assert::Binary::Times, - "^" => assert::Binary::Exponential, - "/" => assert::Binary::Quotient, - "%" => assert::Binary::Reminder, - "::" => assert::Binary::Concat, -} +// AssertUnarySuffix: assert::Unary = { +// ".empty" => assert::Unary::Empty, +// ".length" => assert::Unary::Length, +// ".tostr" => assert::Unary::ToStr, +// ".toel" => assert::Unary::ToEl, +// ".source" => assert::Unary::Source, +// ".target" => assert::Unary::Target, +// ".neighbours" => assert::Unary::Neighbours, +// ".system" => assert::Unary::System, +// "." => assert::Unary::QualifierLabel(q), +// "." => assert::Unary::QualifierSystem(q), +// } -AssertBinaryPrefix: assert::Binary = { - "substr" => assert::Binary::SubStr, - "min" => assert::Binary::Min, - "max" => assert::Binary::Max, - "commonsubstr" => assert::Binary::CommonSubStr, -} +// AssertBinary: assert::Binary = { +// "&&" => assert::Binary::And, +// "||" => assert::Binary::Or, +// "^^" => assert::Binary::Xor, +// "<" => assert::Binary::Less, +// "<=" => assert::Binary::LessEq, +// ">" => assert::Binary::More, +// ">=" => assert::Binary::MoreEq, +// "==" => assert::Binary::Eq, +// "!=" => assert::Binary::NotEq, +// "+" => assert::Binary::Plus, +// "-" => assert::Binary::Minus, +// "*" => assert::Binary::Times, +// "^" => assert::Binary::Exponential, +// "/" => assert::Binary::Quotient, +// "%" => assert::Binary::Reminder, +// "::" => assert::Binary::Concat, +// } -AssertQualifierSystem: assert::QualifierSystem = { - "SystemEntities" => assert::QualifierSystem::Entities, - "SystemContext" => assert::QualifierSystem::Context, -} +// AssertBinaryPrefix: assert::Binary = { +// "substr" => assert::Binary::SubStr, +// "min" => assert::Binary::Min, +// "max" => assert::Binary::Max, +// "commonsubstr" => assert::Binary::CommonSubStr, +// } -AssertQualifierLabel: assert::QualifierLabel = { - "AvailableEntities" => assert::QualifierLabel::AvailableEntities, - "AllReactants" => assert::QualifierLabel::AllReactants, - "AllInhibitors" => assert::QualifierLabel::AllInhibitors, - => assert::QualifierLabel::Restricted(q), -} +// AssertQualifierSystem: assert::QualifierSystem = { +// "SystemEntities" => assert::QualifierSystem::Entities, +// "SystemContext" => assert::QualifierSystem::Context, +// } -AssertQualifierRestricted: assert::QualifierRestricted = { - "Entities" => assert::QualifierRestricted::Entities, - "Context" => assert::QualifierRestricted::Context, - "Reactants" => assert::QualifierRestricted::Reactants, - "ReactantsAbsent" => assert::QualifierRestricted::ReactantsAbsent, - "Inhibitors" => assert::QualifierRestricted::Inhibitors, - "InhibitorsPresent" => assert::QualifierRestricted::InhibitorsPresent, - "Products" => assert::QualifierRestricted::Products, -} +// AssertQualifierLabel: assert::QualifierLabel = { +// "AvailableEntities" => assert::QualifierLabel::AvailableEntities, +// "AllReactants" => assert::QualifierLabel::AllReactants, +// "AllInhibitors" => assert::QualifierLabel::AllInhibitors, +// => assert::QualifierLabel::Restricted(q), +// } -AssertLabel: RSlabel = { - "[" - "Entities" ":" "," - "Context" ":" "," - "Reactants" ":" "," - "ReactantsAbsent" ":" "," - "Inhibitors" ":" "," - "InhibitorsPresent" ":" "," - "Products" ":" "," - "]" => RSlabel::create(e, c, r, r_a, i, i_p, p) -} +// AssertQualifierRestricted: assert::QualifierRestricted = { +// "Entities" => assert::QualifierRestricted::Entities, +// "Context" => assert::QualifierRestricted::Context, +// "Reactants" => assert::QualifierRestricted::Reactants, +// "ReactantsAbsent" => assert::QualifierRestricted::ReactantsAbsent, +// "Inhibitors" => assert::QualifierRestricted::Inhibitors, +// "InhibitorsPresent" => assert::QualifierRestricted::InhibitorsPresent, +// "Products" => assert::QualifierRestricted::Products, +// } -AssertRange: assert::Range = { - "{" "}" => assert::Range::IterateOverSet(Box::new(e)), - "{" ".." "}" => - assert::Range::IterateInRange(Box::new(e1), Box::new(e2)), -} +// AssertLabel: RSlabel = { +// "[" +// "Entities" ":" "," +// "Context" ":" "," +// "Reactants" ":" "," +// "ReactantsAbsent" ":" "," +// "Inhibitors" ":" "," +// "InhibitorsPresent" ":" "," +// "Products" ":" "," +// "]" => RSlabel::create(e, c, r, r_a, i, i_p, p) +// } + +// AssertRange: assert::Range = { +// "{" "}" => assert::Range::IterateOverSet(Box::new(e)), +// "{" ".." "}" => +// assert::Range::IterateInRange(Box::new(e1), Box::new(e2)), +// } // ----------------------------------------------------------------------------- @@ -727,9 +737,16 @@ Instruction: presets::Instruction = { presets::Instruction::FastFrequency { experiment: p, so }, "Digraph" ">" > => presets::Instruction::Digraph { gso }, - "Bisimilarity" "(" ")" "relabel" + // + "Bisimilarity" "(" ")" "relabel" ">" => - presets::Instruction::Bisimilarity { system_b: p, edge_relabeler, so }, + presets::Instruction::Bisimilarity { + system_b: p, + edge_relabeler: Box::new(assert::RSassert { + tree: assert::Tree::Return(Box::new(assert::Expression::True)) + }), + so + }, } pub Run: presets::Instructions = {