add compare predicate.
This commit is contained in:
@@ -23,7 +23,7 @@ Extend rusty-wam to include the following, among other features:
|
|||||||
* Built-in control operators (`,`, `;`, `->`, etc.) (_done_).
|
* Built-in control operators (`,`, `;`, `->`, etc.) (_done_).
|
||||||
* Built-in predicates for list processing and top-level declarative
|
* Built-in predicates for list processing and top-level declarative
|
||||||
control (`setup_call_control/3`, `call_with_inference_limit/3`,
|
control (`setup_call_control/3`, `call_with_inference_limit/3`,
|
||||||
etc.) (_in progress_).
|
etc.) (_done_).
|
||||||
* Add a rudimentary module system.
|
* Add a rudimentary module system.
|
||||||
* Attributed variables using the SICStus Prolog interface and
|
* Attributed variables using the SICStus Prolog interface and
|
||||||
semantics. Adding coroutines like `dif/2`, `freeze/2`, etc.
|
semantics. Adding coroutines like `dif/2`, `freeze/2`, etc.
|
||||||
@@ -98,6 +98,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `call/1..63`
|
* `call/1..63`
|
||||||
* `call_with_inference_limit/3`
|
* `call_with_inference_limit/3`
|
||||||
* `catch/3`
|
* `catch/3`
|
||||||
|
* `compare/3`
|
||||||
* `compound/1`
|
* `compound/1`
|
||||||
* `display/1`
|
* `display/1`
|
||||||
* `duplicate_term/2`
|
* `duplicate_term/2`
|
||||||
|
|||||||
@@ -421,6 +421,7 @@ pub enum QueryTerm {
|
|||||||
CallN(Vec<Box<Term>>),
|
CallN(Vec<Box<Term>>),
|
||||||
CallWithInferenceLimit(Vec<Box<Term>>),
|
CallWithInferenceLimit(Vec<Box<Term>>),
|
||||||
Catch(Vec<Box<Term>>),
|
Catch(Vec<Box<Term>>),
|
||||||
|
Compare(Vec<Box<Term>>),
|
||||||
CompareTerm(CompareTermQT, Vec<Box<Term>>),
|
CompareTerm(CompareTermQT, Vec<Box<Term>>),
|
||||||
Cut,
|
Cut,
|
||||||
Display(Vec<Box<Term>>),
|
Display(Vec<Box<Term>>),
|
||||||
@@ -442,6 +443,7 @@ impl QueryTerm {
|
|||||||
match self {
|
match self {
|
||||||
&QueryTerm::Arg(_) => 3,
|
&QueryTerm::Arg(_) => 3,
|
||||||
&QueryTerm::Catch(_) => 3,
|
&QueryTerm::Catch(_) => 3,
|
||||||
|
&QueryTerm::Compare(_) => 3,
|
||||||
&QueryTerm::CompareTerm(..) => 2,
|
&QueryTerm::CompareTerm(..) => 2,
|
||||||
&QueryTerm::Display(_) => 1,
|
&QueryTerm::Display(_) => 1,
|
||||||
&QueryTerm::Throw(_) => 1,
|
&QueryTerm::Throw(_) => 1,
|
||||||
@@ -473,6 +475,7 @@ pub enum ClauseType<'a> {
|
|||||||
CallN,
|
CallN,
|
||||||
CallWithInferenceLimit,
|
CallWithInferenceLimit,
|
||||||
Catch,
|
Catch,
|
||||||
|
Compare,
|
||||||
CompareNumber(CompareNumberQT),
|
CompareNumber(CompareNumberQT),
|
||||||
CompareTerm(CompareTermQT),
|
CompareTerm(CompareTermQT),
|
||||||
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
|
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
|
||||||
@@ -495,6 +498,7 @@ impl<'a> ClauseType<'a> {
|
|||||||
&ClauseType::CallN => "call",
|
&ClauseType::CallN => "call",
|
||||||
&ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
|
&ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
|
||||||
&ClauseType::Catch => "catch",
|
&ClauseType::Catch => "catch",
|
||||||
|
&ClauseType::Compare => "compare",
|
||||||
&ClauseType::CompareNumber(qt) => qt.name(),
|
&ClauseType::CompareNumber(qt) => qt.name(),
|
||||||
&ClauseType::CompareTerm(qt) => qt.name(),
|
&ClauseType::CompareTerm(qt) => qt.name(),
|
||||||
&ClauseType::Display => "display",
|
&ClauseType::Display => "display",
|
||||||
@@ -922,6 +926,8 @@ pub enum ControlInstruction {
|
|||||||
CatchCall,
|
CatchCall,
|
||||||
CatchExecute,
|
CatchExecute,
|
||||||
CheckCpExecute,
|
CheckCpExecute,
|
||||||
|
CompareCall,
|
||||||
|
CompareExecute,
|
||||||
CompareTermCall(CompareTermQT),
|
CompareTermCall(CompareTermQT),
|
||||||
CompareTermExecute(CompareTermQT),
|
CompareTermExecute(CompareTermQT),
|
||||||
DisplayCall,
|
DisplayCall,
|
||||||
@@ -987,6 +993,8 @@ impl ControlInstruction {
|
|||||||
&ControlInstruction::IsExecute(..) => true,
|
&ControlInstruction::IsExecute(..) => true,
|
||||||
&ControlInstruction::JmpByCall(..) => true,
|
&ControlInstruction::JmpByCall(..) => true,
|
||||||
&ControlInstruction::JmpByExecute(..) => true,
|
&ControlInstruction::JmpByExecute(..) => true,
|
||||||
|
&ControlInstruction::CompareCall => true,
|
||||||
|
&ControlInstruction::CompareExecute => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -632,7 +632,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
|||||||
install_inference_counter!(temp_v!(1), temp_v!(2), temp_v!(4)),
|
install_inference_counter!(temp_v!(1), temp_v!(2), temp_v!(4)),
|
||||||
query![put_value!(temp_v!(3), 1)],
|
query![put_value!(temp_v!(3), 1)],
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
fail!()
|
fail!(),
|
||||||
|
compare_execute!() // compare/3, 454.
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,6 +749,7 @@ pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
|
|||||||
code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
|
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, 391));
|
||||||
code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
|
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)
|
(builtin_code, code_dir, op_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,6 +259,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
},
|
},
|
||||||
&QueryTerm::Catch(_) =>
|
&QueryTerm::Catch(_) =>
|
||||||
code.push(Line::Control(ControlInstruction::CatchCall)),
|
code.push(Line::Control(ControlInstruction::CatchCall)),
|
||||||
|
&QueryTerm::Compare(_) =>
|
||||||
|
code.push(Line::Control(ControlInstruction::CompareCall)),
|
||||||
&QueryTerm::CompareTerm(qt, _) =>
|
&QueryTerm::CompareTerm(qt, _) =>
|
||||||
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
|
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
|
||||||
&QueryTerm::Display(_) =>
|
&QueryTerm::Display(_) =>
|
||||||
@@ -307,6 +309,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
*ctrl = ControlInstruction::Execute(name, arity),
|
*ctrl = ControlInstruction::Execute(name, arity),
|
||||||
ControlInstruction::CallN(arity) =>
|
ControlInstruction::CallN(arity) =>
|
||||||
*ctrl = ControlInstruction::ExecuteN(arity),
|
*ctrl = ControlInstruction::ExecuteN(arity),
|
||||||
|
ControlInstruction::CompareCall =>
|
||||||
|
*ctrl = ControlInstruction::CompareExecute,
|
||||||
ControlInstruction::CompareTermCall(qt) =>
|
ControlInstruction::CompareTermCall(qt) =>
|
||||||
*ctrl = ControlInstruction::CompareTermExecute(qt),
|
*ctrl = ControlInstruction::CompareTermExecute(qt),
|
||||||
ControlInstruction::DisplayCall =>
|
ControlInstruction::DisplayCall =>
|
||||||
|
|||||||
@@ -129,6 +129,10 @@ impl fmt::Display for ControlInstruction {
|
|||||||
write!(f, "catch_execute"),
|
write!(f, "catch_execute"),
|
||||||
&ControlInstruction::CheckCpExecute =>
|
&ControlInstruction::CheckCpExecute =>
|
||||||
write!(f, "check_cp_execute"),
|
write!(f, "check_cp_execute"),
|
||||||
|
&ControlInstruction::CompareCall =>
|
||||||
|
write!(f, "compare_call"),
|
||||||
|
&ControlInstruction::CompareExecute =>
|
||||||
|
write!(f, "compare_execute"),
|
||||||
&ControlInstruction::CompareTermCall(qt) =>
|
&ControlInstruction::CompareTermCall(qt) =>
|
||||||
write!(f, "compare_term_call {}", qt),
|
write!(f, "compare_term_call {}", qt),
|
||||||
&ControlInstruction::CompareTermExecute(qt) =>
|
&ControlInstruction::CompareTermExecute(qt) =>
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ impl<'a> QueryIterator<'a> {
|
|||||||
let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
|
let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
|
||||||
QueryIterator { state_stack: vec![state] }
|
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) => {
|
&QueryTerm::CompareTerm(qt, ref terms) => {
|
||||||
let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
|
let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
|
||||||
QueryIterator { state_stack: vec![state] }
|
QueryIterator { state_stack: vec![state] }
|
||||||
@@ -329,7 +333,7 @@ impl<'a> ChunkedIterator<'a>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&QueryTerm::SetupCallCleanup(_) => {
|
&QueryTerm::SetupCallCleanup(_) | &QueryTerm::Compare(_) => {
|
||||||
result.push(term);
|
result.push(term);
|
||||||
arity = 3;
|
arity = 3;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1020,7 +1020,11 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn copy_and_align_ball_to_heap(&mut self) {
|
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() {
|
for heap_value in self.ball.1.iter().cloned() {
|
||||||
self.heap.push(match heap_value {
|
self.heap.push(match heap_value {
|
||||||
@@ -1830,6 +1834,36 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
&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) => {
|
&ControlInstruction::CompareTermCall(qt) => {
|
||||||
match qt {
|
match qt {
|
||||||
CompareTermQT::Equal =>
|
CompareTermQT::Equal =>
|
||||||
|
|||||||
@@ -658,3 +658,9 @@ macro_rules! remove_call_policy_check {
|
|||||||
Line::BuiltIn(BuiltInInstruction::RemoveCallPolicyCheck)
|
Line::BuiltIn(BuiltInInstruction::RemoveCallPolicyCheck)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! compare_execute {
|
||||||
|
() => (
|
||||||
|
Line::Control(ControlInstruction::CompareExecute)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Submodule src/prolog/parser updated: 74bb1031f5...cd115d7a67
76
src/tests.rs
76
src/tests.rs
@@ -1443,3 +1443,79 @@ fn test_queries_on_setup_call_cleanup()
|
|||||||
assert_prolog_success!(&mut wam, "?- catch(( setup_call_cleanup(true,(G=1;G=2),throw(cl)), throw(cont)), Pat, true).",
|
assert_prolog_success!(&mut wam, "?- catch(( setup_call_cleanup(true,(G=1;G=2),throw(cl)), throw(cont)), Pat, true).",
|
||||||
[["Pat = cont", "G = _1"]]);
|
[["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"]]);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user