]> Repositorios git - scryer-prolog.git/commitdiff
Handle errors in QueryState
authorbakaq <[email protected]>
Sun, 8 Dec 2024 22:47:18 +0000 (19:47 -0300)
committerbakaq <[email protected]>
Sun, 8 Dec 2024 23:18:06 +0000 (20:18 -0300)
src/machine/lib_machine/lib_machine_tests.rs
src/machine/lib_machine/mod.rs

index c05fccf66a121d8f759976aecc3aaaac17dbc8c2..5b89d67da59351d35a5f565cd0ff8e087286587e 100644 (file)
@@ -44,10 +44,21 @@ fn failing_query() {
     let mut machine = MachineBuilder::default().build();
     let query = r#"triple("a",P,"b")."#;
     let complete_answer: Result<Vec<_>, _> = machine.run_query(query).collect();
+
     assert_eq!(
         complete_answer,
-        Err(String::from(
-            "error existence_error procedure / triple 3 / triple 3"
+        Err(Term::compound(
+            "error",
+            [
+                Term::compound(
+                    "existence_error",
+                    [
+                        Term::atom("procedure"),
+                        Term::compound("/", [Term::atom("triple"), Term::integer(3)]),
+                    ]
+                ),
+                Term::compound("/", [Term::atom("triple"), Term::integer(3)]),
+            ],
         ))
     );
 }
@@ -349,8 +360,24 @@ fn non_existent_predicate_should_not_cause_panic_when_other_predicates_are_defin
 
     assert_eq!(
         complete_answer,
-        Err(String::from(
-            "error existence_error procedure / non_existent_predicate 3 / non_existent_predicate 3"
+        Err(Term::compound(
+            "error",
+            [
+                Term::compound(
+                    "existence_error",
+                    [
+                        Term::atom("procedure"),
+                        Term::compound(
+                            "/",
+                            [Term::atom("non_existent_predicate"), Term::integer(3)],
+                        ),
+                    ],
+                ),
+                Term::compound(
+                    "/",
+                    [Term::atom("non_existent_predicate"), Term::integer(3)]
+                ),
+            ],
         ))
     );
 }
@@ -555,3 +582,29 @@ fn order_of_variables_in_binding() {
         ])]
     );
 }
+
+#[test]
+#[cfg_attr(miri, ignore)]
+fn errors_and_exceptions() {
+    let mut machine = MachineBuilder::default().build();
+
+    let complete_answer: Vec<_> = machine.run_query("functor(_,_,_).").collect();
+
+    assert_eq!(
+        complete_answer,
+        [Err(Term::compound(
+            "error",
+            [
+                Term::atom("instantiation_error"),
+                Term::compound("/", [Term::atom("functor"), Term::integer(3)]),
+            ],
+        ))]
+    );
+
+    let complete_answer: Vec<_> = machine.run_query("throw(a).").collect();
+
+    assert_eq!(
+        complete_answer,
+        [Ok(LeafAnswer::Exception(Term::atom("a")))]
+    );
+}
index 55b6817b6dbce6bdab4e009935e9835d5c922a0a..685603236befb0e121d412fff41be2539ecfc89c 100644 (file)
@@ -426,7 +426,7 @@ impl Drop for QueryState<'_> {
 }
 
 impl Iterator for QueryState<'_> {
-    type Item = Result<LeafAnswer, String>;
+    type Item = Result<LeafAnswer, Term>;
 
     fn next(&mut self) -> Option<Self::Item> {
         let var_names = &mut self.var_names;
@@ -448,30 +448,23 @@ impl Iterator for QueryState<'_> {
             // 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
+            let h = machine.machine_st.heap.len();
+            machine
                 .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(" ");
+                .heap
+                .extend(machine.machine_st.ball.stub.clone());
+            let exception_term =
+                Term::from_heapcell(machine, machine.machine_st.heap[h], &mut var_names.clone());
+
+            if let Term::Compound(functor, args) = &exception_term {
+                if functor == "error" && args.len() == 2 {
+                    // We have an error
+                    return Some(Err(exception_term));
+                }
+            }
 
-            return Some(Err(error_string));
+            // We have an exception that is not an error
+            return Some(Ok(LeafAnswer::Exception(exception_term)));
         }
 
         if machine.machine_st.p == LIB_QUERY_SUCCESS {