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