* Built-in control operators (`,`, `;`, `->`, etc.) (_done_).
* Built-in predicates for list processing and top-level declarative
control (`setup_call_control/3`, `call_with_inference_limit/3`,
- etc.) (_in progress_).
+ etc.) (_done_).
* Add a rudimentary module system.
* Attributed variables using the SICStus Prolog interface and
semantics. Adding coroutines like `dif/2`, `freeze/2`, etc.
* `call/1..63`
* `call_with_inference_limit/3`
* `catch/3`
+* `compare/3`
* `compound/1`
* `display/1`
* `duplicate_term/2`
CallN(Vec<Box<Term>>),
CallWithInferenceLimit(Vec<Box<Term>>),
Catch(Vec<Box<Term>>),
+ Compare(Vec<Box<Term>>),
CompareTerm(CompareTermQT, Vec<Box<Term>>),
Cut,
Display(Vec<Box<Term>>),
match self {
&QueryTerm::Arg(_) => 3,
&QueryTerm::Catch(_) => 3,
+ &QueryTerm::Compare(_) => 3,
&QueryTerm::CompareTerm(..) => 2,
&QueryTerm::Display(_) => 1,
&QueryTerm::Throw(_) => 1,
CallN,
CallWithInferenceLimit,
Catch,
+ Compare,
CompareNumber(CompareNumberQT),
CompareTerm(CompareTermQT),
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
&ClauseType::CallN => "call",
&ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
&ClauseType::Catch => "catch",
+ &ClauseType::Compare => "compare",
&ClauseType::CompareNumber(qt) => qt.name(),
&ClauseType::CompareTerm(qt) => qt.name(),
&ClauseType::Display => "display",
CallN(usize), // arity.
CatchCall,
CatchExecute,
- CheckCpExecute,
+ CheckCpExecute,
+ CompareCall,
+ CompareExecute,
CompareTermCall(CompareTermQT),
CompareTermExecute(CompareTermQT),
DisplayCall,
&ControlInstruction::IsExecute(..) => true,
&ControlInstruction::JmpByCall(..) => true,
&ControlInstruction::JmpByExecute(..) => true,
+ &ControlInstruction::CompareCall => true,
+ &ControlInstruction::CompareExecute => true,
_ => false
}
}
install_inference_counter!(temp_v!(1), temp_v!(2), temp_v!(4)),
query![put_value!(temp_v!(3), 1)],
reset_block!(),
- fail!()
+ fail!(),
+ compare_execute!() // compare/3, 454.
]
}
code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
-
+ code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 454));
+
(builtin_code, code_dir, op_dir)
}
},
&QueryTerm::Catch(_) =>
code.push(Line::Control(ControlInstruction::CatchCall)),
+ &QueryTerm::Compare(_) =>
+ code.push(Line::Control(ControlInstruction::CompareCall)),
&QueryTerm::CompareTerm(qt, _) =>
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
&QueryTerm::Display(_) =>
*ctrl = ControlInstruction::Execute(name, arity),
ControlInstruction::CallN(arity) =>
*ctrl = ControlInstruction::ExecuteN(arity),
+ ControlInstruction::CompareCall =>
+ *ctrl = ControlInstruction::CompareExecute,
ControlInstruction::CompareTermCall(qt) =>
*ctrl = ControlInstruction::CompareTermExecute(qt),
ControlInstruction::DisplayCall =>
write!(f, "catch_execute"),
&ControlInstruction::CheckCpExecute =>
write!(f, "check_cp_execute"),
+ &ControlInstruction::CompareCall =>
+ write!(f, "compare_call"),
+ &ControlInstruction::CompareExecute =>
+ write!(f, "compare_execute"),
&ControlInstruction::CompareTermCall(qt) =>
write!(f, "compare_term_call {}", qt),
&ControlInstruction::CompareTermExecute(qt) =>
let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
QueryIterator { state_stack: vec![state] }
},
+ &QueryTerm::Compare(ref terms) => {
+ let state = TermIterState::Clause(0, ClauseType::Compare, terms);
+ QueryIterator { state_stack: vec![state] }
+ },
&QueryTerm::CompareTerm(qt, ref terms) => {
let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
QueryIterator { state_stack: vec![state] }
break;
}
},
- &QueryTerm::SetupCallCleanup(_) => {
+ &QueryTerm::SetupCallCleanup(_) | &QueryTerm::Compare(_) => {
result.push(term);
arity = 3;
break;
}
pub(super) fn copy_and_align_ball_to_heap(&mut self) {
- let diff = self.ball.0 - self.heap.h;
+ let diff = if self.ball.0 > self.heap.h {
+ self.ball.0 - self.heap.h
+ } else {
+ self.heap.h - self.ball.0
+ };
for heap_value in self.ball.1.iter().cloned() {
self.heap.push(match heap_value {
}
};
},
+ &ControlInstruction::CompareCall => {
+ let a1 = self[temp_v!(1)].clone();
+ let a2 = self[temp_v!(2)].clone();
+ let a3 = self[temp_v!(3)].clone();
+
+ let c = Addr::Con(match self.compare_term_test(a2, a3) {
+ Ordering::Greater => atom!(">", self.atom_tbl),
+ Ordering::Equal => atom!("=", self.atom_tbl),
+ Ordering::Less => atom!("<", self.atom_tbl)
+ });
+
+ self.unify(a1, c);
+
+ self.p += 1;
+ },
+ &ControlInstruction::CompareExecute => {
+ let a1 = self[temp_v!(1)].clone();
+ let a2 = self[temp_v!(2)].clone();
+ let a3 = self[temp_v!(3)].clone();
+
+ let c = Addr::Con(match self.compare_term_test(a2, a3) {
+ Ordering::Greater => atom!(">", self.atom_tbl),
+ Ordering::Equal => atom!("=", self.atom_tbl),
+ Ordering::Less => atom!("<", self.atom_tbl)
+ });
+
+ self.unify(a1, c);
+
+ self.p = self.cp;
+ },
&ControlInstruction::CompareTermCall(qt) => {
match qt {
CompareTermQT::Equal =>
Line::BuiltIn(BuiltInInstruction::RemoveCallPolicyCheck)
)
}
+
+macro_rules! compare_execute {
+ () => (
+ Line::Control(ControlInstruction::CompareExecute)
+ )
+}
-Subproject commit 74bb1031f54631bae14aee7d8814c33573e7171d
+Subproject commit cd115d7a6781a59003f0d52451319ae68988e785
assert_prolog_success!(&mut wam, "?- catch(( setup_call_cleanup(true,(G=1;G=2),throw(cl)), throw(cont)), Pat, true).",
[["Pat = cont", "G = _1"]]);
}
+
+#[test]
+fn test_queries_on_call_with_inference_limit()
+{
+ let mut wam = Machine::new();
+
+ // inference_limit_exceeded thrown on 0 limit.
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(throw(error), 0, R).",
+ [["R = inference_limit_exceeded"]]);
+ assert_prolog_success!(&mut wam, "?- catch(call_with_inference_limit(throw(error), 1, R),
+ error,
+ true).");
+
+ assert_prolog_failure!(&mut wam, "?- call_with_inference_limit(g(X), 5, R).");
+
+ submit(&mut wam, "g(1). g(2). g(3). g(4). g(5).");
+
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 5, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = true", "X = 3"],
+ ["R = true", "X = 4"],
+ ["R = !", "X = 5"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 2, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+
+ submit(&mut wam, "f(X) :- call_with_inference_limit(g(X), 5, _).");
+
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 6, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = true", "X = 3"],
+ ["R = true", "X = 4"],
+ ["R = !", "X = 5"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 5, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = true", "X = 3"],
+ ["R = true", "X = 4"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 3, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 2, R).",
+ [["R = true", "X = 1"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 1, R).",
+ [["R = inference_limit_exceeded", "X = _1"]]);
+
+ submit(&mut wam, "e(X) :- call_with_inference_limit(f(X), 10, _).");
+
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 7, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = true", "X = 3"],
+ ["R = true", "X = 4"],
+ ["R = !", "X = 5"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 6, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = true", "X = 3"],
+ ["R = true", "X = 4"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 4, R).",
+ [["R = true", "X = 1"],
+ ["R = true", "X = 2"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 3, R).",
+ [["R = true", "X = 1"],
+ ["R = inference_limit_exceeded", "X = _1"]]);
+ assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 2, R).",
+ [["R = inference_limit_exceeded", "X = _1"]]);
+}