From: Mark Thom Date: Tue, 15 Oct 2019 06:42:55 +0000 (-0600) Subject: re: issues #200, #201 X-Git-Tag: v0.8.110~2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=c4269b87c2ebe484c6015c8c6c54db8e1da107de;p=scryer-prolog.git re: issues #200, #201 --- diff --git a/Cargo.toml b/Cargo.toml index f93f68d5..b6d1fe8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.108" +version = "0.8.109" authors = ["Mark Thom "] build = "build.rs" repository = "https://github.com/mthom/scryer-prolog" diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 45d79f48..d474fe89 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -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, )), diff --git a/src/prolog/lib/non_iso.pl b/src/prolog/lib/non_iso.pl index 14accf43..22104e31 100644 --- a/src/prolog/lib/non_iso.pl +++ b/src/prolog/lib/non_iso.pl @@ -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)). diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index e4e42668..d7cd07f1 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -455,7 +455,7 @@ pub type InSituCodeDir = IndexMap; // key type: module name, predicate indicator. pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>; -pub type GlobalVarDir = IndexMap; +pub type GlobalVarDir = IndexMap)>; pub struct IndexStore { pub(super) atom_tbl: TabledData, diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index f4864dbe..dc1051d6 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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(); diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 6225f9ab..4709a662 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -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 diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 808fbb31..1c6b4505 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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, diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 855df011..eecf3074 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -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::().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 => {