Merge branch 'master' of http://github.com/mthom/rusty-wam into develop
This commit is contained in:
@@ -537,7 +537,7 @@ impl fmt::Display for Constant {
|
|||||||
&Constant::Atom(ref atom) =>
|
&Constant::Atom(ref atom) =>
|
||||||
write!(f, "{}", atom),
|
write!(f, "{}", atom),
|
||||||
&Constant::Char(c) =>
|
&Constant::Char(c) =>
|
||||||
write!(f, "{}", c as u8),
|
write!(f, "'{}'", c as u8),
|
||||||
&Constant::EmptyList =>
|
&Constant::EmptyList =>
|
||||||
write!(f, "[]"),
|
write!(f, "[]"),
|
||||||
&Constant::Number(ref n) =>
|
&Constant::Number(ref n) =>
|
||||||
@@ -1360,13 +1360,6 @@ impl Addr {
|
|||||||
_ => true
|
_ => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty_list(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
&Addr::Con(Constant::EmptyList) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Ref> for Addr {
|
impl From<Ref> for Addr {
|
||||||
|
|||||||
@@ -644,6 +644,7 @@ fn get_builtins() -> Code {
|
|||||||
keysort_execute!(), // keysort/2, 484.
|
keysort_execute!(), // keysort/2, 484.
|
||||||
acyclic_term_execute!(), // acyclic_term/1, 485.
|
acyclic_term_execute!(), // acyclic_term/1, 485.
|
||||||
cyclic_term_execute!(), // cyclic_term/1, 486.
|
cyclic_term_execute!(), // cyclic_term/1, 486.
|
||||||
|
skip_max_list_execute!() // '$skip_max_list', 487.
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,7 +764,8 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
|||||||
code_dir.insert((clause_name!("keysort"), 2), CodeIndex::from((484, builtin.clone())));
|
code_dir.insert((clause_name!("keysort"), 2), CodeIndex::from((484, builtin.clone())));
|
||||||
code_dir.insert((clause_name!("acyclic_term"), 1), CodeIndex::from((485, builtin.clone())));
|
code_dir.insert((clause_name!("acyclic_term"), 1), CodeIndex::from((485, builtin.clone())));
|
||||||
code_dir.insert((clause_name!("cyclic_term"), 1), CodeIndex::from((486, builtin.clone())));
|
code_dir.insert((clause_name!("cyclic_term"), 1), CodeIndex::from((486, builtin.clone())));
|
||||||
|
code_dir.insert((clause_name!("$skip_max_list"), 4), CodeIndex::from((487, builtin.clone())));
|
||||||
|
|
||||||
(code_dir, op_dir)
|
(code_dir, op_dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,7 +828,8 @@ pub fn builtin_module() -> Module
|
|||||||
(clause_name!("sort"), 2),
|
(clause_name!("sort"), 2),
|
||||||
(clause_name!("keysort"), 2),
|
(clause_name!("keysort"), 2),
|
||||||
(clause_name!("acyclic_term"), 1),
|
(clause_name!("acyclic_term"), 1),
|
||||||
(clause_name!("cyclic_term"), 1)]);
|
(clause_name!("cyclic_term"), 1),
|
||||||
|
(clause_name!("$skip_max_list"), 4)]);
|
||||||
|
|
||||||
for arity in 0 .. 63 {
|
for arity in 0 .. 63 {
|
||||||
module_decl.exports.push((clause_name!("call"), arity));
|
module_decl.exports.push((clause_name!("call"), arity));
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ macro_rules! try_or_fail {
|
|||||||
// used by '$skip_max_list'.
|
// used by '$skip_max_list'.
|
||||||
enum CycleSearchResult {
|
enum CycleSearchResult {
|
||||||
EmptyList,
|
EmptyList,
|
||||||
NotList,
|
NotList,
|
||||||
PartialOrProperList(usize, usize), // returns the list length (up to max), and an offset into the heap.
|
PartialList(usize, usize), // the list length (up to max), and an offset into the heap.
|
||||||
UntouchedList(usize) // return the offset of an uniterated Addr::Lis(offset).
|
ProperList(usize), // the list length.
|
||||||
|
UntouchedList(usize) // the address of an uniterated Addr::Lis(address).
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
@@ -1686,8 +1687,7 @@ impl MachineState {
|
|||||||
|
|
||||||
// detect cycles.
|
// detect cycles.
|
||||||
match self.detect_cycles(usize::max_value(), a1.clone()) {
|
match self.detect_cycles(usize::max_value(), a1.clone()) {
|
||||||
CycleSearchResult::PartialOrProperList(_, h)
|
CycleSearchResult::ProperList(_) => {},
|
||||||
if self.store(self.deref(self.heap[h].as_addr(h))).is_empty_list() => {},
|
|
||||||
_ => return Err(functor!("type_error", 2, [heap_atom!("list"), HeapCellValue::Addr(a1)]))
|
_ => return Err(functor!("type_error", 2, [heap_atom!("list"), HeapCellValue::Addr(a1)]))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1752,7 +1752,7 @@ impl MachineState {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
if steps == max_steps {
|
if steps == max_steps {
|
||||||
return CycleSearchResult::PartialOrProperList(steps, hare);
|
return CycleSearchResult::PartialList(steps, hare);
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.heap[hare].clone() {
|
match self.heap[hare].clone() {
|
||||||
@@ -1768,13 +1768,8 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
||||||
return CycleSearchResult::PartialOrProperList(steps, hare),
|
return CycleSearchResult::ProperList(steps),
|
||||||
HeapCellValue::Addr(Addr::HeapCell(hc)) if hc == hare =>
|
_ => return CycleSearchResult::PartialList(steps, hare)
|
||||||
return CycleSearchResult::PartialOrProperList(steps, hare),
|
|
||||||
HeapCellValue::Addr(ref sc @ Addr::StackCell(..))
|
|
||||||
if *sc == self.store(self.deref(sc.clone())) =>
|
|
||||||
return CycleSearchResult::PartialOrProperList(steps, hare),
|
|
||||||
_ => return CycleSearchResult::NotList
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1788,17 +1783,7 @@ impl MachineState {
|
|||||||
self.unify(addr, xs);
|
self.unify(addr, xs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
'$skip_max_list'(N, Max, Xs0, Xs):
|
|
||||||
valid modes: Max is always +Max (a non-negative integer), Xs, Xs0 and N are all ?_.
|
|
||||||
|
|
||||||
Modes | Conditions for success
|
|
||||||
======================================================================================
|
|
||||||
?N, -Xs0 : N = 0, Xs = Xs0.
|
|
||||||
?N, +Xs0 : Xs0 is a proper or partial list, Xs0 = [X1, X2, ..., XN | Xs], N = Max,
|
|
||||||
if |Xs0| >= Max, or, Xs = [] and N = |Xs0|.
|
|
||||||
*/
|
|
||||||
pub(super) fn skip_max_list(&mut self) {
|
pub(super) fn skip_max_list(&mut self) {
|
||||||
let max = self.store(self.deref(self[temp_v!(2)].clone()));
|
let max = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
|
|
||||||
@@ -1822,10 +1807,14 @@ impl MachineState {
|
|||||||
self.finalize_skip_max_list(0, Addr::Lis(l)),
|
self.finalize_skip_max_list(0, Addr::Lis(l)),
|
||||||
CycleSearchResult::EmptyList =>
|
CycleSearchResult::EmptyList =>
|
||||||
self.finalize_skip_max_list(0, Addr::Con(Constant::EmptyList)),
|
self.finalize_skip_max_list(0, Addr::Con(Constant::EmptyList)),
|
||||||
CycleSearchResult::PartialOrProperList(n, hc) =>
|
CycleSearchResult::PartialList(n, hc) =>
|
||||||
self.finalize_skip_max_list(n, Addr::HeapCell(hc)),
|
self.finalize_skip_max_list(n, Addr::HeapCell(hc)),
|
||||||
CycleSearchResult::NotList =>
|
CycleSearchResult::ProperList(n) =>
|
||||||
self.fail = true
|
self.finalize_skip_max_list(n, Addr::Con(Constant::EmptyList)),
|
||||||
|
CycleSearchResult::NotList => {
|
||||||
|
let xs0 = self[temp_v!(3)].clone();
|
||||||
|
self.finalize_skip_max_list(0, xs0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -763,6 +763,12 @@ macro_rules! cyclic_term_execute {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! skip_max_list_execute {
|
||||||
|
() => (
|
||||||
|
Line::Control(ControlInstruction::CallClause(ClauseType::SkipMaxList, 4, 0, true))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! return_from_clause {
|
macro_rules! return_from_clause {
|
||||||
($lco:expr, $machine_st:expr) => {{
|
($lco:expr, $machine_st:expr) => {{
|
||||||
if $lco {
|
if $lco {
|
||||||
|
|||||||
@@ -1644,4 +1644,8 @@ fn test_queries_on_skip_max_list() {
|
|||||||
assert_prolog_failure!(&mut wam, "?- Xs = [a,b|Xs], '$skip_max_list'(3, 5, X, Xs0).");
|
assert_prolog_failure!(&mut wam, "?- Xs = [a,b|Xs], '$skip_max_list'(3, 5, X, Xs0).");
|
||||||
assert_prolog_failure!(&mut wam, "?- X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 5, X, Xs0).");
|
assert_prolog_failure!(&mut wam, "?- X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 5, X, Xs0).");
|
||||||
assert_prolog_failure!(&mut wam, "?- X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 3, X, Xs0).");
|
assert_prolog_failure!(&mut wam, "?- X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 3, X, Xs0).");
|
||||||
|
|
||||||
|
// tests on non lists.
|
||||||
|
assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 9, non_list, Xs).",
|
||||||
|
[["Xs = non_list", "N = 0"]]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user