]> Repositorios git - scryer-prolog.git/commitdiff
re: issues #200, #201
authorMark Thom <[email protected]>
Tue, 15 Oct 2019 06:42:55 +0000 (00:42 -0600)
committerMark Thom <[email protected]>
Tue, 15 Oct 2019 06:42:55 +0000 (00:42 -0600)
Cargo.toml
src/prolog/clause_types.rs
src/prolog/lib/non_iso.pl
src/prolog/machine/machine_indices.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs

index f93f68d506d51ba255ebbd567f99a754f2e8d4b3..b6d1fe8ff1aa5b43075abbfcd4c0a9ba689cd4a6 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.108"
+version = "0.8.109"
 authors = ["Mark Thom <[email protected]>"]
 build = "build.rs"
 repository = "https://github.com/mthom/scryer-prolog"
index 45d79f48cd12638d3ef89e8476a879bf5cb573db..d474fe89f8aaf456088ccdb42b832a225ea0f496 100644 (file)
@@ -172,6 +172,7 @@ pub enum SystemClauseType {
     ExpandGoal,
     ExpandTerm,
     FetchGlobalVar,
+    FetchGlobalVarWithOffset,
     GetChar,
     TruncateIfNoLiftedHeapGrowthDiff,
     TruncateIfNoLiftedHeapGrowth,
@@ -207,10 +208,12 @@ pub enum SystemClauseType {
     RemoveCallPolicyCheck,
     RemoveInferenceCounter,
     ResetGlobalVarAtKey,
+    ResetGlobalVarAtOffset,
     RetractClause,
     RestoreCutPolicy,
     SetCutPoint(RegType),
     StoreGlobalVar,
+    StoreGlobalVarWithOffset,
     InferenceLevel,
     CleanUpBlock,
     EraseBall,
@@ -280,6 +283,9 @@ impl SystemClauseType {
             &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
             &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
             &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
+            &SystemClauseType::FetchGlobalVarWithOffset => {
+                clause_name!("$fetch_global_var_with_offset")
+            }
             &SystemClauseType::GetChar => clause_name!("$get_char"),
             &SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
                 clause_name!("$truncate_if_no_lh_growth")
@@ -324,6 +330,9 @@ impl SystemClauseType {
             &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"),
             &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"),
             &SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"),
+            &SystemClauseType::StoreGlobalVarWithOffset => {
+                clause_name!("$store_global_var_with_offset")
+            }
             &SystemClauseType::InferenceLevel => clause_name!("$inference_level"),
             &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"),
             &SystemClauseType::EraseBall => clause_name!("$erase_ball"),
@@ -336,6 +345,7 @@ impl SystemClauseType {
             &SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
             &SystemClauseType::ReadTerm => clause_name!("$read_term"),
             &SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
+            &SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
             &SystemClauseType::RetractClause => clause_name!("$retract_clause"),
             &SystemClauseType::ResetBlock => clause_name!("$reset_block"),
             &SystemClauseType::ReturnFromAttributeGoals => {
@@ -386,6 +396,7 @@ impl SystemClauseType {
             ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
             ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
             ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
+            ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
             ("$get_char", 1) => Some(SystemClauseType::GetChar),
             ("$truncate_if_no_lh_growth", 1) => {
                 Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
@@ -432,6 +443,7 @@ impl SystemClauseType {
             ("$read_term", 2) => Some(SystemClauseType::ReadTerm),
             ("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
             ("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
+            ("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset),
             ("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
             ("$return_from_attribute_goals", 0) => Some(SystemClauseType::ReturnFromAttributeGoals),
             ("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
@@ -440,6 +452,7 @@ impl SystemClauseType {
             ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
             ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
             ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
+            ("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
             ("$submit_query_and_print_results", 2) => Some(SystemClauseType::REPL(
                 REPLCodePtr::SubmitQueryAndPrintResults,
             )),
index 14accf43b08b6241f4e6bb91101ee5e611a8e060..22104e31a5cfad9505fda54a46c742eac1f2c858 100644 (file)
@@ -12,21 +12,32 @@ forall(Generate, Test) :-
 
 %% (non-)backtrackable global variables.
 
-bb_put(Key, Value) :- atom(Key),
-                     !,
-                     '$store_global_var'(Key, Value).
+bb_put(Key, Value) :- atom(Key), !, '$store_global_var'(Key, Value).
 bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)).
 
+%% backtrackable global variables.
+
 bb_b_put(Key, NewValue) :-
-    (  bb_get(Key, OldValue) ->
-       call_cleanup((store_global_var(Key, NewValue) ; false), store_global_var(Key, OldValue))
-    ;  call_cleanup((store_global_var(Key, NewValue) ; false), reset_global_var_at_key(Key))
+    (  '$bb_get_with_offset'(Key, OldValue, OldOffset) ->
+       call_cleanup((store_global_var_with_offset(Key, NewValue) ; false),
+                   reset_global_var_at_offset(Key, OldValue, OldOffset))
+    ;  call_cleanup((store_global_var(Key, NewValue, _) ; false),
+                   reset_global_var_at_key(Key))
     ).
 
+store_global_var_with_offset(Key, Value) :- '$store_global_var_with_offset'(Key, Value).
+
 store_global_var(Key, Value) :- '$store_global_var'(Key, Value).
 
 reset_global_var_at_key(Key) :- '$reset_global_var_at_key'(Key).
 
+reset_global_var_at_offset(Key, Value, Offset) :- '$reset_global_var_at_offset'(Key, Value, Offset).
+
+'$bb_get_with_offset'(Key, OldValue, Offset) :-
+    atom(Key), !, '$fetch_global_var_with_offset'(Key, OldValue, Offset).
+'$bb_get_with_offset'(Key, _, _) :-
+    throw(error(type_error(atom, Key), bb_b_put/2)).
+
 bb_get(Key, Value) :- atom(Key), !, '$fetch_global_var'(Key, Value).
 bb_get(Key, _) :- throw(error(type_error(atom, Key), bb_get/2)).
 
index e4e4266841d9d2fa0d77084768814225e3de2bdc..d7cd07f1d7fa270dafe62ff37d41b779d9a2121a 100644 (file)
@@ -455,7 +455,7 @@ pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
 // key type: module name, predicate indicator.
 pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
 
-pub type GlobalVarDir = IndexMap<ClauseName, Ball>;
+pub type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<usize>)>;
 
 pub struct IndexStore {
     pub(super) atom_tbl: TabledData<Atom>,
index f4864dbe83794520e6e7706ae539166892e5d1fc..dc1051d6d036d13406af1b8ff0cc19684909b8c9 100644 (file)
@@ -419,6 +419,8 @@ pub(crate) trait CallPolicy: Any {
             machine_st.registers[i] = machine_st.or_stack[b][i].clone();
         }
 
+        // necessary because of restore_snapshot. similarly for other choice instructions.
+        machine_st.num_of_args = n;
         machine_st.e = machine_st.or_stack[b].e;
         machine_st.cp = machine_st.or_stack[b].cp.clone();
 
@@ -462,6 +464,7 @@ pub(crate) trait CallPolicy: Any {
             machine_st.registers[i] = machine_st.or_stack[b][i].clone();
         }
 
+        machine_st.num_of_args = n;
         machine_st.e = machine_st.or_stack[b].e;
         machine_st.cp = machine_st.or_stack[b].cp.clone();
 
@@ -505,6 +508,7 @@ pub(crate) trait CallPolicy: Any {
             machine_st.registers[i] = machine_st.or_stack[b][i].clone();
         }
 
+        machine_st.num_of_args = n;
         machine_st.e = machine_st.or_stack[b].e;
         machine_st.cp = machine_st.or_stack[b].cp.clone();
 
@@ -549,6 +553,7 @@ pub(crate) trait CallPolicy: Any {
             machine_st.registers[i] = machine_st.or_stack[b][i].clone();
         }
 
+        machine_st.num_of_args = n;
         machine_st.e = machine_st.or_stack[b].e;
         machine_st.cp = machine_st.or_stack[b].cp.clone();
 
index 6225f9aba05bb45823e966f6417062b588874ca6..4709a662612a6e4bddbf8611b1c51c022731d5d4 100644 (file)
@@ -114,8 +114,8 @@ impl MachineState {
     }
 
     #[allow(dead_code)]
-    pub fn print_heap(&self) {
-        for h in 0..self.heap.h {
+    pub fn print_heap(&self, start: usize) {
+        for h in start .. self.heap.h {
             println!("{} : {}", h, self.heap[h]);
         }
     }
@@ -2058,7 +2058,7 @@ impl MachineState {
                     for i in 1..narity + 1 {
                         self.registers[i] = self.heap[a + i].as_addr(a + i);
                     }
-
+                    
                     (name, narity)
                 } else {
                     self.fail = true;
@@ -3111,7 +3111,7 @@ impl MachineState {
         let gi = self.next_global_index();
 
         self.p += 1;
-
+        
         if self.e + 1 < self.and_stack.len() {
             let and_gi = self.and_stack[self.e].global_index;
             let or_gi = self
index 808fbb3189045a871f9c1a96c90b5119ffb56d63..1c6b4505162c5607752a0d8ae1748aaa22214a92 100644 (file)
@@ -744,7 +744,7 @@ impl Machine {
 
                 self.machine_st.p = top_level_code_ptr!(cn, p);
             }
-
+            
             self.machine_st.query_stepper(
                 &mut self.indices,
                 &mut self.policies,
index 855df0115d9918632a0cb765f496c33023925476..eecf307487e23931319bb448306d55f095d54ddd 100644 (file)
@@ -307,7 +307,7 @@ impl MachineState {
             }
         }
     }
-    
+
     #[inline]
     fn install_new_block(&mut self, r: RegType) -> usize {
         self.block = self.b;
@@ -840,17 +840,54 @@ impl MachineState {
 
                 let addr = self[temp_v!(2)].clone();
 
-                match indices.global_variables.get(&key) {
-                    Some(ref ball) => {
+                match indices.global_variables.get_mut(&key) {
+                    Some((ref mut ball, None)) => {
                         let h = self.heap.h;
                         let stub = ball.copy_and_align(h);
 
                         self.heap.extend(stub.into_iter());
                         self.unify(addr, Addr::HeapCell(h));
                     }
+                    Some((_, Some(h))) => {
+                        self.unify(addr, Addr::HeapCell(*h))
+                    }
                     None => self.fail = true,
                 };
             }
+            &SystemClauseType::FetchGlobalVarWithOffset => {
+                let key = self[temp_v!(1)].clone();
+
+                let key = match self.store(self.deref(key)) {
+                    Addr::Con(Constant::Atom(atom, _)) => atom,
+                    _ => unreachable!(),
+                };
+
+                let addr = self[temp_v!(2)].clone();
+
+                match indices.global_variables.get_mut(&key) {
+                    Some((ref mut ball, ref mut offset @ None)) => {
+                        let h = self.heap.h;
+                        let stub = ball.copy_and_align(h);
+
+                        self.heap.extend(stub.into_iter());
+                        self.unify(addr, Addr::HeapCell(h));
+
+                        *offset = Some(h);
+                    }
+                    Some((_, Some(h))) => {
+                        let offset = self[temp_v!(3)].clone();
+
+                        self.unify(offset, Addr::Con(Constant::Usize(*h)));
+
+                        if !self.fail {
+                            self.unify(addr, Addr::HeapCell(*h));
+                        }
+                    }
+                    None => {
+                        self.fail = true
+                    }
+                };
+            }
             &SystemClauseType::GetChar => {
                 let result = current_input_stream.next();
                 let a1 = self[temp_v!(1)].clone();
@@ -980,7 +1017,7 @@ impl MachineState {
                         } else {
                             tail
                         };
-                       
+
                         self.heap[l1 + 1] = HeapCellValue::Addr(tail);
                         self.trail(TrailRef::AttrVarLink(l1 + 1, old_addr));
                     }
@@ -1273,7 +1310,7 @@ impl MachineState {
             &SystemClauseType::GetAttributedVariableList => {
                 let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
                 let attr_var_list = match attr_var {
-                    Addr::AttrVar(h) => h + 1,                    
+                    Addr::AttrVar(h) => h + 1,
                     attr_var @ Addr::HeapCell(_) | attr_var @ Addr::StackCell(..) => {
                         // create an AttrVar in the heap.
                         let h = self.heap.h;
@@ -1535,6 +1572,35 @@ impl MachineState {
 
                 indices.global_variables.swap_remove(&key);
             }
+            &SystemClauseType::ResetGlobalVarAtOffset => {
+                let key = self[temp_v!(1)].clone();
+
+                let key = match self.store(self.deref(key)) {
+                    Addr::Con(Constant::Atom(atom, _)) => atom,
+                    _ => unreachable!(),
+                };
+
+                let value = self[temp_v!(2)].clone();
+                let mut ball = Ball::new();
+                let h = self.heap.h;
+
+                ball.boundary = h;
+                copy_term(
+                    CopyBallTerm::new(&mut self.and_stack, &mut self.heap, &mut ball.stub),
+                    value,
+                );
+
+                let offset = self[temp_v!(3)].clone();
+
+                match self.store(self.deref(offset)) {
+                    Addr::Con(Constant::Usize(offset)) => {
+                        indices.global_variables.insert(key, (ball, Some(offset)))
+                    }
+                    _ => {
+                        indices.global_variables.insert(key, (ball, None))
+                    }
+                };
+            },
             &SystemClauseType::RemoveCallPolicyCheck => {
                 let restore_default = match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
                     Some(call_policy) => {
@@ -1617,10 +1683,10 @@ impl MachineState {
                 if let &Addr::Con(Constant::Usize(num_of_args)) = &self.and_stack[e][frame_len] {
                     self.num_of_args = num_of_args;
                 }
-                
+
                 self.deallocate();
                 self.p = CodePtr::Local(self.and_stack[e].interrupt_cp);
-                
+
                 return Ok(());
             }
             &SystemClauseType::RestoreCutPolicy => {
@@ -1771,7 +1837,7 @@ impl MachineState {
             &SystemClauseType::SkipMaxList =>
                 if let Err(err) = self.skip_max_list() {
                     return Err(err);
-                },            
+                },
             &SystemClauseType::StoreGlobalVar => {
                 let key = self[temp_v!(1)].clone();
 
@@ -1780,16 +1846,40 @@ impl MachineState {
                     _ => unreachable!(),
                 };
 
-                let value = self[temp_v!(2)].clone();                
+                let value = self[temp_v!(2)].clone();
                 let mut ball = Ball::new();
-                
+
                 ball.boundary = self.heap.h;
                 copy_term(
                     CopyBallTerm::new(&mut self.and_stack, &mut self.heap, &mut ball.stub),
                     value,
                 );
-                
-                indices.global_variables.insert(key, ball);
+
+                indices.global_variables.insert(key, (ball, None));
+            }
+            &SystemClauseType::StoreGlobalVarWithOffset => {
+                let key = self[temp_v!(1)].clone();
+
+                let key = match self.store(self.deref(key)) {
+                    Addr::Con(Constant::Atom(atom, _)) => atom,
+                    _ => unreachable!(),
+                };
+
+                let value = self[temp_v!(2)].clone();
+                let mut ball = Ball::new();
+                let h = self.heap.h;
+
+                ball.boundary = h;
+                copy_term(
+                    CopyBallTerm::new(&mut self.and_stack, &mut self.heap, &mut ball.stub),
+                    value.clone(),
+                );
+
+                let stub = ball.copy_and_align(h);
+                self.heap.extend(stub.into_iter());
+                indices.global_variables.insert(key, (ball, Some(h)));
+
+                self.unify(value, Addr::HeapCell(h));
             }
             &SystemClauseType::Succeed => {}
             &SystemClauseType::TermVariables => {