From 6c447da730e476f8bce3774ed4a9edf7567b92fc Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 22 Feb 2021 18:27:30 -0700 Subject: [PATCH] no longer generate a choice point in bb_b_put/2 (#742) --- src/clause_types.rs | 28 ++----- src/lib/iso_ext.pl | 39 ++++------ src/machine/heap.rs | 5 ++ src/machine/machine_indices.rs | 11 +-- src/machine/machine_state.rs | 70 ++++++++++++++---- src/machine/machine_state_impl.rs | 61 ++++++++++++++-- src/machine/mod.rs | 18 ++++- src/machine/system_calls.rs | 117 +++++++++++------------------- 8 files changed, 195 insertions(+), 154 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index ecfd0cbf..1804040a 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -186,7 +186,6 @@ pub enum SystemClauseType { EnqueueAttributeGoal, EnqueueAttributedVar, FetchGlobalVar, - FetchGlobalVarWithOffset, FirstStream, FlushOutput, GetByte, @@ -240,14 +239,12 @@ pub enum SystemClauseType { RemoveCallPolicyCheck, RemoveInferenceCounter, ResetContinuationMarker, - ResetGlobalVarAtKey, - ResetGlobalVarAtOffset, RestoreCutPolicy, SetCutPoint(RegType), SetInput, SetOutput, + StoreBacktrackableGlobalVar, StoreGlobalVar, - StoreGlobalVarWithOffset, StreamProperty, SetStreamPosition, InferenceLevel, @@ -434,9 +431,6 @@ impl SystemClauseType { &SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"), &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"), - &SystemClauseType::FetchGlobalVarWithOffset => { - clause_name!("$fetch_global_var_with_offset") - } &SystemClauseType::FirstStream => clause_name!("$first_stream"), &SystemClauseType::FlushOutput => clause_name!("$flush_output"), &SystemClauseType::GetByte => clause_name!("$get_byte"), @@ -527,10 +521,10 @@ impl SystemClauseType { &SystemClauseType::SetSeed => clause_name!("$set_seed"), &SystemClauseType::StreamProperty => clause_name!("$stream_property"), &SystemClauseType::SetStreamPosition => clause_name!("$set_stream_position"), - &SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"), - &SystemClauseType::StoreGlobalVarWithOffset => { - clause_name!("$store_global_var_with_offset") + &SystemClauseType::StoreBacktrackableGlobalVar => { + clause_name!("$store_back_trackable_global_var") } + &SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"), &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), &SystemClauseType::EraseBall => clause_name!("$erase_ball"), @@ -539,15 +533,10 @@ impl SystemClauseType { &SystemClauseType::GetCutPoint => clause_name!("$get_cp"), &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), - // &SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"), &SystemClauseType::NextEP => clause_name!("$nextEP"), &SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"), &SystemClauseType::ReadTerm => clause_name!("$read_term"), &SystemClauseType::ReadTermFromChars => clause_name!("$read_term_from_chars"), - &SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"), - &SystemClauseType::ResetGlobalVarAtOffset => { - clause_name!("$reset_global_var_at_offset") - } &SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::ResetContinuationMarker => clause_name!("$reset_cont_marker"), &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), @@ -654,9 +643,6 @@ impl SystemClauseType { ("$peek_code", 2) => Some(SystemClauseType::PeekCode), ("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), - ("$fetch_global_var_with_offset", 3) => { - Some(SystemClauseType::FetchGlobalVarWithOffset) - } ("$get_byte", 2) => Some(SystemClauseType::GetByte), ("$get_char", 2) => Some(SystemClauseType::GetChar), ("$get_n_chars", 3) => Some(SystemClauseType::GetNChars), @@ -723,8 +709,6 @@ impl SystemClauseType { ("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker), - ("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey), - ("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset), ("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr), ("$set_ball", 1) => Some(SystemClauseType::SetBall), ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), @@ -737,8 +721,8 @@ impl SystemClauseType { ("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept), ("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), - ("$store_global_var_with_offset", 2) => { - Some(SystemClauseType::StoreGlobalVarWithOffset) + ("$store_backtrackable_global_var", 2) => { + Some(SystemClauseType::StoreBacktrackableGlobalVar) } ("$term_attributed_variables", 2) => Some(SystemClauseType::TermAttributedVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables), diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index fe5d4baf..61a3fa29 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -9,7 +9,7 @@ partial_string_tail/2, setup_call_cleanup/3, call_nth/2, variant/2]). -:- use_module(library(error), [can_be/2,domain_error/3]). +:- use_module(library(error), [can_be/2, domain_error/3, type_error/3]). :- meta_predicate call_cleanup(0, 0). @@ -22,34 +22,25 @@ forall(Generate, Test) :- %% (non-)backtrackable global variables. -bb_put(Key, Value) :- atom(Key), !, '$store_global_var'(Key, Value). -bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)). +bb_put(Key, Value) :- + ( atom(Key) -> + '$store_global_var'(Key, Value) + ; type_error(atom, Key, bb_put/2) + ). %% backtrackable global variables. -bb_b_put(Key, NewValue) :- - ( '$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_with_offset(Key, NewValue) ; false), - reset_global_var_at_key(Key)) +bb_b_put(Key, Value) :- + ( atom(Key) -> + '$store_backtrackable_global_var'(Key, Value) + ; type_error(atom, Key, bb_b_put/2) ). -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)). +bb_get(Key, Value) :- + ( atom(Key) -> + '$fetch_global_var'(Key, Value) + ; type_error(atom, Key, bb_get/2) + ). call_cleanup(G, C) :- setup_call_cleanup(true, G, C). diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 7f9323c1..935bad8b 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -206,6 +206,11 @@ impl HeapTemplate { } } + #[inline] + pub(crate) fn is_empty(&self) -> bool { + self.h() == 0 + } + #[inline] pub(crate) fn pop(&mut self) { let h = self.h(); diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 336ab16c..04a60feb 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -12,7 +12,6 @@ use crate::machine::partial_string::*; use crate::machine::raw_block::RawBlockTraits; use crate::machine::streams::Stream; use crate::machine::term_stream::LoadStatePayload; -use crate::machine::Ball; use crate::machine::CompilationTarget; use crate::rug::{Integer, Rational}; use ordered_float::OrderedFloat; @@ -297,6 +296,8 @@ pub enum TrailRef { Ref(Ref), AttrVarHeapLink(usize), AttrVarListLink(usize, usize), + BlackboardEntry(usize), + BlackboardOffset(usize, usize), // key atom heap location, key value heap location } impl From for TrailRef { @@ -691,13 +692,7 @@ impl SubAssign for CodePtr { pub type HeapVarDict = IndexMap, Addr>; pub type AllocVarDict = IndexMap, VarData>; -pub type InSituCodeDir = IndexMap; -pub type GlobalVarDir = IndexMap)>; - -#[derive(Debug)] -pub(crate) struct ModuleStub { - pub(crate) in_situ_code_dir: InSituCodeDir, -} +pub type GlobalVarDir = IndexMap)>; pub(crate) type StreamAliasDir = IndexMap; pub(crate) type StreamDir = BTreeSet; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index b7ac7499..26686fd8 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -657,7 +657,12 @@ impl MachineState { pub(crate) type CallResult = Result<(), Vec>; pub(crate) trait CallPolicy: Any + fmt::Debug { - fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { + fn retry_me_else( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -679,7 +684,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -708,7 +713,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Ok(()) } - fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { + fn retry( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -730,7 +740,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -759,7 +769,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Ok(()) } - fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { + fn trust( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -779,7 +794,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -811,7 +826,11 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Ok(()) } - fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult { + fn trust_me( + &mut self, + machine_st: &mut MachineState, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -831,7 +850,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -1225,23 +1244,42 @@ impl CallPolicy for CWILCallPolicy { self.increment(machine_st) } - fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { - self.prev_policy.retry_me_else(machine_st, offset)?; + fn retry_me_else( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.retry_me_else(machine_st, offset, global_variables)?; self.increment(machine_st) } - fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { - self.prev_policy.retry(machine_st, offset)?; + fn retry( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.retry(machine_st, offset, global_variables)?; self.increment(machine_st) } - fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult { - self.prev_policy.trust_me(machine_st)?; + fn trust_me( + &mut self, + machine_st: &mut MachineState, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.trust_me(machine_st, global_variables)?; self.increment(machine_st) } - fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { - self.prev_policy.trust(machine_st, offset)?; + fn trust( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.trust(machine_st, offset, global_variables)?; self.increment(machine_st) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index d92a4f6f..5b946b0d 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -621,6 +621,14 @@ impl MachineState { self.tr += 1; } } + TrailRef::BlackboardOffset(key_h, value_h) => { + self.trail.push(TrailRef::BlackboardOffset(key_h, value_h)); + self.tr += 1; + } + TrailRef::BlackboardEntry(key_h) => { + self.trail.push(TrailRef::BlackboardEntry(key_h)); + self.tr += 1; + } } } @@ -644,7 +652,12 @@ impl MachineState { } } - pub(super) fn unwind_trail(&mut self, a1: usize, a2: usize) { + pub(super) fn unwind_trail( + &mut self, + a1: usize, + a2: usize, + global_variables: &mut GlobalVarDir, + ) { // the sequence is reversed to respect the chronology of trail // additions, now that deleted attributes can be undeleted by // backtracking. @@ -665,6 +678,30 @@ impl MachineState { TrailRef::AttrVarListLink(h, l) => { self.heap[h] = HeapCellValue::Addr(Addr::Lis(l)); } + TrailRef::BlackboardOffset(key_h, value_h) => { + let key = atom_from!( + self, + self.store(self.deref(self.heap[key_h].as_addr(key_h))) + ); + + let value_addr = self.heap[value_h].as_addr(value_h); + + match global_variables.get_mut(&key) { + Some((_, ref mut loc)) => *loc = Some(value_addr), + None => unreachable!(), + } + } + TrailRef::BlackboardEntry(key_h) => { + let key = atom_from!( + self, + self.store(self.deref(self.heap[key_h].as_addr(key_h))) + ); + + match global_variables.get_mut(&key) { + Some((_, ref mut loc)) => *loc = None, + None => unreachable!(), + } + } } } } @@ -1266,6 +1303,7 @@ impl MachineState { &mut self, indexing_lines: &Vec, call_policy: &mut Box, + global_variables: &mut GlobalVarDir, ) { let mut index = 0; let addr = match &indexing_lines[0] { @@ -1372,7 +1410,12 @@ impl MachineState { unreachable!() } - self.execute_indexed_choice_instr(instrs.first().unwrap(), call_policy); + self.execute_indexed_choice_instr( + instrs.first().unwrap(), + call_policy, + global_variables, + ); + break; } } @@ -2989,6 +3032,7 @@ impl MachineState { &mut self, instr: &IndexedChoiceInstruction, call_policy: &mut Box, + global_variables: &mut GlobalVarDir, ) { match instr { &IndexedChoiceInstruction::Try(offset) => { @@ -3018,10 +3062,10 @@ impl MachineState { self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset)); } &IndexedChoiceInstruction::Retry(l) => { - try_or_fail!(self, call_policy.retry(self, l)); + try_or_fail!(self, call_policy.retry(self, l, global_variables)); } &IndexedChoiceInstruction::Trust(l) => { - try_or_fail!(self, call_policy.trust(self, l)); + try_or_fail!(self, call_policy.trust(self, l, global_variables)); } }; } @@ -3030,6 +3074,7 @@ impl MachineState { &mut self, instr: &ChoiceInstruction, call_policy: &mut Box, + global_variables: &mut GlobalVarDir, ) { match instr { &ChoiceInstruction::TryMeElse(offset) => { @@ -3059,17 +3104,17 @@ impl MachineState { } &ChoiceInstruction::DefaultRetryMeElse(offset) => { let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.retry_me_else(self, offset)) + try_or_fail!(self, call_policy.retry_me_else(self, offset, global_variables)) } &ChoiceInstruction::DefaultTrustMe(_) => { let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.trust_me(self)) + try_or_fail!(self, call_policy.trust_me(self, global_variables)) } &ChoiceInstruction::RetryMeElse(offset) => { - try_or_fail!(self, call_policy.retry_me_else(self, offset)) + try_or_fail!(self, call_policy.retry_me_else(self, offset, global_variables)) } &ChoiceInstruction::TrustMe(_) => { - try_or_fail!(self, call_policy.trust_me(self)) + try_or_fail!(self, call_policy.trust_me(self, global_variables)) } } } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 6e3bd4eb..d23580ba 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -560,7 +560,11 @@ impl MachineState { match instr { &Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr), &Line::Choice(ref choice_instr) => { - self.execute_choice_instr(choice_instr, &mut policies.call_policy) + self.execute_choice_instr( + choice_instr, + &mut policies.call_policy, + &mut indices.global_variables, + ) } &Line::Cut(ref cut_instr) => { self.execute_cut_instr(cut_instr, &mut policies.cut_policy) @@ -579,10 +583,18 @@ impl MachineState { self.p += 1; } &Line::IndexingCode(ref indexing_lines) => { - self.execute_indexing_instr(indexing_lines, &mut policies.call_policy) + self.execute_indexing_instr( + indexing_lines, + &mut policies.call_policy, + &mut indices.global_variables, + ) } &Line::IndexedChoice(ref choice_instr) => { - self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy) + self.execute_indexed_choice_instr( + choice_instr, + &mut policies.call_policy, + &mut indices.global_variables, + ) } &Line::Query(ref query_instr) => { self.execute_query_instr(&query_instr); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 0d94fd1c..72e6b3a9 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1850,12 +1850,10 @@ impl MachineState { self.copy_term(AttrVarPolicy::StripAttributes); } &SystemClauseType::FetchGlobalVar => { - let key = self[temp_v!(1)]; - - let key = match self.store(self.deref(key)) { + let (key_h, key) = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - atom.clone() + (h, atom.clone()) } else { unreachable!() } @@ -1868,52 +1866,24 @@ impl MachineState { let addr = self[temp_v!(2)]; 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)]; - - let key = match self.store(self.deref(key)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - atom.clone() - } else { - unreachable!() - } - } - _ => { - unreachable!() - } - }; - - let addr = self[temp_v!(2)]; - - 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)]; + Some((ref ball, ref mut loc)) => { + match loc { + Some(ref value_addr) => { + self.unify(addr, *value_addr); + } + loc @ None if !ball.stub.is_empty() => { + let h = self.heap.h(); + let stub = ball.copy_and_align(h); - self.unify(offset, Addr::Usize(*h)); + self.heap.extend(stub.into_iter()); + self.unify(addr, Addr::HeapCell(h)); - if !self.fail { - self.unify(addr, Addr::HeapCell(*h)); + if !self.fail { + *loc = Some(Addr::HeapCell(h)); + self.trail(TrailRef::BlackboardEntry(key_h)); + } + } + _ => self.fail = true, } } None => self.fail = true, @@ -3572,6 +3542,7 @@ impl MachineState { } } } + /* &SystemClauseType::ResetGlobalVarAtKey => { let key = self[temp_v!(1)]; @@ -3626,6 +3597,7 @@ impl MachineState { } } } + */ &SystemClauseType::ResetAttrVarState => { self.attr_var_init.reset(); } @@ -4539,9 +4511,7 @@ impl MachineState { self.unify(self[temp_v!(3)], property); } &SystemClauseType::StoreGlobalVar => { - let key = self[temp_v!(1)]; - - let key = match self.store(self.deref(key)) { + let key = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { atom.clone() @@ -4567,13 +4537,11 @@ impl MachineState { indices.global_variables.insert(key, (ball, None)); } - &SystemClauseType::StoreGlobalVarWithOffset => { - let key = self[temp_v!(1)]; - - let key = match self.store(self.deref(key)) { + &SystemClauseType::StoreBacktrackableGlobalVar => { + let (key_h, key) = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - atom.clone() + (h, atom.clone()) } else { unreachable!() } @@ -4583,24 +4551,27 @@ impl MachineState { } }; - let value = self[temp_v!(2)]; - let mut ball = Ball::new(); - let h = self.heap.h(); - - ball.boundary = h; + let new_value = self.store(self.deref(self[temp_v!(2)])); - copy_term( - CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub), - value, - AttrVarPolicy::DeepCopy, - ); - - 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)); + match indices.global_variables.get_mut(&key) { + Some((_, ref mut loc)) => { + match loc { + Some(ref mut value) => { + let old_value_loc = self.heap.push(HeapCellValue::Addr(*value)); + self.trail(TrailRef::BlackboardOffset(key_h, old_value_loc)); + *value = new_value; + } + loc @ None => { + self.trail(TrailRef::BlackboardEntry(key_h)); + *loc = Some(new_value); + } + } + } + None => { + self.trail(TrailRef::BlackboardEntry(key_h)); + indices.global_variables.insert(key, (Ball::new(), Some(new_value))); + } + } } &SystemClauseType::Succeed => {} &SystemClauseType::TermAttributedVariables => { -- 2.54.0