simplify detection of cycles in printer
This commit is contained in:
@@ -4,30 +4,13 @@ use prolog::ast::*;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::IndexMut;
|
||||
|
||||
pub type Trail = Vec<(Ref, HeapCellValue)>;
|
||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||
|
||||
pub struct RedirectInfo {
|
||||
trail: Trail,
|
||||
list_redirect: HashMap<usize, usize>,
|
||||
offset: usize
|
||||
pub(crate) struct RedirectInfo {
|
||||
trail: Trail
|
||||
}
|
||||
|
||||
// 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 struct CellRedirect(pub HashMap<Addr, Addr>);
|
||||
|
||||
impl CellRedirect {
|
||||
pub fn new() -> Self {
|
||||
CellRedirect(HashMap::new())
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.0.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CopierTarget
|
||||
pub(crate) trait CopierTarget
|
||||
{
|
||||
fn source(&self) -> usize;
|
||||
fn threshold(&self) -> usize;
|
||||
@@ -36,34 +19,6 @@ pub trait CopierTarget
|
||||
fn deref(&self, Addr) -> Addr;
|
||||
fn stack(&mut self) -> &mut AndStack;
|
||||
|
||||
// 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 redirect.trail {
|
||||
let addr = Addr::from(r);
|
||||
|
||||
match r {
|
||||
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() - redirect.offset);
|
||||
self.stack()[fr][sc] = hcv.as_addr(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (l, h) in redirect.list_redirect {
|
||||
cell_redirect.insert(Addr::Lis(l), Addr::Lis(h - redirect.offset));
|
||||
}
|
||||
|
||||
CellRedirect(cell_redirect)
|
||||
}
|
||||
|
||||
fn unwind_trail(&mut self, redirect: RedirectInfo)
|
||||
where Self: IndexMut<usize, Output=HeapCellValue>
|
||||
{
|
||||
@@ -173,14 +128,7 @@ pub trait CopierTarget
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
RedirectInfo { trail }
|
||||
}
|
||||
|
||||
fn duplicate_term(&mut self, addr: Addr)
|
||||
|
||||
@@ -190,7 +190,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
|
||||
|
||||
fn print_offset(&mut self, addr: Addr) {
|
||||
match addr {
|
||||
Addr::HeapCell(h) | Addr::Lis(h) =>
|
||||
Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
|
||||
self.outputter.append(format!("_{}", h).as_str()),
|
||||
Addr::StackCell(fr, sc) =>
|
||||
self.outputter.append(format!("s_{}_{}", fr, sc).as_str()),
|
||||
|
||||
@@ -221,7 +221,6 @@ pub struct MachineState {
|
||||
pub(super) hb: usize,
|
||||
pub(super) block: usize, // an offset into the OR stack.
|
||||
pub(super) ball: Ball,
|
||||
pub(super) redirect: CellRedirect,
|
||||
pub(super) interms: Vec<Number>, // intermediate numbers.
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ impl MachineState {
|
||||
hb: 0,
|
||||
block: 0,
|
||||
ball: Ball::new(),
|
||||
redirect: CellRedirect::new(),
|
||||
interms: vec![Number::default(); 256]
|
||||
}
|
||||
}
|
||||
@@ -1618,9 +1617,9 @@ impl MachineState {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
self.ball.boundary = self.heap.h;
|
||||
|
||||
self.redirect = {
|
||||
{
|
||||
let mut duplicator = DuplicateBallTerm::new(self);
|
||||
duplicator.duplicate_term_and_redirect(addr)
|
||||
duplicator.duplicate_term(addr);
|
||||
};
|
||||
|
||||
self.p += 1;
|
||||
@@ -2333,6 +2332,5 @@ impl MachineState {
|
||||
self.block = 0;
|
||||
|
||||
self.ball.reset();
|
||||
self.redirect.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1313,6 +1313,13 @@ fn test_queries_on_builtins()
|
||||
assert_prolog_success!(&mut wam, "?- duplicate_term(f(X), f(X)).",
|
||||
[["X = _1"]]);
|
||||
|
||||
// test duplicate_term on cyclic terms.
|
||||
assert_prolog_failure!(&mut wam, "?- X = g(X, Y), Y = f(X), duplicate_term(Y, g(Z)).");
|
||||
assert_prolog_success!(&mut wam, "?- X = g(X, Y), Y = f(X), duplicate_term(Y, f(Z)).",
|
||||
[["Y = f(g(X, Y))", "X = g(X, f(X))", "Z = g(Z, f(Z))"]]);
|
||||
assert_prolog_success!(&mut wam, "?- X = g(X, Y), Y = f(X), duplicate_term(Y, V).",
|
||||
[["Y = f(g(X, Y))", "X = g(X, f(X))", "V = f(g(_9, V))"]]);
|
||||
|
||||
assert_prolog_success!(&mut wam, "?- float(3.14159269).");
|
||||
assert_prolog_failure!(&mut wam, "?- float(3).");
|
||||
assert_prolog_failure!(&mut wam, "?- float(\"sdfsa\").");
|
||||
|
||||
Reference in New Issue
Block a user