1use std::collections::BTreeMap; 2use std::fmt::Debug; 3 4/// What a host supplies: the facts its rules are about, the values they can 5/// take, and what a rule may do. A domain is a marker type, so it is `Copy` 6/// and the engine's types can derive from it. 7/// 8/// Names are the vocabulary of rules written as data. They are also what a 9/// [`crate::Record`] carries, so a name is never content: a fact's name, never 10/// what it was about. 11pub trait Domain: Copy + Debug + Eq + 'static { 12 /// Something that can be known. Ordered, so that the facts a request 13 /// asks for come in a stable order. 14 type Fact: Copy + Ord + Debug + 'static; 15 /// What a fact can turn out to be. 16 type Value: Copy + Eq + Debug + 'static; 17 /// Something a rule does that teaches a fact ([`Domain::teaches`]). 18 type Effect: Copy + Eq + Debug + 'static; 19 /// How a rule ends the query outright. 20 type End: Copy + Eq + Debug + 'static; 21 /// Something that is so when a rule holds, and that decides no step. 22 type Note: Copy + Eq + Debug + 'static; 23 24 /// Every fact, in the order a drawing lists them. 25 fn facts() -> &'static [Self::Fact]; 26 /// The fact's name: unique among the facts. 27 fn fact_name(fact: Self::Fact) -> &'static str; 28 /// Everything the fact can turn out to be, so a test on any other value 29 /// is refused when a rule is loaded. 30 fn values(fact: Self::Fact) -> &'static [Self::Value]; 31 /// The value's name: unique among one fact's values. 32 fn value_name(value: Self::Value) -> &'static str; 33 /// Whether a source outside the network supplies the fact when asked, in 34 /// the one request that asks for every such fact together. A fact that 35 /// is not is taught by an effect. 36 fn asked_for(fact: Self::Fact) -> bool; 37 /// The fact an effect teaches. An effect whose fact is already known has 38 /// been done. 39 fn teaches(effect: Self::Effect) -> Self::Fact; 40 41 fn effect_name(effect: Self::Effect) -> String; 42 fn end_name(end: Self::End) -> String; 43 fn note_name(note: Self::Note) -> String; 44 45 /// The effect a rule loaded as data names, or why this domain does not 46 /// allow it. Refusing is the default: a domain opts each kind in. 47 fn parse_effect(name: &str) -> Result<Self::Effect, String> { 48 Err(format!("this domain allows no effect, and `{name}` is one")) 49 } 50 /// As [`Domain::parse_effect`], for an end. 51 fn parse_end(name: &str) -> Result<Self::End, String> { 52 Err(format!("this domain allows no end, and `{name}` is one")) 53 } 54 /// As [`Domain::parse_effect`], for a note. 55 fn parse_note(name: &str) -> Result<Self::Note, String> { 56 Err(format!("this domain allows no note, and `{name}` is one")) 57 } 58} 59 60/// One test on one fact: an alpha node. 61#[derive(Clone, Copy, Debug, PartialEq, Eq)] 62pub enum Test<D: Domain> { 63 Is(D::Fact, D::Value), 64 /// The fact is known, whatever it is. 65 Known(D::Fact), 66} 67 68impl<D: Domain> Test<D> { 69 pub fn fact(self) -> D::Fact { 70 match self { 71 Test::Is(fact, _) | Test::Known(fact) => fact, 72 } 73 } 74 75 /// The test without its fact's name, as a drawing labels the node. 76 pub fn label(self) -> String { 77 match self { 78 Test::Is(_, value) => format!("= {}", D::value_name(value)), 79 Test::Known(_) => "is known".to_owned(), 80 } 81 } 82} 83 84/// What a rule does when it holds. 85#[derive(Clone, Copy, Debug, PartialEq, Eq)] 86pub enum Then<D: Domain> { 87 /// Go and make a call that teaches a fact. 88 Do(D::Effect), 89 /// Stop with this. 90 End(D::End), 91 /// Something is so, and no step is decided. 92 Note(D::Note), 93} 94 95/// A rule written in code. Order is priority: of the rules that hold, the 96/// first with something left to do decides. 97#[derive(Clone, Copy, Debug)] 98pub struct Rule<'a, D: Domain> { 99 pub name: &'a str, 100 pub when: &'a [Test<D>], 101 pub then: Then<D>, 102} 103 104/// What is known so far. 105#[derive(Clone, Debug, PartialEq)] 106pub struct Known<D: Domain>(BTreeMap<D::Fact, D::Value>); 107 108impl<D: Domain> Default for Known<D> { 109 fn default() -> Self { 110 Known(BTreeMap::new()) 111 } 112} 113 114impl<D: Domain> Known<D> { 115 pub fn learn(&mut self, fact: D::Fact, value: D::Value) { 116 self.0.insert(fact, value); 117 } 118 119 pub fn get(&self, fact: D::Fact) -> Option<D::Value> { 120 self.0.get(&fact).copied() 121 } 122 123 pub fn forget(&mut self, fact: D::Fact) { 124 self.0.remove(&fact); 125 } 126 127 /// How many facts are known. 128 pub fn len(&self) -> usize { 129 self.0.len() 130 } 131 132 pub fn is_empty(&self) -> bool { 133 self.0.is_empty() 134 } 135}