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)]),
+ ],
))
);
}
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)]
+ ),
+ ],
))
);
}
])]
);
}
+
+#[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")))]
+ );
+}
}
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;
// 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 {