]> Repositorios git - scryer-prolog.git/commitdiff
introduce bind_fn, use in applicable Fact/Query instructions (#841)
authorMark Thom <[email protected]>
Sun, 28 Feb 2021 23:19:06 +0000 (16:19 -0700)
committerMark Thom <[email protected]>
Sun, 28 Feb 2021 23:19:06 +0000 (16:19 -0700)
src/machine/machine_state.rs
src/machine/machine_state_impl.rs
src/machine/system_calls.rs

index 77a0d36844ecd316d91ec1cf8dd3cb513bbb0bd1..ee48340acfc85cf0e1cec8fccbc86c3bc9bf1b9f 100644 (file)
@@ -304,6 +304,7 @@ pub(crate) struct MachineState {
     pub(crate) global_clock: usize,
     pub(crate) dynamic_mode: FirstOrNext,
     pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr),
+    pub(crate) bind_fn: fn(&mut MachineState, Ref, Addr),
 }
 
 impl fmt::Debug for MachineState {
@@ -343,6 +344,14 @@ impl fmt::Debug for MachineState {
                 } else {
                     &"MachineState::unify_with_occurs_check_with_error"
                 })
+         .field("bind_fn",
+                if self.bind_fn as usize == MachineState::bind as usize {
+                    &"MachineState::bind"
+                } else if self.bind_fn as usize == MachineState::bind_with_occurs_check_wrapper as usize {
+                    &"MachineState::bind_with_occurs_check"
+                } else {
+                    &"MachineState::bind_with_occurs_check_with_error_wrapper"
+                })
          .finish()
     }
 }
index 6ca1341acb6045537999db51b54c3edec72c76a9..b1d8dde7c3c300f35ae1cd9add52046fadd0d412 100644 (file)
@@ -57,6 +57,7 @@ impl MachineState {
             global_clock: 0,
             dynamic_mode: FirstOrNext::First,
             unify_fn: MachineState::unify,
+            bind_fn: MachineState::bind,
         }
     }
 
@@ -154,7 +155,25 @@ impl MachineState {
     }
 
     #[inline]
-    fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool {
+    pub(super) fn bind_with_occurs_check_with_error_wrapper(&mut self, r: Ref, addr: Addr) {
+        if self.bind_with_occurs_check(r, addr) {
+            let err = self.representation_error(
+                RepFlag::Term,
+                clause_name!("unify_with_occurs_check"),
+                2,
+            );
+
+            self.throw_exception(err);
+        }
+    }
+
+    #[inline]
+    pub(super) fn bind_with_occurs_check_wrapper(&mut self, r: Ref, addr: Addr) {
+        self.bind_with_occurs_check(r, addr);
+    }
+
+    #[inline]
+    pub(super) fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool {
         if let Ref::StackCell(..) = r {
             // local variable optimization -- r cannot occur in the
             // data structure bound to addr, so don't bother
@@ -871,7 +890,7 @@ impl MachineState {
             }
             Addr::Lis(l) => {
                 let addr = self.heap.put_constant(c.clone());
-                (self.unify_fn)(self, Addr::Lis(l), addr);
+                self.unify(Addr::Lis(l), addr);
             }
             Addr::PStrLocation(h, n) => {
                 if let Constant::String(ref s2) = c {
@@ -889,7 +908,7 @@ impl MachineState {
                 if let Some(r) = addr.as_var() {
                     self.bind(r, c);
                 } else {
-                    (self.unify_fn)(self, addr, c);
+                    self.unify(addr, c);
                 }
             }
         };
@@ -1222,8 +1241,7 @@ impl MachineState {
                         let h = self.heap.h();
 
                         self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
-                        self.heap
-                            .push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
+                        self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
 
                         self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
 
@@ -1283,22 +1301,20 @@ impl MachineState {
                         self.increment_s_ptr(1);
                     }
                     MachineMode::Write => {
-                        let addr = self.deref(self[reg]);
+                        let addr = self.store(self.deref(self[reg]));
                         let h = self.heap.h();
 
                         if let Addr::HeapCell(hc) = addr {
-                            if hc < h {
-                                let val = self.heap.clone(hc);
+                            let val = self.heap.clone(hc);
 
-                                self.heap.push(val);
-                                self.increment_s_ptr(1);
+                            self.heap.push(val);
+                            self.increment_s_ptr(1);
 
-                                return;
-                            }
+                            return;
                         }
 
                         self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
-                        self.bind(Ref::HeapCell(h), addr);
+                        (self.bind_fn)(self, Ref::HeapCell(h), addr);
                     }
                 };
             }
@@ -1569,7 +1585,7 @@ impl MachineState {
                     let h = self.heap.h();
 
                     self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
-                    self.bind(Ref::HeapCell(h), addr);
+                    (self.bind_fn)(self, Ref::HeapCell(h), addr);
 
                     self.registers[arg] = self.heap[h].as_addr(h);
                 }
@@ -1611,7 +1627,7 @@ impl MachineState {
                 }
 
                 self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
-                self.bind(Ref::HeapCell(h), addr);
+                (self.bind_fn)(self, Ref::HeapCell(h), addr);
             }
             &QueryInstruction::SetVariable(reg) => {
                 let h = self.heap.h();
@@ -2466,7 +2482,7 @@ impl MachineState {
             self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + i)));
         }
 
-        self.bind(r, f_a);
+        (self.bind_fn)(self, r, f_a);
     }
 
     pub(super) fn try_functor(&mut self, op_dir: &OpDir) -> CallResult {
index 6793c0859085e061e06056e69bb6d6de00d557f8..dfe0411fec089cdf26dd486ff1302d805762bd44 100644 (file)
@@ -253,11 +253,11 @@ impl MachineState {
 
     fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) {
         let target_n = self[temp_v!(1)];
-        (self.unify_fn)(self, Addr::Usize(n), target_n);
+        self.unify(Addr::Usize(n), target_n);
 
         if !self.fail {
             let xs = self[temp_v!(4)];
-            (self.unify_fn)(self, addr, xs);
+            self.unify(addr, xs);
         }
     }
 
@@ -313,7 +313,7 @@ impl MachineState {
                                 let xs0 = self[temp_v!(3)];
                                 let xs = self[temp_v!(4)];
 
-                                (self.unify_fn)(self, xs0, xs);
+                                self.unify(xs0, xs);
                             } else {
                                 self.skip_max_list_result(max_steps_n);
                             }
@@ -323,7 +323,7 @@ impl MachineState {
                                 let xs0 = self[temp_v!(3)];
                                 let xs = self[temp_v!(4)];
 
-                                (self.unify_fn)(self, xs0, xs);
+                                self.unify(xs0, xs);
                             } else {
                                 self.skip_max_list_result(max_steps_n);
                             }
@@ -5456,12 +5456,15 @@ impl MachineState {
             }
             &SystemClauseType::SetSTOAsUnify => {
                 self.unify_fn = MachineState::unify_with_occurs_check;
+                self.bind_fn = MachineState::bind_with_occurs_check_wrapper;
             }
             &SystemClauseType::SetNSTOAsUnify => {
                 self.unify_fn = MachineState::unify;
+                self.bind_fn = MachineState::bind;
             }
             &SystemClauseType::SetSTOWithErrorAsUnify => {
                 self.unify_fn = MachineState::unify_with_occurs_check_with_error;
+                self.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper;
             }
             &SystemClauseType::HomeDirectory => {
                 let path = match dirs_next::home_dir() {