flatten the instruction dispatch loop

This commit is contained in:
Mark Thom
2021-12-19 18:57:57 -07:00
parent 3db86f1e25
commit 955e1799c8
52 changed files with 14247 additions and 10021 deletions

76
Cargo.lock generated
View File

@@ -378,6 +378,15 @@ dependencies = [
"new_debug_unreachable",
]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "generic-array"
version = "0.12.4"
@@ -436,6 +445,15 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hostname"
version = "0.3.1"
@@ -471,6 +489,20 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "instructions-template"
version = "0.1.0"
dependencies = [
"indexmap",
"proc-macro2 1.0.32",
"quote 1.0.10",
"strum",
"strum_macros",
"syn 1.0.81",
"to-syn-value",
"to-syn-value_derive",
]
[[package]]
name = "iovec"
version = "0.1.4"
@@ -1325,6 +1357,12 @@ dependencies = [
"libc",
]
[[package]]
name = "rustversion"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
[[package]]
name = "rustyline"
version = "9.0.0"
@@ -1392,9 +1430,11 @@ dependencies = [
"crossterm",
"dirs-next",
"divrem",
"fxhash",
"git-version",
"hostname",
"indexmap",
"instructions-template",
"lazy_static",
"lexical",
"libc",
@@ -1655,6 +1695,25 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
[[package]]
name = "strum"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
[[package]]
name = "strum_macros"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
dependencies = [
"heck",
"proc-macro2 1.0.32",
"quote 1.0.10",
"rustversion",
"syn 1.0.81",
]
[[package]]
name = "subtle"
version = "1.0.0"
@@ -1724,6 +1783,23 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "to-syn-value"
version = "0.1.0"
dependencies = [
"syn 1.0.81",
"to-syn-value_derive",
]
[[package]]
name = "to-syn-value_derive"
version = "0.1.0"
dependencies = [
"proc-macro2 1.0.32",
"quote 1.0.10",
"syn 1.0.81",
]
[[package]]
name = "typenum"
version = "1.14.0"

View File

@@ -12,7 +12,11 @@ categories = ["command-line-utilities"]
build = "build.rs"
[workspace]
members = ["crates/num-rug-adapter", "crates/static-string-indexing"]
members = ["crates/num-rug-adapter",
"crates/static-string-indexing",
"crates/instructions-template",
"crates/to-syn-value",
"crates/to-syn-value_derive"]
[features]
num = ["num-rug-adapter"]
@@ -24,6 +28,7 @@ default = ["rug"]
[build-dependencies]
indexmap = "1.0.2"
static-string-indexing = { path = "./crates/static-string-indexing" }
instructions-template = { path = "./crates/instructions-template" }
proc-macro2 = "*"
[dependencies]
@@ -31,13 +36,13 @@ cpu-time = "1.0.0"
crossterm = "0.16.0"
dirs-next = "2.0.0"
divrem = "0.1.0"
fxhash = "0.2.1"
git-version = "0.3.4"
hostname = "0.3.1"
indexmap = "1.0.2"
lazy_static = "1.4.0"
lexical = "5.2.2"
libc = "0.2.62"
# temporary to remove unnecessary braces warnings.
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" } # modular-bitfield = "0.11.2"
nix = "0.15.0"
num-rug-adapter = { optional = true, path = "./crates/num-rug-adapter" }

View File

@@ -1,4 +1,5 @@
use static_string_indexing::index_static_strings;
use instructions_template::generate_instructions_rs;
use std::env;
use std::fs;
@@ -55,6 +56,20 @@ fn main() {
find_prolog_files(&mut libraries, "", &lib_path);
libraries.write_all(b"\n m\n };\n}\n").unwrap();
let instructions_path = Path::new("src/instructions.rs");
let mut instructions_file = File::create(&instructions_path).unwrap();
let quoted_output = generate_instructions_rs();
instructions_file
.write_all(quoted_output.to_string().as_bytes())
.unwrap();
Command::new("rustfmt")
.arg(instructions_path.as_os_str())
.spawn().unwrap()
.wait().unwrap();
let static_atoms_path = Path::new("src/static_atoms.rs");
let mut static_atoms_file = File::create(&static_atoms_path).unwrap();

129
crates/instructions-template/Cargo.lock generated Normal file
View File

@@ -0,0 +1,129 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "indexmap"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instructions-template"
version = "0.1.0"
dependencies = [
"indexmap",
"proc-macro2",
"quote",
"strum",
"strum_macros",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "392a54546fda6b7cc663379d0e6ce8b324cf88aecc5a499838e1be9781bdce2e"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
[[package]]
name = "strum"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
[[package]]
name = "strum_macros"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "1.0.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "to-syn-value"
version = "0.1.0"
dependencies = [
"syn",
"to-syn-value_derive",
]
[[package]]
name = "to-syn-value_derive"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"

View File

@@ -0,0 +1,14 @@
[package]
name = "instructions-template"
version = "0.1.0"
edition = "2021"
[dependencies]
indexmap = "*"
proc-macro2 = "*"
quote = "*"
strum = "0.23"
strum_macros = "0.23"
syn = { version = "*", features = ['full', 'visit', 'extra-traits'] }
to-syn-value = { path = "../to-syn-value" }
to-syn-value_derive = { path = "../to-syn-value_derive" }

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +0,0 @@
[package]
name = "prolog_parser"
version = "0.8.68"
authors = ["Mark Thom <markjordanthom@gmail.com>"]
edition = "2021"
repository = "https://github.com/mthom/scryer-prolog"
description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation."
license = "BSD-3-Clause"
[dependencies]
indexmap = "1.0.2"
lexical = "5.2.1"
ordered-float = "0.5.0"
rug = { optional = true, version = "1.4.0" }
num-rug-adapter = { optional = true, path = "../num-rug-adapter" }
unicode_reader = "1.0.0"
[lib]
path = "src/lib.rs"
[features]
num = ["num-rug-adapter"]
# no default features to make num tests work
# workaround for --no-default-features and --features not working intuitively for workspaces with a root package
# see rust-lang/cargo#7160
# default = ["rug"]

View File

@@ -1,7 +1,7 @@
[package]
name = "static-string-indexing"
version = "0.1.0"
edition = "2018"
edition = "2021"
[dependencies]
proc-macro2 = "*"

View File

@@ -0,0 +1,10 @@
[package]
name = "to-syn-value"
version = "0.1.0"
authors = ["Mark Thom <markjordanthom@gmail.com>"]
edition = "2021"
publish = false
[dependencies]
syn = { version = "*", features = ['full', 'visit', 'extra-traits'] }
to-syn-value_derive = { path = "../to-syn-value_derive" }

View File

@@ -0,0 +1,3 @@
pub trait ToDeriveInput {
fn to_derive_input() -> syn::DeriveInput;
}

View File

@@ -0,0 +1,14 @@
[package]
name = "to-syn-value_derive"
version = "0.1.0"
authors = ["Mark Thom <markjordanthom@gmail.com>"]
edition = "2021"
publish = false
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "*"
syn = { version = "*", features = ['full', 'visit', 'extra-traits'] }
quote = "*"

View File

@@ -0,0 +1,20 @@
use syn::*;
use quote::*;
#[proc_macro_derive(ToDeriveInput)]
pub fn derive_to_derive_input(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive_input = parse_macro_input!(input as DeriveInput);
let ty_name = derive_input.ident.clone();
quote! {
use to_syn_value::*;
impl ToDeriveInput for #ty_name {
fn to_derive_input() -> syn::DeriveInput {
syn::parse_quote! {
#derive_input
}
}
}
}.into()
}

View File

@@ -3,6 +3,7 @@ use crate::temp_v;
use crate::fixtures::*;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::machine_indices::*;
use std::cell::Cell;
@@ -11,7 +12,7 @@ use std::rc::Rc;
pub(crate) trait Allocator<'a> {
fn new() -> Self;
fn mark_anon_var<Target>(&mut self, _: Level, _: GenContext, _: &mut Vec<Target>)
fn mark_anon_var<Target>(&mut self, _: Level, _: GenContext, _: &mut Code)
where
Target: crate::targets::CompilationTarget<'a>;
fn mark_non_var<Target>(
@@ -19,7 +20,7 @@ pub(crate) trait Allocator<'a> {
_: Level,
_: GenContext,
_: &'a Cell<RegType>,
_: &mut Vec<Target>,
_: &mut Code,
) where
Target: crate::targets::CompilationTarget<'a>;
fn mark_reserved_var<Target>(
@@ -28,7 +29,7 @@ pub(crate) trait Allocator<'a> {
_: Level,
_: &'a Cell<VarReg>,
_: GenContext,
_: &mut Vec<Target>,
_: &mut Code,
_: RegType,
_: bool,
) where
@@ -39,7 +40,7 @@ pub(crate) trait Allocator<'a> {
_: Level,
_: &'a Cell<VarReg>,
_: GenContext,
_: &mut Vec<Target>,
_: &mut Code,
) where
Target: crate::targets::CompilationTarget<'a>;

View File

@@ -1,6 +1,5 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::instructions::*;
@@ -25,6 +24,29 @@ use std::ops::Div;
use std::rc::Rc;
use std::vec::Vec;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ArithmeticTerm {
Reg(RegType),
Interm(usize),
Number(Number),
}
impl ArithmeticTerm {
pub(crate) fn interm_or(&self, interm: usize) -> usize {
if let &ArithmeticTerm::Interm(interm) = self {
interm
} else {
interm
}
}
}
impl Default for ArithmeticTerm {
fn default() -> Self {
ArithmeticTerm::Number(Number::default())
}
}
#[derive(Debug)]
pub(crate) struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>>,
@@ -46,7 +68,7 @@ impl<'a> ArithInstructionIterator<'a> {
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
}
ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => {
let ct = ClauseType::Named(atom!("float"), 1, CodeIndex::default());
let ct = ClauseType::Named(1, atom!("float"), CodeIndex::default());
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
}
_ => Err(ArithmeticError::NonEvaluableFunctor(
@@ -174,27 +196,27 @@ impl<'a> ArithmeticEvaluator<'a> {
name: Atom,
a1: ArithmeticTerm,
t: usize,
) -> Result<ArithmeticInstruction, ArithmeticError> {
) -> Result<Instruction, ArithmeticError> {
match name {
atom!("abs") => Ok(ArithmeticInstruction::Abs(a1, t)),
atom!("-") => Ok(ArithmeticInstruction::Neg(a1, t)),
atom!("+") => Ok(ArithmeticInstruction::Plus(a1, t)),
atom!("cos") => Ok(ArithmeticInstruction::Cos(a1, t)),
atom!("sin") => Ok(ArithmeticInstruction::Sin(a1, t)),
atom!("tan") => Ok(ArithmeticInstruction::Tan(a1, t)),
atom!("log") => Ok(ArithmeticInstruction::Log(a1, t)),
atom!("exp") => Ok(ArithmeticInstruction::Exp(a1, t)),
atom!("sqrt") => Ok(ArithmeticInstruction::Sqrt(a1, t)),
atom!("acos") => Ok(ArithmeticInstruction::ACos(a1, t)),
atom!("asin") => Ok(ArithmeticInstruction::ASin(a1, t)),
atom!("atan") => Ok(ArithmeticInstruction::ATan(a1, t)),
atom!("float") => Ok(ArithmeticInstruction::Float(a1, t)),
atom!("truncate") => Ok(ArithmeticInstruction::Truncate(a1, t)),
atom!("round") => Ok(ArithmeticInstruction::Round(a1, t)),
atom!("ceiling") => Ok(ArithmeticInstruction::Ceiling(a1, t)),
atom!("floor") => Ok(ArithmeticInstruction::Floor(a1, t)),
atom!("sign") => Ok(ArithmeticInstruction::Sign(a1, t)),
atom!("\\") => Ok(ArithmeticInstruction::BitwiseComplement(a1, t)),
atom!("abs") => Ok(Instruction::Abs(a1, t)),
atom!("-") => Ok(Instruction::Neg(a1, t)),
atom!("+") => Ok(Instruction::Plus(a1, t)),
atom!("cos") => Ok(Instruction::Cos(a1, t)),
atom!("sin") => Ok(Instruction::Sin(a1, t)),
atom!("tan") => Ok(Instruction::Tan(a1, t)),
atom!("log") => Ok(Instruction::Log(a1, t)),
atom!("exp") => Ok(Instruction::Exp(a1, t)),
atom!("sqrt") => Ok(Instruction::Sqrt(a1, t)),
atom!("acos") => Ok(Instruction::ACos(a1, t)),
atom!("asin") => Ok(Instruction::ASin(a1, t)),
atom!("atan") => Ok(Instruction::ATan(a1, t)),
atom!("float") => Ok(Instruction::Float(a1, t)),
atom!("truncate") => Ok(Instruction::Truncate(a1, t)),
atom!("round") => Ok(Instruction::Round(a1, t)),
atom!("ceiling") => Ok(Instruction::Ceiling(a1, t)),
atom!("floor") => Ok(Instruction::Floor(a1, t)),
atom!("sign") => Ok(Instruction::Sign(a1, t)),
atom!("\\") => Ok(Instruction::BitwiseComplement(a1, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 1)),
}
}
@@ -205,28 +227,28 @@ impl<'a> ArithmeticEvaluator<'a> {
a1: ArithmeticTerm,
a2: ArithmeticTerm,
t: usize,
) -> Result<ArithmeticInstruction, ArithmeticError> {
) -> Result<Instruction, ArithmeticError> {
match name {
atom!("+") => Ok(ArithmeticInstruction::Add(a1, a2, t)),
atom!("-") => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
atom!("/") => Ok(ArithmeticInstruction::Div(a1, a2, t)),
atom!("//") => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
atom!("max") => Ok(ArithmeticInstruction::Max(a1, a2, t)),
atom!("min") => Ok(ArithmeticInstruction::Min(a1, a2, t)),
atom!("div") => Ok(ArithmeticInstruction::IntFloorDiv(a1, a2, t)),
atom!("rdiv") => Ok(ArithmeticInstruction::RDiv(a1, a2, t)),
atom!("*") => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
atom!("**") => Ok(ArithmeticInstruction::Pow(a1, a2, t)),
atom!("^") => Ok(ArithmeticInstruction::IntPow(a1, a2, t)),
atom!(">>") => Ok(ArithmeticInstruction::Shr(a1, a2, t)),
atom!("<<") => Ok(ArithmeticInstruction::Shl(a1, a2, t)),
atom!("/\\") => Ok(ArithmeticInstruction::And(a1, a2, t)),
atom!("\\/") => Ok(ArithmeticInstruction::Or(a1, a2, t)),
atom!("xor") => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
atom!("mod") => Ok(ArithmeticInstruction::Mod(a1, a2, t)),
atom!("rem") => Ok(ArithmeticInstruction::Rem(a1, a2, t)),
atom!("gcd") => Ok(ArithmeticInstruction::Gcd(a1, a2, t)),
atom!("atan2") => Ok(ArithmeticInstruction::ATan2(a1, a2, t)),
atom!("+") => Ok(Instruction::Add(a1, a2, t)),
atom!("-") => Ok(Instruction::Sub(a1, a2, t)),
atom!("/") => Ok(Instruction::Div(a1, a2, t)),
atom!("//") => Ok(Instruction::IDiv(a1, a2, t)),
atom!("max") => Ok(Instruction::Max(a1, a2, t)),
atom!("min") => Ok(Instruction::Min(a1, a2, t)),
atom!("div") => Ok(Instruction::IntFloorDiv(a1, a2, t)),
atom!("rdiv") => Ok(Instruction::RDiv(a1, a2, t)),
atom!("*") => Ok(Instruction::Mul(a1, a2, t)),
atom!("**") => Ok(Instruction::Pow(a1, a2, t)),
atom!("^") => Ok(Instruction::IntPow(a1, a2, t)),
atom!(">>") => Ok(Instruction::Shr(a1, a2, t)),
atom!("<<") => Ok(Instruction::Shl(a1, a2, t)),
atom!("/\\") => Ok(Instruction::And(a1, a2, t)),
atom!("\\/") => Ok(Instruction::Or(a1, a2, t)),
atom!("xor") => Ok(Instruction::Xor(a1, a2, t)),
atom!("mod") => Ok(Instruction::Mod(a1, a2, t)),
atom!("rem") => Ok(Instruction::Rem(a1, a2, t)),
atom!("gcd") => Ok(Instruction::Gcd(a1, a2, t)),
atom!("atan2") => Ok(Instruction::ATan2(a1, a2, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 2)),
}
}
@@ -244,7 +266,7 @@ impl<'a> ArithmeticEvaluator<'a> {
&mut self,
name: Atom,
arity: usize,
) -> Result<ArithmeticInstruction, ArithmeticError> {
) -> Result<Instruction, ArithmeticError> {
match arity {
1 => {
let a1 = self.interm.pop().unwrap();
@@ -310,7 +332,7 @@ impl<'a> ArithmeticEvaluator<'a> {
self.interm.push(ArithmeticTerm::Reg(r));
}
ArithTermRef::Op(name, arity) => {
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
code.push(self.instr_from_clause(name, arity)?);
}
}
}

View File

@@ -1,952 +0,0 @@
use crate::atom_table::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
use crate::parser::rug::rand::RandState;
use crate::forms::Number;
use crate::temp_v;
use ref_thread_local::{ref_thread_local};
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CompareNumberQT {
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
NotEqual,
Equal,
}
impl CompareNumberQT {
fn name(self) -> Atom {
match self {
CompareNumberQT::GreaterThan => atom!(">"),
CompareNumberQT::LessThan => atom!("<"),
CompareNumberQT::GreaterThanOrEqual => atom!(">="),
CompareNumberQT::LessThanOrEqual => atom!("=<"),
CompareNumberQT::NotEqual => atom!("=\\="),
CompareNumberQT::Equal => atom!("=:="),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompareTermQT {
LessThan,
LessThanOrEqual,
GreaterThanOrEqual,
GreaterThan,
}
impl CompareTermQT {
fn name(self) -> Atom {
match self {
CompareTermQT::GreaterThan => atom!("@>"),
CompareTermQT::LessThan => atom!("@<"),
CompareTermQT::GreaterThanOrEqual => atom!("@>="),
CompareTermQT::LessThanOrEqual => atom!("@=<"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ArithmeticTerm {
Reg(RegType),
Interm(usize),
Number(Number),
}
impl ArithmeticTerm {
pub(crate) fn interm_or(&self, interm: usize) -> usize {
if let &ArithmeticTerm::Interm(interm) = self {
interm
} else {
interm
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum InlinedClauseType {
CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
IsAtom(RegType),
IsAtomic(RegType),
IsCompound(RegType),
IsInteger(RegType),
IsNumber(RegType),
IsRational(RegType),
IsFloat(RegType),
IsNonVar(RegType),
IsVar(RegType),
}
ref_thread_local! {
pub(crate) static managed RANDOM_STATE: RandState<'static> = RandState::new();
}
pub fn clause_type_form(name: Atom, arity: usize) -> Option<ClauseType> {
match (name, arity) {
(atom!(">"), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
CompareNumberQT::GreaterThan,
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
))),
(atom!("<"), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
CompareNumberQT::LessThan,
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
))),
(atom!(">="), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
CompareNumberQT::GreaterThanOrEqual,
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
))),
(atom!("=<"), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
CompareNumberQT::LessThanOrEqual,
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
))),
(atom!("=:="), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
CompareNumberQT::Equal,
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
))),
(atom!("=\\="), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
CompareNumberQT::NotEqual,
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
))),
(atom!("atom"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsAtom(temp_v!(1)))),
(atom!("atomic"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsAtomic(temp_v!(1)))),
(atom!("compound"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsCompound(temp_v!(
1
)))),
(atom!("integer"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsInteger(temp_v!(
1
)))),
(atom!("number"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsNumber(temp_v!(1)))),
(atom!("rational"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsRational(temp_v!(
1
)))),
(atom!("float"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsFloat(temp_v!(1)))),
(atom!("nonvar"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsNonVar(temp_v!(1)))),
(atom!("var"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsVar(temp_v!(1)))),
(atom!("acyclic_term"), 1) => Some(ClauseType::BuiltIn(BuiltInClauseType::AcyclicTerm)),
(atom!("arg"), 3) => Some(ClauseType::BuiltIn(BuiltInClauseType::Arg)),
(atom!("compare"), 3) => Some(ClauseType::BuiltIn(BuiltInClauseType::Compare)),
(atom!("@>"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
CompareTermQT::GreaterThan,
))),
(atom!("@<"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
CompareTermQT::LessThan,
))),
(atom!("@>="), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
CompareTermQT::GreaterThanOrEqual,
))),
(atom!("@=<"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
CompareTermQT::LessThanOrEqual,
))),
(atom!("copy_term"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CopyTerm)),
(atom!("=="), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Eq)),
(atom!("functor"), 3) => Some(ClauseType::BuiltIn(BuiltInClauseType::Functor)),
(atom!("ground"), 1) => Some(ClauseType::BuiltIn(BuiltInClauseType::Ground)),
(atom!("is"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Is(
temp_v!(1),
ar_reg!(temp_v!(2)),
))),
(atom!("keysort"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::KeySort)),
(atom!("\\=="), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::NotEq)),
(atom!("read"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Read)),
(atom!("sort"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Sort)),
_ => None,
}
}
impl InlinedClauseType {
pub(crate) fn name(&self) -> Atom {
match self {
&InlinedClauseType::CompareNumber(qt, ..) => qt.name(),
&InlinedClauseType::IsAtom(..) => atom!("atom"),
&InlinedClauseType::IsAtomic(..) => atom!("atomic"),
&InlinedClauseType::IsCompound(..) => atom!("compound"),
&InlinedClauseType::IsNumber(..) => atom!("number"),
&InlinedClauseType::IsInteger(..) => atom!("integer"),
&InlinedClauseType::IsRational(..) => atom!("rational"),
&InlinedClauseType::IsFloat(..) => atom!("float"),
&InlinedClauseType::IsNonVar(..) => atom!("nonvar"),
&InlinedClauseType::IsVar(..) => atom!("var"),
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SystemClauseType {
AtomChars,
AtomCodes,
AtomLength,
BindFromRegister,
CallContinuation,
CharCode,
CharType,
CharsToNumber,
CodesToNumber,
CopyTermWithoutAttrVars,
CheckCutPoint,
Close,
CopyToLiftedHeap,
CreatePartialString,
CurrentHostname,
CurrentInput,
CurrentOutput,
DirectoryFiles,
FileSize,
FileExists,
DirectoryExists,
DirectorySeparator,
MakeDirectory,
MakeDirectoryPath,
DeleteFile,
RenameFile,
WorkingDirectory,
DeleteDirectory,
PathCanonical,
FileTime,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution(usize),
EnqueueAttributedVar,
FetchGlobalVar,
FirstStream,
FlushOutput,
GetByte,
GetChar,
GetNChars,
GetCode,
GetSingleChar,
ResetAttrVarState,
TruncateIfNoLiftedHeapGrowthDiff,
TruncateIfNoLiftedHeapGrowth,
GetAttributedVariableList,
GetAttrVarQueueDelimiter,
GetAttrVarQueueBeyond,
GetBValue,
GetContinuationChunk,
GetNextDBRef,
GetNextOpDBRef,
IsPartialString,
Halt,
GetLiftedHeapFromOffset,
GetLiftedHeapFromOffsetDiff,
GetSCCCleaner,
HeadIsDynamic,
InstallSCCCleaner,
InstallInferenceCounter,
LiftedHeapLength,
LoadLibraryAsStream,
ModuleExists,
NextEP,
NoSuchPredicate,
NumberToChars,
NumberToCodes,
OpDeclaration,
Open,
SetStreamOptions,
NextStream,
PartialStringTail,
PeekByte,
PeekChar,
PeekCode,
PointsToContinuationResetMarker,
PutByte,
PutChar,
PutChars,
PutCode,
REPL(REPLCodePtr),
ReadQueryTerm,
ReadTerm,
RedoAttrVarBinding,
RemoveCallPolicyCheck,
RemoveInferenceCounter,
ResetContinuationMarker,
RestoreCutPolicy,
SetCutPoint(RegType),
SetInput,
SetOutput,
StoreBacktrackableGlobalVar,
StoreGlobalVar,
StreamProperty,
SetStreamPosition,
InferenceLevel,
CleanUpBlock,
EraseBall,
Fail,
GetBall,
GetCurrentBlock,
GetCutPoint,
GetStaggeredCutPoint,
GetDoubleQuotes,
InstallNewBlock,
Maybe,
CpuNow,
CurrentTime,
QuotedToken,
ReadTermFromChars,
ResetBlock,
ReturnFromVerifyAttr,
SetBall,
SetCutPointByDefault(RegType),
SetDoubleQuotes,
SetSeed,
SkipMaxList,
Sleep,
SocketClientOpen,
SocketServerOpen,
SocketServerAccept,
SocketServerClose,
TLSAcceptClient,
TLSClientConnect,
Succeed,
TermAttributedVariables,
TermVariables,
TermVariablesUnderMaxDepth,
TruncateLiftedHeapTo,
UnifyWithOccursCheck,
UnwindEnvironments,
UnwindStack,
WAMInstructions,
WriteTerm,
WriteTermToChars,
ScryerPrologVersion,
CryptoRandomByte,
CryptoDataHash,
CryptoDataHKDF,
CryptoPasswordHash,
CryptoDataEncrypt,
CryptoDataDecrypt,
CryptoCurveScalarMult,
Ed25519Sign,
Ed25519Verify,
Ed25519NewKeyPair,
Ed25519KeyPairPublicKey,
Curve25519ScalarMult,
FirstNonOctet,
LoadHTML,
LoadXML,
GetEnv,
SetEnv,
UnsetEnv,
Shell,
PID,
CharsBase64,
DevourWhitespace,
IsSTOEnabled,
SetSTOAsUnify,
SetNSTOAsUnify,
SetSTOWithErrorAsUnify,
HomeDirectory,
DebugHook,
PopCount
}
impl SystemClauseType {
pub(crate) fn name(&self) -> Atom {
match self {
&SystemClauseType::AtomChars => atom!("$atom_chars"),
&SystemClauseType::AtomCodes => atom!("$atom_codes"),
&SystemClauseType::AtomLength => atom!("$atom_length"),
&SystemClauseType::BindFromRegister => atom!("$bind_from_register"),
&SystemClauseType::CallContinuation => atom!("$call_continuation"),
&SystemClauseType::CharCode => atom!("$char_code"),
&SystemClauseType::CharType => atom!("$char_type"),
&SystemClauseType::CharsToNumber => atom!("$chars_to_number"),
&SystemClauseType::CheckCutPoint => atom!("$check_cp"),
&SystemClauseType::CodesToNumber => atom!("$codes_to_number"),
&SystemClauseType::CopyTermWithoutAttrVars => {
atom!("$copy_term_without_attr_vars")
}
&SystemClauseType::CreatePartialString => atom!("$create_partial_string"),
&SystemClauseType::CurrentInput => atom!("$current_input"),
&SystemClauseType::CurrentHostname => atom!("$current_hostname"),
&SystemClauseType::CurrentOutput => atom!("$current_output"),
&SystemClauseType::DirectoryFiles => atom!("$directory_files"),
&SystemClauseType::FileSize => atom!("$file_size"),
&SystemClauseType::FileExists => atom!("$file_exists"),
&SystemClauseType::DirectoryExists => atom!("$directory_exists"),
&SystemClauseType::DirectorySeparator => atom!("$directory_separator"),
&SystemClauseType::MakeDirectory => atom!("$make_directory"),
&SystemClauseType::MakeDirectoryPath => atom!("$make_directory_path"),
&SystemClauseType::DeleteFile => atom!("$delete_file"),
&SystemClauseType::RenameFile => atom!("$rename_file"),
&SystemClauseType::DeleteDirectory => atom!("$delete_directory"),
&SystemClauseType::WorkingDirectory => atom!("$working_directory"),
&SystemClauseType::PathCanonical => atom!("$path_canonical"),
&SystemClauseType::FileTime => atom!("$file_time"),
&SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate) => {
atom!("$add_discontiguous_predicate")
}
&SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) => atom!("$add_dynamic_predicate"),
&SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate) => {
atom!("$add_multifile_predicate")
}
&SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) => {
atom!("$add_goal_expansion_clause")
}
&SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause) => {
atom!("$add_term_expansion_clause")
}
&SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable) => atom!("$clause_to_evacuable"),
&SystemClauseType::REPL(REPLCodePtr::ScopedClauseToEvacuable) => {
atom!("$scoped_clause_to_evacuable")
}
&SystemClauseType::REPL(REPLCodePtr::ConcludeLoad) => atom!("$conclude_load"),
&SystemClauseType::REPL(REPLCodePtr::DeclareModule) => atom!("$declare_module"),
&SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary) => atom!("$load_compiled_library"),
&SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload) => {
atom!("$push_load_state_payload")
}
&SystemClauseType::REPL(REPLCodePtr::AddInSituFilenameModule) => {
atom!("$add_in_situ_filename_module")
}
&SystemClauseType::REPL(REPLCodePtr::Asserta) => atom!("$asserta"),
&SystemClauseType::REPL(REPLCodePtr::Assertz) => atom!("$assertz"),
&SystemClauseType::REPL(REPLCodePtr::Retract) => atom!("$retract_clause"),
&SystemClauseType::REPL(REPLCodePtr::UseModule) => atom!("$use_module"),
&SystemClauseType::REPL(REPLCodePtr::PushLoadContext) => atom!("$push_load_context"),
&SystemClauseType::REPL(REPLCodePtr::PopLoadContext) => atom!("$pop_load_context"),
&SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload) => atom!("$pop_load_state_payload"),
&SystemClauseType::REPL(REPLCodePtr::LoadContextSource) => atom!("$prolog_lc_source"),
&SystemClauseType::REPL(REPLCodePtr::LoadContextFile) => atom!("$prolog_lc_file"),
&SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory) => atom!("$prolog_lc_dir"),
&SystemClauseType::REPL(REPLCodePtr::LoadContextModule) => atom!("$prolog_lc_module"),
&SystemClauseType::REPL(REPLCodePtr::LoadContextStream) => atom!("$prolog_lc_stream"),
&SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty) => {
atom!("$cpp_meta_predicate_property")
}
&SystemClauseType::REPL(REPLCodePtr::BuiltInProperty) => atom!("$cpp_built_in_property"),
&SystemClauseType::REPL(REPLCodePtr::DynamicProperty) => atom!("$cpp_dynamic_property"),
&SystemClauseType::REPL(REPLCodePtr::MultifileProperty) => atom!("$cpp_multifile_property"),
&SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty) => {
atom!("$cpp_discontiguous_property")
}
&SystemClauseType::REPL(REPLCodePtr::AbolishClause) => atom!("$abolish_clause"),
&SystemClauseType::REPL(REPLCodePtr::IsConsistentWithTermQueue) => {
atom!("$is_consistent_with_term_queue")
}
&SystemClauseType::REPL(REPLCodePtr::FlushTermQueue) => atom!("$flush_term_queue"),
&SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports) => atom!("$remove_module_exports"),
&SystemClauseType::REPL(REPLCodePtr::AddNonCountedBacktracking) => {
atom!("$add_non_counted_backtracking")
}
&SystemClauseType::Close => atom!("$close"),
&SystemClauseType::CopyToLiftedHeap => atom!("$copy_to_lh"),
&SystemClauseType::DeleteAttribute => atom!("$del_attr_non_head"),
&SystemClauseType::DeleteHeadAttribute => atom!("$del_attr_head"),
&SystemClauseType::DynamicModuleResolution(_) => atom!("$module_call"),
&SystemClauseType::EnqueueAttributedVar => atom!("$enqueue_attr_var"),
&SystemClauseType::FetchGlobalVar => atom!("$fetch_global_var"),
&SystemClauseType::FirstStream => atom!("$first_stream"),
&SystemClauseType::FlushOutput => atom!("$flush_output"),
&SystemClauseType::GetByte => atom!("$get_byte"),
&SystemClauseType::GetChar => atom!("$get_char"),
&SystemClauseType::GetNChars => atom!("$get_n_chars"),
&SystemClauseType::GetCode => atom!("$get_code"),
&SystemClauseType::GetSingleChar => atom!("$get_single_char"),
&SystemClauseType::ResetAttrVarState => atom!("$reset_attr_var_state"),
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => atom!("$truncate_if_no_lh_growth"),
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => atom!("$truncate_if_no_lh_growth_diff"),
&SystemClauseType::GetAttributedVariableList => atom!("$get_attr_list"),
&SystemClauseType::GetAttrVarQueueDelimiter => atom!("$get_attr_var_queue_delim"),
&SystemClauseType::GetAttrVarQueueBeyond => atom!("$get_attr_var_queue_beyond"),
&SystemClauseType::GetContinuationChunk => atom!("$get_cont_chunk"),
&SystemClauseType::GetLiftedHeapFromOffset => atom!("$get_lh_from_offset"),
&SystemClauseType::GetLiftedHeapFromOffsetDiff => atom!("$get_lh_from_offset_diff"),
&SystemClauseType::GetBValue => atom!("$get_b_value"),
&SystemClauseType::GetNextDBRef => atom!("$get_next_db_ref"),
&SystemClauseType::GetNextOpDBRef => atom!("$get_next_op_db_ref"),
&SystemClauseType::GetDoubleQuotes => atom!("$get_double_quotes"),
&SystemClauseType::GetSCCCleaner => atom!("$get_scc_cleaner"),
&SystemClauseType::Halt => atom!("$halt"),
&SystemClauseType::HeadIsDynamic => atom!("$head_is_dynamic"),
&SystemClauseType::Open => atom!("$open"),
&SystemClauseType::OpDeclaration => atom!("$op"),
&SystemClauseType::InstallSCCCleaner => atom!("$install_scc_cleaner"),
&SystemClauseType::InstallInferenceCounter => atom!("$install_inference_counter"),
&SystemClauseType::IsPartialString => atom!("$is_partial_string"),
&SystemClauseType::PartialStringTail => atom!("$partial_string_tail"),
&SystemClauseType::PeekByte => atom!("$peek_byte"),
&SystemClauseType::PeekChar => atom!("$peek_char"),
&SystemClauseType::PeekCode => atom!("$peek_code"),
&SystemClauseType::LiftedHeapLength => atom!("$lh_length"),
&SystemClauseType::Maybe => atom!("maybe"),
&SystemClauseType::CpuNow => atom!("$cpu_now"),
&SystemClauseType::CurrentTime => atom!("$current_time"),
&SystemClauseType::ModuleExists => atom!("$module_exists"),
&SystemClauseType::NextStream => atom!("$next_stream"),
&SystemClauseType::NoSuchPredicate => atom!("$no_such_predicate"),
&SystemClauseType::NumberToChars => atom!("$number_to_chars"),
&SystemClauseType::NumberToCodes => atom!("$number_to_codes"),
&SystemClauseType::PointsToContinuationResetMarker => {
atom!("$points_to_cont_reset_marker")
}
&SystemClauseType::PutByte => {
atom!("$put_byte")
}
&SystemClauseType::PutChar => {
atom!("$put_char")
}
&SystemClauseType::PutChars => {
atom!("$put_chars")
}
&SystemClauseType::PutCode => {
atom!("$put_code")
}
&SystemClauseType::QuotedToken => {
atom!("$quoted_token")
}
&SystemClauseType::RedoAttrVarBinding => atom!("$redo_attr_var_binding"),
&SystemClauseType::RemoveCallPolicyCheck => atom!("$remove_call_policy_check"),
&SystemClauseType::RemoveInferenceCounter => atom!("$remove_inference_counter"),
&SystemClauseType::RestoreCutPolicy => atom!("$restore_cut_policy"),
&SystemClauseType::SetCutPoint(_) => atom!("$set_cp"),
&SystemClauseType::SetInput => atom!("$set_input"),
&SystemClauseType::SetOutput => atom!("$set_output"),
&SystemClauseType::SetSeed => atom!("$set_seed"),
&SystemClauseType::StreamProperty => atom!("$stream_property"),
&SystemClauseType::SetStreamPosition => atom!("$set_stream_position"),
&SystemClauseType::SetStreamOptions => atom!("$set_stream_options"),
&SystemClauseType::StoreBacktrackableGlobalVar => {
atom!("$store_back_trackable_global_var")
}
&SystemClauseType::StoreGlobalVar => atom!("$store_global_var"),
&SystemClauseType::InferenceLevel => atom!("$inference_level"),
&SystemClauseType::CleanUpBlock => atom!("$clean_up_block"),
&SystemClauseType::EraseBall => atom!("$erase_ball"),
&SystemClauseType::Fail => atom!("$fail"),
&SystemClauseType::GetBall => atom!("$get_ball"),
&SystemClauseType::GetCutPoint => atom!("$get_cp"),
&SystemClauseType::GetStaggeredCutPoint => atom!("$get_staggered_cp"),
&SystemClauseType::GetCurrentBlock => atom!("$get_current_block"),
&SystemClauseType::InstallNewBlock => atom!("$install_new_block"),
&SystemClauseType::NextEP => atom!("$nextEP"),
&SystemClauseType::ReadQueryTerm => atom!("$read_query_term"),
&SystemClauseType::ReadTerm => atom!("$read_term"),
&SystemClauseType::ReadTermFromChars => atom!("$read_term_from_chars"),
&SystemClauseType::ResetBlock => atom!("$reset_block"),
&SystemClauseType::ResetContinuationMarker => atom!("$reset_cont_marker"),
&SystemClauseType::ReturnFromVerifyAttr => atom!("$return_from_verify_attr"),
&SystemClauseType::SetBall => atom!("$set_ball"),
&SystemClauseType::SetCutPointByDefault(_) => atom!("$set_cp_by_default"),
&SystemClauseType::SetDoubleQuotes => atom!("$set_double_quotes"),
&SystemClauseType::SkipMaxList => atom!("$skip_max_list"),
&SystemClauseType::Sleep => atom!("$sleep"),
&SystemClauseType::SocketClientOpen => atom!("$socket_client_open"),
&SystemClauseType::SocketServerOpen => atom!("$socket_server_open"),
&SystemClauseType::SocketServerAccept => atom!("$socket_server_accept"),
&SystemClauseType::SocketServerClose => atom!("$socket_server_close"),
&SystemClauseType::TLSAcceptClient => atom!("$tls_accept_client"),
&SystemClauseType::TLSClientConnect => atom!("$tls_client_connect"),
&SystemClauseType::Succeed => atom!("$succeed"),
&SystemClauseType::TermAttributedVariables => {
atom!("$term_attributed_variables")
}
&SystemClauseType::TermVariables => atom!("$term_variables"),
&SystemClauseType::TermVariablesUnderMaxDepth => atom!("$term_variables_under_max_depth"),
&SystemClauseType::TruncateLiftedHeapTo => atom!("$truncate_lh_to"),
&SystemClauseType::UnifyWithOccursCheck => atom!("$unify_with_occurs_check"),
&SystemClauseType::UnwindEnvironments => atom!("$unwind_environments"),
&SystemClauseType::UnwindStack => atom!("$unwind_stack"),
&SystemClauseType::WAMInstructions => atom!("$wam_instructions"),
&SystemClauseType::WriteTerm => atom!("$write_term"),
&SystemClauseType::WriteTermToChars => atom!("$write_term_to_chars"),
&SystemClauseType::ScryerPrologVersion => atom!("$scryer_prolog_version"),
&SystemClauseType::CryptoRandomByte => atom!("$crypto_random_byte"),
&SystemClauseType::CryptoDataHash => atom!("$crypto_data_hash"),
&SystemClauseType::CryptoDataHKDF => atom!("$crypto_data_hkdf"),
&SystemClauseType::CryptoPasswordHash => atom!("$crypto_password_hash"),
&SystemClauseType::CryptoDataEncrypt => atom!("$crypto_data_encrypt"),
&SystemClauseType::CryptoDataDecrypt => atom!("$crypto_data_decrypt"),
&SystemClauseType::CryptoCurveScalarMult => atom!("$crypto_curve_scalar_mult"),
&SystemClauseType::Ed25519Sign => atom!("$ed25519_sign"),
&SystemClauseType::Ed25519Verify => atom!("$ed25519_verify"),
&SystemClauseType::Ed25519NewKeyPair => atom!("$ed25519_new_keypair"),
&SystemClauseType::Ed25519KeyPairPublicKey => {
atom!("$ed25519_keypair_public_key")
}
&SystemClauseType::Curve25519ScalarMult => atom!("$curve25519_scalar_mult"),
&SystemClauseType::FirstNonOctet => atom!("$first_non_octet"),
&SystemClauseType::LoadHTML => atom!("$load_html"),
&SystemClauseType::LoadXML => atom!("$load_xml"),
&SystemClauseType::GetEnv => atom!("$getenv"),
&SystemClauseType::SetEnv => atom!("$setenv"),
&SystemClauseType::UnsetEnv => atom!("$unsetenv"),
&SystemClauseType::Shell => atom!("$shell"),
&SystemClauseType::PID => atom!("$pid"),
&SystemClauseType::CharsBase64 => atom!("$chars_base64"),
&SystemClauseType::LoadLibraryAsStream => atom!("$load_library_as_stream"),
&SystemClauseType::DevourWhitespace => atom!("$devour_whitespace"),
&SystemClauseType::IsSTOEnabled => atom!("$is_sto_enabled"),
&SystemClauseType::SetSTOAsUnify => atom!("$set_sto_as_unify"),
&SystemClauseType::SetNSTOAsUnify => atom!("$set_nsto_as_unify"),
&SystemClauseType::HomeDirectory => atom!("$home_directory"),
&SystemClauseType::SetSTOWithErrorAsUnify => {
atom!("$set_sto_with_error_as_unify")
}
&SystemClauseType::DebugHook => atom!("$debug_hook"),
&SystemClauseType::PopCount => atom!("$popcount"),
}
}
pub(crate) fn from(name: Atom, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
(atom!("$abolish_clause"), 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)),
(atom!("$add_dynamic_predicate"), 4) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate))
}
(atom!("$add_multifile_predicate"), 4) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate))
}
(atom!("$add_discontiguous_predicate"), 4) => Some(SystemClauseType::REPL(
REPLCodePtr::AddDiscontiguousPredicate,
)),
(atom!("$add_goal_expansion_clause"), 3) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause))
}
(atom!("$add_term_expansion_clause"), 2) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause))
}
(atom!("$atom_chars"), 2) => Some(SystemClauseType::AtomChars),
(atom!("$atom_codes"), 2) => Some(SystemClauseType::AtomCodes),
(atom!("$atom_length"), 2) => Some(SystemClauseType::AtomLength),
(atom!("$bind_from_register"), 2) => Some(SystemClauseType::BindFromRegister),
(atom!("$call_continuation"), 1) => Some(SystemClauseType::CallContinuation),
(atom!("$char_code"), 2) => Some(SystemClauseType::CharCode),
(atom!("$char_type"), 2) => Some(SystemClauseType::CharType),
(atom!("$chars_to_number"), 2) => Some(SystemClauseType::CharsToNumber),
(atom!("$codes_to_number"), 2) => Some(SystemClauseType::CodesToNumber),
(atom!("$copy_term_without_attr_vars"), 2) => Some(SystemClauseType::CopyTermWithoutAttrVars),
(atom!("$create_partial_string"), 3) => Some(SystemClauseType::CreatePartialString),
(atom!("$check_cp"), 1) => Some(SystemClauseType::CheckCutPoint),
(atom!("$copy_to_lh"), 2) => Some(SystemClauseType::CopyToLiftedHeap),
(atom!("$close"), 2) => Some(SystemClauseType::Close),
(atom!("$current_hostname"), 1) => Some(SystemClauseType::CurrentHostname),
(atom!("$current_input"), 1) => Some(SystemClauseType::CurrentInput),
(atom!("$current_output"), 1) => Some(SystemClauseType::CurrentOutput),
(atom!("$first_stream"), 1) => Some(SystemClauseType::FirstStream),
(atom!("$next_stream"), 2) => Some(SystemClauseType::NextStream),
(atom!("$flush_output"), 1) => Some(SystemClauseType::FlushOutput),
(atom!("$del_attr_non_head"), 1) => Some(SystemClauseType::DeleteAttribute),
(atom!("$del_attr_head"), 1) => Some(SystemClauseType::DeleteHeadAttribute),
(atom!("$get_next_db_ref"), 4) => Some(SystemClauseType::GetNextDBRef),
(atom!("$get_next_op_db_ref"), 7) => Some(SystemClauseType::GetNextOpDBRef),
(atom!("$module_call"), _) => Some(SystemClauseType::DynamicModuleResolution(arity - 2)),
(atom!("$enqueue_attr_var"), 1) => Some(SystemClauseType::EnqueueAttributedVar),
(atom!("$partial_string_tail"), 2) => Some(SystemClauseType::PartialStringTail),
(atom!("$peek_byte"), 2) => Some(SystemClauseType::PeekByte),
(atom!("$peek_char"), 2) => Some(SystemClauseType::PeekChar),
(atom!("$peek_code"), 2) => Some(SystemClauseType::PeekCode),
(atom!("$is_partial_string"), 1) => Some(SystemClauseType::IsPartialString),
(atom!("$fetch_global_var"), 2) => Some(SystemClauseType::FetchGlobalVar),
(atom!("$get_byte"), 2) => Some(SystemClauseType::GetByte),
(atom!("$get_char"), 2) => Some(SystemClauseType::GetChar),
(atom!("$get_n_chars"), 3) => Some(SystemClauseType::GetNChars),
(atom!("$get_code"), 2) => Some(SystemClauseType::GetCode),
(atom!("$get_single_char"), 1) => Some(SystemClauseType::GetSingleChar),
(atom!("$points_to_cont_reset_marker"), 1) => {
Some(SystemClauseType::PointsToContinuationResetMarker)
}
(atom!("$put_byte"), 2) => Some(SystemClauseType::PutByte),
(atom!("$put_char"), 2) => Some(SystemClauseType::PutChar),
(atom!("$put_chars"), 2) => Some(SystemClauseType::PutChars),
(atom!("$put_code"), 2) => Some(SystemClauseType::PutCode),
(atom!("$reset_attr_var_state"), 0) => Some(SystemClauseType::ResetAttrVarState),
(atom!("$truncate_if_no_lh_growth"), 1) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
}
(atom!("$truncate_if_no_lh_growth_diff"), 2) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff)
}
(atom!("$get_attr_list"), 2) => Some(SystemClauseType::GetAttributedVariableList),
(atom!("$get_b_value"), 1) => Some(SystemClauseType::GetBValue),
(atom!("$get_lh_from_offset"), 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
(atom!("$get_lh_from_offset_diff"), 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
(atom!("$get_double_quotes"), 1) => Some(SystemClauseType::GetDoubleQuotes),
(atom!("$get_scc_cleaner"), 1) => Some(SystemClauseType::GetSCCCleaner),
(atom!("$halt"), 1) => Some(SystemClauseType::Halt),
(atom!("$head_is_dynamic"), 2) => Some(SystemClauseType::HeadIsDynamic),
(atom!("$install_scc_cleaner"), 2) => Some(SystemClauseType::InstallSCCCleaner),
(atom!("$install_inference_counter"), 3) => Some(SystemClauseType::InstallInferenceCounter),
(atom!("$lh_length"), 1) => Some(SystemClauseType::LiftedHeapLength),
(atom!("$maybe"), 0) => Some(SystemClauseType::Maybe),
(atom!("$cpu_now"), 1) => Some(SystemClauseType::CpuNow),
(atom!("$current_time"), 1) => Some(SystemClauseType::CurrentTime),
(atom!("$module_exists"), 1) => Some(SystemClauseType::ModuleExists),
(atom!("$no_such_predicate"), 2) => Some(SystemClauseType::NoSuchPredicate),
(atom!("$number_to_chars"), 2) => Some(SystemClauseType::NumberToChars),
(atom!("$number_to_codes"), 2) => Some(SystemClauseType::NumberToCodes),
(atom!("$op"), 3) => Some(SystemClauseType::OpDeclaration),
(atom!("$open"), 7) => Some(SystemClauseType::Open),
(atom!("$set_stream_options"), 5) => Some(SystemClauseType::SetStreamOptions),
(atom!("$redo_attr_var_binding"), 2) => Some(SystemClauseType::RedoAttrVarBinding),
(atom!("$remove_call_policy_check"), 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
(atom!("$remove_inference_counter"), 2) => Some(SystemClauseType::RemoveInferenceCounter),
(atom!("$restore_cut_policy"), 0) => Some(SystemClauseType::RestoreCutPolicy),
(atom!("$set_cp"), 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))),
(atom!("$set_input"), 1) => Some(SystemClauseType::SetInput),
(atom!("$set_output"), 1) => Some(SystemClauseType::SetOutput),
(atom!("$stream_property"), 3) => Some(SystemClauseType::StreamProperty),
(atom!("$set_stream_position"), 2) => Some(SystemClauseType::SetStreamPosition),
(atom!("$inference_level"), 2) => Some(SystemClauseType::InferenceLevel),
(atom!("$clean_up_block"), 1) => Some(SystemClauseType::CleanUpBlock),
(atom!("$erase_ball"), 0) => Some(SystemClauseType::EraseBall),
(atom!("$fail"), 0) => Some(SystemClauseType::Fail),
(atom!("$get_attr_var_queue_beyond"), 2) => Some(SystemClauseType::GetAttrVarQueueBeyond),
(atom!("$get_attr_var_queue_delim"), 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter),
(atom!("$get_ball"), 1) => Some(SystemClauseType::GetBall),
(atom!("$get_cont_chunk"), 3) => Some(SystemClauseType::GetContinuationChunk),
(atom!("$get_current_block"), 1) => Some(SystemClauseType::GetCurrentBlock),
(atom!("$get_cp"), 1) => Some(SystemClauseType::GetCutPoint),
(atom!("$get_staggered_cp"), 1) => Some(SystemClauseType::GetStaggeredCutPoint),
(atom!("$install_new_block"), 1) => Some(SystemClauseType::InstallNewBlock),
(atom!("$quoted_token"), 1) => Some(SystemClauseType::QuotedToken),
(atom!("$nextEP"), 3) => Some(SystemClauseType::NextEP),
(atom!("$read_query_term"), 5) => Some(SystemClauseType::ReadQueryTerm),
(atom!("$read_term"), 5) => Some(SystemClauseType::ReadTerm),
(atom!("$read_term_from_chars"), 2) => Some(SystemClauseType::ReadTermFromChars),
(atom!("$reset_block"), 1) => Some(SystemClauseType::ResetBlock),
(atom!("$reset_cont_marker"), 0) => Some(SystemClauseType::ResetContinuationMarker),
(atom!("$return_from_verify_attr"), 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
(atom!("$set_ball"), 1) => Some(SystemClauseType::SetBall),
(atom!("$set_cp_by_default"), 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
(atom!("$set_double_quotes"), 1) => Some(SystemClauseType::SetDoubleQuotes),
(atom!("$set_seed"), 1) => Some(SystemClauseType::SetSeed),
(atom!("$skip_max_list"), 4) => Some(SystemClauseType::SkipMaxList),
(atom!("$sleep"), 1) => Some(SystemClauseType::Sleep),
(atom!("$tls_accept_client"), 4) => Some(SystemClauseType::TLSAcceptClient),
(atom!("$tls_client_connect"), 3) => Some(SystemClauseType::TLSClientConnect),
(atom!("$socket_client_open"), 8) => Some(SystemClauseType::SocketClientOpen),
(atom!("$socket_server_open"), 3) => Some(SystemClauseType::SocketServerOpen),
(atom!("$socket_server_accept"), 7) => Some(SystemClauseType::SocketServerAccept),
(atom!("$socket_server_close"), 1) => Some(SystemClauseType::SocketServerClose),
(atom!("$store_global_var"), 2) => Some(SystemClauseType::StoreGlobalVar),
(atom!("$store_backtrackable_global_var"), 2) => {
Some(SystemClauseType::StoreBacktrackableGlobalVar)
}
(atom!("$term_attributed_variables"), 2) => Some(SystemClauseType::TermAttributedVariables),
(atom!("$term_variables"), 2) => Some(SystemClauseType::TermVariables),
(atom!("$term_variables_under_max_depth"), 3) => Some(SystemClauseType::TermVariablesUnderMaxDepth),
(atom!("$truncate_lh_to"), 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
(atom!("$unwind_environments"), 0) => Some(SystemClauseType::UnwindEnvironments),
(atom!("$unwind_stack"), 0) => Some(SystemClauseType::UnwindStack),
(atom!("$unify_with_occurs_check"), 2) => Some(SystemClauseType::UnifyWithOccursCheck),
(atom!("$directory_files"), 2) => Some(SystemClauseType::DirectoryFiles),
(atom!("$file_size"), 2) => Some(SystemClauseType::FileSize),
(atom!("$file_exists"), 1) => Some(SystemClauseType::FileExists),
(atom!("$directory_exists"), 1) => Some(SystemClauseType::DirectoryExists),
(atom!("$directory_separator"), 1) => Some(SystemClauseType::DirectorySeparator),
(atom!("$make_directory"), 1) => Some(SystemClauseType::MakeDirectory),
(atom!("$make_directory_path"), 1) => Some(SystemClauseType::MakeDirectoryPath),
(atom!("$delete_file"), 1) => Some(SystemClauseType::DeleteFile),
(atom!("$rename_file"), 2) => Some(SystemClauseType::RenameFile),
(atom!("$delete_directory"), 1) => Some(SystemClauseType::DeleteDirectory),
(atom!("$working_directory"), 2) => Some(SystemClauseType::WorkingDirectory),
(atom!("$path_canonical"), 2) => Some(SystemClauseType::PathCanonical),
(atom!("$file_time"), 3) => Some(SystemClauseType::FileTime),
(atom!("$clause_to_evacuable"), 2) => {
Some(SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable))
}
(atom!("$scoped_clause_to_evacuable"), 3) => {
Some(SystemClauseType::REPL(REPLCodePtr::ScopedClauseToEvacuable))
}
(atom!("$conclude_load"), 1) => Some(SystemClauseType::REPL(REPLCodePtr::ConcludeLoad)),
(atom!("$use_module"), 3) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
(atom!("$declare_module"), 3) => Some(SystemClauseType::REPL(REPLCodePtr::DeclareModule)),
(atom!("$load_compiled_library"), 3) => {
Some(SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary))
}
(atom!("$push_load_state_payload"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload))
}
(atom!("$add_in_situ_filename_module"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::AddInSituFilenameModule))
}
(atom!("$asserta"), 5) => Some(SystemClauseType::REPL(REPLCodePtr::Asserta)),
(atom!("$assertz"), 5) => Some(SystemClauseType::REPL(REPLCodePtr::Assertz)),
(atom!("$retract_clause"), 4) => Some(SystemClauseType::REPL(REPLCodePtr::Retract)),
(atom!("$is_consistent_with_term_queue"), 4) => Some(SystemClauseType::REPL(
REPLCodePtr::IsConsistentWithTermQueue,
)),
(atom!("$flush_term_queue"), 1) => Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)),
(atom!("$remove_module_exports"), 2) => {
Some(SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports))
}
(atom!("$add_non_counted_backtracking"), 3) => Some(SystemClauseType::REPL(
REPLCodePtr::AddNonCountedBacktracking,
)),
(atom!("$wam_instructions"), 4) => Some(SystemClauseType::WAMInstructions),
(atom!("$write_term"), 7) => Some(SystemClauseType::WriteTerm),
(atom!("$write_term_to_chars"), 7) => Some(SystemClauseType::WriteTermToChars),
(atom!("$scryer_prolog_version"), 1) => Some(SystemClauseType::ScryerPrologVersion),
(atom!("$crypto_random_byte"), 1) => Some(SystemClauseType::CryptoRandomByte),
(atom!("$crypto_data_hash"), 4) => Some(SystemClauseType::CryptoDataHash),
(atom!("$crypto_data_hkdf"), 7) => Some(SystemClauseType::CryptoDataHKDF),
(atom!("$crypto_password_hash"), 4) => Some(SystemClauseType::CryptoPasswordHash),
(atom!("$crypto_data_encrypt"), 7) => Some(SystemClauseType::CryptoDataEncrypt),
(atom!("$crypto_data_decrypt"), 6) => Some(SystemClauseType::CryptoDataDecrypt),
(atom!("$crypto_curve_scalar_mult"), 5) => Some(SystemClauseType::CryptoCurveScalarMult),
(atom!("$ed25519_sign"), 4) => Some(SystemClauseType::Ed25519Sign),
(atom!("$ed25519_verify"), 4) => Some(SystemClauseType::Ed25519Verify),
(atom!("$ed25519_new_keypair"), 1) => Some(SystemClauseType::Ed25519NewKeyPair),
(atom!("$ed25519_keypair_public_key"), 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
(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_xml"), 3) => Some(SystemClauseType::LoadXML),
(atom!("$getenv"), 2) => Some(SystemClauseType::GetEnv),
(atom!("$setenv"), 2) => Some(SystemClauseType::SetEnv),
(atom!("$unsetenv"), 1) => Some(SystemClauseType::UnsetEnv),
(atom!("$shell"), 2) => Some(SystemClauseType::Shell),
(atom!("$pid"), 1) => Some(SystemClauseType::PID),
(atom!("$chars_base64"), 4) => Some(SystemClauseType::CharsBase64),
(atom!("$load_library_as_stream"), 3) => Some(SystemClauseType::LoadLibraryAsStream),
(atom!("$push_load_context"), 2) => Some(SystemClauseType::REPL(REPLCodePtr::PushLoadContext)),
(atom!("$pop_load_state_payload"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload))
}
(atom!("$pop_load_context"), 0) => Some(SystemClauseType::REPL(REPLCodePtr::PopLoadContext)),
(atom!("$prolog_lc_source"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::LoadContextSource))
}
(atom!("$prolog_lc_file"), 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextFile)),
(atom!("$prolog_lc_dir"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory))
}
(atom!("$prolog_lc_module"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::LoadContextModule))
}
(atom!("$prolog_lc_stream"), 1) => {
Some(SystemClauseType::REPL(REPLCodePtr::LoadContextStream))
}
(atom!("$cpp_meta_predicate_property"), 4) => {
Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty))
}
(atom!("$cpp_built_in_property"), 2) => {
Some(SystemClauseType::REPL(REPLCodePtr::BuiltInProperty))
}
(atom!("$cpp_dynamic_property"), 3) => {
Some(SystemClauseType::REPL(REPLCodePtr::DynamicProperty))
}
(atom!("$cpp_multifile_property"), 3) => {
Some(SystemClauseType::REPL(REPLCodePtr::MultifileProperty))
}
(atom!("$cpp_discontiguous_property"), 3) => {
Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty))
}
(atom!("$devour_whitespace"), 1) => Some(SystemClauseType::DevourWhitespace),
(atom!("$is_sto_enabled"), 1) => Some(SystemClauseType::IsSTOEnabled),
(atom!("$set_sto_as_unify"), 0) => Some(SystemClauseType::SetSTOAsUnify),
(atom!("$set_nsto_as_unify"), 0) => Some(SystemClauseType::SetNSTOAsUnify),
(atom!("$set_sto_with_error_as_unify"), 0) => Some(SystemClauseType::SetSTOWithErrorAsUnify),
(atom!("$home_directory"), 1) => Some(SystemClauseType::HomeDirectory),
(atom!("$debug_hook"), 0) => Some(SystemClauseType::DebugHook),
(atom!("$popcount"), 2) => Some(SystemClauseType::PopCount),
_ => None,
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BuiltInClauseType {
AcyclicTerm,
Arg,
Compare,
CompareTerm(CompareTermQT),
CopyTerm,
Eq,
Functor,
Ground,
Is(RegType, ArithmeticTerm),
KeySort,
NotEq,
Read,
Sort,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClauseType {
BuiltIn(BuiltInClauseType),
CallN,
Inlined(InlinedClauseType),
Named(Atom, usize, CodeIndex), // name, arity, index.
System(SystemClauseType),
}
impl BuiltInClauseType {
pub(crate) fn name(&self) -> Atom {
match self {
&BuiltInClauseType::AcyclicTerm => atom!("acyclic_term"),
&BuiltInClauseType::Arg => atom!("arg"),
&BuiltInClauseType::Compare => atom!("compare"),
&BuiltInClauseType::CompareTerm(qt) => qt.name(),
&BuiltInClauseType::CopyTerm => atom!("copy_term"),
&BuiltInClauseType::Eq => atom!("=="),
&BuiltInClauseType::Functor => atom!("functor"),
&BuiltInClauseType::Ground => atom!("ground"),
&BuiltInClauseType::Is(..) => atom!("is"),
&BuiltInClauseType::KeySort => atom!("keysort"),
&BuiltInClauseType::NotEq => atom!("\\=="),
&BuiltInClauseType::Read => atom!("read"),
&BuiltInClauseType::Sort => atom!("sort"),
}
}
pub(crate) fn arity(&self) -> usize {
match self {
&BuiltInClauseType::AcyclicTerm => 1,
&BuiltInClauseType::Arg => 3,
&BuiltInClauseType::Compare => 2,
&BuiltInClauseType::CompareTerm(_) => 2,
&BuiltInClauseType::CopyTerm => 2,
&BuiltInClauseType::Eq => 2,
&BuiltInClauseType::Functor => 3,
&BuiltInClauseType::Ground => 1,
&BuiltInClauseType::Is(..) => 2,
&BuiltInClauseType::KeySort => 2,
&BuiltInClauseType::NotEq => 2,
&BuiltInClauseType::Read => 1,
&BuiltInClauseType::Sort => 2,
}
}
}
impl ClauseType {
pub(crate) fn name(&self) -> Atom {
match self {
&ClauseType::BuiltIn(ref built_in) => built_in.name(),
&ClauseType::CallN => atom!("$call"),
&ClauseType::Inlined(ref inlined) => inlined.name(),
&ClauseType::Named(name, ..) => name,
&ClauseType::System(ref system) => system.name(),
}
}
pub(crate) fn from(name: Atom, arity: usize) -> Self {
clause_type_form(name, arity).unwrap_or_else(|| {
SystemClauseType::from(name, arity)
.map(ClauseType::System)
.unwrap_or_else(|| {
if name == atom!("$call") {
ClauseType::CallN
} else {
ClauseType::Named(name, arity, CodeIndex::default())
}
})
})
}
}
impl From<InlinedClauseType> for ClauseType {
fn from(inlined_ct: InlinedClauseType) -> Self {
ClauseType::Inlined(inlined_ct)
}
}

View File

@@ -4,7 +4,6 @@ use crate::{perm_v, temp_v};
use crate::allocator::*;
use crate::arithmetic::*;
use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::indexing::*;
@@ -13,6 +12,7 @@ use crate::iterators::*;
use crate::targets::*;
use crate::types::*;
use crate::instr;
use crate::machine::machine_errors::*;
use indexmap::{IndexMap, IndexSet};
@@ -57,7 +57,9 @@ impl<'a> ConjunctInfo<'a> {
let mut code_index = 0;
for phase in 0.. {
while let Line::Query(ref query_instr) = &code[code_index] {
while code[code_index].is_query_instr() {
let query_instr = &mut code[code_index];
if !unsafe_var_marker.mark_safe_vars(query_instr) {
unsafe_var_marker.mark_phase(query_instr, phase);
}
@@ -75,7 +77,8 @@ impl<'a> ConjunctInfo<'a> {
code_index = 0;
for phase in 0.. {
while let Line::Query(ref mut query_instr) = &mut code[code_index] {
while code[code_index].is_query_instr() {
let query_instr = &mut code[code_index];
unsafe_var_marker.mark_unsafe_vars(query_instr, phase);
code_index += 1;
}
@@ -103,9 +106,9 @@ impl CodeGenSettings {
}
#[inline]
pub(crate) fn internal_try_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn internal_try_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_time) = self.global_clock_tick {
ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
global_clock_time,
Death::Infinity,
if offset == 0 {
@@ -115,13 +118,13 @@ impl CodeGenSettings {
},
)
} else {
ChoiceInstruction::TryMeElse(offset)
Instruction::TryMeElse(offset)
}
}
pub(crate) fn try_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn try_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicElse(
Instruction::DynamicElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
@@ -131,13 +134,13 @@ impl CodeGenSettings {
},
)
} else {
ChoiceInstruction::TryMeElse(offset)
Instruction::TryMeElse(offset)
}
}
pub(crate) fn internal_retry_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn internal_retry_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
@@ -147,13 +150,13 @@ impl CodeGenSettings {
},
)
} else {
ChoiceInstruction::RetryMeElse(offset)
Instruction::RetryMeElse(offset)
}
}
pub(crate) fn retry_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn retry_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicElse(
Instruction::DynamicElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
@@ -163,33 +166,33 @@ impl CodeGenSettings {
},
)
} else if self.non_counted_bt {
ChoiceInstruction::DefaultRetryMeElse(offset)
Instruction::DefaultRetryMeElse(offset)
} else {
ChoiceInstruction::RetryMeElse(offset)
Instruction::RetryMeElse(offset)
}
}
pub(crate) fn internal_trust_me(&self) -> ChoiceInstruction {
pub(crate) fn internal_trust_me(&self) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
global_clock_tick,
Death::Infinity,
NextOrFail::Fail(0),
)
} else if self.non_counted_bt {
ChoiceInstruction::DefaultTrustMe(0)
Instruction::DefaultTrustMe(0)
} else {
ChoiceInstruction::TrustMe(0)
Instruction::TrustMe(0)
}
}
pub(crate) fn trust_me(&self) -> ChoiceInstruction {
pub(crate) fn trust_me(&self) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicElse(global_clock_tick, Death::Infinity, NextOrFail::Fail(0))
Instruction::DynamicElse(global_clock_tick, Death::Infinity, NextOrFail::Fail(0))
} else if self.non_counted_bt {
ChoiceInstruction::DefaultTrustMe(0)
Instruction::DefaultTrustMe(0)
} else {
ChoiceInstruction::TrustMe(0)
Instruction::TrustMe(0)
}
}
}
@@ -238,12 +241,11 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
vr: &'a Cell<VarReg>,
code: &mut Code,
) -> RegType {
let mut target = Vec::new();
self.marker
.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
let mut target = Code::new();
self.marker.mark_var::<QueryInstruction>(name, Level::Shallow, vr, term_loc, &mut target);
if !target.is_empty() {
code.extend(target.into_iter().map(Line::Query));
code.extend(target.into_iter());
}
vr.get().norm()
@@ -271,7 +273,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
}
fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>)
fn add_or_increment_void_instr<Target>(target: &mut Code)
where
Target: crate::targets::CompilationTarget<'a>,
{
@@ -291,13 +293,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
var: &'a Rc<String>,
term_loc: GenContext,
is_exposed: bool,
target: &mut Vec<Target>,
target: &mut Code,
) {
if is_exposed || self.get_var_count(var.as_ref()) > 1 {
self.marker
.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
self.marker.mark_var::<Target>(var.clone(), Level::Deep, cell, term_loc, target);
} else {
Self::add_or_increment_void_instr(target);
Self::add_or_increment_void_instr::<Target>(target);
}
}
@@ -306,27 +307,26 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
subterm: &'a Term,
term_loc: GenContext,
is_exposed: bool,
target: &mut Vec<Target>,
target: &mut Code,
) {
match subterm {
&Term::AnonVar if is_exposed => {
self.marker.mark_anon_var(Level::Deep, term_loc, target);
self.marker.mark_anon_var::<Target>(Level::Deep, term_loc, target);
}
&Term::AnonVar => {
Self::add_or_increment_void_instr(target);
Self::add_or_increment_void_instr::<Target>(target);
}
&Term::Cons(ref cell, ..)
| &Term::Clause(ref cell, ..)
| Term::PartialString(ref cell, ..) => {
self.marker
.mark_non_var(Level::Deep, term_loc, cell, target);
self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
target.push(Target::clause_arg_to_instr(cell.get()));
}
&Term::Literal(_, ref constant) => {
target.push(Target::constant_subterm(constant.clone()));
}
&Term::Var(ref cell, ref var) => {
self.deep_var_instr(cell, var, term_loc, is_exposed, target);
self.deep_var_instr::<Target>(cell, var, term_loc, is_exposed, target);
}
};
}
@@ -336,12 +336,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
iter: Iter,
term_loc: GenContext,
is_exposed: bool,
) -> Vec<Target>
) -> Code
where
Target: crate::targets::CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>,
{
let mut target = Vec::new();
let mut target: Code = Vec::new();
for term in iter {
match term {
@@ -349,38 +349,38 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
if let GenContext::Head = term_loc {
self.marker.advance_arg();
} else {
self.marker.mark_anon_var(lvl, term_loc, &mut target);
self.marker.mark_anon_var::<Target>(lvl, term_loc, &mut target);
}
}
TermRef::Clause(lvl, cell, ct, terms) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(ct, terms.len(), cell.get()));
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(ct.name(), terms.len(), cell.get()));
for subterm in terms {
self.subterm_to_instr(subterm, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(subterm, term_loc, is_exposed, &mut target);
}
}
TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get()));
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
}
TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_pstr(lvl, *string, cell.get(), false));
}
TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_constant(lvl, *constant, cell.get()));
}
TermRef::PartialString(lvl, cell, string, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
if let Some(tail) = tail {
target.push(Target::to_pstr(lvl, string, cell.get(), true));
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
} else {
target.push(Target::to_pstr(lvl, string, cell.get(), false));
}
@@ -388,7 +388,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
if self.marker.is_unbound(var.clone()) {
if term_loc != GenContext::Head {
self.marker.mark_reserved_var(
self.marker.mark_reserved_var::<Target>(
var.clone(),
lvl,
cell,
@@ -401,12 +401,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
}
self.marker
.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
}
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
self.marker
.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
}
_ => {}
};
@@ -451,13 +449,13 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
match qt {
&QueryTerm::Jump(ref vars) => {
self.jmp_by_locs.push(code.len());
code.push(jmp_call!(vars.len(), 0, pvs));
code.push(instr!("jmp_by_call", vars.len(), 0, pvs));
}
&QueryTerm::Clause(_, ref ct, ref terms, true) => {
code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs));
&QueryTerm::Clause(_, ref ct, _, true) => {
code.push(call_clause_by_default!(ct.clone(), pvs));
}
&QueryTerm::Clause(_, ref ct, ref terms, false) => {
code.push(call_clause!(ct.clone(), terms.len(), pvs));
&QueryTerm::Clause(_, ref ct, _, false) => {
code.push(call_clause!(ct.clone(), pvs));
}
_ => {}
}
@@ -465,25 +463,29 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
fn lco(code: &mut Code) -> usize {
let mut dealloc_index = code.len() - 1;
let last_instr = code.pop();
match code.last_mut() {
Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
&mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
*last_call = true;
match last_instr {
Some(instr @ Instruction::Proceed) => {
code.push(instr);
}
&mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => {
*last_call = true;
}
&mut ControlInstruction::Proceed => {}
_ => {
Some(instr @ Instruction::Cut(_)) => {
dealloc_index += 1;
code.push(instr);
}
},
Some(&mut Line::Cut(CutInstruction::Cut(_))) => {
Some(mut instr) if instr.is_ctrl_instr() => {
code.push(if instr.perm_vars_mut().is_some() {
instr.to_execute()
} else {
dealloc_index += 1;
instr
});
}
Some(instr) => {
code.push(instr);
}
None => {}
}
_ => {}
};
dealloc_index
}
@@ -496,7 +498,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
code: &mut Code,
) -> Result<(), CompilationError> {
match ct {
&InlinedClauseType::CompareNumber(cmp, ..) => {
&InlinedClauseType::CompareNumber(mut cmp) => {
self.marker.reset_arg(2);
let (mut lcode, at_1) = self.call_arith_eval(&terms[0], 1)?;
@@ -523,71 +525,71 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
&Term::Literal(_, Literal::Char(_))
| &Term::Literal(_, Literal::Atom(atom!("[]")))
| &Term::Literal(_, Literal::Atom(..)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_atom!(r));
code.push(instr!("atom", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsAtomic(..) => match &terms[0] {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::Literal(_, Literal::String(_)) => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::Literal(..) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_atomic!(r));
code.push(instr!("atomic", r, 0));
}
},
&InlinedClauseType::IsCompound(..) => match &terms[0] {
&Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) |
&Term::Literal(_, Literal::String(..)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_compound!(r));
code.push(instr!("compound", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsRational(..) => match &terms[0] {
&Term::Literal(_, Literal::Rational(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_rational!(r));
code.push(instr!("rational", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsFloat(..) => match &terms[0] {
&Term::Literal(_, Literal::Float(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_float!(r));
code.push(instr!("float", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsNumber(..) => match &terms[0] {
@@ -595,41 +597,41 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
| &Term::Literal(_, Literal::Rational(_))
| &Term::Literal(_, Literal::Integer(_))
| &Term::Literal(_, Literal::Fixnum(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_number!(r));
code.push(instr!("number", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsNonVar(..) => match &terms[0] {
&Term::AnonVar => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_nonvar!(r));
code.push(instr!("nonvar", r, 0));
}
_ => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
},
&InlinedClauseType::IsInteger(..) => match &terms[0] {
&Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_integer!(r));
code.push(instr!("integer", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsVar(..) => match &terms[0] {
@@ -637,15 +639,15 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
| &Term::Clause(..)
| &Term::Cons(..)
| &Term::PartialString(..) => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::AnonVar => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_var!(r));
code.push(instr!("var", r, 0));
}
},
}
@@ -678,34 +680,39 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
&Term::Var(ref vr, ref name) => {
let mut target = vec![];
self.marker
.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
self.marker.mark_var::<QueryInstruction>(
name.clone(),
Level::Shallow,
vr,
term_loc,
&mut target,
);
if !target.is_empty() {
code.extend(target.into_iter().map(Line::Query));
code.extend(target.into_iter());
}
}
&Term::Literal(_, c @ Literal::Integer(_))
| &Term::Literal(_, c @ Literal::Fixnum(_)) => {
let v = HeapCellValue::from(c);
code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
&Term::Literal(_, c @ Literal::Float(_)) => {
let v = HeapCellValue::from(c);
code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
&Term::Literal(_, c @ Literal::Rational(_)) => {
let v = HeapCellValue::from(c);
code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
return Ok(());
}
}
@@ -717,9 +724,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
};
Ok(if use_default_call_policy {
code.push(is_call_by_default!(temp_v!(1), at));
code.push(instr!("is", default, temp_v!(1), at, 0));
} else {
code.push(is_call!(temp_v!(1), at));
code.push(instr!("is", temp_v!(1), at, 0));
})
}
@@ -727,7 +734,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
let r = self.marker.get(Rc::new(String::from("!")));
cell.set(VarReg::Norm(r));
code.push(set_cp!(cell.get().norm()));
code.push(instr!("$set_cp", cell.get().norm(), 0));
}
fn compile_get_level_and_unify(
@@ -737,21 +744,16 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
var: Rc<String>,
term_loc: GenContext,
) {
let mut target = Vec::new();
let mut target = Code::new();
self.marker.reset_arg(1);
self.marker
.mark_var(var, Level::Shallow, cell, term_loc, &mut target);
self.marker.mark_var::<QueryInstruction>(var, Level::Shallow, cell, term_loc, &mut target);
if !target.is_empty() {
code.extend(
target
.into_iter()
.map(|query_instr| Line::Query(query_instr)),
);
code.extend(target.into_iter());
}
code.push(get_level_and_unify!(cell.get().norm()));
code.push(instr!("get_level_and_unify", cell.get().norm()));
}
fn compile_seq(
@@ -775,9 +777,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
&QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
&QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
Instruction::NeckCut
} else {
Line::Cut(CutInstruction::Cut(perm_v!(1)))
Instruction::Cut(perm_v!(1))
}),
&QueryTerm::Clause(
_,
@@ -810,10 +812,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
if conjunct_info.allocates() {
let perm_vars = conjunct_info.perm_vars();
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
body.push(Instruction::Allocate(perm_vars));
if conjunct_info.has_deep_cut {
body.push(Line::Cut(CutInstruction::GetLevel(perm_v!(1))));
body.push(Instruction::GetLevel(perm_v!(1)));
}
}
}
@@ -826,8 +828,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
) {
// add a proceed to bookend any trailing cuts.
match toc {
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
&QueryTerm::Clause(_, ClauseType::Inlined(..), ..) => code.push(proceed!()),
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => {
code.push(instr!("proceed"));
}
_ => {}
};
@@ -843,7 +846,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
}
code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
code.insert(dealloc_index, instr!("deallocate"));
}
}
@@ -865,16 +868,13 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.compile_seq_prelude(&conjunct_info, &mut code);
let iter = FactIterator::from_rule_head_clause(args);
let mut fact = self.compile_target(iter, GenContext::Head, false);
let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head, false);
let mut unsafe_var_marker = UnsafeVarMarker::new();
if !fact.is_empty() {
unsafe_var_marker = self.mark_unsafe_fact_vars(&mut fact);
for fact_instr in fact {
code.push(Line::Fact(fact_instr));
}
code.extend(fact.into_iter());
}
let iter = ChunkedIterator::from_rule_body(p1, clauses);
@@ -886,18 +886,18 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
Ok(code)
}
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker {
fn mark_unsafe_fact_vars(&self, fact: &mut Code) -> UnsafeVarMarker {
let mut safe_vars = IndexSet::new();
for fact_instr in fact.iter_mut() {
match fact_instr {
&mut FactInstruction::UnifyValue(r) => {
&mut Instruction::UnifyValue(r) => {
if !safe_vars.contains(&r) {
*fact_instr = FactInstruction::UnifyLocalValue(r);
*fact_instr = Instruction::UnifyLocalValue(r);
safe_vars.insert(r);
}
}
&mut FactInstruction::UnifyVariable(r) => {
&mut Instruction::UnifyVariable(r) => {
safe_vars.insert(r);
}
_ => {}
@@ -923,18 +923,20 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.marker.reset_at_head(args);
let iter = FactInstruction::iter(term);
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
let mut compiled_fact = self.compile_target::<FactInstruction, _>(
iter,
GenContext::Head,
false,
);
self.mark_unsafe_fact_vars(&mut compiled_fact);
if !compiled_fact.is_empty() {
for fact_instr in compiled_fact {
code.push(Line::Fact(fact_instr));
}
code.extend(compiled_fact.into_iter());
}
}
code.push(proceed!());
code.push(instr!("proceed"));
code
}
@@ -949,12 +951,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.marker.reset_arg(term.arity());
let iter = query_term_post_order_iter(term);
let query = self.compile_target(iter, term_loc, is_exposed);
let query = self.compile_target::<QueryInstruction, _>(iter, term_loc, is_exposed);
if !query.is_empty() {
for query_instr in query {
code.push(Line::Query(query_instr));
}
code.extend(query.into_iter());
}
self.add_conditional_call(code, term, num_perm_vars_left);
@@ -1061,12 +1061,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
if clauses.len() > 1 {
let choice = match i {
0 => self.settings.internal_try_me_else(clause_code.len() + 1),
//ChoiceInstruction::TryMeElse(clause_code.len() + 1),
//Instruction::TryMeElse(clause_code.len() + 1),
_ if i == clauses.len() - 1 => self.settings.internal_trust_me(),
_ => self.settings.internal_retry_me_else(clause_code.len() + 1),
};
code.push_back(Line::Choice(choice));
code.push_back(choice);
} else if self.settings.is_extensible {
/*
generate stub choice instructions for extensible
@@ -1079,9 +1079,8 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
over them.
*/
code.push_front(Line::Choice(self.settings.internal_try_me_else(0)));
//Line::Choice(ChoiceInstruction::TryMeElse(0)));
skip_stub_try_me_else = !self.settings.is_dynamic(); //true;
code.push_front(self.settings.internal_try_me_else(0));
skip_stub_try_me_else = !self.settings.is_dynamic();
}
let arg = match clause.args() {
@@ -1109,7 +1108,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.global_jmp_by_locs_offset = jmp_by_locs_len;
if !index_code.is_empty() {
code.push_front(Line::IndexingCode(index_code));
code.push_front(Instruction::IndexingCode(index_code));
if skip_stub_try_me_else {
// skip the TryMeElse(0) also.
@@ -1160,13 +1159,13 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
_ => self.settings.retry_me_else(code_segment.len() + 1),
};
code.push(Line::Choice(choice));
code.push(choice);
} else if self.settings.is_extensible {
code.push(Line::Choice(self.settings.try_me_else(0)));
code.push(self.settings.try_me_else(0));
}
if self.settings.is_extensible {
let segment_is_indexed = to_indexing_line(&code_segment[0]).is_some();
let segment_is_indexed = code_segment[0].to_indexing_line().is_some();
for clause_index_info in self.skeleton.clauses[skel_lower_bound..].iter_mut() {
clause_index_info.clause_start +=

View File

@@ -3,23 +3,26 @@ use indexmap::IndexMap;
use crate::allocator::*;
use crate::fixtures::*;
use crate::forms::Level;
use crate::instructions::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
use crate::targets::CompilationTarget;
use crate::temp_v;
use fxhash::FxBuildHasher;
use std::cell::Cell;
use std::collections::BTreeSet;
use std::rc::Rc;
#[derive(Debug)]
pub(crate) struct DebrayAllocator {
bindings: IndexMap<Rc<String>, VarData>,
bindings: IndexMap<Rc<String>, VarData, FxBuildHasher>,
arg_c: usize,
temp_lb: usize,
arity: usize, // 0 if not at head.
contents: IndexMap<usize, Rc<String>>,
contents: IndexMap<usize, Rc<String>, FxBuildHasher>,
in_use: BTreeSet<usize>,
}
@@ -123,7 +126,7 @@ impl DebrayAllocator {
}
}
fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Target>)
fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Instruction>)
where
Target: CompilationTarget<'a>,
{
@@ -152,7 +155,7 @@ impl DebrayAllocator {
var: &String,
lvl: Level,
term_loc: GenContext,
target: &mut Vec<Target>,
target: &mut Vec<Instruction>,
) -> usize
where
Target: CompilationTarget<'a>,
@@ -160,7 +163,7 @@ impl DebrayAllocator {
match term_loc {
GenContext::Head => {
if let Level::Shallow = lvl {
self.evacuate_arg(0, target);
self.evacuate_arg::<Target>(0, target);
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
@@ -169,7 +172,7 @@ impl DebrayAllocator {
GenContext::Mid(_) => self.alloc_with_ca(var),
GenContext::Last(chunk_num) => {
if let Level::Shallow = lvl {
self.evacuate_arg(chunk_num, target);
self.evacuate_arg::<Target>(chunk_num, target);
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
@@ -210,13 +213,18 @@ impl<'a> Allocator<'a> for DebrayAllocator {
arity: 0,
arg_c: 1,
temp_lb: 1,
bindings: IndexMap::new(),
contents: IndexMap::new(),
bindings: IndexMap::with_hasher(FxBuildHasher::default()),
contents: IndexMap::with_hasher(FxBuildHasher::default()),
in_use: BTreeSet::new(),
}
}
fn mark_anon_var<Target>(&mut self, lvl: Level, term_loc: GenContext, target: &mut Vec<Target>)
fn mark_anon_var<Target>(
&mut self,
lvl: Level,
term_loc: GenContext,
target: &mut Vec<Instruction>,
)
where
Target: CompilationTarget<'a>,
{
@@ -228,7 +236,7 @@ impl<'a> Allocator<'a> for DebrayAllocator {
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
self.evacuate_arg(chunk_num, target);
self.evacuate_arg::<Target>(chunk_num, target);
}
self.arg_c += 1;
@@ -243,7 +251,7 @@ impl<'a> Allocator<'a> for DebrayAllocator {
lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
target: &mut Vec<Target>,
target: &mut Vec<Instruction>,
) where
Target: CompilationTarget<'a>,
{
@@ -254,7 +262,7 @@ impl<'a> Allocator<'a> for DebrayAllocator {
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
self.evacuate_arg(chunk_num, target);
self.evacuate_arg::<Target>(chunk_num, target);
}
self.arg_c += 1;
@@ -270,20 +278,18 @@ impl<'a> Allocator<'a> for DebrayAllocator {
cell.set(r);
}
fn mark_var<Target>(
fn mark_var<Target: CompilationTarget<'a>>(
&mut self,
var: Rc<String>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>,
) where
Target: CompilationTarget<'a>,
{
target: &mut Vec<Instruction>,
) {
let (r, is_new_var) = match self.get(var.clone()) {
RegType::Temp(0) => {
// here, r is temporary *and* unassigned.
let o = self.alloc_reg_to_var(&var, lvl, term_loc, target);
let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, target);
cell.set(VarReg::Norm(RegType::Temp(o)));
(RegType::Temp(o), true)
@@ -297,27 +303,25 @@ impl<'a> Allocator<'a> for DebrayAllocator {
r => (r, false),
};
self.mark_reserved_var(var, lvl, cell, term_loc, target, r, is_new_var);
self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, target, r, is_new_var);
}
fn mark_reserved_var<Target>(
fn mark_reserved_var<Target: CompilationTarget<'a>>(
&mut self,
var: Rc<String>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>,
target: &mut Vec<Instruction>,
r: RegType,
is_new_var: bool,
) where
Target: CompilationTarget<'a>,
{
) {
match lvl {
Level::Root | Level::Shallow => {
let k = self.arg_c;
if self.is_curr_arg_distinct_from(&var) {
self.evacuate_arg(term_loc.chunk_num(), target);
self.evacuate_arg::<Target>(term_loc.chunk_num(), target);
}
self.arg_c += 1;

View File

@@ -272,10 +272,10 @@ impl UnsafeVarMarker {
}
}
pub(crate) fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) -> bool {
pub(crate) fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool {
match query_instr {
&QueryInstruction::PutVariable(r @ RegType::Temp(_), _)
| &QueryInstruction::SetVariable(r) => {
&Instruction::PutVariable(r @ RegType::Temp(_), _) |
&Instruction::SetVariable(r) => {
self.safe_vars.insert(r);
true
}
@@ -283,10 +283,10 @@ impl UnsafeVarMarker {
}
}
pub(crate) fn mark_phase(&mut self, query_instr: &QueryInstruction, phase: usize) {
pub(crate) fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) {
match query_instr {
&QueryInstruction::PutValue(r @ RegType::Perm(_), _)
| &QueryInstruction::SetValue(r) => {
&Instruction::PutValue(r @ RegType::Perm(_), _) |
&Instruction::SetValue(r) => {
let p = self.unsafe_vars.entry(r).or_insert(0);
*p = phase;
}
@@ -294,21 +294,21 @@ impl UnsafeVarMarker {
}
}
pub(crate) fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction, phase: usize) {
pub(crate) fn mark_unsafe_vars(&mut self, query_instr: &mut Instruction, phase: usize) {
match query_instr {
&mut QueryInstruction::PutValue(RegType::Perm(i), arg) => {
&mut Instruction::PutValue(RegType::Perm(i), arg) => {
if let Some(p) = self.unsafe_vars.swap_remove(&RegType::Perm(i)) {
if p == phase {
*query_instr = QueryInstruction::PutUnsafeValue(i, arg);
*query_instr = Instruction::PutUnsafeValue(i, arg);
self.safe_vars.insert(RegType::Perm(i));
} else {
self.unsafe_vars.insert(RegType::Perm(i), p);
}
}
}
&mut QueryInstruction::SetValue(r) => {
&mut Instruction::SetValue(r) => {
if !self.safe_vars.contains(&r) {
*query_instr = QueryInstruction::SetLocalValue(r);
*query_instr = Instruction::SetLocalValue(r);
self.safe_vars.insert(r);
self.unsafe_vars.remove(&r);

View File

@@ -1,17 +1,17 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::parser::ast::*;
use crate::parser::parser::CompositeOpDesc;
use crate::parser::rug::{Integer, Rational};
use crate::{is_infix, is_postfix};
use crate::clause_types::*;
use crate::instructions::*;
use crate::machine::heap::*;
use crate::machine::loader::PredicateQueue;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
use crate::parser::parser::CompositeOpDesc;
use crate::parser::rug::{Integer, Rational};
use crate::types::*;
use fxhash::FxBuildHasher;
use indexmap::{IndexMap, IndexSet};
use ordered_float::OrderedFloat;
@@ -19,10 +19,13 @@ use slice_deque::*;
use std::cell::Cell;
use std::convert::TryFrom;
use std::fmt;
use std::ops::AddAssign;
use std::path::PathBuf;
use std::rc::Rc;
use crate::{is_infix, is_postfix};
pub type PredicateKey = (Atom, usize); // name, arity.
pub type Predicate = Vec<PredicateClause>;
@@ -375,7 +378,6 @@ impl AtomOrString {
}
}
//TODO: try to rid yourself and the earth of the next two functions.
pub(crate) fn fetch_atom_op_spec(
name: Atom,
spec: Option<OpDesc>,
@@ -431,7 +433,7 @@ pub(crate) fn fetch_op_spec(name: Atom, arity: usize, op_dir: &OpDir) -> Option<
}
}
pub(crate) type ModuleDir = IndexMap<Atom, Module>;
pub(crate) type ModuleDir = IndexMap<Atom, Module, FxBuildHasher>;
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum ModuleExport {
@@ -464,11 +466,13 @@ impl Module {
) -> Self {
Module {
module_decl,
code_dir: CodeDir::new(),
code_dir: CodeDir::with_hasher(FxBuildHasher::default()),
op_dir: default_op_dir(),
meta_predicates: MetaPredicateDir::new(),
extensible_predicates: ExtensiblePredicates::new(),
local_extensible_predicates: LocalExtensiblePredicates::new(),
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
FxBuildHasher::default(),
),
listing_src,
}
}
@@ -476,11 +480,13 @@ impl Module {
pub(crate) fn new_in_situ(module_decl: ModuleDecl) -> Self {
Module {
module_decl,
code_dir: CodeDir::new(),
op_dir: OpDir::new(),
meta_predicates: MetaPredicateDir::new(),
extensible_predicates: ExtensiblePredicates::new(),
local_extensible_predicates: LocalExtensiblePredicates::new(),
code_dir: CodeDir::with_hasher(FxBuildHasher::default()),
op_dir: OpDir::with_hasher(FxBuildHasher::default()),
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
FxBuildHasher::default()
),
listing_src: ListingSource::DynamicallyGenerated,
}
}
@@ -495,12 +501,22 @@ pub enum Number {
}
impl Default for Number {
#[inline]
fn default() -> Self {
Number::Fixnum(Fixnum::build_with(0))
}
}
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Number::Float(fl) => write!(f, "{}", fl),
Number::Integer(n) => write!(f, "{}", n),
Number::Rational(r) => write!(f, "{}", r),
Number::Fixnum(n) => write!(f, "{}", n.get_num()),
}
}
}
pub trait ArenaFrom<T> {
fn arena_from(value: T, arena: &mut Arena) -> Self;
}
@@ -849,12 +865,3 @@ impl PredicateSkeleton {
}
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum IndexingCodePtr {
External(usize), // the index points past the indexing instruction prelude.
DynamicExternal(usize), // an External index of a dynamic predicate, potentially invalidated by retraction.
Fail,
Internal(usize), // the index points into the indexing instruction prelude.
}

View File

@@ -1,5 +1,6 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::instructions::*;
use crate::parser::ast::*;
use crate::parser::rug::{Integer, Rational};
use crate::{
@@ -8,7 +9,6 @@ use crate::{
sign_char, single_quote_char, small_letter_char, solo_char, variable_indicator_char,
};
use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::heap::*;

View File

@@ -1,919 +0,0 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::parser::ast::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::types::*;
use crate::machine::heap::*;
use crate::machine::machine_errors::MachineStub;
use indexmap::IndexMap;
use slice_deque::SliceDeque;
fn reg_type_into_functor(r: RegType) -> MachineStub {
match r {
RegType::Temp(r) => functor!(atom!("x"), [fixnum(r)]),
RegType::Perm(r) => functor!(atom!("y"), [fixnum(r)]),
}
}
impl Level {
fn into_functor(self) -> MachineStub {
match self {
Level::Root => functor!(atom!("level"), [atom(atom!("root"))]),
Level::Shallow => functor!(atom!("level"), [atom(atom!("shallow"))]),
Level::Deep => functor!(atom!("level"), [atom(atom!("deep"))]),
}
}
}
impl ArithmeticTerm {
fn into_functor(&self, arena: &mut Arena) -> MachineStub {
match self {
&ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
&ArithmeticTerm::Interm(i) => {
functor!(atom!("intermediate"), [fixnum(i)])
}
&ArithmeticTerm::Number(n) => {
vec![HeapCellValue::from((n, arena))]
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum NextOrFail {
Next(usize),
Fail(usize),
}
impl NextOrFail {
#[inline]
pub fn is_next(&self) -> bool {
if let NextOrFail::Next(_) = self {
true
} else {
false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum Death {
Finite(usize),
Infinity,
}
#[derive(Debug)]
pub(crate) enum ChoiceInstruction {
DynamicElse(usize, Death, NextOrFail),
DynamicInternalElse(usize, Death, NextOrFail),
DefaultRetryMeElse(usize),
DefaultTrustMe(usize),
RetryMeElse(usize),
TrustMe(usize),
TryMeElse(usize),
}
impl ChoiceInstruction {
pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
match self {
&ChoiceInstruction::DynamicElse(birth, death, next_or_fail) => {
match (death, next_or_fail) {
(Death::Infinity, NextOrFail::Next(i)) => {
functor!(
atom!("dynamic_else"),
[fixnum(birth), atom(atom!("inf")), fixnum(i)]
)
}
(Death::Infinity, NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!(
atom!("dynamic_else"),
[fixnum(birth), atom(atom!("inf")), str(h, 0)],
[next_functor]
)
}
(Death::Finite(d), NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!(
atom!("dynamic_else"),
[fixnum(birth), fixnum(d), str(h, 0)],
[next_functor]
)
}
(Death::Finite(d), NextOrFail::Next(i)) => {
functor!(atom!("dynamic_else"), [fixnum(birth), fixnum(d), fixnum(i)])
}
}
}
&ChoiceInstruction::DynamicInternalElse(birth, death, next_or_fail) => {
match (death, next_or_fail) {
(Death::Infinity, NextOrFail::Next(i)) => {
functor!(
atom!("dynamic_internal_else"),
[fixnum(birth), atom(atom!("inf")), fixnum(i)]
)
}
(Death::Infinity, NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!(
atom!("dynamic_internal_else"),
[fixnum(birth), atom(atom!("inf")), str(h, 0)],
[next_functor]
)
}
(Death::Finite(d), NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!(
atom!("dynamic_internal_else"),
[fixnum(birth), fixnum(d), str(h, 0)],
[next_functor]
)
}
(Death::Finite(d), NextOrFail::Next(i)) => {
functor!(
atom!("dynamic_internal_else"),
[fixnum(birth), fixnum(d), fixnum(i)]
)
}
}
}
&ChoiceInstruction::TryMeElse(offset) => {
functor!(atom!("try_me_else"), [fixnum(offset)])
}
&ChoiceInstruction::RetryMeElse(offset) => {
functor!(atom!("retry_me_else"), [fixnum(offset)])
}
&ChoiceInstruction::TrustMe(offset) => {
functor!(atom!("trust_me"), [fixnum(offset)])
}
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
functor!(atom!("default_retry_me_else"), [fixnum(offset)])
}
&ChoiceInstruction::DefaultTrustMe(offset) => {
functor!(atom!("default_trust_me"), [fixnum(offset)])
}
}
}
}
#[derive(Debug)]
pub(crate) enum CutInstruction {
Cut(RegType),
GetLevel(RegType),
GetLevelAndUnify(RegType),
NeckCut,
}
impl CutInstruction {
pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
match self {
&CutInstruction::Cut(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("cut"), [str(h, 0)], [rt_stub])
}
&CutInstruction::GetLevel(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_level"), [str(h, 0)], [rt_stub])
}
&CutInstruction::GetLevelAndUnify(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_level_and_unify"), [str(h, 0)], [rt_stub])
}
&CutInstruction::NeckCut => {
functor!(atom!("neck_cut"))
}
}
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum IndexedChoiceInstruction {
Retry(usize),
Trust(usize),
Try(usize),
}
impl IndexedChoiceInstruction {
pub(crate) fn offset(&self) -> usize {
match self {
&IndexedChoiceInstruction::Retry(offset) => offset,
&IndexedChoiceInstruction::Trust(offset) => offset,
&IndexedChoiceInstruction::Try(offset) => offset,
}
}
pub(crate) fn to_functor(&self) -> MachineStub {
match self {
&IndexedChoiceInstruction::Try(offset) => {
functor!(atom!("try"), [fixnum(offset)])
}
&IndexedChoiceInstruction::Trust(offset) => {
functor!(atom!("trust"), [fixnum(offset)])
}
&IndexedChoiceInstruction::Retry(offset) => {
functor!(atom!("retry"), [fixnum(offset)])
}
}
}
}
/// A `Line` is an instruction (cf. page 98 of wambook).
#[derive(Debug)]
pub(crate) enum IndexingLine {
Indexing(IndexingInstruction),
IndexedChoice(SliceDeque<IndexedChoiceInstruction>),
DynamicIndexedChoice(SliceDeque<usize>),
}
impl From<IndexingInstruction> for IndexingLine {
#[inline]
fn from(instr: IndexingInstruction) -> Self {
IndexingLine::Indexing(instr)
}
}
impl From<SliceDeque<IndexedChoiceInstruction>> for IndexingLine {
#[inline]
fn from(instrs: SliceDeque<IndexedChoiceInstruction>) -> Self {
IndexingLine::IndexedChoice(instrs)
}
}
#[derive(Debug)]
pub(crate) enum Line {
Arithmetic(ArithmeticInstruction),
Choice(ChoiceInstruction),
Control(ControlInstruction),
Cut(CutInstruction),
Fact(FactInstruction),
IndexingCode(Vec<IndexingLine>),
IndexedChoice(IndexedChoiceInstruction),
DynamicIndexedChoice(usize),
Query(QueryInstruction),
}
impl Line {
#[inline]
pub(crate) fn is_head_instr(&self) -> bool {
match self {
&Line::Fact(_) => true,
&Line::Query(_) => true,
_ => false,
}
}
pub(crate) fn enqueue_functors(
&self,
mut h: usize,
arena: &mut Arena,
functors: &mut Vec<MachineStub>,
) {
match self {
&Line::Arithmetic(ref arith_instr) => {
functors.push(arith_instr.to_functor(h, arena))
}
&Line::Choice(ref choice_instr) => functors.push(choice_instr.to_functor(h)),
&Line::Control(ref control_instr) => functors.push(control_instr.to_functor()),
&Line::Cut(ref cut_instr) => functors.push(cut_instr.to_functor(h)),
&Line::Fact(ref fact_instr) => functors.push(fact_instr.to_functor(h)),
&Line::IndexingCode(ref indexing_instrs) => {
for indexing_instr in indexing_instrs {
match indexing_instr {
IndexingLine::Indexing(indexing_instr) => {
let section = indexing_instr.to_functor(h);
h += section.len();
functors.push(section);
}
IndexingLine::IndexedChoice(indexed_choice_instrs) => {
for indexed_choice_instr in indexed_choice_instrs {
let section = indexed_choice_instr.to_functor();
h += section.len();
functors.push(section);
}
}
IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => {
for indexed_choice_instr in indexed_choice_instrs {
let section = functor!(
atom!("dynamic"),
[fixnum(*indexed_choice_instr)]
);
h += section.len();
functors.push(section);
}
}
}
}
}
&Line::IndexedChoice(ref indexed_choice_instr) => {
functors.push(indexed_choice_instr.to_functor())
}
&Line::DynamicIndexedChoice(ref indexed_choice_instr) => {
functors.push(functor!(atom!("dynamic"), [fixnum(*indexed_choice_instr)]));
}
&Line::Query(ref query_instr) => functors.push(query_instr.to_functor(h)),
}
}
}
#[inline]
pub(crate) fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec<IndexingLine>> {
match line {
Line::IndexingCode(ref mut indexing_code) => Some(indexing_code),
_ => None,
}
}
#[inline]
pub(crate) fn to_indexing_line(line: &Line) -> Option<&Vec<IndexingLine>> {
match line {
Line::IndexingCode(ref indexing_code) => Some(indexing_code),
_ => None,
}
}
#[derive(Debug, Copy, Clone)]
pub enum ArithmeticInstruction {
Add(ArithmeticTerm, ArithmeticTerm, usize),
Sub(ArithmeticTerm, ArithmeticTerm, usize),
Mul(ArithmeticTerm, ArithmeticTerm, usize),
Pow(ArithmeticTerm, ArithmeticTerm, usize),
IntPow(ArithmeticTerm, ArithmeticTerm, usize),
IDiv(ArithmeticTerm, ArithmeticTerm, usize),
Max(ArithmeticTerm, ArithmeticTerm, usize),
Min(ArithmeticTerm, ArithmeticTerm, usize),
IntFloorDiv(ArithmeticTerm, ArithmeticTerm, usize),
RDiv(ArithmeticTerm, ArithmeticTerm, usize),
Div(ArithmeticTerm, ArithmeticTerm, usize),
Shl(ArithmeticTerm, ArithmeticTerm, usize),
Shr(ArithmeticTerm, ArithmeticTerm, usize),
Xor(ArithmeticTerm, ArithmeticTerm, usize),
And(ArithmeticTerm, ArithmeticTerm, usize),
Or(ArithmeticTerm, ArithmeticTerm, usize),
Mod(ArithmeticTerm, ArithmeticTerm, usize),
Rem(ArithmeticTerm, ArithmeticTerm, usize),
Gcd(ArithmeticTerm, ArithmeticTerm, usize),
Sign(ArithmeticTerm, usize),
Cos(ArithmeticTerm, usize),
Sin(ArithmeticTerm, usize),
Tan(ArithmeticTerm, usize),
Log(ArithmeticTerm, usize),
Exp(ArithmeticTerm, usize),
ACos(ArithmeticTerm, usize),
ASin(ArithmeticTerm, usize),
ATan(ArithmeticTerm, usize),
ATan2(ArithmeticTerm, ArithmeticTerm, usize),
Sqrt(ArithmeticTerm, usize),
Abs(ArithmeticTerm, usize),
Float(ArithmeticTerm, usize),
Truncate(ArithmeticTerm, usize),
Round(ArithmeticTerm, usize),
Ceiling(ArithmeticTerm, usize),
Floor(ArithmeticTerm, usize),
Neg(ArithmeticTerm, usize),
Plus(ArithmeticTerm, usize),
BitwiseComplement(ArithmeticTerm, usize),
}
fn arith_instr_unary_functor(
h: usize,
name: Atom,
arena: &mut Arena,
at: &ArithmeticTerm,
t: usize,
) -> MachineStub {
let at_stub = at.into_functor(arena);
functor!(name, [str(h, 0), fixnum(t)], [at_stub])
}
fn arith_instr_bin_functor(
h: usize,
name: Atom,
arena: &mut Arena,
at_1: &ArithmeticTerm,
at_2: &ArithmeticTerm,
t: usize,
) -> MachineStub {
let at_1_stub = at_1.into_functor(arena);
let at_2_stub = at_2.into_functor(arena);
functor!(
name,
[str(h, 0), str(h, 1), fixnum(t)],
[at_1_stub, at_2_stub]
)
}
impl ArithmeticInstruction {
pub(crate) fn to_functor(
&self,
h: usize,
arena: &mut Arena,
) -> MachineStub {
match self {
&ArithmeticInstruction::Add(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("add"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Sub(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("sub"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Mul(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("mul"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::IntPow(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("int_pow"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Pow(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("pow"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::IDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("idiv"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Max(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("max"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Min(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("min"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::IntFloorDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("int_floor_div"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::RDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("rdiv"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Div(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("div"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Shl(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("shl"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Shr(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("shr"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Xor(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("xor"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::And(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("and"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Or(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("or"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Mod(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("mod"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Rem(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::ATan2(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("gcd"), arena, at_1, at_2, t)
}
&ArithmeticInstruction::Sign(ref at, t) => {
arith_instr_unary_functor(h, atom!("sign"), arena, at, t)
}
&ArithmeticInstruction::Cos(ref at, t) => {
arith_instr_unary_functor(h, atom!("cos"), arena, at, t)
}
&ArithmeticInstruction::Sin(ref at, t) => {
arith_instr_unary_functor(h, atom!("sin"), arena, at, t)
}
&ArithmeticInstruction::Tan(ref at, t) => {
arith_instr_unary_functor(h, atom!("tan"), arena, at, t)
}
&ArithmeticInstruction::Log(ref at, t) => {
arith_instr_unary_functor(h, atom!("log"), arena, at, t)
}
&ArithmeticInstruction::Exp(ref at, t) => {
arith_instr_unary_functor(h, atom!("exp"), arena, at, t)
}
&ArithmeticInstruction::ACos(ref at, t) => {
arith_instr_unary_functor(h, atom!("acos"), arena, at, t)
}
&ArithmeticInstruction::ASin(ref at, t) => {
arith_instr_unary_functor(h, atom!("asin"), arena, at, t)
}
&ArithmeticInstruction::ATan(ref at, t) => {
arith_instr_unary_functor(h, atom!("atan"), arena, at, t)
}
&ArithmeticInstruction::Sqrt(ref at, t) => {
arith_instr_unary_functor(h, atom!("sqrt"), arena, at, t)
}
&ArithmeticInstruction::Abs(ref at, t) => {
arith_instr_unary_functor(h, atom!("abs"), arena, at, t)
}
&ArithmeticInstruction::Float(ref at, t) => {
arith_instr_unary_functor(h, atom!("float"), arena, at, t)
}
&ArithmeticInstruction::Truncate(ref at, t) => {
arith_instr_unary_functor(h, atom!("truncate"), arena, at, t)
}
&ArithmeticInstruction::Round(ref at, t) => {
arith_instr_unary_functor(h, atom!("round"), arena, at, t)
}
&ArithmeticInstruction::Ceiling(ref at, t) => {
arith_instr_unary_functor(h, atom!("ceiling"), arena, at, t)
}
&ArithmeticInstruction::Floor(ref at, t) => {
arith_instr_unary_functor(h, atom!("floor"), arena, at, t)
}
&ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(
h,
atom!("-"),
arena,
at,
t,
),
&ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(
h,
atom!("+"),
arena,
at,
t,
),
&ArithmeticInstruction::BitwiseComplement(ref at, t) => arith_instr_unary_functor(
h,
atom!("\\"),
arena,
at,
t,
),
}
}
}
#[derive(Debug)]
pub enum ControlInstruction {
Allocate(usize), // num_frames.
// name, arity, perm_vars after threshold, last call, use default call policy.
CallClause(ClauseType, usize, usize, bool, bool),
Deallocate,
JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
RevJmpBy(usize), // notice the lack of context change as in
// JmpBy. RevJmpBy is used only to patch extensible
// predicates together.
Proceed,
}
impl ControlInstruction {
pub(crate) fn perm_vars(&self) -> Option<usize> {
match self {
ControlInstruction::CallClause(_, _, num_cells, ..) => Some(*num_cells),
ControlInstruction::JmpBy(_, _, num_cells, ..) => Some(*num_cells),
_ => None,
}
}
pub(crate) fn to_functor(&self) -> MachineStub {
match self {
&ControlInstruction::Allocate(num_frames) => {
functor!(atom!("allocate"), [fixnum(num_frames)])
}
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => {
functor!(atom!("call"), [atom(ct.name()), fixnum(arity)])
}
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => {
functor!(atom!("execute"), [atom(ct.name()), fixnum(arity)])
}
&ControlInstruction::Deallocate => {
functor!(atom!("deallocate"))
}
&ControlInstruction::JmpBy(_, offset, ..) => {
functor!(atom!("jmp_by"), [fixnum(offset)])
}
&ControlInstruction::RevJmpBy(offset) => {
functor!(atom!("rev_jmp_by"), [fixnum(offset)])
}
&ControlInstruction::Proceed => {
functor!(atom!("proceed"))
}
}
}
}
/// `IndexingInstruction` cf. page 110 of wambook.
#[derive(Debug)]
pub(crate) enum IndexingInstruction {
// The first index is the optimal argument being indexed.
SwitchOnTerm(
usize,
IndexingCodePtr,
IndexingCodePtr,
IndexingCodePtr,
IndexingCodePtr,
),
SwitchOnConstant(IndexMap<Literal, IndexingCodePtr>),
SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr>),
}
impl IndexingCodePtr {
#[allow(dead_code)]
pub(crate) fn to_functor(self) -> MachineStub {
match self {
IndexingCodePtr::DynamicExternal(o) => functor!(atom!("dynamic_external"), [fixnum(o)]),
IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]),
IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]),
IndexingCodePtr::Fail => {
vec![atom_as_cell!(atom!("fail"))]
},
}
}
}
impl IndexingInstruction {
pub(crate) fn to_functor(&self, mut h: usize) -> MachineStub {
match self {
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
functor!(
atom!("switch_on_term"),
[
fixnum(arg),
indexing_code_ptr(h, vars),
indexing_code_ptr(h, constants),
indexing_code_ptr(h, lists),
indexing_code_ptr(h, structures)
]
)
}
&IndexingInstruction::SwitchOnConstant(ref constants) => {
let mut key_value_list_stub = vec![];
let orig_h = h;
h += 2; // skip the 2-cell "switch_on_constant" functor.
for (c, ptr) in constants.iter() {
let key_value_pair = functor!(
atom!(":"),
[literal(*c), indexing_code_ptr(h + 3, *ptr)]
);
key_value_list_stub.push(list_loc_as_cell!(h + 1));
key_value_list_stub.push(str_loc_as_cell!(h + 3));
key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
h += key_value_pair.len() + 3;
key_value_list_stub.extend(key_value_pair.into_iter());
}
key_value_list_stub.push(empty_list_as_cell!());
functor!(
atom!("switch_on_constant"),
[str(orig_h, 0)],
[key_value_list_stub]
)
}
&IndexingInstruction::SwitchOnStructure(ref structures) => {
let mut key_value_list_stub = vec![];
let orig_h = h;
h += 2; // skip the 2-cell "switch_on_constant" functor.
for ((name, arity), ptr) in structures.iter() {
let predicate_indicator_stub = functor!(
atom!("/"),
[atom(name), fixnum(*arity)]
);
let key_value_pair = functor!(
atom!(":"),
[str(h + 3, 0), indexing_code_ptr(h + 3, *ptr)],
[predicate_indicator_stub]
);
key_value_list_stub.push(list_loc_as_cell!(h + 1));
key_value_list_stub.push(str_loc_as_cell!(h + 3));
key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
h += key_value_pair.len() + 3;
key_value_list_stub.extend(key_value_pair.into_iter());
}
key_value_list_stub.push(empty_list_as_cell!());
functor!(
atom!("switch_on_structure"),
[str(orig_h, 0)],
[key_value_list_stub]
)
}
}
}
}
#[derive(Debug, Clone)]
pub enum FactInstruction {
GetConstant(Level, HeapCellValue, RegType),
GetList(Level, RegType),
GetPartialString(Level, Atom, RegType, bool),
GetStructure(ClauseType, usize, RegType),
GetValue(RegType, usize),
GetVariable(RegType, usize),
UnifyConstant(HeapCellValue),
UnifyLocalValue(RegType),
UnifyVariable(RegType),
UnifyValue(RegType),
UnifyVoid(usize),
}
impl FactInstruction {
pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
match self {
&FactInstruction::GetConstant(lvl, c, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("get_constant"),
[str(h, 0), cell(c), str(h, 1)],
[lvl_stub, rt_stub]
)
}
&FactInstruction::GetList(lvl, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("get_list"),
[str(h, 0), str(h, 1)],
[lvl_stub, rt_stub]
)
}
&FactInstruction::GetPartialString(lvl, s, r, has_tail) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("get_partial_string"),
[
str(h, 0),
string(h, s),
str(h, 1),
boolean(has_tail)
],
[lvl_stub, rt_stub]
)
}
&FactInstruction::GetStructure(ref ct, arity, r) => {
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("get_structure"),
[atom(ct.name()), fixnum(arity), str(h, 0)],
[rt_stub]
)
}
&FactInstruction::GetValue(r, arg) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_value"), [str(h, 0), fixnum(arg)], [rt_stub])
}
&FactInstruction::GetVariable(r, arg) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
}
&FactInstruction::UnifyConstant(c) => {
functor!(atom!("unify_constant"), [cell(c)])
}
&FactInstruction::UnifyLocalValue(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("unify_local_value"), [str(h, 0)], [rt_stub])
}
&FactInstruction::UnifyVariable(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("unify_variable"), [str(h, 0)], [rt_stub])
}
&FactInstruction::UnifyValue(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("unify_value"), [str(h, 0)], [rt_stub])
}
&FactInstruction::UnifyVoid(vars) => {
functor!(atom!("unify_void"), [fixnum(vars)])
}
}
}
}
#[derive(Debug, Clone)]
pub(crate) enum QueryInstruction {
GetVariable(RegType, usize),
PutConstant(Level, HeapCellValue, RegType),
PutList(Level, RegType),
PutPartialString(Level, Atom, RegType, bool),
PutStructure(ClauseType, usize, RegType),
PutUnsafeValue(usize, usize),
PutValue(RegType, usize),
PutVariable(RegType, usize),
SetConstant(HeapCellValue),
SetLocalValue(RegType),
SetVariable(RegType),
SetValue(RegType),
SetVoid(usize),
}
impl QueryInstruction {
pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
match self {
&QueryInstruction::PutUnsafeValue(norm, arg) => {
functor!(atom!("put_unsafe_value"), [fixnum(norm), fixnum(arg)])
}
&QueryInstruction::PutConstant(lvl, c, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("put_constant"),
[str(h, 0), cell(c), str(h, 1)],
[lvl_stub, rt_stub]
)
}
&QueryInstruction::PutList(lvl, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("put_list"),
[str(h, 0), str(h, 1)],
[lvl_stub, rt_stub]
)
}
&QueryInstruction::PutPartialString(lvl, s, r, has_tail) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("put_partial_string"),
[
str(h, 0),
string(h, s),
str(h, 1),
boolean(has_tail)
],
[lvl_stub, rt_stub]
)
}
&QueryInstruction::PutStructure(ref ct, arity, r) => {
let rt_stub = reg_type_into_functor(r);
functor!(
atom!("put_structure"),
[atom(ct.name()), fixnum(arity), str(h, 0)],
[rt_stub]
)
}
&QueryInstruction::PutValue(r, arg) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("put_value"), [str(h, 0), fixnum(arg)], [rt_stub])
}
&QueryInstruction::GetVariable(r, arg) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
}
&QueryInstruction::PutVariable(r, arg) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("put_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
}
&QueryInstruction::SetConstant(c) => {
functor!(atom!("set_constant"), [cell(c)], [])
}
&QueryInstruction::SetLocalValue(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("set_local_value"), [str(h, 0)], [rt_stub])
}
&QueryInstruction::SetVariable(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("set_variable"), [str(h, 0)], [rt_stub])
}
&QueryInstruction::SetValue(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(atom!("set_value"), [str(h, 0)], [rt_stub])
}
&QueryInstruction::SetVoid(vars) => {
functor!(atom!("set_void"), [fixnum(vars)])
}
}
}
}
pub(crate) type CompiledFact = Vec<FactInstruction>;
pub(crate) type Code = Vec<Line>;

View File

@@ -1,9 +1,8 @@
use crate::atom_table::*;
use crate::parser::ast::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
use std::cell::Cell;
use std::collections::VecDeque;
@@ -52,7 +51,7 @@ impl<'a> TermIterState<'a> {
match term {
Term::AnonVar => TermIterState::AnonVar(lvl),
Term::Clause(cell, name, subterms) => {
let ct = ClauseType::Named(name.clone(), subterms.len(), CodeIndex::default());
let ct = ClauseType::Named(subterms.len(), *name, CodeIndex::default());
TermIterState::Clause(lvl, 0, cell, ct, subterms)
}
Term::Cons(cell, head, tail) => {
@@ -112,8 +111,8 @@ impl<'a> QueryIterator<'a> {
fn new(term: &'a QueryTerm) -> Self {
match term {
&QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms, _) => {
let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
&QueryTerm::Clause(ref cell, ClauseType::CallN(arity), ref terms, _) => {
let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN(arity), terms);
QueryIterator {
state_stack: vec![state],
}
@@ -164,7 +163,7 @@ impl<'a> Iterator for QueryIterator<'a> {
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
if child_num == child_terms.len() {
match ct {
ClauseType::CallN => {
ClauseType::CallN(_) => {
self.push_subterm(Level::Shallow, &child_terms[0]);
}
ClauseType::Named(..) => {
@@ -499,7 +498,7 @@ impl<'a> ChunkedIterator<'a> {
}
ChunkedTerm::BodyTerm(&QueryTerm::Clause(
_,
ClauseType::CallN,
ClauseType::CallN(_),
ref subterms,
_,
)) => {

View File

@@ -1,3 +1,5 @@
#![recursion_limit = "4112"]
#[macro_use]
extern crate static_assertions;
@@ -11,7 +13,6 @@ pub mod arena;
pub mod parser;
mod allocator;
mod arithmetic;
mod clause_types;
pub mod codegen;
mod debray_allocator;
mod fixtures;
@@ -19,7 +20,8 @@ mod forms;
mod heap_iter;
pub mod heap_print;
mod indexing;
mod instructions;
#[macro_use]
pub mod instructions;
mod iterators;
pub mod machine;
mod raw_block;

View File

@@ -12,9 +12,7 @@ between(Lower, Upper, X) :-
( nonvar(X) ->
Lower =< X,
X =< Upper
; % compare(Ord, Lower, Upper),
% between_(Ord, Lower, Upper, X)
Lower =< Upper,
; Lower =< Upper,
between_(Lower, Upper, X)
).
@@ -27,16 +25,6 @@ between_(Lower, Upper, Lower1) :-
)
).
/*
between_(<, Lower0, Upper, X) :-
( X = Lower0
; Lower1 is Lower0 + 1,
compare(Ord, Lower1, Upper),
between_(Ord, Lower1, Upper, X)
).
between_(=, Upper, Upper, Upper).
*/
enumerate_nats(I, I).
enumerate_nats(I0, N) :-
I1 is I0 + 1,

View File

@@ -59,15 +59,13 @@ call(G, A, B, C, D, E, F, G) :- '$call'(G, A, B, C, D, E, F, G).
call(G, A, B, C, D, E, F, G, H) :- '$call'(G, A, B, C, D, E, F, G, H).
% dynamic module resolution.
Module : Predicate :-
( atom(Module) -> '$module_call'(Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
% dynamic module resolution.
:(Module, Predicate, A1) :-
( atom(Module) ->
'$module_call'(A1, Module, Predicate)

View File

@@ -56,13 +56,16 @@ length(Xs, N) :-
!,
'$skip_max_list'(M, -1, Xs, Xs0),
( Xs0 == [] -> N = M
; var(Xs0) -> length_addendum(Xs0, N, M)).
; var(Xs0) -> length_addendum(Xs0, N, M)
).
length(Xs, N) :-
integer(N),
N >= 0, !,
N >= 0,
!,
'$skip_max_list'(M, N, Xs, Xs0),
( Xs0 == [] -> N = M
; var(Xs0) -> R is N-M, length_rundown(Xs0, R)).
; var(Xs0) -> R is N-M, length_rundown(Xs0, R)
).
length(_, N) :-
integer(N), !,
domain_error(not_less_than_zero, N, length/2).

View File

@@ -90,7 +90,6 @@ unload_evacuable(Evacuable) :-
run_initialization_goals(Module) :-
( predicate_property(Module:'$initialization_goals'(_), dynamic) ->
% FIXME: failing here. also, see add_module.
'$debug_hook',
findall(Module:Goal, '$call'(builtins:retract(Module:'$initialization_goals'(Goal))), Goals),
abolish(Module:'$initialization_goals'/1),
( maplist(Module:call, Goals) ->
@@ -543,15 +542,15 @@ use_module(Module, Exports, Evacuable) :-
check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :-
'$cpp_meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm).
'$meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm).
check_predicate_property(built_in, _, Name, Arity, built_in) :-
'$cpp_built_in_property'(Name, Arity).
'$built_in_property'(Name, Arity).
check_predicate_property(dynamic, Module, Name, Arity, dynamic) :-
'$cpp_dynamic_property'(Module, Name, Arity).
'$dynamic_property'(Module, Name, Arity).
check_predicate_property(multifile, Module, Name, Arity, multifile) :-
'$cpp_multifile_property'(Module, Name, Arity).
'$multifile_property'(Module, Name, Arity).
check_predicate_property(discontiguous, Module, Name, Arity, discontiguous) :-
'$cpp_discontiguous_property'(Module, Name, Arity).
'$discontiguous_property'(Module, Name, Arity).

View File

@@ -3,7 +3,6 @@ use divrem::*;
use crate::arena::*;
use crate::arithmetic::*;
use crate::atom_table::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::machine_errors::*;

View File

@@ -15,8 +15,9 @@ pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
pub(super) struct AttrVarInitializer {
pub(super) attr_var_queue: Vec<usize>,
pub(super) bindings: Bindings,
pub(super) cp: LocalCodePtr,
pub(super) instigating_p: LocalCodePtr,
pub(super) p: usize,
pub(super) cp: usize,
// pub(super) instigating_p: usize,
pub(super) verify_attrs_loc: usize,
}
@@ -25,8 +26,8 @@ impl AttrVarInitializer {
AttrVarInitializer {
attr_var_queue: vec![],
bindings: vec![],
instigating_p: LocalCodePtr::default(),
cp: LocalCodePtr::default(),
p: 0,
cp: 0,
verify_attrs_loc,
}
}
@@ -41,15 +42,14 @@ impl AttrVarInitializer {
impl MachineState {
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: HeapCellValue) {
if self.attr_var_init.bindings.is_empty() {
self.attr_var_init.instigating_p = self.p.local();
// save self.p and self.cp and ensure that the next
// instruction is InstallVerifyAttrInterrupt.
if self.last_call {
self.attr_var_init.p = self.p;
self.attr_var_init.cp = self.cp;
} else {
self.attr_var_init.cp = self.p.local() + 1;
}
self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
self.p = INSTALL_VERIFY_ATTR_INTERRUPT - 1;
self.cp = INSTALL_VERIFY_ATTR_INTERRUPT;
}
self.attr_var_init.bindings.push((h, addr));
@@ -109,25 +109,27 @@ impl MachineState {
}
pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
self.allocate(self.num_of_args + 2);
self.allocate(self.num_of_args + 3);
let e = self.e;
self.stack.index_and_frame_mut(e).prelude.interrupt_cp = self.attr_var_init.cp;
let and_frame = self.stack.index_and_frame_mut(e);
for i in 1..self.num_of_args + 1 {
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)];
and_frame[i] = self.registers[i];
}
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
and_frame[self.num_of_args + 1] =
fixnum_as_cell!(Fixnum::build_with(self.b0 as i64));
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
and_frame[self.num_of_args + 2] =
fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[self.num_of_args + 3] =
fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
self.verify_attributes();
self.num_of_args = 2;
self.num_of_args = 3;
self.b0 = self.b;
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
self.p = p;
}
pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> {

View File

@@ -1,197 +0,0 @@
use crate::clause_types::*;
use crate::instructions::*;
use crate::machine::{Machine, MachineState};
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'.
#[derive(Debug)]
pub struct CodeRepo {
pub(super) code: Code,
}
impl CodeRepo {
pub(super) fn lookup_instr(&self, machine_st: &MachineState, p: &CodePtr) -> Option<OwnedOrIndexed> {
match p {
&CodePtr::Local(local) => {
return Some(self.lookup_local_instr(machine_st, local));
}
&CodePtr::REPL(..) => None,
&CodePtr::BuiltInClause(ref built_in, _) => {
let call_clause = call_clause!(
ClauseType::BuiltIn(built_in.clone()),
built_in.arity(),
0,
machine_st.last_call
);
Some(OwnedOrIndexed::Owned(call_clause))
}
&CodePtr::CallN(arity, _, last_call) => {
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
Some(OwnedOrIndexed::Owned(call_clause))
}
&CodePtr::VerifyAttrInterrupt(p) => Some(OwnedOrIndexed::Indexed(p)),
}
}
#[inline]
pub(super) fn lookup_local_instr(&self, machine_st: &MachineState, p: LocalCodePtr) -> OwnedOrIndexed {
match p {
LocalCodePtr::Halt => {
// exit with the interrupt exit code.
std::process::exit(1);
}
LocalCodePtr::DirEntry(p) => match &self.code[p] {
&Line::IndexingCode(ref indexing_lines) => {
match &indexing_lines[machine_st.oip as usize] {
&IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
OwnedOrIndexed::Owned(
Line::IndexedChoice(indexed_choice_instrs[machine_st.iip as usize])
)
}
&IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
OwnedOrIndexed::Owned(
Line::DynamicIndexedChoice(indexed_choice_instrs[machine_st.iip as usize])
)
}
_ => {
OwnedOrIndexed::Indexed(p)
}
}
}
_ => OwnedOrIndexed::Indexed(p)
}
}
}
}
impl Machine {
pub(super) fn find_living_dynamic_else(&self, mut p: usize) -> Option<(usize, usize)> {
loop {
match &self.code_repo.code[p] {
&Line::Choice(ChoiceInstruction::DynamicElse(
birth,
death,
NextOrFail::Next(i),
)) => {
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
return Some((p, i));
} else if i > 0 {
p += i;
} else {
return None;
}
}
&Line::Choice(ChoiceInstruction::DynamicElse(
birth,
death,
NextOrFail::Fail(_),
)) => {
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
return Some((p, 0));
} else {
return None;
}
}
&Line::Choice(ChoiceInstruction::DynamicInternalElse(
birth,
death,
NextOrFail::Next(i),
)) => {
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
return Some((p, i));
} else if i > 0 {
p += i;
} else {
return None;
}
}
&Line::Choice(ChoiceInstruction::DynamicInternalElse(
birth,
death,
NextOrFail::Fail(_),
)) => {
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
return Some((p, 0));
} else {
return None;
}
}
&Line::Control(ControlInstruction::RevJmpBy(i)) => {
p -= i;
}
_ => {
unreachable!();
}
}
}
}
pub(super) fn find_living_dynamic(&self, oi: u32, mut ii: u32) -> Option<(usize, u32, u32, bool)> {
let p = self.machine_st.p.local().abs_loc();
let indexed_choice_instrs = match &self.code_repo.code[p] {
Line::IndexingCode(ref indexing_code) => match &indexing_code[oi as usize] {
IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
indexed_choice_instrs
}
_ => unreachable!(),
},
_ => unreachable!(),
};
loop {
match &indexed_choice_instrs.get(ii as usize) {
Some(&offset) => match &self.code_repo.code[p + offset - 1] {
&Line::Choice(ChoiceInstruction::DynamicInternalElse(
birth,
death,
next_or_fail,
)) => {
if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
return Some((offset, oi, ii, next_or_fail.is_next()));
} else {
ii += 1;
}
}
_ => unreachable!(),
},
None => return None,
}
}
}
}
impl CodeRepo {
#[inline]
pub(super) fn new() -> Self {
CodeRepo { code: Code::new() }
}
}

View File

@@ -2,45 +2,47 @@ use crate::instructions::*;
use indexmap::IndexSet;
fn capture_offset(line: &Line, index: usize, stack: &mut Vec<usize>) -> bool {
fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> bool {
match line {
&Line::Choice(ChoiceInstruction::TryMeElse(offset)) if offset > 0 => {
&Instruction::TryMeElse(offset) if offset > 0 => {
stack.push(index + offset);
}
&Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset))
| &Line::Choice(ChoiceInstruction::RetryMeElse(offset))
&Instruction::DefaultRetryMeElse(offset) |
&Instruction::RetryMeElse(offset)
if offset > 0 =>
{
stack.push(index + offset);
}
&Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset)))
&Instruction::DynamicElse(_, _, NextOrFail::Next(offset))
if offset > 0 =>
{
stack.push(index + offset);
}
&Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(offset)))
&Instruction::DynamicInternalElse(_, _, NextOrFail::Next(offset))
if offset > 0 =>
{
stack.push(index + offset);
}
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
&Instruction::JmpByCall(_, offset, _) => {
stack.push(index + offset);
}
&Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
&Instruction::JmpByExecute(_, offset, _) => {
stack.push(index + offset);
return true;
}
&Line::Control(ControlInstruction::Proceed)
| &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) => {
&Instruction::Proceed => {
return true;
}
&Line::Control(ControlInstruction::RevJmpBy(offset)) => {
&Instruction::RevJmpBy(offset) => {
if offset > 0 {
stack.push(index - offset);
} else {
return true;
}
}
instr if instr.is_execute() => {
return true;
}
_ => {}
};
@@ -51,7 +53,7 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec<usize>) -> bool {
* begin in code at the offset p. Each instruction is passed to the
* walker function.
*/
pub(crate) fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) {
pub(crate) fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Instruction)) {
let mut stack = vec![p];
let mut visited_indices = IndexSet::new();

View File

@@ -38,7 +38,7 @@ pub(super) fn bootstrapping_compile(
);
let payload = BootstrappingLoadState(
LoadStatePayload::new(wam_prelude.code_repo.code.len(), term_stream)
LoadStatePayload::new(wam_prelude.code.len(), term_stream)
);
let loader: Loader<'_, BootstrappingLoadState> = Loader { payload, wam_prelude };
@@ -73,7 +73,8 @@ pub(super) fn compile_appendix(
let code_len = code.len();
match &mut code[jmp_by_offset] {
&mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => {
&mut Instruction::JmpByCall(_, ref mut offset, ..) |
&mut Instruction::JmpByExecute(_, ref mut offset, ..) => {
*offset = code_len - jmp_by_offset;
}
_ => {
@@ -144,20 +145,20 @@ fn derelictize_try_me_else(
retraction_info: &mut RetractionInfo,
) -> Option<usize> {
match &mut code[index] {
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(0))) => None,
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))) => {
Instruction::DynamicElse(_, _, NextOrFail::Next(0)) => None,
Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o));
Some(mem::replace(o, 0))
}
Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(0))) => None,
Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))) => {
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(0)) => None,
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o));
Some(mem::replace(o, 0))
}
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(_)))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(_))) => None,
Line::Choice(ChoiceInstruction::TryMeElse(0)) => None,
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => None,
Instruction::TryMeElse(0) => None,
Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *o));
Some(mem::replace(o, 0))
}
@@ -183,7 +184,7 @@ fn merge_indices(
let clause_loc =
find_inner_choice_instr(code, skeleton[clause_index].clause_start, index_loc);
let target_indexing_line = to_indexing_line_mut(&mut code[target_index_loc]).unwrap();
let target_indexing_line = code[target_index_loc].to_indexing_line_mut().unwrap();
skeleton[clause_index]
.opt_arg_index_key
@@ -210,8 +211,8 @@ fn merge_indices(
fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize {
loop {
match &code[index] {
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(i)))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(i)))
Instruction::DynamicElse(_, _, NextOrFail::Next(i)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(i))
if *i > 0 =>
{
index += i;
@@ -226,15 +227,15 @@ fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize {
fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> usize {
loop {
match &code[index] {
Line::Choice(ChoiceInstruction::TryMeElse(o))
| Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
Instruction::TryMeElse(o) |
Instruction::RetryMeElse(o) => {
if *o > 0 {
return index;
} else {
index = index_loc;
}
}
&Line::Choice(ChoiceInstruction::DynamicElse(_, _, next_or_fail)) => match next_or_fail
&Instruction::DynamicElse(_, _, next_or_fail) => match next_or_fail
{
NextOrFail::Next(i) => {
if i == 0 {
@@ -247,7 +248,7 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
index = index_loc;
}
},
&Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, next_or_fail)) => {
&Instruction::DynamicInternalElse(_, _, next_or_fail) => {
match next_or_fail {
NextOrFail::Next(i) => {
if i == 0 {
@@ -261,20 +262,20 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
}
}
}
Line::Choice(ChoiceInstruction::TrustMe(_)) => {
Instruction::TrustMe(_) => {
return index;
}
Line::IndexingCode(indexing_code) => match &indexing_code[0] {
Instruction::IndexingCode(indexing_code) => match &indexing_code[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => match v {
IndexingCodePtr::External(v) => {
index += v;
}
IndexingCodePtr::DynamicExternal(v) => match &code[index + v] {
&Line::Choice(ChoiceInstruction::DynamicInternalElse(
&Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(0),
)) => {
) => {
return index + v;
}
_ => {
@@ -287,7 +288,7 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
unreachable!();
}
},
Line::Control(ControlInstruction::RevJmpBy(offset)) => {
Instruction::RevJmpBy(offset) => {
index -= offset;
}
_ => {
@@ -310,9 +311,7 @@ fn remove_index_from_subsequence(
) {
if let Some(index_loc) = opt_arg_index_key.switch_on_term_loc() {
let clause_start = find_inner_choice_instr(code, clause_start, index_loc);
let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
let offset = clause_start - index_loc + 1;
remove_index(opt_arg_index_key, target_indexing_line, offset);
@@ -351,7 +350,7 @@ fn merge_indexed_subsequences(
);
match &mut code[inner_try_me_else_loc] {
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
inner_try_me_else_loc,
*o,
@@ -359,15 +358,15 @@ fn merge_indexed_subsequences(
match *o {
0 => {
code[inner_try_me_else_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
code[inner_try_me_else_loc] = Instruction::TrustMe(0);
}
o => match &code[inner_try_me_else_loc + o] {
Line::Control(ControlInstruction::RevJmpBy(0)) => {
code[inner_try_me_else_loc] = Line::Choice(ChoiceInstruction::TrustMe(o));
Instruction::RevJmpBy(0) => {
code[inner_try_me_else_loc] = Instruction::TrustMe(o);
}
_ => {
code[inner_try_me_else_loc] =
Line::Choice(ChoiceInstruction::RetryMeElse(o));
Instruction::RetryMeElse(o);
}
},
}
@@ -403,7 +402,7 @@ fn merge_indexed_subsequences(
);
}
None => match &mut code[outer_threaded_choice_instr_loc] {
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
Instruction::TryMeElse(ref mut o) => {
retraction_info
.push_record(RetractionRecord::ModifiedTryMeElse(inner_trust_me_loc, *o));
@@ -461,60 +460,55 @@ fn blunt_leading_choice_instr(
) -> usize {
loop {
match &mut code[instr_loc] {
Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(instr_loc, *o));
code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(*o));
code[instr_loc] = Instruction::TryMeElse(*o);
return instr_loc;
}
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(_)))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(_))) => {
Instruction::DynamicElse(_, _, NextOrFail::Next(_)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(_)) => {
return instr_loc;
}
&mut Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Fail(o))) => {
&mut Instruction::DynamicElse(b, d, NextOrFail::Fail(o)) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Fail(o),
));
code[instr_loc] =
Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(0)));
code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(0));
return instr_loc;
}
&mut Line::Choice(ChoiceInstruction::DynamicInternalElse(
&mut Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Fail(o),
)) => {
) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Fail(o),
));
code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Next(0),
));
);
return instr_loc;
}
Line::Choice(ChoiceInstruction::TrustMe(o)) => {
retraction_info
.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
Instruction::TrustMe(o) => {
retraction_info.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(0));
code[instr_loc] = Instruction::TryMeElse(0);
return instr_loc + 1;
}
Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
Instruction::TryMeElse(0) => {
return instr_loc + 1;
}
Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
Instruction::TryMeElse(o) => {
instr_loc += *o;
}
Line::Control(ControlInstruction::RevJmpBy(o)) => {
Instruction::RevJmpBy(o) => {
instr_loc -= *o;
}
_ => {
@@ -530,7 +524,7 @@ fn set_switch_var_offset_to_choice_instr(
offset: usize,
retraction_info: &mut RetractionInfo,
) {
let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
let v = match &target_indexing_line[0] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => match v {
@@ -543,9 +537,9 @@ fn set_switch_var_offset_to_choice_instr(
};
match &code[index_loc + v] {
Line::Choice(ChoiceInstruction::TryMeElse(_))
| Line::Choice(ChoiceInstruction::DynamicElse(..))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(..)) => {}
Instruction::TryMeElse(_) |
Instruction::DynamicElse(..) |
Instruction::DynamicInternalElse(..) => {}
_ => {
set_switch_var_offset(code, index_loc, offset, retraction_info);
}
@@ -559,7 +553,7 @@ fn set_switch_var_offset(
offset: usize,
retraction_info: &mut RetractionInfo,
) {
let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
let old_v = match &mut target_indexing_line[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => match *v {
@@ -585,72 +579,67 @@ fn internalize_choice_instr_at(
retraction_info: &mut RetractionInfo,
) {
match &mut code[instr_loc] {
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(_)))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(_))) => {}
Line::Choice(ChoiceInstruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0))) => {
Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => {
}
Instruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0));
*o = NextOrFail::Fail(0);
}
&mut Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(o))) => {
&mut Instruction::DynamicElse(b, d, NextOrFail::Next(o)) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Next(o),
));
match &mut code[instr_loc + o] {
Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => {
code[instr_loc] =
Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Fail(o)));
Instruction::RevJmpBy(p) if *p == 0 => {
code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Fail(o));
}
_ => {
code[instr_loc] =
Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(o)));
code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(o));
}
}
}
Line::Choice(ChoiceInstruction::DynamicInternalElse(
_,
_,
ref mut o @ NextOrFail::Next(0),
)) => {
Instruction::DynamicInternalElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0));
*o = NextOrFail::Fail(0);
}
&mut Line::Choice(ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Next(o))) => {
&mut Instruction::DynamicInternalElse(b, d, NextOrFail::Next(o)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, o));
match &mut code[instr_loc + o] {
Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => {
code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
Instruction::RevJmpBy(p) if *p == 0 => {
code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Fail(o),
));
);
}
_ => {
code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Next(o),
));
);
}
}
}
Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
Instruction::TryMeElse(0) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(instr_loc, 0));
code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
code[instr_loc] = Instruction::TrustMe(0);
}
Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
Instruction::TryMeElse(o) => {
let o = *o;
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(instr_loc, o));
match &mut code[instr_loc + o] {
Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => {
code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(o));
Instruction::RevJmpBy(p) if *p == 0 => {
code[instr_loc] = Instruction::TrustMe(o);
}
_ => {
code[instr_loc] = Line::Choice(ChoiceInstruction::RetryMeElse(o));
code[instr_loc] = Instruction::RetryMeElse(o);
}
}
}
@@ -668,8 +657,7 @@ fn thread_choice_instr_at_to(
) {
loop {
match &mut code[instr_loc] {
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o))
| Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o))
Instruction::TryMeElse(ref mut o) | Instruction::RetryMeElse(ref mut o)
if target_loc >= instr_loc =>
{
retraction_info.push_record(RetractionRecord::ReplacedChoiceOffset(instr_loc, *o));
@@ -677,82 +665,80 @@ fn thread_choice_instr_at_to(
*o = target_loc - instr_loc;
return;
}
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)) |
Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
)) if target_loc >= instr_loc => {
) if target_loc >= instr_loc => {
retraction_info
.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, *o));
*o = target_loc - instr_loc;
return;
}
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(o)))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(o))) => {
Instruction::DynamicElse(_, _, NextOrFail::Next(o)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(o)) => {
instr_loc += *o;
}
Line::Choice(ChoiceInstruction::TryMeElse(o))
| Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
Instruction::TryMeElse(o)
| Instruction::RetryMeElse(o) => {
instr_loc += *o;
}
Line::Control(ControlInstruction::RevJmpBy(ref mut o)) if instr_loc >= target_loc => {
Instruction::RevJmpBy(ref mut o) if instr_loc >= target_loc => {
retraction_info.push_record(RetractionRecord::ModifiedRevJmpBy(instr_loc, *o));
*o = instr_loc - target_loc;
return;
}
&mut Line::Control(ControlInstruction::RevJmpBy(o)) => {
&mut Instruction::RevJmpBy(o) => {
instr_loc -= o;
}
&mut Line::Choice(ChoiceInstruction::DynamicElse(birth, death, ref mut fail))
&mut Instruction::DynamicElse(birth, death, ref mut fail)
if target_loc >= instr_loc =>
{
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicElse(
code[instr_loc] = instr!("dynamic_else",
birth,
death,
NextOrFail::Next(target_loc - instr_loc),
));
NextOrFail::Next(target_loc - instr_loc)
);
return;
}
Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(o))) if *o > 0 => {
Instruction::DynamicElse(_, _, NextOrFail::Fail(o)) if *o > 0 => {
instr_loc += *o;
}
&mut Line::Choice(ChoiceInstruction::DynamicInternalElse(
&mut Instruction::DynamicInternalElse(
birth,
death,
ref mut fail,
)) if target_loc >= instr_loc => {
) if target_loc >= instr_loc => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
code[instr_loc] = instr!("dynamic_internal_else",
birth,
death,
NextOrFail::Next(target_loc - instr_loc),
));
NextOrFail::Next(target_loc - instr_loc)
);
return;
}
Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(o)))
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(o))
if *o > 0 =>
{
instr_loc += *o;
}
Line::Choice(ChoiceInstruction::TrustMe(ref mut o)) if target_loc >= instr_loc => {
Instruction::TrustMe(ref mut o) if target_loc >= instr_loc => {
retraction_info.push_record(
RetractionRecord::AppendedTrustMe(instr_loc, *o, false),
//choice_instr.is_default()),
);
code[instr_loc] =
Line::Choice(ChoiceInstruction::RetryMeElse(target_loc - instr_loc));
code[instr_loc] = instr!("retry_me_else", target_loc - instr_loc);
return;
}
Line::Choice(ChoiceInstruction::TrustMe(o)) if *o > 0 => {
Instruction::TrustMe(o) if *o > 0 => {
instr_loc += *o;
}
_ => {
@@ -769,7 +755,7 @@ fn remove_non_leading_clause(
retraction_info: &mut RetractionInfo,
) -> Option<IndexPtr> {
match &mut code[non_indexed_choice_instr_loc] {
Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) => {
Instruction::RetryMeElse(ref mut o) => {
let o = *o;
thread_choice_instr_at_to(
@@ -781,19 +767,19 @@ fn remove_non_leading_clause(
None
}
Line::Choice(ChoiceInstruction::TrustMe(_)) => {
Instruction::TrustMe(_) => {
match &mut code[preceding_choice_instr_loc] {
Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(
preceding_choice_instr_loc,
*o,
));
code[preceding_choice_instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
code[preceding_choice_instr_loc] = Instruction::TrustMe(0);
None
}
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
preceding_choice_instr_loc,
*o,
@@ -850,7 +836,7 @@ fn remove_leading_unindexed_clause(
retraction_info: &mut RetractionInfo,
) -> Option<IndexPtr> {
match &mut code[non_indexed_choice_instr_loc] {
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
Instruction::TryMeElse(ref mut o) => {
if *o > 0 {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
non_indexed_choice_instr_loc,
@@ -878,7 +864,7 @@ fn remove_leading_unindexed_clause(
fn find_dynamic_outer_choice_instr(code: &Code, index_loc: usize) -> usize {
match &code[index_loc] {
Line::IndexingCode(indexing_code) => match &indexing_code[0] {
Instruction::IndexingCode(indexing_code) => match &indexing_code[0] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_,
IndexingCodePtr::DynamicExternal(v),
@@ -951,22 +937,16 @@ fn prepend_compiled_clause(
let inner_thread_rev_offset =
3 + prepend_queue.len() + clause_loc - skeleton.clauses[1].clause_start;
prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
inner_thread_rev_offset,
)));
prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
prepend_queue.push_front(Line::Choice(
settings.internal_try_me_else(prepend_queue.len()),
));
prepend_queue.push_front(settings.internal_try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse N_2
// | (clause_code)
// +N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1)
prepend_queue.push_front(Line::Control(ControlInstruction::RevJmpBy(
1 + clause_loc - index_loc,
)));
prepend_queue.push_front(Instruction::RevJmpBy(1 + clause_loc - index_loc));
let outer_thread_choice_offset = // outer_thread_choice_loc WAS index_loc - 1..
match derelictize_try_me_else(code, outer_thread_choice_loc, retraction_info) {
@@ -978,7 +958,7 @@ fn prepend_compiled_clause(
next_subseq_offset;
prepend_queue.push_back(
Line::Control(ControlInstruction::RevJmpBy(outer_thread_rev_offset))
Instruction::RevJmpBy(outer_thread_rev_offset)
);
prepend_queue.len()
@@ -994,17 +974,13 @@ fn prepend_compiled_clause(
// awaiting the addition of unindexed
// clauses.
prepend_queue.push_back(
Line::Control(ControlInstruction::RevJmpBy(0)),
);
prepend_queue.push_back(Instruction::RevJmpBy(0));
0
}
};
prepend_queue.push_front(Line::Choice(
settings.try_me_else(outer_thread_choice_offset),
));
prepend_queue.push_front(settings.try_me_else(outer_thread_choice_offset));
// prepend_queue is now:
// | TryMeElse N_3
@@ -1014,7 +990,7 @@ fn prepend_compiled_clause(
// N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1)
// N_3 | RevJmpBy (TryMeElse(N_1) at index_loc - 1 or TrustMe if N_1 == 0)
let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
merge_clause_index(
target_indexing_line,
@@ -1060,19 +1036,19 @@ fn prepend_compiled_clause(
// this is a stub for chaining inner-threaded choice
// instructions.
prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(0)));
prepend_queue.push_back(Instruction::RevJmpBy(0));
let prepend_queue_len = prepend_queue.len();
match &mut prepend_queue[1] {
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) if *o == 0 => {
Instruction::TryMeElse(ref mut o) if *o == 0 => {
*o = prepend_queue_len - 2;
}
Line::Choice(ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
_,
_,
ref mut o @ NextOrFail::Next(0),
)) => {
) => {
*o = NextOrFail::Fail(prepend_queue_len - 2);
}
_ => {
@@ -1080,11 +1056,8 @@ fn prepend_compiled_clause(
}
}
prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
inner_thread_rev_offset,
)));
prepend_queue.push_front(Line::Choice(settings.try_me_else(prepend_queue.len())));
prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
prepend_queue.push_front(settings.try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse(N_2)
@@ -1114,11 +1087,8 @@ fn prepend_compiled_clause(
let inner_thread_rev_offset =
1 + prepend_queue.len() + clause_loc - old_clause_start;
prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
inner_thread_rev_offset,
)));
prepend_queue.push_front(Line::Choice(settings.try_me_else(prepend_queue.len())));
prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
prepend_queue.push_front(settings.try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse(N_2)
@@ -1142,11 +1112,8 @@ fn prepend_compiled_clause(
let inner_thread_rev_offset =
1 + prepend_queue.len() + clause_loc - old_clause_start;
prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
inner_thread_rev_offset,
)));
prepend_queue.push_front(Line::Choice(settings.try_me_else(prepend_queue.len())));
prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
prepend_queue.push_front(settings.try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse(N_2)
@@ -1205,7 +1172,7 @@ fn append_compiled_clause(
.switch_on_term_loc()
{
Some(index_loc) if lower_bound_arg_num == target_arg_num => {
code.push(Line::Choice(settings.internal_trust_me()));
code.push(settings.internal_trust_me());
code.extend(clause_code.drain(3..)); // skip the indexing code
@@ -1218,7 +1185,7 @@ fn append_compiled_clause(
skeleton.clauses[target_pos].clause_start,
));
let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
merge_clause_index(
target_indexing_line,
@@ -1252,7 +1219,7 @@ fn append_compiled_clause(
target_pos_clause_start // skeleton.clauses[target_pos - 1].clause_start
}
_ => {
code.push(Line::Choice(settings.trust_me()));
code.push(settings.trust_me());
skeleton.clauses[target_pos].opt_arg_index_key += clause_loc;
code.extend(clause_code.drain(1..));
@@ -1331,9 +1298,9 @@ fn print_overwrite_warning(
key: &PredicateKey,
is_dynamic: bool,
) {
if let CompilationTarget::Module(ref module_name) = compilation_target {
match module_name.as_str() {
"builtins" | "loader" => return,
if let CompilationTarget::Module(module_name) = compilation_target {
match module_name {
atom!("builtins") | atom!("loader") => return,
_ => {}
}
}
@@ -1405,7 +1372,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
) -> Result<CodeIndex, SessionError> {
let code_index = self.get_or_insert_code_index(key, predicates.compilation_target);
let code_len = self.wam_prelude.code_repo.code.len();
let code_len = self.wam_prelude.code.len();
let mut code_ptr = code_len;
let mut clauses = vec![];
@@ -1443,7 +1410,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
match &mut code[0] {
Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
Instruction::TryMeElse(0) => {
code_ptr += 1;
}
_ => {}
@@ -1514,7 +1481,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
index_ptr,
);
self.wam_prelude.code_repo.code.extend(code.into_iter());
self.wam_prelude.code.extend(code.into_iter());
Ok(code_index)
}
@@ -1690,7 +1657,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
mut standalone_skeleton,
} = self.compile_standalone_clause(clause, settings)?;
let code_len = self.wam_prelude.code_repo.code.len();
let code_len = self.wam_prelude.code.len();
let skeleton = match self
.wam_prelude
@@ -1717,7 +1684,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let global_clock = LS::machine_st(&mut self.payload).global_clock;
let result = append_compiled_clause(
&mut self.wam_prelude.code_repo.code,
&mut self.wam_prelude.code,
clause_code,
skeleton,
&mut self.payload.retraction_info,
@@ -1757,7 +1724,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let global_clock = LS::machine_st(&mut self.payload).global_clock;
let new_code_ptr = prepend_compiled_clause(
&mut self.wam_prelude.code_repo.code,
&mut self.wam_prelude.code,
compilation_target,
key,
clause_code,
@@ -1801,16 +1768,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.switch_on_term_loc()
{
Some(index_loc) => find_inner_choice_instr(
&self.wam_prelude.code_repo.code,
&self.wam_prelude.code,
skeleton.clauses[target_pos].clause_start,
index_loc,
),
None => skeleton.clauses[target_pos].clause_start,
};
match &mut self.wam_prelude.code_repo.code[clause_loc] {
Line::Choice(ChoiceInstruction::DynamicElse(_, ref mut d, _))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(_, ref mut d, _)) => {
match &mut self.wam_prelude.code[clause_loc] {
Instruction::DynamicElse(_, ref mut d, _) |
Instruction::DynamicInternalElse(_, ref mut d, _) => {
*d = Death::Finite(LS::machine_st(&mut self.payload).global_clock);
}
_ => unreachable!(),
@@ -1840,7 +1807,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
};
let code = &mut self.wam_prelude.code_repo.code;
let code = &mut self.wam_prelude.code;
let lower_bound = lower_bound_of_target_clause(skeleton, target_pos);
let lower_bound_is_unindexed = !skeleton.clauses[lower_bound].opt_arg_index_key.is_some();
@@ -1975,13 +1942,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
Some(later_indexing_loc) if later_indexing_loc < target_indexing_loc => {
let target_indexing_line = mem::replace(
&mut code[target_indexing_loc],
Line::Control(ControlInstruction::RevJmpBy(
target_indexing_loc - later_indexing_loc,
)),
Instruction::RevJmpBy(target_indexing_loc - later_indexing_loc),
);
match target_indexing_line {
Line::IndexingCode(indexing_code) => {
Instruction::IndexingCode(indexing_code) => {
self.payload.retraction_info.push_record(
RetractionRecord::ReplacedIndexingLine(
target_indexing_loc,
@@ -2073,7 +2038,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
);
match &mut code[preceding_choice_instr_loc] {
Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
Instruction::TryMeElse(0) => {
set_switch_var_offset(
code,
index_loc,

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@ use crate::types::*;
use core::marker::PhantomData;
// TODO: rename to 'unmark_if_iter', 'mark_if_gc'
pub(crate) trait UnmarkPolicy {
fn unmark(heap: &mut [HeapCellValue], current: usize) -> bool;
fn mark(heap: &mut [HeapCellValue], current: usize);

View File

@@ -1,7 +1,6 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
use crate::machine::machine_indices::*;
use crate::machine::partial_string::*;
use crate::parser::ast::*;
use crate::types::*;
@@ -251,7 +250,7 @@ where
filtered_iter_to_heap_list(heap, values, |_, _| true)
}
pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<LocalCodePtr> {
pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<usize> {
let extract_integer = |s: usize| -> Option<usize> {
match Number::try_from(heap[s]) {
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
@@ -265,7 +264,7 @@ pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<Loca
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
if name == atom!("dir_entry") && arity == 1 {
extract_integer(s+1).map(LocalCodePtr::DirEntry)
extract_integer(s+1)
} else {
panic!(
"to_local_code_ptr crashed with p.i. {}/{}",
@@ -279,182 +278,3 @@ pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<Loca
}
)
}
/*
impl<T: RawBlockTraits> HeapTemplate<T> {
#[inline]
pub(crate) fn new() -> Self {
HeapTemplate {
buf: RawBlock::new(),
_marker: PhantomData,
}
}
/*
// TODO: move this to the WAM, then remove the temporary (and by
// then, unnecessary and impossible) "arena" argument. OR, remove
// this thing totally! if we can. by that I mean, just convert a
// little to a HeapCellValue. don't bother writing to the
// heap at all. Each of these data is either already inlinable in a
// HeapCellValue or a pointer to an GC'ed location in memory.
#[inline]
pub(crate) fn put_literal(&mut self, literal: Literal) -> HeapCellValue {
match literal {
Literal::Atom(name) => atom_as_cell!(name),
Literal::Char(c) => char_as_cell!(c),
Literal::EmptyList => empty_list_as_cell!(),
Literal::Fixnum(n) => fixnum_as_cell!(n),
Literal::Integer(bigint_ptr) => {
let h = self.push(typed_arena_ptr_as_cell!(bigint_ptr));
self[h]
}
Literal::Rational(bigint_ptr) => {
let h = self.push(typed_arena_ptr_as_cell!(bigint_ptr));
self[h]
}
Literal::Float(f) => typed_arena_ptr_as_cell!(f),
Literal::String(s) => {
if s.as_str().is_empty() {
empty_list_as_cell!()
} else {
// TODO: how do we know where the tail is located?? well, there is no tail. separate tag?
untyped_arena_ptr_as_cell!(s) // self.put_complete_string(arena, &s)
}
} // Literal::Usize(n) => Addr::Usize(n),
}
}
*/
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.h() == 0
}
#[inline]
pub(crate) fn pop(&mut self) {
let h = self.h();
if h > 0 {
self.truncate(h - 1);
}
}
#[inline]
pub(crate) fn push(&mut self, val: HeapCellValue) -> usize {
let h = self.h();
unsafe {
let new_ptr = self.buf.alloc(mem::size_of::<HeapCellValue>());
ptr::write(new_ptr as *mut _, val);
}
h
}
/*
#[inline]
pub(crate) fn atom_at(&self, h: usize) -> bool {
if let HeapCellValue::Atom(..) = &self[h] {
true
} else {
false
}
}
#[inline]
pub(crate) fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr {
match non_heap_value {
HeapCellValue::Addr(addr) => addr,
val @ HeapCellValue::Atom(..)
| val @ HeapCellValue::Integer(_)
| val @ HeapCellValue::DBRef(_)
| val @ HeapCellValue::Rational(_) => Addr::Con(self.push(val)),
val @ HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(self.push(val)),
val @ HeapCellValue::NamedStr(..) => Addr::Str(self.push(val)),
HeapCellValue::PartialString(pstr, has_tail) => {
let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
if has_tail {
self.push(HeapCellValue::Addr(Addr::EmptyList));
}
Addr::Con(h)
}
val @ HeapCellValue::Stream(..) => Addr::Stream(self.push(val)),
val @ HeapCellValue::TcpListener(..) => Addr::TcpListener(self.push(val)),
}
}
*/
#[inline]
pub(crate) fn truncate(&mut self, h: usize) {
let new_ptr = self.buf.top as usize - h * mem::size_of::<HeapCellValue>();
self.buf.ptr = new_ptr as *mut _;
}
#[inline]
pub(crate) fn h(&self) -> usize {
(self.buf.top as usize - self.buf.ptr as usize) / mem::size_of::<HeapCellValue>()
}
pub(crate) fn append(&mut self, vals: Vec<HeapCellValue>) {
for val in vals {
self.push(val);
}
}
pub(crate) fn clear(&mut self) {
if !self.buf.base.is_null() {
self.truncate(0);
self.buf.top = self.buf.base;
}
}
/* TODO: get rid of this!!
#[inline]
pub(crate) fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
match addr {
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => {
RefOrOwned::Borrowed(&self[h])
}
addr => RefOrOwned::Owned(HeapCellValue::Addr(*addr)),
}
}
*/
}
impl<T: RawBlockTraits> Index<u64> for HeapTemplate<T> {
type Output = HeapCellValue;
#[inline]
fn index(&self, index: u64) -> &Self::Output {
unsafe {
let ptr =
self.buf.top as usize - (index as usize + 1) * mem::size_of::<HeapCellValue>();
&*(ptr as *const HeapCellValue)
}
}
}
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
type Output = HeapCellValue;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
unsafe {
let ptr = self.buf.top as usize - (index + 1) * mem::size_of::<HeapCellValue>();
&*(ptr as *const HeapCellValue)
}
}
}
impl<T: RawBlockTraits> IndexMut<usize> for HeapTemplate<T> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe {
let ptr = self.buf.top as usize - (index + 1) * mem::size_of::<HeapCellValue>();
&mut *(ptr as *mut HeapCellValue)
}
}
}
*/

View File

@@ -1,4 +1,3 @@
use crate::clause_types::*;
use crate::forms::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
@@ -8,6 +7,7 @@ use crate::machine::term_stream::*;
use crate::machine::*;
use crate::parser::ast::*;
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use ref_thread_local::RefThreadLocal;
use slice_deque::{sdeq, SliceDeque};
@@ -753,7 +753,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
pub(super) fn get_clause_type(&mut self, name: Atom, arity: usize) -> ClauseType {
match ClauseType::from(name, arity) {
ClauseType::Named(name, arity, _) => {
ClauseType::Named(arity, name, _) => {
let payload_compilation_target = self.payload.compilation_target;
let idx = self.get_or_insert_code_index(
@@ -761,7 +761,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
payload_compilation_target,
);
ClauseType::Named(name, arity, idx)
ClauseType::Named(arity, name, idx)
}
ct => ct,
}
@@ -774,11 +774,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
arity: usize,
) -> ClauseType {
match ClauseType::from(name, arity) {
ClauseType::Named(name, arity, _) => {
ClauseType::Named(arity, name, _) => {
let key = (name, arity);
let idx = self.get_or_insert_qualified_code_index(module_name, key);
ClauseType::Named(name, arity, idx)
ClauseType::Named(arity, name, idx)
}
ct => ct,
}
@@ -922,7 +922,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let local_extensible_predicates = mem::replace(
&mut module.local_extensible_predicates,
LocalExtensiblePredicates::new(),
LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()),
);
for ((compilation_target, key), skeleton) in local_extensible_predicates.iter() {
@@ -1162,11 +1162,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState(
LoadStatePayload::new(self.wam_prelude.code_repo.code.len(), term_stream)
LoadStatePayload::new(self.wam_prelude.code.len(), term_stream)
),
wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices,
code_repo: self.wam_prelude.code_repo,
code: self.wam_prelude.code,
load_contexts: self.wam_prelude.load_contexts,
}
};
@@ -1225,11 +1225,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState(
LoadStatePayload::new(self.wam_prelude.code_repo.code.len(), term_stream),
LoadStatePayload::new(self.wam_prelude.code.len(), term_stream),
),
wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices,
code_repo: self.wam_prelude.code_repo,
code: self.wam_prelude.code,
load_contexts: self.wam_prelude.load_contexts,
}
};

View File

@@ -1,6 +1,5 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::indexing::*;
@@ -327,7 +326,7 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
loader.compile_and_submit()?;
}
let repo_len = loader.wam_prelude.code_repo.code.len();
let repo_len = loader.wam_prelude.code.len();
loader
.payload
@@ -363,7 +362,7 @@ pub struct Loader<'a, LS: LoadState<'a>> {
impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
#[inline]
pub(super) fn new(wam: &'a mut Machine, term_stream: <LS as LoadState<'a>>::TS) -> Self {
let payload = LoadStatePayload::new(wam.code_repo.code.len(), term_stream);
let payload = LoadStatePayload::new(wam.code.len(), term_stream);
let (wam_prelude, machine_st) = wam.prelude_view_and_machine_st();
Self {
@@ -696,8 +695,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::AddedIndex(index_key, clause_loc) => {
// WAS: inner_index_locs) => {
if let Some(index_loc) = index_key.switch_on_term_loc() {
let indexing_code = match &mut self.wam_prelude.code_repo.code[index_loc] {
Line::IndexingCode(indexing_code) => indexing_code,
let indexing_code = match &mut self.wam_prelude.code[index_loc] {
Instruction::IndexingCode(indexing_code) => indexing_code,
_ => {
unreachable!()
}
@@ -743,10 +742,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
// write the retraction logic of this arm.
}
RetractionRecord::ReplacedChoiceOffset(instr_loc, offset) => {
match self.wam_prelude.code_repo.code[instr_loc] {
Line::Choice(ChoiceInstruction::TryMeElse(ref mut o))
| Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o))
| Line::Choice(ChoiceInstruction::DefaultRetryMeElse(ref mut o)) => {
match self.wam_prelude.code[instr_loc] {
Instruction::TryMeElse(ref mut o) |
Instruction::RetryMeElse(ref mut o) |
Instruction::DefaultRetryMeElse(ref mut o) => {
*o = offset;
}
_ => {
@@ -755,22 +754,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
RetractionRecord::AppendedTrustMe(instr_loc, offset, is_default) => {
match self.wam_prelude.code_repo.code[instr_loc] {
Line::Choice(ref mut choice_instr) => {
*choice_instr = if is_default {
ChoiceInstruction::DefaultTrustMe(offset)
self.wam_prelude.code[instr_loc] = if is_default {
Instruction::DefaultTrustMe(offset)
} else {
ChoiceInstruction::TrustMe(offset)
Instruction::TrustMe(offset)
};
}
_ => {
unreachable!();
}
}
}
RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v) => {
match self.wam_prelude.code_repo.code[index_loc] {
Line::IndexingCode(ref mut indexing_code) => match &mut indexing_code[0] {
match self.wam_prelude.code[index_loc] {
Instruction::IndexingCode(ref mut indexing_code) => match &mut indexing_code[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_,
ref mut v,
@@ -784,16 +776,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
RetractionRecord::ModifiedTryMeElse(instr_loc, o) => {
self.wam_prelude.code_repo.code[instr_loc] =
Line::Choice(ChoiceInstruction::TryMeElse(o));
self.wam_prelude.code[instr_loc] = Instruction::TryMeElse(o);
}
RetractionRecord::ModifiedRetryMeElse(instr_loc, o) => {
self.wam_prelude.code_repo.code[instr_loc] =
Line::Choice(ChoiceInstruction::RetryMeElse(o));
self.wam_prelude.code[instr_loc] = Instruction::RetryMeElse(o);
}
RetractionRecord::ModifiedRevJmpBy(instr_loc, o) => {
self.wam_prelude.code_repo.code[instr_loc] =
Line::Control(ControlInstruction::RevJmpBy(o));
self.wam_prelude.code[instr_loc] = Instruction::RevJmpBy(o);
}
RetractionRecord::SkeletonClausePopBack(compilation_target, key) => {
match self
@@ -959,7 +948,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
RetractionRecord::ReplacedIndexingLine(index_loc, indexing_code) => {
self.wam_prelude.code_repo.code[index_loc] = Line::IndexingCode(indexing_code);
self.wam_prelude.code[index_loc] = Instruction::IndexingCode(indexing_code);
}
RetractionRecord::RemovedLocalSkeletonClauseLocations(
compilation_target,
@@ -992,34 +981,34 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
RetractionRecord::ReplacedDynamicElseOffset(instr_loc, next) => {
match self.wam_prelude.code_repo.code[instr_loc] {
Line::Choice(ChoiceInstruction::DynamicElse(
match self.wam_prelude.code[instr_loc] {
Instruction::DynamicElse(
_,
_,
NextOrFail::Next(ref mut o),
))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(
)
| Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
)) => {
) => {
*o = next;
}
_ => {}
}
}
RetractionRecord::AppendedNextOrFail(instr_loc, fail) => {
match self.wam_prelude.code_repo.code[instr_loc] {
Line::Choice(ChoiceInstruction::DynamicElse(
match self.wam_prelude.code[instr_loc] {
Instruction::DynamicElse(
_,
_,
ref mut next_or_fail,
))
| Line::Choice(ChoiceInstruction::DynamicInternalElse(
)
| Instruction::DynamicInternalElse(
_,
_,
ref mut next_or_fail,
)) => {
) => {
*next_or_fail = fail;
}
_ => {}
@@ -1384,7 +1373,7 @@ impl<'a> MachinePreludeView<'a> {
}
impl Machine {
pub(crate) fn use_module(&mut self) {
pub(crate) fn use_module(&mut self) -> CallResult {
let subevacuable_addr = self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[2]));
@@ -1395,7 +1384,7 @@ impl Machine {
match payload.compilation_target {
CompilationTarget::Module(module_name) => module_name,
CompilationTarget::User => {
return;
return Ok(());
}
}
});
@@ -1415,10 +1404,10 @@ impl Machine {
};
let result = use_module();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn load_compiled_library(&mut self) {
pub(crate) fn load_compiled_library(&mut self) -> CallResult {
let library = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -1426,7 +1415,7 @@ impl Machine {
if let Some(module) = self.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = module.listing_src {
self.machine_st.fail = true;
return;
return Ok(());
}
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1444,13 +1433,14 @@ impl Machine {
};
let result = import_module();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
} else {
self.machine_st.fail = true;
Ok(())
}
}
pub(crate) fn declare_module(&mut self) {
pub(crate) fn declare_module(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -1471,34 +1461,34 @@ impl Machine {
};
let result = declare_module();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
#[inline]
pub(crate) fn add_discontiguous_predicate(&mut self) {
pub(crate) fn add_discontiguous_predicate(&mut self) -> CallResult {
self.add_extensible_predicate_declaration(
|loader, compilation_target, clause_name, arity| {
loader.add_discontiguous_predicate(compilation_target, clause_name, arity)
},
);
)
}
#[inline]
pub(crate) fn add_dynamic_predicate(&mut self) {
pub(crate) fn add_dynamic_predicate(&mut self) -> CallResult {
self.add_extensible_predicate_declaration(
|loader, compilation_target, clause_name, arity| {
loader.add_dynamic_predicate(compilation_target, clause_name, arity)
},
);
)
}
#[inline]
pub(crate) fn add_multifile_predicate(&mut self) {
pub(crate) fn add_multifile_predicate(&mut self) -> CallResult {
self.add_extensible_predicate_declaration(
|loader, compilation_target, clause_name, arity| {
loader.add_multifile_predicate(compilation_target, clause_name, arity)
},
);
)
}
fn add_extensible_predicate_declaration(
@@ -1509,7 +1499,7 @@ impl Machine {
Atom,
usize,
) -> Result<(), SessionError>,
) {
) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -1543,10 +1533,10 @@ impl Machine {
};
let result = add_predicate_decl();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn add_term_expansion_clause(&mut self) {
pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
let add_clause = || {
@@ -1564,10 +1554,10 @@ impl Machine {
};
let result = add_clause();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn add_goal_expansion_clause(&mut self) {
pub(crate) fn add_goal_expansion_clause(&mut self) -> CallResult {
let target_module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -1594,10 +1584,10 @@ impl Machine {
};
let result = add_clause();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn add_in_situ_filename_module(&mut self) {
pub(crate) fn add_in_situ_filename_module(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(1));
let add_in_situ_filename_module = || {
@@ -1643,7 +1633,7 @@ impl Machine {
};
let result = add_in_situ_filename_module();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn loader_from_heap_evacuable<'a>(
@@ -1668,15 +1658,13 @@ impl Machine {
pub(crate) fn push_load_state_payload(&mut self) {
let payload = arena_alloc!(
LoadStatePayload::new(
self.code_repo.code.len(),
self.code.len(),
LiveTermStream::new(ListingSource::User),
),
&mut self.machine_st.arena
);
let var = self.machine_st.deref(
self.machine_st.registers[1]
);
let var = self.machine_st.deref(self.machine_st.registers[1]);
self.machine_st.bind(
var.as_var().unwrap(),
@@ -1718,38 +1706,40 @@ impl Machine {
self.load_contexts.pop();
}
pub(crate) fn push_load_context(&mut self) {
let stream = try_or_fail!(
self.machine_st,
self.machine_st.get_stream_or_alias(
pub(crate) fn push_load_context(&mut self) -> CallResult {
let stream = self.machine_st.get_stream_or_alias(
self.machine_st.registers[1],
&self.indices.stream_aliases,
atom!("$push_load_context"),
2,
)
);
)?;
let path = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
);
self.load_contexts.push(LoadContext::new(path.as_str(), stream));
Ok(())
}
pub(crate) fn restore_load_state_payload(
&mut self,
result: Result<TypedArenaPtr<LiveLoadState>, SessionError>,
) {
) -> CallResult {
match result {
Ok(_payload) => {
Ok(())
}
Err(e) => {
self.throw_session_error(e, (atom!("load"), 1));
let err = self.machine_st.session_error(e);
let stub = functor_stub(atom!("load"), 1);
Err(self.machine_st.error_form(err, stub))
}
}
}
pub(crate) fn scoped_clause_to_evacuable(&mut self) {
pub(crate) fn scoped_clause_to_evacuable(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -1762,18 +1752,18 @@ impl Machine {
};
let result = loader.read_and_enqueue_term(temp_v!(2), compilation_target);
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn clause_to_evacuable(&mut self) {
pub(crate) fn clause_to_evacuable(&mut self) -> CallResult {
let loader = self.loader_from_heap_evacuable(temp_v!(2));
let compilation_target = loader.payload.compilation_target;
let result = loader.read_and_enqueue_term(temp_v!(1), compilation_target);
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn conclude_load(&mut self) {
pub(crate) fn conclude_load(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(1));
let compile_final_terms = || {
@@ -1786,7 +1776,7 @@ impl Machine {
};
let result = compile_final_terms();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn load_context_source(&mut self) {
@@ -1852,7 +1842,7 @@ impl Machine {
}
}
pub(crate) fn compile_assert<'a>(&'a mut self, append_or_prepend: AppendOrPrepend) {
pub(crate) fn compile_assert<'a>(&'a mut self, append_or_prepend: AppendOrPrepend) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(3)], self.machine_st[temp_v!(4)]);
@@ -1906,26 +1896,27 @@ impl Machine {
};
match compile_assert() {
Ok(_) => {}
Ok(_) => Ok(()),
Err(e) => {
let error_pi = match append_or_prepend {
AppendOrPrepend::Append => (atom!("assertz"), 1),
AppendOrPrepend::Prepend => (atom!("asserta"), 1),
let stub = match append_or_prepend {
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
};
let err = self.machine_st.session_error(e);
self.throw_session_error(e, error_pi);
Err(self.machine_st.error_form(err, stub))
}
}
}
pub(crate) fn abolish_clause(&mut self) {
pub(crate) fn abolish_clause(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]);
.read_predicate_key(self.machine_st.registers[2], self.machine_st.registers[3]);
let compilation_target = match module_name {
atom!("user") => CompilationTarget::User,
@@ -2000,14 +1991,16 @@ impl Machine {
};
match abolish_clause() {
Ok(_) => {}
Ok(_) => Ok(()),
Err(e) => {
self.throw_session_error(e, (atom!("abolish"), 1));
let stub = functor_stub(atom!("abolish"), 1);
let err = self.machine_st.session_error(e);
Err(self.machine_st.error_form(err, stub))
}
}
}
pub(crate) fn retract_clause(&mut self) {
pub(crate) fn retract_clause(&mut self) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)]);
@@ -2066,14 +2059,17 @@ impl Machine {
};
match retract_clause() {
Ok(_) => {}
Ok(_) => Ok(()),
Err(e) => {
self.throw_session_error(e, (atom!("retract"), 1));
let stub = functor_stub(atom!("retract"), 1);
let err = self.machine_st.session_error(e);
Err(self.machine_st.error_form(err, stub))
}
}
}
pub(crate) fn is_consistent_with_term_queue(&mut self) {
pub(crate) fn is_consistent_with_term_queue(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -2095,10 +2091,10 @@ impl Machine {
|| !key.is_consistent(&loader.payload.predicates);
let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn flush_term_queue(&mut self) {
pub(crate) fn flush_term_queue(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(1));
let flush_term_queue = || {
@@ -2110,10 +2106,10 @@ impl Machine {
};
let result = flush_term_queue();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn remove_module_exports(&mut self) {
pub(crate) fn remove_module_exports(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
@@ -2126,10 +2122,10 @@ impl Machine {
};
let result = remove_module_exports();
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn add_non_counted_backtracking(&mut self) {
pub(crate) fn add_non_counted_backtracking(&mut self) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)]);
@@ -2138,7 +2134,7 @@ impl Machine {
loader.payload.non_counted_bt_preds.insert(key);
let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result);
self.restore_load_state_payload(result)
}
pub(crate) fn meta_predicate_property(&mut self) {
@@ -2271,10 +2267,10 @@ impl Machine {
.read_predicate_key(self.machine_st.registers[1], self.machine_st.registers[2]);
match ClauseType::from(key.0, key.1) {
ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN => {
ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN(_) => {
return;
}
ClauseType::Named(name, arity, _) => {
ClauseType::Named(arity, name, _) => {
if let Some(module) = self.indices.modules.get(&(atom!("builtins"))) {
self.machine_st.fail = !module.code_dir.contains_key(&(name, arity));
return;

View File

@@ -538,13 +538,18 @@ impl MachineState {
pub(super) fn throw_exception(&mut self, err: MachineStub) {
let h = self.heap.len();
let err_len = err.len();
self.ball.boundary = 0;
self.ball.stub.truncate(0);
self.heap.extend(err.into_iter());
self.registers[1] = str_loc_as_cell!(h);
self.registers[1] = if err_len == 1 {
heap_loc_as_cell!(h)
} else {
str_loc_as_cell!(h)
};
self.set_ball();
self.unwind_stack();

View File

@@ -2,30 +2,22 @@ use crate::parser::ast::*;
use crate::arena::*;
use crate::atom_table::*;
use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::*;
use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::MachineStub;
use crate::machine::machine_state::*;
use crate::machine::streams::Stream;
use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
use std::ops::Deref;
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::*;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
@@ -134,6 +126,7 @@ impl Default for CodeIndex {
}
}
/*
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr {
AddDiscontiguousPredicate,
@@ -174,156 +167,28 @@ pub enum REPLCodePtr {
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CodePtr {
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
CallN(usize, LocalCodePtr, bool), // arity, local, last call.
Local(LocalCodePtr),
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
BuiltInClause(BuiltInClauseType, usize), // local is the successor call.
CallN(usize, usize, bool), // arity, local, last call.
Local(usize),
REPL(REPLCodePtr, usize), // the REPL code, the return pointer.
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
}
impl CodePtr {
pub(crate) fn local(&self) -> LocalCodePtr {
pub(crate) fn local(&self) -> usize {
match self {
&CodePtr::BuiltInClause(_, ref local)
| &CodePtr::CallN(_, ref local, _)
| &CodePtr::Local(ref local) => local.clone(),
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
&CodePtr::REPL(_, p) => p, // | &CodePtr::DynamicTransaction(_, p) => p,
&CodePtr::BuiltInClause(_, ref local) |
&CodePtr::CallN(_, ref local, _) |
&CodePtr::Local(ref local) => *local,
&CodePtr::VerifyAttrInterrupt(p) => p,
&CodePtr::REPL(_, p) => p,
}
}
#[inline]
pub(crate) fn is_halt(&self) -> bool {
if let CodePtr::Local(LocalCodePtr::Halt) = self {
true
} else {
false
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum LocalCodePtr {
DirEntry(usize), // offset
Halt,
// IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset
// TopLevel(usize, usize), // chunk_num, offset
}
impl Machine {
pub(crate) fn is_reset_cont_marker(&self, p: LocalCodePtr) -> bool {
match self.code_repo.lookup_instr(&self.machine_st, &CodePtr::Local(p)) {
Some(line) => match line.as_ref(&self.code_repo.code) {
Line::Control(ControlInstruction::CallClause(ref ct, ..)) => {
if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct {
return true;
}
}
pub fn assign_if_local(&self, cp: &mut usize) {
match self {
CodePtr::Local(local) => *cp = *local,
_ => {}
},
None => {}
}
false
}
}
impl LocalCodePtr {
pub fn assign_if_local(&mut self, cp: CodePtr) {
match cp {
CodePtr::Local(local) => *self = local,
_ => {}
}
}
#[inline]
pub fn abs_loc(&self) -> usize {
match self {
LocalCodePtr::DirEntry(ref p) => *p,
// LocalCodePtr::IndexingBuf(ref p, ..) => *p,
LocalCodePtr::Halt => unreachable!(),
}
}
pub(crate) fn as_functor(&self) -> MachineStub {
match self {
LocalCodePtr::DirEntry(p) => {
functor!(atom!("dir_entry"), [fixnum(*p)])
}
LocalCodePtr::Halt => {
functor!(atom!("halt"))
}
/*
LocalCodePtr::IndexingBuf(p, o, i) => {
functor!(
atom!("indexed_buf"),
[fixnum(*p), fixnum(*o), fixnum(*i)]
)
}
*/
}
}
}
impl Default for CodePtr {
#[inline]
fn default() -> Self {
CodePtr::Local(LocalCodePtr::default())
}
}
impl Default for LocalCodePtr {
#[inline]
fn default() -> Self {
LocalCodePtr::DirEntry(0)
}
}
impl Add<usize> for LocalCodePtr {
type Output = LocalCodePtr;
#[inline]
fn add(self, rhs: usize) -> Self::Output {
match self {
LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs),
LocalCodePtr::Halt => unreachable!(),
// LocalCodePtr::IndexingBuf(p, o, i) => LocalCodePtr::IndexingBuf(p, o, i + rhs),
}
}
}
impl Sub<usize> for LocalCodePtr {
type Output = Option<LocalCodePtr>;
#[inline]
fn sub(self, rhs: usize) -> Self::Output {
match self {
LocalCodePtr::DirEntry(p) => p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
LocalCodePtr::Halt => unreachable!(),
// LocalCodePtr::IndexingBuf(p, o, i) => i
// .checked_sub(rhs)
// .map(|r| LocalCodePtr::IndexingBuf(p, o, r)),
}
}
}
impl SubAssign<usize> for LocalCodePtr {
#[inline]
fn sub_assign(&mut self, rhs: usize) {
match self {
LocalCodePtr::DirEntry(ref mut p) => *p -= rhs,
LocalCodePtr::Halt => unreachable!() // | LocalCodePtr::IndexingBuf(..) => unreachable!(),
}
}
}
impl AddAssign<usize> for LocalCodePtr {
#[inline]
fn add_assign(&mut self, rhs: usize) {
match self {
&mut LocalCodePtr::DirEntry(ref mut i) => *i += rhs,
// | &mut LocalCodePtr::IndexingBuf(_, _, ref mut i) => *i += rhs,
&mut LocalCodePtr::Halt => unreachable!(),
}
}
}
@@ -333,7 +198,9 @@ impl Add<usize> for CodePtr {
fn add(self, rhs: usize) -> Self::Output {
match self {
p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => p,
p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => {
p
}
CodePtr::Local(local) => CodePtr::Local(local + rhs),
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
CodePtr::Local(local + rhs)
@@ -362,20 +229,30 @@ impl SubAssign<usize> for CodePtr {
}
}
pub(crate) type HeapVarDict = IndexMap<Rc<String>, HeapCellValue>;
pub(crate) type AllocVarDict = IndexMap<Rc<String>, VarData>;
impl Default for CodePtr {
#[inline]
fn default() -> Self {
CodePtr::Local(0)
}
}
*/
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>)>;
pub(crate) type HeapVarDict = IndexMap<Rc<String>, HeapCellValue, FxBuildHasher>;
pub(crate) type AllocVarDict = IndexMap<Rc<String>, VarData, FxBuildHasher>;
pub(crate) type StreamAliasDir = IndexMap<Atom, Stream>;
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;
pub(crate) type StreamAliasDir = IndexMap<Atom, Stream, FxBuildHasher>;
pub(crate) type StreamDir = BTreeSet<Stream>;
pub(crate) type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>>;
pub(crate) type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>, FxBuildHasher>;
pub(crate) type ExtensiblePredicates = IndexMap<PredicateKey, PredicateSkeleton>;
pub(crate) type ExtensiblePredicates = IndexMap<PredicateKey, PredicateSkeleton, FxBuildHasher>;
pub(crate) type LocalExtensiblePredicates =
IndexMap<(CompilationTarget, PredicateKey), LocalPredicateSkeleton>;
IndexMap<(CompilationTarget, PredicateKey), LocalPredicateSkeleton, FxBuildHasher>;
pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex, FxBuildHasher>;
#[derive(Debug)]
pub struct IndexStore {
@@ -504,14 +381,14 @@ impl IndexStore {
) -> Option<CodeIndex> {
if module == atom!("user") {
match ClauseType::from(name, arity) {
ClauseType::Named(name, arity, _) => self.code_dir.get(&(name, arity)).cloned(),
ClauseType::Named(arity, name, _) => self.code_dir.get(&(name, arity)).cloned(),
_ => None,
}
} else {
self.modules
.get(&module)
.and_then(|module| match ClauseType::from(name, arity) {
ClauseType::Named(name, arity, _) => {
ClauseType::Named(arity, name, _) => {
module.code_dir.get(&(name, arity)).cloned()
}
_ => None,
@@ -561,8 +438,10 @@ impl IndexStore {
#[inline]
pub(super) fn new() -> Self {
index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
index_store!(
CodeDir::with_hasher(FxBuildHasher::default()),
default_op_dir(),
ModuleDir::with_hasher(FxBuildHasher::default())
)
}
}
pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex>;

View File

@@ -55,14 +55,14 @@ pub struct MachineState {
pub arena: Arena,
pub(super) pdl: Vec<HeapCellValue>,
pub(super) s: HeapPtr,
pub(super) p: CodePtr,
pub(super) p: usize,
pub(super) oip: u32, // first internal code ptr
pub(super) iip : u32, // second internal code ptr
pub(super) b: usize,
pub(super) b0: usize,
pub(super) e: usize,
pub(super) num_of_args: usize,
pub(super) cp: LocalCodePtr,
pub(super) cp: usize,
pub(super) attr_var_init: AttrVarInitializer,
pub(super) fail: bool,
pub heap: Heap,
@@ -79,7 +79,6 @@ pub struct MachineState {
// 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(crate) flags: MachineFlags,
pub(crate) cc: usize,
pub(crate) global_clock: usize,
@@ -115,7 +114,6 @@ impl fmt::Debug for MachineState {
.field("ball", &self.ball)
.field("lifted_heap", &self.lifted_heap)
.field("interms", &self.interms)
.field("last_call", &self.last_call)
.field("flags", &self.flags)
.field("cc", &self.cc)
.field("global_clock", &self.global_clock)
@@ -365,6 +363,20 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
}
impl MachineState {
pub(crate) fn backtrack(&mut self) {
let b = self.b;
let or_frame = self.stack.index_or_frame(b);
self.b0 = or_frame.prelude.b0;
self.p = or_frame.prelude.bp;
self.oip = or_frame.prelude.boip;
self.iip = or_frame.prelude.biip;
self.pdl.clear();
self.fail = false;
}
pub(crate) fn increment_call_count(&mut self) -> CallResult {
if self.cwil.inference_limit_exceeded || self.ball.stub.len() > 0 {
return Ok(());
@@ -422,17 +434,19 @@ impl MachineState {
self.error_form(err, stub)
}
pub(super) fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
self.cp.assign_if_local(self.p + 1);
#[inline(always)]
pub(super) fn call_at_index(&mut self, arity: usize, p: usize) {
self.cp = self.p + 1;
self.p = p;
self.num_of_args = arity;
self.b0 = self.b;
self.p = CodePtr::Local(p);
}
pub(super) fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) {
#[inline(always)]
pub(super) fn execute_at_index(&mut self, arity: usize, p: usize) {
self.num_of_args = arity;
self.b0 = self.b;
self.p = CodePtr::Local(p);
self.p = p;
}
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
@@ -467,7 +481,7 @@ impl MachineState {
if stream.past_end_of_stream() {
if EOFAction::Reset != stream.options().eof_action() {
return return_from_clause!(self.last_call, self);
return Ok(());
} else if self.fail {
return Ok(());
}
@@ -710,7 +724,7 @@ impl MachineState {
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.bp = self.p + offset;
or_frame.prelude.boip = 0;
or_frame.prelude.biip = 0;
or_frame.prelude.tr = self.tr;
@@ -720,7 +734,7 @@ impl MachineState {
self.b = b;
for i in 0..n {
self.stack[stack_loc!(OrFrame, b, i)] = self.registers[i+1];
or_frame[i] = self.registers[i+1];
}
self.hb = self.heap.len();
@@ -737,7 +751,7 @@ impl MachineState {
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.bp = self.p; // + 1; in self.iip now!
or_frame.prelude.boip = self.oip;
or_frame.prelude.biip = self.iip + 1;
or_frame.prelude.tr = self.tr;
@@ -751,7 +765,7 @@ impl MachineState {
}
self.hb = self.heap.len();
self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset));
self.p = self.p + offset;
self.oip = 0;
self.iip = 0;

View File

@@ -1,13 +1,11 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::types::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::attributed_variables::*;
use crate::machine::copier::*;
use crate::machine::heap::*;
use crate::machine::Machine;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
@@ -23,11 +21,6 @@ use indexmap::IndexSet;
use std::cmp::Ordering;
use std::convert::TryFrom;
// TODO: move this block to.. a place.
impl Machine {
}
impl MachineState {
pub(crate) fn new() -> Self {
MachineState {
@@ -35,14 +28,14 @@ impl MachineState {
atom_tbl: AtomTable::new(),
pdl: Vec::with_capacity(1024),
s: HeapPtr::default(),
p: CodePtr::default(),
p: 0,
oip: 0,
iip: 0,
b: 0,
b0: 0,
e: 0,
num_of_args: 0,
cp: LocalCodePtr::default(),
cp: 0,
attr_var_init: AttrVarInitializer::new(0),
fail: false,
heap: Heap::with_capacity(256 * 256),
@@ -58,7 +51,6 @@ impl MachineState {
interms: vec![Number::default();256],
cont_pts: Vec::with_capacity(256),
cwil: CWIL::new(),
last_call: false,
flags: MachineFlags::default(),
cc: 0,
global_clock: 0,
@@ -202,16 +194,16 @@ impl MachineState {
match r1.get_tag() {
RefTag::StackCell => {
self.stack[r1.get_value() as usize] = t2;
self.trail(TrailRef::Ref(r1));
}
RefTag::HeapCell => {
self.heap[r1.get_value() as usize] = t2;
self.trail(TrailRef::Ref(r1));
}
RefTag::AttrVar => {
self.bind_attr_var(r1.get_value() as usize, t2);
}
};
self.trail(TrailRef::Ref(r1));
} else {
read_heap_cell!(a2,
(HeapCellValueTag::StackVar, s) => {
@@ -864,17 +856,6 @@ impl MachineState {
);
}
pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
let old_h = self.heap.len();
let a1 = self.registers[1];
let a2 = self.registers[2];
copy_term(CopyTerm::new(self), a1, attr_var_policy);
unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
}
pub(super) fn unwind_stack(&mut self) {
self.b = self.block;
self.fail = true;
@@ -1912,9 +1893,6 @@ impl MachineState {
);
}
Some(PStrPrefixCmpResult { prefix_len, .. }) => {
// TODO: this is woefully insufficient! you need to
// match the remaining portion of string if offset <
// pstr.len().
let focus = heap_pstr_iter.focus();
let tail_addr = self.heap[focus];
@@ -1996,23 +1974,7 @@ impl MachineState {
)
}
pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
let arity = arity + 1;
let pred = self.registers[1];
for i in 2..arity {
self.registers[i - 1] = self.registers[i];
}
if arity > 1 {
self.registers[arity - 1] = pred;
return;
}
self.fail = true;
}
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
pub(super) fn setup_call_n(&mut self, arity: usize) -> Result<PredicateKey, MachineStub> {
let addr = self.store(self.deref(self.registers[arity]));
let (name, narity) = read_heap_cell!(addr,
@@ -2022,10 +1984,7 @@ impl MachineState {
if narity + arity > MAX_ARITY {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.representation_error(RepFlag::MaxArity);
let representation_error = self.error_form(err, stub);
self.throw_exception(representation_error);
return None;
return Err(self.error_form(err, stub));
}
for i in (1..arity).rev() {
@@ -2039,12 +1998,8 @@ impl MachineState {
(name, narity)
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
debug_assert_eq!(arity, 0);
(name, 0)
} else {
self.fail = true;
return None;
}
}
(HeapCellValueTag::Char, c) => {
(self.atom_tbl.build_with(&c.to_string()), 0)
@@ -2052,22 +2007,16 @@ impl MachineState {
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, _h) => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.instantiation_error();
let instantiation_error = self.error_form(err, stub);
self.throw_exception(instantiation_error);
return None;
return Err(self.error_form(err, stub));
}
_ => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.type_error(ValidType::Callable, addr);
let type_error = self.error_form(err, stub);
self.throw_exception(type_error);
return None;
return Err(self.error_form(err, stub));
}
);
Some((name, arity + narity - 1))
Ok((name, arity + narity - 1))
}
#[inline]
@@ -2233,45 +2182,6 @@ impl MachineState {
Ok(())
}
pub fn compare_numbers(&mut self, cmp: CompareNumberQT, n1: Number, n2: Number) {
let ordering = n1.cmp(&n2);
self.fail = match cmp {
CompareNumberQT::GreaterThan if ordering == Ordering::Greater => false,
CompareNumberQT::GreaterThanOrEqual if ordering != Ordering::Less => false,
CompareNumberQT::LessThan if ordering == Ordering::Less => false,
CompareNumberQT::LessThanOrEqual if ordering != Ordering::Greater => false,
CompareNumberQT::NotEqual if ordering != Ordering::Equal => false,
CompareNumberQT::Equal if ordering == Ordering::Equal => false,
_ => true,
};
self.p += 1;
}
pub fn compare_term(&mut self, qt: CompareTermQT) {
let a1 = self.registers[1];
let a2 = self.registers[2];
match compare_term_test!(self, a1, a2) {
Some(Ordering::Greater) => match qt {
CompareTermQT::GreaterThan | CompareTermQT::GreaterThanOrEqual => {}
_ => self.fail = true,
},
Some(Ordering::Equal) => match qt {
CompareTermQT::GreaterThanOrEqual | CompareTermQT::LessThanOrEqual => {}
_ => self.fail = true,
},
Some(Ordering::Less) => match qt {
CompareTermQT::LessThan | CompareTermQT::LessThanOrEqual => {}
_ => self.fail = true,
},
None => {
self.fail = true;
}
}
}
// returns true on failure, false on success.
pub fn eq_test(&mut self, h1: HeapCellValue, h2: HeapCellValue) -> bool {
if h1 == h2 {
@@ -2652,12 +2562,14 @@ impl MachineState {
)
}
/*
pub fn setup_built_in_call(&mut self, ct: BuiltInClauseType) {
self.num_of_args = ct.arity();
self.b0 = self.b;
self.p = CodePtr::BuiltInClause(ct, self.p.local());
}
*/
pub fn deallocate(&mut self) {
let e = self.e;

View File

@@ -227,7 +227,7 @@ impl Machine {
let mut wam = Machine {
machine_st,
indices: IndexStore::new(),
code_repo: CodeRepo::new(),
code: Code::new(),
user_input,
user_output,
user_error,
@@ -239,6 +239,8 @@ impl Machine {
lib_path.pop();
lib_path.push("lib");
wam.add_impls_to_indices();
bootstrapping_compile(
Stream::from_static_string(
LIBRARIES.borrow()["ops_and_meta_predicates"],
@@ -262,7 +264,7 @@ impl Machine {
)
.unwrap();
if let Some(builtins) = wam.indices.modules.get(&atom!("builtins")) {
if let Some(ref mut builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
load_module(
&mut wam.indices.code_dir,
&mut wam.indices.op_dir,
@@ -270,6 +272,8 @@ impl Machine {
&CompilationTarget::User,
builtins,
);
import_builtin_impls(&wam.indices.code_dir, builtins);
} else {
unreachable!()
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
use crate::atom_table::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
@@ -207,34 +207,6 @@ fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, Compilati
}
}
/*
fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, CompilationError> {
let dbl_quotes = *terms.pop().unwrap();
match terms[0].as_ref() {
Term::Literal(_, Literal::Atom(ref name, _))
if name.as_str() == "double_quotes" => {
match dbl_quotes {
Term::Literal(_, Literal::Atom(name, _)) => {
match name.as_str() {
"atom" => Ok(DoubleQuotes::Atom),
"chars" => Ok(DoubleQuotes::Chars),
"codes" => Ok(DoubleQuotes::Codes),
_ => Err(CompilationError::InvalidDoubleQuotesDecl),
}
}
_ => {
Err(CompilationError::InvalidDoubleQuotesDecl)
}
}
},
_ => {
Err(CompilationError::InvalidDoubleQuotesDecl)
}
}
}
*/
type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
fn setup_qualified_import(
@@ -735,7 +707,7 @@ impl Preprocessor {
},
Term::Var(..) => Ok(QueryTerm::Clause(
Cell::default(),
ClauseType::CallN,
ClauseType::CallN(1),
vec![term],
false,
)),

View File

@@ -1,9 +1,7 @@
use core::marker::PhantomData;
use crate::types::*;
use crate::machine::machine_indices::*;
use crate::raw_block::*;
use crate::types::*;
use std::mem;
use std::ops::{Index, IndexMut};
@@ -47,8 +45,7 @@ pub(crate) struct FramePrelude {
pub(crate) struct AndFramePrelude {
pub(crate) univ_prelude: FramePrelude,
pub(crate) e: usize,
pub(crate) cp: LocalCodePtr,
pub(crate) interrupt_cp: LocalCodePtr, // TODO: get rid of it!
pub(crate) cp: usize,
}
#[derive(Debug)]
@@ -118,9 +115,9 @@ impl IndexMut<usize> for Stack {
pub(crate) struct OrFramePrelude {
pub(crate) univ_prelude: FramePrelude,
pub(crate) e: usize,
pub(crate) cp: LocalCodePtr,
pub(crate) cp: usize,
pub(crate) b: usize,
pub(crate) bp: LocalCodePtr,
pub(crate) bp: usize,
pub(crate) boip: u32,
pub(crate) biip: u32,
pub(crate) tr: usize,

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,3 @@
macro_rules! interm {
($n: expr) => {
ArithmeticTerm::Interm($n)
};
}
/* A simple macro to count the arguments in a variadic list
* of token trees.
*/
@@ -524,6 +518,35 @@ macro_rules! functor_term {
);
}
macro_rules! compare_number_instr {
($cmp: expr, $at_1: expr, $at_2: expr) => {{
$cmp.set_terms($at_1, $at_2);
call_clause!(ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)), 0)
}};
}
macro_rules! call_clause {
($clause_type:expr, $pvs:expr) => {{
let mut instr = $clause_type.to_instr();
instr.perm_vars_mut().map(|pvs| *pvs = $pvs);
instr
}};
}
macro_rules! call_clause_by_default {
($clause_type:expr, $pvs:expr) => {{
let mut instr = $clause_type.to_instr().to_default();
instr.perm_vars_mut().map(|pvs| *pvs = $pvs);
instr
}};
}
macro_rules! interm {
($n: expr) => {
ArithmeticTerm::Interm($n)
};
}
macro_rules! ar_reg {
($r: expr) => {
ArithmeticTerm::Reg($r)
@@ -545,229 +568,18 @@ macro_rules! index_store {
($code_dir:expr, $op_dir:expr, $modules:expr) => {
IndexStore {
code_dir: $code_dir,
extensible_predicates: ExtensiblePredicates::new(),
local_extensible_predicates: LocalExtensiblePredicates::new(),
global_variables: GlobalVarDir::new(),
meta_predicates: MetaPredicateDir::new(),
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()),
global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()),
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
modules: $modules,
op_dir: $op_dir,
streams: StreamDir::new(),
stream_aliases: StreamAliasDir::new(),
stream_aliases: StreamAliasDir::with_hasher(FxBuildHasher::default()),
}
};
}
macro_rules! is_atom {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtom($r)), 1, 0)
};
}
macro_rules! is_atomic {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtomic($r)), 1, 0)
};
}
macro_rules! is_integer {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsInteger($r)), 1, 0)
};
}
macro_rules! is_compound {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsCompound($r)), 1, 0)
};
}
macro_rules! is_float {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsFloat($r)), 1, 0)
};
}
macro_rules! is_rational {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsRational($r)), 1, 0)
};
}
macro_rules! is_number {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsNumber($r)), 1, 0)
};
}
macro_rules! is_nonvar {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsNonVar($r)), 1, 0)
};
}
macro_rules! is_var {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsVar($r)), 1, 0)
};
}
macro_rules! call_clause {
($ct:expr, $arity:expr, $pvs:expr) => {
Line::Control(ControlInstruction::CallClause(
$ct, $arity, $pvs, false, false,
))
};
($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => {
Line::Control(ControlInstruction::CallClause(
$ct, $arity, $pvs, $lco, false,
))
};
}
macro_rules! call_clause_by_default {
($ct:expr, $arity:expr, $pvs:expr) => {
Line::Control(ControlInstruction::CallClause(
$ct, $arity, $pvs, false, true,
))
};
($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => {
Line::Control(ControlInstruction::CallClause(
$ct, $arity, $pvs, $lco, true,
))
};
}
macro_rules! proceed {
() => {
Line::Control(ControlInstruction::Proceed)
};
}
macro_rules! is_call {
($r:expr, $at:expr) => {
call_clause!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0)
};
}
macro_rules! is_call_by_default {
($r:expr, $at:expr) => {
call_clause_by_default!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0)
};
}
macro_rules! set_cp {
($r:expr) => {
call_clause!(ClauseType::System(SystemClauseType::SetCutPoint($r)), 1, 0)
};
}
macro_rules! succeed {
() => {
call_clause!(ClauseType::System(SystemClauseType::Succeed), 0, 0)
};
}
macro_rules! fail {
() => {
call_clause!(ClauseType::System(SystemClauseType::Fail), 0, 0)
};
}
macro_rules! compare_number_instr {
($cmp: expr, $at_1: expr, $at_2: expr) => {{
let ct = ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp, $at_1, $at_2));
call_clause!(ct, 2, 0)
}};
}
macro_rules! jmp_call {
($arity:expr, $offset:expr, $pvs:expr) => {
Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false))
};
}
macro_rules! return_from_clause {
($lco:expr, $machine_st:expr) => {{
if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
return Ok(());
}
if $lco {
$machine_st.p = CodePtr::Local($machine_st.cp);
} else {
$machine_st.p += 1;
}
Ok(())
}};
}
macro_rules! dir_entry {
($idx:expr) => {
LocalCodePtr::DirEntry($idx)
};
}
macro_rules! put_constant {
($lvl:expr, $cons:expr, $r:expr) => {
QueryInstruction::PutConstant($lvl, $cons, $r)
};
}
macro_rules! get_level_and_unify {
($r: expr) => {
Line::Cut(CutInstruction::GetLevelAndUnify($r))
};
}
/*
macro_rules! unwind_protect {
($e: expr, $protected: expr) => {
match $e {
Err(e) => {
$protected;
return Err(e);
}
_ => {}
}
};
}
*/
/*
macro_rules! discard_result {
($f: expr) => {
match $f {
_ => (),
}
};
}
*/
macro_rules! try_or_fail {
($s:expr, $e:expr) => {{
match $e {
Ok(val) => val,
Err(msg) => {
$s.throw_exception(msg);
return;
}
}
}};
}
macro_rules! try_or_fail_gen {
($s:expr, $e:expr) => {{
match $e {
Ok(val) => val,
Err(msg_fn) => {
let e = msg_fn($s);
$s.throw_exception(e);
return;
}
}
}};
}
macro_rules! unify {
($machine_st:expr, $($value:expr),*) => {{
$($machine_st.pdl.push($value);)*

View File

@@ -13,6 +13,7 @@ use std::vec::Vec;
use rug::{Integer, Rational};
use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use modular_bitfield::error::OutOfBounds;
use modular_bitfield::prelude::*;
@@ -286,7 +287,7 @@ impl OpDesc {
}
// name and fixity -> operator type and precedence.
pub type OpDir = IndexMap<(Atom, Fixity), OpDesc>;
pub type OpDir = IndexMap<(Atom, Fixity), OpDesc, FxBuildHasher>;
#[derive(Debug, Clone, Copy)]
pub struct MachineFlags {
@@ -329,7 +330,7 @@ impl Default for DoubleQuotes {
}
pub fn default_op_dir() -> OpDir {
let mut op_dir = OpDir::new();
let mut op_dir = OpDir::with_hasher(FxBuildHasher::default());
op_dir.insert(
(atom!(":-"), Fixity::In),

View File

@@ -12,6 +12,8 @@ use crate::machine::streams::*;
use crate::parser::char_reader::*;
use crate::types::*;
use fxhash::FxBuildHasher;
use rustyline::error::ReadlineError;
use rustyline::{Cmd, Config, Editor, KeyEvent};
@@ -257,7 +259,7 @@ impl<'a, 'b> TermWriter<'a, 'b> {
heap,
atom_tbl,
queue: SubtermDeque::new(),
var_dict: HeapVarDict::new(),
var_dict: HeapVarDict::with_hasher(FxBuildHasher::default()),
}
}

View File

@@ -1,39 +1,41 @@
use crate::parser::ast::*;
use crate::atom_table::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
use crate::types::*;
pub(crate) struct FactInstruction;
pub(crate) struct QueryInstruction;
pub(crate) trait CompilationTarget<'a> {
type Iterator: Iterator<Item = TermRef<'a>>;
fn iter(term: &'a Term) -> Self::Iterator;
fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Self;
fn to_list(lvl: Level, r: RegType) -> Self;
fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self;
fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Instruction;
fn to_list(lvl: Level, r: RegType) -> Instruction;
fn to_structure(name: Atom, arity: usize, r: RegType) -> Instruction;
fn to_void(num_subterms: usize) -> Self;
fn is_void_instr(&self) -> bool;
fn to_void(num_subterms: usize) -> Instruction;
fn is_void_instr(instr: &Instruction) -> bool;
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Self;
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction;
fn incr_void_instr(&mut self);
fn incr_void_instr(instr: &mut Instruction);
fn constant_subterm(literal: Literal) -> Self;
fn constant_subterm(literal: Literal) -> Instruction;
fn argument_to_variable(r: RegType, r: usize) -> Self;
fn argument_to_value(r: RegType, val: usize) -> Self;
fn argument_to_variable(r: RegType, r: usize) -> Instruction;
fn argument_to_value(r: RegType, val: usize) -> Instruction;
fn move_to_register(r: RegType, val: usize) -> Self;
fn move_to_register(r: RegType, val: usize) -> Instruction;
fn subterm_to_variable(r: RegType) -> Self;
fn subterm_to_value(r: RegType) -> Self;
fn subterm_to_variable(r: RegType) -> Instruction;
fn subterm_to_value(r: RegType) -> Instruction;
fn clause_arg_to_instr(r: RegType) -> Self;
fn clause_arg_to_instr(r: RegType) -> Instruction;
}
impl<'a> CompilationTarget<'a> for FactInstruction {
@@ -43,66 +45,66 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
breadth_first_iter(term, false) // do not iterate over the root clause if one exists.
}
fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Self {
FactInstruction::GetConstant(lvl, HeapCellValue::from(constant), reg)
fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
Instruction::GetConstant(lvl, HeapCellValue::from(constant), reg)
}
fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self {
FactInstruction::GetStructure(ct, arity, reg)
fn to_structure(name: Atom, arity: usize, reg: RegType) -> Instruction {
Instruction::GetStructure(name, arity, reg)
}
fn to_list(lvl: Level, reg: RegType) -> Self {
FactInstruction::GetList(lvl, reg)
fn to_list(lvl: Level, reg: RegType) -> Instruction {
Instruction::GetList(lvl, reg)
}
fn to_void(num_subterms: usize) -> Self {
FactInstruction::UnifyVoid(num_subterms)
fn to_void(num_subterms: usize) -> Instruction {
Instruction::UnifyVoid(num_subterms)
}
fn is_void_instr(&self) -> bool {
match self {
&FactInstruction::UnifyVoid(_) => true,
fn is_void_instr(instr: &Instruction) -> bool {
match instr {
&Instruction::UnifyVoid(_) => true,
_ => false,
}
}
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Self {
FactInstruction::GetPartialString(lvl, string, r, has_tail)
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction {
Instruction::GetPartialString(lvl, string, r, has_tail)
}
fn incr_void_instr(&mut self) {
match self {
&mut FactInstruction::UnifyVoid(ref mut incr) => *incr += 1,
fn incr_void_instr(instr: &mut Instruction) {
match instr {
&mut Instruction::UnifyVoid(ref mut incr) => *incr += 1,
_ => {}
}
}
fn constant_subterm(constant: Literal) -> Self {
FactInstruction::UnifyConstant(HeapCellValue::from(constant))
fn constant_subterm(constant: Literal) -> Instruction {
Instruction::UnifyConstant(HeapCellValue::from(constant))
}
fn argument_to_variable(arg: RegType, val: usize) -> Self {
FactInstruction::GetVariable(arg, val)
fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
Instruction::GetVariable(arg, val)
}
fn move_to_register(arg: RegType, val: usize) -> Self {
FactInstruction::GetVariable(arg, val)
fn move_to_register(arg: RegType, val: usize) -> Instruction {
Instruction::GetVariable(arg, val)
}
fn argument_to_value(arg: RegType, val: usize) -> Self {
FactInstruction::GetValue(arg, val)
fn argument_to_value(arg: RegType, val: usize) -> Instruction {
Instruction::GetValue(arg, val)
}
fn subterm_to_variable(val: RegType) -> Self {
FactInstruction::UnifyVariable(val)
fn subterm_to_variable(val: RegType) -> Instruction {
Instruction::UnifyVariable(val)
}
fn subterm_to_value(val: RegType) -> Self {
FactInstruction::UnifyValue(val)
fn subterm_to_value(val: RegType) -> Instruction {
Instruction::UnifyValue(val)
}
fn clause_arg_to_instr(val: RegType) -> Self {
FactInstruction::UnifyVariable(val)
fn clause_arg_to_instr(val: RegType) -> Instruction {
Instruction::UnifyVariable(val)
}
}
@@ -113,65 +115,65 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
post_order_iter(term)
}
fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self {
QueryInstruction::PutStructure(ct, arity, r)
fn to_structure(name: Atom, arity: usize, r: RegType) -> Instruction {
Instruction::PutStructure(name, arity, r)
}
fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Self {
QueryInstruction::PutConstant(lvl, HeapCellValue::from(constant), reg)
fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
Instruction::PutConstant(lvl, HeapCellValue::from(constant), reg)
}
fn to_list(lvl: Level, reg: RegType) -> Self {
QueryInstruction::PutList(lvl, reg)
fn to_list(lvl: Level, reg: RegType) -> Instruction {
Instruction::PutList(lvl, reg)
}
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Self {
QueryInstruction::PutPartialString(lvl, string, r, has_tail)
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction {
Instruction::PutPartialString(lvl, string, r, has_tail)
}
fn to_void(subterms: usize) -> Self {
QueryInstruction::SetVoid(subterms)
fn to_void(subterms: usize) -> Instruction {
Instruction::SetVoid(subterms)
}
fn is_void_instr(&self) -> bool {
match self {
&QueryInstruction::SetVoid(_) => true,
fn is_void_instr(instr: &Instruction) -> bool {
match instr {
&Instruction::SetVoid(_) => true,
_ => false,
}
}
fn incr_void_instr(&mut self) {
match self {
&mut QueryInstruction::SetVoid(ref mut incr) => *incr += 1,
fn incr_void_instr(instr: &mut Instruction) {
match instr {
&mut Instruction::SetVoid(ref mut incr) => *incr += 1,
_ => {}
}
}
fn constant_subterm(constant: Literal) -> Self {
QueryInstruction::SetConstant(HeapCellValue::from(constant))
fn constant_subterm(constant: Literal) -> Instruction {
Instruction::SetConstant(HeapCellValue::from(constant))
}
fn argument_to_variable(arg: RegType, val: usize) -> Self {
QueryInstruction::PutVariable(arg, val)
fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
Instruction::PutVariable(arg, val)
}
fn move_to_register(arg: RegType, val: usize) -> Self {
QueryInstruction::GetVariable(arg, val)
fn move_to_register(arg: RegType, val: usize) -> Instruction {
Instruction::GetVariable(arg, val)
}
fn argument_to_value(arg: RegType, val: usize) -> Self {
QueryInstruction::PutValue(arg, val)
fn argument_to_value(arg: RegType, val: usize) -> Instruction {
Instruction::PutValue(arg, val)
}
fn subterm_to_variable(val: RegType) -> Self {
QueryInstruction::SetVariable(val)
fn subterm_to_variable(val: RegType) -> Instruction {
Instruction::SetVariable(val)
}
fn subterm_to_value(val: RegType) -> Self {
QueryInstruction::SetValue(val)
fn subterm_to_value(val: RegType) -> Instruction {
Instruction::SetValue(val)
}
fn clause_arg_to_instr(val: RegType) -> Self {
QueryInstruction::SetValue(val)
fn clause_arg_to_instr(val: RegType) -> Instruction {
Instruction::SetValue(val)
}
}

View File

@@ -1,6 +1,5 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::clause_types::*;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::loader::CompilationTarget;
@@ -15,18 +14,7 @@ use ordered_float::OrderedFloat;
use std::fmt;
impl fmt::Display for LocalCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LocalCodePtr::DirEntry(p) => write!(f, "LocalCodePtr::DirEntry({})", p),
LocalCodePtr::Halt => write!(f, "LocalCodePtr::Halt"),
// LocalCodePtr::IndexingBuf(p, o, i) => {
// write!(f, "LocalCodePtr::IndexingBuf({}, {}, {})", p, o, i)
// }
}
}
}
/*
impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -77,6 +65,7 @@ impl fmt::Display for REPLCodePtr {
}
}
}
*/
impl fmt::Display for IndexPtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -97,6 +86,7 @@ impl fmt::Display for CompilationTarget {
}
}
/*
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -221,6 +211,7 @@ impl fmt::Display for ClauseType {
}
}
}
*/
impl fmt::Display for HeapCellValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -269,82 +260,10 @@ impl fmt::Display for HeapCellValue {
unreachable!()
}
)
/*
match self {
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
&HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
&HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
&HeapCellValue::Integer(ref n) => write!(f, "{}", n),
&HeapCellValue::LoadStatePayload(_) => write!(f, "LoadStatePayload"),
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
f,
"{}/{} (op, priority: {}, spec: {})",
name.as_str(),
arity,
cell.prec(),
cell.assoc()
),
&HeapCellValue::NamedStr(arity, ref name, None) => {
write!(f, "{}/{}", name.as_str(), arity)
}
&HeapCellValue::PartialString(ref pstr, has_tail) => {
write!(
f,
"pstr ( buf: \"{}\", has_tail({}) )",
pstr.as_str_from(0),
has_tail,
)
}
&HeapCellValue::Stream(ref stream) => {
write!(f, "$stream({})", stream.as_ptr() as usize)
}
&HeapCellValue::TcpListener(ref tcp_listener) => {
write!(f, "$tcp_listener({})", tcp_listener.local_addr().unwrap())
}
}
*/
}
}
/*
impl fmt::Display for DBRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&DBRef::NamedPred(ref name, arity, _) => write!(f, "db_ref:named:{}/{}", name, arity),
&DBRef::Op(priority, spec, ref name, ..) => {
write!(f, "db_ref:op({}, {}, {})", priority, spec, name)
}
}
}
}
*/
/*
impl fmt::Display for Addr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Addr::Char(c) => write!(f, "Addr::Char({})", c),
&Addr::EmptyList => write!(f, "Addr::EmptyList"),
&Addr::Fixnum(n) => write!(f, "Addr::Fixnum({})", n),
&Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
&Addr::LoadStatePayload(s) => write!(f, "Addr::LoadStatePayload({})", s),
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
&Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
&Addr::TcpListener(tcp_listener) => write!(f, "Addr::TcpListener({})", tcp_listener),
&Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
}
}
}
*/
impl fmt::Display for ControlInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -375,6 +294,7 @@ impl fmt::Display for ControlInstruction {
}
}
}
*/
impl fmt::Display for IndexedChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -386,6 +306,7 @@ impl fmt::Display for IndexedChoiceInstruction {
}
}
/*
impl fmt::Display for ChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -443,6 +364,7 @@ impl fmt::Display for ChoiceInstruction {
}
}
}
*/
impl fmt::Display for IndexingCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -602,6 +524,7 @@ impl fmt::Display for IndexingLine {
}
}
/*
impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -625,17 +548,8 @@ impl fmt::Display for Line {
}
}
}
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Number::Float(fl) => write!(f, "{}", fl),
Number::Integer(n) => write!(f, "{}", n),
Number::Rational(r) => write!(f, "{}", r),
Number::Fixnum(n) => write!(f, "{}", n.get_num()),
}
}
}
*/
/*
impl fmt::Display for ArithmeticTerm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -745,7 +659,8 @@ impl fmt::Display for CutInstruction {
}
}
}
*/
/*
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -754,3 +669,4 @@ impl fmt::Display for Level {
}
}
}
*/