use std::collections::HashMap;
use std::ops::IndexMut;
+pub type Trail = Vec<(Ref, HeapCellValue)>;
+
+pub struct RedirectInfo {
+ trail: Trail,
+ list_redirect: HashMap<usize, usize>,
+ offset: usize
+}
+
// allows us to reconstruct a HeapVarDict by relating variables
// in an existing HeapVarDict to the ones created in fn duplicate_term.
// It is used to create meaningful error reports at the toplevel.
pub fn new() -> Self {
CellRedirect(HashMap::new())
}
-}
-pub type Trail = Vec<(Ref, HeapCellValue)>;
+ pub fn clear(&mut self) {
+ self.0.clear();
+ }
+}
pub trait CopierTarget
{
fn deref(&self, Addr) -> Addr;
fn stack(&mut self) -> &mut AndStack;
- fn compile_redirect(&mut self, trail: Trail, list_redirect: HashMap<usize, usize>, old_h: usize)
- -> CellRedirect
- where Self: IndexMut<usize, Output=HeapCellValue>
+ // unwind the trail *and* compute a cell redirection table.
+ fn unwind_and_redirect(&mut self, redirect: RedirectInfo) -> CellRedirect
+ where Self: IndexMut<usize, Output=HeapCellValue>
{
let mut cell_redirect: HashMap<Addr, Addr> = HashMap::new();
-
- for (r, hcv) in trail {
+
+ for (r, hcv) in redirect.trail {
let addr = Addr::from(r);
-
+
match r {
- Ref::HeapCell(hc) => {
- cell_redirect.insert(addr, self[hc].as_addr(hc) - old_h);
- self[hc] = hcv;
+ Ref::HeapCell(h) => {
+ cell_redirect.insert(addr, self[h].as_addr(h) - redirect.offset);
+ self[h] = hcv;
},
Ref::StackCell(fr, sc) => {
- cell_redirect.insert(addr, self.stack()[fr][sc].clone() - old_h);
+ cell_redirect.insert(addr, self.stack()[fr][sc].clone() - redirect.offset);
self.stack()[fr][sc] = hcv.as_addr(0);
}
- }
+ };
}
- for (l, h) in list_redirect {
- cell_redirect.insert(Addr::Lis(l), Addr::Lis(h - old_h));
+ for (l, h) in redirect.list_redirect {
+ cell_redirect.insert(Addr::Lis(l), Addr::Lis(h - redirect.offset));
}
CellRedirect(cell_redirect)
}
-
- // duplicate_term(L1, L2) uses Cheney's algorithm to copy the term
+
+ fn unwind_trail(&mut self, redirect: RedirectInfo)
+ where Self: IndexMut<usize, Output=HeapCellValue>
+ {
+ for (r, hcv) in redirect.trail {
+ match r {
+ Ref::HeapCell(hc) => self[hc] = hcv.clone(),
+ Ref::StackCell(fr, sc) => self.stack()[fr][sc] = hcv.as_addr(0)
+ }
+ }
+ }
+
+ // duplicate_term_impl(L1, L2) uses Cheney's algorithm to copy the term
// at L1 to L2. trail is kept to restore the innards of L1 after
// it's been copied to L2.
- fn duplicate_term(&mut self, addr: Addr) -> CellRedirect
+ fn duplicate_term_impl(&mut self, addr: Addr) -> RedirectInfo
where Self: IndexMut<usize, Output=HeapCellValue>
{
let mut trail = Trail::new();
- let mut scan = self.source();
- let old_h = self.threshold();
+ let mut scan = self.source();
+ let old_h = self.threshold();
// Lists have a compressed representation as structures,
// removing the need for NamedStr, so we use a redirection
// table for copying lists.
let mut list_redirect = HashMap::new();
-
+
self.push(HeapCellValue::Addr(addr));
while scan < self.threshold() {
continue;
}
- list_redirect.insert(a, self.threshold());
+ list_redirect.insert(a, self.threshold());
self[scan] = HeapCellValue::Addr(Addr::Lis(self.threshold()));
-
+
let hcv = self[a].clone();
self.push(hcv);
-
+
let hcv = self[a+1].clone();
self.push(hcv);
-
+
scan += 1;
},
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
}
}
- self.compile_redirect(trail, list_redirect, old_h)
+ RedirectInfo { trail, list_redirect, offset: old_h }
+ }
+
+ fn duplicate_term_and_redirect(&mut self, addr: Addr) -> CellRedirect
+ where Self: IndexMut<usize, Output=HeapCellValue>
+ {
+ let redirect = self.duplicate_term_impl(addr);
+ self.unwind_and_redirect(redirect)
+ }
+
+ fn duplicate_term(&mut self, addr: Addr)
+ where Self: IndexMut<usize, Output=HeapCellValue>
+ {
+ let redirect = self.duplicate_term_impl(addr);
+ self.unwind_trail(redirect);
}
}
assert_prolog_success!(&mut wam, "?- p(f(X, g(Y), Z), g(Z), h).",
[["Z = b", "Y = b", "X = f(a)"]]);
assert_prolog_success!(&mut wam, "?- p(Z, Y, X).",
- [["X = h", "Y = g(b)", "Z = f(f(a), g(b), _)"]]);
+ [["X = h", "Y = g(b)", "Z = f(f(a), g(b), _7)"]]);
assert_prolog_success!(&mut wam, "?- p(f(X, Y, Z), Y, h).",
[["Y = g(b)", "Z = _3", "X = f(a)"]]);
assert_prolog_success!(&mut wam, "?- p([Z, Z]).", [["Z = _0"]]);
assert_prolog_failure!(&mut wam, "?- p([Z, W, Y]).");
- assert_prolog_success!(&mut wam, "?- p([Z | W]).", [["Z = _0", "W = [_]"]]);
+ assert_prolog_success!(&mut wam, "?- p([Z | W]).", [["Z = _0", "W = [_3]"]]);
assert_prolog_success!(&mut wam, "?- p([Z | [Z]]).", [["Z = _0"]]);
assert_prolog_success!(&mut wam, "?- p([Z | [W]]).", [["Z = _2", "W = _0"]]);
assert_prolog_failure!(&mut wam, "?- p([Z | []]).");
submit(&mut wam, "p(a, [f(g(X))]).");
submit(&mut wam, "q(Y, c).");
- assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", [["Y = [f(g(_))]", "X = a", "Z = c"]]);
+ assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", [["Y = [f(g(_9))]", "X = a", "Z = c"]]);
assert_prolog_failure!(&mut wam, "?- p(X, Y), q(Y, X).");
submit(&mut wam, "member(X, [X|_]).
submit(&mut wam, "q(Y, c).");
assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).",
- [["X = a", "Z = c", "Y = [f(g(_))]"],
+ [["X = a", "Z = c", "Y = [f(g(_9))]"],
["X = _0", "Z = c", "Y = c"]]);
assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, Z).",
- [["Z = c", "Y = [f(g(_))]", "X = a"]]);
+ [["Z = c", "Y = [f(g(_9))]", "X = a"]]);
submit(&mut wam, "q([f(g(x))], Z). q([f(g(y))], Y). q([f(g(z))], a).");
assert_prolog_success!(&mut wam, "?- functor(F, f, 0).", [["F = f"]]);
- assert_prolog_success!(&mut wam, "?- functor(Func, f, 3).", [["Func = f(_, _, _)"]]);
- assert_prolog_success!(&mut wam, "?- functor(Func, f, 4).", [["Func = f(_, _, _, _)"]]);
+ assert_prolog_success!(&mut wam, "?- functor(Func, f, 3).", [["Func = f(_2, _3, _4)"]]);
+ assert_prolog_success!(&mut wam, "?- functor(Func, f, 4).", [["Func = f(_2, _3, _4, _5)"]]);
assert_prolog_success!(&mut wam, "?- catch(functor(F, \"sdf\", 3), error(E, _), true).",
[["E = instantiation_error", "F = _1"]]);
assert_prolog_success_with_limit!(&mut wam, "?- length(Xs, N).",
[["N = 0", "Xs = []"],
- ["N = 1", "Xs = [_]"],
- ["N = 2", "Xs = [_, _]"],
- ["N = 3", "Xs = [_, _, _]"],
- ["N = 4", "Xs = [_, _, _, _]"],
- ["N = 5", "Xs = [_, _, _, _, _]"]],
+ ["N = 1", "Xs = [_3]"],
+ ["N = 2", "Xs = [_3, _6]"],
+ ["N = 3", "Xs = [_3, _6, _9]"],
+ ["N = 4", "Xs = [_3, _6, _9, _12]"],
+ ["N = 5", "Xs = [_3, _6, _9, _12, _15]"]],
6);
- assert_prolog_success!(&mut wam, "?- length(Xs, 3).", [["Xs = [_, _, _]"]]);
+ assert_prolog_success!(&mut wam, "?- length(Xs, 3).", [["Xs = [_2, _5, _8]"]]);
assert_prolog_success!(&mut wam, "?- length([a,b,c], N).", [["N = 3"]]);
assert_prolog_success!(&mut wam, "?- length([], N).", [["N = 0"]]);
assert_prolog_success!(&mut wam, "?- length(Xs, 0).", [["Xs = []"]]);
assert_prolog_success!(&mut wam, "?- keysort([1-1, 1-1], Sorted).",
[["Sorted = [1 - 1, 1 - 1]"]]);
assert_prolog_success!(&mut wam, "?- keysort([2-99, 1-a, 3-f(_), 1-z, 1-a, 2-44], Sorted).",
- [["Sorted = [1 - a, 1 - z, 1 - a, 2 - 99, 2 - 44, 3 - f(_)]"]]);
+ [["Sorted = [1 - a, 1 - z, 1 - a, 2 - 99, 2 - 44, 3 - f(_7)]"]]);
assert_prolog_success!(&mut wam, "?- keysort([X-1,1-1],[2-1,1-1]).",
[["X = 2"]]);
-
+
assert_prolog_failure!(&mut wam, "?- Pairs = [a-a|Pairs], keysort(Pairs, _).");
-// assert_prolog_success!(&mut wam, "?- Pairs = [a-a|Pairs], catch(keysort(Pairs, _), error(E, _), true).",
- // [["E = type_error(list, Pairs)", "Pairs = [a - a | Pairs]"]]);
+ assert_prolog_success!(&mut wam, "?- Pairs = [a-a|Pairs], catch(keysort(Pairs, _), error(E, _), true).",
+ [["E = type_error(list, [a - a | _21])", "Pairs = [a - a | Pairs]"]]);
assert_prolog_success!(&mut wam, "?- keysort([], L).",
[["L = []"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([],[a|a]),error(Pat, _),true).",
[["Pat = type_error(list, [a | a])"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort(_, _), error(E, _), true).",
- [["E = type_error(list, _)"]]);
+ [["E = type_error(list, _12)"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [_|b]), error(E, _), true).",
- [["E = type_error(list, [_ | b])"]]);
+ [["E = type_error(list, [_23 | b])"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [a-b,c-d,a]), error(E, _), true).",
[["E = type_error(pair, a)"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([a], [a-b]), error(E, _), true).",
assert_prolog_success!(&mut wam, "?- sort([], L).",
[["L = []"]]);
assert_prolog_success!(&mut wam, "?- catch(sort(_, []), error(E, _), true).",
- [["E = type_error(list, _)"]]);
+ [["E = type_error(list, _12)"]]);
assert_prolog_success!(&mut wam, "?- catch(sort([a,b,c], not_a_list), error(E, _), true).",
[["E = type_error(list, not_a_list)"]]);