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