Version two of assert, now with parser
This commit is contained in:
@ -1,5 +1,8 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
// If changing IntegerType in assert.rs, also change from Num to another
|
||||||
|
// similar parser with different return type in grammar.lalrpop in
|
||||||
|
// AssertExpression
|
||||||
type IntegerType = i64;
|
type IntegerType = i64;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -10,126 +13,65 @@ pub struct RSassert {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Tree {
|
pub enum Tree {
|
||||||
Concat(Box<Tree>, Box<Tree>),
|
Concat(Box<Tree>, Box<Tree>),
|
||||||
If(Box<Boolean>, Box<Tree>),
|
If(Box<Expression>, Box<Tree>),
|
||||||
IfElse(Box<Boolean>, Box<Tree>, Box<Tree>),
|
IfElse(Box<Expression>, Box<Tree>, Box<Tree>),
|
||||||
Assignment(AssignmentVar, Box<Expression>),
|
Assignment(AssignmentVariable, Box<Expression>),
|
||||||
Return(Box<Expression>),
|
Return(Box<Expression>),
|
||||||
For(Variable, Range, Box<Tree>),
|
For(Variable, Range, Box<Tree>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expression {
|
pub struct Variable {
|
||||||
B(Boolean),
|
data: String,
|
||||||
A(Arithmetic),
|
}
|
||||||
Lab(Label),
|
|
||||||
Set(Set),
|
|
||||||
El(Element),
|
|
||||||
Str(Str),
|
|
||||||
|
|
||||||
Var(Variable), // for when the type should just be passed through
|
impl Variable {
|
||||||
|
pub fn from(data: String) -> Self {
|
||||||
|
Self { data }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Boolean {
|
pub enum AssignmentVariable {
|
||||||
Var(Variable), // should be of type boolean
|
Var(Variable),
|
||||||
|
QualifiedVar(Variable, QualifierRestricted)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Expression {
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
Not(Box<Boolean>),
|
|
||||||
And(Box<Boolean>, Box<Boolean>),
|
|
||||||
Or(Box<Boolean>, Box<Boolean>),
|
|
||||||
Xor(Box<Boolean>, Box<Boolean>),
|
|
||||||
|
|
||||||
Less(Arithmetic, Arithmetic),
|
|
||||||
LessEq(Arithmetic, Arithmetic),
|
|
||||||
More(Arithmetic, Arithmetic),
|
|
||||||
MoreEq(Arithmetic, Arithmetic),
|
|
||||||
Eq(Arithmetic, Arithmetic),
|
|
||||||
NotEq(Arithmetic, Arithmetic),
|
|
||||||
|
|
||||||
LabelEq(Label, Label),
|
|
||||||
LabelNotEq(Label, Label),
|
|
||||||
|
|
||||||
SetSub(Set, Set),
|
|
||||||
SetSubEq(Set, Set),
|
|
||||||
SetSuper(Set, Set),
|
|
||||||
SetSuperEq(Set, Set),
|
|
||||||
SetEq(Set, Set),
|
|
||||||
SetEmpty(Set),
|
|
||||||
|
|
||||||
ElEq(Element, Element),
|
|
||||||
ElNotEq(Element, Element),
|
|
||||||
|
|
||||||
StrEq(Str, Str),
|
|
||||||
StrNotEq(Str, Str),
|
|
||||||
StrSubstring(Str, Str),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Arithmetic {
|
|
||||||
Var(Variable), // should be of type arithmetic
|
|
||||||
Integer(IntegerType),
|
Integer(IntegerType),
|
||||||
Plus(Box<Arithmetic>, Box<Arithmetic>),
|
Label(Box<super::structure::RSlabel>),
|
||||||
Minus(Box<Arithmetic>, Box<Arithmetic>),
|
Set(super::structure::RSset),
|
||||||
Times(Box<Arithmetic>, Box<Arithmetic>),
|
Element(super::translator::IdType),
|
||||||
Quotient(Box<Arithmetic>, Box<Arithmetic>),
|
String(String),
|
||||||
Reminder(Box<Arithmetic>, Box<Arithmetic>),
|
Var(AssignmentVariable),
|
||||||
Exponential(Box<Arithmetic>, Box<Arithmetic>),
|
|
||||||
Rand(Box<Arithmetic>, Box<Arithmetic>),
|
|
||||||
Min(Box<Arithmetic>, Box<Arithmetic>),
|
|
||||||
Max(Box<Arithmetic>, Box<Arithmetic>),
|
|
||||||
|
|
||||||
SetLength(Set),
|
Unary(Unary, Box<Expression>),
|
||||||
StrLength(Str),
|
Binary(Binary, Box<Expression>, Box<Expression>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Label {
|
pub enum Range {
|
||||||
Var(Variable), // should be of type label
|
IterateOverSet(Box<Expression>),
|
||||||
Literal(Box<super::structure::RSlabel>),
|
IterateInRange(Box<Expression>, Box<Expression>),
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Set {
|
|
||||||
Var(Variable), // should be of type set
|
|
||||||
Literal(super::structure::RSset),
|
|
||||||
Append(Box<Set>, Element),
|
|
||||||
Union(Box<Set>, Box<Set>),
|
|
||||||
Intersection(Box<Set>, Box<Set>),
|
|
||||||
Difference(Box<Set>, Box<Set>),
|
|
||||||
SimmetricDifference(Box<Set>, Box<Set>),
|
|
||||||
ValueOfLabel(Label, Qualifier),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Element {
|
|
||||||
Var(Variable), // should be of type element
|
|
||||||
Literal(super::translator::IdType),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Str {
|
|
||||||
Var(Variable), // should be of type string
|
|
||||||
Literal(String),
|
|
||||||
Concat(Box<Str>, Box<Str>),
|
|
||||||
ArithmeticToString(Box<Arithmetic>),
|
|
||||||
BooleanToString(Box<Boolean>),
|
|
||||||
ElementToString(Element),
|
|
||||||
CommonSubstring(Box<Str>, Box<Str>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum AssignmentVar {
|
|
||||||
Var(Variable),
|
|
||||||
ValueOfVariable(Variable, QualifierAssignment),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Variable {
|
|
||||||
name: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum QualifierAssignment {
|
pub enum Unary {
|
||||||
|
Not,
|
||||||
|
Rand,
|
||||||
|
|
||||||
|
Empty,
|
||||||
|
Length,
|
||||||
|
ToStr,
|
||||||
|
Qualifier(Qualifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum QualifierRestricted {
|
||||||
Entities,
|
Entities,
|
||||||
Context,
|
Context,
|
||||||
Reactants,
|
Reactants,
|
||||||
@ -141,23 +83,33 @@ pub enum QualifierAssignment {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Qualifier {
|
pub enum Qualifier {
|
||||||
Entities,
|
|
||||||
Context,
|
|
||||||
AvailableEntities,
|
AvailableEntities,
|
||||||
|
|
||||||
Reactants,
|
|
||||||
ReactantsAbsent,
|
|
||||||
AllReactants,
|
AllReactants,
|
||||||
|
|
||||||
Inhibitors,
|
|
||||||
InhibitorsPresent,
|
|
||||||
AllInhibitors,
|
AllInhibitors,
|
||||||
|
Restricted(QualifierRestricted),
|
||||||
Products,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Range {
|
pub enum Binary {
|
||||||
IterateOverSet(Set),
|
And,
|
||||||
IterateInRange(Box<Arithmetic>, Box<Arithmetic>),
|
Or,
|
||||||
|
Xor,
|
||||||
|
Less,
|
||||||
|
LessEq,
|
||||||
|
More,
|
||||||
|
MoreEq,
|
||||||
|
Eq,
|
||||||
|
NotEq,
|
||||||
|
Plus,
|
||||||
|
Minus,
|
||||||
|
Times,
|
||||||
|
Exponential,
|
||||||
|
Quotient,
|
||||||
|
Reminder,
|
||||||
|
Concat,
|
||||||
|
|
||||||
|
SubStr,
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
CommonSubStr,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,9 @@ use crate::rsprocess::structure::{RSset,
|
|||||||
RSprocess,
|
RSprocess,
|
||||||
RSenvironment,
|
RSenvironment,
|
||||||
RSsystem,
|
RSsystem,
|
||||||
|
RSlabel,
|
||||||
RSreaction};
|
RSreaction};
|
||||||
|
use crate::rsprocess::structure::assert;
|
||||||
use crate::rsprocess::translator::{Translator, IdType};
|
use crate::rsprocess::translator::{Translator, IdType};
|
||||||
use crate::rsprocess::presets::Instructions;
|
use crate::rsprocess::presets::Instructions;
|
||||||
use crate::rsprocess::presets;
|
use crate::rsprocess::presets;
|
||||||
@ -120,6 +122,7 @@ Reaction: RSreaction = {
|
|||||||
RSreaction::from(r, i, p),
|
RSreaction::from(r, i, p),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// ContextParser
|
// ContextParser
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -152,6 +155,7 @@ CTX_process: RSprocess = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// EnvironmentParser
|
// EnvironmentParser
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -165,28 +169,154 @@ Env_term: (IdType, RSprocess) = {
|
|||||||
(translator.encode(identifier), k)
|
(translator.encode(identifier), k)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// AssertParser
|
// AssertParser
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// pub Assert: Box<RSassert> = {
|
pub Assert: Box<assert::RSassert> = {
|
||||||
// <f: Formula_Assert> => Box::new(f)
|
"fn" "{" <f: AssertTree> "}" =>
|
||||||
// };
|
Box::new(assert::RSassert{tree: f}),
|
||||||
|
};
|
||||||
|
|
||||||
|
AssertTree: assert::Tree = {
|
||||||
|
<t1: AssertTree2> ";" <t2: AssertTree> =>
|
||||||
|
assert::Tree::Concat(Box::new(t1), Box::new(t2)),
|
||||||
|
<t: AssertTree2> => t,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertTree2: assert::Tree = {
|
||||||
|
"if" <e: AssertExpression>
|
||||||
|
"then" "{" <t: AssertTree> "}" =>
|
||||||
|
assert::Tree::If(Box::new(e), Box::new(t)),
|
||||||
|
|
||||||
|
"if" <e: AssertExpression>
|
||||||
|
"then" "{" <t1: AssertTree> "}"
|
||||||
|
"else" "{" <t2: AssertTree> "}" =>
|
||||||
|
assert::Tree::IfElse(Box::new(e), Box::new(t1), Box::new(t2)),
|
||||||
|
|
||||||
|
"let" <v: AssertAssignmentVar> "=" <e: AssertExpression> =>
|
||||||
|
assert::Tree::Assignment(v, Box::new(e)),
|
||||||
|
|
||||||
|
"return" <e: AssertExpression> =>
|
||||||
|
assert::Tree::Return(Box::new(e)),
|
||||||
|
|
||||||
|
"for" <v: AssertVariable> "in" <r: AssertRange> "{" <t: AssertTree> "}" =>
|
||||||
|
assert::Tree::For(v, r, Box::new(t)),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertAssignmentVar: assert::AssignmentVariable = {
|
||||||
|
<v: AssertVariable> => assert::AssignmentVariable::Var(v),
|
||||||
|
<v: AssertVariable> "." <q: AssertQualifierRestricted> =>
|
||||||
|
assert::AssignmentVariable::QualifiedVar(v, q),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertVariable: assert::Variable = {
|
||||||
|
<v: Literal> => assert::Variable::from(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertExpression: assert::Expression = {
|
||||||
|
"(" <e: AssertExpression> ")" => 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
|
||||||
|
<i: Num> => assert::Expression::Integer(i),
|
||||||
|
|
||||||
|
<lab: AssertLabel> => assert::Expression::Label(Box::new(lab)),
|
||||||
|
<set: Set_of_entities> => assert::Expression::Set(set),
|
||||||
|
"'" <el: Literal> "'" => assert::Expression::Element(translator.encode(el)),
|
||||||
|
|
||||||
|
// strings
|
||||||
|
PATH => assert::Expression::String(<>.trim_end_matches("\"")
|
||||||
|
.trim_start_matches("\"")
|
||||||
|
.to_string()),
|
||||||
|
|
||||||
|
<unp: AssertUnaryPrefix> <e: AssertExpression> =>
|
||||||
|
assert::Expression::Unary(unp, Box::new(e)),
|
||||||
|
"(" <e: AssertExpression> ")" <uns: AssertUnarySuffix> =>
|
||||||
|
assert::Expression::Unary(uns, Box::new(e)),
|
||||||
|
|
||||||
|
"(" <e1: AssertExpression> <b: AssertBinary> <e2: AssertExpression> ")" =>
|
||||||
|
assert::Expression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||||
|
<b: AssertBinaryPrefix>
|
||||||
|
"(" <e1: AssertExpression> "," <e2: AssertExpression> ")" =>
|
||||||
|
assert::Expression::Binary(b, Box::new(e1), Box::new(e2)),
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertUnaryPrefix: assert::Unary = {
|
||||||
|
"not" => assert::Unary::Not,
|
||||||
|
"rand" => assert::Unary::Rand,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertUnarySuffix: assert::Unary = {
|
||||||
|
".empty" => assert::Unary::Empty,
|
||||||
|
".length" => assert::Unary::Length,
|
||||||
|
".tostr" => assert::Unary::ToStr,
|
||||||
|
"." <q: AssertQualifier> => assert::Unary::Qualifier(q),
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertBinaryPrefix: assert::Binary = {
|
||||||
|
"substr" => assert::Binary::SubStr,
|
||||||
|
"min" => assert::Binary::Min,
|
||||||
|
"max" => assert::Binary::Max,
|
||||||
|
"commonsubstr" => assert::Binary::CommonSubStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertQualifier: assert::Qualifier = {
|
||||||
|
"AvailableEntities" => assert::Qualifier::AvailableEntities,
|
||||||
|
"AllReactants" => assert::Qualifier::AllReactants,
|
||||||
|
"AllInhibitors" => assert::Qualifier::AllInhibitors,
|
||||||
|
<q: AssertQualifierRestricted> => assert::Qualifier::Restricted(q),
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertLabel: RSlabel = {
|
||||||
|
"["
|
||||||
|
"Entities" ":" <e: Set_of_entities> ","
|
||||||
|
"Context" ":" <c: Set_of_entities> ","
|
||||||
|
"Reactants" ":" <r: Set_of_entities> ","
|
||||||
|
"ReactantsAbsent" ":" <r_a: Set_of_entities> ","
|
||||||
|
"Inhibitors" ":" <i: Set_of_entities> ","
|
||||||
|
"InhibitorsPresent" ":" <i_p: Set_of_entities> ","
|
||||||
|
"Products" ":" <p: Set_of_entities> ","
|
||||||
|
"]" => RSlabel::create(e, c, r, r_a, i, i_p, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertRange: assert::Range = {
|
||||||
|
"{" <e: AssertExpression> "}" => assert::Range::IterateOverSet(Box::new(e)),
|
||||||
|
"{" <e1: AssertExpression> ".." <e2: AssertExpression> "}" =>
|
||||||
|
assert::Range::IterateInRange(Box::new(e1), Box::new(e2)),
|
||||||
|
}
|
||||||
|
|
||||||
// Formula_Assert: RSassert = {
|
|
||||||
// "-" <f: Formula_Assert> => RSassert::Not(Box::new(f)),
|
|
||||||
// "(" <f1: Formula_Assert> "^" <f2: Formula_Assert> ")" =>
|
|
||||||
// RSassert::Xor(Box::new(f1), Box::new(f2)),
|
|
||||||
// "(" <f: Separated<Formula_Assert, "\\/">> ")" => RSassert::Or(f),
|
|
||||||
// "(" <f: Separated<Formula_Assert, "/\\">> ")" => RSassert::And(f),
|
|
||||||
// <c: Set_of_entities> "inW" => RSassert::Sub(c, RSassertOp::InW),
|
|
||||||
// <c: Set_of_entities> "inR" => RSassert::Sub(c, RSassertOp::InR),
|
|
||||||
// <c: Set_of_entities> "inI" => RSassert::Sub(c, RSassertOp::InI),
|
|
||||||
// <c: Set_of_entities> "inP" => RSassert::Sub(c, RSassertOp::InP),
|
|
||||||
// "?" "inW" => RSassert::NonEmpty(RSassertOp::InW),
|
|
||||||
// "?" "inR" => RSassert::NonEmpty(RSassertOp::InR),
|
|
||||||
// "?" "inI" => RSassert::NonEmpty(RSassertOp::InI),
|
|
||||||
// "?" "inP" => RSassert::NonEmpty(RSassertOp::InP),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// BHMLParser
|
// BHMLParser
|
||||||
@ -272,7 +402,9 @@ LiteralSeparatorNode: graph::NodeDisplayBase = {
|
|||||||
LiteralSeparatorEdge: graph::EdgeDisplayBase = {
|
LiteralSeparatorEdge: graph::EdgeDisplayBase = {
|
||||||
PATH =>
|
PATH =>
|
||||||
graph::EdgeDisplayBase::String {
|
graph::EdgeDisplayBase::String {
|
||||||
string: <>.trim_end_matches("\"").trim_start_matches("\"").to_string()
|
string: <>.trim_end_matches("\"")
|
||||||
|
.trim_start_matches("\"")
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -551,6 +551,28 @@ impl RSlabel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn create(
|
||||||
|
available_entities: RSset,
|
||||||
|
context: RSset,
|
||||||
|
reactants: RSset,
|
||||||
|
reactants_absent: RSset,
|
||||||
|
inhibitors: RSset,
|
||||||
|
inhibitors_present: RSset,
|
||||||
|
products: RSset,
|
||||||
|
) -> Self {
|
||||||
|
RSlabel {
|
||||||
|
available_entities: available_entities.clone(),
|
||||||
|
context: context.clone(),
|
||||||
|
t: available_entities.union(&context),
|
||||||
|
reactants,
|
||||||
|
reactants_absent,
|
||||||
|
inhibitors,
|
||||||
|
inhibitors_present,
|
||||||
|
products,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_context(&self) -> (&RSset, &RSset, &RSset) {
|
pub fn get_context(&self) -> (&RSset, &RSset, &RSset) {
|
||||||
(
|
(
|
||||||
&self.available_entities,
|
&self.available_entities,
|
||||||
|
|||||||
Reference in New Issue
Block a user