Handle errors in QueryState
This commit is contained in:
@@ -44,10 +44,21 @@ fn failing_query() {
|
|||||||
let mut machine = MachineBuilder::default().build();
|
let mut machine = MachineBuilder::default().build();
|
||||||
let query = r#"triple("a",P,"b")."#;
|
let query = r#"triple("a",P,"b")."#;
|
||||||
let complete_answer: Result<Vec<_>, _> = machine.run_query(query).collect();
|
let complete_answer: Result<Vec<_>, _> = machine.run_query(query).collect();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
complete_answer,
|
complete_answer,
|
||||||
Err(String::from(
|
Err(Term::compound(
|
||||||
"error existence_error procedure / triple 3 / triple 3"
|
"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!(
|
assert_eq!(
|
||||||
complete_answer,
|
complete_answer,
|
||||||
Err(String::from(
|
Err(Term::compound(
|
||||||
"error existence_error procedure / non_existent_predicate 3 / non_existent_predicate 3"
|
"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")))]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ impl Drop for QueryState<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for QueryState<'_> {
|
impl Iterator for QueryState<'_> {
|
||||||
type Item = Result<LeafAnswer, String>;
|
type Item = Result<LeafAnswer, Term>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let var_names = &mut self.var_names;
|
let var_names = &mut self.var_names;
|
||||||
@@ -448,30 +448,23 @@ impl Iterator for QueryState<'_> {
|
|||||||
// this should halt the search for solutions as it
|
// this should halt the search for solutions as it
|
||||||
// does in the Scryer top-level. the exception term is
|
// does in the Scryer top-level. the exception term is
|
||||||
// contained in self.machine_st.ball.
|
// contained in self.machine_st.ball.
|
||||||
let error_string = self
|
let h = machine.machine_st.heap.len();
|
||||||
.machine
|
machine
|
||||||
.machine_st
|
.machine_st
|
||||||
.ball
|
.heap
|
||||||
.stub
|
.extend(machine.machine_st.ball.stub.clone());
|
||||||
.iter()
|
let exception_term =
|
||||||
.filter(|h| {
|
Term::from_heapcell(machine, machine.machine_st.heap[h], &mut var_names.clone());
|
||||||
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 Some(Err(error_string));
|
if let Term::Compound(functor, args) = &exception_term {
|
||||||
|
if functor == "error" && args.len() == 2 {
|
||||||
|
// We have an error
|
||||||
|
return Some(Err(exception_term));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have an exception that is not an error
|
||||||
|
return Some(Ok(LeafAnswer::Exception(exception_term)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if machine.machine_st.p == LIB_QUERY_SUCCESS {
|
if machine.machine_st.p == LIB_QUERY_SUCCESS {
|
||||||
|
|||||||
Reference in New Issue
Block a user