]> Repositorios git - scryer-prolog.git/commitdiff
fix attributed variables dealing with NeckCut on return
authorMark Thom <[email protected]>
Tue, 12 Feb 2019 15:38:46 +0000 (08:38 -0700)
committerMark Thom <[email protected]>
Tue, 12 Feb 2019 15:38:46 +0000 (08:38 -0700)
src/prolog/and_stack.rs
src/prolog/machine/attributed_variables.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs

index b1a5d5a47873dca239bb349f491e975038d5b5f4..368ada0f029bed97442b2384d8c93eb93bbc89c4 100644 (file)
@@ -41,11 +41,6 @@ impl AndStack {
         self.0.push(Frame::new(global_index, len, e, cp, n));
     }
 
-    #[allow(dead_code)]
-    pub fn top(&self) -> Option<&Frame> {
-        self.0.last()
-    }
-
     pub fn len(&self) -> usize {
         self.0.len()
     }
index 783206785b80dca4c9dfd318db6fa2cb54deae7d..940d34133ba827e4f96cb02eb07dccd6f63b5a73 100644 (file)
@@ -29,7 +29,7 @@ impl MachineState {
     pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr)
     {
         if self.attr_var_init.bindings.is_empty() {
-            self.attr_var_init.cp = self.p.local() + 1;
+            self.attr_var_init.cp = self.p.local();
             self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
         }
 
index f01a2bb039e0f63acddd2db557b88d4886fdb573..e0245a9977cf0c6177f62833519040a4a2ae8627 100644 (file)
@@ -585,27 +585,38 @@ impl MachineState {
                     if p < code_repo.in_situ_code.len() => {},
                 CodePtr::Local(_) =>
                     break,
-                CodePtr::VerifyAttrInterrupt(p) => {
-                    let rs  = self.calculate_register_threshold();
-
-                    self.allocate(rs); // store temp vars in perm vars slots.
+                CodePtr::VerifyAttrInterrupt(p) =>
+                    self.verify_attr_interrupt(p),
+                _ => {}
+            };
+        }
+    }
 
-                    let e = self.e;
-                    self.and_stack[e].special_form_cp = self.attr_var_init.cp;
+    fn verify_attr_interrupt(&mut self, p: usize) {
+        let rs = self.calculate_register_threshold();
 
-                    for i in 1 .. self.and_stack[e].len() + 1 {
-                        self.and_stack[e][i] = self[RegType::Temp(i)].clone();
-                    }
+        // store temp vars in perm vars slots along with
+        // self.b0 and self.num_of_args. why self.bo? if we return to a
+        // NeckCut after finishing the interrupt, it won't
+        // work correctly if self.b == self.b0. we must
+        // change it back when we return, as if nothing happened.
+        self.allocate(rs + 2);
 
-                    self.verify_attributes();
+        let e = self.e;
+        self.and_stack[e].special_form_cp = self.attr_var_init.cp;
 
-                    self.num_of_args = 2;
-                    self.b0 = self.b;
-                    self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
-                },
-                _ => {}
-            };
+        for i in 1 .. rs + 1 {
+            self.and_stack[e][i] = self[RegType::Temp(i)].clone();
         }
+        
+        self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0));
+        self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args));
+
+        self.verify_attributes();
+
+        self.num_of_args = 2;
+        self.b0 = self.b;
+        self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
     }
 
     fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
index ef299842ab67979d800ce10385bf6181737ccc62..6a96180a7f8c5bfd281736df520b85c71154ac28 100644 (file)
@@ -451,9 +451,19 @@ impl MachineState {
                 },
             &SystemClauseType::RestoreCodePtrFromSpecialFormCP => {
                 let e = self.e;
+
+                let frame_len = self.and_stack[e].len();
                 
-                for i in 1 .. self.and_stack[e].len() + 1 {
+                for i in 1 .. frame_len - 1 { 
                     self[RegType::Temp(i)] = self.and_stack[e][i].clone();
+                }                
+                
+                if let &Addr::Con(Constant::Usize(b0)) = &self.and_stack[e][frame_len - 1] {
+                    self.b0 = b0;
+                }
+
+                if let &Addr::Con(Constant::Usize(num_of_args)) = &self.and_stack[e][frame_len] {
+                    self.num_of_args = num_of_args;
                 }
 
                 self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
@@ -576,6 +586,8 @@ impl MachineState {
 
                     for item in iter {
                         match item {
+                            HeapCellValue::Addr(Addr::AttrVar(h)) =>
+                                vars.push(Ref::AttrVar(h)),
                             HeapCellValue::Addr(Addr::HeapCell(h)) =>
                                 vars.push(Ref::HeapCell(h)),
                             HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>