trivial_kernel/stream/
unify.rs1use crate::context::{store, Context, Ptr, Store};
2use crate::error::Kind;
3use crate::KResult;
4use crate::Table;
5use crate::Var;
6use core::convert::TryInto;
7use core::ops::Range;
8
9#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
10pub enum Mode {
11 Def,
12 Thm,
13 ThmEnd,
14}
15
16use crate::opcode;
17
18pub trait Unify {
19 fn end(&mut self, mode: Mode) -> KResult;
20
21 fn term(&mut self, idx: u32, save: bool) -> KResult;
22
23 fn reference(&mut self, idx: u32) -> KResult;
24
25 fn dummy(&mut self, sort: u32) -> KResult;
26
27 fn hyp_thm(&mut self) -> KResult;
28
29 fn hyp_thm_end(&mut self) -> KResult;
30
31 fn execute(&mut self, command: opcode::Command<opcode::Unify>, mode: Mode) -> KResult<bool> {
32 use crate::opcode::Unify::*;
33 match command.opcode {
34 End => {
35 self.end(mode)?;
36 return Ok(true);
37 }
38 Ref => self.reference(command.operand),
39 Term => self.term(command.operand, false),
40 TermSave => self.term(command.operand, true),
41 Dummy => match mode {
42 Mode::Def => self.dummy(command.operand),
43 _ => Err(Kind::DummyCommandInTheorem),
44 },
45 Hyp => match mode {
46 Mode::Def => Err(Kind::HypInDefStatement),
47 Mode::Thm => self.hyp_thm(),
48 Mode::ThmEnd => self.hyp_thm_end(),
49 },
50 }?;
51
52 Ok(false)
53 }
54}
55
56impl<S: Store> Unify for Context<S> {
57 fn end(&mut self, mode: Mode) -> KResult {
58 if mode == Mode::ThmEnd && self.hyp_stack.len() != 0 {
59 return Err(Kind::UnfinishedHypStack);
60 }
61
62 if self.unify_stack.len() != 0 {
63 return Err(Kind::UnfinishedUnifyStack);
64 }
65
66 Ok(())
67 }
68
69 fn term(&mut self, idx: u32, save: bool) -> KResult {
70 let ptr = self.unify_stack.pop().ok_or(Kind::UnifyStackUnderflow)?;
71
72 let term: store::Term<_> = self.store.get(ptr.into())?;
73
74 if *term.id != idx {
75 return Err(Kind::UnifyTermFailure);
76 }
77
78 for i in term.args.iter().rev() {
79 self.unify_stack.push(*i);
80 }
81
82 if save {
83 self.unify_heap.push(ptr);
84 }
85
86 Ok(())
87 }
88
89 fn reference(&mut self, idx: u32) -> KResult {
90 let x = self.unify_heap.get(idx).ok_or(Kind::InvalidHeapIndex)?;
91 let y = self.unify_stack.pop().ok_or(Kind::UnifyStackUnderflow)?;
92
93 if x == y {
94 Ok(())
95 } else {
96 Err(Kind::UnifyRefFailure)
97 }
98 }
99
100 fn dummy(&mut self, sort: u32) -> KResult {
101 let e = self
102 .unify_stack
103 .pop()
104 .ok_or(Kind::UnifyStackUnderflow)?
105 .as_expr()
106 .ok_or(Kind::InvalidStackType)?;
107
108 let var: store::Variable<_> = self.store.get(e)?;
109 let ty = var.ty;
110
111 if !(ty.is_bound() && ty.sort_idx() == (sort as u8)) {
112 return Err(Kind::UnifyTermFailure);
113 }
114
115 let deps = ty.dependencies();
116
117 for i in self.unify_heap.as_slice() {
118 let i = i.as_expr().ok_or(Kind::InvalidStoreExpr)?;
119 let d = self
122 .store
123 .get_type_of_expr(i)
124 .ok_or(Kind::InvalidStoreExpr)?;
125
126 if d.depends_on_full(deps) {
127 return Err(Kind::DisjointVariableViolation);
128 }
129 }
130
131 self.unify_heap.push(e.to_expr());
132
133 Ok(())
134 }
135
136 fn hyp_thm(&mut self) -> KResult {
137 let proof = self
138 .proof_stack
139 .pop()
140 .ok_or(Kind::ProofStackUnderflow)?
141 .as_proof()
142 .ok_or(Kind::InvalidStackType)?;
143
144 self.unify_stack.push(proof.to_expr());
145
146 Ok(())
147 }
148
149 fn hyp_thm_end(&mut self) -> KResult {
150 if self.unify_stack.len() != 0 {
151 return Err(Kind::UnfinishedUnifyStack);
152 }
153
154 let e = self.hyp_stack.pop().ok_or(Kind::HypStackUnderflow)?;
155
156 self.unify_stack.push(e);
157
158 Ok(())
159 }
160}
161
162pub trait Run<S: Store> {
163 fn run<T>(&mut self, stream: Range<usize>, table: &T, mode: Mode, target: Ptr) -> KResult
164 where
165 T: Table<Var = S::Var>;
166}
167
168impl<S: Store> Run<S> for Context<S> {
169 fn run<T>(&mut self, stream: Range<usize>, table: &T, mode: Mode, target: Ptr) -> KResult
170 where
171 T: Table<Var = S::Var>,
172 {
173 self.unify_stack.clear();
174 self.unify_stack.push(target.to_expr());
175
176 let commands = table
177 .unify_commands(stream)
178 .ok_or(Kind::InvalidUnifyCommandIndex)?;
179
180 for i in commands {
181 let command = i.try_into().map_err(|_| Kind::UnknownCommand)?;
182
183 if self.execute(command, mode)? {
184 return Ok(());
185 }
186 }
187
188 Err(Kind::StreamExhausted)
189 }
190}
191
192#[derive(Debug, Clone, Eq, PartialEq, Hash)]
193pub struct Stepper {
194 started: bool,
195 done: bool,
196 mode: Mode,
197 target: Ptr,
198 stream: Range<usize>,
199}
200
201#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
202pub enum Action {
203 Started,
204 Cmd(usize, opcode::Command<opcode::Unify>),
205}
206
207impl Stepper {
208 pub fn new(mode: Mode, target: Ptr, stream: Range<usize>) -> Stepper {
209 Stepper {
210 started: false,
211 done: false,
212 mode,
213 target,
214 stream,
215 }
216 }
217
218 pub fn step<S: Store, T: Table<Var = S::Var>>(
219 &mut self,
220 context: &mut Context<S>,
221 table: &T,
222 ) -> KResult<Option<Action>> {
223 if self.done {
224 Ok(None)
225 } else if !self.started {
226 context.unify_stack.clear();
227 context.unify_stack.push(self.target.to_expr());
228 self.started = true;
229 Ok(Some(Action::Started))
230 } else {
231 let current_idx = self.stream.next();
232
233 match current_idx {
234 Some(idx) => {
235 let command = table
236 .unify_command(idx)
237 .ok_or(Kind::InvalidUnifyCommandIndex)?;
238
239 self.done = context.execute(*command, self.mode)?;
240
241 Ok(Some(Action::Cmd(idx, *command)))
242 }
243 None => Ok(None),
244 }
245 }
246 }
247}