Adding transitions support
This commit is contained in:
27
src/main.rs
27
src/main.rs
@ -12,21 +12,28 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
// let result = grammar::SetParser::new().parse(&buffer).unwrap();
|
// let result = grammar::SetParser::new().parse(&buffer).unwrap();
|
||||||
|
|
||||||
|
|
||||||
let reactants = grammar::SetParser::new().parse("{a}").unwrap();
|
// -------------------------------------------------------------------------
|
||||||
let inihibitors = grammar::SetParser::new().parse("{c}").unwrap();
|
// let reactants = grammar::SetParser::new().parse("{a}").unwrap();
|
||||||
let products = grammar::SetParser::new().parse("{a,c}").unwrap();
|
// let inihibitors = grammar::SetParser::new().parse("{c}").unwrap();
|
||||||
|
// let products = grammar::SetParser::new().parse("{a,c}").unwrap();
|
||||||
|
|
||||||
let process1 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products);
|
// let process1 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products);
|
||||||
|
|
||||||
let reactants = grammar::SetParser::new().parse("{b}").unwrap();
|
// let reactants = grammar::SetParser::new().parse("{b}").unwrap();
|
||||||
let inihibitors = grammar::SetParser::new().parse("{c}").unwrap();
|
// let inihibitors = grammar::SetParser::new().parse("{c}").unwrap();
|
||||||
let products = grammar::SetParser::new().parse("{b,c}").unwrap();
|
// let products = grammar::SetParser::new().parse("{b,c}").unwrap();
|
||||||
|
|
||||||
let process2 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products);
|
// let process2 = rsprocess::structure::RSreaction::from(reactants, inihibitors, products);
|
||||||
|
|
||||||
let current_state = grammar::SetParser::new().parse("{b}").unwrap();
|
// let current_state = grammar::SetParser::new().parse("{b}").unwrap();
|
||||||
|
|
||||||
println!("{:?}", rsprocess::classical::compute_all(¤t_state, vec![&process1, &process2]));
|
// println!("{:?}", rsprocess::classical::compute_all(¤t_state, vec![&process1, &process2]));
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
let env = grammar::EnvironmentParser::new().parse("[x = {a}.{b}.x , y = ({a,c}.y + {b,c}.y)]").unwrap();
|
||||||
|
let process = grammar::ContextParser::new().parse("[({a}.nil + x + y)]").unwrap();
|
||||||
|
|
||||||
|
println!("{:?}", rsprocess::transitions::unfold(&env, &process));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
//! Reaction System (RS) Framework.
|
//! Reaction System (RS) Framework.
|
||||||
//! The data is held in RSset or RSreaction, in the latter the reagents,
|
//! The data is held in RSset or RSreaction, in the latter the reagents,
|
||||||
//! inhibitors and products are held.
|
//! inhibitors and products are held.
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use super::structure::{RSset, RSreaction};
|
use super::structure::{RSset, RSreaction};
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use lalrpop_util::ParseError;
|
use lalrpop_util::ParseError;
|
||||||
use crate::rsprocess::structure::{RSset, RSprocess, RSenvironment, RSassert, RSassertOp, RSBHML};
|
use crate::rsprocess::structure::{RSset, RSprocess, RSenvironment, RSassert, RSassertOp, RSBHML};
|
||||||
@ -39,23 +40,27 @@ Set_of_entities: RSset<'input> = {
|
|||||||
pub Context: Box<RSprocess<'input>> = {
|
pub Context: Box<RSprocess<'input>> = {
|
||||||
"[" "]" => Box::new(RSprocess::Nill),
|
"[" "]" => Box::new(RSprocess::Nill),
|
||||||
"[" <t: CTX_process> "]" => Box::new(t),
|
"[" <t: CTX_process> "]" => Box::new(t),
|
||||||
"[" <t: Separeted<CTX_process, ",">> "]" =>
|
"[" <t: Separeted<Boxed_CTX_process, ",">> "]" =>
|
||||||
Box::new(RSprocess::NondeterministicChoice{ children: t })
|
Box::new(RSprocess::NondeterministicChoice{ children: t })
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Boxed_CTX_process: Rc<RSprocess<'input>> = {
|
||||||
|
<t: CTX_process> => Rc::new(t)
|
||||||
|
}
|
||||||
|
|
||||||
CTX_process: RSprocess<'input> = {
|
CTX_process: RSprocess<'input> = {
|
||||||
<c: Set_of_entities> "." <k: CTX_process> =>
|
<c: Set_of_entities> "." <k: CTX_process> =>
|
||||||
RSprocess::EntitySet{ entities: c, next_process: Box::new(k) },
|
RSprocess::EntitySet{ entities: c, next_process: Rc::new(k) },
|
||||||
"(" <k: CTX_process> ")" => k,
|
"(" <k: CTX_process> ")" => k,
|
||||||
"(" <k: Separeted<CTX_process, "+">> ")" =>
|
"(" <k: Separeted<CTX_process, "+">> ")" =>
|
||||||
RSprocess::Summation{ children: k },
|
RSprocess::Summation{ children: k },
|
||||||
"<" <n: Num> <k1: CTX_process> ">" "." <k: CTX_process> =>
|
"<" <n: Num> <k1: CTX_process> ">" "." <k: CTX_process> =>
|
||||||
RSprocess::WaitEntity{ repeat: n,
|
RSprocess::WaitEntity{ repeat: n,
|
||||||
repeated_process: Box::new(k1),
|
repeated_process: Rc::new(k1),
|
||||||
next_process: Box::new(k)},
|
next_process: Rc::new(k)},
|
||||||
"nil" => RSprocess::Nill,
|
"nil" => RSprocess::Nill,
|
||||||
<identifier: Literal> =>
|
<identifier: Literal> =>
|
||||||
RSprocess::ConstantIdentifier{ identifier }
|
RSprocess::RecursiveIdentifier{ identifier }
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----- EnvironmentParser -----
|
// ----- EnvironmentParser -----
|
||||||
@ -64,8 +69,8 @@ pub Environment: Box<RSenvironment<'input>> = {
|
|||||||
"[" <t: Separeted<Env_term, ",">> "]" => Box::new(RSenvironment::from(t))
|
"[" <t: Separeted<Env_term, ",">> "]" => Box::new(RSenvironment::from(t))
|
||||||
};
|
};
|
||||||
|
|
||||||
Env_term: (&'input str, Box<RSprocess<'input>>) = {
|
Env_term: (&'input str, RSprocess<'input>) = {
|
||||||
<identifier: Literal> "=" <k: CTX_process> => (identifier, Box::new(k))
|
<identifier: Literal> "=" <k: CTX_process> => (identifier, k)
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----- AssertParser -----
|
// ----- AssertParser -----
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod structure;
|
pub mod structure;
|
||||||
pub mod classical;
|
pub mod classical;
|
||||||
|
pub mod transitions;
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
use std::collections::{BTreeMap, HashSet};
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// RSset
|
// RSset
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct RSset<'a> {
|
pub struct RSset<'a> {
|
||||||
identifiers: HashSet<&'a str>
|
identifiers: HashSet<&'a str>
|
||||||
}
|
}
|
||||||
@ -40,7 +42,6 @@ impl<'a> RSset<'a> {
|
|||||||
self.identifiers.is_disjoint(&b.identifiers)
|
self.identifiers.is_disjoint(&b.identifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn union(&self, b: &RSset<'a>) -> RSset<'a> {
|
pub fn union(&self, b: &RSset<'a>) -> RSset<'a> {
|
||||||
// TODO maybe find more efficient way
|
// TODO maybe find more efficient way
|
||||||
let mut ret: RSset = b.clone();
|
let mut ret: RSset = b.clone();
|
||||||
@ -65,7 +66,6 @@ impl<'a> RSset<'a> {
|
|||||||
// RSreaction
|
// RSreaction
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct RSreaction<'a> {
|
pub struct RSreaction<'a> {
|
||||||
reactants: RSset<'a>,
|
reactants: RSset<'a>,
|
||||||
inihibitors: RSset<'a>,
|
inihibitors: RSset<'a>,
|
||||||
@ -73,7 +73,6 @@ pub struct RSreaction<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RSreaction<'a> {
|
impl<'a> RSreaction<'a> {
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
RSreaction{ reactants: RSset::new(),
|
RSreaction{ reactants: RSset::new(),
|
||||||
inihibitors: RSset::new(),
|
inihibitors: RSset::new(),
|
||||||
@ -91,7 +90,6 @@ impl<'a> RSreaction<'a> {
|
|||||||
&& self.inihibitors.is_disjoint(current_state)
|
&& self.inihibitors.is_disjoint(current_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn products_clone(&self) -> RSset<'a> {
|
pub fn products_clone(&self) -> RSset<'a> {
|
||||||
self.products.clone()
|
self.products.clone()
|
||||||
}
|
}
|
||||||
@ -107,47 +105,123 @@ impl<'a> RSreaction<'a> {
|
|||||||
// RSprocess
|
// RSprocess
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum RSprocess<'a> {
|
pub enum RSprocess<'a> {
|
||||||
Nill,
|
Nill,
|
||||||
ConstantIdentifier{identifier: &'a str},
|
RecursiveIdentifier{identifier: &'a str},
|
||||||
EntitySet{entities: RSset<'a>, next_process: Box<RSprocess<'a>>},
|
EntitySet{entities: RSset<'a>, next_process: Rc<RSprocess<'a>>},
|
||||||
WaitEntity{repeat: i64, repeated_process: Box<RSprocess<'a>>, next_process: Box<RSprocess<'a>>},
|
WaitEntity{repeat: i64, repeated_process: Rc<RSprocess<'a>>, next_process: Rc<RSprocess<'a>>},
|
||||||
NondeterministicChoice{children: Vec<RSprocess<'a>>},
|
Summation{children: Vec<RSprocess<'a>>},
|
||||||
Summation{children: Vec<RSprocess<'a>>}
|
NondeterministicChoice{children: Vec<Rc<RSprocess<'a>>>}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> RSprocess<'a> {
|
||||||
|
// TODO: remove all the clone()
|
||||||
|
pub fn concat(&self, new: &RSprocess<'a>) -> RSprocess<'a>{
|
||||||
|
match (self, new) {
|
||||||
|
(RSprocess::NondeterministicChoice{children: c1}, RSprocess::NondeterministicChoice{children: c2}) => {
|
||||||
|
RSprocess::NondeterministicChoice { children: [c1.clone(), c2.clone()].concat() }
|
||||||
|
},
|
||||||
|
(RSprocess::NondeterministicChoice{children}, new) |
|
||||||
|
(new, RSprocess::NondeterministicChoice{children}) => {
|
||||||
|
let mut new_children = children.clone();
|
||||||
|
new_children.push(Rc::new(new.clone()));
|
||||||
|
RSprocess::NondeterministicChoice{ children: new_children }
|
||||||
|
},
|
||||||
|
(_, _) => {
|
||||||
|
RSprocess::NondeterministicChoice { children: vec![Rc::new(self.clone()), Rc::new(new.clone())] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct RSChoices<'a> {
|
||||||
|
context_moves: Vec<(Rc<RSset<'a>>, Rc<RSprocess<'a>>)>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> RSChoices<'a> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
RSChoices{ context_moves: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, a: &mut RSChoices<'a>) {
|
||||||
|
self.context_moves.append(&mut a.context_moves);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace(&mut self, a: Rc<RSprocess<'a>>) {
|
||||||
|
self.context_moves =
|
||||||
|
self.context_moves
|
||||||
|
.iter_mut()
|
||||||
|
.map(|(c1, _)| (Rc::clone(c1), Rc::clone(&a))).collect::<Vec<_>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shuffle(&mut self, choices: RSChoices<'a>) {
|
||||||
|
if self.context_moves.is_empty() || choices.context_moves.is_empty() {
|
||||||
|
self.context_moves = vec![];
|
||||||
|
} else {
|
||||||
|
let mut new_self = vec![];
|
||||||
|
for item_self in &self.context_moves {
|
||||||
|
for item_choices in &choices.context_moves {
|
||||||
|
new_self.push((Rc::new(item_self.0.union(&item_choices.0)),
|
||||||
|
Rc::new(item_self.1.concat(&item_choices.1))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.context_moves = new_self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, const N: usize> From<[(Rc<RSset<'a>>, Rc<RSprocess<'a>>); N]> for RSChoices<'a> {
|
||||||
|
fn from(arr: [(Rc<RSset<'a>>, Rc<RSprocess<'a>>); N]) -> Self {
|
||||||
|
RSChoices{context_moves: arr.to_vec()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&[(Rc<RSset<'a>>, Rc<RSprocess<'a>>)]> for RSChoices<'a> {
|
||||||
|
fn from(arr: &[(Rc<RSset<'a>>, Rc<RSprocess<'a>>)]) -> Self {
|
||||||
|
RSChoices{context_moves: arr.to_vec()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<Vec<(Rc<RSset<'a>>, Rc<RSprocess<'a>>)>> for RSChoices<'a> {
|
||||||
|
fn from(arr: Vec<(Rc<RSset<'a>>, Rc<RSprocess<'a>>)>) -> Self {
|
||||||
|
RSChoices{context_moves: arr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// RSenvironment
|
// RSenvironment
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct RSenvironment<'a> {
|
pub struct RSenvironment<'a> {
|
||||||
definitions: BTreeMap<&'a str, Box<RSprocess<'a>>>,
|
definitions: HashMap<&'a str, RSprocess<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RSenvironment<'a> {
|
impl<'a> RSenvironment<'a> {
|
||||||
pub fn new() -> RSenvironment<'a> {
|
pub fn new() -> RSenvironment<'a> {
|
||||||
RSenvironment{definitions: BTreeMap::new()}
|
RSenvironment{definitions: HashMap::new()}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, k: &'a str) -> Option<&RSprocess<'a>> {
|
||||||
|
self.definitions.get(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, const N: usize> From<[(&'a str, Box<RSprocess<'a>>); N]> for RSenvironment<'a> {
|
impl<'a, const N: usize> From<[(&'a str, RSprocess<'a>); N]> for RSenvironment<'a> {
|
||||||
fn from(arr: [(&'a str, Box<RSprocess<'a>>); N]) -> Self {
|
fn from(arr: [(&'a str, RSprocess<'a>); N]) -> Self {
|
||||||
RSenvironment{definitions: BTreeMap::from(arr)}
|
RSenvironment{definitions: HashMap::from(arr)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&[(&'a str, Box<RSprocess<'a>>)]> for RSenvironment<'a> {
|
impl<'a> From<&[(&'a str, RSprocess<'a>)]> for RSenvironment<'a> {
|
||||||
fn from(arr: &[(&'a str, Box<RSprocess<'a>>)]) -> Self {
|
fn from(arr: &[(&'a str, RSprocess<'a>)]) -> Self {
|
||||||
RSenvironment{definitions: BTreeMap::from_iter(arr.to_vec())}
|
RSenvironment{definitions: HashMap::from_iter(arr.to_vec())}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<Vec<(&'a str, Box<RSprocess<'a>>)>> for RSenvironment<'a> {
|
impl<'a> From<Vec<(&'a str, RSprocess<'a>)>> for RSenvironment<'a> {
|
||||||
fn from(arr: Vec<(&'a str, Box<RSprocess<'a>>)>) -> Self {
|
fn from(arr: Vec<(&'a str, RSprocess<'a>)>) -> Self {
|
||||||
RSenvironment{definitions: BTreeMap::from_iter(arr)}
|
RSenvironment{definitions: HashMap::from_iter(arr)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +229,6 @@ impl<'a> From<Vec<(&'a str, Box<RSprocess<'a>>)>> for RSenvironment<'a> {
|
|||||||
// RSassertOp
|
// RSassertOp
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum RSassertOp {
|
pub enum RSassertOp {
|
||||||
InW,
|
InW,
|
||||||
InR,
|
InR,
|
||||||
@ -167,7 +240,6 @@ pub enum RSassertOp {
|
|||||||
// RSassert
|
// RSassert
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum RSassert<'a> {
|
pub enum RSassert<'a> {
|
||||||
Not(Box<RSassert<'a>>),
|
Not(Box<RSassert<'a>>),
|
||||||
Xor(Box<RSassert<'a>>, Box<RSassert<'a>>),
|
Xor(Box<RSassert<'a>>, Box<RSassert<'a>>),
|
||||||
@ -181,7 +253,6 @@ pub enum RSassert<'a> {
|
|||||||
// RSBHML
|
// RSBHML
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(dead_code)]
|
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
pub enum RSBHML<'a> {
|
pub enum RSBHML<'a> {
|
||||||
True,
|
True,
|
||||||
|
|||||||
58
src/rsprocess/transitions.rs
Normal file
58
src/rsprocess/transitions.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
use super::structure::{RSChoices, RSenvironment, RSprocess};
|
||||||
|
|
||||||
|
pub fn unfold<'a>(environment: &'a RSenvironment<'a>, context_process: &'a RSprocess<'a>) -> Result<RSChoices<'a>, String> {
|
||||||
|
match context_process {
|
||||||
|
RSprocess::Nill => Ok(RSChoices::new()),
|
||||||
|
RSprocess::RecursiveIdentifier{identifier} => {
|
||||||
|
let newprocess = environment.get(identifier);
|
||||||
|
if let Some(newprocess) = newprocess {
|
||||||
|
unfold(environment, newprocess)
|
||||||
|
} else {
|
||||||
|
Err(format!("Recursive call to missing symbol: {identifier}"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RSprocess::EntitySet{entities, next_process} => {
|
||||||
|
Ok(RSChoices::from(vec![(Rc::new(entities.clone()), Rc::clone(next_process))]))
|
||||||
|
},
|
||||||
|
RSprocess::WaitEntity{repeat, repeated_process: _, next_process} if *repeat <= 0 => {
|
||||||
|
unfold(environment, next_process)
|
||||||
|
},
|
||||||
|
RSprocess::WaitEntity{repeat, repeated_process, next_process} if *repeat == 1 => {
|
||||||
|
let mut choices1 = unfold(environment, repeated_process)?;
|
||||||
|
choices1.replace(Rc::clone(next_process));
|
||||||
|
Ok(choices1)
|
||||||
|
},
|
||||||
|
RSprocess::WaitEntity{repeat, repeated_process, next_process} => {
|
||||||
|
let mut choices1 = unfold(environment, repeated_process)?;
|
||||||
|
choices1.replace(
|
||||||
|
Rc::new(
|
||||||
|
RSprocess::WaitEntity{ repeat: (*repeat - 1),
|
||||||
|
repeated_process: Rc::clone(repeated_process),
|
||||||
|
next_process: Rc::clone(next_process) }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Ok(choices1)
|
||||||
|
},
|
||||||
|
RSprocess::Summation{children} => {
|
||||||
|
// short-circuits with try_fold.
|
||||||
|
children.iter().try_fold(RSChoices::new(), |mut acc, x| {
|
||||||
|
match unfold(environment, x) {
|
||||||
|
Ok(mut choices) => {acc.append(&mut choices); Ok(acc)},
|
||||||
|
Err(e) => Err(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
RSprocess::NondeterministicChoice{children} => {
|
||||||
|
// short-circuits with try_fold.
|
||||||
|
children.iter().try_fold(RSChoices::new(), |mut acc, x| {
|
||||||
|
match unfold(environment, x) {
|
||||||
|
Ok(choices) => {acc.shuffle(choices); Ok(acc)},
|
||||||
|
Err(e) => Err(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user