push of preliminary delimited continuations library cont.pl (#136)

This commit is contained in:
Mark Thom
2019-12-20 22:27:49 -07:00
parent 4ef8ab6e76
commit 3bf1cbbe6c
13 changed files with 422 additions and 56 deletions

6
Cargo.lock generated
View File

@@ -311,8 +311,7 @@ dependencies = [
[[package]] [[package]]
name = "prolog_parser" name = "prolog_parser"
version = "0.8.36" version = "0.8.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -447,7 +446,7 @@ dependencies = [
"nix 0.15.0 (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)", "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)", "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)", "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)", "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)", "rustyline 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -590,7 +589,6 @@ source = "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 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 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 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 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.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" "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"

View File

@@ -24,7 +24,7 @@ libc = "0.2.62"
nix = "0.15.0" nix = "0.15.0"
num-rug-adapter = { optional = true, version = "0.1.1" } num-rug-adapter = { optional = true, version = "0.1.1" }
ordered-float = "0.5.0" 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" ref_thread_local = "0.0.0"
rug = { version = "1.4.0", optional = true } rug = { version = "1.4.0", optional = true }
rustyline = "5.0.3" rustyline = "5.0.3"

View File

@@ -50,6 +50,8 @@ Extend Scryer Prolog to include the following, among other features:
- [x] Backtrackable and non-backtrackable global variables via `bb_get/2` - [x] Backtrackable and non-backtrackable global variables via `bb_get/2`
`bb_put/2` (non-backtrackable) and `bb_b_put/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_). - [ ] clp(B) and clp() as builtin libraries (_in progress_).
- [ ] Streams and predicates for stream control (_in progress_). - [ ] Streams and predicates for stream control (_in progress_).
- [ ] An incremental compacting garbage collector satisfying the five - [ ] An incremental compacting garbage collector satisfying the five
@@ -79,15 +81,12 @@ Programming?"
unum implementation or an ad hoc one. Unums are described in unum implementation or an ad hoc one. Unums are described in
Gustafson's book "The End of Error." Gustafson's book "The End of Error."
3. Add support for shift/reset delimited continuations, see "Delimited 3. Add concurrent tables to manage shared references to atoms and
Continuations for Prolog."
4. Add concurrent tables to manage shared references to atoms and
strings. 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 ## Installing Scryer Prolog

View File

@@ -165,6 +165,7 @@ pub enum SystemClauseType {
AtomLength, AtomLength,
BindFromRegister, BindFromRegister,
CallAttributeGoals, CallAttributeGoals,
CallContinuation,
CharCode, CharCode,
CharsToNumber, CharsToNumber,
ClearAttrVarBindings, ClearAttrVarBindings,
@@ -193,6 +194,7 @@ pub enum SystemClauseType {
GetAttrVarQueueBeyond, GetAttrVarQueueBeyond,
GetBValue, GetBValue,
GetClause, GetClause,
GetContinuationChunk,
GetModuleClause, GetModuleClause,
GetNextDBRef, GetNextDBRef,
GetNextOpDBRef, GetNextOpDBRef,
@@ -212,10 +214,12 @@ pub enum SystemClauseType {
ModuleExists, ModuleExists,
ModuleOf, ModuleOf,
ModuleRetractClause, ModuleRetractClause,
NextEP,
NoSuchPredicate, NoSuchPredicate,
NumberToChars, NumberToChars,
NumberToCodes, NumberToCodes,
OpDeclaration, OpDeclaration,
PointsToContinuationResetMarker,
REPL(REPLCodePtr), REPL(REPLCodePtr),
ReadQueryTerm, ReadQueryTerm,
ReadTerm, ReadTerm,
@@ -252,6 +256,7 @@ pub enum SystemClauseType {
TermVariables, TermVariables,
TruncateLiftedHeapTo, TruncateLiftedHeapTo,
UnifyWithOccursCheck, UnifyWithOccursCheck,
UnwindEnvironments,
UnwindStack, UnwindStack,
Variant, Variant,
WAMInstructions, WAMInstructions,
@@ -271,6 +276,7 @@ impl SystemClauseType {
&SystemClauseType::AtomLength => clause_name!("$atom_length"), &SystemClauseType::AtomLength => clause_name!("$atom_length"),
&SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"), &SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"),
&SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"), &SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
&SystemClauseType::CallContinuation => clause_name!("$call_continuation"),
&SystemClauseType::CharCode => clause_name!("$char_code"), &SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"), &SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
&SystemClauseType::ClearAttributeGoals => clause_name!("$clear_attribute_goals"), &SystemClauseType::ClearAttributeGoals => clause_name!("$clear_attribute_goals"),
@@ -316,6 +322,7 @@ impl SystemClauseType {
clause_name!("$get_attr_var_queue_delim") clause_name!("$get_attr_var_queue_delim")
} }
&SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"), &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::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"),
&SystemClauseType::GetLiftedHeapFromOffsetDiff => { &SystemClauseType::GetLiftedHeapFromOffsetDiff => {
clause_name!("$get_lh_from_offset_diff") clause_name!("$get_lh_from_offset_diff")
@@ -350,6 +357,9 @@ impl SystemClauseType {
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"), &SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"), &SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
&SystemClauseType::NumberToCodes => clause_name!("$number_to_codes"), &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::RawInputReadChar => clause_name!("$raw_input_read_char"),
&SystemClauseType::RedoAttrVarBinding => clause_name!("$redo_attr_var_binding"), &SystemClauseType::RedoAttrVarBinding => clause_name!("$redo_attr_var_binding"),
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"), &SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
@@ -370,6 +380,7 @@ impl SystemClauseType {
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
&SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"), &SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
&SystemClauseType::NextEP => clause_name!("$nextEP"),
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"), &SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
&SystemClauseType::ReadTerm => clause_name!("$read_term"), &SystemClauseType::ReadTerm => clause_name!("$read_term"),
&SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"), &SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
@@ -386,6 +397,7 @@ impl SystemClauseType {
&SystemClauseType::TermVariables => clause_name!("$term_variables"), &SystemClauseType::TermVariables => clause_name!("$term_variables"),
&SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"), &SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"),
&SystemClauseType::UnifyWithOccursCheck => clause_name!("$unify_with_occurs_check"), &SystemClauseType::UnifyWithOccursCheck => clause_name!("$unify_with_occurs_check"),
&SystemClauseType::UnwindEnvironments => clause_name!("$unwind_environments"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
&SystemClauseType::Variant => clause_name!("$variant"), &SystemClauseType::Variant => clause_name!("$variant"),
&SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"), &SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
@@ -407,6 +419,7 @@ impl SystemClauseType {
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront), ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack), ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals), ("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
("$char_code", 2) => Some(SystemClauseType::CharCode), ("$char_code", 2) => Some(SystemClauseType::CharCode),
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber), ("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
("$clear_attr_var_bindings", 0) => Some(SystemClauseType::ClearAttrVarBindings), ("$clear_attr_var_bindings", 0) => Some(SystemClauseType::ClearAttrVarBindings),
@@ -432,6 +445,9 @@ impl SystemClauseType {
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_char", 1) => Some(SystemClauseType::GetChar), ("$get_char", 1) => Some(SystemClauseType::GetChar),
("$points_to_cont_reset_marker", 1) => {
Some(SystemClauseType::PointsToContinuationResetMarker)
}
("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState), ("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState),
("$truncate_if_no_lh_growth", 1) => { ("$truncate_if_no_lh_growth", 1) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth) Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
@@ -473,10 +489,12 @@ impl SystemClauseType {
("$get_attr_var_queue_beyond", 2) => Some(SystemClauseType::GetAttrVarQueueBeyond), ("$get_attr_var_queue_beyond", 2) => Some(SystemClauseType::GetAttrVarQueueBeyond),
("$get_attr_var_queue_delim", 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter), ("$get_attr_var_queue_delim", 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter),
("$get_ball", 1) => Some(SystemClauseType::GetBall), ("$get_ball", 1) => Some(SystemClauseType::GetBall),
("$get_cont_chunk", 3) => Some(SystemClauseType::GetContinuationChunk),
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar), ("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar),
("$nextEP", 3) => Some(SystemClauseType::NextEP),
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm), ("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
("$read_term", 2) => Some(SystemClauseType::ReadTerm), ("$read_term", 2) => Some(SystemClauseType::ReadTerm),
("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
@@ -494,6 +512,7 @@ impl SystemClauseType {
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset), ("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables),
("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
("$unwind_environments", 0) => Some(SystemClauseType::UnwindEnvironments),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck), ("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)), ("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),

View File

@@ -809,6 +809,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
}); });
} }
Constant::CharCode(c) => self.append_str(&format!("{}", c)), Constant::CharCode(c) => self.append_str(&format!("{}", c)),
Constant::CutPoint(b) => self.append_str(&format!("{}", b)),
Constant::EmptyList => self.append_str("[]"), Constant::EmptyList => self.append_str("[]"),
Constant::Integer(n) => self.print_number(Number::Integer(n), op), Constant::Integer(n) => self.print_number(Number::Integer(n), op),
Constant::Float(n) => self.print_number(Number::Float(n), op), Constant::Float(n) => self.print_number(Number::Float(n), op),

View File

@@ -364,6 +364,17 @@ pub enum ControlInstruction {
} }
impl ControlInstruction { 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 { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&ControlInstruction::Allocate(num_frames) => { &ControlInstruction::Allocate(num_frames) => {

View File

@@ -17,7 +17,7 @@ shift(Term) :-
get_chunks(E, P, L) :- get_chunks(E, P, L) :-
( '$points_to_cont_reset_marker'(P) -> ( '$points_to_cont_reset_marker'(P) ->
L = [] L = []
; '$get_chunk'(E,P,TB), ; '$get_cont_chunk'(E,P,TB),
L = [TB|Rest], L = [TB|Rest],
'$nextEP'(E, NextE, NextP), '$nextEP'(E, NextE, NextP),
get_chunks(NextE, NextP, Rest) get_chunks(NextE, NextP, Rest)
@@ -26,4 +26,3 @@ get_chunks(E, P, L) :-
call_continuation(L) :- '$call_continuation'(L). call_continuation(L) :- '$call_continuation'(L).
'$write_cont_and_term'(_, _, _, _). '$write_cont_and_term'(_, _, _, _).

View File

@@ -117,7 +117,7 @@ impl MachineState {
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)].clone(); 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.stack.index_and_frame_mut(e)[self.num_of_args + 2] = Addr::Con(Constant::Usize(self.num_of_args));
self.verify_attributes(); self.verify_attributes();

View File

@@ -82,6 +82,50 @@ impl Heap {
self.push(hcv); 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 { impl Index<usize> for Heap {

View File

@@ -4,7 +4,11 @@ use prolog_parser::tabled_rc::*;
use crate::prolog::clause_types::*; use crate::prolog::clause_types::*;
use crate::prolog::fixtures::*; use crate::prolog::fixtures::*;
use crate::prolog::forms::*; use crate::prolog::forms::*;
use crate::prolog::machine::code_repo::CodeRepo;
use crate::prolog::machine::Ball; use crate::prolog::machine::Ball;
use crate::prolog::machine::heap::Heap;
use crate::prolog::instructions::*;
use crate::prolog::rug::Integer;
use indexmap::IndexMap; use indexmap::IndexMap;
@@ -346,6 +350,69 @@ impl LocalCodePtr {
_ => {} _ => {}
} }
} }
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 PartialOrd<CodePtr> for CodePtr {
@@ -399,6 +466,25 @@ impl Add<usize> for LocalCodePtr {
} }
} }
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 { impl AddAssign<usize> for LocalCodePtr {
fn add_assign(&mut self, rhs: usize) { fn add_assign(&mut self, rhs: usize) {
match self { match self {

View File

@@ -1063,17 +1063,20 @@ downcast!(dyn CutPolicy);
fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool { fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
let b = machine_st.b; let b = machine_st.b;
if let Addr::Con(Constant::Usize(b0)) = addr { match addr {
if b > b0 { Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
machine_st.b = b0; if b > b0 {
machine_st.tidy_trail(); machine_st.b = b0;
machine_st.tidy_pstr_trail(); machine_st.tidy_trail();
machine_st.truncate_stack(); machine_st.tidy_pstr_trail();
machine_st.truncate_stack();
}
} }
} else { _ => {
machine_st.fail = true; machine_st.fail = true;
return true; return true;
} }
};
false false
} }
@@ -1148,15 +1151,19 @@ impl CutPolicy for SCCCutPolicy {
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool { fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
let b = machine_st.b; let b = machine_st.b;
if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() { match machine_st[r].clone() {
if b > b0 { Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
machine_st.b = b0; if b > b0 {
machine_st.tidy_trail(); machine_st.b = b0;
machine_st.tidy_pstr_trail(); 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) self.run_cleaners(machine_st)

View File

@@ -3337,7 +3337,7 @@ impl MachineState {
&CutInstruction::GetLevel(r) => { &CutInstruction::GetLevel(r) => {
let b0 = self.b0; let b0 = self.b0;
self[r] = Addr::Con(Constant::Usize(b0)); self[r] = Addr::Con(Constant::CutPoint(b0));
self.p += 1; self.p += 1;
} }
&CutInstruction::GetLevelAndUnify(r) => { &CutInstruction::GetLevelAndUnify(r) => {

View File

@@ -580,6 +580,51 @@ impl MachineState {
functors 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( pub(super) fn system_call(
&mut self, &mut self,
ct: &SystemClauseType, ct: &SystemClauseType,
@@ -784,6 +829,28 @@ impl MachineState {
return Ok(()); 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 => { &SystemClauseType::CharsToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2); let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
@@ -897,7 +964,7 @@ impl MachineState {
let addr = self.store(self.deref(self[temp_v!(1)].clone())); let addr = self.store(self.deref(self[temp_v!(1)].clone()));
match addr { 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(self.b).prelude.b;
let prev_b = self.stack.index_or_frame(prev_b).prelude.b; let prev_b = self.stack.index_or_frame(prev_b).prelude.b;
@@ -1477,6 +1544,50 @@ impl MachineState {
_ => self.fail = true, _ => 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 => { &SystemClauseType::GetLiftedHeapFromOffsetDiff => {
let lh_offset = self[temp_v!(1)].clone(); let lh_offset = self[temp_v!(1)].clone();
@@ -1609,7 +1720,8 @@ impl MachineState {
} }
match (a1, a2.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() { match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
Some(call_policy) => { Some(call_policy) => {
let count = call_policy.add_limit(n, bp); let count = call_policy.add_limit(n, bp);
@@ -1771,14 +1883,17 @@ impl MachineState {
Some(call_policy) => { Some(call_policy) => {
let a1 = self.store(self.deref(self[temp_v!(1)].clone())); let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
if let Addr::Con(Constant::Usize(bp)) = a1 { match a1 {
if call_policy.is_empty() && bp == self.b { Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
Some(call_policy.into_inner()) if call_policy.is_empty() && bp == self.b {
} else { Some(call_policy.into_inner())
None } else {
None
}
}
_ => {
panic!("remove_call_policy_check: expected Usize in A1.");
} }
} else {
panic!("remove_call_policy_check: expected Usize in A1.");
} }
} }
None => panic!( None => panic!(
@@ -1796,15 +1911,18 @@ impl MachineState {
Some(call_policy) => { Some(call_policy) => {
let a1 = self.store(self.deref(self[temp_v!(1)].clone())); let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
if let Addr::Con(Constant::Usize(bp)) = a1 { match a1 {
let count = call_policy.remove_limit(bp); Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
let count = Addr::Con(Constant::Integer(count.clone())); 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); self.unify(a2, count);
} else { }
panic!("remove_inference_counter: expected Usize in A1."); _ => {
panic!("remove_inference_counter: expected Usize in A1.");
}
} }
} }
None => panic!( None => panic!(
@@ -1836,7 +1954,7 @@ impl MachineState {
self[RegType::Temp(i)] = self.stack.index_and_frame(e)[i].clone(); 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; self.b0 = b0;
} }
@@ -1884,7 +2002,7 @@ impl MachineState {
let a2 = self.store(self.deref(self[temp_v!(2)].clone())); let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
match a2 { 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; let prev_b = self.stack.index_or_frame(self.b).prelude.b;
if prev_b <= bp { if prev_b <= bp {
@@ -1975,7 +2093,7 @@ impl MachineState {
} }
&SystemClauseType::GetCutPoint => { &SystemClauseType::GetCutPoint => {
let a1 = self[temp_v!(1)].clone(); 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); self.unify(a1, a2);
} }
@@ -1997,6 +2115,72 @@ impl MachineState {
let target = self[temp_v!(1)].clone(); let target = self[temp_v!(1)].clone();
self.unify(Addr::Con(Constant::Char(c)), target); 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 => { &SystemClauseType::ReadQueryTerm => {
readline::set_prompt(true); readline::set_prompt(true);
let result = self.read_term(current_input_stream, indices); let result = self.read_term(current_input_stream, indices);
@@ -2013,6 +2197,8 @@ impl MachineState {
self.reset_block(addr); self.reset_block(addr);
} }
&SystemClauseType::ResetContinuationMarker => { &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 => &SystemClauseType::SetBall =>
self.set_ball(), self.set_ball(),
@@ -2123,6 +2309,22 @@ impl MachineState {
self.unify_with_occurs_check(a1, a2); 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::UnwindStack => self.unwind_stack(),
&SystemClauseType::Variant => self.fail = self.structural_eq_test(), &SystemClauseType::Variant => self.fail = self.structural_eq_test(),
&SystemClauseType::WAMInstructions => { &SystemClauseType::WAMInstructions => {