]> Repositorios git - scryer-prolog.git/commitdiff
fix faulty chunking on call/N.
authorMark Thom <[email protected]>
Thu, 3 Aug 2017 16:55:43 +0000 (10:55 -0600)
committerMark Thom <[email protected]>
Thu, 3 Aug 2017 16:55:43 +0000 (10:55 -0600)
src/main.rs
src/prolog/io.rs
src/prolog/iterators.rs
src/prolog/machine.rs

index cdf1f6390ffc50bbf5d17a797f99a95c89f99d58..f98fd34cef9768173fd4503155045202ef39c70b 100644 (file)
@@ -549,7 +549,7 @@ mod tests {
         submit(&mut wam, "maplist(Pred, []).
                           maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
         submit(&mut wam, "f(a). f(b). f(c).");
-
+        
         assert_eq!(submit(&mut wam, "?- maplist(f, [X,Y,Z])."), true);
         assert_eq!(submit(&mut wam, "?- maplist(f, [a,Y,Z])."), true);
         assert_eq!(submit(&mut wam, "?- maplist(f, [X,a,b])."), true);
@@ -647,6 +647,9 @@ mod tests {
         assert_eq!(submit(&mut wam, "?- call_mult(p(two), one)."), false);
         assert_eq!(submit(&mut wam, "?- call_mult(p(two), two)."), true);
 
+        assert_eq!(submit(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), two)."), true);
+        assert_eq!(submit(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), one)."), false);
+        
         submit(&mut wam, "f(call(f, undefined)). f(undefined).");
         submit(&mut wam, "call_var(P) :- P.");
                 
index ef844cd7766f60365599a26b837d360bd7e23c1c..ac1f720ef8e4f35318ba57027378af33d2285fc1 100644 (file)
@@ -301,6 +301,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
 
             if is_consistent(clauses) {
                 let compiled_pred = cg.compile_predicate(clauses);
+                print_code(&compiled_pred);
                 wam.add_predicate(clauses, compiled_pred)                
             } else {
                 let msg = r"Error: predicate is inconsistent.
@@ -319,12 +320,14 @@ Each predicate must have the same name and arity.";
             let mut cg = CodeGenerator::<DebrayAllocator>::new();
 
             let compiled_rule = cg.compile_rule(rule);
+            print_code(&compiled_rule);
             wam.add_rule(rule, compiled_rule)
         },
         &TopLevel::Query(ref query) => {
             let mut cg = CodeGenerator::<DebrayAllocator>::new();
 
             let compiled_query = cg.compile_query(query);
+            print_code(&compiled_query);
             wam.submit_query(compiled_query, cg.take_vars())
         }
     }
index b4279a7850b230eb51782d02d1b0aab27d96c840..83a0178b3b9ab478554bbecd8f0cbbd8524dc278 100644 (file)
@@ -285,7 +285,7 @@ impl<'a> ChunkedIterator<'a>
                     result.push(term);
                     arity = child_terms.len() + 1;
                     break;
-                },
+                },              
                 _ => {
                     result.push(term);
                     self.deep_cut_encountered = true;
@@ -312,6 +312,8 @@ impl<'a> Iterator for ChunkedIterator<'a>
                 },
                 Some(QueryTermRef::Term(term)) if term.is_callable() =>
                     return Some((term.arity(), vec![QueryTermRef::Term(term)])),
+                Some(QueryTermRef::CallN(child_terms)) =>
+                    return Some((child_terms.len() + 1, vec![QueryTermRef::CallN(child_terms)])),
                 Some(term_or_cut_ref) =>
                     return Some(self.take_chunk(term_or_cut_ref))
             }
index 4c39a26e4452b74d8df2907d1084edc4cbcb6ab5..f0ea0c5b4fb450897a89eea7ea3ec7ecf93b92dd 100644 (file)
@@ -33,7 +33,6 @@ struct MachineState {
     trail: Vec<Ref>,
     tr: usize,
     hb: usize,
-    lco: bool
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
@@ -98,7 +97,8 @@ impl Index<CodePtr> for Machine {
 impl Machine {
     pub fn new() -> Self {
         let mut code_dir = HashMap::new();
-        let code = vec![Line::BuiltIn(BuiltInInstruction::InternalCallN)];
+        let code = vec![Line::BuiltIn(BuiltInInstruction::InternalCallN),
+                        Line::Control(ControlInstruction::Proceed)];                        
 
         // there are 64 registers in the VM, so call/N is defined for all 0 <= N <= 63
         // (an extra register is needed for the predicate name)
@@ -450,7 +450,6 @@ impl MachineState {
                        trail: Vec::new(),
                        tr: 0,
                        hb: 0,
-                       lco: false
         }
     }
 
@@ -993,22 +992,27 @@ impl MachineState {
         }
     }
 
-    fn try_call_predicate(&mut self, code_dir: &CodeDir, name: Atom, arity: usize, lco: bool)
+    fn try_call_predicate(&mut self, code_dir: &CodeDir, name: Atom, arity: usize)
     {
-        let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);        
-        
+        let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
+
         match compiled_tl_index {
-            Some(compiled_tl_index) if lco => {
-                self.lco = true;
-                
+            Some(compiled_tl_index) => {
+                self.cp = self.p + 1;
                 self.num_of_args = arity;
                 self.b0 = self.b;
                 self.p  = CodePtr::DirEntry(compiled_tl_index);
             },
+            None => self.fail = true
+        };
+    }
+
+    fn try_execute_predicate(&mut self, code_dir: &CodeDir, name: Atom, arity: usize)
+    {
+        let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
+        
+        match compiled_tl_index {
             Some(compiled_tl_index) => {
-                self.lco = false;
-                
-                self.cp = self.p + 1;
                 self.num_of_args = arity;
                 self.b0 = self.b;
                 self.p  = CodePtr::DirEntry(compiled_tl_index);
@@ -1020,7 +1024,6 @@ impl MachineState {
     fn handle_internal_call_n(&mut self, code_dir: &CodeDir)
     {
         let arity = self.num_of_args + 1;
-        let lco   = self.lco;
         let pred  = self.registers[1].clone();
 
         for i in 2 .. arity {
@@ -1029,15 +1032,18 @@ impl MachineState {
 
         if arity > 1 {
             self.registers[arity - 1] = pred;
-            self.execute_call_n(code_dir, arity - 1, lco);
+
+            if let Some((name, arity)) = self.setup_call_n(arity - 1) {                
+                self.try_execute_predicate(code_dir, name, arity);
+            }
         } else {
             self.fail = true;
         }
     }
 
-    fn execute_call_n(&mut self, code_dir: &CodeDir, arity: usize, lco: bool)
+    fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey>
     {
-        let addr  = self.deref(self.registers[arity].clone());
+        let addr = self.deref(self.registers[arity].clone());
 
         let (name, narity) = match self.store(addr) {
             Addr::Str(a) => {
@@ -1055,17 +1061,17 @@ impl MachineState {
                     (name, narity)
                 } else {
                     self.fail = true;
-                    return;
+                    return None;
                 }
             },
             Addr::Con(Constant::Atom(name)) => (name, 0),
             _ => {
                 self.fail = true;
-                return;
+                return None;
             }
         };
 
-        self.try_call_predicate(code_dir, name, arity + narity - 1, lco);
+        Some((name, arity + narity - 1))
     }
 
     fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
@@ -1080,9 +1086,11 @@ impl MachineState {
                 self.p += 1;
             },
             &ControlInstruction::Call(ref name, arity, _) =>
-                self.try_call_predicate(code_dir, name.clone(), arity, false),
+                self.try_call_predicate(code_dir, name.clone(), arity),
             &ControlInstruction::CallN(arity) =>
-                self.execute_call_n(code_dir, arity, false),            
+                if let Some((name, arity)) = self.setup_call_n(arity) {
+                    self.try_call_predicate(code_dir, name, arity);
+                },
             &ControlInstruction::Deallocate => {
                 let e = self.e;
 
@@ -1091,10 +1099,12 @@ impl MachineState {
 
                 self.p += 1;
             },
-            &ControlInstruction::Execute(ref name, arity) =>                
-                self.try_call_predicate(code_dir, name.clone(), arity, true),            
+            &ControlInstruction::Execute(ref name, arity) =>
+                self.try_execute_predicate(code_dir, name.clone(), arity),
             &ControlInstruction::ExecuteN(arity) =>
-                self.execute_call_n(code_dir, arity, true),            
+                if let Some((name, arity)) = self.setup_call_n(arity) {
+                    self.try_execute_predicate(code_dir, name, arity);
+                },
             &ControlInstruction::Proceed =>
                 self.p = self.cp,
         };
@@ -1189,7 +1199,7 @@ impl MachineState {
     fn execute_builtin_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
     {
         match instr {
-            &BuiltInInstruction::InternalCallN => self.handle_internal_call_n(code_dir)            
+            &BuiltInInstruction::InternalCallN => self.handle_internal_call_n(code_dir)
         }
     }