1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use super::error::PolarResult;
use super::events::*;
use super::messages::*;
use super::runnable::Runnable;
use super::terms::*;
use super::vm::*;
pub struct Query {
runnable_stack: Vec<(Box<dyn Runnable>, u64)>,
vm: PolarVirtualMachine,
term: Term,
done: bool,
}
impl Query {
pub fn new(vm: PolarVirtualMachine, term: Term) -> Self {
Self {
runnable_stack: vec![],
vm,
term,
done: false,
}
}
#[cfg(target_arch = "wasm32")]
pub fn set_logging_options(&mut self, rust_log: Option<String>, polar_log: Option<String>) {
self.vm.set_logging_options(rust_log, polar_log);
}
pub fn next_event(&mut self) -> PolarResult<QueryEvent> {
let mut counter = self.vm.id_counter();
let qe = match self.top_runnable().run(Some(&mut counter)) {
Ok(e) => e,
Err(e) => self.top_runnable().handle_error(e)?,
};
self.recv_event(qe)
}
fn recv_event(&mut self, qe: QueryEvent) -> PolarResult<QueryEvent> {
match qe {
QueryEvent::None => self.next_event(),
QueryEvent::Run { runnable, call_id } => {
self.push_runnable(runnable, call_id);
self.next_event()
}
QueryEvent::Done { result } => {
if let Some((_, result_call_id)) = self.pop_runnable() {
self.top_runnable()
.external_question_result(result_call_id, result)?;
self.next_event()
} else {
assert!(self.runnable_stack.is_empty());
Ok(QueryEvent::Done { result })
}
}
ev => Ok(ev),
}
}
fn top_runnable(&mut self) -> &mut (dyn Runnable) {
self.runnable_stack
.last_mut()
.map(|b| b.0.as_mut())
.unwrap_or(&mut self.vm)
}
fn push_runnable(&mut self, runnable: Box<dyn Runnable>, call_id: u64) {
self.runnable_stack.push((runnable, call_id));
}
fn pop_runnable(&mut self) -> Option<(Box<dyn Runnable>, u64)> {
self.runnable_stack.pop()
}
pub fn call_result(&mut self, call_id: u64, value: Option<Term>) -> PolarResult<()> {
self.top_runnable().external_call_result(call_id, value)
}
pub fn question_result(&mut self, call_id: u64, result: bool) -> PolarResult<()> {
self.top_runnable()
.external_question_result(call_id, result)
}
pub fn application_error(&mut self, message: String) -> PolarResult<()> {
self.vm.external_error(message)
}
pub fn debug_command(&mut self, command: &str) -> PolarResult<()> {
self.top_runnable().debug_command(command)
}
pub fn next_message(&self) -> Option<Message> {
self.vm.messages.next()
}
pub fn source_info(&self) -> String {
self.vm.term_source(&self.term, true)
}
pub fn bind(&mut self, name: Symbol, value: Term) -> PolarResult<()> {
self.vm.bind(&name, value)
}
}
impl Iterator for Query {
type Item = PolarResult<QueryEvent>;
fn next(&mut self) -> Option<PolarResult<QueryEvent>> {
if self.done {
return None;
}
let event = self.next_event();
if let Ok(QueryEvent::Done { .. }) = event {
self.done = true;
}
Some(event)
}
}