EnqueueAttributeGoal,
EnqueueAttributedVar,
FetchGlobalVar,
- FetchGlobalVarWithOffset,
FirstStream,
FlushOutput,
GetByte,
RemoveCallPolicyCheck,
RemoveInferenceCounter,
ResetContinuationMarker,
- ResetGlobalVarAtKey,
- ResetGlobalVarAtOffset,
RestoreCutPolicy,
SetCutPoint(RegType),
SetInput,
SetOutput,
+ StoreBacktrackableGlobalVar,
StoreGlobalVar,
- StoreGlobalVarWithOffset,
StreamProperty,
SetStreamPosition,
InferenceLevel,
&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"),
&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"),
&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"),
("$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),
("$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))),
("$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),
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).
%% (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).
}
}
+ #[inline]
+ pub(crate) fn is_empty(&self) -> bool {
+ self.h() == 0
+ }
+
#[inline]
pub(crate) fn pop(&mut self) {
let h = self.h();
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;
Ref(Ref),
AttrVarHeapLink(usize),
AttrVarListLink(usize, usize),
+ BlackboardEntry(usize),
+ BlackboardOffset(usize, usize), // key atom heap location, key value heap location
}
impl From<Ref> for TrailRef {
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
-pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
-pub type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<usize>)>;
-
-#[derive(Debug)]
-pub(crate) struct ModuleStub {
- pub(crate) in_situ_code_dir: InSituCodeDir,
-}
+pub type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<Addr>)>;
pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
pub(crate) type StreamDir = BTreeSet<Stream>;
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
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
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);
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
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);
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
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);
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
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);
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)
}
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;
+ }
}
}
}
}
- 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.
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!(),
+ }
+ }
}
}
}
&mut self,
indexing_lines: &Vec<IndexingLine>,
call_policy: &mut Box<dyn CallPolicy>,
+ global_variables: &mut GlobalVarDir,
) {
let mut index = 0;
let addr = match &indexing_lines[0] {
unreachable!()
}
- self.execute_indexed_choice_instr(instrs.first().unwrap(), call_policy);
+ self.execute_indexed_choice_instr(
+ instrs.first().unwrap(),
+ call_policy,
+ global_variables,
+ );
+
break;
}
}
&mut self,
instr: &IndexedChoiceInstruction,
call_policy: &mut Box<dyn CallPolicy>,
+ global_variables: &mut GlobalVarDir,
) {
match instr {
&IndexedChoiceInstruction::Try(offset) => {
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));
}
};
}
&mut self,
instr: &ChoiceInstruction,
call_policy: &mut Box<dyn CallPolicy>,
+ global_variables: &mut GlobalVarDir,
) {
match instr {
&ChoiceInstruction::TryMeElse(offset) => {
}
&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))
}
}
}
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)
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);
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!()
}
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,
}
}
}
+ /*
&SystemClauseType::ResetGlobalVarAtKey => {
let key = self[temp_v!(1)];
}
}
}
+ */
&SystemClauseType::ResetAttrVarState => {
self.attr_var_init.reset();
}
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()
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!()
}
}
};
- 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 => {