relocate most instruction routines from MachineState to Machine
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -289,12 +289,6 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "downcast"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ed25519"
|
name = "ed25519"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -1398,7 +1392,6 @@ dependencies = [
|
|||||||
"crossterm",
|
"crossterm",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"divrem",
|
"divrem",
|
||||||
"downcast",
|
|
||||||
"git-version",
|
"git-version",
|
||||||
"hostname",
|
"hostname",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ cpu-time = "1.0.0"
|
|||||||
crossterm = "0.16.0"
|
crossterm = "0.16.0"
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
divrem = "0.1.0"
|
divrem = "0.1.0"
|
||||||
downcast = "0.10.0"
|
|
||||||
git-version = "0.3.4"
|
git-version = "0.3.4"
|
||||||
hostname = "0.3.1"
|
hostname = "0.3.1"
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
@@ -66,3 +65,6 @@ slice-deque = "0.3.0"
|
|||||||
assert_cmd = "1.0.3"
|
assert_cmd = "1.0.3"
|
||||||
predicates-core = "1.0.2"
|
predicates-core = "1.0.2"
|
||||||
serial_test = "0.5.1"
|
serial_test = "0.5.1"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
@@ -799,11 +799,13 @@ impl SystemClauseType {
|
|||||||
(atom!("$ed25519_new_keypair"), 1) => Some(SystemClauseType::Ed25519NewKeyPair),
|
(atom!("$ed25519_new_keypair"), 1) => Some(SystemClauseType::Ed25519NewKeyPair),
|
||||||
(atom!("$ed25519_keypair_public_key"), 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
|
(atom!("$ed25519_keypair_public_key"), 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
|
||||||
(atom!("$curve25519_scalar_mult"), 3) => Some(SystemClauseType::Curve25519ScalarMult),
|
(atom!("$curve25519_scalar_mult"), 3) => Some(SystemClauseType::Curve25519ScalarMult),
|
||||||
|
(atom!("$first_non_octet"), 2) => Some(SystemClauseType::FirstNonOctet),
|
||||||
(atom!("$load_html"), 3) => Some(SystemClauseType::LoadHTML),
|
(atom!("$load_html"), 3) => Some(SystemClauseType::LoadHTML),
|
||||||
(atom!("$load_xml"), 3) => Some(SystemClauseType::LoadXML),
|
(atom!("$load_xml"), 3) => Some(SystemClauseType::LoadXML),
|
||||||
(atom!("$getenv"), 2) => Some(SystemClauseType::GetEnv),
|
(atom!("$getenv"), 2) => Some(SystemClauseType::GetEnv),
|
||||||
(atom!("$setenv"), 2) => Some(SystemClauseType::SetEnv),
|
(atom!("$setenv"), 2) => Some(SystemClauseType::SetEnv),
|
||||||
(atom!("$unsetenv"), 1) => Some(SystemClauseType::UnsetEnv),
|
(atom!("$unsetenv"), 1) => Some(SystemClauseType::UnsetEnv),
|
||||||
|
(atom!("$shell"), 2) => Some(SystemClauseType::Shell),
|
||||||
(atom!("$pid"), 1) => Some(SystemClauseType::PID),
|
(atom!("$pid"), 1) => Some(SystemClauseType::PID),
|
||||||
(atom!("$chars_base64"), 4) => Some(SystemClauseType::CharsBase64),
|
(atom!("$chars_base64"), 4) => Some(SystemClauseType::CharsBase64),
|
||||||
(atom!("$load_library_as_stream"), 3) => Some(SystemClauseType::LoadLibraryAsStream),
|
(atom!("$load_library_as_stream"), 3) => Some(SystemClauseType::LoadLibraryAsStream),
|
||||||
@@ -847,6 +849,7 @@ impl SystemClauseType {
|
|||||||
(atom!("$set_sto_with_error_as_unify"), 0) => Some(SystemClauseType::SetSTOWithErrorAsUnify),
|
(atom!("$set_sto_with_error_as_unify"), 0) => Some(SystemClauseType::SetSTOWithErrorAsUnify),
|
||||||
(atom!("$home_directory"), 1) => Some(SystemClauseType::HomeDirectory),
|
(atom!("$home_directory"), 1) => Some(SystemClauseType::HomeDirectory),
|
||||||
(atom!("$debug_hook"), 0) => Some(SystemClauseType::DebugHook),
|
(atom!("$debug_hook"), 0) => Some(SystemClauseType::DebugHook),
|
||||||
|
(atom!("$popcount"), 2) => Some(SystemClauseType::PopCount),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::types::*;
|
|||||||
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -490,11 +490,7 @@ pub struct HCPrinter<'a, Outputter> {
|
|||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
state_stack: Vec<TokenOrRedirect>,
|
state_stack: Vec<TokenOrRedirect>,
|
||||||
toplevel_spec: Option<DirectedOp>,
|
toplevel_spec: Option<DirectedOp>,
|
||||||
// heap_locs: ReverseHeapVarDict,
|
|
||||||
printed_vars: IndexSet<HeapCellValue>,
|
|
||||||
last_item_idx: usize,
|
last_item_idx: usize,
|
||||||
// cyclic_terms: IndexMap<HeapCellValue, usize>,
|
|
||||||
// non_cyclic_terms: IndexSet<usize>,
|
|
||||||
pub var_names: IndexMap<HeapCellValue, Rc<String>>,
|
pub var_names: IndexMap<HeapCellValue, Rc<String>>,
|
||||||
pub numbervars_offset: Integer,
|
pub numbervars_offset: Integer,
|
||||||
pub numbervars: bool,
|
pub numbervars: bool,
|
||||||
@@ -530,7 +526,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
op_dir,
|
op_dir,
|
||||||
state_stack: vec![],
|
state_stack: vec![],
|
||||||
toplevel_spec: None,
|
toplevel_spec: None,
|
||||||
printed_vars: IndexSet::new(),
|
|
||||||
last_item_idx: 0,
|
last_item_idx: 0,
|
||||||
numbervars: false,
|
numbervars: false,
|
||||||
numbervars_offset: Integer::from(0),
|
numbervars_offset: Integer::from(0),
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ pub(crate) fn to_indexing_line(line: &Line) -> Option<&Vec<IndexingLine>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum ArithmeticInstruction {
|
pub enum ArithmeticInstruction {
|
||||||
Add(ArithmeticTerm, ArithmeticTerm, usize),
|
Add(ArithmeticTerm, ArithmeticTerm, usize),
|
||||||
Sub(ArithmeticTerm, ArithmeticTerm, usize),
|
Sub(ArithmeticTerm, ArithmeticTerm, usize),
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ scc_helper(_, _, _) :-
|
|||||||
|
|
||||||
:- non_counted_backtracking run_cleaners_with_handling/0.
|
:- non_counted_backtracking run_cleaners_with_handling/0.
|
||||||
run_cleaners_with_handling :-
|
run_cleaners_with_handling :-
|
||||||
'$get_scc_cleaner'(C), '$get_level'(B),
|
'$get_scc_cleaner'(C),
|
||||||
|
'$get_level'(B),
|
||||||
'$call_with_default_policy'(catch(C, _, true)),
|
'$call_with_default_policy'(catch(C, _, true)),
|
||||||
'$set_cp_by_default'(B),
|
'$set_cp_by_default'(B),
|
||||||
'$call_with_default_policy'(run_cleaners_with_handling).
|
'$call_with_default_policy'(run_cleaners_with_handling).
|
||||||
|
|||||||
@@ -1,8 +1,35 @@
|
|||||||
use crate::clause_types::*;
|
use crate::clause_types::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::MachineState;
|
use crate::machine::{Machine, MachineState};
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub(crate) enum OwnedOrIndexed {
|
||||||
|
Indexed(usize),
|
||||||
|
Owned(Line),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for OwnedOrIndexed {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
&OwnedOrIndexed::Indexed(ref index) => write!(f, "Indexed({:?})", index),
|
||||||
|
&OwnedOrIndexed::Owned(ref owned) => write!(f, "Owned({:?})", owned),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OwnedOrIndexed {
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn as_ref<'a>(&'a self, code: &'a Code) -> &'a Line {
|
||||||
|
match self {
|
||||||
|
&OwnedOrIndexed::Indexed(p) => &code[p],
|
||||||
|
&OwnedOrIndexed::Owned(ref r) => r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: remove this, replace with just 'Code'.
|
// TODO: remove this, replace with just 'Code'.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CodeRepo {
|
pub struct CodeRepo {
|
||||||
@@ -10,7 +37,7 @@ pub struct CodeRepo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CodeRepo {
|
impl CodeRepo {
|
||||||
pub(super) fn lookup_instr<'a>(&'a self, machine_st: &MachineState, p: &CodePtr) -> Option<RefOrOwned<'a, Line>> {
|
pub(super) fn lookup_instr(&self, machine_st: &MachineState, p: &CodePtr) -> Option<OwnedOrIndexed> {
|
||||||
match p {
|
match p {
|
||||||
&CodePtr::Local(local) => {
|
&CodePtr::Local(local) => {
|
||||||
return Some(self.lookup_local_instr(machine_st, local));
|
return Some(self.lookup_local_instr(machine_st, local));
|
||||||
@@ -24,18 +51,18 @@ impl CodeRepo {
|
|||||||
machine_st.last_call
|
machine_st.last_call
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(RefOrOwned::Owned(call_clause))
|
Some(OwnedOrIndexed::Owned(call_clause))
|
||||||
}
|
}
|
||||||
&CodePtr::CallN(arity, _, last_call) => {
|
&CodePtr::CallN(arity, _, last_call) => {
|
||||||
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
|
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
|
||||||
Some(RefOrOwned::Owned(call_clause))
|
Some(OwnedOrIndexed::Owned(call_clause))
|
||||||
}
|
}
|
||||||
&CodePtr::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])),
|
&CodePtr::VerifyAttrInterrupt(p) => Some(OwnedOrIndexed::Indexed(p)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn lookup_local_instr<'a>(&'a self, machine_st: &MachineState, p: LocalCodePtr) -> RefOrOwned<'a, Line> {
|
pub(super) fn lookup_local_instr(&self, machine_st: &MachineState, p: LocalCodePtr) -> OwnedOrIndexed {
|
||||||
match p {
|
match p {
|
||||||
LocalCodePtr::Halt => {
|
LocalCodePtr::Halt => {
|
||||||
// exit with the interrupt exit code.
|
// exit with the interrupt exit code.
|
||||||
@@ -45,32 +72,36 @@ impl CodeRepo {
|
|||||||
&Line::IndexingCode(ref indexing_lines) => {
|
&Line::IndexingCode(ref indexing_lines) => {
|
||||||
match &indexing_lines[machine_st.oip as usize] {
|
match &indexing_lines[machine_st.oip as usize] {
|
||||||
&IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
|
&IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
|
||||||
RefOrOwned::Owned(Line::IndexedChoice(indexed_choice_instrs[machine_st.iip as usize]))
|
OwnedOrIndexed::Owned(
|
||||||
|
Line::IndexedChoice(indexed_choice_instrs[machine_st.iip as usize])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
|
&IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
|
||||||
RefOrOwned::Owned(Line::DynamicIndexedChoice(indexed_choice_instrs[machine_st.iip as usize]))
|
OwnedOrIndexed::Owned(
|
||||||
|
Line::DynamicIndexedChoice(indexed_choice_instrs[machine_st.iip as usize])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
RefOrOwned::Borrowed(&self.code[p as usize])
|
OwnedOrIndexed::Indexed(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => RefOrOwned::Borrowed(&self.code[p as usize]),
|
_ => OwnedOrIndexed::Indexed(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl Machine {
|
||||||
pub(super) fn find_living_dynamic_else(&self, code: &Code, mut p: usize) -> Option<(usize, usize)> {
|
pub(super) fn find_living_dynamic_else(&self, mut p: usize) -> Option<(usize, usize)> {
|
||||||
loop {
|
loop {
|
||||||
match &code[p] {
|
match &self.code_repo.code[p] {
|
||||||
&Line::Choice(ChoiceInstruction::DynamicElse(
|
&Line::Choice(ChoiceInstruction::DynamicElse(
|
||||||
birth,
|
birth,
|
||||||
death,
|
death,
|
||||||
NextOrFail::Next(i),
|
NextOrFail::Next(i),
|
||||||
)) => {
|
)) => {
|
||||||
if birth < self.cc && Death::Finite(self.cc) <= death {
|
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
|
||||||
return Some((p, i));
|
return Some((p, i));
|
||||||
} else if i > 0 {
|
} else if i > 0 {
|
||||||
p += i;
|
p += i;
|
||||||
@@ -83,7 +114,7 @@ impl MachineState {
|
|||||||
death,
|
death,
|
||||||
NextOrFail::Fail(_),
|
NextOrFail::Fail(_),
|
||||||
)) => {
|
)) => {
|
||||||
if birth < self.cc && Death::Finite(self.cc) <= death {
|
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
|
||||||
return Some((p, 0));
|
return Some((p, 0));
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
@@ -94,7 +125,7 @@ impl MachineState {
|
|||||||
death,
|
death,
|
||||||
NextOrFail::Next(i),
|
NextOrFail::Next(i),
|
||||||
)) => {
|
)) => {
|
||||||
if birth < self.cc && Death::Finite(self.cc) <= death {
|
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
|
||||||
return Some((p, i));
|
return Some((p, i));
|
||||||
} else if i > 0 {
|
} else if i > 0 {
|
||||||
p += i;
|
p += i;
|
||||||
@@ -107,7 +138,7 @@ impl MachineState {
|
|||||||
death,
|
death,
|
||||||
NextOrFail::Fail(_),
|
NextOrFail::Fail(_),
|
||||||
)) => {
|
)) => {
|
||||||
if birth < self.cc && Death::Finite(self.cc) <= death {
|
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
|
||||||
return Some((p, 0));
|
return Some((p, 0));
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
@@ -123,10 +154,10 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn find_living_dynamic(&self, code: &Code, oi: u32, mut ii: u32) -> Option<(usize, u32, u32, bool)> {
|
pub(super) fn find_living_dynamic(&self, oi: u32, mut ii: u32) -> Option<(usize, u32, u32, bool)> {
|
||||||
let p = self.p.local().abs_loc();
|
let p = self.machine_st.p.local().abs_loc();
|
||||||
|
|
||||||
let indexed_choice_instrs = match &code[p] {
|
let indexed_choice_instrs = match &self.code_repo.code[p] {
|
||||||
Line::IndexingCode(ref indexing_code) => match &indexing_code[oi as usize] {
|
Line::IndexingCode(ref indexing_code) => match &indexing_code[oi as usize] {
|
||||||
IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
|
IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
|
||||||
indexed_choice_instrs
|
indexed_choice_instrs
|
||||||
@@ -138,13 +169,13 @@ impl MachineState {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
match &indexed_choice_instrs.get(ii as usize) {
|
match &indexed_choice_instrs.get(ii as usize) {
|
||||||
Some(&offset) => match &code[p + offset - 1] {
|
Some(&offset) => match &self.code_repo.code[p + offset - 1] {
|
||||||
&Line::Choice(ChoiceInstruction::DynamicInternalElse(
|
&Line::Choice(ChoiceInstruction::DynamicInternalElse(
|
||||||
birth,
|
birth,
|
||||||
death,
|
death,
|
||||||
next_or_fail,
|
next_or_fail,
|
||||||
)) => {
|
)) => {
|
||||||
if birth < self.cc && Death::Finite(self.cc) <= death {
|
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
|
||||||
return Some((offset, oi, ii, next_or_fail.is_next()));
|
return Some((offset, oi, ii, next_or_fail.is_next()));
|
||||||
} else {
|
} else {
|
||||||
ii += 1;
|
ii += 1;
|
||||||
|
|||||||
@@ -1371,12 +1371,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
term: Term,
|
term: Term,
|
||||||
settings: CodeGenSettings,
|
settings: CodeGenSettings,
|
||||||
) -> Result<StandaloneCompileResult, SessionError> {
|
) -> Result<StandaloneCompileResult, SessionError> {
|
||||||
let mut preprocessor = Preprocessor::new(LS::machine_st(&mut self.payload).flags);
|
let mut preprocessor = Preprocessor::new();
|
||||||
|
|
||||||
let clause = self.try_term_to_tl(term, &mut preprocessor)?;
|
let clause = self.try_term_to_tl(term, &mut preprocessor)?;
|
||||||
let queue = preprocessor.parse_queue(self)?;
|
let queue = preprocessor.parse_queue(self)?;
|
||||||
|
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(&mut LS::machine_st(&mut self.payload).atom_tbl, settings);
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(
|
||||||
|
&mut LS::machine_st(&mut self.payload).atom_tbl,
|
||||||
|
settings,
|
||||||
|
);
|
||||||
|
|
||||||
let mut clause_code = cg.compile_predicate(&vec![clause])?;
|
let mut clause_code = cg.compile_predicate(&vec![clause])?;
|
||||||
|
|
||||||
compile_appendix(
|
compile_appendix(
|
||||||
@@ -1405,7 +1409,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
let mut code_ptr = code_len;
|
let mut code_ptr = code_len;
|
||||||
|
|
||||||
let mut clauses = vec![];
|
let mut clauses = vec![];
|
||||||
let mut preprocessor = Preprocessor::new(LS::machine_st(&mut self.payload).flags);
|
let mut preprocessor = Preprocessor::new();
|
||||||
|
|
||||||
for term in predicates.predicates.drain(0..) {
|
for term in predicates.predicates.drain(0..) {
|
||||||
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
|
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
|
||||||
|
|||||||
1279
src/machine/dispatch.rs
Normal file
1279
src/machine/dispatch.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,7 @@ use crate::clause_types::*;
|
|||||||
use crate::fixtures::*;
|
use crate::fixtures::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
|
use crate::machine::*;
|
||||||
use crate::machine::code_repo::CodeRepo;
|
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
use crate::machine::loader::*;
|
use crate::machine::loader::*;
|
||||||
use crate::machine::machine_errors::MachineStub;
|
use crate::machine::machine_errors::MachineStub;
|
||||||
@@ -19,10 +18,14 @@ use indexmap::IndexMap;
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::fmt;
|
|
||||||
use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
// these statics store the locations of one-off control instructions
|
||||||
|
// in the code vector.
|
||||||
|
|
||||||
|
pub static HALT_CODE: usize = 0;
|
||||||
|
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
|
pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
|
||||||
@@ -81,126 +84,7 @@ impl PartialOrd<Ref> for HeapCellValue {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
impl HeapCellValue {
|
|
||||||
#[inline]
|
|
||||||
pub fn as_constant_index(self, machine_st: &MachineState) -> Option<Literal> {
|
|
||||||
read_heap_cell!(self,
|
|
||||||
(HeapCellValueTag::Char, c) => Some(Literal::Char(c)),
|
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
|
||||||
if arity == 0 {
|
|
||||||
Some(Literal::Atom(name))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Fixnum, n) => {
|
|
||||||
Some(Literal::Fixnum(n))
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::F64, f) => {
|
|
||||||
Some(Literal::Float(f))
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Cons, ptr) => {
|
|
||||||
match_untyped_arena_ptr!(ptr,
|
|
||||||
(ArenaHeaderTag::Integer, n) => {
|
|
||||||
Some(Literal::Integer(n))
|
|
||||||
}
|
|
||||||
(ArenaHeaderTag::Rational, r) => {
|
|
||||||
Some(Literal::Rational(r))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
impl Ord for Ref {
|
|
||||||
fn cmp(&self, other: &Ref) -> Ordering {
|
|
||||||
match (self, other) {
|
|
||||||
(Ref::AttrVar(h1), Ref::AttrVar(h2))
|
|
||||||
| (Ref::HeapCell(h1), Ref::HeapCell(h2))
|
|
||||||
| (Ref::HeapCell(h1), Ref::AttrVar(h2))
|
|
||||||
| (Ref::AttrVar(h1), Ref::HeapCell(h2)) => h1.cmp(&h2),
|
|
||||||
(Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) => {
|
|
||||||
fr1.cmp(&fr2).then_with(|| sc1.cmp(&sc2))
|
|
||||||
}
|
|
||||||
(Ref::StackCell(..), _) => Ordering::Greater,
|
|
||||||
(_, Ref::StackCell(..)) => Ordering::Less,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq<Ref> for Addr {
|
|
||||||
fn eq(&self, r: &Ref) -> bool {
|
|
||||||
self.as_var() == Some(*r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Addr {
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn is_heap_bound(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Addr::Char(_)
|
|
||||||
| Addr::EmptyList
|
|
||||||
| Addr::CutPoint(_)
|
|
||||||
| Addr::Usize(_)
|
|
||||||
| Addr::Fixnum(_)
|
|
||||||
| Addr::Float(_) => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn is_ref(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn as_var(&self) -> Option<Ref> {
|
|
||||||
match self {
|
|
||||||
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
|
|
||||||
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
|
|
||||||
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_protected(&self, e: usize) -> bool {
|
|
||||||
match self {
|
|
||||||
&Addr::StackCell(addr, _) if addr >= e => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubAssign<usize> for Addr {
|
|
||||||
fn sub_assign(&mut self, rhs: usize) {
|
|
||||||
*self = self.clone() - rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub(crate) enum TrailRef {
|
|
||||||
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 {
|
|
||||||
fn from(r: Ref) -> Self {
|
|
||||||
TrailRef::Ref(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub enum IndexPtr {
|
pub enum IndexPtr {
|
||||||
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||||
@@ -326,10 +210,10 @@ pub enum LocalCodePtr {
|
|||||||
// TopLevel(usize, usize), // chunk_num, offset
|
// TopLevel(usize, usize), // chunk_num, offset
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl Machine {
|
||||||
pub(crate) fn is_reset_cont_marker(&self, code_repo: &CodeRepo, p: LocalCodePtr) -> bool {
|
pub(crate) fn is_reset_cont_marker(&self, p: LocalCodePtr) -> bool {
|
||||||
match code_repo.lookup_instr(self, &CodePtr::Local(p)) {
|
match self.code_repo.lookup_instr(&self.machine_st, &CodePtr::Local(p)) {
|
||||||
Some(line) => match line.as_ref() {
|
Some(line) => match line.as_ref(&self.code_repo.code) {
|
||||||
Line::Control(ControlInstruction::CallClause(ref ct, ..)) => {
|
Line::Control(ControlInstruction::CallClause(ref ct, ..)) => {
|
||||||
if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct {
|
if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct {
|
||||||
return true;
|
return true;
|
||||||
@@ -679,50 +563,6 @@ impl IndexStore {
|
|||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
|
index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
|
||||||
let r_w_h = atom!("run_cleaners_with_handling");
|
|
||||||
let r_wo_h = atom!("run_cleaners_without_handling");
|
|
||||||
let iso_ext = atom!("iso_ext");
|
|
||||||
|
|
||||||
let r_w_h = self
|
|
||||||
.get_predicate_code_index(r_w_h, 0, iso_ext)
|
|
||||||
.and_then(|item| item.local());
|
|
||||||
let r_wo_h = self
|
|
||||||
.get_predicate_code_index(r_wo_h, 1, iso_ext)
|
|
||||||
.and_then(|item| item.local());
|
|
||||||
|
|
||||||
if let Some(r_w_h) = r_w_h {
|
|
||||||
if let Some(r_wo_h) = r_wo_h {
|
|
||||||
return (r_w_h, r_wo_h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex>;
|
pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex>;
|
||||||
|
|
||||||
pub(crate) enum RefOrOwned<'a, T: 'a> {
|
|
||||||
Borrowed(&'a T),
|
|
||||||
Owned(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for RefOrOwned<'a, T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
&RefOrOwned::Borrowed(ref borrowed) => write!(f, "Borrowed({:?})", borrowed),
|
|
||||||
&RefOrOwned::Owned(ref owned) => write!(f, "Owned({:?})", owned),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> RefOrOwned<'a, T> {
|
|
||||||
pub(crate) fn as_ref(&'a self) -> &'a T {
|
|
||||||
match self {
|
|
||||||
&RefOrOwned::Borrowed(r) => r,
|
|
||||||
&RefOrOwned::Owned(ref r) => r,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::parser::ast::*;
|
|
||||||
|
|
||||||
use crate::clause_types::*;
|
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::heap_iter::*;
|
use crate::heap_iter::*;
|
||||||
use crate::heap_print::*;
|
use crate::heap_print::*;
|
||||||
|
use crate::machine::Machine;
|
||||||
use crate::machine::attributed_variables::*;
|
use crate::machine::attributed_variables::*;
|
||||||
use crate::machine::copier::*;
|
use crate::machine::copier::*;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
@@ -13,20 +11,15 @@ use crate::machine::machine_errors::*;
|
|||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
|
use crate::parser::ast::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use crate::parser::rug::Integer;
|
use crate::parser::rug::Integer;
|
||||||
|
|
||||||
use downcast::{
|
|
||||||
downcast, downcast_methods, downcast_methods_core, downcast_methods_std, impl_downcast, Any,
|
|
||||||
};
|
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@@ -83,6 +76,9 @@ pub struct MachineState {
|
|||||||
pub(super) ball: Ball,
|
pub(super) ball: Ball,
|
||||||
pub(super) lifted_heap: Heap,
|
pub(super) lifted_heap: Heap,
|
||||||
pub(super) interms: Vec<Number>, // intermediate numbers.
|
pub(super) interms: Vec<Number>, // intermediate numbers.
|
||||||
|
// locations of cleaners, cut points, the previous block. for setup_call_cleanup.
|
||||||
|
pub(super) cont_pts: Vec<(HeapCellValue, usize, usize)>,
|
||||||
|
pub(super) cwil: CWIL,
|
||||||
pub(super) last_call: bool, // TODO: REMOVE THIS.
|
pub(super) last_call: bool, // TODO: REMOVE THIS.
|
||||||
pub(crate) flags: MachineFlags,
|
pub(crate) flags: MachineFlags,
|
||||||
pub(crate) cc: usize,
|
pub(crate) cc: usize,
|
||||||
@@ -90,6 +86,8 @@ pub struct MachineState {
|
|||||||
pub(crate) dynamic_mode: FirstOrNext,
|
pub(crate) dynamic_mode: FirstOrNext,
|
||||||
pub(crate) unify_fn: fn(&mut MachineState),
|
pub(crate) unify_fn: fn(&mut MachineState),
|
||||||
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
||||||
|
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
||||||
|
pub(crate) increment_call_count_fn: fn(&mut MachineState) -> CallResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MachineState {
|
impl fmt::Debug for MachineState {
|
||||||
@@ -178,505 +176,6 @@ impl IndexMut<RegType> for MachineState {
|
|||||||
|
|
||||||
pub type CallResult = Result<(), Vec<HeapCellValue>>;
|
pub type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||||
|
|
||||||
pub trait CutPolicy: Any + fmt::Debug {
|
|
||||||
// returns true iff we fail or cut redirected the MachineState's p itself
|
|
||||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
downcast!(dyn CutPolicy);
|
|
||||||
|
|
||||||
pub trait CallPolicy: Any + fmt::Debug {
|
|
||||||
fn retry_me_else(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
offset: usize,
|
|
||||||
global_variables: &mut GlobalVarDir,
|
|
||||||
) -> CallResult {
|
|
||||||
let b = machine_st.b;
|
|
||||||
let or_frame = machine_st.stack.index_or_frame_mut(b);
|
|
||||||
let n = or_frame.prelude.univ_prelude.num_cells;
|
|
||||||
|
|
||||||
for i in 0..n {
|
|
||||||
machine_st.registers[i + 1] = or_frame[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
|
||||||
machine_st.e = or_frame.prelude.e;
|
|
||||||
machine_st.cp = or_frame.prelude.cp;
|
|
||||||
|
|
||||||
or_frame.prelude.bp = machine_st.p.local() + offset;
|
|
||||||
|
|
||||||
let old_tr = or_frame.prelude.tr;
|
|
||||||
let curr_tr = machine_st.tr;
|
|
||||||
let target_h = or_frame.prelude.h;
|
|
||||||
|
|
||||||
machine_st.tr = or_frame.prelude.tr;
|
|
||||||
|
|
||||||
machine_st.attr_var_init.reset();
|
|
||||||
machine_st.hb = machine_st.heap.len();
|
|
||||||
machine_st.p += 1;
|
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr, global_variables);
|
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
|
||||||
machine_st.heap.truncate(target_h);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn retry(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
offset: usize,
|
|
||||||
global_variables: &mut GlobalVarDir,
|
|
||||||
) -> CallResult {
|
|
||||||
let b = machine_st.b;
|
|
||||||
let or_frame = machine_st.stack.index_or_frame_mut(b);
|
|
||||||
let n = or_frame.prelude.univ_prelude.num_cells;
|
|
||||||
|
|
||||||
for i in 0..n {
|
|
||||||
machine_st.registers[i+1] = or_frame[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
|
||||||
machine_st.e = or_frame.prelude.e;
|
|
||||||
machine_st.cp = or_frame.prelude.cp;
|
|
||||||
|
|
||||||
// WAS: or_frame.prelude.bp = machine_st.p.local() + 1;
|
|
||||||
or_frame.prelude.biip += 1;
|
|
||||||
|
|
||||||
let old_tr = or_frame.prelude.tr;
|
|
||||||
let curr_tr = machine_st.tr;
|
|
||||||
let target_h = or_frame.prelude.h;
|
|
||||||
|
|
||||||
machine_st.tr = or_frame.prelude.tr;
|
|
||||||
machine_st.attr_var_init.reset();
|
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr, global_variables);
|
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
|
||||||
machine_st.heap.truncate(target_h);
|
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.len();
|
|
||||||
machine_st.p = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset));
|
|
||||||
|
|
||||||
machine_st.oip = 0;
|
|
||||||
machine_st.iip = 0;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn trust(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
offset: usize,
|
|
||||||
global_variables: &mut GlobalVarDir,
|
|
||||||
) -> CallResult {
|
|
||||||
let b = machine_st.b;
|
|
||||||
let or_frame = machine_st.stack.index_or_frame(b);
|
|
||||||
let n = or_frame.prelude.univ_prelude.num_cells;
|
|
||||||
|
|
||||||
for i in 0..n {
|
|
||||||
machine_st.registers[i+1] = or_frame[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
|
||||||
machine_st.e = or_frame.prelude.e;
|
|
||||||
machine_st.cp = or_frame.prelude.cp;
|
|
||||||
|
|
||||||
let old_tr = or_frame.prelude.tr;
|
|
||||||
let curr_tr = machine_st.tr;
|
|
||||||
let target_h = or_frame.prelude.h;
|
|
||||||
|
|
||||||
machine_st.tr = or_frame.prelude.tr;
|
|
||||||
|
|
||||||
machine_st.attr_var_init.reset();
|
|
||||||
machine_st.b = or_frame.prelude.b;
|
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr, global_variables);
|
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
|
||||||
machine_st.stack.truncate(b);
|
|
||||||
machine_st.heap.truncate(target_h);
|
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.len();
|
|
||||||
machine_st.p = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset));
|
|
||||||
|
|
||||||
machine_st.oip = 0;
|
|
||||||
machine_st.iip = 0;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn trust_me(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
global_variables: &mut GlobalVarDir,
|
|
||||||
) -> CallResult {
|
|
||||||
let b = machine_st.b;
|
|
||||||
let or_frame = machine_st.stack.index_or_frame(b);
|
|
||||||
let n = or_frame.prelude.univ_prelude.num_cells;
|
|
||||||
|
|
||||||
for i in 0..n {
|
|
||||||
machine_st.registers[i+1] = or_frame[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
|
||||||
machine_st.e = or_frame.prelude.e;
|
|
||||||
machine_st.cp = or_frame.prelude.cp;
|
|
||||||
|
|
||||||
let old_tr = or_frame.prelude.tr;
|
|
||||||
let curr_tr = machine_st.tr;
|
|
||||||
let target_h = or_frame.prelude.h;
|
|
||||||
|
|
||||||
machine_st.tr = or_frame.prelude.tr;
|
|
||||||
|
|
||||||
machine_st.attr_var_init.reset();
|
|
||||||
machine_st.b = or_frame.prelude.b;
|
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr, global_variables);
|
|
||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
|
||||||
machine_st.stack.truncate(b);
|
|
||||||
machine_st.heap.truncate(target_h);
|
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.len();
|
|
||||||
machine_st.p += 1;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn context_call(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
name: Atom,
|
|
||||||
arity: usize,
|
|
||||||
idx: &CodeIndex,
|
|
||||||
) -> CallResult {
|
|
||||||
if machine_st.last_call {
|
|
||||||
self.try_execute(machine_st, name, arity, idx)
|
|
||||||
} else {
|
|
||||||
self.try_call(machine_st, name, arity, idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_call(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
name: Atom,
|
|
||||||
arity: usize,
|
|
||||||
idx: &CodeIndex,
|
|
||||||
) -> CallResult {
|
|
||||||
match idx.get() {
|
|
||||||
IndexPtr::DynamicUndefined => {
|
|
||||||
machine_st.fail = true;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
IndexPtr::Undefined => {
|
|
||||||
return Err(machine_st.throw_undefined_error(name, arity));
|
|
||||||
}
|
|
||||||
IndexPtr::DynamicIndex(compiled_tl_index) => {
|
|
||||||
machine_st.dynamic_mode = FirstOrNext::First;
|
|
||||||
machine_st.call_at_index(arity, dir_entry!(compiled_tl_index));
|
|
||||||
}
|
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
|
||||||
machine_st.call_at_index(arity, dir_entry!(compiled_tl_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_execute(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
name: Atom,
|
|
||||||
arity: usize,
|
|
||||||
idx: &CodeIndex,
|
|
||||||
) -> CallResult {
|
|
||||||
match idx.get() {
|
|
||||||
IndexPtr::DynamicUndefined => {
|
|
||||||
machine_st.fail = true;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
IndexPtr::Undefined => {
|
|
||||||
return Err(machine_st.throw_undefined_error(name, arity));
|
|
||||||
}
|
|
||||||
IndexPtr::DynamicIndex(compiled_tl_index) => {
|
|
||||||
machine_st.dynamic_mode = FirstOrNext::First;
|
|
||||||
machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index));
|
|
||||||
}
|
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
|
||||||
machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_builtin(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
ct: &BuiltInClauseType,
|
|
||||||
_code_dir: &CodeDir,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
stream_aliases: &StreamAliasDir,
|
|
||||||
) -> CallResult {
|
|
||||||
match ct {
|
|
||||||
&BuiltInClauseType::AcyclicTerm => {
|
|
||||||
let addr = machine_st.registers[1];
|
|
||||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Arg => {
|
|
||||||
machine_st.try_arg()?;
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Compare => {
|
|
||||||
let stub_gen = || functor_stub(atom!("compare"), 3);
|
|
||||||
|
|
||||||
let a1 = machine_st.store(machine_st.deref(machine_st.registers[1]));
|
|
||||||
let a2 = machine_st.registers[2];
|
|
||||||
let a3 = machine_st.registers[3];
|
|
||||||
|
|
||||||
read_heap_cell!(a1,
|
|
||||||
(HeapCellValueTag::Str, s) => {
|
|
||||||
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
match name {
|
|
||||||
atom!(">") | atom!("<") | atom!("=") if arity == 2 => {
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let err = machine_st.domain_error(DomainErrorType::Order, a1);
|
|
||||||
return Err(machine_st.error_form(err, stub_gen()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let err = machine_st.type_error(ValidType::Atom, a1);
|
|
||||||
return Err(machine_st.error_form(err, stub_gen()));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let atom = match compare_term_test!(machine_st, a2, a3) {
|
|
||||||
Some(Ordering::Greater) => {
|
|
||||||
atom!(">")
|
|
||||||
}
|
|
||||||
Some(Ordering::Equal) => {
|
|
||||||
atom!("=")
|
|
||||||
}
|
|
||||||
None | Some(Ordering::Less) => {
|
|
||||||
atom!("<")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
machine_st.unify_atom(atom, a1);
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::CompareTerm(qt) => {
|
|
||||||
machine_st.compare_term(qt);
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Read => {
|
|
||||||
let stream = machine_st.get_stream_or_alias(
|
|
||||||
machine_st.registers[1],
|
|
||||||
stream_aliases,
|
|
||||||
atom!("read"),
|
|
||||||
2,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
match machine_st.read(stream, op_dir) {
|
|
||||||
Ok(offset) => {
|
|
||||||
let value = machine_st.registers[2];
|
|
||||||
unify_fn!(machine_st, value, heap_loc_as_cell!(offset.heap_loc));
|
|
||||||
}
|
|
||||||
Err(ParserError::UnexpectedEOF) => {
|
|
||||||
let value = machine_st.registers[2];
|
|
||||||
machine_st.unify_atom(atom!("end_of_file"), value);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let stub = functor_stub(atom!("read"), 2);
|
|
||||||
let err = machine_st.syntax_error(e);
|
|
||||||
|
|
||||||
return Err(machine_st.error_form(err, stub));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::CopyTerm => {
|
|
||||||
machine_st.copy_term(AttrVarPolicy::DeepCopy);
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Eq => {
|
|
||||||
let a1 = machine_st.registers[1];
|
|
||||||
let a2 = machine_st.registers[2];
|
|
||||||
|
|
||||||
machine_st.fail = machine_st.eq_test(a1, a2);
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Ground => {
|
|
||||||
machine_st.fail = machine_st.ground_test();
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Functor => {
|
|
||||||
machine_st.try_functor()?;
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::NotEq => {
|
|
||||||
let a1 = machine_st.registers[1];
|
|
||||||
let a2 = machine_st.registers[2];
|
|
||||||
|
|
||||||
machine_st.fail =
|
|
||||||
if let Some(Ordering::Equal) = compare_term_test!(machine_st, a1, a2) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Sort => {
|
|
||||||
machine_st.check_sort_errors()?;
|
|
||||||
|
|
||||||
let stub_gen = || functor_stub(atom!("sort"), 2);
|
|
||||||
let mut list = machine_st.try_from_list(machine_st.registers[1], stub_gen)?;
|
|
||||||
|
|
||||||
list.sort_unstable_by(|v1, v2| {
|
|
||||||
compare_term_test!(machine_st, *v1, *v2).unwrap_or(Ordering::Less)
|
|
||||||
});
|
|
||||||
|
|
||||||
list.dedup_by(|v1, v2| {
|
|
||||||
compare_term_test!(machine_st, *v1, *v2) == Some(Ordering::Equal)
|
|
||||||
});
|
|
||||||
|
|
||||||
let heap_addr = heap_loc_as_cell!(
|
|
||||||
iter_to_heap_list(&mut machine_st.heap, list.into_iter())
|
|
||||||
);
|
|
||||||
|
|
||||||
let r2 = machine_st.registers[2];
|
|
||||||
unify_fn!(machine_st, r2, heap_addr);
|
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::KeySort => {
|
|
||||||
machine_st.check_keysort_errors()?;
|
|
||||||
|
|
||||||
let stub_gen = || functor_stub(atom!("keysort"), 2);
|
|
||||||
let list = machine_st.try_from_list(machine_st.registers[1], stub_gen)?;
|
|
||||||
|
|
||||||
let mut key_pairs = Vec::with_capacity(list.len());
|
|
||||||
|
|
||||||
for val in list {
|
|
||||||
let key = machine_st.project_onto_key(val)?;
|
|
||||||
key_pairs.push((key, val));
|
|
||||||
}
|
|
||||||
|
|
||||||
key_pairs.sort_by(|a1, a2| {
|
|
||||||
compare_term_test!(machine_st, a1.0, a2.0).unwrap_or(Ordering::Less)
|
|
||||||
});
|
|
||||||
|
|
||||||
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
|
||||||
let heap_addr = heap_loc_as_cell!(
|
|
||||||
iter_to_heap_list(&mut machine_st.heap, key_pairs)
|
|
||||||
);
|
|
||||||
|
|
||||||
let r2 = machine_st.registers[2];
|
|
||||||
unify_fn!(machine_st, r2, heap_addr);
|
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Is(r, ref at) => {
|
|
||||||
let n1 = machine_st.store(machine_st.deref(machine_st[r]));
|
|
||||||
let n2 = machine_st.get_number(at)?;
|
|
||||||
|
|
||||||
match n2 {
|
|
||||||
Number::Fixnum(n) => machine_st.unify_fixnum(n, n1),
|
|
||||||
Number::Float(n) => {
|
|
||||||
// TODO: argghh.. deal with it.
|
|
||||||
let n = arena_alloc!(n, &mut machine_st.arena);
|
|
||||||
machine_st.unify_f64(n, n1)
|
|
||||||
}
|
|
||||||
Number::Integer(n) => machine_st.unify_big_int(n, n1),
|
|
||||||
Number::Rational(n) => machine_st.unify_rational(n, n1),
|
|
||||||
}
|
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_clause_type(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
key: PredicateKey,
|
|
||||||
code_dir: &CodeDir,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
stream_aliases: &StreamAliasDir,
|
|
||||||
) -> CallResult {
|
|
||||||
let (name, arity) = key;
|
|
||||||
|
|
||||||
match ClauseType::from(name, arity) {
|
|
||||||
ClauseType::BuiltIn(built_in) => {
|
|
||||||
machine_st.setup_built_in_call(built_in);
|
|
||||||
self.call_builtin(machine_st, &built_in, code_dir, op_dir, stream_aliases)?;
|
|
||||||
}
|
|
||||||
ClauseType::CallN => {
|
|
||||||
machine_st.handle_internal_call_n(arity);
|
|
||||||
|
|
||||||
if machine_st.fail {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
|
|
||||||
}
|
|
||||||
ClauseType::Inlined(inlined) => {
|
|
||||||
machine_st.execute_inlined(&inlined);
|
|
||||||
|
|
||||||
if machine_st.last_call {
|
|
||||||
machine_st.p = CodePtr::Local(machine_st.cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClauseType::Named(..) => {
|
|
||||||
if let Some(idx) = code_dir.get(&(name, arity)) {
|
|
||||||
self.context_call(machine_st, name, arity, idx)?;
|
|
||||||
} else {
|
|
||||||
return Err(machine_st.throw_undefined_error(name, arity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClauseType::System(_) => {
|
|
||||||
let (name, arity) = key;
|
|
||||||
let name = functor!(name);
|
|
||||||
|
|
||||||
let stub = functor_stub(atom!("call"), arity + 1);
|
|
||||||
let err = machine_st.type_error(ValidType::Callable, name);
|
|
||||||
|
|
||||||
return Err(machine_st.error_form(err, stub));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_n(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
arity: usize,
|
|
||||||
code_dir: &CodeDir,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
stream_aliases: &StreamAliasDir,
|
|
||||||
) -> CallResult {
|
|
||||||
if let Some(key) = machine_st.setup_call_n(arity) {
|
|
||||||
self.call_clause_type(machine_st, key, code_dir, op_dir, stream_aliases)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixnum) {
|
pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixnum) {
|
||||||
read_heap_cell!(heap[index],
|
read_heap_cell!(heap[index],
|
||||||
@@ -866,6 +365,26 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
|
pub(crate) fn increment_call_count(&mut self) -> CallResult {
|
||||||
|
if self.cwil.inference_limit_exceeded || self.ball.stub.len() > 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(&(ref limit, bp)) = self.cwil.limits.last() {
|
||||||
|
if self.cwil.count == *limit {
|
||||||
|
self.cwil.inference_limit_exceeded = true;
|
||||||
|
|
||||||
|
return Err(
|
||||||
|
functor!(atom!("inference_limit_exceeded"), [fixnum(bp)])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.cwil.count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(super) fn try_char_list(&mut self, addrs: Vec<HeapCellValue>) -> Result<String, MachineError> {
|
pub(super) fn try_char_list(&mut self, addrs: Vec<HeapCellValue>) -> Result<String, MachineError> {
|
||||||
let mut chars = String::new();
|
let mut chars = String::new();
|
||||||
@@ -958,7 +477,7 @@ impl MachineState {
|
|||||||
match self.read(stream, &indices.op_dir) {
|
match self.read(stream, &indices.op_dir) {
|
||||||
Ok(term_write_result) => {
|
Ok(term_write_result) => {
|
||||||
let term = self.registers[2];
|
let term = self.registers[2];
|
||||||
unify_fn!(self, heap_loc_as_cell!(term_write_result.heap_loc), term);
|
unify_fn!(*self, heap_loc_as_cell!(term_write_result.heap_loc), term);
|
||||||
let term = heap_loc_as_cell!(term_write_result.heap_loc);
|
let term = heap_loc_as_cell!(term_write_result.heap_loc);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail {
|
||||||
@@ -1004,7 +523,7 @@ impl MachineState {
|
|||||||
iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter())
|
iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter())
|
||||||
);
|
);
|
||||||
|
|
||||||
unify_fn!(self, singletons_offset, singleton_addr);
|
unify_fn!(*self, singletons_offset, singleton_addr);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1015,7 +534,7 @@ impl MachineState {
|
|||||||
iter_to_heap_list(&mut self.heap, var_list.into_iter())
|
iter_to_heap_list(&mut self.heap, var_list.into_iter())
|
||||||
);
|
);
|
||||||
|
|
||||||
unify_fn!(self, vars_offset, vars_addr);
|
unify_fn!(*self, vars_offset, vars_addr);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1026,7 +545,7 @@ impl MachineState {
|
|||||||
iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter())
|
iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter())
|
||||||
);
|
);
|
||||||
|
|
||||||
return Ok(unify_fn!(self, var_names_offset, var_names_addr));
|
return Ok(unify_fn!(*self, var_names_offset, var_names_addr));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let ParserError::UnexpectedEOF = err {
|
if let ParserError::UnexpectedEOF = err {
|
||||||
@@ -1163,83 +682,96 @@ impl MachineState {
|
|||||||
(name, usize::try_from(arity.get_num()).unwrap())
|
(name, usize::try_from(arity.get_num()).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn module_lookup(
|
#[inline(always)]
|
||||||
&mut self,
|
pub(super) fn cut_body(&mut self, value: HeapCellValue) {
|
||||||
indices: &IndexStore,
|
let b = self.b;
|
||||||
call_policy: &mut Box<dyn CallPolicy>,
|
|
||||||
key: PredicateKey,
|
read_heap_cell!(value,
|
||||||
module_name: Atom,
|
(HeapCellValueTag::Fixnum, b0) => {
|
||||||
_last_call: bool,
|
let b0 = b0.get_num() as usize;
|
||||||
stream_aliases: &StreamAliasDir,
|
|
||||||
) -> CallResult {
|
if b > b0 {
|
||||||
if module_name == atom!("user") {
|
self.b = b0;
|
||||||
return call_policy.call_clause_type(
|
}
|
||||||
self,
|
}
|
||||||
key,
|
_ => {
|
||||||
&indices.code_dir,
|
self.fail = true;
|
||||||
&indices.op_dir,
|
}
|
||||||
stream_aliases,
|
);
|
||||||
);
|
}
|
||||||
} else if let Some(module) = indices.modules.get(&module_name) {
|
|
||||||
return call_policy.call_clause_type(
|
#[inline(always)]
|
||||||
self,
|
pub(super) fn try_me_else(&mut self, offset: usize) {
|
||||||
key,
|
let n = self.num_of_args;
|
||||||
&module.code_dir,
|
let b = self.stack.allocate_or_frame(n);
|
||||||
&module.op_dir,
|
let or_frame = self.stack.index_or_frame_mut(b);
|
||||||
stream_aliases,
|
|
||||||
);
|
or_frame.prelude.univ_prelude.num_cells = n;
|
||||||
|
or_frame.prelude.e = self.e;
|
||||||
|
or_frame.prelude.cp = self.cp;
|
||||||
|
or_frame.prelude.b = self.b;
|
||||||
|
or_frame.prelude.bp = self.p.local() + offset;
|
||||||
|
or_frame.prelude.boip = 0;
|
||||||
|
or_frame.prelude.biip = 0;
|
||||||
|
or_frame.prelude.tr = self.tr;
|
||||||
|
or_frame.prelude.h = self.heap.len();
|
||||||
|
or_frame.prelude.b0 = self.b0;
|
||||||
|
|
||||||
|
self.b = b;
|
||||||
|
|
||||||
|
for i in 0..n {
|
||||||
|
self.stack[stack_loc!(OrFrame, b, i)] = self.registers[i+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
let (name, arity) = key;
|
self.hb = self.heap.len();
|
||||||
|
self.p += 1;
|
||||||
|
}
|
||||||
|
|
||||||
let stub = functor_stub(name, arity);
|
#[inline(always)]
|
||||||
let err = self.module_resolution_error(module_name, name, arity);
|
pub(super) fn indexed_try(&mut self, offset: usize) {
|
||||||
|
let n = self.num_of_args;
|
||||||
|
let b = self.stack.allocate_or_frame(n);
|
||||||
|
let or_frame = self.stack.index_or_frame_mut(b);
|
||||||
|
|
||||||
return Err(self.error_form(err, stub));
|
or_frame.prelude.univ_prelude.num_cells = n;
|
||||||
|
or_frame.prelude.e = self.e;
|
||||||
|
or_frame.prelude.cp = self.cp;
|
||||||
|
or_frame.prelude.b = self.b;
|
||||||
|
or_frame.prelude.bp = self.p.local(); // + 1; in self.iip now!
|
||||||
|
or_frame.prelude.boip = self.oip;
|
||||||
|
or_frame.prelude.biip = self.iip + 1;
|
||||||
|
or_frame.prelude.tr = self.tr;
|
||||||
|
or_frame.prelude.h = self.heap.len();
|
||||||
|
or_frame.prelude.b0 = self.b0;
|
||||||
|
|
||||||
|
self.b = b;
|
||||||
|
|
||||||
|
for i in 0..n {
|
||||||
|
or_frame[i] = self.registers[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.hb = self.heap.len();
|
||||||
|
self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset));
|
||||||
|
|
||||||
|
self.oip = 0;
|
||||||
|
self.iip = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct CWILCallPolicy {
|
pub(crate) struct CWIL {
|
||||||
pub(crate) prev_policy: Box<dyn CallPolicy>,
|
|
||||||
count: Integer,
|
count: Integer,
|
||||||
limits: Vec<(Integer, usize)>,
|
limits: Vec<(Integer, usize)>,
|
||||||
inference_limit_exceeded: bool,
|
inference_limit_exceeded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CWILCallPolicy {
|
impl CWIL {
|
||||||
pub(crate) fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
pub(crate) fn new() -> Self {
|
||||||
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
CWIL {
|
||||||
mem::swap(&mut prev_policy, policy);
|
|
||||||
|
|
||||||
let new_policy = CWILCallPolicy {
|
|
||||||
prev_policy,
|
|
||||||
count: Integer::from(0),
|
count: Integer::from(0),
|
||||||
limits: vec![],
|
limits: vec![],
|
||||||
inference_limit_exceeded: false,
|
inference_limit_exceeded: false,
|
||||||
};
|
|
||||||
|
|
||||||
*policy = Box::new(new_policy);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn increment(&mut self, machine_st: &MachineState) -> CallResult {
|
|
||||||
if self.inference_limit_exceeded || machine_st.ball.stub.len() > 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
|
||||||
if self.count == *limit {
|
|
||||||
self.inference_limit_exceeded = true;
|
|
||||||
|
|
||||||
return Err(
|
|
||||||
functor!(atom!("inference_limit_exceeded"), [fixnum(bp)])
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
self.count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_limit(&mut self, limit: usize, b: usize) -> &Integer {
|
pub(crate) fn add_limit(&mut self, limit: usize, b: usize) -> &Integer {
|
||||||
@@ -1254,6 +786,7 @@ impl CWILCallPolicy {
|
|||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
||||||
if let Some((_, bp)) = self.limits.last() {
|
if let Some((_, bp)) = self.limits.last() {
|
||||||
if bp == &b {
|
if bp == &b {
|
||||||
@@ -1264,207 +797,15 @@ impl CWILCallPolicy {
|
|||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn reset(&mut self) {
|
||||||
|
self.count = Integer::from(0);
|
||||||
|
self.limits.clear();
|
||||||
|
self.inference_limit_exceeded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub(crate) fn is_empty(&self) -> bool {
|
pub(crate) fn is_empty(&self) -> bool {
|
||||||
self.limits.is_empty()
|
self.limits.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
|
||||||
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
|
||||||
mem::swap(&mut self.prev_policy, &mut new_inner);
|
|
||||||
new_inner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallPolicy for CWILCallPolicy {
|
|
||||||
fn context_call(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
name: Atom,
|
|
||||||
arity: usize,
|
|
||||||
idx: &CodeIndex,
|
|
||||||
) -> CallResult {
|
|
||||||
self.prev_policy.context_call(machine_st, name, arity, idx)?;
|
|
||||||
self.increment(machine_st)
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
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,
|
|
||||||
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,
|
|
||||||
global_variables: &mut GlobalVarDir,
|
|
||||||
) -> CallResult {
|
|
||||||
self.prev_policy.trust(machine_st, offset, global_variables)?;
|
|
||||||
self.increment(machine_st)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_builtin(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
ct: &BuiltInClauseType,
|
|
||||||
code_dir: &CodeDir,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
stream_aliases: &StreamAliasDir,
|
|
||||||
) -> CallResult {
|
|
||||||
self.prev_policy.call_builtin(machine_st, ct, code_dir, op_dir, stream_aliases)?;
|
|
||||||
self.increment(machine_st)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_n(
|
|
||||||
&mut self,
|
|
||||||
machine_st: &mut MachineState,
|
|
||||||
arity: usize,
|
|
||||||
code_dir: &CodeDir,
|
|
||||||
op_dir: &OpDir,
|
|
||||||
stream_aliases: &StreamAliasDir,
|
|
||||||
) -> CallResult {
|
|
||||||
self.prev_policy.call_n(machine_st, arity, code_dir, op_dir, stream_aliases)?;
|
|
||||||
self.increment(machine_st)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downcast!(dyn CallPolicy);
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct DefaultCallPolicy {}
|
|
||||||
|
|
||||||
impl CallPolicy for DefaultCallPolicy {}
|
|
||||||
|
|
||||||
fn cut_body(machine_st: &mut MachineState, addr: HeapCellValue) -> bool {
|
|
||||||
let b = machine_st.b;
|
|
||||||
|
|
||||||
read_heap_cell!(addr,
|
|
||||||
(HeapCellValueTag::Fixnum, b0) => {
|
|
||||||
let b0 = b0.get_num() as usize;
|
|
||||||
|
|
||||||
if b > b0 {
|
|
||||||
machine_st.b = b0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
machine_st.fail = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct DefaultCutPolicy {}
|
|
||||||
|
|
||||||
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
|
|
||||||
let addr = machine_st.store(machine_st.deref(machine_st[r]));
|
|
||||||
cut_body(machine_st, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CutPolicy for DefaultCutPolicy {
|
|
||||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
|
||||||
let addr = machine_st[r];
|
|
||||||
cut_body(machine_st, addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct SCCCutPolicy {
|
|
||||||
// locations of cleaners, cut points, the previous block
|
|
||||||
cont_pts: Vec<(HeapCellValue, usize, usize)>,
|
|
||||||
r_c_w_h: usize,
|
|
||||||
r_c_wo_h: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SCCCutPolicy {
|
|
||||||
pub(crate) fn new(r_c_w_h: usize, r_c_wo_h: usize) -> Self {
|
|
||||||
SCCCutPolicy {
|
|
||||||
cont_pts: vec![],
|
|
||||||
r_c_w_h,
|
|
||||||
r_c_wo_h,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn out_of_cont_pts(&self) -> bool {
|
|
||||||
self.cont_pts.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn push_cont_pt(&mut self, addr: HeapCellValue, b: usize, prev_b: usize) {
|
|
||||||
self.cont_pts.push((addr, b, prev_b));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn pop_cont_pt(&mut self) -> Option<(HeapCellValue, usize, usize)> {
|
|
||||||
self.cont_pts.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_cleaners(&self, machine_st: &mut MachineState) -> bool {
|
|
||||||
if let Some(&(_, b_cutoff, prev_block)) = self.cont_pts.last() {
|
|
||||||
if machine_st.b < b_cutoff {
|
|
||||||
let (idx, arity) = if machine_st.block > prev_block {
|
|
||||||
(dir_entry!(self.r_c_w_h), 0)
|
|
||||||
} else {
|
|
||||||
machine_st.registers[1] = fixnum_as_cell!(Fixnum::build_with(b_cutoff as i64));
|
|
||||||
(dir_entry!(self.r_c_wo_h), 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
if machine_st.last_call {
|
|
||||||
machine_st.execute_at_index(arity, idx);
|
|
||||||
} else {
|
|
||||||
machine_st.call_at_index(arity, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CutPolicy for SCCCutPolicy {
|
|
||||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
|
||||||
let b = machine_st.b;
|
|
||||||
|
|
||||||
read_heap_cell!(machine_st[r],
|
|
||||||
(HeapCellValueTag::Fixnum, b0) => {
|
|
||||||
let b0 = b0.get_num() as usize;
|
|
||||||
|
|
||||||
if b > b0 {
|
|
||||||
machine_st.b = b0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
machine_st.fail = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
self.run_cleaners(machine_st)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -226,8 +226,6 @@ impl Machine {
|
|||||||
|
|
||||||
let mut wam = Machine {
|
let mut wam = Machine {
|
||||||
machine_st,
|
machine_st,
|
||||||
inner_heap: Heap::new(),
|
|
||||||
policies: MachinePolicies::new(),
|
|
||||||
indices: IndexStore::new(),
|
indices: IndexStore::new(),
|
||||||
code_repo: CodeRepo::new(),
|
code_repo: CodeRepo::new(),
|
||||||
user_input,
|
user_input,
|
||||||
|
|||||||
1044
src/machine/mod.rs
1044
src/machine/mod.rs
File diff suppressed because it is too large
Load Diff
@@ -542,14 +542,12 @@ fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Preprocessor {
|
pub(crate) struct Preprocessor {
|
||||||
flags: MachineFlags,
|
|
||||||
queue: VecDeque<VecDeque<Term>>,
|
queue: VecDeque<VecDeque<Term>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Preprocessor {
|
impl Preprocessor {
|
||||||
pub(super) fn new(flags: MachineFlags) -> Self {
|
pub(super) fn new() -> Self {
|
||||||
Preprocessor {
|
Preprocessor {
|
||||||
flags,
|
|
||||||
queue: VecDeque::new(),
|
queue: VecDeque::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -778,7 +778,7 @@ macro_rules! unify {
|
|||||||
macro_rules! unify_fn {
|
macro_rules! unify_fn {
|
||||||
($machine_st:expr, $($value:expr),*) => {{
|
($machine_st:expr, $($value:expr),*) => {{
|
||||||
$($machine_st.pdl.push($value);)*
|
$($machine_st.pdl.push($value);)*
|
||||||
($machine_st.unify_fn)($machine_st)
|
($machine_st.unify_fn)(&mut $machine_st)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user