use std::collections::{BTreeMap, VecDeque};
use sim_kernel::{Expr, Symbol};
#[derive(Clone, Debug)]
pub struct TopologyNonlinearState {
nodes: Vec<NodeNonlinearState>,
}
impl TopologyNonlinearState {
pub fn new(node_count: usize) -> Self {
Self {
nodes: vec![NodeNonlinearState::default(); node_count],
}
}
pub fn push_merge(&mut self, node_index: usize, _port: Symbol, expr: Expr) -> usize {
let state = &mut self.nodes[node_index];
state.merge_buffer.push_back(PortValue { expr });
state.merge_buffer.len()
}
pub fn drain_merge(&mut self, node_index: usize, count: usize) -> Vec<Expr> {
let state = &mut self.nodes[node_index];
(0..count)
.filter_map(|_| state.merge_buffer.pop_front())
.map(|value| value.expr)
.collect()
}
pub fn mark_merge_any_complete(&mut self, node_index: usize) -> bool {
let state = &mut self.nodes[node_index];
if state.merge_any_done {
false
} else {
state.merge_any_done = true;
true
}
}
pub fn update_latest(&mut self, node_index: usize, port: Symbol, expr: Expr) -> Expr {
let state = &mut self.nodes[node_index];
state.latest.insert(port, expr);
Expr::Map(
state
.latest
.iter()
.map(|(port, expr)| (Expr::Symbol(port.clone()), expr.clone()))
.collect(),
)
}
pub fn reduce_current(&self, node_index: usize, initial: Expr) -> Expr {
self.nodes[node_index].reduce_acc.clone().unwrap_or(initial)
}
pub fn record_reduce(&mut self, node_index: usize, next: Expr) -> usize {
let state = &mut self.nodes[node_index];
state.reduce_acc = Some(next);
state.reduce_count += 1;
state.reduce_count
}
pub fn reset_reduce(&mut self, node_index: usize) {
let state = &mut self.nodes[node_index];
state.reduce_acc = None;
state.reduce_count = 0;
}
pub fn mark_race_complete(&mut self, node_index: usize) -> bool {
let state = &mut self.nodes[node_index];
if state.race_done {
false
} else {
state.race_done = true;
true
}
}
pub fn record_quorum(&mut self, node_index: usize, key: Expr, value: Expr) -> (Expr, u32) {
let state = &mut self.nodes[node_index];
if let Some(entry) = state
.quorum
.iter_mut()
.find(|entry| entry.key.canonical_eq(&key))
{
entry.count = entry.count.saturating_add(1);
return (entry.value.clone(), entry.count);
}
state.quorum.push(QuorumEntry {
key,
value: value.clone(),
count: 1,
});
(value, 1)
}
pub fn mark_quorum_complete(&mut self, node_index: usize) -> bool {
let state = &mut self.nodes[node_index];
if state.quorum_done {
false
} else {
state.quorum_done = true;
true
}
}
}
#[derive(Clone, Debug, Default)]
struct NodeNonlinearState {
merge_buffer: VecDeque<PortValue>,
merge_any_done: bool,
latest: BTreeMap<Symbol, Expr>,
reduce_acc: Option<Expr>,
reduce_count: usize,
race_done: bool,
quorum_done: bool,
quorum: Vec<QuorumEntry>,
}
#[derive(Clone, Debug)]
struct PortValue {
expr: Expr,
}
#[derive(Clone, Debug)]
struct QuorumEntry {
key: Expr,
value: Expr,
count: u32,
}