rustcrates.git / rete / src / domain.rs
1use std::collections::BTreeMap;
2use std::fmt::Debug;

What a host supplies: the facts its rules are about, the values they can take, and what a rule may do. A domain is a marker type, so it is Copy and the engine's types can derive from it.

Names are the vocabulary of rules written as data. They are also what a [crate::Record] carries, so a name is never content: a fact's name, never what it was about.

11pub trait Domain: Copy + Debug + Eq + 'static {

Something that can be known. Ordered, so that the facts a request asks for come in a stable order.

14    type Fact: Copy + Ord + Debug + 'static;

What a fact can turn out to be.

16    type Value: Copy + Eq + Debug + 'static;

Something a rule does that teaches a fact ([Domain::teaches]).

18    type Effect: Copy + Eq + Debug + 'static;

How a rule ends the query outright.

20    type End: Copy + Eq + Debug + 'static;

Something that is so when a rule holds, and that decides no step.

22    type Note: Copy + Eq + Debug + 'static;

Every fact, in the order a drawing lists them.

25    fn facts() -> &'static [Self::Fact];

The fact's name: unique among the facts.

27    fn fact_name(fact: Self::Fact) -> &'static str;

Everything the fact can turn out to be, so a test on any other value is refused when a rule is loaded.

30    fn values(fact: Self::Fact) -> &'static [Self::Value];

The value's name: unique among one fact's values.

32    fn value_name(value: Self::Value) -> &'static str;

Whether a source outside the network supplies the fact when asked, in the one request that asks for every such fact together. A fact that is not is taught by an effect.

36    fn asked_for(fact: Self::Fact) -> bool;

The fact an effect teaches. An effect whose fact is already known has been done.

39    fn teaches(effect: Self::Effect) -> Self::Fact;
41    fn effect_name(effect: Self::Effect) -> String;
42    fn end_name(end: Self::End) -> String;
43    fn note_name(note: Self::Note) -> String;

The effect a rule loaded as data names, or why this domain does not 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    }

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    }

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}

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),

The fact is known, whatever it is.

65    Known(D::Fact),
66}
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    }

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}

What a rule does when it holds.

85#[derive(Clone, Copy, Debug, PartialEq, Eq)]
86pub enum Then<D: Domain> {

Go and make a call that teaches a fact.

88    Do(D::Effect),

Stop with this.

90    End(D::End),

Something is so, and no step is decided.

92    Note(D::Note),
93}

A rule written in code. Order is priority: of the rules that hold, the 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}

What is known so far.

105#[derive(Clone, Debug, PartialEq)]
106pub struct Known<D: Domain>(BTreeMap<D::Fact, D::Value>);
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    }

How many facts are known.

128    pub fn len(&self) -> usize {
129        self.0.len()
130    }
132    pub fn is_empty(&self) -> bool {
133        self.0.is_empty()
134    }
135}