use crate::ast::stmt::{SelectBranch, Stmt};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Determinacy {
Determinate,
Nondeterminate {
witnesses: Vec<NondetWitness>,
},
}
impl Determinacy {
pub fn is_determinate(&self) -> bool {
matches!(self, Determinacy::Determinate)
}
pub fn nondet_kinds(&self) -> Vec<NondetKind> {
match self {
Determinacy::Determinate => Vec::new(),
Determinacy::Nondeterminate { witnesses } => witnesses.iter().map(|w| w.kind).collect(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NondetWitness {
pub kind: NondetKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NondetKind {
Select,
AfterTimer,
TryRecv,
TrySend,
StopTask,
ConcurrentPrint,
}
pub(crate) fn direct_nondet_witnesses(stmt: &Stmt, out: &mut Vec<NondetWitness>) {
match stmt {
Stmt::Select { branches } => {
out.push(NondetWitness { kind: NondetKind::Select });
for branch in branches {
if let SelectBranch::Timeout { .. } = branch {
out.push(NondetWitness { kind: NondetKind::AfterTimer });
}
}
}
Stmt::TryReceivePipe { .. } => out.push(NondetWitness { kind: NondetKind::TryRecv }),
Stmt::TrySendPipe { .. } => out.push(NondetWitness { kind: NondetKind::TrySend }),
Stmt::StopTask { .. } => out.push(NondetWitness { kind: NondetKind::StopTask }),
_ => {}
}
}