]> Repositorios git - scryer-prolog.git/commitdiff
handle non-list cases in '', add '' as a built-in (re: issue #31)
authorMark Thom <[email protected]>
Tue, 1 May 2018 16:11:27 +0000 (10:11 -0600)
committerMark Thom <[email protected]>
Tue, 1 May 2018 16:11:27 +0000 (10:11 -0600)
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/macros.rs
src/tests.rs

index b1208c0a57639201d7d7edcef34b9ae942884ff1..318586fdbbfdcf428f3a95b059e05ad135161aa2 100644 (file)
@@ -537,7 +537,7 @@ impl fmt::Display for Constant {
             &Constant::Atom(ref atom) =>
                 write!(f, "{}", atom),
             &Constant::Char(c) =>
-                write!(f, "{}", c as u8),
+                write!(f, "'{}'", c as u8),
             &Constant::EmptyList =>
                 write!(f, "[]"),
             &Constant::Number(ref n) =>
index bb88d6bf8d549b4074f028176a19f1d96172975c..2f5fbc9c1498e046bd9f8afc2971071e1a80045e 100644 (file)
@@ -644,6 +644,7 @@ fn get_builtins() -> Code {
          keysort_execute!(), // keysort/2, 484.
          acyclic_term_execute!(), // acyclic_term/1, 485.
          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!("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!("$skip_max_list"), 4), CodeIndex::from((487, builtin.clone())));
+    
     (code_dir, op_dir)
 }
 
@@ -826,7 +828,8 @@ pub fn builtin_module() -> Module
                                             (clause_name!("sort"), 2),
                                             (clause_name!("keysort"), 2),
                                             (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 {
         module_decl.exports.push((clause_name!("call"), arity));
index 71397049b4cafc4c519d0e36e03fec24cc57a32b..cedff74decb91bf8ffb0ab77293f768f7d4cd8da 100644 (file)
@@ -1759,8 +1759,9 @@ impl MachineState {
                 },
                 HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
                     return CycleSearchResult::PartialOrProperList(steps, hare),
-                HeapCellValue::Addr(Addr::HeapCell(hc)) if hc == hare =>
-                    return CycleSearchResult::PartialOrProperList(steps, hare),
+                HeapCellValue::Addr(ref hc @ Addr::HeapCell(_))
+                    if Addr::HeapCell(hare) == self.store(self.deref(hc.clone())) =>
+                      return CycleSearchResult::PartialOrProperList(steps, hare),
                 HeapCellValue::Addr(ref sc @ Addr::StackCell(..))
                     if *sc == self.store(self.deref(sc.clone())) =>
                       return CycleSearchResult::PartialOrProperList(steps, hare),
@@ -1787,7 +1788,7 @@ impl MachineState {
   ======================================================================================
       ?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|.
+                 if |Xs0| >= Max, or, Xs = Xs0 and N = |Xs0|.
 */
     pub(super) fn skip_max_list(&mut self) {
         let max = self.store(self.deref(self[temp_v!(2)].clone()));
@@ -1814,8 +1815,10 @@ impl MachineState {
                                     self.finalize_skip_max_list(0, Addr::Con(Constant::EmptyList)),
                                 CycleSearchResult::PartialOrProperList(n, hc) =>
                                     self.finalize_skip_max_list(n, Addr::HeapCell(hc)),
-                                CycleSearchResult::NotList =>
-                                    self.fail = true
+                                CycleSearchResult::NotList => {
+                                    let xs0 = self[temp_v!(3)].clone();
+                                    self.finalize_skip_max_list(0, xs0);
+                                }
                             }
                         }
                     }
index 799f666d6314299c2bb8ff843f4d141987404efb..2cd018bcb24c98c373bc8b206f7ce81e81ca20b5 100644 (file)
@@ -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 {
     ($lco:expr, $machine_st:expr) => {{
         if $lco {
index b970af2a44c98a44405b8205564da5333e3b986f..4066300ed67444e9347bc649010ebad241786ab2 100644 (file)
@@ -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, "?- 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).");
+
+    // tests on non lists.
+    assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 9, non_list, Xs).",
+                           [["Xs = non_list", "N = 0"]]);
 }