Consolidate external inputs with rules

This commit is contained in:
Shadowfacts 2024-10-29 10:57:07 -04:00
parent 3b943cb828
commit b7d0271f4e

View File

@ -48,20 +48,18 @@ impl<Output: Clone + 'static> Graph<Output> {
return self.add_node(RuleNode::new(rule));
}
pub fn add_input<I, F>(&mut self, mut f: F) -> Input<I::Output>
pub fn add_invalidatable_rule<R, V, F>(&mut self, mut f: F) -> Input<V>
where
I: ExternalInput + 'static,
I::Output: Clone,
F: FnMut(InvalidationSignal) -> I,
R: Rule<V> + 'static,
V: Clone + 'static,
F: FnMut(InvalidationSignal) -> R,
{
let node_idx = Rc::new(Cell::new(None));
let signal = InvalidationSignal {
node_idx: Rc::clone(&node_idx),
graph: Rc::clone(&self.node_graph),
};
let input = f(signal);
let node = ExternalInputNode::<I>::new(input);
let input = self.add_node(node);
let input = self.add_rule(f(signal));
node_idx.set(Some(input.node_idx));
input
}
@ -306,6 +304,7 @@ impl<R: Rule<V> + 'static, V: Clone + 'static> Node<V> for RuleNode<R, V> {
}
fn update(&mut self) {
self.valid = true;
let new_value = self.rule.evaluate();
*self.value.borrow_mut() = Some(new_value);
}
@ -323,47 +322,6 @@ impl<R: Rule<V> + 'static, V: Clone + 'static> Node<V> for RuleNode<R, V> {
}
}
struct ExternalInputNode<I: ExternalInput> {
input: I,
value: Rc<RefCell<Option<I::Output>>>,
valid: bool,
}
impl<I: ExternalInput> ExternalInputNode<I> {
fn new(input: I) -> Self {
Self {
input,
value: Rc::new(RefCell::new(None)),
valid: false,
}
}
}
impl<I: ExternalInput> Node<I::Output> for ExternalInputNode<I> {
fn is_valid(&self) -> bool {
self.valid
}
fn invalidate(&mut self) {
self.valid = false;
}
fn visit_inputs(&mut self, _visitor: &mut dyn FnMut(NodeIndex<u32>) -> ()) {}
fn update(&mut self) {
self.valid = true;
*self.value.borrow_mut() = Some(self.input.value());
}
fn value_rc(&self) -> Rc<RefCell<Option<I::Output>>> {
Rc::clone(&self.value)
}
fn value(&self) -> I::Output {
todo!()
}
}
pub trait Rule<Output> {
fn visit_inputs(&mut self, visitor: &mut impl InputVisitor);
@ -374,12 +332,6 @@ pub trait InputVisitor {
fn visit<T>(&mut self, input: &mut Input<T>);
}
pub trait ExternalInput {
type Output;
fn value(&mut self) -> Self::Output;
}
#[cfg(test)]
mod tests {
use super::*;
@ -434,18 +386,18 @@ mod tests {
}
#[test]
fn external_input() {
fn invalidatable_rule() {
struct Inc(i32);
impl ExternalInput for Inc {
type Output = i32;
fn value(&mut self) -> i32 {
impl Rule<i32> for Inc {
fn visit_inputs(&mut self, _visitor: &mut impl InputVisitor) {}
fn evaluate(&mut self) -> i32 {
self.0 += 1;
return self.0;
}
}
let mut graph = Graph::new();
let mut invalidate = None;
let input = graph.add_input(|inv| {
let input = graph.add_invalidatable_rule(|inv| {
invalidate = Some(inv);
Inc(0)
});