]> Repositorios git - scryer-prolog.git/commitdiff
Implement run_query() in terms of run_query_iter()
authorbakaq <[email protected]>
Wed, 14 Aug 2024 21:44:10 +0000 (18:44 -0300)
committerbakaq <[email protected]>
Wed, 14 Aug 2024 22:59:42 +0000 (19:59 -0300)
src/machine/lib_machine.rs
src/machine/parsed_results.rs

index f068c9083eda695efd40e5e2a0f00c283617b15e..a420d79e4ea0fef75fd42e3b98e70f0001ffdae5 100644 (file)
@@ -13,7 +13,7 @@ use indexmap::IndexMap;
 
 use super::{
     streams::Stream, Atom, AtomCell, HeapCellValue, HeapCellValueTag, Machine, MachineConfig,
-    QueryResolution, QueryResolutionLine, QueryResult, Value,
+    QueryResolutionLine, QueryResult, Value,
 };
 
 pub struct QueryState<'a> {
@@ -180,171 +180,7 @@ impl Machine {
     }
 
     pub fn run_query(&mut self, query: String) -> QueryResult {
-        // println!("Query: {}", query);
-        // Parse the query so we can analyze and then call the term
-        let mut parser = Parser::new(
-            Stream::from_owned_string(query, &mut self.machine_st.arena),
-            &mut self.machine_st,
-        );
-        let op_dir = CompositeOpDir::new(&self.indices.op_dir, None);
-        let term = parser
-            .read_term(&op_dir, Tokens::Default)
-            .expect("Failed to parse query");
-
-        self.allocate_stub_choice_point();
-
-        // Write parsed term to heap
-        let term_write_result =
-            write_term_to_heap(&term, &mut self.machine_st.heap, &self.machine_st.atom_tbl)
-                .expect("couldn't write term to heap");
-
-        let var_names: IndexMap<_, _> = term_write_result
-            .var_dict
-            .iter()
-            .map(|(var_key, cell)| match var_key {
-                // NOTE: not the intention behind Var::InSitu here but
-                // we can hijack it to store anonymous variables
-                // without creating problems.
-                VarKey::AnonVar(h) => (*cell, VarPtr::from(Var::InSitu(*h))),
-                VarKey::VarPtr(var_ptr) => (*cell, var_ptr.clone()),
-            })
-            .collect();
-
-        // Write term to heap
-        self.machine_st.registers[1] = self.machine_st.heap[term_write_result.heap_loc];
-
-        self.machine_st.cp = LIB_QUERY_SUCCESS; // BREAK_FROM_DISPATCH_LOOP_LOC;
-        let call_index_p = self
-            .indices
-            .code_dir
-            .get(&(atom!("call"), 1))
-            .expect("couldn't get code index")
-            .local()
-            .unwrap();
-
-        self.machine_st.execute_at_index(1, call_index_p);
-
-        let stub_b = self.machine_st.b;
-
-        let mut matches: Vec<QueryResolutionLine> = Vec::new();
-        // Call the term
-        loop {
-            self.dispatch_loop();
-
-            //println!("b: {}", self.machine_st.b);
-            //println!("stub_b: {}", stub_b);
-            //println!("fail: {}", self.machine_st.fail);
-
-            if !self.machine_st.ball.stub.is_empty() {
-                // NOTE: this means an exception was thrown, at which
-                // point we backtracked to the stub choice point.
-                // this should halt the search for solutions as it
-                // does in the Scryer top-level. the exception term is
-                // contained in self.machine_st.ball.
-                let error_string = self
-                    .machine_st
-                    .ball
-                    .stub
-                    .iter()
-                    .filter(|h| {
-                        matches!(
-                            h.get_tag(),
-                            HeapCellValueTag::Atom | HeapCellValueTag::Fixnum
-                        )
-                    })
-                    .map(|h| match h.get_tag() {
-                        HeapCellValueTag::Atom => {
-                            let (name, _) = cell_as_atom_cell!(h).get_name_and_arity();
-                            name.as_str().to_string()
-                        }
-                        HeapCellValueTag::Fixnum => h.get_value().clone().to_string(),
-                        _ => unreachable!(),
-                    })
-                    .collect::<Vec<String>>()
-                    .join(" ");
-
-                return Err(error_string);
-            }
-
-            /*
-            if self.machine_st.fail {
-                // NOTE: only print results on success
-                self.machine_st.fail = false;
-                println!("fail!");
-                matches.push(QueryResolutionLine::False);
-                break;
-            };
-            */
-
-            if self.machine_st.p == LIB_QUERY_SUCCESS {
-                if term_write_result.var_dict.is_empty() {
-                    matches.push(QueryResolutionLine::True);
-                    break;
-                }
-            } else if self.machine_st.p == BREAK_FROM_DISPATCH_LOOP_LOC {
-                // NOTE: only print results on success
-                // self.machine_st.fail = false;
-                // println!("b == stub_b");
-                matches.push(QueryResolutionLine::False);
-                break;
-            }
-
-            let mut bindings: BTreeMap<String, Value> = BTreeMap::new();
-
-            for (var_key, term_to_be_printed) in &term_write_result.var_dict {
-                if var_key.to_string().starts_with('_') {
-                    continue;
-                }
-                let mut printer = HCPrinter::new(
-                    &mut self.machine_st.heap,
-                    Arc::clone(&self.machine_st.atom_tbl),
-                    &mut self.machine_st.stack,
-                    &self.indices.op_dir,
-                    PrinterOutputter::new(),
-                    *term_to_be_printed,
-                );
-
-                printer.ignore_ops = false;
-                printer.numbervars = true;
-                printer.quoted = true;
-                printer.max_depth = 1000; // NOTE: set this to 0 for unbounded depth
-                printer.double_quotes = true;
-                printer.var_names.clone_from(&var_names);
-
-                let outputter = printer.print();
-
-                let output: String = outputter.result();
-                // println!("Result: {} = {}", var_key.to_string(), output);
-
-                if var_key.to_string() != output {
-                    bindings.insert(
-                        var_key.to_string(),
-                        Value::try_from(output).expect("Couldn't convert Houtput to Value"),
-                    );
-                }
-            }
-
-            matches.push(QueryResolutionLine::Match(bindings));
-
-            // NOTE: there are outstanding choicepoints, backtrack
-            // through them for further solutions. if
-            // self.machine_st.b == stub_b we've backtracked to the stub
-            // choice point, so we should break.
-            self.machine_st.backtrack();
-
-            if self.machine_st.b <= stub_b {
-                // NOTE: out of choicepoints to backtrack through, no
-                // more solutions to gather.
-                break;
-            }
-        }
-
-        // NOTE: deallocate stub choice point
-        if self.machine_st.b == stub_b {
-            self.trust_me();
-        }
-
-        Ok(QueryResolution::from(matches))
+        self.run_query_iter(query).collect()
     }
 
     pub fn run_query_iter(&mut self, query: String) -> QueryState {
index 8ca6f8e8214b611f4426557e756bc528f00628ff..0dd8236f88c27aa3fea793833284f134f5eb4740 100644 (file)
@@ -5,6 +5,7 @@ use std::collections::BTreeMap;
 use std::collections::HashMap;
 use std::fmt::Display;
 use std::fmt::Write;
+use std::iter::FromIterator;
 
 pub type QueryResult = Result<QueryResolution, String>;
 
@@ -198,6 +199,14 @@ impl From<Vec<QueryResolutionLine>> for QueryResolution {
     }
 }
 
+impl FromIterator<QueryResolutionLine> for QueryResolution {
+    fn from_iter<I: IntoIterator<Item = QueryResolutionLine>>(iter: I) -> Self {
+        // TODO: Probably a good idea to implement From<Vec<QueryResolutionLine>> based on this
+        // instead.
+        iter.into_iter().collect::<Vec<_>>().into()
+    }
+}
+
 fn split_response_string(input: &str) -> Vec<String> {
     let mut level_bracket = 0;
     let mut level_parenthesis = 0;