From: Mark Thom Date: Fri, 4 May 2018 21:44:11 +0000 (-0600) Subject: correct the copier's mishandling of cyclic lists X-Git-Tag: v0.8.110~474 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=8974035fed37c2001872ebe919fa32e870e8204b;p=scryer-prolog.git correct the copier's mishandling of cyclic lists --- diff --git a/src/prolog/copier.rs b/src/prolog/copier.rs index e3e26873..5ca2d08e 100644 --- a/src/prolog/copier.rs +++ b/src/prolog/copier.rs @@ -1,6 +1,7 @@ use prolog::and_stack::*; use prolog::ast::*; +use std::collections::HashMap; use std::ops::IndexMut; pub trait CopierTarget @@ -21,6 +22,11 @@ pub trait CopierTarget let mut scan = self.source(); let old_h = self.threshold(); + // Lists have a flattened representation as structures, + // removing the need for a NamedStr variant, so we use a + // redirection table for reconstructing lists. + let mut list_redirect = HashMap::new(); + self.push(HeapCellValue::Addr(a)); while scan < self.threshold() { @@ -30,6 +36,13 @@ pub trait CopierTarget HeapCellValue::Addr(a) => match a.clone() { Addr::Lis(a) => { + if let Some(idx) = list_redirect.get(&a) { + self[scan] = HeapCellValue::Addr(Addr::Lis(*idx)); + scan += 1; + continue; + } + + list_redirect.insert(a, self.threshold()); self[scan] = HeapCellValue::Addr(Addr::Lis(self.threshold())); let hcv = self[a].clone(); diff --git a/src/tests.rs b/src/tests.rs index 1bb6e8f6..1b177d90 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1416,7 +1416,8 @@ fn test_queries_on_builtins() [["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"]]); - + //TODO: enable the printer to print cyclic terms. Then run this test. + //assert_prolog_failure!(&mut wam, "?- Pairs = [a-a|Pairs], keysort(Pairs, _)."); assert_prolog_success!(&mut wam, "?- keysort([], L).", [["L = []"]]); assert_prolog_success!(&mut wam, "?- catch(keysort([a|_], _), error(E, _), true).",