The sources of a host's facts, as callbacks: [Network::run] calls them,
and they are the only place a fact is supplied from.
7pub trait Host<D: Domain> {
One request for every fact the network wants from outside it. Returns what it taught; a fact left out was not supplied.
10 fn ask(&mut self, facts: &[D::Fact]) -> Vec<(D::Fact, D::Value)>;
Does an effect, and returns what it taught. It must teach
[Domain::teaches] its effect, or the run stops.
No rule has anything left to do: what to show is in the notes of the rules that hold.
21 Done,
A rule ended the query outright.
23 Ended(D::End),
A rule that decided a step, and what it stood on.
The facts the rule's tests are on, with what each was: not what any of them was about.
One thing that happened in a run.
These facts were asked for in one request.
44 Asked(Vec<D::Fact>),
A rule decided the next step.
46 Fired(Firing<D>),
Every event of a run, in order.
An event as data to log: names, ids and counts, never what a fact was
about. step is the event's place in its trace, from 0.
asked, fired, learned, done, ended or stuck.
70 pub event: &'static str,
For fired: the rule's index and name.
For fired: the kind (do, end, note) and name of what it does,
and for ended the end's name.
The facts the event is about: asked for, stood on, learned or missing.
81 pub facts: Vec<String>,
For fired and learned: the value of each fact, in the same order.
87fn named<D: Domain>(pairs: &[(D::Fact, D::Value)]) -> (Vec<String>, Vec<String>) { 88 ( 89 pairs.iter().map(|(fact, _)| D::fact_name(*fact).to_owned()).collect(), 90 pairs.iter().map(|(_, value)| D::value_name(*value).to_owned()).collect(), 91 ) 92} 93 94fn fact_names<D: Domain>(facts: &[D::Fact]) -> Vec<String> { 95 facts.iter().map(|fact| D::fact_name(*fact).to_owned()).collect() 96} 97 98impl<D: Domain> Event<D> { 99 pub fn record(&self, step: usize) -> Record { 100 let blank = Record { step, event: "", rule: None, name: None, then: None, facts: Vec::new(), values: Vec::new(), count: 0 }; 101 match self { 102 Event::Asked(facts) => Record { event: "asked", facts: fact_names::<D>(facts), count: facts.len(), ..blank }, 103 Event::Fired(firing) => { 104 let (facts, values) = named::<D>(&firing.on); 105 let then = match firing.then { 106 Then::Do(effect) => format!("do {}", D::effect_name(effect)), 107 Then::End(end) => format!("end {}", D::end_name(end)), 108 Then::Note(note) => format!("note {}", D::note_name(note)), 109 }; 110 Record { 111 event: "fired", 112 rule: Some(firing.rule), 113 name: Some(firing.name.clone()), 114 then: Some(then), 115 count: facts.len(), 116 facts, 117 values, 118 ..blank 119 } 120 } 121 Event::Learned(pairs) => { 122 let (facts, values) = named::<D>(pairs); 123 Record { event: "learned", count: facts.len(), facts, values, ..blank } 124 } 125 Event::Stopped(Outcome::Done) => Record { event: "done", ..blank }, 126 Event::Stopped(Outcome::Ended(end)) => Record { event: "ended", then: Some(D::end_name(*end)), ..blank }, 127 Event::Stopped(Outcome::Stuck(facts)) => { 128 Record { event: "stuck", facts: fact_names::<D>(facts), count: facts.len(), ..blank } 129 } 130 } 131 } 132} 133 134impl<D: Domain> Trace<D> {
The trace as records, ready to log as JSON lines.
The rules that decided a step, in order, as indices into the network's terminals: what a drawing numbers.
What a run came to.
161impl<D: Domain> Network<D> {
Does what [Network::decide] says until the query ends, asking host
for facts and for effects, and recording a trace.
Stops with [Outcome::Stuck] rather than looping when the host leaves
a wanted fact unsupplied.
167 pub fn run(&self, mut known: Known<D>, host: &mut impl Host<D>) -> Run<D> { 168 let mut trace = Trace::default(); 169 let outcome = loop { 170 let (by, next) = self.decide(&known); 171 if let Some(rule) = by { 172 trace.events.push(Event::Fired(self.explain(rule, &known))); 173 } 174 let (wanted, taught) = match next { 175 Next::Done => break Outcome::Done, 176 Next::End(end) => break Outcome::Ended(end), 177 Next::Ask(facts) => { 178 trace.events.push(Event::Asked(facts.clone())); 179 let taught = host.ask(&facts); 180 (facts, taught) 181 } 182 Next::Do(effect) => (vec![D::teaches(effect)], host.perform(effect)), 183 }; 184 for (fact, value) in &taught { 185 known.learn(*fact, *value); 186 } 187 trace.events.push(Event::Learned(taught)); 188 let missing: Vec<D::Fact> = wanted.into_iter().filter(|fact| known.get(*fact).is_none()).collect(); 189 if !missing.is_empty() { 190 break Outcome::Stuck(missing); 191 } 192 }; 193 trace.events.push(Event::Stopped(outcome.clone())); 194 Run { outcome, known, trace } 195 } 196}