nova_interpreter/
engine.rs1use 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 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 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 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 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 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}