[[package]]
name = "prolog_parser"
-version = "0.8.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.8.37"
dependencies = [
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "prolog_parser 0.8.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "prolog_parser 0.8.37",
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustyline 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6"
"checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-"checksum prolog_parser 0.8.36 (registry+https://github.com/rust-lang/crates.io-index)" = "fea0ae985b51f28cb3582469fbe9318e238d504a7358d90eb671f0d772fb5061"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
nix = "0.15.0"
num-rug-adapter = { optional = true, version = "0.1.1" }
ordered-float = "0.5.0"
-prolog_parser = { version = "0.8.36", default-features = false }
+prolog_parser = { version = "0.8.37", default-features = false }
ref_thread_local = "0.0.0"
rug = { version = "1.4.0", optional = true }
rustyline = "5.0.3"
`retract/1`, `abolish/1`) with logical update semantics.
- [x] Backtrackable and non-backtrackable global variables via `bb_get/2`
`bb_put/2` (non-backtrackable) and `bb_b_put/2`
- (backtrackable).
+ (backtrackable).
+- [ ] Delimited continuations based on reset/3, shift/1 (documented in
+ "Delimited Continuations for Prolog") (_in progress_).
- [ ] clp(B) and clp(ℤ) as builtin libraries (_in progress_).
- [ ] Streams and predicates for stream control (_in progress_).
- [ ] An incremental compacting garbage collector satisfying the five
unum implementation or an ad hoc one. Unums are described in
Gustafson's book "The End of Error."
-3. Add support for shift/reset delimited continuations, see "Delimited
-Continuations for Prolog."
-
-4. Add concurrent tables to manage shared references to atoms and
+3. Add concurrent tables to manage shared references to atoms and
strings.
-5. Add optional SLG resolution for fast memoization of predicates.
+4. Add optional SLG resolution for fast memoization of predicates.
-6. Add some form of JIT predicate indexing.
+5. Add some form of JIT predicate indexing.
## Installing Scryer Prolog
AtomLength,
BindFromRegister,
CallAttributeGoals,
+ CallContinuation,
CharCode,
CharsToNumber,
ClearAttrVarBindings,
GetAttrVarQueueBeyond,
GetBValue,
GetClause,
+ GetContinuationChunk,
GetModuleClause,
GetNextDBRef,
GetNextOpDBRef,
ModuleExists,
ModuleOf,
ModuleRetractClause,
+ NextEP,
NoSuchPredicate,
NumberToChars,
NumberToCodes,
OpDeclaration,
+ PointsToContinuationResetMarker,
REPL(REPLCodePtr),
ReadQueryTerm,
ReadTerm,
TermVariables,
TruncateLiftedHeapTo,
UnifyWithOccursCheck,
+ UnwindEnvironments,
UnwindStack,
Variant,
WAMInstructions,
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
&SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"),
&SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
+ &SystemClauseType::CallContinuation => clause_name!("$call_continuation"),
&SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
&SystemClauseType::ClearAttributeGoals => clause_name!("$clear_attribute_goals"),
clause_name!("$get_attr_var_queue_delim")
}
&SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"),
+ &SystemClauseType::GetContinuationChunk => clause_name!("$get_cont_chunk"),
&SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"),
&SystemClauseType::GetLiftedHeapFromOffsetDiff => {
clause_name!("$get_lh_from_offset_diff")
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
&SystemClauseType::NumberToCodes => clause_name!("$number_to_codes"),
+ &SystemClauseType::PointsToContinuationResetMarker => {
+ clause_name!("$points_to_cont_reset_marker")
+ }
&SystemClauseType::RawInputReadChar => clause_name!("$raw_input_read_char"),
&SystemClauseType::RedoAttrVarBinding => clause_name!("$redo_attr_var_binding"),
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
&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::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
&SystemClauseType::TermVariables => clause_name!("$term_variables"),
&SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"),
&SystemClauseType::UnifyWithOccursCheck => clause_name!("$unify_with_occurs_check"),
+ &SystemClauseType::UnwindEnvironments => clause_name!("$unwind_environments"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
&SystemClauseType::Variant => clause_name!("$variant"),
&SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
+ ("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
("$char_code", 2) => Some(SystemClauseType::CharCode),
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
("$clear_attr_var_bindings", 0) => Some(SystemClauseType::ClearAttrVarBindings),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_char", 1) => Some(SystemClauseType::GetChar),
+ ("$points_to_cont_reset_marker", 1) => {
+ Some(SystemClauseType::PointsToContinuationResetMarker)
+ }
("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState),
("$truncate_if_no_lh_growth", 1) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
("$get_attr_var_queue_beyond", 2) => Some(SystemClauseType::GetAttrVarQueueBeyond),
("$get_attr_var_queue_delim", 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter),
("$get_ball", 1) => Some(SystemClauseType::GetBall),
+ ("$get_cont_chunk", 3) => Some(SystemClauseType::GetContinuationChunk),
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar),
+ ("$nextEP", 3) => Some(SystemClauseType::NextEP),
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
("$term_variables", 2) => Some(SystemClauseType::TermVariables),
("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
+ ("$unwind_environments", 0) => Some(SystemClauseType::UnwindEnvironments),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
});
}
Constant::CharCode(c) => self.append_str(&format!("{}", c)),
+ Constant::CutPoint(b) => self.append_str(&format!("{}", b)),
Constant::EmptyList => self.append_str("[]"),
Constant::Integer(n) => self.print_number(Number::Integer(n), op),
Constant::Float(n) => self.print_number(Number::Float(n), op),
}
impl ControlInstruction {
+ pub fn perm_vars(&self) -> Option<usize> {
+ match self {
+ ControlInstruction::CallClause(_, _, num_cells, ..) =>
+ Some(*num_cells),
+ ControlInstruction::JmpBy(_, _, num_cells, ..) =>
+ Some(*num_cells),
+ _ =>
+ None
+ }
+ }
+
pub fn to_functor(&self) -> MachineStub {
match self {
&ControlInstruction::Allocate(num_frames) => {
get_chunks(E, P, L) :-
( '$points_to_cont_reset_marker'(P) ->
L = []
- ; '$get_chunk'(E,P,TB),
+ ; '$get_cont_chunk'(E,P,TB),
L = [TB|Rest],
'$nextEP'(E, NextE, NextP),
get_chunks(NextE, NextP, Rest)
call_continuation(L) :- '$call_continuation'(L).
'$write_cont_and_term'(_, _, _, _).
-
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)].clone();
}
- self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = Addr::Con(Constant::Usize(self.b0));
+ self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = Addr::Con(Constant::CutPoint(self.b0));
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] = Addr::Con(Constant::Usize(self.num_of_args));
self.verify_attributes();
self.push(hcv);
}
}
+
+ pub fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
+ let extract_integer = |s: usize| -> Option<usize> {
+ match self.heap[s].as_addr(s) {
+ Addr::Con(Constant::Integer(n)) => n.to_usize(),
+ _ => None
+ }
+ };
+
+ match addr {
+ Addr::Str(s) => {
+ match &self.heap[*s] {
+ HeapCellValue::NamedStr(arity, ref name, _) => {
+ match (name.as_str(), *arity) {
+ ("dir_entry", 1) => {
+ extract_integer(s+1).map(LocalCodePtr::DirEntry)
+ }
+ ("in_situ_dir_entry", 1) => {
+ extract_integer(s+1).map(LocalCodePtr::InSituDirEntry)
+ }
+ ("top_level", 2) => {
+ if let Some(chunk_num) = extract_integer(s+1) {
+ if let Some(p) = extract_integer(s+2) {
+ return Some(LocalCodePtr::TopLevel(chunk_num, p));
+ }
+ }
+
+ None
+ }
+ ("user_goal_expansion", 1) => {
+ extract_integer(s+1).map(LocalCodePtr::UserGoalExpansion)
+ }
+ ("user_term_expansion", 1) => {
+ extract_integer(s+1).map(LocalCodePtr::UserTermExpansion)
+ }
+ _ => None
+ }
+ }
+ _ => unreachable!()
+ }
+ }
+ _ => None
+ }
+ }
}
impl Index<usize> for Heap {
use crate::prolog::clause_types::*;
use crate::prolog::fixtures::*;
use crate::prolog::forms::*;
+use crate::prolog::machine::code_repo::CodeRepo;
use crate::prolog::machine::Ball;
+use crate::prolog::machine::heap::Heap;
+use crate::prolog::instructions::*;
+use crate::prolog::rug::Integer;
use indexmap::IndexMap;
_ => {}
}
}
+
+ pub fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool {
+ match code_repo.lookup_instr(last_call, &CodePtr::Local(*self)) {
+ Some(line) => {
+ match line.as_ref() {
+ Line::Control(ControlInstruction::CallClause(ref ct, ..)) => {
+ if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct {
+ return true;
+ }
+ }
+ _ => {}
+ }
+ }
+ None => {}
+ }
+
+ false
+ }
+
+ pub fn as_functor(&self, heap: &mut Heap) -> Addr {
+ let addr = Addr::HeapCell(heap.h);
+
+ match self {
+ LocalCodePtr::DirEntry(p) => {
+ heap.append(functor!(
+ "dir_entry",
+ 1,
+ [heap_integer!(Integer::from(*p))]
+ ));
+ }
+ LocalCodePtr::InSituDirEntry(p) => {
+ heap.append(functor!(
+ "in_situ_dir_entry",
+ 1,
+ [heap_integer!(Integer::from(*p))]
+ ));
+ }
+ LocalCodePtr::TopLevel(chunk_num, offset) => {
+ heap.append(functor!(
+ "top_level",
+ 2,
+ [heap_integer!(Integer::from(*chunk_num)),
+ heap_integer!(Integer::from(*offset))]
+ ));
+ }
+ LocalCodePtr::UserGoalExpansion(p) => {
+ heap.append(functor!(
+ "user_goal_expansion",
+ 1,
+ [heap_integer!(Integer::from(*p))]
+ ));
+ }
+ LocalCodePtr::UserTermExpansion(p) => {
+ heap.append(functor!(
+ "user_term_expansion",
+ 1,
+ [heap_integer!(Integer::from(*p))]
+ ));
+ }
+ }
+
+ addr
+ }
}
impl PartialOrd<CodePtr> for CodePtr {
}
}
+impl Sub<usize> for LocalCodePtr {
+ type Output = Option<LocalCodePtr>;
+
+ fn sub(self, rhs: usize) -> Self::Output {
+ match self {
+ LocalCodePtr::InSituDirEntry(p) =>
+ p.checked_sub(rhs).map(LocalCodePtr::InSituDirEntry),
+ LocalCodePtr::DirEntry(p) =>
+ p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
+ LocalCodePtr::TopLevel(cn, p) =>
+ p.checked_sub(rhs).map(|r| LocalCodePtr::TopLevel(cn, r)),
+ LocalCodePtr::UserTermExpansion(p) =>
+ p.checked_sub(rhs).map(LocalCodePtr::UserTermExpansion),
+ LocalCodePtr::UserGoalExpansion(p) =>
+ p.checked_sub(rhs).map(LocalCodePtr::UserGoalExpansion),
+ }
+ }
+}
+
impl AddAssign<usize> for LocalCodePtr {
fn add_assign(&mut self, rhs: usize) {
match self {
fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
let b = machine_st.b;
- if let Addr::Con(Constant::Usize(b0)) = addr {
- if b > b0 {
- machine_st.b = b0;
- machine_st.tidy_trail();
- machine_st.tidy_pstr_trail();
- machine_st.truncate_stack();
+ match addr {
+ Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
+ if b > b0 {
+ machine_st.b = b0;
+ machine_st.tidy_trail();
+ machine_st.tidy_pstr_trail();
+ machine_st.truncate_stack();
+ }
}
- } else {
- machine_st.fail = true;
- return true;
- }
+ _ => {
+ machine_st.fail = true;
+ return true;
+ }
+ };
false
}
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
let b = machine_st.b;
- if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() {
- if b > b0 {
- machine_st.b = b0;
- machine_st.tidy_trail();
- machine_st.tidy_pstr_trail();
+ match machine_st[r].clone() {
+ Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
+ if b > b0 {
+ machine_st.b = b0;
+ machine_st.tidy_trail();
+ machine_st.tidy_pstr_trail();
+ machine_st.truncate_stack();
+ }
+ }
+ _ => {
+ machine_st.fail = true;
+ return true;
}
- } else {
- machine_st.fail = true;
- return true;
}
self.run_cleaners(machine_st)
&CutInstruction::GetLevel(r) => {
let b0 = self.b0;
- self[r] = Addr::Con(Constant::Usize(b0));
+ self[r] = Addr::Con(Constant::CutPoint(b0));
self.p += 1;
}
&CutInstruction::GetLevelAndUnify(r) => {
functors
}
+ fn call_continuation_chunk(&mut self, chunk: Addr, return_p: LocalCodePtr) -> LocalCodePtr {
+ let chunk = self.store(self.deref(chunk));
+
+ match chunk {
+ Addr::Str(s) => {
+ match &self.heap[s] {
+ HeapCellValue::NamedStr(arity, ..) => {
+ let num_cells = arity - 1;
+ let p_functor = self.heap[s+1].as_addr(s+1);
+
+ let cp = self.heap.to_local_code_ptr(&p_functor).unwrap();
+ let prev_e = self.e;
+
+ let e = self.stack.allocate_and_frame(num_cells);
+ let and_frame = self.stack.index_and_frame_mut(e);
+
+ and_frame.prelude.e = prev_e;
+ and_frame.prelude.cp = return_p;
+
+ self.p = CodePtr::Local(cp + 1);
+
+ // adjust cut point to occur after call_continuation.
+ if num_cells > 0 {
+ if let Addr::Con(Constant::CutPoint(_)) = self.heap[s+2].as_addr(s+2) {
+ and_frame[1] = Addr::Con(Constant::CutPoint(self.b));
+ } else {
+ and_frame[1] = self.heap[s+2].as_addr(s+2);
+ }
+ }
+
+ for index in s+3 .. s+2+num_cells {
+ and_frame[index - (s+1)] = self.heap[index].as_addr(index);
+ }
+
+ self.e = e;
+
+ self.p.local()
+ }
+ _ => unreachable!()
+ }
+ }
+ _ => unreachable!()
+ }
+ }
+
pub(super) fn system_call(
&mut self,
ct: &SystemClauseType,
Addr::Con(Constant::Integer(n)) => n.to_usize(),
_ => unreachable!()
};
-
+
if let Some(n) = n {
if n <= MAX_ARITY {
let target = self[temp_v!(n)].clone();
let addr = self[temp_v!(1)].clone();
-
+
self.unify(addr, target);
return return_from_clause!(self.last_call, self);
}
}
-
+
self.fail = true;
}
&SystemClauseType::AssertDynamicPredicateToFront => {
return Ok(());
}
+ &SystemClauseType::CallContinuation => {
+ let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1);
+
+ match self.try_from_list(temp_v!(1), stub) {
+ Err(e) => return Err(e),
+ Ok(cont_chunks) => {
+ let mut return_p = if self.last_call {
+ self.cp
+ } else {
+ self.p.local() + 1
+ };
+
+ self.p = CodePtr::Local(return_p);
+
+ for chunk in cont_chunks.into_iter().rev() {
+ return_p = self.call_continuation_chunk(chunk, return_p);
+ }
+ }
+ }
+
+ return Ok(());
+ }
&SystemClauseType::CharsToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
match addr {
- Addr::Con(Constant::Usize(old_b)) => {
+ Addr::Con(Constant::Usize(old_b)) | Addr::Con(Constant::CutPoint(old_b)) => {
let prev_b = self.stack.index_or_frame(self.b).prelude.b;
let prev_b = self.stack.index_or_frame(prev_b).prelude.b;
_ => self.fail = true,
}
}
+ &SystemClauseType::GetContinuationChunk => {
+ let e = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ let e = if let Addr::Con(Constant::Usize(e)) = e {
+ e
+ } else {
+ self.fail = true;
+ return Ok(());
+ };
+
+ let p_functor = self.store(self.deref(self[temp_v!(2)].clone()));
+ let p = self.heap.to_local_code_ptr(&p_functor).unwrap();
+
+ let num_cells = match code_repo.lookup_instr(self.last_call, &CodePtr::Local(p)) {
+ Some(line) => {
+ let perm_vars = match line.as_ref() {
+ Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(),
+ _ => None
+ };
+
+ perm_vars.unwrap()
+ }
+ _ => unreachable!()
+ };
+
+ let mut addrs = vec![];
+
+ for index in 1 .. num_cells + 1 {
+ addrs.push(self.stack.index_and_frame(e)[index].clone());
+ }
+
+ let chunk = Addr::HeapCell(self.heap.h);
+
+ self.heap.push(HeapCellValue::NamedStr(
+ 1 + num_cells,
+ clause_name!("cont_chunk"),
+ None,
+ ));
+
+ self.heap.push(HeapCellValue::Addr(p_functor));
+ self.heap.extend(addrs.into_iter().map(HeapCellValue::Addr));
+
+ self.unify(self[temp_v!(3)].clone(), chunk);
+ }
&SystemClauseType::GetLiftedHeapFromOffsetDiff => {
let lh_offset = self[temp_v!(1)].clone();
}
match (a1, a2.clone()) {
- (Addr::Con(Constant::Usize(bp)), Addr::Con(Constant::Integer(n))) => {
+ (Addr::Con(Constant::Usize(bp)), Addr::Con(Constant::Integer(n)))
+ | (Addr::Con(Constant::CutPoint(bp)), Addr::Con(Constant::Integer(n))) => {
match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
Some(call_policy) => {
let count = call_policy.add_limit(n, bp);
Some(call_policy) => {
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
- if let Addr::Con(Constant::Usize(bp)) = a1 {
- if call_policy.is_empty() && bp == self.b {
- Some(call_policy.into_inner())
- } else {
- None
+ match a1 {
+ Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
+ if call_policy.is_empty() && bp == self.b {
+ Some(call_policy.into_inner())
+ } else {
+ None
+ }
+ }
+ _ => {
+ panic!("remove_call_policy_check: expected Usize in A1.");
}
- } else {
- panic!("remove_call_policy_check: expected Usize in A1.");
}
}
None => panic!(
Some(call_policy) => {
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
- if let Addr::Con(Constant::Usize(bp)) = a1 {
- let count = call_policy.remove_limit(bp);
- let count = Addr::Con(Constant::Integer(count.clone()));
+ match a1 {
+ Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
+ let count = call_policy.remove_limit(bp);
+ let count = Addr::Con(Constant::Integer(count.clone()));
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)].clone();
- self.unify(a2, count);
- } else {
- panic!("remove_inference_counter: expected Usize in A1.");
+ self.unify(a2, count);
+ }
+ _ => {
+ panic!("remove_inference_counter: expected Usize in A1.");
+ }
}
}
None => panic!(
self[RegType::Temp(i)] = self.stack.index_and_frame(e)[i].clone();
}
- if let &Addr::Con(Constant::Usize(b0)) = &self.stack.index_and_frame(e)[frame_len - 1] {
+ if let &Addr::Con(Constant::CutPoint(b0)) = &self.stack.index_and_frame(e)[frame_len - 1] {
self.b0 = b0;
}
let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
match a2 {
- Addr::Con(Constant::Usize(bp)) => {
+ Addr::Con(Constant::CutPoint(bp)) | Addr::Con(Constant::Usize(bp)) => {
let prev_b = self.stack.index_or_frame(self.b).prelude.b;
if prev_b <= bp {
}
&SystemClauseType::GetCutPoint => {
let a1 = self[temp_v!(1)].clone();
- let a2 = Addr::Con(Constant::Usize(self.b0));
+ let a2 = Addr::Con(Constant::CutPoint(self.b0));
self.unify(a1, a2);
}
let target = self[temp_v!(1)].clone();
self.unify(Addr::Con(Constant::Char(c)), target);
}
+ &SystemClauseType::NextEP => {
+ let first_arg = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ match first_arg {
+ Addr::Con(Constant::Atom(ref name, _))
+ if name.as_str() == "first" => {
+ if self.e == 0 {
+ self.fail = true;
+ return Ok(());
+ }
+
+ let cp = (self.stack.index_and_frame(self.e).prelude.cp - 1).unwrap();
+
+ let e = self.stack.index_and_frame(self.e).prelude.e;
+ let e = Addr::Con(Constant::Usize(e));
+
+ let p = cp.as_functor(&mut self.heap);
+
+ self.unify(self[temp_v!(2)].clone(), e);
+
+ if !self.fail {
+ self.unify(self[temp_v!(3)].clone(), p);
+ }
+ },
+ Addr::Con(Constant::Usize(e)) => {
+ if e == 0 {
+ self.fail = true;
+ return Ok(());
+ }
+
+ // get the call site so that the number of active permanent variables can be read
+ // from it later.
+ let cp = (self.stack.index_and_frame(e).prelude.cp - 1).unwrap();
+
+ let p = cp.as_functor(&mut self.heap);
+ let e = self.stack.index_and_frame(e).prelude.e;
+
+ let e = Addr::Con(Constant::Usize(e));
+
+ self.unify(self[temp_v!(2)].clone(), e);
+
+ if !self.fail {
+ self.unify(self[temp_v!(3)].clone(), p);
+ }
+ }
+ _ => unreachable!()
+ }
+ }
+ &SystemClauseType::PointsToContinuationResetMarker => {
+ let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ let p = match self.heap.to_local_code_ptr(&addr) {
+ Some(p) => p + 1,
+ None => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
+
+ if p.is_reset_cont_marker(code_repo, self.last_call) {
+ return return_from_clause!(self.last_call, self);
+ }
+
+ self.fail = true;
+ return Ok(());
+ }
&SystemClauseType::ReadQueryTerm => {
readline::set_prompt(true);
let result = self.read_term(current_input_stream, indices);
self.reset_block(addr);
}
&SystemClauseType::ResetContinuationMarker => {
+ self[temp_v!(3)] = Addr::Con(Constant::Integer(Integer::from(0)));
+ self[temp_v!(4)] = Addr::Con(Constant::Integer(Integer::from(0)));
}
&SystemClauseType::SetBall =>
self.set_ball(),
self.unify_with_occurs_check(a1, a2);
}
+ &SystemClauseType::UnwindEnvironments => {
+ let mut e = self.e;
+ let mut cp = self.cp;
+
+ while e > 0 {
+ if cp.is_reset_cont_marker(code_repo, self.last_call) {
+ self.e = e;
+ self.p = CodePtr::Local(cp + 1); // skip the reset marker.
+
+ return Ok(());
+ }
+
+ cp = self.stack.index_and_frame(e).prelude.cp;
+ e = self.stack.index_and_frame(e).prelude.e;
+ }
+ }
&SystemClauseType::UnwindStack => self.unwind_stack(),
&SystemClauseType::Variant => self.fail = self.structural_eq_test(),
&SystemClauseType::WAMInstructions => {