]> Repositorios git - scryer-prolog.git/commitdiff
bug fixes.
authorMark Thom <[email protected]>
Tue, 15 Aug 2017 17:06:19 +0000 (11:06 -0600)
committerMark Thom <[email protected]>
Tue, 15 Aug 2017 17:06:19 +0000 (11:06 -0600)
README.md
src/main.rs
src/prolog/ast.rs
src/prolog/copier.rs
src/prolog/io.rs
src/prolog/machine.rs
src/prolog/macros.rs

index 4e19b5ef8b97cf8fcec0eafc41572780940bc8db..76ce76dc06e6b2e2cbaf94b84cfc49e4a2293f7c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ argument indexing, and conjunctive queries.
 Extend rusty-wam to include the following, among other features:
 
 * call/N as a built-in meta-predicate (_done_).
-* ISO Prolog compliant throw/catch (_in progress_).
+* ISO Prolog compliant throw/catch (_done_).
 * Built-in and user-defined operators of all fixities,
   with custom associativity and precedence.
 * Bignum and floating point arithmetic.
@@ -42,6 +42,18 @@ IR to get JIT-compiled and -executed Prolog programs.
 It's my hope to use rusty-wam as the logic engine of a low level (and
 ideally, very fast) [Shen](http://shenlanguage.org) implementation.
 
+## Built-in predicates
+
+The following predicates are built-in to rusty-wam.
+
+* atomic
+* call/N (0 <= N <= 62)
+* catch/3
+* duplicate_term/2
+* false/0
+* not/1
+* var/1
+
 ## Tutorial
 To enter a multi-clause predicate, the brackets ":{" and "}:" are used
 as delimiters. They must be contained entirely within their own lines.
index ae87f9243b716082889a6c933541bfbbb1f6e464..aea87ddb4509b4dbec778f3b7d5244dde29701c3 100644 (file)
@@ -721,9 +721,16 @@ mod tests {
         submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
         submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
 
-        //TODO: fix this test. record the ball properly. currently it
-        // is unwound when the heap is truncated.
         assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
+
+        submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(handle_top(X)).");
+        submit(&mut wam, "handle_top(an_error_1). handle_top(an_error_2).");
+
+        assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
+
+        submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
+
+        assert_eq!(submit(&mut wam, "?- catch(f(X), E, handle_top(E))."), true);
     }
 }
 
index 0737ef14cf2185692f54a3276210cbee867d4f31..91f4ef38ee380b5e87112d5c2e0ecb22a68c407b 100644 (file)
@@ -297,7 +297,6 @@ pub enum BuiltInInstruction {
     Fail,
     GetBall,
     GetCurrentBlock,
-    Goto(usize, usize),
     InstallNewBlock,
     InternalCallN,
     IsAtomic,
@@ -317,6 +316,7 @@ pub enum ControlInstruction {
     Deallocate,
     Execute(Atom, usize),
     ExecuteN(usize),
+    Goto(usize, usize),
     Proceed,
     ThrowCall,
     ThrowExecute
@@ -333,6 +333,7 @@ impl ControlInstruction {
             &ControlInstruction::ExecuteN(_) => true,
             &ControlInstruction::ThrowCall => true,
             &ControlInstruction::ThrowExecute => true,
+            &ControlInstruction::Goto(_, _) => true,
             _ => false
         }
     }
index 774e7ee340250839721d0c513505506e421fff95..6bff84e5940ae59f2a0106d65395b344cf23c1dc 100644 (file)
@@ -12,6 +12,12 @@ pub trait CopierTarget
     fn deref(&self, Addr) -> Addr;
     fn stack(&mut self) -> &mut AndStack;
 
+    //TODO: extend this so include a boundary() function which is constant!!
+    // this will return self.h. the threshold() will be used to set the addresses
+    // contained within the terms so that the offsets match those of the heap
+    // to be truncated by BLOCK, ie. starting at the BLOCK.H value. This should
+    // allow us to get around the latest bug.
+
     // duplicate_term(L1, L2) uses Cheney's algorithm to copy the term at
     // L1 to L2. forwarding_terms is kept to restore the innards of L1
     // after it's been copied to L2.
@@ -67,7 +73,7 @@ pub trait CopierTarget
                     match self[s].clone() {
                         HeapCellValue::NamedStr(arity, name) => {
                             let threshold = self.threshold();
-                            
+
                             self[scan] = HeapCellValue::Str(threshold);
                             self[s] = HeapCellValue::Str(threshold);
 
@@ -89,8 +95,8 @@ pub trait CopierTarget
                     scan += 1;
                 }
             };
-        }   
-        
+        }
+
         for (r, hcv) in forward_trail {
             match r {
                 Ref::HeapCell(hc) => self[hc] = hcv,
@@ -99,4 +105,3 @@ pub trait CopierTarget
         }
     }
 }
-    
index 5d59a2fb4b309ac5e66107f9eee0b33a9ea59bf6..f26453e77531a57961214d7d3f16ff5952ee8f18 100644 (file)
@@ -114,6 +114,8 @@ impl fmt::Display for ControlInstruction {
                 write!(f, "deallocate"),
             &ControlInstruction::Execute(ref name, arity) =>
                 write!(f, "execute {}/{}", name, arity),
+            &ControlInstruction::Goto(p, arity) =>
+                write!(f, "goto {}/{}", p, arity),
             &ControlInstruction::Proceed =>
                 write!(f, "proceed"),
             &ControlInstruction::ThrowCall =>
@@ -372,7 +374,6 @@ 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.
@@ -391,14 +392,12 @@ 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 908783633bf9921dbed2d520220939a0845c07ea..a04d53612d960d66ab42bd3a959f5c10334857c3 100644 (file)
@@ -36,7 +36,7 @@ struct MachineState {
     tr: usize,
     hb: usize,
     block: usize, // an offset into the OR stack.
-    ball: Heap
+    ball: (usize, Heap) // heap boundary, and a term copy
 }
 
 struct DuplicateTerm<'a> {
@@ -111,7 +111,7 @@ impl<'a> Index<usize> for DuplicateBallTerm<'a> {
             &self.state.heap[index]
         } else {
             let index = index - self.heap_boundary;
-            &self.state.ball[index]
+            &self.state.ball.1[index]
         }
     }
 }
@@ -122,7 +122,7 @@ impl<'a> IndexMut<usize> for DuplicateBallTerm<'a> {
             &mut self.state.heap[index]
         } else {
             let index = index - self.heap_boundary;
-            &mut self.state.ball[index]
+            &mut self.state.ball.1[index]
         }
     }
 }
@@ -134,11 +134,11 @@ impl<'a> CopierTarget for DuplicateBallTerm<'a> {
     }
 
     fn threshold(&self) -> usize {
-        self.heap_boundary + self.state.ball.len()
+        self.heap_boundary + self.state.ball.1.len()
     }
     
     fn push(&mut self, hcv: HeapCellValue) {
-        self.state.ball.push(hcv);        
+        self.state.ball.1.push(hcv);        
     }
 
     fn store(&self, a: Addr) -> Addr {
@@ -377,7 +377,7 @@ impl Machine {
             };
         }
     }
-
+    
     fn record_var_places<'a>(&self,
                              chunk_num: usize,
                              alloc_locs: &AllocVarDict<'a>,
@@ -409,6 +409,10 @@ impl Machine {
 
         while self.ms.p < end_ptr {
             if let CodePtr::TopLevel(mut cn, p) = self.ms.p {
+                //TODO: Shouldn't have to work nearly this hard!! Why
+                // are we only recording addresses, for instance? Why
+                // not just offsets into the heap? Not like they
+                // change.
                 if let &Line::Control(ref ctrl_instr) = &self[CodePtr::TopLevel(cn, p)] {
                     if ctrl_instr.is_jump_instr() {
                         self.record_var_places(cn, alloc_locs, heap_locs);
@@ -558,7 +562,7 @@ impl MachineState {
                        tr: 0,
                        hb: 0,
                        block: 0,
-                       ball: Vec::new()
+                       ball: (0, Vec::new())
         }
     }
     
@@ -1207,17 +1211,29 @@ impl MachineState {
                 self.p += 1;
             },
             &BuiltInInstruction::EraseBall => {
-                self.ball.truncate(0);
+                self.ball.0 = 0;
+                self.ball.1.truncate(0);
                 self.p += 1;
             },
             &BuiltInInstruction::GetBall => {
                 let addr = self.store(self.deref(self[temp_v!(1)].clone()));                
                 let h = self.h;
 
-                if self.ball.len() > 0 {
-                    let copied_ball_iter = self.ball.iter().cloned();
-                    self.heap.extend(copied_ball_iter);
-                    self.h += self.ball.len();
+                if self.ball.1.len() > 0 {
+                    let diff = self.ball.0 - h;
+                    
+                    for heap_value in self.ball.1.iter().cloned() {
+                        self.heap.push(match heap_value {
+                            HeapCellValue::Con(c) => HeapCellValue::Con(c),
+                            HeapCellValue::Lis(a) => HeapCellValue::Lis(a - diff),
+                            HeapCellValue::Ref(Ref::HeapCell(hc)) =>
+                                HeapCellValue::Ref(Ref::HeapCell(hc - diff)),
+                            HeapCellValue::Str(s) => HeapCellValue::Str(s - diff),
+                            _ => heap_value
+                        });
+                    }
+                                        
+                    self.h += self.ball.1.len();
                 } else {
                     self.fail = true;
                     return;
@@ -1237,6 +1253,8 @@ impl MachineState {
                 let addr = self[temp_v!(1)].clone();
 
                 {
+                    self.ball.0 = self.h;
+                    
                     let mut duplicator = DuplicateBallTerm::new(self);                
                     duplicator.duplicate_term(addr);
                 }
@@ -1304,12 +1322,7 @@ impl MachineState {
             &BuiltInInstruction::Fail => {
                 self.fail = true;
                 self.p += 1;
-            },
-            &BuiltInInstruction::Goto(p, arity) => {
-                self.num_of_args = arity;
-                self.b0 = self.b;
-                self.p  = CodePtr::DirEntry(p);
-            }
+            }            
         };
     }
 
@@ -1355,6 +1368,11 @@ impl MachineState {
                 if let Some((name, arity)) = self.setup_call_n(arity) {
                     self.try_execute_predicate(code_dir, name, arity);
                 },
+            &ControlInstruction::Goto(p, arity) => {
+                self.num_of_args = arity;
+                self.b0 = self.b;
+                self.p  = CodePtr::DirEntry(p);
+            },
             &ControlInstruction::Proceed =>
                 self.p = self.cp,
             &ControlInstruction::ThrowCall => {
@@ -1605,5 +1623,7 @@ impl MachineState {
         self.and_stack.clear();
         self.or_stack.clear();
         self.registers = vec![Addr::HeapCell(0); 64];
+        self.block = 0;
+        self.ball = (0, Vec::new());
     }
 }
index 4b6e2951683cc244a3c2bb19e1e5c448e805c005..077c52b7fc23566b6ebe361b853b7ee0acec22d7 100644 (file)
@@ -146,7 +146,7 @@ macro_rules! install_new_block {
 
 macro_rules! goto {
     ($line:expr, $arity:expr) => (
-        Line::BuiltIn(BuiltInInstruction::Goto($line, $arity))
+        Line::Control(ControlInstruction::Goto($line, $arity))
     )
 }