nova_interpreter/
engine.rs

1use std::{cmp, fmt::Debug};
2
3use state::State;
4
5use crate::{primitives::Builtins, utils::interner::Interner};
6
7use super::{parser::ruleset::RuleSet, utils::PrimitiveFn};
8
9pub mod state;
10
11pub struct Engine {
12    pub state: State,
13    pub program: Program,
14}
15
16pub struct Program {
17    pub primitives: Vec<(Box<[usize]>, PrimitiveFn)>,
18    program: RuleSet,
19}
20
21#[derive(Debug)]
22pub enum VeraEvent {
23    Continuing,
24    Error(VeraError),
25}
26
27#[derive(Debug)]
28pub enum VeraError {
29    MaxStepsExceeded,
30}
31
32type StepCallback = Box<dyn Fn(&mut Engine, usize, VeraEvent)>;
33
34impl Engine {
35    pub fn new(interner: Interner<String>) -> Self {
36        let regs = vec![];
37        let regs = regs.into_boxed_slice();
38        Engine {
39            state: State {
40                registers: regs,
41                interner,
42            },
43            program: Program {
44                primitives: vec![],
45                program: RuleSet::empty(),
46            },
47        }
48    }
49
50    /// Run a callback to get builtins to add to the engine
51    pub fn with_builtins(&mut self, f: &dyn Fn(&mut Builtins, &mut Interner<String>)) {
52        let mut builtins = Builtins {
53            builtins: &mut self.program.primitives,
54        };
55        f(&mut builtins, &mut self.state.interner);
56    }
57
58    /// Parse code from a string and add it to the current program
59    pub fn load_notecard(&mut self, code: &str) {
60        let notecard = crate::parser::parse(code, &mut self.state.interner);
61        self.program.program += notecard.unwrap();
62    }
63
64    /// Run the program for up to `max_steps` steps, calling a given callback
65    /// on each step
66    pub fn run(&mut self, max_steps: usize, step_callback: StepCallback) -> usize {
67        let mut steps = 0;
68
69        self.setup();
70
71        while self.run_step() {
72            steps += 1;
73
74            if steps >= max_steps {
75                step_callback(self, steps, VeraEvent::Error(VeraError::MaxStepsExceeded));
76                break;
77            } else {
78                step_callback(self, steps, VeraEvent::Continuing);
79            }
80        }
81
82        steps
83    }
84
85    /// Initialize the engine, creating the registers list
86    /// and setting up the initial facts in the knowledge base
87    pub fn setup(&mut self) {
88        let registers = vec![0; self.state.interner.count()].into_boxed_slice();
89
90        self.state.registers = registers;
91
92        for fact in &self.program.program.facts {
93            for (register, multiplicity) in &fact.multiplicities {
94                self.state.produce(*register, *multiplicity);
95            }
96        }
97    }
98
99    /// Run the engine for a single step
100    /// returning false if no rules or builtins matched
101    pub fn run_step(&mut self) -> bool {
102        'prims: for (condition, primitive) in self.program.primitives.iter() {
103            for register in condition.iter() {
104                if !self.state.present(*register) {
105                    continue 'prims;
106                }
107            }
108
109            primitive(&mut self.state, 0);
110            return true;
111        }
112
113        'rules: for rule in &self.program.program.rules {
114            let mut minimum = usize::MAX;
115
116            for register in rule.conditions.iter() {
117                let value = self.state.value(register.0);
118                if value == 0 {
119                    continue 'rules;
120                }
121
122                minimum = cmp::min(value, minimum);
123            }
124
125            for register in rule.conditions.iter() {
126                self.state.consume(register.0, minimum);
127            }
128
129            for (register, multiplicity) in rule.multiplicities.iter() {
130                self.state.produce(*register, minimum * *multiplicity);
131            }
132
133            return true;
134        }
135
136        false
137    }
138
139    pub fn print_state(&mut self) {
140        self.state.print_state();
141    }
142}