Merge branch 'master' into dashu-fixes

This commit is contained in:
Fayeed Pawaskar
2023-09-10 21:51:02 +05:30
64 changed files with 12489 additions and 9940 deletions

View File

@@ -20,7 +20,7 @@ jobs:
- { os: macos-11, rust-version: stable, shell: bash, target: 'x86_64-apple-darwin' }
- { os: ubuntu-20.04, rust-version: stable, shell: bash, extra: true, target: 'x86_64-unknown-linux-gnu' }
- { os: ubuntu-20.04, rust-version: stable, shell: bash, target: 'i686-unknown-linux-gnu' }
- { os: ubuntu-20.04, rust-version: 1.65, shell: bash, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-20.04, rust-version: "1.70", shell: bash, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-20.04, rust-version: beta, shell: bash, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-20.04, rust-version: nightly, shell: bash, target: 'x86_64-unknown-linux-gnu'}
defaults:
@@ -54,6 +54,9 @@ jobs:
~/.cargo/git/db/
target/
key: ${{ matrix.os }}_${{ matrix.target }}_rustc-${{ steps.toolchain.outputs.cachekey }}_cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install wasm-pack
if: matrix.extra
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Build and test.
- name: Build library
@@ -97,12 +100,22 @@ jobs:
run: |
cargo rustc --target ${{ matrix.target }} --verbose --bin scryer-prolog --release -- -D warnings
echo "$PWD/target/release" >> $GITHUB_PATH
- name: Build wasm
if: matrix.extra
run: |
wasm-pack build --target web -- --no-default-features
- name: Publish release binary artifact
if: contains(matrix.rust-version,'stable')
uses: actions/upload-artifact@v3
with:
path: target/${{ matrix.target }}/release/scryer-prolog*
name: scryer-prolog_${{ matrix.os }}_${{ matrix.target }}
- name: Publish wasm artifact
if: matrix.extra
uses: actions/upload-artifact@v3
with:
path: pkg/*
name: scryer-prolog_unknown_wasm32
logtalk-test:
runs-on: ubuntu-20.04
@@ -162,6 +175,7 @@ jobs:
zip scryer-prolog_macos-11.zip ./scryer-prolog_macos-11_x86_64-apple-darwin/scryer-prolog
zip scryer-prolog_ubuntu-20.04.zip ./scryer-prolog_ubuntu-20.04_x86_64-unknown-linux-gnu/scryer-prolog
zip scryer-prolog_windows-latest.zip ./scryer-prolog_windows-latest_x86_64-pc-windows-gnu/scryer-prolog.exe
zip -r scryer-prolog_unknown-wasm32.zip ./scryer-prolog_unknown_wasm32
- name: Release
uses: softprops/action-gh-release@v1
with:
@@ -169,3 +183,4 @@ jobs:
scryer-prolog_macos-11.zip
scryer-prolog_ubuntu-20.04.zip
scryer-prolog_windows-latest.zip
scryer-prolog_unknown-wasm32.zip

View File

@@ -10,15 +10,20 @@ license = "BSD-3-Clause"
keywords = ["prolog", "prolog-interpreter", "prolog-system"]
categories = ["command-line-utilities"]
build = "build/main.rs"
rust-version = "1.63"
rust-version = "1.70"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["ffi", "repl", "hostname", "tls", "http"]
default = ["ffi", "repl", "hostname", "tls", "http", "crypto-full"]
ffi = ["dep:libffi"]
repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
hostname = ["dep:hostname"]
tls = ["dep:native-tls"]
http = ["dep:hyper", "dep:reqwest"]
rust_beta_channel = []
crypto-full = []
[build-dependencies]
indexmap = "1.0.2"
@@ -80,7 +85,19 @@ tokio = { version = "1.28.2", features = ["full"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.10", features = ["js"] }
tokio = { version = "1.28.2", features = ["sync", "macros", "io-util", "rt", "time"] }
tokio = { version = "1.28.2", features = ["sync", "macros", "io-util", "rt"] }
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
console_error_panic_hook = "0.1"
console_log = "1.0"
wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4"
serde-wasm-bindgen = "0.5"
web-sys = { version = "0.3", features = [
"Document",
"Window",
"Element",
]}
[target.'cfg(target_os = "wasi")'.dependencies]
ring-wasi = { version = "0.16.25" }

View File

@@ -105,7 +105,14 @@ strings.
## Installing Scryer Prolog
### Native Install
### Binaries
Precompiled binaries for several platforms are available for download
at:
**https://github.com/mthom/scryer-prolog/releases/tag/v0.9.2**
### Native Compilation
First, install the latest stable version of
[Rust](https://www.rust-lang.org/en-US/install.html) using your
@@ -143,7 +150,78 @@ light.exe scryer-prolog.wixobj
```
It will generate a very basic MSI file which installs the main executable and a shortcut in the Start Menu. It can be installed with a double-click. To uninstall, go to the Control Panel and uninstall as usual.
Scryer Prolog must be built with **Rust 1.63 and up**.
Scryer Prolog must be built with **Rust 1.70 and up**.
### Building WebAssembly
Scryer Prolog has basic WebAssembly support. You can follow `wasm-pack`'s [official instructions](https://rustwasm.github.io/docs/wasm-pack/quickstart.html) to install `wasm-pack` and build it in any way you like.
However, none of the [default features](https://doc.rust-lang.org/cargo/reference/features.html#the-default-feature) are currently supported. The preferred way of disabling them is passing [extra options](https://rustwasm.github.io/wasm-pack/book/commands/build.html#extra-options) to `wasm-pack`.
For example, if you want a minimal working package without using any bundler like `webpack`, you can do this:
```
wasm-pack build --target web -- --no-default-features
```
Then a `pkg` directory will be created, containing everything you need for a webapp. You can test whether the package is successfully built by creating an html file, adapted from `wasm-bindgen`'s [official example](https://rustwasm.github.io/wasm-bindgen/examples/without-a-bundler.html) like this:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Scryer Prolog - Sudoku Solver Example</title>
<script type="module">
import init, { eval_code } from './pkg/scryer_prolog.js';
const run = async () => {
await init("./pkg/scryer_prolog_bg.wasm");
let code = `
:- use_module(library(format)).
:- use_module(library(clpz)).
:- use_module(library(lists)).
sudoku(Rows) :-
length(Rows, 9), maplist(same_length(Rows), Rows),
append(Rows, Vs), Vs ins 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
blocks(As, Bs, Cs),
blocks(Ds, Es, Fs),
blocks(Gs, Hs, Is).
blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
blocks(Ns1, Ns2, Ns3).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).
main :-
problem(1, Rows), sudoku(Rows), maplist(portray_clause, Rows).
:- initialization(main).
`;
const result = eval_code(code);
document.write(`<p>Sudoku solver returns:</p><pre>${result}</pre>`);
}
run();
</script>
</head>
<body></body>
</html>
```
Then you can serve it with your favorite http server like `python -m http.server` or `npx serve`, and access the page with your browser.
### Docker Install
@@ -285,14 +363,14 @@ innovations of Scryer Prolog. This means that terms which appear as
lists of characters to Prolog programs are stored in packed
UTF-8&nbsp;encoding by the engine.
Without this innovation, storing a list of characters in memory
would use one memory&nbsp;cell per character, one memory&nbsp;cell per
list constructor, and one memory&nbsp;cell for each tail that occurs
in the list. Since one memory&nbsp;cell takes 8&nbsp;bytes on 64-bit
machines, the packed representation used by Scryer&nbsp;Prolog yields
an up&nbsp;to **24-fold&nbsp;reduction** of memory usage, and
corresponding reduction of memory&nbsp;accesses when creating and
processing strings.
Without this innovation, storing a list of characters in memory would
use one WAM memory&nbsp;cell per character, one cell per list
constructor, and one cell for each tail that occurs in the list. Since
one cell takes 8&nbsp;bytes in the WAM as implemented by
Scryer&nbsp;Prolog, the packed representation yields an up&nbsp;to
**24-fold&nbsp;reduction** of memory usage, and corresponding
reduction of memory&nbsp;accesses when creating and processing
strings.
Scryer Prolog's compact internal string representation makes it
ideally suited for the use case Prolog was originally developed for:

View File

@@ -496,22 +496,28 @@ enum SystemClauseType {
CryptoDataHKDF,
#[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_password_hash")))]
CryptoPasswordHash,
#[strum_discriminants(strum(props(Arity = "7", Name = "$crypto_data_encrypt")))]
CryptoDataEncrypt,
#[strum_discriminants(strum(props(Arity = "6", Name = "$crypto_data_decrypt")))]
CryptoDataDecrypt,
#[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_curve_scalar_mult")))]
CryptoCurveScalarMult,
#[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_sign")))]
Ed25519Sign,
#[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_verify")))]
Ed25519Verify,
#[strum_discriminants(strum(props(Arity = "1", Name = "$ed25519_new_keypair")))]
Ed25519NewKeyPair,
#[strum_discriminants(strum(props(Arity = "2", Name = "$ed25519_keypair_public_key")))]
Ed25519KeyPairPublicKey,
#[strum_discriminants(strum(props(Arity = "3", Name = "$curve25519_scalar_mult")))]
Curve25519ScalarMult,
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "7", Name = "$crypto_data_encrypt")))]
CryptoDataEncrypt,
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "6", Name = "$crypto_data_decrypt")))]
CryptoDataDecrypt,
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_sign")))]
Ed25519Sign,
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_verify")))]
Ed25519Verify,
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "1", Name = "$ed25519_new_keypair")))]
Ed25519NewKeyPair,
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "2", Name = "$ed25519_keypair_public_key")))]
Ed25519KeyPairPublicKey,
#[strum_discriminants(strum(props(Arity = "2", Name = "$first_non_octet")))]
FirstNonOctet,
#[strum_discriminants(strum(props(Arity = "3", Name = "$load_html")))]
@@ -590,7 +596,10 @@ enum SystemClauseType {
UnattributedVar,
#[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))]
GetDBRefs,
#[strum_discriminants(strum(props(Arity = "2", Name = "$keysort_with_constant_var_ordering")))]
#[strum_discriminants(strum(props(
Arity = "2",
Name = "$keysort_with_constant_var_ordering"
)))]
KeySortWithConstantVarOrdering,
REPL(REPLCodePtr),
}
@@ -801,7 +810,7 @@ enum InstructionTemplate {
}
fn derive_input(ty: &Type) -> Option<DeriveInput> {
let clause_type: Type = parse_quote!{ ClauseType };
let clause_type: Type = parse_quote! { ClauseType };
let built_in_clause_type: Type = parse_quote! { BuiltInClauseType };
let inlined_clause_type: Type = parse_quote! { InlinedClauseType };
let system_clause_type: Type = parse_quote! { SystemClauseType };
@@ -847,7 +856,8 @@ fn add_discriminant_data<DiscriminantT>(
prefix: &'static str,
variant_data: &mut Vec<(&'static str, Arity, Variant)>,
) -> (&'static str, Arity)
where DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug
where
DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug,
{
let name = prop_from_ident::<DiscriminantT>(&variant.ident, "Name");
let arity = Arity::from(prop_from_ident::<DiscriminantT>(&variant.ident, "Arity"));
@@ -948,7 +958,9 @@ fn generate_instruction_preface() -> TokenStream {
#[derive(Clone, Copy, Debug)]
pub enum IndexedChoiceInstruction {
Retry(usize),
DefaultRetry(usize),
Trust(usize),
DefaultTrust(usize),
Try(usize),
}
@@ -958,6 +970,8 @@ fn generate_instruction_preface() -> TokenStream {
&IndexedChoiceInstruction::Retry(offset) => offset,
&IndexedChoiceInstruction::Trust(offset) => offset,
&IndexedChoiceInstruction::Try(offset) => offset,
&IndexedChoiceInstruction::DefaultRetry(offset) => offset,
&IndexedChoiceInstruction::DefaultTrust(offset) => offset,
}
}
@@ -972,6 +986,12 @@ fn generate_instruction_preface() -> TokenStream {
&IndexedChoiceInstruction::Retry(offset) => {
functor!(atom!("retry"), [fixnum(offset)])
}
&IndexedChoiceInstruction::DefaultTrust(offset) => {
functor!(atom!("default_trust"), [fixnum(offset)])
}
&IndexedChoiceInstruction::DefaultRetry(offset) => {
functor!(atom!("default_retry"), [fixnum(offset)])
}
}
}
}
@@ -1689,7 +1709,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallMakeDirectoryPath |
&Instruction::CallDeleteFile |
&Instruction::CallRenameFile |
&Instruction::CallFileCopy |
&Instruction::CallFileCopy |
&Instruction::CallWorkingDirectory |
&Instruction::CallDeleteDirectory |
&Instruction::CallPathCanonical |
@@ -1783,9 +1803,9 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallHttpListen |
&Instruction::CallHttpAccept |
&Instruction::CallHttpAnswer |
&Instruction::CallLoadForeignLib |
&Instruction::CallForeignCall |
&Instruction::CallDefineForeignStruct |
&Instruction::CallLoadForeignLib |
&Instruction::CallForeignCall |
&Instruction::CallDefineForeignStruct |
&Instruction::CallPredicateDefined |
&Instruction::CallStripModule |
&Instruction::CallCurrentTime |
@@ -1828,13 +1848,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallCryptoDataHash |
&Instruction::CallCryptoDataHKDF |
&Instruction::CallCryptoPasswordHash |
&Instruction::CallCryptoDataEncrypt |
&Instruction::CallCryptoDataDecrypt |
&Instruction::CallCryptoCurveScalarMult |
&Instruction::CallEd25519Sign |
&Instruction::CallEd25519Verify |
&Instruction::CallEd25519NewKeyPair |
&Instruction::CallEd25519KeyPairPublicKey |
&Instruction::CallCurve25519ScalarMult |
&Instruction::CallFirstNonOctet |
&Instruction::CallLoadHTML |
@@ -1891,6 +1905,17 @@ fn generate_instruction_preface() -> TokenStream {
functor!(atom!("call"), [atom(name), fixnum(arity)])
}
//
#[cfg(feature = "crypto-full")]
&Instruction::CallCryptoDataEncrypt |
&Instruction::CallCryptoDataDecrypt |
&Instruction::CallEd25519Sign |
&Instruction::CallEd25519Verify |
&Instruction::CallEd25519NewKeyPair |
&Instruction::CallEd25519KeyPairPublicKey => {
let (name, arity) = self.to_name_and_arity();
functor!(atom!("call"), [atom(name), fixnum(arity)])
}
//
&Instruction::ExecuteAtomChars |
&Instruction::ExecuteAtomCodes |
&Instruction::ExecuteAtomLength |
@@ -1917,7 +1942,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteMakeDirectoryPath |
&Instruction::ExecuteDeleteFile |
&Instruction::ExecuteRenameFile |
&Instruction::ExecuteFileCopy |
&Instruction::ExecuteFileCopy |
&Instruction::ExecuteWorkingDirectory |
&Instruction::ExecuteDeleteDirectory |
&Instruction::ExecutePathCanonical |
@@ -2011,9 +2036,9 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteHttpListen |
&Instruction::ExecuteHttpAccept |
&Instruction::ExecuteHttpAnswer |
&Instruction::ExecuteLoadForeignLib |
&Instruction::ExecuteForeignCall |
&Instruction::ExecuteDefineForeignStruct |
&Instruction::ExecuteLoadForeignLib |
&Instruction::ExecuteForeignCall |
&Instruction::ExecuteDefineForeignStruct |
&Instruction::ExecutePredicateDefined |
&Instruction::ExecuteStripModule |
&Instruction::ExecuteCurrentTime |
@@ -2056,13 +2081,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteCryptoDataHash |
&Instruction::ExecuteCryptoDataHKDF |
&Instruction::ExecuteCryptoPasswordHash |
&Instruction::ExecuteCryptoDataEncrypt |
&Instruction::ExecuteCryptoDataDecrypt |
&Instruction::ExecuteCryptoCurveScalarMult |
&Instruction::ExecuteEd25519Sign |
&Instruction::ExecuteEd25519Verify |
&Instruction::ExecuteEd25519NewKeyPair |
&Instruction::ExecuteEd25519KeyPairPublicKey |
&Instruction::ExecuteCurve25519ScalarMult |
&Instruction::ExecuteFirstNonOctet |
&Instruction::ExecuteLoadHTML |
@@ -2119,6 +2138,17 @@ fn generate_instruction_preface() -> TokenStream {
functor!(atom!("execute"), [atom(name), fixnum(arity)])
}
//
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteCryptoDataEncrypt |
&Instruction::ExecuteCryptoDataDecrypt |
&Instruction::ExecuteEd25519Sign |
&Instruction::ExecuteEd25519Verify |
&Instruction::ExecuteEd25519NewKeyPair |
&Instruction::ExecuteEd25519KeyPairPublicKey => {
let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute"), [atom(name), fixnum(arity)])
}
//
&Instruction::Deallocate => {
functor!(atom!("deallocate"))
}
@@ -2290,7 +2320,8 @@ pub fn generate_instructions_rs() -> TokenStream {
instr_data.generate_instruction_enum_loop(input);
let instr_variants: Vec<_> = instr_data.instr_variants
let instr_variants: Vec<_> = instr_data
.instr_variants
.iter()
.cloned()
.map(|(_, _, _, variant)| variant)
@@ -2329,7 +2360,8 @@ pub fn generate_instructions_rs() -> TokenStream {
for (name, arity, variant) in instr_data.compare_number_variants {
let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields
let variant_fields: Vec<_> = variant
.fields
.into_iter()
.map(|field| {
let ty = field.ty;
@@ -2368,29 +2400,23 @@ pub fn generate_instructions_rs() -> TokenStream {
let ident = variant.ident;
let instr_ident = format_ident!("Call{}", ident);
let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
let placeholder_ids: Vec<_> = (0..variant_fields.len())
.map(|n| format_ident!("f_{}", n))
.collect();
clause_type_to_instr_arms.push(
quote! {
ClauseType::Inlined(
InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*))
) => Instruction::#instr_ident(#(*#placeholder_ids),*)
}
);
clause_type_to_instr_arms.push(quote! {
ClauseType::Inlined(
InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*))
) => Instruction::#instr_ident(#(*#placeholder_ids),*)
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inbuilt_arms.push(quote! {
(atom!(#name), #arity) => true
});
is_inlined_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inlined_arms.push(quote! {
(atom!(#name), #arity) => true
});
}
for (name, arity, variant) in instr_data.compare_term_variants {
@@ -2402,36 +2428,31 @@ pub fn generate_instructions_rs() -> TokenStream {
)
});
clause_type_name_arms.push(
quote! {
ClauseType::BuiltIn(
BuiltInClauseType::CompareTerm(CompareTerm::#ident)
) => atom!(#name)
}
);
clause_type_name_arms.push(quote! {
ClauseType::BuiltIn(
BuiltInClauseType::CompareTerm(CompareTerm::#ident)
) => atom!(#name)
});
let ident = variant.ident;
let instr_ident = format_ident!("Call{}", ident);
clause_type_to_instr_arms.push(
quote! {
ClauseType::BuiltIn(
BuiltInClauseType::CompareTerm(CompareTerm::#ident)
) => Instruction::#instr_ident
}
);
clause_type_to_instr_arms.push(quote! {
ClauseType::BuiltIn(
BuiltInClauseType::CompareTerm(CompareTerm::#ident)
) => Instruction::#instr_ident
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inbuilt_arms.push(quote! {
(atom!(#name), #arity) => true
});
}
for (name, arity, variant) in instr_data.builtin_type_variants {
let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields
let variant_fields: Vec<_> = variant
.fields
.into_iter()
.map(|field| {
let ty = field.ty;
@@ -2470,7 +2491,7 @@ pub fn generate_instructions_rs() -> TokenStream {
let ident = variant.ident;
let instr_ident = format_ident!("Call{}", ident);
let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
let placeholder_ids: Vec<_> = (0..variant_fields.len())
.map(|n| format_ident!("f_{}", n))
.collect();
@@ -2488,17 +2509,16 @@ pub fn generate_instructions_rs() -> TokenStream {
}
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inbuilt_arms.push(quote! {
(atom!(#name), #arity) => true
});
}
for (name, arity, variant) in instr_data.inlined_type_variants {
let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields
let variant_fields: Vec<_> = variant
.fields
.into_iter()
.map(|field| {
if field.ty.type_id() == TypeId::of::<usize>() {
@@ -2541,35 +2561,30 @@ pub fn generate_instructions_rs() -> TokenStream {
let ident = variant.ident;
let instr_ident = format_ident!("Call{}", ident);
let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
let placeholder_ids: Vec<_> = (0..variant_fields.len())
.map(|n| format_ident!("f_{}", n))
.collect();
clause_type_to_instr_arms.push(
quote! {
ClauseType::Inlined(
InlinedClauseType::#ident(#(#placeholder_ids),*)
) => Instruction::#instr_ident(*#(#placeholder_ids),*)
}
);
clause_type_to_instr_arms.push(quote! {
ClauseType::Inlined(
InlinedClauseType::#ident(#(#placeholder_ids),*)
) => Instruction::#instr_ident(*#(#placeholder_ids),*)
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inbuilt_arms.push(quote! {
(atom!(#name), #arity) => true
});
is_inlined_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inlined_arms.push(quote! {
(atom!(#name), #arity) => true
});
}
for (name, arity, variant) in instr_data.system_clause_type_variants {
let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields
let variant_fields: Vec<_> = variant
.fields
.into_iter()
.map(|field| {
if field.ty == parse_quote! { usize } {
@@ -2637,7 +2652,7 @@ pub fn generate_instructions_rs() -> TokenStream {
ident.clone()
};
let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
let placeholder_ids: Vec<_> = (0..variant_fields.len())
.map(|n| format_ident!("f_{}", n))
.collect();
@@ -2655,23 +2670,22 @@ pub fn generate_instructions_rs() -> TokenStream {
}
});
is_inbuilt_arms.push(
if let Arity::Ident("arity") = &arity {
quote! {
(atom!(#name), _arity) => true
}
} else {
quote! {
(atom!(#name), #arity) => true
}
is_inbuilt_arms.push(if let Arity::Ident("arity") = &arity {
quote! {
(atom!(#name), _arity) => true
}
);
} else {
quote! {
(atom!(#name), #arity) => true
}
});
}
for (name, arity, variant) in instr_data.repl_code_ptr_variants {
let ident = variant.ident.clone();
let variant_fields: Vec<_> = variant.fields
let variant_fields: Vec<_> = variant
.fields
.into_iter()
.map(|field| {
if field.ty.type_id() == TypeId::of::<usize>() {
@@ -2714,7 +2728,7 @@ pub fn generate_instructions_rs() -> TokenStream {
let ident = variant.ident;
let instr_ident = format_ident!("Call{}", ident);
let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
let placeholder_ids: Vec<_> = (0..variant_fields.len())
.map(|n| format_ident!("f_{}", n))
.collect();
@@ -2732,11 +2746,9 @@ pub fn generate_instructions_rs() -> TokenStream {
}
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
is_inbuilt_arms.push(quote! {
(atom!(#name), #arity) => true
});
}
for (name, arity, variant) in instr_data.clause_type_variants {
@@ -2758,7 +2770,8 @@ pub fn generate_instructions_rs() -> TokenStream {
continue;
}
let variant_fields: Vec<_> = variant.fields
let variant_fields: Vec<_> = variant
.fields
.into_iter()
.map(|field| {
if field.ty == parse_quote! { usize } {
@@ -2792,7 +2805,7 @@ pub fn generate_instructions_rs() -> TokenStream {
let ident = variant.ident;
let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
let placeholder_ids: Vec<_> = (0..variant_fields.len())
.map(|n| format_ident!("f_{}", n))
.collect();
@@ -2807,14 +2820,13 @@ pub fn generate_instructions_rs() -> TokenStream {
}
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), _arity) => true
}
);
is_inbuilt_arms.push(quote! {
(atom!(#name), _arity) => true
});
}
let to_execute_arms: Vec<_> = instr_data.instr_variants
let to_execute_arms: Vec<_> = instr_data
.instr_variants
.iter()
.cloned()
.filter_map(|(_, _, _, variant)| {
@@ -2827,12 +2839,11 @@ pub fn generate_instructions_rs() -> TokenStream {
0
};
let placeholder_ids: Vec<_> = (0 .. enum_arity)
.map(|n| format_ident!("f_{}", n))
.collect();
let placeholder_ids: Vec<_> =
(0..enum_arity).map(|n| format_ident!("f_{}", n)).collect();
if variant_string.starts_with("Call") {
let execute_ident = format_ident!("Execute{}", variant_string["Call".len() ..]);
let execute_ident = format_ident!("Execute{}", variant_string["Call".len()..]);
Some(if enum_arity == 0 {
quote! {
@@ -2847,7 +2858,7 @@ pub fn generate_instructions_rs() -> TokenStream {
})
} else if variant_string.starts_with("DefaultCall") {
let execute_ident =
format_ident!("DefaultExecute{}", variant_string["DefaultCall".len() ..]);
format_ident!("DefaultExecute{}", variant_string["DefaultCall".len()..]);
Some(if enum_arity == 0 {
quote! {
@@ -2866,7 +2877,8 @@ pub fn generate_instructions_rs() -> TokenStream {
})
.collect();
let is_execute_arms: Vec<_> = instr_data.instr_variants
let is_execute_arms: Vec<_> = instr_data
.instr_variants
.iter()
.cloned()
.filter_map(|(_, _, _, variant)| {
@@ -2909,7 +2921,8 @@ pub fn generate_instructions_rs() -> TokenStream {
})
.collect();
let to_default_arms: Vec<_> = instr_data.instr_variants
let to_default_arms: Vec<_> = instr_data
.instr_variants
.iter()
.cloned()
.filter_map(|(_, _, countable_inference, variant)| {
@@ -2926,9 +2939,8 @@ pub fn generate_instructions_rs() -> TokenStream {
0
};
let placeholder_ids: Vec<_> = (0 .. enum_arity)
.map(|n| format_ident!("f_{}", n))
.collect();
let placeholder_ids: Vec<_> =
(0..enum_arity).map(|n| format_ident!("f_{}", n)).collect();
Some(if enum_arity == 0 {
quote! {
@@ -2947,7 +2959,8 @@ pub fn generate_instructions_rs() -> TokenStream {
})
.collect();
let control_flow_arms: Vec<_> = instr_data.instr_variants
let control_flow_arms: Vec<_> = instr_data
.instr_variants
.iter()
.cloned()
.filter_map(|(_, _, _, variant)| {
@@ -2975,7 +2988,8 @@ pub fn generate_instructions_rs() -> TokenStream {
})
.collect();
let instr_macro_arms: Vec<_> = instr_data.instr_variants
let instr_macro_arms: Vec<_> = instr_data
.instr_variants
.iter()
.rev() // produce default, execute & default & execute cases first.
.cloned()
@@ -2984,7 +2998,7 @@ pub fn generate_instructions_rs() -> TokenStream {
let variant_string = variant.ident.to_string();
let arity = match arity {
Arity::Static(arity) => arity,
_ => 1
_ => 1,
};
Some(if variant_string.starts_with("Execute") {
@@ -3061,9 +3075,10 @@ pub fn generate_instructions_rs() -> TokenStream {
})
.collect();
let name_and_arity_arms: Vec<_> = instr_data.instr_variants
let name_and_arity_arms: Vec<_> = instr_data
.instr_variants
.into_iter()
.map(|(name,arity,_,variant)| {
.map(|(name, arity, _, variant)| {
let ident = &variant.ident;
let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
@@ -3293,8 +3308,10 @@ pub fn generate_instructions_rs() -> TokenStream {
fn is_callable(id: &Ident) -> bool {
let id = id.to_string();
id.starts_with("Call") || id.starts_with("Execute") || id.starts_with("DefaultCall") ||
id.starts_with("DefaultExecute")
id.starts_with("Call")
|| id.starts_with("Execute")
|| id.starts_with("DefaultCall")
|| id.starts_with("DefaultExecute")
}
fn is_non_default_callable(id: &Ident) -> bool {
@@ -3315,7 +3332,8 @@ fn create_instr_variant(id: Ident, mut variant: Variant) -> Variant {
}
fn prop_from_ident<DiscriminantT>(id: &Ident, key: &'static str) -> &'static str
where DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug
where
DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug,
{
let disc = match DiscriminantT::from_str(id.to_string().as_str()) {
Ok(disc) => disc,
@@ -3335,7 +3353,7 @@ fn prop_from_ident<DiscriminantT>(id: &Ident, key: &'static str) -> &'static str
#[derive(Clone, Copy)]
enum Arity {
Static(usize),
Ident(&'static str)
Ident(&'static str),
}
impl From<&'static str> for Arity {
@@ -3427,9 +3445,13 @@ impl InstructionData {
(name, arity, CountableInference::NotCounted)
} else if id == "InstructionTemplate" {
( prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Name"),
Arity::from(prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Arity")),
CountableInference::NotCounted
(
prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Name"),
Arity::from(prop_from_ident::<InstructionTemplateDiscriminants>(
&variant.ident,
"Arity",
)),
CountableInference::NotCounted,
)
} else if id == "ClauseType" {
let (name, arity) = add_discriminant_data::<ClauseTypeDiscriminants>(
@@ -3446,19 +3468,16 @@ impl InstructionData {
let v_string = variant.ident.to_string();
let v_ident = if v_string.starts_with("Call") {
format_ident!("{}", v_string["Call".len() ..])
format_ident!("{}", v_string["Call".len()..])
} else {
variant.ident.clone()
};
let generated_variant = create_instr_variant(
format_ident!("{}{}", prefix, v_ident),
variant.clone(),
);
let generated_variant =
create_instr_variant(format_ident!("{}{}", prefix, v_ident), variant.clone());
self.instr_variants.push(
(name, arity, countable_inference, generated_variant)
);
self.instr_variants
.push((name, arity, countable_inference, generated_variant));
}
fn generate_instruction_enum_loop(&mut self, input: syn::DeriveInput) {
@@ -3480,10 +3499,10 @@ impl InstructionData {
self.label_variant(&input.ident, "Call", variant.clone());
self.label_variant(&input.ident, "Execute", variant.clone());
if input.ident == "BuiltInClauseType" ||
input.ident == "CompareNumber" ||
input.ident == "CompareTerm" ||
input.ident == "ClauseType"
if input.ident == "BuiltInClauseType"
|| input.ident == "CompareNumber"
|| input.ident == "CompareTerm"
|| input.ident == "ClauseType"
{
self.label_variant(&input.ident, "DefaultCall", variant.clone());
self.label_variant(&input.ident, "DefaultExecute", variant);

View File

@@ -1,7 +1,7 @@
use proc_macro2::TokenStream;
use syn::*;
use syn::parse::*;
use syn::visit::*;
use syn::*;
use indexmap::IndexSet;
@@ -11,7 +11,9 @@ struct StaticStrVisitor {
impl StaticStrVisitor {
fn new() -> Self {
Self { static_strs: IndexSet::new() }
Self {
static_strs: IndexSet::new(),
}
}
}

491
flamegraph.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 4.8 MiB

View File

@@ -4,12 +4,16 @@ use crate::machine::loader::LiveLoadState;
use crate::machine::machine_indices::*;
use crate::machine::streams::*;
use crate::raw_block::*;
use crate::rcu::Rcu;
use crate::rcu::RcuRef;
use crate::read::*;
use ordered_float::OrderedFloat;
use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat;
use tokio::sync::RwLock;
use std::alloc;
use std::cell::UnsafeCell;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem;
@@ -22,7 +26,9 @@ macro_rules! arena_alloc {
($e:expr, $arena:expr) => {{
let result = $e;
#[allow(unused_unsafe)]
unsafe { ArenaAllocated::alloc($arena, result) }
unsafe {
ArenaAllocated::alloc($arena, result)
}
}};
}
@@ -31,24 +37,36 @@ macro_rules! float_alloc {
($e:expr, $arena:expr) => {{
let result = $e;
#[allow(unused_unsafe)]
unsafe { $arena.f64_tbl.build_with(result) }
unsafe {
$arena.f64_tbl.build_with(result).as_ptr()
}
}};
}
#[cfg(test)]
use std::cell::RefCell;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
const F64_TABLE_INIT_SIZE: usize = 1 << 16;
const F64_TABLE_ALIGN: usize = 8;
#[cfg(test)]
thread_local! {
static F64_TABLE_BUF_BASE: RefCell<*const u8> = RefCell::new(ptr::null_mut());
#[inline(always)]
fn global_f64table() -> &'static RwLock<Weak<F64Table>> {
#[cfg(feature = "rust_beta_channel")]
{
// const Weak::new will be stabilized in 1.73 which is currently in beta,
// till then we need a OnceLock for initialization
static GLOBAL_ATOM_TABLE: RwLock<Weak<F64Table>> = RwLock::const_new(Weak::new());
&GLOBAL_ATOM_TABLE
}
#[cfg(not(feature = "rust_beta_channel"))]
{
use std::sync::OnceLock;
static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<F64Table>>> = OnceLock::new();
GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
}
}
#[cfg(not(test))]
static mut F64_TABLE_BUF_BASE: *const u8 = ptr::null_mut();
impl RawBlockTraits for F64Table {
#[inline]
fn init_size() -> usize {
@@ -63,69 +81,86 @@ impl RawBlockTraits for F64Table {
#[derive(Debug)]
pub struct F64Table {
block: RawBlock<F64Table>,
}
impl Drop for F64Table {
fn drop(&mut self) {
self.block.deallocate();
}
}
#[cfg(test)]
fn set_f64_tbl_buf_base(ptr: *const u8) {
F64_TABLE_BUF_BASE.with(|f64_table_buf_base| {
*f64_table_buf_base.borrow_mut() = ptr;
});
}
#[cfg(test)]
pub(crate) fn get_f64_tbl_buf_base() -> *const u8 {
F64_TABLE_BUF_BASE.with(|f64_table_buf_base| *f64_table_buf_base.borrow())
}
#[cfg(not(test))]
fn set_f64_tbl_buf_base(ptr: *const u8) {
unsafe {
F64_TABLE_BUF_BASE = ptr;
}
}
#[cfg(not(test))]
pub(crate) fn get_f64_tbl_buf_base() -> *const u8 {
unsafe { F64_TABLE_BUF_BASE }
block: Rcu<RawBlock<F64Table>>,
update: Mutex<()>,
}
#[inline(always)]
pub fn lookup_float(offset: usize) -> *mut OrderedFloat<f64> {
let base = get_f64_tbl_buf_base() as usize;
(base + offset) as *mut _
pub fn lookup_float(
offset: F64Offset,
) -> RcuRef<RawBlock<F64Table>, UnsafeCell<OrderedFloat<f64>>> {
let f64table = global_f64table()
.blocking_read()
.upgrade()
.expect("We should only be looking up floats while there is a float table");
RcuRef::try_map(f64table.block.active_epoch(), |raw_block| unsafe {
raw_block
.base
.offset(offset.0 as isize)
.cast_mut()
.cast::<UnsafeCell<OrderedFloat<f64>>>()
.as_ref()
})
.expect("The offset should result in a non-null pointer")
}
impl F64Table {
#[inline]
pub fn new() -> Self {
let table = Self { block: RawBlock::new() };
set_f64_tbl_buf_base(table.block.base);
table
pub fn new() -> Arc<Self> {
let upgraded = global_f64table().blocking_read().upgrade();
// don't inline upgraded, otherwise temporary will be dropped too late in case of None
if let Some(atom_table) = upgraded {
atom_table
} else {
let mut guard = global_f64table().blocking_write();
// try to upgrade again in case we lost the race on the write lock
if let Some(atom_table) = guard.upgrade() {
atom_table
} else {
let atom_table = Arc::new(Self {
block: Rcu::new(RawBlock::new()),
update: Mutex::new(()),
});
*guard = Arc::downgrade(&atom_table);
atom_table
}
}
}
pub unsafe fn build_with(&mut self, value: f64) -> F64Ptr {
pub unsafe fn build_with(&self, value: f64) -> F64Offset {
let update_guard = self.update.lock();
// we don't have an index table for lookups as AtomTable does so
// just get the epoch after we take the upgrade lock
let mut block_epoch = self.block.active_epoch();
let mut ptr;
loop {
ptr = self.block.alloc(mem::size_of::<f64>());
ptr = block_epoch.alloc(mem::size_of::<f64>());
if ptr.is_null() {
self.block.grow();
set_f64_tbl_buf_base(self.block.base);
let new_block = block_epoch.grow_new().unwrap();
self.block.replace(new_block);
block_epoch = self.block.active_epoch();
} else {
break;
}
}
ptr::write(ptr as *mut OrderedFloat<f64>, OrderedFloat(value));
F64Ptr(ptr::NonNull::new_unchecked(ptr as *mut _))
let float = F64Offset {
0: ptr as usize - block_epoch.base as usize,
};
// atometable would have to update the index table at this point
// expicit drop to ensure we don't accidentally drop it early
drop(update_guard);
float
}
}
@@ -141,7 +176,7 @@ pub enum ArenaHeaderTag {
OutputFileStream = 0b10100,
NamedTcpStream = 0b011100,
NamedTlsStream = 0b100000,
HttpReadStream = 0b100001,
HttpReadStream = 0b100001,
HttpWriteStream = 0b100010,
ReadlineStream = 0b110000,
StaticStringStream = 0b110100,
@@ -276,7 +311,9 @@ impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
#[inline]
pub fn set_tag(&mut self, tag: ArenaHeaderTag) {
unsafe { (*self.header_ptr_mut()).set_tag(tag); }
unsafe {
(*self.header_ptr_mut()).set_tag(tag);
}
}
#[inline]
@@ -313,10 +350,10 @@ pub trait ArenaAllocated: Sized {
unsafe fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
let size = value.size() + mem::size_of::<AllocSlab>();
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
let align = mem::align_of::<AllocSlab>() * 2;
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
let align = mem::align_of::<AllocSlab>();
let layout = alloc::Layout::from_size_align_unchecked(size, align);
@@ -334,12 +371,18 @@ pub trait ArenaAllocated: Sized {
}
}
#[derive(Copy, Clone, Debug)]
pub struct F64Ptr(pub ptr::NonNull<OrderedFloat<f64>>);
#[derive(Debug)]
pub struct F64Ptr(RcuRef<RawBlock<F64Table>, UnsafeCell<OrderedFloat<f64>>>);
impl Clone for F64Ptr {
fn clone(&self) -> Self {
Self(RcuRef::clone(&self.0))
}
}
impl PartialEq for F64Ptr {
fn eq(&self, other: &F64Ptr) -> bool {
self.0 == other.0 || &**self == &**other
RcuRef::ptr_eq(&self.0, &other.0) || self.deref() == other.deref()
}
}
@@ -375,28 +418,26 @@ impl Deref for F64Ptr {
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.0.as_ptr() }
unsafe { &*self.0.get().as_ref().unwrap() }
}
}
impl DerefMut for F64Ptr {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.0.as_ptr() }
unsafe { &mut *self.0.get().as_mut().unwrap() }
}
}
impl F64Ptr {
#[inline(always)]
pub fn from_offset(offset: usize) -> Self {
unsafe {
F64Ptr(ptr::NonNull::new_unchecked(lookup_float(offset)))
}
pub fn from_offset(offset: F64Offset) -> Self {
Self(lookup_float(offset))
}
#[inline(always)]
pub fn as_offset(&self) -> F64Offset {
F64Offset(self.0.as_ptr() as usize - get_f64_tbl_buf_base() as usize)
F64Offset(self.0.get() as usize - RcuRef::get_root(&self.0).base as usize)
}
}
@@ -416,7 +457,7 @@ impl F64Offset {
#[inline(always)]
pub fn as_ptr(self) -> F64Ptr {
F64Ptr::from_offset(self.0)
F64Ptr::from_offset(self)
}
#[inline(always)]
@@ -577,20 +618,20 @@ impl ArenaAllocated for HttpListener {
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::HttpListener
ArenaHeaderTag::HttpListener
}
#[inline]
fn size(&self) -> usize {
mem::size_of::<Self>()
mem::size_of::<Self>()
}
#[inline]
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
unsafe {
ptr::write(dst, self);
TypedArenaPtr::new(dst as *mut Self)
}
unsafe {
ptr::write(dst, self);
TypedArenaPtr::new(dst as *mut Self)
}
}
}
@@ -600,20 +641,20 @@ impl ArenaAllocated for HttpResponse {
#[inline]
fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::HttpResponse
ArenaHeaderTag::HttpResponse
}
#[inline]
fn size(&self) -> usize {
mem::size_of::<Self>()
mem::size_of::<Self>()
}
#[inline]
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
unsafe {
ptr::write(dst, self);
TypedArenaPtr::new(dst as *mut Self)
}
unsafe {
ptr::write(dst, self);
TypedArenaPtr::new(dst as *mut Self)
}
}
}
@@ -664,7 +705,7 @@ impl ArenaAllocated for IndexPtr {
#[derive(Clone, Copy, Debug)]
struct AllocSlab {
next: *mut AllocSlab,
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
_padding: u32,
header: ArenaHeader,
}
@@ -672,7 +713,7 @@ struct AllocSlab {
#[derive(Debug)]
pub struct Arena {
base: *mut AllocSlab,
pub f64_tbl: F64Table,
pub f64_tbl: Arc<F64Table>,
}
unsafe impl Send for Arena {}
@@ -681,7 +722,10 @@ unsafe impl Sync for Arena {}
impl Arena {
#[inline]
pub fn new() -> Self {
Arena { base: ptr::null_mut(), f64_tbl: F64Table::new() }
Arena {
base: ptr::null_mut(),
f64_tbl: F64Table::new(),
}
}
}
@@ -712,10 +756,10 @@ unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
#[cfg(feature = "http")]
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<HttpReadStream>>>());
}
ArenaHeaderTag::HttpWriteStream => {
ArenaHeaderTag::HttpWriteStream => {
#[cfg(feature = "http")]
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<HttpWriteStream>>>());
}
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<HttpWriteStream>>>());
}
ArenaHeaderTag::ReadlineStream => {
ptr::drop_in_place(value.payload_offset::<StreamLayout<ReadlineStream>>());
}
@@ -731,29 +775,29 @@ unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
ptr::drop_in_place(value.payload_offset::<LiveLoadState>());
}
ArenaHeaderTag::Dropped => {
}
ArenaHeaderTag::Dropped => {}
ArenaHeaderTag::TcpListener => {
ptr::drop_in_place(value.payload_offset::<TcpListener>());
}
ArenaHeaderTag::HttpListener => {
ArenaHeaderTag::HttpListener => {
#[cfg(feature = "http")]
ptr::drop_in_place(value.payload_offset::<HttpListener>());
}
ArenaHeaderTag::HttpResponse => {
ptr::drop_in_place(value.payload_offset::<HttpListener>());
}
ArenaHeaderTag::HttpResponse => {
#[cfg(feature = "http")]
ptr::drop_in_place(value.payload_offset::<HttpResponse>());
}
ptr::drop_in_place(value.payload_offset::<HttpResponse>());
}
ArenaHeaderTag::StandardOutputStream => {
ptr::drop_in_place(value.payload_offset::<StreamLayout<StandardOutputStream>>());
}
ArenaHeaderTag::StandardErrorStream => {
ptr::drop_in_place(value.payload_offset::<StreamLayout<StandardErrorStream>>());
}
ArenaHeaderTag::NullStream | ArenaHeaderTag::IndexPtrUndefined |
ArenaHeaderTag::IndexPtrDynamicUndefined | ArenaHeaderTag::IndexPtrDynamicIndex |
ArenaHeaderTag::IndexPtrIndex => {
}
ArenaHeaderTag::NullStream
| ArenaHeaderTag::IndexPtrUndefined
| ArenaHeaderTag::IndexPtrDynamicUndefined
| ArenaHeaderTag::IndexPtrDynamicIndex
| ArenaHeaderTag::IndexPtrIndex => {}
}
}
@@ -801,23 +845,25 @@ const_assert!(mem::size_of::<OrderedFloat<f64>>() == 8);
#[cfg(test)]
mod tests {
use std::ops::Deref;
use crate::machine::mock_wam::*;
use crate::machine::partial_string::*;
use ordered_float::OrderedFloat;
use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat;
#[test]
fn float_ptr_cast() {
let mut wam = MockWAM::new();
let wam = MockWAM::new();
let f = 0f64;
let fp = float_alloc!(f, wam.machine_st.arena);
let mut cell = HeapCellValue::from(fp);
let mut cell = HeapCellValue::from(fp.clone());
assert_eq!(cell.get_tag(), HeapCellValueTag::F64);
assert_eq!(cell.get_mark_bit(), false);
assert_eq!(*fp, OrderedFloat(f));
assert_eq!(fp.deref(), &OrderedFloat(f));
cell.set_mark_bit(true);
@@ -834,12 +880,12 @@ mod tests {
#[test]
fn heap_cell_value_const_cast() {
let mut wam = MockWAM::new();
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
let const_value = HeapCellValue::from(ConsPtr::build_with(
0x0000_0431 as *const _,
ConsPtrMaskTag::Cons,
));
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
let const_value = HeapCellValue::from(ConsPtr::build_with(
0x0000_5555_ff00_0431 as *const _,
ConsPtrMaskTag::Cons,
@@ -847,7 +893,10 @@ mod tests {
match const_value.to_untyped_arena_ptr() {
Some(arena_ptr) => {
assert_eq!(arena_ptr.into_bytes(), const_value.to_untyped_arena_ptr_bytes());
assert_eq!(
arena_ptr.into_bytes(),
const_value.to_untyped_arena_ptr_bytes()
);
}
None => {
assert!(false);
@@ -860,7 +909,10 @@ mod tests {
match stream_cell.to_untyped_arena_ptr() {
Some(arena_ptr) => {
assert_eq!(arena_ptr.into_bytes(), stream_cell.to_untyped_arena_ptr_bytes());
assert_eq!(
arena_ptr.into_bytes(),
stream_cell.to_untyped_arena_ptr_bytes()
);
}
None => {
assert!(false);
@@ -875,8 +927,7 @@ mod tests {
// integer
let big_int: Integer = 2 * Integer::from(1u64 << 63);
let big_int_ptr: TypedArenaPtr<Integer> =
arena_alloc!(big_int, &mut wam.machine_st.arena);
let big_int_ptr: TypedArenaPtr<Integer> = arena_alloc!(big_int, &mut wam.machine_st.arena);
assert!(!big_int_ptr.as_ptr().is_null());
@@ -951,8 +1002,8 @@ mod tests {
let f_atom = atom!("f");
let g_atom = atom!("g");
assert_eq!(f_atom.as_str(), "f");
assert_eq!(g_atom.as_str(), "g");
assert_eq!(&*f_atom.as_str(), "f");
assert_eq!(&*g_atom.as_str(), "g");
let f_atom_cell = atom_as_cell!(f_atom);
let g_atom_cell = atom_as_cell!(g_atom);
@@ -962,7 +1013,7 @@ mod tests {
match f_atom_cell.to_atom() {
Some(atom) => {
assert_eq!(f_atom, atom);
assert_eq!(atom.as_str(), "f");
assert_eq!(&*atom.as_str(), "f");
}
None => {
assert!(false);
@@ -973,7 +1024,7 @@ mod tests {
(HeapCellValueTag::Atom, (atom, arity)) => {
assert_eq!(f_atom, atom);
assert_eq!(arity, 0);
assert_eq!(atom.as_str(), "f");
assert_eq!(&*atom.as_str(), "f");
}
_ => { unreachable!() }
);
@@ -982,21 +1033,22 @@ mod tests {
(HeapCellValueTag::Atom, (atom, arity)) => {
assert_eq!(g_atom, atom);
assert_eq!(arity, 0);
assert_eq!(atom.as_str(), "g");
assert_eq!(&*atom.as_str(), "g");
}
_ => { unreachable!() }
);
// complete string
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "ronan", &mut wam.machine_st.atom_tbl);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "ronan", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr);
match pstr_cell.to_pstr() {
Some(pstr) => {
assert_eq!(pstr.as_str_from(0), "ronan");
assert_eq!(&*pstr.as_str_from(0), "ronan");
}
None => {
assert!(false);
@@ -1006,7 +1058,7 @@ mod tests {
read_heap_cell!(pstr_cell,
(HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom);
assert_eq!(pstr.as_str_from(0), "ronan");
assert_eq!(&*pstr.as_str_from(0), "ronan");
}
_ => { unreachable!() }
);
@@ -1115,7 +1167,7 @@ mod tests {
read_heap_cell!(cell,
(HeapCellValueTag::Atom, (el, _arity)) => {
assert_eq!(el.flat_index(), empty_list_as_cell!().get_value());
assert_eq!(el.as_str(), "[]");
assert_eq!(&*el.as_str(), "[]");
}
_ => { unreachable!() }
);

View File

@@ -160,13 +160,13 @@ fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: &Literal) -> Result<(), Ari
Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))),
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))),
Literal::Atom(name) if name == &atom!("e") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::E))
Number::Float(OrderedFloat(std::f64::consts::E)),
)),
Literal::Atom(name) if name == &atom!("pi") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::PI))
Number::Float(OrderedFloat(std::f64::consts::PI)),
)),
Literal::Atom(name) if name == &atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::EPSILON))
Number::Float(OrderedFloat(std::f64::EPSILON)),
)),
_ => return Err(ArithmeticError::NonEvaluableFunctor(*c, 0)),
}
@@ -328,23 +328,14 @@ impl<'a> ArithmeticEvaluator<'a> {
let var_num = name.to_var_num().unwrap();
let r = if lvl == Level::Shallow {
self.marker.mark_non_callable(
var_num,
arg,
term_loc,
cell,
&mut code,
)
self.marker
.mark_non_callable(var_num, arg, term_loc, cell, &mut code)
} else if term_loc.is_last() || cell.get().norm().reg_num() == 0 {
let r = self.marker.get_binding(var_num);
if r.reg_num() == 0 {
self.marker.mark_var::<QueryInstruction>(
var_num,
lvl,
cell,
term_loc,
&mut code,
var_num, lvl, cell, term_loc, &mut code,
);
cell.get().norm()
} else {
@@ -438,7 +429,7 @@ fn classify_float(f: f64) -> Result<f64, EvalError> {
}
}
FpCategory::Nan => Err(EvalError::Undefined),
_ => Ok(f)
_ => Ok(f),
}
}
@@ -553,8 +544,12 @@ impl PartialEq for Number {
(&Number::Fixnum(n1), &Number::Float(n2)) => OrderedFloat(n1.get_num() as f64).eq(&n2),
(&Number::Float(n1), &Number::Fixnum(n2)) => n1.eq(&OrderedFloat(n2.get_num() as f64)),
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.eq(n2),
(&Number::Integer(ref n1), Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).eq(n2),
(&Number::Float(n1), &Number::Integer(ref n2)) => n1.eq(&OrderedFloat(n2.to_f64().value())),
(&Number::Integer(ref n1), Number::Float(n2)) => {
OrderedFloat(n1.to_f64().value()).eq(n2)
}
(&Number::Float(n1), &Number::Integer(ref n2)) => {
n1.eq(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Integer(ref n1), &Number::Rational(ref n2)) => {
#[cfg(feature = "num")]
{
@@ -575,8 +570,12 @@ impl PartialEq for Number {
(&**n1).num_eq(&**n2)
}
}
(&Number::Rational(ref n1), &Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).eq(&n2),
(&Number::Float(n1), &Number::Rational(ref n2)) => n1.eq(&OrderedFloat(n2.to_f64().value())),
(&Number::Rational(ref n1), &Number::Float(n2)) => {
OrderedFloat(n1.to_f64().value()).eq(&n2)
}
(&Number::Float(n1), &Number::Rational(ref n2)) => {
n1.eq(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Float(f1), &Number::Float(f2)) => f1.eq(&f2),
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.eq(&r2),
}
@@ -645,7 +644,9 @@ impl Ord for Number {
(&Number::Float(n1), &Number::Fixnum(n2)) => n1.cmp(&OrderedFloat(n2.get_num() as f64)),
(&Number::Integer(n1), &Number::Integer(n2)) => (*n1).cmp(&*n2),
(&Number::Integer(n1), Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).cmp(n2),
(&Number::Float(n1), &Number::Integer(ref n2)) => n1.cmp(&OrderedFloat(n2.to_f64().value())),
(&Number::Float(n1), &Number::Integer(ref n2)) => {
n1.cmp(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Integer(n1), &Number::Rational(n2)) => {
#[cfg(feature = "num")]
{
@@ -666,8 +667,12 @@ impl Ord for Number {
(&*n1).num_partial_cmp(&*n2).unwrap_or(Ordering::Less)
}
}
(&Number::Rational(n1), &Number::Float(n2)) => OrderedFloat(n1.to_f64().value()).cmp(&n2),
(&Number::Float(n1), &Number::Rational(n2)) => n1.cmp(&OrderedFloat(n2.to_f64().value())),
(&Number::Rational(n1), &Number::Float(n2)) => {
OrderedFloat(n1.to_f64().value()).cmp(&n2)
}
(&Number::Float(n1), &Number::Rational(n2)) => {
n1.cmp(&OrderedFloat(n2.to_f64().value()))
}
(&Number::Float(f1), &Number::Float(f2)) => f1.cmp(&f2),
(&Number::Rational(r1), &Number::Rational(r2)) => (*r1).cmp(&*r2),
}

View File

@@ -1,18 +1,23 @@
use crate::parser::ast::MAX_ARITY;
use crate::raw_block::*;
use crate::rcu::{Rcu, RcuRef};
use crate::types::*;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::slice;
use std::str;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
use indexmap::IndexSet;
use modular_bitfield::prelude::*;
use tokio::sync::RwLock;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Atom {
@@ -33,65 +38,43 @@ impl<'a> From<&'a Atom> for Atom {
impl From<bool> for Atom {
#[inline]
fn from(value: bool) -> Self {
if value { atom!("true") } else { atom!("false") }
if value {
atom!("true")
} else {
atom!("false")
}
}
}
impl indexmap::Equivalent<Atom> for str {
fn equivalent(&self, key: &Atom) -> bool {
&*key.as_str() == self
}
}
const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
const ATOM_TABLE_ALIGN: usize = 8;
#[cfg(test)]
thread_local! {
static ATOM_TABLE_BUF_BASE: std::cell::RefCell<*const u8> = std::cell::RefCell::new(ptr::null_mut());
}
#[cfg(not(test))]
static ATOM_TABLE_BUF_BASE: std::sync::atomic::AtomicPtr<u8> =
std::sync::atomic::AtomicPtr::new(ptr::null_mut());
fn set_atom_tbl_buf_base(old_ptr: *const u8, new_ptr: *const u8) -> Result<(), *const u8> {
#[cfg(test)]
#[inline(always)]
fn global_atom_table() -> &'static RwLock<Weak<AtomTable>> {
#[cfg(feature = "rust_beta_channel")]
{
ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| {
let mut borrow = atom_table_buf_base.borrow_mut();
if *borrow != old_ptr {
Err(*borrow)
} else {
*borrow = new_ptr;
Ok(())
}
})?;
};
#[cfg(not(test))]
// const Weak::new will be stabilized in 1.73 which is currently in beta,
// till then we need a OnceLock for initialization
static GLOBAL_ATOM_TABLE: RwLock<Weak<AtomTable>> = RwLock::const_new(Weak::new());
&GLOBAL_ATOM_TABLE
}
#[cfg(not(feature = "rust_beta_channel"))]
{
ATOM_TABLE_BUF_BASE
.compare_exchange(
old_ptr.cast_mut(),
new_ptr.cast_mut(),
std::sync::atomic::Ordering::Relaxed,
std::sync::atomic::Ordering::Relaxed,
)
.map_err(|ptr| ptr.cast_const())
}?;
Ok(())
}
pub(crate) fn get_atom_tbl_buf_base() -> *const u8 {
#[cfg(test)]
{
ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| *atom_table_buf_base.borrow())
}
#[cfg(not(test))]
{
ATOM_TABLE_BUF_BASE.load(std::sync::atomic::Ordering::Relaxed)
use std::sync::OnceLock;
static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<AtomTable>>> = OnceLock::new();
GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
}
}
#[test]
#[should_panic(expected = "Overwriting atom table base pointer")]
fn atomtable_is_not_concurrency_safe() {
let _table_a = AtomTable::new();
let _table_b = AtomTable::new();
#[inline(always)]
fn arc_atom_table() -> Option<Arc<AtomTable>> {
global_atom_table().blocking_read().upgrade()
}
impl RawBlockTraits for AtomTable {
@@ -109,9 +92,11 @@ impl RawBlockTraits for AtomTable {
#[bitfield]
#[derive(Copy, Clone, Debug)]
struct AtomHeader {
#[allow(unused)] m: bool,
#[allow(unused)]
m: bool,
len: B50,
#[allow(unused)] padding: B13,
#[allow(unused)]
padding: B13,
}
impl AtomHeader {
@@ -120,13 +105,6 @@ impl AtomHeader {
}
}
impl Borrow<str> for Atom {
#[inline]
fn borrow(&self) -> &str {
self.as_str()
}
}
impl Hash for Atom {
#[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) {
@@ -142,29 +120,76 @@ macro_rules! is_char {
};
}
impl Atom {
#[inline]
pub fn buf(self) -> *const u8 {
let ptr = self.as_ptr();
pub enum AtomString<'a> {
Static(&'a str),
Dynamic(AtomTableRef<str>),
}
if ptr.is_null() {
return ptr::null();
impl AtomString<'_> {
pub fn map<F>(self, f: F) -> Self
where
for<'a> F: FnOnce(&'a str) -> &'a str,
{
match self {
Self::Static(reference) => Self::Static(f(reference)),
Self::Dynamic(guard) => Self::Dynamic(AtomTableRef::map(guard, f)),
}
}
}
(ptr as usize + mem::size_of::<AtomHeader>()) as *const u8
impl std::fmt::Debug for AtomString<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(self.deref(), f)
}
}
impl std::fmt::Display for AtomString<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(self.deref(), f)
}
}
impl std::ops::Deref for AtomString<'_> {
type Target = str;
fn deref(&self) -> &Self::Target {
match self {
Self::Static(reference) => reference,
Self::Dynamic(guard) => guard.deref(),
}
}
}
#[cfg(feature = "repl")]
impl rustyline::completion::Candidate for AtomString<'_> {
fn display(&self) -> &str {
self.deref()
}
fn replacement(&self) -> &str {
self.deref()
}
}
impl Atom {
#[inline(always)]
pub fn is_static(self) -> bool {
(self.index as usize) < STRINGS.len() << 3
}
#[inline(always)]
pub fn as_ptr(self) -> *const u8 {
pub fn as_ptr(self) -> Option<AtomTableRef<u8>> {
if self.is_static() {
ptr::null()
None
} else {
(get_atom_tbl_buf_base() as usize + (self.index as usize) - (STRINGS.len() << 3)) as *const u8
let atom_table =
arc_atom_table().expect("We should only have an Atom while there is an AtomTable");
unsafe {
AtomTableRef::try_map(atom_table.buf(), |buf| {
(buf as *const u8)
.offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
.as_ref()
})
}
}
}
@@ -178,7 +203,9 @@ impl Atom {
if self.is_static() {
STRINGS[(self.index >> 3) as usize].len()
} else {
unsafe { ptr::read(self.as_ptr() as *const AtomHeader).len() as _ }
let ptr = self.as_ptr().unwrap();
let ptr = ptr.deref() as *const u8 as *const AtomHeader;
unsafe { ptr::read(ptr) }.len() as _
}
}
@@ -194,41 +221,44 @@ impl Atom {
let c1 = it.next();
let c2 = it.next();
if c2.is_none() { c1 } else { None }
}
#[inline]
pub fn chars(&self) -> str::Chars {
self.as_str().chars()
}
#[inline]
pub fn as_str(&self) -> &str {
unsafe {
let ptr = self.as_ptr();
if ptr.is_null() {
return STRINGS[(self.index >> 3) as usize];
}
let header = ptr::read::<AtomHeader>(ptr as *const _);
let len = header.len() as usize;
let buf = (ptr as usize + mem::size_of::<AtomHeader>()) as *mut u8;
str::from_utf8_unchecked(slice::from_raw_parts(buf, len))
if c2.is_none() {
c1
} else {
None
}
}
pub fn defrock_brackets(&self, atom_tbl: &mut AtomTable) -> Self {
#[inline]
pub fn as_str(&self) -> AtomString<'static> {
if self.is_static() {
AtomString::Static(STRINGS[(self.index >> 3) as usize])
} else {
if let Some(ptr) = self.as_ptr() {
AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| {
let header =
unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
let len = header.len() as usize;
let buf =
unsafe { (ptr as *const u8).offset(mem::size_of::<AtomHeader>() as isize) };
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) }
}))
} else {
AtomString::Static(&STRINGS[(self.index >> 3) as usize])
}
}
}
pub fn defrock_brackets(&self, atom_tbl: &AtomTable) -> Self {
let s = self.as_str();
let s = if s.starts_with('(') && s.ends_with(')') {
let sub_str = if s.starts_with('(') && s.ends_with(')') {
&s['('.len_utf8()..s.len() - ')'.len_utf8()]
} else {
return *self;
};
atom_tbl.build_with(s)
AtomTable::build_with(&atom_tbl, &sub_str)
}
}
@@ -248,116 +278,156 @@ impl PartialOrd for Atom {
impl Ord for Atom {
#[inline]
fn cmp(&self, other: &Atom) -> Ordering {
self.as_str().cmp(other.as_str())
self.as_str().cmp(&*other.as_str())
}
}
#[derive(Debug)]
pub struct AtomTable {
pub struct InnerAtomTable {
block: RawBlock<AtomTable>,
pub table: IndexSet<Atom>,
pub table: Rcu<IndexSet<Atom>>,
}
#[cold]
fn atom_table_base_pointer_mismatch(expected: *const u8, got: *const u8) -> ! {
assert_eq!(expected, got, "Overwriting atom table base pointer, expected old value to be {expected:p}, but found {got:p}");
unreachable!("This should only be called in a case of a mismatch as such the assert_eq should have failed!")
#[derive(Debug)]
pub struct AtomTable {
inner: Rcu<InnerAtomTable>,
// this lock is taking during resizing
update: Mutex<()>,
}
impl Drop for AtomTable {
fn drop(&mut self) {
if let Err(got) = set_atom_tbl_buf_base(self.block.base, ptr::null()) {
atom_table_base_pointer_mismatch(self.block.base, got);
}
self.block.deallocate();
pub type AtomTableRef<M> = RcuRef<InnerAtomTable, M>;
impl InnerAtomTable {
#[inline(always)]
fn lookup_str(self: &InnerAtomTable, string: &str) -> Option<Atom> {
STATIC_ATOMS_MAP
.get(string)
.cloned()
.or_else(|| self.table.active_epoch().get(string).cloned())
}
}
impl AtomTable {
#[inline]
pub fn new() -> Self {
let mut block = RawBlock::new();
if let Err(got) = set_atom_tbl_buf_base(ptr::null(), block.base) {
block.deallocate();
atom_table_base_pointer_mismatch(ptr::null(), got);
}
Self {
block,
table: IndexSet::new(),
pub fn new() -> Arc<Self> {
let upgraded = global_atom_table().blocking_read().upgrade();
// don't inline upgraded, otherwise temporary will be dropped too late in case of None
if let Some(atom_table) = upgraded {
atom_table
} else {
let mut guard = global_atom_table().blocking_write();
// try to upgrade again in case we lost the race on the write lock
if let Some(atom_table) = guard.upgrade() {
atom_table
} else {
let atom_table = Arc::new(Self {
inner: Rcu::new(InnerAtomTable {
block: RawBlock::new(),
table: Rcu::new(IndexSet::new()),
}),
update: Mutex::new(()),
});
*guard = Arc::downgrade(&atom_table);
atom_table
}
}
}
#[inline]
pub fn buf(&self) -> *const u8 {
self.block.base as *const u8
pub fn buf(&self) -> AtomTableRef<u8> {
AtomTableRef::<InnerAtomTable>::map(self.inner.active_epoch(), |inner| {
unsafe { inner.block.base.as_ref() }.unwrap()
})
}
#[inline]
pub fn top(&self) -> *const u8 {
self.block.top
pub fn active_table(&self) -> RcuRef<IndexSet<Atom>, IndexSet<Atom>> {
self.inner.active_epoch().table.active_epoch()
}
#[inline(always)]
fn lookup_str(&self, string: &str) -> Option<Atom> {
STATIC_ATOMS_MAP.get(string).or_else(|| self.table.get(string)).cloned()
}
pub fn build_with(atom_table: &AtomTable, string: &str) -> Atom {
loop {
let mut block_epoch = atom_table.inner.active_epoch();
let mut table_epoch = block_epoch.table.active_epoch();
pub fn build_with(&mut self, string: &str) -> Atom {
if let Some(atom) = self.lookup_str(string) {
return atom;
}
if let Some(atom) = block_epoch.lookup_str(string) {
return atom;
}
// take a lock to prevent concurrent updates
let update_guard = atom_table.update.lock().unwrap();
let is_same_allocation =
RcuRef::same_epoch(&block_epoch, &atom_table.inner.active_epoch());
let is_same_atom_list =
RcuRef::same_epoch(&table_epoch, &block_epoch.table.active_epoch());
if !(is_same_allocation && is_same_atom_list) {
// some other thread raced us between our lookup and
// us aquring the update lock,
// try again
continue;
}
unsafe {
let size = mem::size_of::<AtomHeader>() + string.len();
let align_offset = 8 * mem::align_of::<AtomHeader>();
let size = (size & !(align_offset - 1)) + align_offset;
let len_ptr = {
let mut ptr;
loop {
ptr = self.block.alloc(size);
unsafe {
let len_ptr = loop {
let ptr = block_epoch.block.alloc(size);
if ptr.is_null() {
let old_base = self.block.base;
self.block.grow();
if let Err(got) = set_atom_tbl_buf_base(old_base, self.block.base) {
atom_table_base_pointer_mismatch(old_base, got);
}
// garbage collection would go here
let new_block = block_epoch.block.grow_new().unwrap();
let new_table = Rcu::new(table_epoch.clone());
let new_alloc = InnerAtomTable {
block: new_block,
table: new_table,
};
atom_table.inner.replace(new_alloc);
block_epoch = atom_table.inner.active_epoch();
table_epoch = block_epoch.table.active_epoch();
} else {
break;
break ptr;
}
}
};
ptr
};
let ptr_base = block_epoch.block.base as usize;
let ptr_base = self.block.base as usize;
write_to_ptr(string, len_ptr);
write_to_ptr(string, len_ptr);
let atom = Atom {
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
};
let atom = Atom {
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
};
let mut table = table_epoch.clone();
table.insert(atom);
block_epoch.table.replace(table);
self.table.insert(atom);
// expicit drop to ensure we don't accidentally drop it early
drop(update_guard);
atom
return atom;
}
}
}
}
unsafe impl Send for AtomTable {}
unsafe impl Sync for AtomTable {}
#[bitfield]
#[repr(u64)]
#[derive(Copy, Clone, Debug)]
pub struct AtomCell {
name: B46,
arity: B10,
#[allow(unused)] f: bool,
#[allow(unused)] m: bool,
#[allow(unused)] tag: B6,
#[allow(unused)]
f: bool,
#[allow(unused)]
m: bool,
#[allow(unused)]
tag: B6,
}
impl AtomCell {

View File

@@ -1,11 +1,12 @@
fn main() -> std::process::ExitCode {
use std::sync::atomic::Ordering;
use scryer_prolog::*;
use std::sync::atomic::Ordering;
#[cfg(feature = "repl")]
ctrlc::set_handler(move || {
scryer_prolog::machine::INTERRUPT.store(true, Ordering::Relaxed);
}).unwrap();
})
.unwrap();
let mut wam = machine::Machine::new();
wam.run_top_level()

View File

@@ -1,14 +1,14 @@
use crate::atom_table::*;
use crate::parser::ast::*;
use crate::temp_v;
use crate::allocator::*;
use crate::arithmetic::*;
use crate::atom_table::*;
use crate::debray_allocator::*;
use crate::forms::*;
use crate::indexing::*;
use crate::instructions::*;
use crate::iterators::*;
use crate::parser::ast::*;
use crate::targets::*;
use crate::temp_v;
use crate::types::*;
use crate::instr;
@@ -48,15 +48,20 @@ impl BranchCodeStack {
}
fn code<'a>(&'a mut self, default_code: &'a mut CodeDeque) -> &'a mut CodeDeque {
self.stack.last_mut()
self.stack
.last_mut()
.and_then(|stack| stack.last_mut())
.unwrap_or(default_code)
}
fn push_missing_vars(&mut self, depth: usize, marker: &mut DebrayAllocator) -> SubsumedBranchHits {
fn push_missing_vars(
&mut self,
depth: usize,
marker: &mut DebrayAllocator,
) -> SubsumedBranchHits {
let mut subsumed_hits = SubsumedBranchHits::with_hasher(FxBuildHasher::default());
for idx in (self.stack.len() - depth .. self.stack.len()).rev() {
for idx in (self.stack.len() - depth..self.stack.len()).rev() {
let branch = &mut marker.branch_stack[idx];
let branch_hits = &branch.hits;
@@ -91,14 +96,14 @@ impl BranchCodeStack {
fn push_jump_instrs(&mut self, depth: usize) {
// add 2 in each arm length to compensate for each jump
// instruction and each branch instruction not yet added.
let mut jump_span: usize = self.stack[self.stack.len() - depth ..]
let mut jump_span: usize = self.stack[self.stack.len() - depth..]
.iter()
.map(|branch| branch.iter().map(|code| code.len() + 2).sum::<usize>())
.sum();
jump_span -= depth;
for idx in self.stack.len() - depth .. self.stack.len() {
for idx in self.stack.len() - depth..self.stack.len() {
let inner_len = self.stack[idx].len();
for (inner_idx, code) in self.stack[idx].iter_mut().enumerate() {
@@ -117,9 +122,11 @@ impl BranchCodeStack {
fn pop_branch(&mut self, depth: usize, settings: CodeGenSettings) -> CodeDeque {
let mut combined_code = CodeDeque::new();
for mut branch_arm in self.stack.drain(self.stack.len() - depth ..).rev() {
for mut branch_arm in self.stack.drain(self.stack.len() - depth..).rev() {
let num_branch_arms = branch_arm.len();
branch_arm.last_mut().map(|code| code.extend(combined_code.drain(..)));
branch_arm
.last_mut()
.map(|code| code.extend(combined_code.drain(..)));
for (idx, code) in branch_arm.into_iter().enumerate() {
combined_code.push_back(if idx == 0 {
@@ -255,7 +262,7 @@ impl CodeGenSettings {
#[derive(Debug)]
pub(crate) struct CodeGenerator<'a> {
pub(crate) atom_tbl: &'a mut AtomTable,
pub(crate) atom_tbl: &'a AtomTable,
marker: DebrayAllocator,
settings: CodeGenSettings,
pub(crate) skeleton: PredicateSkeleton,
@@ -269,13 +276,7 @@ impl DebrayAllocator {
vr: &Cell<VarReg>,
code: &mut CodeDeque,
) -> RegType {
self.mark_var::<QueryInstruction>(
var_num,
Level::Shallow,
vr,
term_loc,
code,
);
self.mark_var::<QueryInstruction>(var_num, Level::Shallow, vr, term_loc, code);
vr.get().norm()
}
@@ -308,8 +309,8 @@ impl DebrayAllocator {
// decrement the arity of the PutStructure instruction by 1.
fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term) {
match instr {
Instruction::PutStructure(_, ref mut arity, _) |
Instruction::GetStructure(.., ref mut arity, _) => {
Instruction::PutStructure(_, ref mut arity, _)
| Instruction::GetStructure(.., ref mut arity, _) => {
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
// it is acceptable if arity == 0 is the result of
// this decrement. call/N will have to read the index
@@ -352,16 +353,16 @@ impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> {
fn structure_cell(term: &Term) -> Option<&Cell<RegType>> {
match term {
&Term::Cons(ref cell, ..) |
&Term::Clause(ref cell, ..) |
Term::PartialString(ref cell, ..) |
Term::CompleteString(ref cell, ..) => Some(cell),
&Term::Cons(ref cell, ..)
| &Term::Clause(ref cell, ..)
| Term::PartialString(ref cell, ..)
| Term::CompleteString(ref cell, ..) => Some(cell),
_ => None,
}
}
impl<'b> CodeGenerator<'b> {
pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
pub(crate) fn new(atom_tbl: &'b AtomTable, settings: CodeGenSettings) -> Self {
CodeGenerator {
atom_tbl,
marker: DebrayAllocator::new(),
@@ -392,7 +393,8 @@ impl<'b> CodeGenerator<'b> {
target: &mut CodeDeque,
) {
if self.marker.var_data.records[var_num].num_occurrences > 1 {
self.marker.mark_var::<Target>(var_num, Level::Deep, cell, term_loc, target);
self.marker
.mark_var::<Target>(var_num, Level::Deep, cell, term_loc, target);
} else {
Self::add_or_increment_void_instr::<Target>(target);
}
@@ -408,31 +410,33 @@ impl<'b> CodeGenerator<'b> {
&Term::AnonVar => {
Self::add_or_increment_void_instr::<Target>(target);
}
&Term::Cons(ref cell, ..) |
&Term::Clause(ref cell, ..) |
Term::PartialString(ref cell, ..) |
Term::CompleteString(ref cell, ..) => {
self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
&Term::Cons(ref cell, ..)
| &Term::Clause(ref cell, ..)
| Term::PartialString(ref cell, ..)
| Term::CompleteString(ref cell, ..) => {
self.marker
.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
target.push_back(Target::clause_arg_to_instr(cell.get()));
}
&Term::Literal(_, ref constant) => {
target.push_back(Target::constant_subterm(constant.clone()));
}
&Term::Var(ref cell, ref var_ptr) => {
self.deep_var_instr::<Target>(cell, var_ptr.to_var_num().unwrap(), term_loc, target);
self.deep_var_instr::<Target>(
cell,
var_ptr.to_var_num().unwrap(),
term_loc,
target,
);
}
};
}
fn compile_target<'a, Target, Iter>(
&mut self,
iter: Iter,
term_loc: GenContext,
) -> CodeDeque
fn compile_target<'a, Target, Iter>(&mut self, iter: Iter, term_loc: GenContext) -> CodeDeque
where
Target: crate::targets::CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>,
CodeGenerator<'b>: AddToFreeList<'a, Target>
CodeGenerator<'b>: AddToFreeList<'a, Target>,
{
let mut target = CodeDeque::new();
@@ -442,14 +446,19 @@ impl<'b> CodeGenerator<'b> {
if let GenContext::Head = term_loc {
self.marker.advance_arg();
} else {
self.marker.mark_anon_var::<Target>(lvl, term_loc, &mut target);
self.marker
.mark_anon_var::<Target>(lvl, term_loc, &mut target);
}
}
TermRef::Clause(lvl, cell, name, terms) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push_back(Target::to_structure(lvl, name, terms.len(), cell.get()));
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get());
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
self,
cell.get(),
);
if let Some(instr) = target.back_mut() {
if let Some(term) = terms.last() {
@@ -462,38 +471,52 @@ impl<'b> CodeGenerator<'b> {
}
for subterm in terms {
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, subterm);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, subterm,
);
}
}
TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push_back(Target::to_list(lvl, cell.get()));
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get());
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(
self,
cell.get(),
);
self.subterm_to_instr::<Target>(head, term_loc, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, head);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, tail);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, head,
);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, tail,
);
}
TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push_back(Target::to_pstr(lvl, *string, cell.get(), false));
}
TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push_back(Target::to_constant(lvl, *constant, cell.get()));
}
TermRef::PartialString(lvl, cell, string, tail) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
let atom = self.atom_tbl.build_with(&string);
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
let atom = AtomTable::build_with(&self.atom_tbl, &string);
target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
}
TermRef::CompleteString(lvl, cell, atom) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push_back(Target::to_pstr(lvl, atom, cell.get(), false));
}
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
@@ -563,9 +586,9 @@ impl<'b> CodeGenerator<'b> {
compare_number_instr!(cmp, at_1, at_2)
}
&InlinedClauseType::IsAtom(..) => match &terms[0] {
&Term::Literal(_, Literal::Char(_)) |
&Term::Literal(_, Literal::Atom(atom!("[]"))) |
&Term::Literal(_, Literal::Atom(..)) => {
&Term::Literal(_, Literal::Char(_))
| &Term::Literal(_, Literal::Atom(atom!("[]")))
| &Term::Literal(_, Literal::Atom(..)) => {
instr!("$succeed")
}
&Term::Var(ref vr, ref name) => {
@@ -586,11 +609,11 @@ impl<'b> CodeGenerator<'b> {
}
},
&InlinedClauseType::IsAtomic(..) => match &terms[0] {
&Term::AnonVar |
&Term::Clause(..) |
&Term::Cons(..) |
&Term::PartialString(..) |
&Term::CompleteString(..) => {
&Term::AnonVar
| &Term::Clause(..)
| &Term::Cons(..)
| &Term::PartialString(..)
| &Term::CompleteString(..) => {
instr!("$fail")
}
&Term::Literal(_, Literal::String(_)) => {
@@ -614,11 +637,11 @@ impl<'b> CodeGenerator<'b> {
}
},
&InlinedClauseType::IsCompound(..) => match &terms[0] {
&Term::Clause(..) |
&Term::Cons(..) |
&Term::PartialString(..) |
&Term::CompleteString(..) |
&Term::Literal(_, Literal::String(..)) => {
&Term::Clause(..)
| &Term::Cons(..)
| &Term::PartialString(..)
| &Term::CompleteString(..)
| &Term::Literal(_, Literal::String(..)) => {
instr!("$succeed")
}
&Term::Var(ref vr, ref name) => {
@@ -644,7 +667,13 @@ impl<'b> CodeGenerator<'b> {
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.marker.mark_non_callable(name.to_var_num().unwrap(), 1, term_loc, vr, code);
let r = self.marker.mark_non_callable(
name.to_var_num().unwrap(),
1,
term_loc,
vr,
code,
);
instr!("rational", r)
}
_ => {
@@ -673,10 +702,10 @@ impl<'b> CodeGenerator<'b> {
}
},
&InlinedClauseType::IsNumber(..) => match &terms[0] {
&Term::Literal(_, Literal::Float(_)) |
&Term::Literal(_, Literal::Rational(_)) |
&Term::Literal(_, Literal::Integer(_)) |
&Term::Literal(_, Literal::Fixnum(_)) => {
&Term::Literal(_, Literal::Float(_))
| &Term::Literal(_, Literal::Rational(_))
| &Term::Literal(_, Literal::Integer(_))
| &Term::Literal(_, Literal::Fixnum(_)) => {
instr!("$succeed")
}
&Term::Var(ref vr, ref name) => {
@@ -718,8 +747,7 @@ impl<'b> CodeGenerator<'b> {
}
},
&InlinedClauseType::IsInteger(..) => match &terms[0] {
&Term::Literal(_, Literal::Integer(_)) |
&Term::Literal(_, Literal::Fixnum(_)) => {
&Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => {
instr!("$succeed")
}
&Term::Var(ref vr, ref name) => {
@@ -740,11 +768,11 @@ impl<'b> CodeGenerator<'b> {
}
},
&InlinedClauseType::IsVar(..) => match &terms[0] {
&Term::Literal(..) |
&Term::Clause(..) |
&Term::Cons(..) |
&Term::PartialString(..) |
&Term::CompleteString(..) => {
&Term::Literal(..)
| &Term::Clause(..)
| &Term::Cons(..)
| &Term::PartialString(..)
| &Term::CompleteString(..) => {
instr!("$fail")
}
&Term::AnonVar => {
@@ -791,11 +819,11 @@ impl<'b> CodeGenerator<'b> {
call_policy: CallPolicy,
) -> Result<(), CompilationError> {
macro_rules! compile_expr {
($self:expr, $terms:expr, $term_loc:expr, $code:expr) => ({
($self:expr, $terms:expr, $term_loc:expr, $code:expr) => {{
let (acode, at) = $self.compile_arith_expr($terms, 1, $term_loc, 2)?;
$code.extend(acode.into_iter());
at
});
}};
}
self.marker.reset_arg(2);
@@ -843,10 +871,13 @@ impl<'b> CodeGenerator<'b> {
compile_expr!(self, &terms[1], term_loc, code)
}
}
&Term::Literal(_, c @ Literal::Integer(_) |
c @ Literal::Float(_) |
c @ Literal::Rational(_) |
c @ Literal::Fixnum(_)) => {
&Term::Literal(
_,
c @ Literal::Integer(_)
| c @ Literal::Float(_)
| c @ Literal::Rational(_)
| c @ Literal::Fixnum(_),
) => {
let v = HeapCellValue::from(c);
code.push_back(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
@@ -939,15 +970,29 @@ impl<'b> CodeGenerator<'b> {
ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
ref terms,
call_policy,
) => self.compile_is_call(terms, branch_code_stack.code(code), term_loc, call_policy)?,
) => self.compile_is_call(
terms,
branch_code_stack.code(code),
term_loc,
call_policy,
)?,
&QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
self.compile_inlined(ct, terms, term_loc, branch_code_stack.code(code))?
self.compile_inlined(
ct,
terms,
term_loc,
branch_code_stack.code(code),
)?
}
&QueryTerm::Fail => {
branch_code_stack.code(code).push_back(instr!("$fail"));
}
term @ &QueryTerm::Clause(..) => {
self.compile_query_line(term, term_loc, branch_code_stack.code(code));
self.compile_query_line(
term,
term_loc,
branch_code_stack.code(code),
);
if self.marker.max_reg_allocated() > MAX_ARITY {
return Err(CompilationError::ExceededMaxArity);
@@ -975,7 +1020,8 @@ impl<'b> CodeGenerator<'b> {
}
ClauseItem::BranchEnd(depth) => {
if !clause_iter.in_tail_position() {
let subsumed_hits = branch_code_stack.push_missing_vars(depth, &mut self.marker);
let subsumed_hits =
branch_code_stack.push_missing_vars(depth, &mut self.marker);
self.marker.pop_branch(depth, subsumed_hits);
branch_code_stack.push_jump_instrs(depth);
} else {
@@ -1001,8 +1047,15 @@ impl<'b> CodeGenerator<'b> {
Ok(())
}
pub(crate) fn compile_rule(&mut self, rule: &Rule, var_data: VarData) -> Result<Code, CompilationError> {
let Rule { head: (_, args), clauses } = rule;
pub(crate) fn compile_rule(
&mut self,
rule: &Rule,
var_data: VarData,
) -> Result<Code, CompilationError> {
let Rule {
head: (_, args),
clauses,
} = rule;
self.marker.var_data = var_data;
let mut code = VecDeque::new();
@@ -1023,7 +1076,11 @@ impl<'b> CodeGenerator<'b> {
Ok(Vec::from(code))
}
pub(crate) fn compile_fact(&mut self, fact: &Fact, var_data: VarData) -> Result<Code, CompilationError> {
pub(crate) fn compile_fact(
&mut self,
fact: &Fact,
var_data: VarData,
) -> Result<Code, CompilationError> {
let mut code = Vec::new();
self.marker.var_data = var_data;
@@ -1031,10 +1088,7 @@ impl<'b> CodeGenerator<'b> {
self.marker.reset_at_head(args);
let iter = FactInstruction::iter(&fact.head);
let compiled_fact = self.compile_target::<FactInstruction, _>(
iter,
GenContext::Head,
);
let compiled_fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);
if self.marker.max_reg_allocated() > MAX_ARITY {
return Err(CompilationError::ExceededMaxArity);
@@ -1059,7 +1113,7 @@ impl<'b> CodeGenerator<'b> {
&QueryTerm::Clause(_, ref ct, _, call_policy) => {
self.add_call(code, ct.to_instr(), call_policy);
}
_ => unreachable!()
_ => unreachable!(),
};
}
@@ -1072,8 +1126,7 @@ impl<'b> CodeGenerator<'b> {
if let Some(args) = clause.args() {
for (instantiated_arg_index, arg) in args.iter().enumerate() {
match arg {
Term::Var(..) | Term::AnonVar => {
}
Term::Var(..) | Term::AnonVar => {}
_ => {
if optimal_index != instantiated_arg_index {
if left >= right {
@@ -1098,7 +1151,11 @@ impl<'b> CodeGenerator<'b> {
}
if left < right {
subseqs.push(ClauseSpan { left, right, instantiated_arg_index: optimal_index });
subseqs.push(ClauseSpan {
left,
right,
instantiated_arg_index: optimal_index,
});
}
optimal_index = 0;
@@ -1129,7 +1186,8 @@ impl<'b> CodeGenerator<'b> {
optimal_index: usize,
) -> Result<Code, CompilationError> {
let mut code = VecDeque::new();
let mut code_offsets = CodeOffsets::new(I::new(), optimal_index + 1);
let mut code_offsets =
CodeOffsets::new(I::new(), optimal_index + 1, self.settings.non_counted_bt);
let mut skip_stub_try_me_else = false;
let clauses_len = clauses.len();
@@ -1174,7 +1232,9 @@ impl<'b> CodeGenerator<'b> {
skip_stub_try_me_else = !self.settings.is_dynamic();
}
let arg = clause.args().and_then(|args| args.iter().nth(optimal_index));
let arg = clause
.args()
.and_then(|args| args.iter().nth(optimal_index));
if let Some(arg) = arg {
let index = code.len();
@@ -1217,7 +1277,12 @@ impl<'b> CodeGenerator<'b> {
let split_pred = Self::split_predicate(&clauses);
let multi_seq = split_pred.len() > 1;
for ClauseSpan { left, right, instantiated_arg_index } in split_pred {
for ClauseSpan {
left,
right,
instantiated_arg_index,
} in split_pred
{
let skel_lower_bound = self.skeleton.clauses.len();
let code_segment = if self.settings.is_dynamic() {
self.compile_pred_subseq::<DynamicCodeIndices>(
@@ -1248,9 +1313,8 @@ impl<'b> CodeGenerator<'b> {
if self.settings.is_extensible {
let segment_is_indexed = code_segment[0].to_indexing_line().is_some();
for clause_index_info in self.skeleton.clauses
.make_contiguous()[skel_lower_bound..]
.iter_mut()
for clause_index_info in
self.skeleton.clauses.make_contiguous()[skel_lower_bound..].iter_mut()
{
clause_index_info.clause_start +=
clause_start_offset + 2 * (segment_is_indexed as usize);

View File

@@ -76,11 +76,16 @@ impl BranchStack {
}
}
fn safety_unneeded_in_branch(&self, safety: &VarSafetyStatus, branch: &BranchDesignator) -> bool {
fn safety_unneeded_in_branch(
&self,
safety: &VarSafetyStatus,
branch: &BranchDesignator,
) -> bool {
match safety {
VarSafetyStatus::Needed => false,
VarSafetyStatus::LocallyUnneeded(planter_branch) =>
self.branch_subsumes(planter_branch, branch),
VarSafetyStatus::LocallyUnneeded(planter_branch) => {
self.branch_subsumes(planter_branch, branch)
}
VarSafetyStatus::GloballyUnneeded => true,
}
}
@@ -91,7 +96,9 @@ impl BranchStack {
let num_branches = occurrences.num_branches;
let entry = occurrences.hits.entry(var_num)
let entry = occurrences
.hits
.entry(var_num)
.or_insert_with(|| BitVec::repeat(false, num_branches));
entry.set(occurrences.current_branch, true);
@@ -105,11 +112,15 @@ impl BranchStack {
pub(crate) fn current_branch_designator(&self) -> BranchDesignator {
let branch_stack_num = self.len();
let branch_num = self.last()
let branch_num = self
.last()
.map(|occurrences| occurrences.current_branch)
.unwrap_or(0);
BranchDesignator { branch_stack_num, branch_num }
BranchDesignator {
branch_stack_num,
branch_num,
}
}
#[inline]
@@ -121,7 +132,7 @@ impl BranchStack {
#[inline]
pub(crate) fn drain_branches(&mut self, depth: usize) -> std::vec::Drain<BranchOccurrences> {
let start_idx = self.len() - depth;
self.drain(start_idx ..)
self.drain(start_idx..)
}
}
@@ -156,13 +167,23 @@ impl DebrayAllocator {
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, ref mut allocation) => {
match allocation {
PermVarAllocation::Done { shallow_safety, deep_safety, .. } => {
if !self.branch_stack.safety_unneeded_in_branch(shallow_safety, &branch_designator) {
PermVarAllocation::Done {
shallow_safety,
deep_safety,
..
} => {
if !self
.branch_stack
.safety_unneeded_in_branch(shallow_safety, &branch_designator)
{
let branch_occurrences = self.branch_stack.last_mut().unwrap();
branch_occurrences.shallow_safety.insert(var_num);
}
if !self.branch_stack.safety_unneeded_in_branch(deep_safety, &branch_designator) {
if !self
.branch_stack
.safety_unneeded_in_branch(deep_safety, &branch_designator)
{
let branch_occurrences = self.branch_stack.last_mut().unwrap();
branch_occurrences.deep_safety.insert(var_num);
}
@@ -182,15 +203,15 @@ impl DebrayAllocator {
pub(crate) fn pop_branch(&mut self, depth: usize, subsumed_hits: SubsumedBranchHits) {
let removed_branches = self.branch_stack.drain_branches(depth);
let (deep_safety, shallow_safety) = removed_branches
.into_iter()
.fold((BitSet::default(), BitSet::default()),
|(mut deep_safety, mut shallow_safety), branch_occurrences| {
deep_safety.union_with(&branch_occurrences.deep_safety);
shallow_safety.union_with(&branch_occurrences.shallow_safety);
let (deep_safety, shallow_safety) = removed_branches.into_iter().fold(
(BitSet::default(), BitSet::default()),
|(mut deep_safety, mut shallow_safety), branch_occurrences| {
deep_safety.union_with(&branch_occurrences.deep_safety);
shallow_safety.union_with(&branch_occurrences.shallow_safety);
(deep_safety, shallow_safety)
});
(deep_safety, shallow_safety)
},
);
let branch_designator = self.branch_stack.current_branch_designator();
@@ -201,7 +222,7 @@ impl DebrayAllocator {
(&latest_branch.deep_safety, &latest_branch.shallow_safety)
}
None => (&deep_safety, &shallow_safety)
None => (&deep_safety, &shallow_safety),
};
for var_num in subsumed_hits.iter().cloned() {
@@ -221,10 +242,13 @@ impl DebrayAllocator {
);
if running_count < num_occurrences {
*allocation = PermVarAllocation::Done { shallow_safety, deep_safety };
*allocation = PermVarAllocation::Done {
shallow_safety,
deep_safety,
};
}
}
_ => unreachable!()
_ => unreachable!(),
}
}
@@ -244,9 +268,11 @@ impl DebrayAllocator {
fn occurs_shallowly_in_head(&self, var_num: usize, r: usize) -> bool {
match &self.var_data.records[var_num].allocation {
VarAlloc::Temp { temp_var_data, term_loc: GenContext::Head, .. } => {
temp_var_data.use_set.contains(&(GenContext::Head, r))
}
VarAlloc::Temp {
temp_var_data,
term_loc: GenContext::Head,
..
} => temp_var_data.use_set.contains(&(GenContext::Head, r)),
_ => false,
}
}
@@ -325,12 +351,14 @@ impl DebrayAllocator {
match &self.var_data.records[t_var].allocation {
VarAlloc::Temp { temp_var_data, .. } => {
if !temp_var_data.use_set.contains(&(GenContext::Last(chunk_num), k)) {
if !temp_var_data
.use_set
.contains(&(GenContext::Last(chunk_num), k))
{
return Some((t_var, self.alloc_with_ca(t_var)));
}
}
_ => {
}
_ => {}
}
None
@@ -356,7 +384,9 @@ impl DebrayAllocator {
self.shallow_temp_mappings.swap_remove(&k);
self.shallow_temp_mappings.insert(r.reg_num(), var_num);
self.var_data.records[var_num].allocation.set_register(r.reg_num());
self.var_data.records[var_num]
.allocation
.set_register(r.reg_num());
self.in_use.insert(r.reg_num());
}
}
@@ -417,12 +447,9 @@ impl DebrayAllocator {
fn in_place(&self, var_num: usize, term_loc: GenContext, r: RegType, k: usize) -> bool {
match term_loc {
GenContext::Head if !r.is_perm() => r.reg_num() == k,
_ => {
match &self.var_data.records[var_num].allocation {
&VarAlloc::Temp { temp_reg, .. } if r.reg_num() == k =>
temp_reg == k,
_ => false,
}
_ => match &self.var_data.records[var_num].allocation {
&VarAlloc::Temp { temp_reg, .. } if r.reg_num() == k => temp_reg == k,
_ => false,
},
}
}
@@ -483,8 +510,7 @@ impl DebrayAllocator {
VarAlloc::Perm(p, PermVarAllocation::Pending) if *p > 0 => {
return Some(std::mem::replace(p, 0));
}
_ => {
}
_ => {}
}
} else {
return None;
@@ -500,8 +526,7 @@ impl DebrayAllocator {
*allocation = PermVarAllocation::Pending;
self.add_perm_to_free_list(chunk_num, var_num);
}
_ => {
}
_ => {}
}
}
@@ -509,7 +534,14 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => {
VarAlloc::Perm(
_,
PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
) => {
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
}
@@ -524,7 +556,14 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => {
VarAlloc::Perm(
_,
PermVarAllocation::Done {
deep_safety,
shallow_safety,
..
},
) => {
// GetVariable in head chunk is considered safe.
if lvl == Level::Deep {
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -532,12 +571,16 @@ impl DebrayAllocator {
} else if term_loc == GenContext::Head {
*shallow_safety = VarSafetyStatus::GloballyUnneeded;
} else {
if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() {
if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned()
{
match &mut self.var_data.records[temp_var_num].allocation {
VarAlloc::Temp { ref mut to_perm_var_num, .. } => {
VarAlloc::Temp {
ref mut to_perm_var_num,
..
} => {
*to_perm_var_num = Some(var_num);
}
_ => unreachable!()
_ => unreachable!(),
}
}
}
@@ -560,8 +603,18 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => {
if !self.in_tail_position || self.branch_stack.safety_unneeded_in_branch(shallow_safety, &branch_designator) {
VarAlloc::Perm(
_,
PermVarAllocation::Done {
ref mut shallow_safety,
..
},
) => {
if !self.in_tail_position
|| self
.branch_stack
.safety_unneeded_in_branch(shallow_safety, &branch_designator)
{
Target::argument_to_value(r, arg_c)
} else {
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -569,7 +622,10 @@ impl DebrayAllocator {
}
}
VarAlloc::Temp { ref mut safety, .. } => {
if self.branch_stack.safety_unneeded_in_branch(safety, &branch_designator) {
if self
.branch_stack
.safety_unneeded_in_branch(safety, &branch_designator)
{
Target::argument_to_value(r, arg_c)
} else {
*safety = VarSafetyStatus::GloballyUnneeded;
@@ -590,8 +646,17 @@ impl DebrayAllocator {
let branch_designator = self.branch_stack.current_branch_designator();
match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => {
if self.branch_stack.safety_unneeded_in_branch(deep_safety, &branch_designator) {
VarAlloc::Perm(
_,
PermVarAllocation::Done {
ref mut deep_safety,
..
},
) => {
if self
.branch_stack
.safety_unneeded_in_branch(deep_safety, &branch_designator)
{
Target::subterm_to_value(r)
} else {
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
@@ -599,7 +664,10 @@ impl DebrayAllocator {
}
}
VarAlloc::Temp { ref mut safety, .. } => {
if self.branch_stack.safety_unneeded_in_branch(safety, &branch_designator) {
if self
.branch_stack
.safety_unneeded_in_branch(safety, &branch_designator)
{
Target::subterm_to_value(r)
} else {
*safety = VarSafetyStatus::unneeded(branch_designator);
@@ -626,7 +694,7 @@ impl Allocator for DebrayAllocator {
in_use: BitSet::default(),
temp_free_list: vec![],
perm_free_list: VecDeque::new(),
branch_stack: BranchStack { stack: vec![] }
branch_stack: BranchStack { stack: vec![] },
}
}
@@ -705,12 +773,14 @@ impl Allocator for DebrayAllocator {
}
r @ RegType::Perm(_) => {
let is_new_var = match &mut self.var_data.records[var_num].allocation {
VarAlloc::Perm(_, allocation) => if allocation.pending() {
*allocation = PermVarAllocation::done();
true
} else {
false
},
VarAlloc::Perm(_, allocation) => {
if allocation.pending() {
*allocation = PermVarAllocation::done();
true
} else {
false
}
}
_ => unreachable!(),
};
@@ -828,7 +898,9 @@ impl Allocator for DebrayAllocator {
if !r.is_perm() && r.reg_num() == 0 {
self.in_use.insert(idx + 1);
self.shallow_temp_mappings.insert(idx + 1, var_num);
self.var_data.records[var_num].allocation.set_register(idx + 1);
self.var_data.records[var_num]
.allocation
.set_register(idx + 1);
}
}
}

View File

@@ -24,12 +24,12 @@ use crate::atom_table::Atom;
use std::alloc::{alloc, Layout};
use std::any::Any;
use std::collections::HashMap;
use std::error::Error;
use std::ffi::{CString, c_void};
use std::convert::TryFrom;
use std::error::Error;
use std::ffi::{c_void, CString};
use libffi::low::{ffi_cif, types, CodePtr, ffi_abi_FFI_DEFAULT_ABI, prep_cif, ffi_type, type_tag};
use libloading::{Symbol, Library};
use libffi::low::{ffi_abi_FFI_DEFAULT_ABI, ffi_cif, ffi_type, prep_cif, type_tag, types, CodePtr};
use libloading::{Library, Symbol};
pub struct FunctionDefinition {
pub name: String,
@@ -65,338 +65,393 @@ struct PointerArgs {
impl ForeignFunctionTable {
pub fn merge(&mut self, other: ForeignFunctionTable) {
self.table.extend(other.table);
self.table.extend(other.table);
}
pub fn define_struct(&mut self, name: &str, atom_fields: Vec<Atom>) {
let mut fields: Vec<_> = atom_fields.iter().map(|x| self.map_type_ffi(&x)).collect();
fields.push(std::ptr::null_mut::<ffi_type>());
let mut struct_type: ffi_type = Default::default();
struct_type.type_ = type_tag::STRUCT;
struct_type.elements = fields.as_mut_ptr();
self.structs.insert(name.to_string(), StructImpl { ffi_type: struct_type, fields, atom_fields});
let mut fields: Vec<_> = atom_fields.iter().map(|x| self.map_type_ffi(&x)).collect();
fields.push(std::ptr::null_mut::<ffi_type>());
let mut struct_type: ffi_type = Default::default();
struct_type.type_ = type_tag::STRUCT;
struct_type.elements = fields.as_mut_ptr();
self.structs.insert(
name.to_string(),
StructImpl {
ffi_type: struct_type,
fields,
atom_fields,
},
);
}
fn map_type_ffi(&mut self, source: &Atom) -> *mut ffi_type {
unsafe {
match source {
atom!("sint64") => &mut types::sint64,
atom!("sint32") => &mut types::sint32,
atom!("sint16") => &mut types::sint16,
atom!("sint8") => &mut types::sint8,
atom!("uint64") => &mut types::uint64,
atom!("uint32") => &mut types::uint32,
atom!("uint16") => &mut types::uint16,
atom!("uint8") => &mut types::uint8,
atom!("bool") => &mut types::sint8,
atom!("void") => &mut types::void,
atom!("cstr") => &mut types::pointer,
atom!("ptr") => &mut types::pointer,
atom!("f32") => &mut types::float,
atom!("f64") => &mut types::double,
struct_name => {
match self.structs.get_mut(struct_name.as_str()) {
Some(ref mut struct_type) => {
&mut struct_type.ffi_type
},
None => unreachable!()
}
}
}
}
unsafe {
match source {
atom!("sint64") => &mut types::sint64,
atom!("sint32") => &mut types::sint32,
atom!("sint16") => &mut types::sint16,
atom!("sint8") => &mut types::sint8,
atom!("uint64") => &mut types::uint64,
atom!("uint32") => &mut types::uint32,
atom!("uint16") => &mut types::uint16,
atom!("uint8") => &mut types::uint8,
atom!("bool") => &mut types::sint8,
atom!("void") => &mut types::void,
atom!("cstr") => &mut types::pointer,
atom!("ptr") => &mut types::pointer,
atom!("f32") => &mut types::float,
atom!("f64") => &mut types::double,
struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
Some(ref mut struct_type) => &mut struct_type.ffi_type,
None => unreachable!(),
},
}
}
}
pub(crate) fn load_library(&mut self, library_name: &str, functions: &Vec<FunctionDefinition>) -> Result<(), Box<dyn Error>> {
let mut ff_table: ForeignFunctionTable = Default::default();
unsafe {
let library = Library::new(library_name)?;
for function in functions {
let symbol_name: CString = CString::new(function.name.clone())?;
let code_ptr: Symbol<*mut c_void> = library.get(&symbol_name.into_bytes_with_nul())?;
let mut args: Vec<_> = function.args.iter().map(|x| self.map_type_ffi(&x)).collect();
let mut cif: ffi_cif = Default::default();
prep_cif(
&mut cif,
ffi_abi_FFI_DEFAULT_ABI,
args.len(),
self.map_type_ffi(&function.return_value),
args.as_mut_ptr()
).unwrap();
pub(crate) fn load_library(
&mut self,
library_name: &str,
functions: &Vec<FunctionDefinition>,
) -> Result<(), Box<dyn Error>> {
let mut ff_table: ForeignFunctionTable = Default::default();
unsafe {
let library = Library::new(library_name)?;
for function in functions {
let symbol_name: CString = CString::new(function.name.clone())?;
let code_ptr: Symbol<*mut c_void> =
library.get(&symbol_name.into_bytes_with_nul())?;
let mut args: Vec<_> = function
.args
.iter()
.map(|x| self.map_type_ffi(&x))
.collect();
let mut cif: ffi_cif = Default::default();
prep_cif(
&mut cif,
ffi_abi_FFI_DEFAULT_ABI,
args.len(),
self.map_type_ffi(&function.return_value),
args.as_mut_ptr(),
)
.unwrap();
let return_struct_name = if (*self.map_type_ffi(&function.return_value)).type_ as u32 == libffi::raw::FFI_TYPE_STRUCT {
Some(function.return_value.as_str().to_string())
} else {
None
};
let return_struct_name = if (*self.map_type_ffi(&function.return_value)).type_
as u32
== libffi::raw::FFI_TYPE_STRUCT
{
Some(function.return_value.as_str().to_string())
} else {
None
};
ff_table.table.insert(function.name.clone(), FunctionImpl {
cif,
args,
code_ptr: CodePtr(code_ptr.into_raw().into_raw() as *mut _),
return_struct_name,
});
}
std::mem::forget(library);
}
self.merge(ff_table);
Ok(())
ff_table.table.insert(
function.name.clone(),
FunctionImpl {
cif,
args,
code_ptr: CodePtr(code_ptr.into_raw().into_raw() as *mut _),
return_struct_name,
},
);
}
std::mem::forget(library);
}
self.merge(ff_table);
Ok(())
}
fn build_pointer_args(args: &mut Vec<Value>, type_args: &Vec<*mut ffi_type>, structs_table: &mut HashMap<String, StructImpl>) -> Result<PointerArgs, FFIError> {
let mut pointers = Vec::with_capacity(args.len());
let mut _memory = Vec::new();
for i in 0..args.len() {
let field_type = type_args[i];
unsafe {
macro_rules! push_int {
($type:ty) => {
{
let n: $type = <$type>::try_from(args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?;
let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value);
}
}
}
match (*field_type).type_ as u32 {
libffi::raw::FFI_TYPE_UINT8 => push_int!(u8),
libffi::raw::FFI_TYPE_SINT8 => push_int!(i8),
libffi::raw::FFI_TYPE_UINT16 => push_int!(u16),
libffi::raw::FFI_TYPE_SINT16 => push_int!(i16),
libffi::raw::FFI_TYPE_UINT32 => push_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => push_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => push_int!(u64),
libffi::raw::FFI_TYPE_SINT64 => push_int!(i64),
libffi::raw::FFI_TYPE_FLOAT => {
let n: f32 = args[i].as_float()? as f32;
let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value);
},
libffi::raw::FFI_TYPE_DOUBLE => {
let n: f64 = args[i].as_float()?;
let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value);
},
libffi::raw::FFI_TYPE_POINTER => {
let ptr: *mut c_void = args[i].as_ptr()?;
pointers.push(ptr);
},
libffi::raw::FFI_TYPE_STRUCT => {
let (mut ptr, _size, _align) = Self::build_struct(&mut args[i], structs_table)?;
pointers.push(&mut *ptr as *mut _ as *mut c_void);
_memory.push(ptr);
},
_ => return Err(FFIError::InvalidFFIType)
}
}
}
Ok(PointerArgs {
pointers,
_memory
})
fn build_pointer_args(
args: &mut Vec<Value>,
type_args: &Vec<*mut ffi_type>,
structs_table: &mut HashMap<String, StructImpl>,
) -> Result<PointerArgs, FFIError> {
let mut pointers = Vec::with_capacity(args.len());
let mut _memory = Vec::new();
for i in 0..args.len() {
let field_type = type_args[i];
unsafe {
macro_rules! push_int {
($type:ty) => {{
let n: $type = <$type>::try_from(args[i].as_int()?)
.map_err(|_| FFIError::ValueDontFit)?;
let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value);
}};
}
match (*field_type).type_ as u32 {
libffi::raw::FFI_TYPE_UINT8 => push_int!(u8),
libffi::raw::FFI_TYPE_SINT8 => push_int!(i8),
libffi::raw::FFI_TYPE_UINT16 => push_int!(u16),
libffi::raw::FFI_TYPE_SINT16 => push_int!(i16),
libffi::raw::FFI_TYPE_UINT32 => push_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => push_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => push_int!(u64),
libffi::raw::FFI_TYPE_SINT64 => push_int!(i64),
libffi::raw::FFI_TYPE_FLOAT => {
let n: f32 = args[i].as_float()? as f32;
let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value);
}
libffi::raw::FFI_TYPE_DOUBLE => {
let n: f64 = args[i].as_float()?;
let mut box_value = Box::new(n) as Box<dyn Any>;
pointers.push(&mut *box_value as *mut _ as *mut c_void);
_memory.push(box_value);
}
libffi::raw::FFI_TYPE_POINTER => {
let ptr: *mut c_void = args[i].as_ptr()?;
pointers.push(ptr);
}
libffi::raw::FFI_TYPE_STRUCT => {
let (mut ptr, _size, _align) =
Self::build_struct(&mut args[i], structs_table)?;
pointers.push(&mut *ptr as *mut _ as *mut c_void);
_memory.push(ptr);
}
_ => return Err(FFIError::InvalidFFIType),
}
}
}
Ok(PointerArgs { pointers, _memory })
}
fn build_struct(arg: &mut Value, structs_table: &mut HashMap<String, StructImpl>) -> Result<(Box<dyn Any>, usize, usize), FFIError> {
unsafe {
match arg {
Value::Struct(ref name, ref mut struct_args) => {
if let Some(ref mut struct_type) = structs_table.clone().get_mut(name) {
let layout = Layout::from_size_align(struct_type.ffi_type.size, struct_type.ffi_type.alignment.into()).unwrap();
let align = struct_type.ffi_type.alignment as usize;
let size = struct_type.ffi_type.size;
let ptr = alloc(layout) as *mut c_void;
let mut field_ptr = ptr;
fn build_struct(
arg: &mut Value,
structs_table: &mut HashMap<String, StructImpl>,
) -> Result<(Box<dyn Any>, usize, usize), FFIError> {
unsafe {
match arg {
Value::Struct(ref name, ref mut struct_args) => {
if let Some(ref mut struct_type) = structs_table.clone().get_mut(name) {
let layout = Layout::from_size_align(
struct_type.ffi_type.size,
struct_type.ffi_type.alignment.into(),
)
.unwrap();
let align = struct_type.ffi_type.alignment as usize;
let size = struct_type.ffi_type.size;
let ptr = alloc(layout) as *mut c_void;
let mut field_ptr = ptr;
for i in 0..(struct_type.fields.len()-1) {
macro_rules! try_write_int {
($type:ty) => {
{
field_ptr = field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
let n: $type = <$type>::try_from(struct_args[i].as_int()?).map_err(|_| FFIError::ValueDontFit)?;
std::ptr::write(field_ptr as *mut $type, n);
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
}
}
}
for i in 0..(struct_type.fields.len() - 1) {
macro_rules! try_write_int {
($type:ty) => {{
field_ptr = field_ptr
.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
let n: $type = <$type>::try_from(struct_args[i].as_int()?)
.map_err(|_| FFIError::ValueDontFit)?;
std::ptr::write(field_ptr as *mut $type, n);
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
}};
}
macro_rules! write {
($type:ty, $value:expr) => {
{
let data: $type = $value;
std::ptr::write(field_ptr as *mut $type, data);
field_ptr = field_ptr.add(align);
}
}
}
macro_rules! write {
($type:ty, $value:expr) => {{
let data: $type = $value;
std::ptr::write(field_ptr as *mut $type, data);
field_ptr = field_ptr.add(align);
}};
}
let field = struct_type.fields[i];
match (*field).type_ as u32 {
libffi::raw::FFI_TYPE_UINT8 => try_write_int!(u8),
libffi::raw::FFI_TYPE_SINT8 => try_write_int!(i8),
libffi::raw::FFI_TYPE_UINT16 => try_write_int!(u16),
libffi::raw::FFI_TYPE_SINT16 => try_write_int!(i16),
libffi::raw::FFI_TYPE_UINT32 => try_write_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => try_write_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => try_write_int!(u64),
libffi::raw::FFI_TYPE_SINT64 => try_write_int!(i64),
libffi::raw::FFI_TYPE_POINTER => write!(*mut c_void, struct_args[i].as_ptr()?),
libffi::raw::FFI_TYPE_FLOAT => write!(f32, struct_args[i].as_float()? as f32),
libffi::raw::FFI_TYPE_DOUBLE => write!(f64, struct_args[i].as_float()?),
libffi::raw::FFI_TYPE_STRUCT => {
let (struct_ptr, struct_size, struct_align) = Self::build_struct(&mut struct_args[i], structs_table)?;
field_ptr = field_ptr.add(field_ptr.align_offset(struct_align));
std::ptr::copy(& *struct_ptr as *const _ as *const c_void, field_ptr as *mut c_void, struct_size);
field_ptr = field_ptr.add(struct_size);
},
_ => {
unreachable!()
}
}
}
return Ok((Box::from_raw(ptr), size, align));
} else {
return Err(FFIError::InvalidStructName);
}
}
_ => return Err(FFIError::ValueCast)
}
}
let field = struct_type.fields[i];
match (*field).type_ as u32 {
libffi::raw::FFI_TYPE_UINT8 => try_write_int!(u8),
libffi::raw::FFI_TYPE_SINT8 => try_write_int!(i8),
libffi::raw::FFI_TYPE_UINT16 => try_write_int!(u16),
libffi::raw::FFI_TYPE_SINT16 => try_write_int!(i16),
libffi::raw::FFI_TYPE_UINT32 => try_write_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => try_write_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => try_write_int!(u64),
libffi::raw::FFI_TYPE_SINT64 => try_write_int!(i64),
libffi::raw::FFI_TYPE_POINTER => {
write!(*mut c_void, struct_args[i].as_ptr()?)
}
libffi::raw::FFI_TYPE_FLOAT => {
write!(f32, struct_args[i].as_float()? as f32)
}
libffi::raw::FFI_TYPE_DOUBLE => {
write!(f64, struct_args[i].as_float()?)
}
libffi::raw::FFI_TYPE_STRUCT => {
let (struct_ptr, struct_size, struct_align) =
Self::build_struct(&mut struct_args[i], structs_table)?;
field_ptr = field_ptr.add(field_ptr.align_offset(struct_align));
std::ptr::copy(
&*struct_ptr as *const _ as *const c_void,
field_ptr as *mut c_void,
struct_size,
);
field_ptr = field_ptr.add(struct_size);
}
_ => {
unreachable!()
}
}
}
return Ok((Box::from_raw(ptr), size, align));
} else {
return Err(FFIError::InvalidStructName);
}
}
_ => return Err(FFIError::ValueCast),
}
}
}
pub fn exec(&mut self, name: &str, mut args: Vec<Value>) -> Result<Value, FFIError> {
let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?;
let mut pointer_args = Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?;
return unsafe {
macro_rules! call_and_return {
($type:ty) => {
{
let mut n: Box<u8> = Box::new(0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void
);
Ok(Value::Int(i64::from(*n)))
}
}
}
match (*function_impl.cif.rtype).type_ as u32 {
libffi::raw::FFI_TYPE_VOID => call_and_return!(i32),
libffi::raw::FFI_TYPE_UINT8 => call_and_return!(u8),
libffi::raw::FFI_TYPE_SINT8 => call_and_return!(i8),
libffi::raw::FFI_TYPE_UINT16 => call_and_return!(u16),
libffi::raw::FFI_TYPE_SINT16 => call_and_return!(i16),
libffi::raw::FFI_TYPE_UINT32 => call_and_return!(u32),
libffi::raw::FFI_TYPE_SINT32 => call_and_return!(i32),
libffi::raw::FFI_TYPE_UINT64 => {
let mut n: Box<u64> = Box::new(0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void
);
Ok(Value::Int(i64::try_from(*n).map_err(|_| FFIError::ValueDontFit)?))
},
libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64),
libffi::raw::FFI_TYPE_POINTER => call_and_return!(*mut c_void),
libffi::raw::FFI_TYPE_FLOAT => {
let mut n: Box<f32> = Box::new(0.0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void
);
Ok(Value::Float((*n).into()))
},
libffi::raw::FFI_TYPE_DOUBLE => {
let mut n: Box<f64> = Box::new(0.0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void
);
Ok(Value::Float(*n))
},
libffi::raw::FFI_TYPE_STRUCT => {
let name = &function_impl.return_struct_name.clone().ok_or(FFIError::StructNotFound)?;
let struct_type = self.structs.get(name).ok_or(FFIError::StructNotFound)?;
let layout = Layout::from_size_align(struct_type.ffi_type.size, struct_type.ffi_type.alignment.into()).unwrap();
let ptr = alloc(layout) as *mut c_void;
let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?;
let mut pointer_args =
Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?;
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *ptr as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void
);
let struct_val = self.read_struct(ptr, name, struct_type);
drop(Box::from_raw(ptr));
struct_val
}
_ => unreachable!()
}
};
return unsafe {
macro_rules! call_and_return {
($type:ty) => {{
let mut n: Box<u8> = Box::new(0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
);
Ok(Value::Int(i64::from(*n)))
}};
}
match (*function_impl.cif.rtype).type_ as u32 {
libffi::raw::FFI_TYPE_VOID => call_and_return!(i32),
libffi::raw::FFI_TYPE_UINT8 => call_and_return!(u8),
libffi::raw::FFI_TYPE_SINT8 => call_and_return!(i8),
libffi::raw::FFI_TYPE_UINT16 => call_and_return!(u16),
libffi::raw::FFI_TYPE_SINT16 => call_and_return!(i16),
libffi::raw::FFI_TYPE_UINT32 => call_and_return!(u32),
libffi::raw::FFI_TYPE_SINT32 => call_and_return!(i32),
libffi::raw::FFI_TYPE_UINT64 => {
let mut n: Box<u64> = Box::new(0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
);
Ok(Value::Int(
i64::try_from(*n).map_err(|_| FFIError::ValueDontFit)?,
))
}
libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64),
libffi::raw::FFI_TYPE_POINTER => call_and_return!(*mut c_void),
libffi::raw::FFI_TYPE_FLOAT => {
let mut n: Box<f32> = Box::new(0.0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
);
Ok(Value::Float((*n).into()))
}
libffi::raw::FFI_TYPE_DOUBLE => {
let mut n: Box<f64> = Box::new(0.0);
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *n as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
);
Ok(Value::Float(*n))
}
libffi::raw::FFI_TYPE_STRUCT => {
let name = &function_impl
.return_struct_name
.clone()
.ok_or(FFIError::StructNotFound)?;
let struct_type = self.structs.get(name).ok_or(FFIError::StructNotFound)?;
let layout = Layout::from_size_align(
struct_type.ffi_type.size,
struct_type.ffi_type.alignment.into(),
)
.unwrap();
let ptr = alloc(layout) as *mut c_void;
libffi::raw::ffi_call(
&mut function_impl.cif,
Some(*function_impl.code_ptr.as_safe_fun()),
&mut *ptr as *mut _ as *mut c_void,
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
);
let struct_val = self.read_struct(ptr, name, struct_type);
drop(Box::from_raw(ptr));
struct_val
}
_ => unreachable!(),
}
};
}
fn read_struct(&self, ptr: *mut c_void, name: &str, struct_type: &StructImpl) -> Result<Value, FFIError> {
unsafe {
let mut returns = Vec::new();
let mut field_ptr = ptr;
fn read_struct(
&self,
ptr: *mut c_void,
name: &str,
struct_type: &StructImpl,
) -> Result<Value, FFIError> {
unsafe {
let mut returns = Vec::new();
let mut field_ptr = ptr;
for i in 0..(struct_type.fields.len()-1) {
let field = struct_type.fields[i];
for i in 0..(struct_type.fields.len() - 1) {
let field = struct_type.fields[i];
macro_rules! read_and_push_int {
($type:ty) => {
{
field_ptr = field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
let n = std::ptr::read(field_ptr as *mut $type);
returns.push(Value::Int(i64::from(n)));
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
}
}
}
macro_rules! read_and_push_int {
($type:ty) => {{
field_ptr =
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
let n = std::ptr::read(field_ptr as *mut $type);
returns.push(Value::Int(i64::from(n)));
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
}};
}
match (*field).type_ as u32 {
libffi::raw::FFI_TYPE_UINT8 => read_and_push_int!(u8),
libffi::raw::FFI_TYPE_SINT8 => read_and_push_int!(i8),
libffi::raw::FFI_TYPE_UINT16 => read_and_push_int!(u16),
libffi::raw::FFI_TYPE_SINT16 => read_and_push_int!(i16),
libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => {
field_ptr = field_ptr.add(field_ptr.align_offset(std::mem::align_of::<u64>()));
let n = std::ptr::read(field_ptr as *mut u64);
returns.push(Value::Int(i64::try_from(n).map_err(|_| FFIError::ValueDontFit)?));
field_ptr = field_ptr.add(std::mem::size_of::<u64>());
},
libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64),
libffi::raw::FFI_TYPE_POINTER => read_and_push_int!(i64),
libffi::raw::FFI_TYPE_STRUCT => {
let substruct = struct_type.atom_fields[i].as_str();
let struct_type = self.structs.get(substruct).ok_or(FFIError::StructNotFound)?;
field_ptr = field_ptr.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize));
let struct_val = self.read_struct(field_ptr, substruct, struct_type);
returns.push(struct_val?);
field_ptr = field_ptr.add(struct_type.ffi_type.size);
},
_ => {
unreachable!()
}
}
}
Ok(Value::Struct(name.into(), returns))
}
match (*field).type_ as u32 {
libffi::raw::FFI_TYPE_UINT8 => read_and_push_int!(u8),
libffi::raw::FFI_TYPE_SINT8 => read_and_push_int!(i8),
libffi::raw::FFI_TYPE_UINT16 => read_and_push_int!(u16),
libffi::raw::FFI_TYPE_SINT16 => read_and_push_int!(i16),
libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32),
libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32),
libffi::raw::FFI_TYPE_UINT64 => {
field_ptr =
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<u64>()));
let n = std::ptr::read(field_ptr as *mut u64);
returns.push(Value::Int(
i64::try_from(n).map_err(|_| FFIError::ValueDontFit)?,
));
field_ptr = field_ptr.add(std::mem::size_of::<u64>());
}
libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64),
libffi::raw::FFI_TYPE_POINTER => read_and_push_int!(i64),
libffi::raw::FFI_TYPE_STRUCT => {
let substruct = struct_type.atom_fields[i].as_str();
let struct_type = self
.structs
.get(&*substruct)
.ok_or(FFIError::StructNotFound)?;
field_ptr = field_ptr
.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize));
let struct_val = self.read_struct(field_ptr, &*substruct, struct_type);
returns.push(struct_val?);
field_ptr = field_ptr.add(struct_type.ffi_type.size);
}
_ => {
unreachable!()
}
}
}
Ok(Value::Struct(name.into(), returns))
}
}
}
@@ -410,26 +465,26 @@ pub enum Value {
impl Value {
fn as_int(&self) -> Result<i64, FFIError> {
match self {
Value::Int(n) => Ok(*n),
_ => Err(FFIError::ValueCast),
}
match self {
Value::Int(n) => Ok(*n),
_ => Err(FFIError::ValueCast),
}
}
fn as_float(&self) -> Result<f64, FFIError> {
match self {
Value::Float(n) => Ok(*n),
Value::Int(n) => Ok(*n as f64),
_ => Err(FFIError::ValueCast),
}
match self {
Value::Float(n) => Ok(*n),
Value::Int(n) => Ok(*n as f64),
_ => Err(FFIError::ValueCast),
}
}
fn as_ptr(&mut self) -> Result<*mut c_void, FFIError> {
match self {
Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void),
Value::Int(n) => Ok(*n as *mut c_void),
_ => Err(FFIError::ValueCast)
}
match self {
Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void),
Value::Int(n) => Ok(*n as *mut c_void),
_ => Err(FFIError::ValueCast),
}
}
}

View File

@@ -7,8 +7,8 @@ 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::dashu::{Integer, Rational};
use crate::parser::parser::CompositeOpDesc;
use crate::types::*;
use fxhash::FxBuildHasher;
@@ -58,7 +58,7 @@ impl AppendOrPrepend {
#[derive(Debug, Clone, Copy)]
pub enum VarComparison {
Indistinct,
Distinct
Distinct,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -153,11 +153,14 @@ impl DerefMut for ChunkedTermVec {
impl ChunkedTermVec {
#[inline]
pub fn new() -> Self {
Self { chunk_vec: VecDeque::new() }
Self {
chunk_vec: VecDeque::new(),
}
}
pub fn reserve_branch(&mut self, capacity: usize) {
self.chunk_vec.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
self.chunk_vec
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
}
pub fn push_branch_arm(&mut self, branch: VecDeque<ChunkedTerms>) {
@@ -173,19 +176,22 @@ impl ChunkedTermVec {
#[inline]
pub fn add_chunk(&mut self) {
self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![])));
self.chunk_vec
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![])));
}
pub fn push_chunk_term(&mut self, term: QueryTerm) {
match self.chunk_vec.back_mut() {
Some(ChunkedTerms::Branch(_)) => {
self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
self.chunk_vec
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
}
Some(ChunkedTerms::Chunk(chunk)) => {
chunk.push_back(term);
}
None => {
self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
self.chunk_vec
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
}
}
}
@@ -196,7 +202,7 @@ pub enum QueryTerm {
// register, clause type, subterms, clause call policy.
Clause(Cell<RegType>, ClauseType, Vec<Term>, CallPolicy),
Fail,
LocalCut(usize), // var_num
LocalCut(usize), // var_num
GlobalCut(usize), // var_num
GetCutPoint { var_num: usize, prev_b: bool },
GetLevel(usize), // var_num
@@ -266,11 +272,10 @@ impl ClauseInfo for Term {
fn name(&self) -> Option<Atom> {
match self {
Term::Clause(_, name, terms) => {
match name {
atom!(":-") => {
match terms.len() {
1 => None, // a declaration.
1 => None, // a declaration.
2 => terms[0].name(),
_ => Some(*name),
}
@@ -285,7 +290,7 @@ impl ClauseInfo for Term {
fn arity(&self) -> usize {
match self {
Term::Clause(_, name, terms) => match name.as_str() {
Term::Clause(_, name, terms) => match &*name.as_str() {
":-" => match terms.len() {
1 => 0,
2 => terms[0].arity(),
@@ -410,7 +415,6 @@ pub(crate) fn fixity(spec: u32) -> Fixity {
}
}
impl OpDecl {
#[inline]
pub(crate) fn new(op_desc: OpDesc, name: Atom) -> Self {
@@ -477,35 +481,27 @@ pub enum AtomOrString {
impl AtomOrString {
#[inline]
pub fn as_atom(&self, atom_tbl: &mut AtomTable) -> Atom {
pub fn as_atom(&self, atom_tbl: &AtomTable) -> Atom {
match self {
&AtomOrString::Atom(atom) => {
atom
}
AtomOrString::String(string) => {
atom_tbl.build_with(&string)
}
&AtomOrString::Atom(atom) => atom,
AtomOrString::String(string) => AtomTable::build_with(atom_tbl, &string),
}
}
#[inline]
pub fn as_str(&self) -> &str {
pub fn as_str(&self) -> AtomString<'_> {
match self {
AtomOrString::Atom(atom) if atom == &atom!("[]") => "",
AtomOrString::Atom(atom) if atom == &atom!("[]") => AtomString::Static(""),
AtomOrString::Atom(atom) => atom.as_str(),
AtomOrString::String(string) => string.as_str(),
AtomOrString::String(string) => AtomString::Static(string.as_str()),
}
}
#[inline]
pub fn to_string(self) -> String {
match self {
AtomOrString::Atom(atom) => {
atom.as_str().to_owned()
}
AtomOrString::String(string) => {
string
}
AtomOrString::Atom(atom) => atom.as_str().to_owned(),
AtomOrString::String(string) => string,
}
}
}
@@ -561,9 +557,7 @@ pub(crate) fn fetch_op_spec(name: Atom, arity: usize, op_dir: &OpDir) -> Option<
}
})
}
0 => {
fetch_atom_op_spec(name, None, op_dir)
}
0 => fetch_atom_op_spec(name, None, op_dir),
_ => None,
}
}
@@ -595,10 +589,7 @@ pub struct Module {
// Module's and related types are defined in forms.
impl Module {
pub(crate) fn new(
module_decl: ModuleDecl,
listing_src: ListingSource,
) -> Self {
pub(crate) fn new(module_decl: ModuleDecl, listing_src: ListingSource) -> Self {
Module {
module_decl,
code_dir: CodeDir::with_hasher(FxBuildHasher::default()),
@@ -620,7 +611,7 @@ impl Module {
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
FxBuildHasher::default()
FxBuildHasher::default(),
),
listing_src: ListingSource::DynamicallyGenerated,
}
@@ -923,8 +914,10 @@ impl PredicateInfo {
#[inline]
pub(crate) fn must_retract_local_clauses(&self, is_cross_module_clause: bool) -> bool {
self.is_extensible && self.has_clauses && !self.is_discontiguous &&
!(self.is_multifile && is_cross_module_clause)
self.is_extensible
&& self.has_clauses
&& !self.is_discontiguous
&& !(self.is_multifile && is_cross_module_clause)
}
}
@@ -1013,19 +1006,17 @@ impl PredicateSkeleton {
&mut self,
clause_clause_loc: usize,
) -> Option<usize> {
let search_result = self.core.clause_clause_locs
.make_contiguous()[0..self.core.clause_assert_margin]
let search_result = self.core.clause_clause_locs.make_contiguous()
[0..self.core.clause_assert_margin]
.binary_search_by(|loc| clause_clause_loc.cmp(&loc));
match search_result {
Ok(loc) => Some(loc),
Err(_) => {
self.core.clause_clause_locs
.make_contiguous()[self.core.clause_assert_margin..]
.binary_search_by(|loc| loc.cmp(&clause_clause_loc))
.map(|loc| loc + self.core.clause_assert_margin)
.ok()
}
Err(_) => self.core.clause_clause_locs.make_contiguous()
[self.core.clause_assert_margin..]
.binary_search_by(|loc| loc.cmp(&clause_clause_loc))
.map(|loc| loc + self.core.clause_assert_margin)
.ok(),
}
}
}

View File

@@ -73,12 +73,8 @@ impl IterStackLoc {
#[inline]
pub fn as_ref(self) -> Ref {
match self.heap_or_stack() {
HeapOrStackTag::Heap => {
Ref::heap_cell(self.value() as usize)
}
HeapOrStackTag::Stack => {
Ref::stack_cell(self.value() as usize)
}
HeapOrStackTag::Heap => Ref::heap_cell(self.value() as usize),
HeapOrStackTag::Stack => Ref::stack_cell(self.value() as usize),
}
}
}
@@ -158,24 +154,16 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
#[inline]
pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue {
match loc.heap_or_stack() {
HeapOrStackTag::Heap => {
&mut self.heap[loc.value() as usize]
}
HeapOrStackTag::Stack => {
&mut self.machine_stack[loc.value() as usize]
}
HeapOrStackTag::Heap => &mut self.heap[loc.value() as usize],
HeapOrStackTag::Stack => &mut self.machine_stack[loc.value() as usize],
}
}
#[inline]
pub fn read_cell(&self, loc: IterStackLoc) -> HeapCellValue {
match loc.heap_or_stack() {
HeapOrStackTag::Heap => {
self.heap[loc.value() as usize]
}
HeapOrStackTag::Stack => {
self.machine_stack[loc.value() as usize]
}
HeapOrStackTag::Heap => self.heap[loc.value() as usize],
HeapOrStackTag::Stack => self.machine_stack[loc.value() as usize],
}
}
@@ -228,7 +216,10 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
if !cell.get_mark_bit() {
cell.set_mark_bit(true);
self.stack.push(IterStackLoc::iterable_loc(loc.value() as usize, loc.heap_or_stack()));
self.stack.push(IterStackLoc::iterable_loc(
loc.value() as usize,
loc.heap_or_stack(),
));
}
}
@@ -236,7 +227,10 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
while let Some(h) = self.stack.pop() {
if h.is_pending_mark() {
self.push_if_unmarked(h);
self.stack.push(IterStackLoc::mark_loc(h.value() as usize, h.heap_or_stack()));
self.stack.push(IterStackLoc::mark_loc(
h.value() as usize,
h.heap_or_stack(),
));
self.forward_if_referent_marked(h);
continue;
@@ -467,7 +461,7 @@ impl<'a> LeftistPostOrderHeapIter<'a> {
#[inline]
pub fn pop_stack(&mut self) {
if let Some((child_count, ..)) = self.parent_stack.last() {
for _ in 0 .. *child_count {
for _ in 0..*child_count {
self.base_iter.pop_stack();
}
@@ -508,7 +502,6 @@ mod tests {
use super::*;
use crate::machine::mock_wam::*;
#[test]
fn heap_stackless_iter_tests() {
let mut wam = MockWAM::new();
@@ -518,8 +511,8 @@ mod tests {
let b_atom = atom!("b");
wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
@@ -629,12 +622,12 @@ mod tests {
{
wam.machine_st.heap.push(heap_loc_as_cell!(0));
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
heap_loc_as_cell!(0)
);
assert_eq!(iter.next(), None);
}
@@ -650,10 +643,7 @@ mod tests {
wam.machine_st.heap.push(empty_list_as_cell!());
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -688,10 +678,7 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(0));
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -721,7 +708,8 @@ mod tests {
// first a 'dangling' partial string, later modified to be a two-part complete string,
// then a three-part cyclic string involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{
@@ -742,11 +730,8 @@ mod tests {
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
&mut wam.machine_st.atom_tbl,
);
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
@@ -771,13 +756,12 @@ mod tests {
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(4));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(2)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(2)));
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
pstr_loc_as_cell!(4),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(4));
let pstr_offset_cell = pstr_offset_as_cell!(0);
@@ -789,19 +773,35 @@ mod tests {
}
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_loc_as_cell!(2));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
pstr_loc_as_cell!(2)
);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_loc_as_cell!(4));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_offset_as_cell!(0));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[5]), fixnum_as_cell!(Fixnum::build_with(2)));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[3]),
pstr_loc_as_cell!(4)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[4]),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[5]),
fixnum_as_cell!(Fixnum::build_with(2))
);
wam.machine_st.heap.truncate(4);
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
@@ -819,7 +819,9 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
@@ -827,8 +829,14 @@ mod tests {
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(iter.next(), None);
@@ -1059,10 +1067,22 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), heap_loc_as_cell!(1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(2));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), heap_loc_as_cell!(3));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
heap_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
heap_loc_as_cell!(2)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[2]),
heap_loc_as_cell!(3)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[3]),
heap_loc_as_cell!(3)
);
wam.machine_st.heap.clear();
@@ -1089,9 +1109,18 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), list_loc_as_cell!(1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(1));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
list_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
list_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[2]),
list_loc_as_cell!(1)
);
wam.machine_st.heap.clear();
@@ -1202,37 +1231,109 @@ mod tests {
assert_eq!(iter.next(), None);
}
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), list_loc_as_cell!(4));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), str_loc_as_cell!(6));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[5]), heap_loc_as_cell!(8));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(f_atom, 1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(11));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[8]), list_loc_as_cell!(9));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[9]), heap_loc_as_cell!(9));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[10]), empty_list_as_cell!());
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[11]), attr_var_as_cell!(11));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[12]), heap_loc_as_cell!(13));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[13]), list_loc_as_cell!(14));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[14]), str_loc_as_cell!(16));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[15]), heap_loc_as_cell!(19));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[16]), atom_as_cell!(clpz_atom, 2));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[17]), atom_as_cell!(a_atom));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[18]), atom_as_cell!(b_atom));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[19]), list_loc_as_cell!(20));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[20]), str_loc_as_cell!(22));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[21]), empty_list_as_cell!());
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[22]), atom_as_cell!(p_atom, 1));
assert_eq!(unmark_cell_bits!(wam.machine_st.heap[23]), heap_loc_as_cell!(23));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
list_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[1]),
heap_loc_as_cell!(1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[2]),
heap_loc_as_cell!(3)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[3]),
list_loc_as_cell!(4)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[4]),
str_loc_as_cell!(6)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[5]),
heap_loc_as_cell!(8)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[6]),
atom_as_cell!(f_atom, 1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[7]),
heap_loc_as_cell!(11)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[8]),
list_loc_as_cell!(9)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[9]),
heap_loc_as_cell!(9)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[10]),
empty_list_as_cell!()
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[11]),
attr_var_as_cell!(11)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[12]),
heap_loc_as_cell!(13)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[13]),
list_loc_as_cell!(14)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[14]),
str_loc_as_cell!(16)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[15]),
heap_loc_as_cell!(19)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[16]),
atom_as_cell!(clpz_atom, 2)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[17]),
atom_as_cell!(a_atom)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[18]),
atom_as_cell!(b_atom)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[19]),
list_loc_as_cell!(20)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[20]),
str_loc_as_cell!(22)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[21]),
empty_list_as_cell!()
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[22]),
atom_as_cell!(p_atom, 1)
);
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[23]),
heap_loc_as_cell!(23)
);
wam.machine_st.heap.clear();
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
fixnum_as_cell!(Fixnum::build_with(0))
fixnum_as_cell!(Fixnum::build_with(0)),
);
assert_eq!(
@@ -1251,19 +1352,16 @@ mod tests {
wam.machine_st.heap.push(str_loc_as_cell!(1));
wam.machine_st.heap.push(atom_as_cell!(atom!("g"),2));
wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
wam.machine_st.heap.push(heap_loc_as_cell!(0));
wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
str_loc_as_cell!(1),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(1));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(atom!("g"),2)
atom_as_cell!(atom!("g"), 2)
);
assert_eq!(
@@ -1271,10 +1369,7 @@ mod tests {
atom_as_cell!(atom!("y"))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(1)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
assert!(iter.next().is_none());
}
@@ -1283,19 +1378,16 @@ mod tests {
wam.machine_st.heap.clear();
wam.machine_st.heap.push(atom_as_cell!(atom!("g"),2));
wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
wam.machine_st.heap.push(str_loc_as_cell!(0));
wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(atom!("g"),2)
atom_as_cell!(atom!("g"), 2)
);
assert_eq!(
@@ -1303,10 +1395,7 @@ mod tests {
atom_as_cell!(atom!("y"))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
str_loc_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
assert!(iter.next().is_none());
}
@@ -1327,10 +1416,7 @@ mod tests {
wam.machine_st.heap.push(empty_list_as_cell!());
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(7),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(7));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -1390,10 +1476,7 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(1));
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -1420,38 +1503,38 @@ mod tests {
wam.machine_st.heap.clear();
// representation of one of the heap terms as in issue #1384.
/*
wam.machine_st.heap.push(list_loc_as_cell!(7));
wam.machine_st.heap.push(heap_loc_as_cell!(0));
wam.machine_st.heap.push(list_loc_as_cell!(3));
wam.machine_st.heap.push(list_loc_as_cell!(5));
wam.machine_st.heap.push(empty_list_as_cell!());
wam.machine_st.heap.push(heap_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2));
wam.machine_st.heap.push(empty_list_as_cell!());
wam.machine_st.heap.push(heap_loc_as_cell!(3));
/*
wam.machine_st.heap.push(list_loc_as_cell!(7));
wam.machine_st.heap.push(heap_loc_as_cell!(0));
wam.machine_st.heap.push(list_loc_as_cell!(3));
wam.machine_st.heap.push(list_loc_as_cell!(5));
wam.machine_st.heap.push(empty_list_as_cell!());
wam.machine_st.heap.push(heap_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2));
wam.machine_st.heap.push(empty_list_as_cell!());
wam.machine_st.heap.push(heap_loc_as_cell!(3));
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
{
let mut iter = stackless_preorder_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
while let Some(_) = iter.next() {
print_heap_terms(iter.heap.iter(), 0);
println!("");
}
while let Some(_) = iter.next() {
print_heap_terms(iter.heap.iter(), 0);
println!("");
}
/*
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(atom!("f"), 2)
);
/*
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(atom!("f"), 2)
);
assert!(iter.next().is_none());
*/
}
*/
assert!(iter.next().is_none());
*/
}
*/
}
#[test]
@@ -1462,7 +1545,8 @@ mod tests {
let a_atom = atom!("a");
let b_atom = atom!("b");
wam.machine_st.heap
wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{
@@ -1686,7 +1770,8 @@ mod tests {
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{
@@ -1710,7 +1795,8 @@ mod tests {
wam.machine_st.heap.pop();
wam.machine_st.heap.push(heap_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl);
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
{
@@ -1731,10 +1817,14 @@ mod tests {
}
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{
let mut iter = stackful_preorder_iter(
@@ -1750,7 +1840,10 @@ mod tests {
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(
iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(0i64))
);
assert_eq!(iter.next(), None);
}
@@ -1764,7 +1857,9 @@ mod tests {
*/
wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
{
let mut iter = stackful_preorder_iter(
@@ -1781,13 +1876,19 @@ mod tests {
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1i64)));
assert_eq!(
iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(1i64))
);
let h = iter.focus();
assert_eq!(h.value(), 5);
assert_eq!(unmark_cell_bits!(iter.heap[4]), pstr_offset_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.heap[5]), fixnum_as_cell!(Fixnum::build_with(1i64)));
assert_eq!(
unmark_cell_bits!(iter.heap[5]),
fixnum_as_cell!(Fixnum::build_with(1i64))
);
assert_eq!(iter.next(), None);
}
@@ -1980,10 +2081,7 @@ mod tests {
pstr_as_cell!(atom!("a string"))
);
assert_eq!(
iter.next().unwrap(),
empty_list_as_cell!()
);
assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
assert_eq!(iter.next(), None);
}
@@ -2037,7 +2135,8 @@ mod tests {
let a_atom = atom!("a");
let b_atom = atom!("b");
wam.machine_st.heap
wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{
@@ -2075,7 +2174,8 @@ mod tests {
]
));
for _ in 0..20 { // 0000 {
for _ in 0..20 {
// 0000 {
let mut iter = stackful_post_order_iter(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
@@ -2263,7 +2363,8 @@ mod tests {
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{
@@ -2286,7 +2387,8 @@ mod tests {
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl);
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
{
@@ -2307,10 +2409,14 @@ mod tests {
}
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{
let mut iter = stackful_post_order_iter(
@@ -2319,8 +2425,14 @@ mod tests {
pstr_loc_as_cell!(0),
);
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(
iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(0i64))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2329,7 +2441,9 @@ mod tests {
}
wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
{
let mut iter = stackful_post_order_iter(
@@ -2338,8 +2452,14 @@ mod tests {
pstr_loc_as_cell!(0),
);
assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1i64)));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(
iter.next().unwrap(),
fixnum_as_cell!(Fixnum::build_with(1i64))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2498,13 +2618,12 @@ mod tests {
let a_atom = atom!("a");
let b_atom = atom!("b");
wam.machine_st.heap.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{
let mut iter = stackless_post_order_iter(
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2535,10 +2654,7 @@ mod tests {
));
for _ in 0..20 {
let mut iter = stackless_post_order_iter(
&mut wam.machine_st.heap,
str_loc_as_cell!(0),
);
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
@@ -2568,10 +2684,8 @@ mod tests {
{
wam.machine_st.heap.push(heap_loc_as_cell!(0));
let mut iter = stackless_post_order_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2587,10 +2701,8 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(1));
wam.machine_st.heap.push(heap_loc_as_cell!(0));
let mut iter = stackless_post_order_iter(
&mut wam.machine_st.heap,
heap_loc_as_cell!(0),
);
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2615,7 +2727,8 @@ mod tests {
wam.machine_st.heap.push(empty_list_as_cell!());
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2647,7 +2760,8 @@ mod tests {
wam.machine_st.heap.push(heap_loc_as_cell!(0));
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
// the cycle will be iterated twice before being detected.
assert_eq!(
@@ -2675,7 +2789,8 @@ mod tests {
}
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
// cut the iteration short to check that all cells are
// unmarked and unforwarded by the Drop instance of
@@ -2705,11 +2820,13 @@ mod tests {
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2724,16 +2841,14 @@ mod tests {
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
&mut wam.machine_st.atom_tbl,
);
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2749,20 +2864,31 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0)));
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
let mut pstr_loc_cell = pstr_loc_as_cell!(0);
pstr_loc_cell.set_forwarding_bit(true);
// assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2773,14 +2899,23 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap);
wam.machine_st.heap.pop();
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1)));
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
//assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
pstr_offset_as_cell!(0)
);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
@@ -2801,7 +2936,8 @@ mod tests {
wam.machine_st.heap.extend(functor);
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
@@ -2861,7 +2997,8 @@ mod tests {
wam.machine_st.heap[4] = list_loc_as_cell!(1);
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
let mut iter =
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),

View File

@@ -29,6 +29,7 @@ use std::convert::TryFrom;
use std::iter::once;
use std::net::{IpAddr, TcpListener};
use std::rc::Rc;
use std::sync::Arc;
/* contains the location, name, precision and Specifier of the parent op. */
#[derive(Debug, Copy, Clone)]
@@ -46,7 +47,7 @@ impl DirectedOp {
}
#[inline]
fn is_prefix(&self )-> bool {
fn is_prefix(&self) -> bool {
match self {
&DirectedOp::Left(_name, cell) | &DirectedOp::Right(_name, cell) => {
is_prefix!(cell.get_spec() as u32)
@@ -74,7 +75,7 @@ fn needs_bracketing(child_desc: OpDesc, op: &DirectedOp) -> bool {
DirectedOp::Left(name, cell) => {
let (priority, spec) = cell.get();
if name.as_str() == "-" {
if &*name.as_str() == "-" {
let child_assoc = child_desc.get_spec();
if is_prefix!(spec) && (is_postfix!(child_assoc) || is_infix!(child_assoc)) {
return true;
@@ -178,16 +179,16 @@ fn char_to_string(is_quoted: bool, c: char) -> String {
'\u{08}' if is_quoted => "\\b".to_string(), // UTF-8 backspace
'\u{07}' if is_quoted => "\\a".to_string(), // UTF-8 alert
'\\' if is_quoted => "\\\\".to_string(),
' ' | '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => {
c.to_string()
}
_ =>
' ' | '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"'
| '\\' => c.to_string(),
_ => {
if c.is_whitespace() || c.is_control() {
// print all other control and whitespace characters in hex.
format!("\\x{:x}\\", c as u32)
} else {
c.to_string()
}
}
}
}
@@ -217,7 +218,8 @@ enum TokenOrRedirect {
CompositeRedirect(usize, DirectedOp),
CurlyBracketRedirect(usize),
FunctorRedirect(usize),
#[allow(unused)] IpAddr(IpAddr),
#[allow(unused)]
IpAddr(IpAddr),
NumberFocus(usize, NumberFocus, Option<DirectedOp>),
Open,
Close,
@@ -467,8 +469,8 @@ pub fn fmt_float(mut fl: f64) -> String {
*/
if let Some(e_index) = fl_str.find('e') {
if !fl_str[0 .. e_index].contains('.') {
return fl_str[0 .. e_index].to_string() + ".0" + &fl_str[e_index ..];
if !fl_str[0..e_index].contains('.') {
return fl_str[0..e_index].to_string() + ".0" + &fl_str[e_index..];
}
}
@@ -479,7 +481,7 @@ pub fn fmt_float(mut fl: f64) -> String {
pub struct HCPrinter<'a, Outputter> {
outputter: Outputter,
iter: StackfulPreOrderHeapIter<'a>,
atom_tbl: &'a mut AtomTable,
atom_tbl: Arc<AtomTable>,
op_dir: &'a OpDir,
state_stack: Vec<TokenOrRedirect>,
toplevel_spec: Option<DirectedOp>,
@@ -548,7 +550,7 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option<String>
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
pub fn new(
heap: &'a mut Heap,
atom_tbl: &'a mut AtomTable,
atom_tbl: Arc<AtomTable>,
stack: &'a mut Stack,
op_dir: &'a OpDir,
output: Outputter,
@@ -578,7 +580,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
fn ambiguity_check(&self, atom: &str) -> bool {
let tail = &self.outputter.as_str()[self.last_item_idx..];
if !self.quoted || non_quoted_token(atom.chars()) {
if atom == "," || !self.quoted || non_quoted_token(atom.chars()) {
requires_space(tail, atom)
} else {
requires_space(tail, "'")
@@ -625,11 +627,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} else {
let op = DirectedOp::Left(name, spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, op));
self.state_stack
.push(TokenOrRedirect::CompositeRedirect(max_depth, op));
self.state_stack.push(TokenOrRedirect::Op(name, spec));
}
} else {
match name.as_str() {
match &*name.as_str() {
"|" => {
self.format_bar_separator_op(max_depth, name, spec);
return;
@@ -653,9 +656,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let left_directed_op = DirectedOp::Left(name, spec);
let right_directed_op = DirectedOp::Right(name, spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
max_depth,
left_directed_op,
));
self.state_stack.push(TokenOrRedirect::Op(name, spec));
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op));
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
max_depth,
right_directed_op,
));
}
}
}
@@ -681,7 +690,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Close);
for _ in 0..arity {
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.state_stack.push(TokenOrRedirect::Comma);
}
@@ -738,9 +748,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
return false;
}
self.state_stack.push(TokenOrRedirect::RightCurly);
self.state_stack.push(TokenOrRedirect::CurlyBracketRedirect(max_depth));
self.state_stack
.push(TokenOrRedirect::CurlyBracketRedirect(max_depth));
self.state_stack.push(TokenOrRedirect::LeftCurly);
true
@@ -750,10 +760,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let h = self.iter.stack_last().unwrap();
let cell = self.iter.read_cell(h);
let cell = heap_bound_store(
&self.iter.heap,
heap_bound_deref(&self.iter.heap, cell),
);
let cell = heap_bound_store(&self.iter.heap, heap_bound_deref(&self.iter.heap, cell));
// 7.10.4
if let Some(var) = numbervar(&self.numbervars_offset, cell) {
@@ -835,10 +842,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if let Some(cell) = self.iter.next() {
let is_cyclic = cell.get_forwarding_bit();
let cell = heap_bound_store(
self.iter.heap,
heap_bound_deref(self.iter.heap, cell),
);
let cell = heap_bound_store(self.iter.heap, heap_bound_deref(self.iter.heap, cell));
let cell = unmark_cell_bits!(cell);
match self.var_names.get(&cell).cloned() {
@@ -891,7 +895,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
}
fn print_impromptu_atom(&mut self, atom: Atom) {
let result = self.print_op_addendum(atom.as_str());
let result = self.print_op_addendum(&*atom.as_str());
push_space_if_amb!(self, result.as_str(), {
append_str!(self, &result);
@@ -1050,7 +1054,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
NumberFocus::Denominator(r),
left_directed_op,
));
self.state_stack.push(TokenOrRedirect::Op(rdiv_ct, *op_desc));
self.state_stack
.push(TokenOrRedirect::Op(rdiv_ct, *op_desc));
self.state_stack.push(TokenOrRedirect::NumberFocus(
max_depth,
NumberFocus::Numerator(r),
@@ -1157,8 +1162,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset => {
self.iter.pop_stack();
}
HeapCellValueTag::CStr => {
}
HeapCellValueTag::CStr => {}
_ => {
unreachable!();
}
@@ -1203,8 +1207,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
append_str!(self, "[]");
}
} else {
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.iter
.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
}
}
} else {
@@ -1298,7 +1304,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
}
}
self.state_stack.push(TokenOrRedirect::CloseList(switch.clone()));
self.state_stack
.push(TokenOrRedirect::CloseList(switch.clone()));
Some(switch)
}
@@ -1335,9 +1342,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let switch = self.close_list(cell);
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth+1));
self.state_stack
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
self.open_list(switch);
}
@@ -1353,8 +1362,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
max_depth: usize,
) {
let add_brackets = if !self.ignore_ops {
negated_operand ||
if let Some(ref op) = op {
negated_operand
|| if let Some(ref op) = op {
if self.numbervars && arity == 1 && name == atom!("$VAR") {
!self.iter.immediate_leaf_has_property(|addr| {
match Number::try_from(addr) {
@@ -1381,7 +1390,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Open);
if !self.outputter.ends_with(" ") {
let parent_op = self.parent_of_first_op
let parent_op = self
.parent_of_first_op
.and_then(|(parent_op, last_item_idx)| {
// if parent_op isn't printed to the output string
// already, then it doesn't border the present op
@@ -1395,7 +1405,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
for op in &[op, parent_op] {
if let Some(ref op) = &op {
if op.is_left() && (op.is_prefix() || requires_space(op.as_atom().as_str(), "(")) {
if op.is_left()
&& (op.is_prefix() || requires_space(&*op.as_atom().as_str(), "("))
{
self.state_stack.push(TokenOrRedirect::Space);
return;
}
@@ -1519,7 +1531,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
max_depth,
);
} else {
push_space_if_amb!(printer, name.as_str(), {
push_space_if_amb!(printer, &*name.as_str(), {
printer.format_clause(max_depth, arity, name, None);
});
}
@@ -1529,14 +1541,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if let Some(ref op) = op {
let op_is_prefix = op.is_prefix() && op.is_left();
if op_is_prefix || printer.outputter.ends_with(&format!(" {}", op.as_atom().as_str())) {
if op_is_prefix
|| printer
.outputter
.ends_with(&format!(" {}", op.as_atom().as_str()))
{
result.push(' ');
}
result.push('(');
}
result += &printer.print_op_addendum(name.as_str());
result += &printer.print_op_addendum(&*name.as_str());
if op.is_some() {
result.push(')');
@@ -1546,7 +1562,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
append_str!(printer, &result);
});
} else {
push_space_if_amb!(printer, name.as_str(), {
push_space_if_amb!(printer, &*name.as_str(), {
printer.print_impromptu_atom(name);
});
}
@@ -1557,7 +1573,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
None => return,
};
if !addr.is_var() && !addr.is_compound(&self.iter.heap) && self.max_depth_exhausted(max_depth) {
if !addr.is_var()
&& !addr.is_compound(&self.iter.heap)
&& self.max_depth_exhausted(max_depth)
{
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
return;
}
@@ -1567,7 +1586,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
print_struct(self, name, arity);
}
(HeapCellValueTag::Char, c) => {
let name = self.atom_tbl.build_with(&String::from(c));
let name = AtomTable::build_with(&self.atom_tbl, &String::from(c));
print_struct(self, name, 0);
}
(HeapCellValueTag::Str, s) => {
@@ -1585,7 +1604,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
max_depth,
);
} else {
push_space_if_amb!(self, name.as_str(), {
push_space_if_amb!(self, &*name.as_str(), {
self.format_clause(max_depth, arity, name, None);
});
}
@@ -1668,7 +1687,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
TokenOrRedirect::BarAsOp => append_str!(self, " | "),
TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c),
TokenOrRedirect::Op(atom, op) => {
self.print_op(atom.as_str());
self.print_op(&*atom.as_str());
if is_prefix!(op.get_spec()) {
self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op)));
@@ -1737,16 +1756,18 @@ mod tests {
let b_atom = atom!("b");
let c_atom = atom!("c");
wam.machine_st.heap.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
heap_loc_as_cell!(0)
heap_loc_as_cell!(0),
);
let output = printer.print();
@@ -1771,11 +1792,11 @@ mod tests {
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
heap_loc_as_cell!(0)
heap_loc_as_cell!(0),
);
let output = printer.print();
@@ -1795,11 +1816,11 @@ mod tests {
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
heap_loc_as_cell!(0)
heap_loc_as_cell!(0),
);
let output = printer.print();
@@ -1808,14 +1829,16 @@ mod tests {
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
heap_loc_as_cell!(0)
heap_loc_as_cell!(0),
);
printer.var_names.insert(list_loc_as_cell!(1), VarPtr::from("L"));
printer
.var_names
.insert(list_loc_as_cell!(1), VarPtr::from("L"));
let output = printer.print();
@@ -1839,7 +1862,7 @@ mod tests {
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
@@ -1858,7 +1881,7 @@ mod tests {
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
@@ -1875,14 +1898,16 @@ mod tests {
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
heap_loc_as_cell!(0)
heap_loc_as_cell!(0),
);
printer.var_names.insert(list_loc_as_cell!(1), VarPtr::from("L"));
printer
.var_names
.insert(list_loc_as_cell!(1), VarPtr::from("L"));
let output = printer.print();
@@ -1905,11 +1930,11 @@ mod tests {
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
heap_loc_as_cell!(0)
heap_loc_as_cell!(0),
);
printer.max_depth = 5;
@@ -1923,16 +1948,16 @@ mod tests {
wam.machine_st.heap.clear();
put_partial_string(&mut wam.machine_st.heap, "abc", &mut wam.machine_st.atom_tbl);
put_partial_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
pstr_loc_as_cell!(0)
pstr_loc_as_cell!(0),
);
let output = printer.print();
@@ -1956,7 +1981,7 @@ mod tests {
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.atom_tbl,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
@@ -2000,35 +2025,39 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir.insert(
(atom!("+"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
wam.op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
wam.op_dir
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
wam.op_dir
.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
assert_eq!(&wam.parse_and_print_term("[a|[] + b].").unwrap(), "[a|[]+b]");
assert_eq!(
&wam.parse_and_print_term("[a|[] + b].").unwrap(),
"[a|[]+b]"
);
all_cells_unmarked(&wam.machine_st.heap);
assert_eq!(&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(), "[a|[b|c]*d]");
assert_eq!(
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
"[a|[b|c]*d]"
);
all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir.insert(
(atom!("fy"), Fixity::Pre),
OpDesc::build_with(9, FY as u8),
wam.op_dir
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY as u8));
wam.op_dir
.insert((atom!("yf"), Fixity::Post), OpDesc::build_with(9, YF as u8));
assert_eq!(
&wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(),
"(fy (fy 1)yf)yf"
);
wam.op_dir.insert(
(atom!("yf"), Fixity::Post),
OpDesc::build_with(9, YF as u8),
assert_eq!(
&wam.parse_and_print_term("fy(fy(yf(fy(1)))).").unwrap(),
"fy fy (fy 1)yf"
);
assert_eq!(&wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(), "(fy (fy 1)yf)yf");
assert_eq!(&wam.parse_and_print_term("fy(fy(yf(fy(1)))).").unwrap(), "fy fy (fy 1)yf");
}
}

View File

@@ -1,13 +1,13 @@
use std::sync::{Arc, Mutex, Condvar};
use std::future::Future;
use std::pin::Pin;
use http_body_util::Full;
use bytes::Bytes;
use http_body_util::Full;
use hyper::service::Service;
use hyper::{body::Incoming as IncomingBody, Request, Response};
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Condvar, Mutex};
pub struct HttpListener {
pub incoming: std::sync::mpsc::Receiver<HttpRequest>
pub incoming: std::sync::mpsc::Receiver<HttpRequest>,
}
#[derive(Debug)]
@@ -28,27 +28,28 @@ impl Service<Request<IncomingBody>> for HttpService {
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn call(&mut self, req: Request<IncomingBody>) -> Self::Future {
// new connection!
// we send the Request info to Prolog
let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
let http_request = HttpRequest { request: req, response: Arc::clone(&response) };
self.tx.send(http_request).unwrap();
// new connection!
// we send the Request info to Prolog
let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
let http_request = HttpRequest {
request: req,
response: Arc::clone(&response),
};
self.tx.send(http_request).unwrap();
// we wait for the Response info from Prolog
{
let (ready, _response, cvar) = &*response;
let mut ready = ready.lock().unwrap();
while !*ready {
ready = cvar.wait(ready).unwrap();
}
}
{
let (_, response, _) = &*response;
let response = response.lock().unwrap().take();
let res = response.expect("Data race error in HTTP Server");
Box::pin(async move {
Ok(res)
})
}
// we wait for the Response info from Prolog
{
let (ready, _response, cvar) = &*response;
let mut ready = ready.lock().unwrap();
while !*ready {
ready = cvar.wait(ready).unwrap();
}
}
{
let (_, response, _) = &*response;
let response = response.lock().unwrap().take();
let res = response.expect("Data race error in HTTP Server");
Box::pin(async move { Ok(res) })
}
}
}

View File

@@ -150,17 +150,20 @@ impl<'a> IndexingCodeMergingPtr<'a> {
let third_level_index = if self.append_or_prepend.is_append() {
vec![
IndexedChoiceInstruction::Try(external),
IndexedChoiceInstruction::Trust(index)
].into()
IndexedChoiceInstruction::Trust(index),
]
.into()
} else {
vec![
IndexedChoiceInstruction::Try(index),
IndexedChoiceInstruction::Trust(external)
].into()
IndexedChoiceInstruction::Trust(external),
]
.into()
};
let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index));
self.indexing_code
.push(IndexingLine::IndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => {
@@ -188,7 +191,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
};
let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::DynamicIndexedChoice(third_level_index));
self.indexing_code
.push(IndexingLine::DynamicIndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => {
@@ -275,10 +279,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
);
}
None | Some(IndexingCodePtr::Fail) => {
constants.insert(
overlapping_constant,
IndexingCodePtr::External(index),
);
constants
.insert(overlapping_constant, IndexingCodePtr::External(index));
}
Some(IndexingCodePtr::DynamicExternal(o)) => {
self.add_dynamic_indexed_choice_for_constant(
@@ -345,16 +347,10 @@ impl<'a> IndexingCodeMergingPtr<'a> {
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => {
match constants.get(&constant).cloned() {
None | Some(IndexingCodePtr::Fail) if self.is_dynamic => {
constants.insert(
constant,
IndexingCodePtr::DynamicExternal(index),
);
constants.insert(constant, IndexingCodePtr::DynamicExternal(index));
}
None | Some(IndexingCodePtr::Fail) => {
constants.insert(
constant,
IndexingCodePtr::External(index),
);
constants.insert(constant, IndexingCodePtr::External(index));
}
Some(IndexingCodePtr::DynamicExternal(o)) => {
self.add_dynamic_indexed_choice_for_constant(o, constant, index);
@@ -432,17 +428,20 @@ impl<'a> IndexingCodeMergingPtr<'a> {
let third_level_index = if self.append_or_prepend.is_append() {
vec![
IndexedChoiceInstruction::Try(external),
IndexedChoiceInstruction::Trust(index)
].into()
IndexedChoiceInstruction::Trust(index),
]
.into()
} else {
vec![
IndexedChoiceInstruction::Try(index),
IndexedChoiceInstruction::Trust(external)
].into()
IndexedChoiceInstruction::Trust(external),
]
.into()
};
let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index));
self.indexing_code
.push(IndexingLine::IndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => {
@@ -470,7 +469,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
};
let indexing_code_len = self.indexing_code.len();
self.indexing_code.push(IndexingLine::DynamicIndexedChoice(third_level_index));
self.indexing_code
.push(IndexingLine::DynamicIndexedChoice(third_level_index));
match &mut self.indexing_code[self.offset] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => {
@@ -584,13 +584,15 @@ impl<'a> IndexingCodeMergingPtr<'a> {
let third_level_index = if self.append_or_prepend.is_append() {
vec![
IndexedChoiceInstruction::Try(o),
IndexedChoiceInstruction::Trust(index)
].into()
IndexedChoiceInstruction::Trust(index),
]
.into()
} else {
vec![
IndexedChoiceInstruction::Try(index),
IndexedChoiceInstruction::Trust(o)
].into()
IndexedChoiceInstruction::Trust(o),
]
.into()
};
self.indexing_code
@@ -613,7 +615,7 @@ pub(crate) fn merge_clause_index(
target_indexing_code: &mut Vec<IndexingLine>,
skeleton: &mut [ClauseIndexInfo], // the clause to be merged is the last element in the skeleton.
retracted_clauses: &Option<Vec<ClauseIndexInfo>>,
new_clause_loc: usize, // the absolute location of the new clause in the code vector.
new_clause_loc: usize, // the absolute location of the new clause in the code vector.
append_or_prepend: AppendOrPrepend,
) {
let opt_arg_index_key = match append_or_prepend {
@@ -636,11 +638,7 @@ pub(crate) fn merge_clause_index(
for overlapping_constant in overlapping_constants {
merging_ptr.offset = 0;
merging_ptr.index_overlapping_constant(
*constant,
*overlapping_constant,
offset,
);
merging_ptr.index_overlapping_constant(*constant, *overlapping_constant, offset);
}
}
OptArgIndexKey::Structure(_, index_loc, name, arity) => {
@@ -1060,19 +1058,27 @@ fn cap_choice_seq(prelude: &mut [IndexedChoiceInstruction]) {
#[inline]
fn cap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
prelude.last_mut().map(|instr| {
if let IndexedChoiceInstruction::Retry(i) = instr {
prelude.last_mut().map(|instr| match instr {
IndexedChoiceInstruction::Retry(i) => {
*instr = IndexedChoiceInstruction::Trust(*i);
}
IndexedChoiceInstruction::DefaultRetry(i) => {
*instr = IndexedChoiceInstruction::DefaultTrust(*i);
}
_ => {}
});
}
#[inline]
fn uncap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
prelude.last_mut().map(|instr| {
if let IndexedChoiceInstruction::Trust(i) = instr {
prelude.last_mut().map(|instr| match instr {
IndexedChoiceInstruction::Trust(i) => {
*instr = IndexedChoiceInstruction::Retry(*i);
}
IndexedChoiceInstruction::DefaultTrust(i) => {
*instr = IndexedChoiceInstruction::DefaultRetry(*i);
}
_ => {}
});
}
@@ -1087,7 +1093,7 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) {
pub(crate) fn constant_key_alternatives(
constant: Literal,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
// arena: &mut Arena,
) -> Vec<Literal> {
let mut constants = vec![];
@@ -1099,7 +1105,7 @@ pub(crate) fn constant_key_alternatives(
}
}
Literal::Char(c) => {
let atom = atom_tbl.build_with(&c.to_string());
let atom = AtomTable::build_with(&atom_tbl, &c.to_string());
constants.push(Literal::Atom(atom));
}
/*
@@ -1148,11 +1154,19 @@ pub(crate) trait Indexer {
fn new() -> Self;
fn constants(&mut self) -> &mut IndexMap<Literal, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn constants(
&mut self,
) -> &mut IndexMap<Literal, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn lists(&mut self) -> &mut VecDeque<Self::ThirdLevelIndex>;
fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn structures(
&mut self,
) -> &mut IndexMap<(Atom, usize), VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn compute_index(is_initial_index: bool, index: usize) -> Self::ThirdLevelIndex;
fn compute_index(
is_initial_index: bool,
index: usize,
non_counted_bt: bool,
) -> Self::ThirdLevelIndex;
fn second_level_index<IndexKey: Eq + Hash>(
indices: IndexMap<IndexKey, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>,
@@ -1188,7 +1202,9 @@ impl Indexer for StaticCodeIndices {
}
#[inline]
fn constants(&mut self) -> &mut IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
fn constants(
&mut self,
) -> &mut IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
&mut self.constants
}
@@ -1198,13 +1214,21 @@ impl Indexer for StaticCodeIndices {
}
#[inline]
fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
fn structures(
&mut self,
) -> &mut IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
&mut self.structures
}
fn compute_index(is_initial_index: bool, index: usize) -> IndexedChoiceInstruction {
fn compute_index(
is_initial_index: bool,
index: usize,
non_counted_bt: bool,
) -> IndexedChoiceInstruction {
if is_initial_index {
IndexedChoiceInstruction::Try(index + 1)
} else if non_counted_bt {
IndexedChoiceInstruction::DefaultRetry(index + 1)
} else {
IndexedChoiceInstruction::Retry(index + 1)
}
@@ -1232,7 +1256,9 @@ impl Indexer for StaticCodeIndices {
}
fn switch_on<IndexKey: Eq + Hash>(
mut instr_fn: impl FnMut(IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>) -> IndexingInstruction,
mut instr_fn: impl FnMut(
IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>,
) -> IndexingInstruction,
index: &mut IndexMap<IndexKey, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
prelude: &mut VecDeque<IndexingLine>,
) -> IndexingCodePtr {
@@ -1319,7 +1345,7 @@ impl Indexer for DynamicCodeIndices {
}
#[inline]
fn compute_index(_: bool, index: usize) -> usize {
fn compute_index(_: bool, index: usize, _: bool) -> usize {
index + 1
}
@@ -1332,7 +1358,9 @@ impl Indexer for DynamicCodeIndices {
for (key, code) in indices.into_iter() {
if code.len() > 1 {
index_locs.insert(key, IndexingCodePtr::Internal(prelude.len() + 1));
prelude.push_back(IndexingLine::DynamicIndexedChoice(code.into_iter().collect()));
prelude.push_back(IndexingLine::DynamicIndexedChoice(
code.into_iter().collect(),
));
} else {
code.front().map(|i| {
index_locs.insert(key, IndexingCodePtr::DynamicExternal(*i));
@@ -1344,7 +1372,9 @@ impl Indexer for DynamicCodeIndices {
}
fn switch_on<IndexKey: Eq + Hash>(
mut instr_fn: impl FnMut(IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>) -> IndexingInstruction,
mut instr_fn: impl FnMut(
IndexMap<IndexKey, IndexingCodePtr, FxBuildHasher>,
) -> IndexingInstruction,
index: &mut IndexMap<IndexKey, VecDeque<usize>, FxBuildHasher>,
prelude: &mut VecDeque<IndexingLine>,
) -> IndexingCodePtr {
@@ -1371,7 +1401,9 @@ impl Indexer for DynamicCodeIndices {
) -> IndexingCodePtr {
if lists.len() > 1 {
let lists = mem::replace(lists, VecDeque::new());
prelude.push_back(IndexingLine::DynamicIndexedChoice(lists.into_iter().collect()));
prelude.push_back(IndexingLine::DynamicIndexedChoice(
lists.into_iter().collect(),
));
IndexingCodePtr::Internal(1)
} else {
lists
@@ -1401,33 +1433,43 @@ impl Indexer for DynamicCodeIndices {
pub(crate) struct CodeOffsets<I: Indexer> {
indices: I,
optimal_index: usize,
non_counted_bt: bool,
}
impl<I: Indexer> CodeOffsets<I> {
pub(crate) fn new(indices: I, optimal_index: usize) -> Self {
pub(crate) fn new(indices: I, optimal_index: usize, non_counted_bt: bool) -> Self {
CodeOffsets {
indices,
optimal_index,
non_counted_bt,
}
}
fn index_list(&mut self, index: usize) {
let is_initial_index = self.indices.lists().is_empty();
let index = I::compute_index(is_initial_index, index);
let index = I::compute_index(is_initial_index, index, self.non_counted_bt);
self.indices.lists().push_back(index);
}
fn index_constant(
&mut self,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
constant: Literal,
index: usize,
) -> Vec<Literal> {
let overlapping_constants = constant_key_alternatives(constant, atom_tbl);
let code = self.indices.constants().entry(constant).or_insert(VecDeque::new());
let code = self
.indices
.constants()
.entry(constant)
.or_insert(VecDeque::new());
let is_initial_index = code.is_empty();
code.push_back(I::compute_index(is_initial_index, index));
code.push_back(I::compute_index(
is_initial_index,
index,
self.non_counted_bt,
));
for constant in &overlapping_constants {
let code = self
@@ -1437,7 +1479,7 @@ impl<I: Indexer> CodeOffsets<I> {
.or_insert(VecDeque::new());
let is_initial_index = code.is_empty();
let index = I::compute_index(is_initial_index, index);
let index = I::compute_index(is_initial_index, index, self.non_counted_bt);
code.push_back(index);
}
@@ -1455,7 +1497,11 @@ impl<I: Indexer> CodeOffsets<I> {
let code_len = code.len();
let is_initial_index = code.is_empty();
code.push_back(I::compute_index(is_initial_index, index));
code.push_back(I::compute_index(
is_initial_index,
index,
self.non_counted_bt,
));
code_len
}
@@ -1464,7 +1510,7 @@ impl<I: Indexer> CodeOffsets<I> {
optimal_arg: &Term,
index: usize,
clause_index_info: &mut ClauseIndexInfo,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) {
match optimal_arg {
&Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {

View File

@@ -62,9 +62,7 @@ impl<'a> TermIterState<'a> {
Term::PartialString(cell, string_buf, tail) => {
TermIterState::InitialPartialString(lvl, cell, string_buf, tail)
}
Term::CompleteString(cell, atom) => {
TermIterState::CompleteString(lvl, cell, *atom)
}
Term::CompleteString(cell, atom) => TermIterState::CompleteString(lvl, cell, *atom),
Term::Var(cell, var_ptr) => TermIterState::Var(lvl, cell, var_ptr.clone()),
}
}
@@ -77,7 +75,8 @@ pub(crate) struct QueryIterator<'a> {
impl<'a> QueryIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
self.state_stack
.push(TermIterState::subterm_to_state(lvl, term));
}
/*
@@ -94,19 +93,16 @@ impl<'a> QueryIterator<'a> {
fn from_term(term: &'a Term) -> Self {
let state = match term {
Term::AnonVar | Term::Cons(..) | Term::Literal(..) |
Term::PartialString(..) | Term::CompleteString(..) => {
Term::AnonVar
| Term::Cons(..)
| Term::Literal(..)
| Term::PartialString(..)
| Term::CompleteString(..) => {
return QueryIterator {
state_stack: vec![],
}
}
Term::Clause(r, name, terms) => TermIterState::Clause(
Level::Root,
0,
r,
*name,
terms,
),
Term::Clause(r, name, terms) => TermIterState::Clause(Level::Root, 0, r, *name, terms),
Term::Var(cell, var_ptr) => TermIterState::Var(Level::Root, cell, var_ptr.clone()),
};
@@ -118,18 +114,21 @@ impl<'a> QueryIterator<'a> {
fn extend_state(&mut self, lvl: Level, term: &'a QueryTerm) {
match term {
&QueryTerm::Clause(ref cell, ClauseType::CallN(_), ref terms, _) => {
self.state_stack.push(TermIterState::Clause(lvl, 1, cell, atom!("$call"), terms));
self.state_stack
.push(TermIterState::Clause(lvl, 1, cell, atom!("$call"), terms));
}
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
self.state_stack.push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms));
}
_ => {
self.state_stack
.push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms));
}
_ => {}
}
}
pub fn new(term: &'a QueryTerm) -> Self {
let mut iter = QueryIterator { state_stack: vec![] };
let mut iter = QueryIterator {
state_stack: vec![],
};
iter.extend_state(Level::Root, term);
iter
}
@@ -170,13 +169,15 @@ impl<'a> Iterator for QueryIterator<'a> {
}
}
TermIterState::InitialCons(lvl, cell, head, tail) => {
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
self.state_stack
.push(TermIterState::FinalCons(lvl, cell, head, tail));
self.push_subterm(lvl.child_level(), tail);
self.push_subterm(lvl.child_level(), head);
}
TermIterState::InitialPartialString(lvl, cell, string, tail) => {
self.state_stack.push(TermIterState::FinalPartialString(lvl, cell, string, tail));
self.state_stack
.push(TermIterState::FinalPartialString(lvl, cell, string, tail));
self.push_subterm(lvl.child_level(), tail);
}
TermIterState::FinalPartialString(lvl, cell, atom, tail) => {
@@ -248,11 +249,7 @@ impl<'a> FactIterator<'a> {
)]
}
Term::CompleteString(cell, atom) => {
vec![TermIterState::CompleteString(
Level::Root,
cell,
*atom,
)]
vec![TermIterState::CompleteString(Level::Root, cell, *atom)]
}
Term::Literal(cell, constant) => {
vec![TermIterState::Literal(Level::Root, cell, constant)]
@@ -319,7 +316,10 @@ pub(crate) fn post_order_iter<'a>(term: &'a Term) -> QueryIterator<'a> {
QueryIterator::from_term(term)
}
pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: RootIterationPolicy) -> FactIterator<'a> {
pub(crate) fn breadth_first_iter<'a>(
term: &'a Term,
iterable_root: RootIterationPolicy,
) -> FactIterator<'a> {
FactIterator::new(term, iterable_root)
}
@@ -356,18 +356,14 @@ fn state_from_chunked_terms<'a>(chunk_vec: &'a VecDeque<ChunkedTerms>) -> Clause
impl<'a> ClauseIterator<'a> {
pub fn new(clauses: &'a ChunkedTermVec) -> Self {
match state_from_chunked_terms(&clauses.chunk_vec) {
state @ ClauseIteratorState::RemainingBranches(..) => {
Self {
state_stack: vec![state],
remaining_chunks_on_stack: 0,
}
}
state @ ClauseIteratorState::RemainingChunks(..) => {
Self {
state_stack: vec![state],
remaining_chunks_on_stack: 1,
}
}
state @ ClauseIteratorState::RemainingBranches(..) => Self {
state_stack: vec![state],
remaining_chunks_on_stack: 0,
},
state @ ClauseIteratorState::RemainingChunks(..) => Self {
state_stack: vec![state],
remaining_chunks_on_stack: 1,
},
}
}
@@ -403,14 +399,16 @@ impl<'a> Iterator for ClauseIterator<'a> {
match state {
ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
if focus + 1 < chunks.len() {
self.state_stack.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
self.state_stack
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
} else {
self.remaining_chunks_on_stack -= 1;
}
match &chunks[focus] {
ChunkedTerms::Branch(branches) => {
self.state_stack.push(ClauseIteratorState::RemainingBranches(branches, 0));
self.state_stack
.push(ClauseIteratorState::RemainingBranches(branches, 0));
}
ChunkedTerms::Chunk(chunk) => {
return Some(ClauseItem::Chunk(chunk));
@@ -420,8 +418,11 @@ impl<'a> Iterator for ClauseIterator<'a> {
ClauseIteratorState::RemainingChunks(chunks, focus) => {
debug_assert_eq!(chunks.len(), focus);
}
ClauseIteratorState::RemainingBranches(branches, focus) if focus < branches.len() => {
self.state_stack.push(ClauseIteratorState::RemainingBranches(&branches, focus + 1));
ClauseIteratorState::RemainingBranches(branches, focus)
if focus < branches.len() =>
{
self.state_stack
.push(ClauseIteratorState::RemainingBranches(&branches, focus + 1));
let state = state_from_chunked_terms(&branches[focus]);
if let ClauseIteratorState::RemainingChunks(..) = &state {

View File

@@ -17,13 +17,13 @@ pub mod codegen;
mod debray_allocator;
#[cfg(feature = "ffi")]
mod ffi;
mod variable_records;
mod forms;
mod heap_iter;
pub mod heap_print;
#[cfg(feature = "http")]
mod http;
mod indexing;
mod variable_records;
#[macro_use]
pub mod instructions {
include!(concat!(env!("OUT_DIR"), "/instructions.rs"));
@@ -38,3 +38,19 @@ mod targets;
pub mod types;
use instructions::instr;
mod rcu;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn eval_code(s: &str) -> String {
use web_sys::console;
use machine::mock_wam::*;
let mut wam = Machine::with_test_streams();
let bytes = wam.test_load_string(s);
String::from_utf8_lossy(&bytes).to_string()
}

View File

@@ -143,6 +143,7 @@ call(_, _, _, _, _, _, _, _, _).
% enabled) and `error` which throws an exception when a cylic term is created. Read and write.
% * `unknown`: How undefined predicates are handled when called. Possible values are `error` (the default, an error is thrown),
% `fail` (the call silently fails) and `warn` (the call fails and a warning about the undefined predicate is printed).
% * `answer_write_options`: Additional write options used by the top level for writing answers.
%
current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 1023.
current_prolog_flag(max_arity, 1023).
@@ -160,6 +161,14 @@ current_prolog_flag(Flag, OccursCheckEnabled) :-
Flag == occurs_check,
!,
'$is_sto_enabled'(OccursCheckEnabled).
current_prolog_flag(occurs_check, OccursCheckEnabled) :-
'$is_sto_enabled'(OccursCheckEnabled).
current_prolog_flag(Flag, Value) :-
Flag == answer_write_options,
!,
answer_write_options(Value).
current_prolog_flag(answer_write_options, Value) :-
answer_write_options(Value).
current_prolog_flag(Flag, _) :-
atom(Flag),
throw(error(domain_error(prolog_flag, Flag), current_prolog_flag/2)). % 8.17.2.3 b
@@ -167,6 +176,11 @@ current_prolog_flag(Flag, _) :-
nonvar(Flag),
throw(error(type_error(atom, Flag), current_prolog_flag/2)). % 8.17.2.3 a
answer_write_options(Value) :-
( iso_ext:bb_get('$answer_write_options', Value) -> true
; Value = []
).
%% set_prolog_flag(Flag, Value).
%
% Sets the internal value of the flag. To see the list of flags supported by Scryer Prolog,
@@ -207,14 +221,25 @@ set_prolog_flag(occurs_check, false) :-
set_prolog_flag(occurs_check, error) :-
!, '$set_sto_with_error_as_unify'.
set_prolog_flag(double_quotes, Value) :-
throw(error(domain_error(flag_value, double_quotes + Value),
set_prolog_flag/2)). % 8.17.1.3 e
flag_domain_error(double_quotes, Value).
set_prolog_flag(answer_write_options, Options) :-
!,
catch(catch(builtins:parse_write_options(Options, _, set_prolog_flag/2),
error(domain_error(_,_), _),
throw(error(type_error(_,_), _))), % convert domain error to type error ....
error(type_error(_,_), _), % ... to catch type and domain errors.
flag_domain_error(answer_write_options, Options)),
iso_ext:bb_put('$answer_write_options', Options).
set_prolog_flag(Flag, _) :-
atom(Flag),
throw(error(domain_error(prolog_flag, Flag), set_prolog_flag/2)). % 8.17.1.3 d
set_prolog_flag(Flag, _) :-
throw(error(type_error(atom, Flag), set_prolog_flag/2)). % 8.17.1.3 c
flag_domain_error(Flag, Value) :-
% domain error via 8.17.1.3 e: Value is inappropriate for Flag
throw(error(domain_error(flag_value, Flag + Value), set_prolog_flag/2)).
% control operators.
%% fail.
@@ -262,6 +287,9 @@ repeat :- repeat.
%% ->(G1, G2)
%
% If-then and if-then-else constructs
:- non_counted_backtracking (->)/2.
G1 -> G2 :- control_entry_point((G1 -> G2)).
@@ -275,6 +303,9 @@ staggered_if_then(G1, G2) :-
%% ;(G1, G2)
%
% Disjunction (or)
:- non_counted_backtracking (;)/2.
G1 ; G2 :- control_entry_point((G1 ; G2)).
@@ -304,6 +335,9 @@ set_cp(B) :- '$set_cp'(B).
%% ,(G1, G2)
%
% Conjuction (and)
:- non_counted_backtracking (',')/2.
','(G1, G2) :- control_entry_point((G1, G2)).
@@ -788,7 +822,7 @@ catch(G,C,R) :-
catch(G,C,R,Bb) :-
'$install_new_block'(NBb),
'$call_with_inference_counting'(call(G)),
call(G),
end_block(Bb, NBb).
catch(G,C,R,Bb) :-
'$reset_block'(Bb),
@@ -2186,6 +2220,9 @@ set_stream_position(S_or_a, Position) :-
%% callable(X).
%
% True iff X is bound o an atom or a compund term.
:- non_counted_backtracking callable/1.
callable(X) :-
( nonvar(X), functor(X, F, _), atom(F) ->
true

View File

@@ -1,10 +1,29 @@
/* CLP(B): Constraint Logic Programming over Boolean Variables
Copyright (C): 2019-2023 Markus Triska
All rights reserved.
Author: Markus Triska
E-mail: triska@metalevel.at
WWW: http://www.metalevel.at
WWW: https://www.metalevel.at
Copyright (C): 2019-2023 Markus Triska
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
@@ -17,8 +36,8 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- module(clpb, [op(300, fy, ~),
op(500, yfx, #),
sat/1,
op(500, yfx, #),
sat/1,
taut/2,
labeling/1,
sat_count/2,
@@ -91,6 +110,46 @@ domain_error(Expectation, Term) :-
type_error(Expectation, Term) :-
type_error(Expectation, Term, unknown(Term)-1).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Compatibility predicates.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- meta_predicate(include(1, ?, ?)).
include(_, [], []).
include(Goal, [L|Ls0], Ls) :-
( call(Goal, L) ->
Ls = [L|Rest]
; Ls = Rest
),
include(Goal, Ls0, Rest).
:- meta_predicate(exclude(1, ?, ?)).
exclude(_, [], []).
exclude(Goal, [L|Ls0], Ls) :-
( call(Goal, L) ->
Ls = Rest
; Ls = [L|Rest]
),
exclude(Goal, Ls0, Rest).
:- meta_predicate(partition(2,?,?,?,?)).
partition(_, [], [], [], []).
partition(Pred, [H|T], L, E, G) :-
call(Pred, H, Diff),
partition_(Diff, H, Pred, T, L, E, G).
partition_(<, H, Pred, T, [H|Rest], E, G) :-
partition(Pred, T, Rest, E, G).
partition_(=, H, Pred, T, L, [H|Rest], G) :-
partition(Pred, T, L, Rest, G).
partition_(>, H, Pred, T, L, E, [H|Rest]) :-
partition(Pred, T, L, E, Rest).
:- meta_predicate(partition(1,?,?,?)).
partition(Pred, Ls0, As, Bs) :-
include(Pred, Ls0, As),
exclude(Pred, Ls0, Bs).
@@ -447,6 +506,10 @@ non_monotonic(X) :-
; true
).
:- meta_predicate(bdd_nodes(1, ?, ?)).
:- meta_predicate(bdd_nodes_(1, ?, ?, ?)).
:- meta_predicate(with_aux(1, ?)).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Rewriting to canonical expressions.
Atoms are converted to variables with a special attribute.
@@ -1513,8 +1576,7 @@ random_bindings(VNum, Node) -->
%
% ```
% ?- sat(A#B), weighted_maximum([1,2,1], [A,B,C], Maximum).
% A = 0, B = 1, C = 1, Maximum = 3
% ; false.
% A = 0, B = 1, C = 1, Maximum = 3.
% ```
weighted_maximum(Ws, Vars, Max) :-
@@ -1635,8 +1697,7 @@ attribute_goals(Var) -->
{ bdd_nodes(BDD, Nodes),
phrase(nodes(Nodes), Ns) },
[clpb:'$clpb_bdd'(Ns)]
; { prepare_global_variables(BDD),
phrase(sat_ands(Formula), Ands0),
; { phrase(sat_ands(Formula), Ands0),
ands_fusion(Ands0, Ands),
maplist(formula_anf, Ands, ANFs0),
sort(ANFs0, ANFs1),
@@ -1656,6 +1717,10 @@ attribute_goals(Var) -->
booleans(RestVs)
; boolean(Var) % the variable may have occurred only in taut/2
).
attribute_goals(Var) -->
{ get_atts(Var, clpb_max(_)),
!,
put_atts(Var, -clpb_max(_)) }.
attribute_goals(Var) -->
{ get_atts(Var, clpb_bdd(BDD)),
ground(BDD),
@@ -1663,36 +1728,13 @@ attribute_goals(Var) -->
del_clpb(Var) :-
del_attr(Var, clpb),
del_attr(Var, clpb_hash).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
To make residual projection work with recorded constraints, the
global counters must be adjusted so that new variables and nodes
also get new IDs. Also, clpb_next_id/2 is used to actually create
these counters, because creating them with b_setval/2 would make
them [] on backtracking, which is quite unfortunate in itself.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
del_attr(Var, clpb_hash),
del_attr(Var, clpb_atom).
b_setval(K, T) :- bb_b_put(K, T).
nb_setval(K, T) :- bb_put(K, T).
b_getval(K, T) :- bb_get(K, T).
prepare_global_variables(BDD) :-
clpb_next_id('$clpb_next_var', V0),
clpb_next_id('$clpb_next_node', N0),
bdd_nodes(BDD, Nodes),
foldl(max_variable_node, Nodes, V0-N0, MaxV0-MaxN0),
MaxV is MaxV0 + 1,
MaxN is MaxN0 + 1,
b_setval('$clpb_next_var', MaxV),
b_setval('$clpb_next_node', MaxN).
max_variable_node(Node, V0-N0, V-N) :-
node_id(Node, N1),
node_varindex(Node, V1),
N is max(N0,N1),
V is max(V0,V1).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Fuse formulas that share the same variables into single conjunctions.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -1817,7 +1859,8 @@ booleans([B|Bs]) --> boolean(B), booleans(Bs).
boolean(Var) -->
{ del_clpb(Var) },
( { get_attr(Var, clpb_omit_boolean, true) } -> []
( { get_attr(Var, clpb_omit_boolean, true) } ->
{ put_atts(Var, -clpb_omit_boolean(_)) }
; [clpb:sat(Var =:= Var)]
).
@@ -1919,49 +1962,3 @@ clpb_atom_var(Atom, Var) :-
put_assoc(Atom, A0, Var, A),
b_setval('$clpb_atoms', A)
).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Compatibility predicates.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
include(Goal, List, Is) :-
include_(List, Goal, Is).
include_([], _, []).
include_([X1|Xs1], P, Is) :-
( call(P, X1)
-> Is = [X1|Is1]
; Is = Is1
),
include_(Xs1, P, Is1).
exclude(Goal, List, Is) :-
exclude_(List, Goal, Is).
exclude_([], _, []).
exclude_([X1|Xs1], P, Is) :-
( call(P, X1)
-> Is = Is1
; Is = [X1|Is1]
),
exclude_(Xs1, P, Is1).
partition(Pred, List, Less, Equal, Greater) :-
partition_(List, Pred, Less, Equal, Greater).
partition_([], _, [], [], []).
partition_([H|T], Pred, L, E, G) :-
call(Pred, H, Diff),
partition_(Diff, H, Pred, T, L, E, G).
partition_(<, H, Pred, T, [H|Rest], E, G) :-
partition_(T, Pred, Rest, E, G).
partition_(=, H, Pred, T, L, [H|Rest], G) :-
partition_(T, Pred, L, Rest, G).
partition_(>, H, Pred, T, L, E, [H|Rest]) :-
partition_(T, Pred, L, E, Rest).

View File

@@ -2142,16 +2142,17 @@ fds_sespsize([V|Vs], S0, S) :-
fds_sespsize(Vs, S2, S).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Optimisation uses destructive assignment to save the computed
extremum over backtracking. Failure is used to get rid of copies of
attributed variables that are created in intermediate steps. At
least that's the intention - it currently doesn't work in SWI:
Optimisation uses the clause database to save the computed extremum
over backtracking. Failure is used to get rid of copies of
attributed variables that are created in intermediate steps.
%?- X in 0..3, call_residue_vars(labeling([min(X)], [X]), Vs).
%@ X = 0,
%@ Vs = [_G6174, _G6177],
%@ _G6174 in 0..3
Example:
?- X in 1..3, call_residue_vars(labeling([min(X)], [X]), Vs).
%@ X = 1, Vs = []
%@ ; X = 2, Vs = []
%@ ; X = 3, Vs = []
%@ ; false.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- dynamic(extremum/1).

View File

@@ -226,8 +226,9 @@ end_block(B, _Bb, NBb, L) :-
:- non_counted_backtracking handle_ile/3.
handle_ile(B, inference_limit_exceeded(B), inference_limit_exceeded) :-
handle_ile(B, inference_limit_exceeded(B), R) :-
!,
R = inference_limit_exceeded,
'$pop_ball_stack'.
handle_ile(B, _, _) :-
'$remove_call_policy_check'(B),
@@ -358,10 +359,10 @@ call_nth_nesting(C, ID) :-
bb_put(ID, 0),
bb_put(i_call_nth_counter, C).
%% countall(Goal, N).
%% countall(G_0, N).
%
% countall(Goal, N) counts all solutions of Goal and unifies N with
% this number of solutions. This predicate always succeeds once.
% countall(G_0, N) is true iff N unifies with the total number of
% answers of call(G_0).
:- meta_predicate(countall(0, ?)).
@@ -370,7 +371,7 @@ countall(Goal, N) :-
( integer(N) ->
( N < 0 ->
domain_error(not_less_than_zero, N, countall/2)
; N > 0
; true
)
; true
),

View File

@@ -35,9 +35,9 @@ write_error(Error) :-
),
write('.').
% '$print_message_and_fail'(inference_limit_exceeded(B)) :-
% integer(B),
% throw(inference_limit_exceeded(B)).
:- non_counted_backtracking '$print_message_and_fail'/1.
'$print_message_and_fail'(Error) :-
write_error(Error),
nl,
@@ -70,6 +70,8 @@ term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :-
).
:- non_counted_backtracking goal_expansion/3.
goal_expansion(Goal, Module, ExpandedGoal) :-
( atom(Module),
'$predicate_defined'(Module, goal_expansion, 2),
@@ -84,7 +86,6 @@ goal_expansion(Goal, Module, ExpandedGoal) :-
).
create_file_load_context(Stream, Path, Evacuable) :-
'$push_load_context'(Stream, Path),
'$push_load_state_payload'(Evacuable).
@@ -134,9 +135,15 @@ file_load_init(Stream, Evacuable) :-
run_initialization_goals.
file_load_cleanup(Evacuable, Error) :-
load_context(Module),
abolish(Module:'$initialization_goals'/1),
unload_evacuable(Evacuable),
'$print_message_and_fail'(Error),
throw(Error).
( clause('$toplevel':argv(_), _) ->
% let the toplevel call loader:write_error/1
throw(Error)
; '$print_message_and_fail'(Error)
; throw(file_load_error)
).
file_load(Stream, Path, Evacuable) :-
create_file_load_context(Stream, Path, Evacuable),
@@ -504,7 +511,9 @@ consult(Item) :-
use_module(Module) :-
'$push_load_state_payload'(Evacuable),
use_module(Module, [], Evacuable).
catch('$call'(loader:use_module(Module, [], Evacuable)),
file_load_error,
'$call'(builtins:false)).
use_module(Module, Exports) :-
'$push_load_state_payload'(Evacuable),
@@ -587,6 +596,8 @@ use_module(Module, Exports, Evacuable) :-
).
:- non_counted_backtracking check_predicate_property/5.
check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :-
'$meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm).
check_predicate_property(built_in, _, Name, Arity, built_in) :-
@@ -599,6 +610,7 @@ check_predicate_property(discontiguous, Module, Name, Arity, discontiguous) :-
'$discontiguous_property'(Module, Name, Arity).
:- non_counted_backtracking extract_predicate_property/2.
extract_predicate_property(Property, PropertyType) :-
( var(Property) ->
@@ -606,12 +618,16 @@ extract_predicate_property(Property, PropertyType) :-
; functor(Property, PropertyType, _)
).
:- non_counted_backtracking load_context/1.
load_context(Module) :-
( prolog_load_context(module, Module) ->
true
; Module = user
).
:- non_counted_backtracking predicate_property/2.
predicate_property(Callable, Property) :-
( var(Callable) ->
instantiation_error(predicate_property/2)
@@ -648,8 +664,6 @@ strip_subst_module(Goal, M1, M2, G) :-
; true
).
:- non_counted_backtracking subgoal_expansion/3.
/*
* subgoal_expansion differs from goal_expansion only in that it fails
* unconditionally after catching an(y) exception, aborting the
@@ -657,10 +671,14 @@ strip_subst_module(Goal, M1, M2, G) :-
* when expand_goal is later invoked at runtime.
*/
:- non_counted_backtracking subgoal_expansion_fail/1.
subgoal_expansion_fail(B) :-
builtins:set_cp(B),
fail.
:- non_counted_backtracking subgoal_expansion/3.
subgoal_expansion(Goal, Module, ExpandedGoal) :-
'$get_cp'(B),
( atom(Module),
@@ -890,7 +908,6 @@ thread_goals(Goals0, Goals1, Hole, Functor) :-
% n_call_clause(N, Clauses) :-
% length(Args, N),
% Head =.. [call, G | Args],
% CallNHead =.. [call, '$call'(G) | Args],
% N1 is N + 1,
% StripModule =.. ['$strip_module', G, M1, G1],
% FastCall =.. ['$fast_call', G | Args],
@@ -903,7 +920,7 @@ thread_goals(Goals0, Goals1, Hole, Functor) :-
% PrepareCallClause,
% expand_call_goal(G2, M1, G3),
% strip_subst_module(G3, M1, M2, G4),
% '$call_with_inference_counting'(ModuleCall))].
% ModuleCall)].
%
% generate_call_forms :-
% between(1, 64, N),
@@ -930,7 +947,7 @@ call(G0) :-
'$strip_module'(G0, M0, G1),
expand_call_goal(G1, M0, G2),
strip_subst_module(G2, M0, M1, G3),
'$call_with_inference_counting'('$module_call'(M1, G3)).
'$module_call'(M1, G3).
:-non_counted_backtracking call/2.
call(A,B) :-
@@ -943,7 +960,7 @@ call(A,B) :-
'$prepare_call_clause'(E,D,B),
expand_call_goal(E,C,F),
strip_subst_module(F,C,G,H),
'$call_with_inference_counting'('$module_call'(G,H)).
'$module_call'(G,H).
:-non_counted_backtracking call/3.
call(A,B,C) :-
@@ -956,7 +973,7 @@ call(A,B,C) :-
'$prepare_call_clause'(F,E,B,C),
expand_call_goal(F,D,G),
strip_subst_module(G,D,H,I),
'$call_with_inference_counting'('$module_call'(H,I)).
'$module_call'(H,I).
:-non_counted_backtracking call/4.
call(A,B,C,D) :-
@@ -969,7 +986,7 @@ call(A,B,C,D) :-
'$prepare_call_clause'(G,F,B,C,D),
expand_call_goal(G,E,H),
strip_subst_module(H,E,I,J),
'$call_with_inference_counting'('$module_call'(I,J)).
'$module_call'(I,J).
:-non_counted_backtracking call/5.
call(A,B,C,D,E) :-
@@ -982,7 +999,7 @@ call(A,B,C,D,E) :-
'$prepare_call_clause'(H,G,B,C,D,E),
expand_call_goal(H,F,I),
strip_subst_module(I,F,J,K),
'$call_with_inference_counting'('$module_call'(J,K)).
'$module_call'(J,K).
:-non_counted_backtracking call/6.
call(A,B,C,D,E,F) :-
@@ -995,7 +1012,7 @@ call(A,B,C,D,E,F) :-
'$prepare_call_clause'(I,H,B,C,D,E,F),
expand_call_goal(I,G,J),
strip_subst_module(J,G,K,L),
'$call_with_inference_counting'('$module_call'(K,L)).
'$module_call'(K,L).
:-non_counted_backtracking call/7.
call(A,B,C,D,E,F,G) :-
@@ -1008,7 +1025,7 @@ call(A,B,C,D,E,F,G) :-
'$prepare_call_clause'(J,I,B,C,D,E,F,G),
expand_call_goal(J,H,K),
strip_subst_module(K,H,L,M),
'$call_with_inference_counting'('$module_call'(L,M)).
'$module_call'(L,M).
:-non_counted_backtracking call/8.
call(A,B,C,D,E,F,G,H) :-
@@ -1021,7 +1038,7 @@ call(A,B,C,D,E,F,G,H) :-
'$prepare_call_clause'(K,J,B,C,D,E,F,G,H),
expand_call_goal(K,I,L),
strip_subst_module(L,I,M,N),
'$call_with_inference_counting'('$module_call'(M,N)).
'$module_call'(M,N).
:-non_counted_backtracking call/9.
call(A,B,C,D,E,F,G,H,I) :-
@@ -1034,7 +1051,7 @@ call(A,B,C,D,E,F,G,H,I) :-
'$prepare_call_clause'(L,K,B,C,D,E,F,G,H,I),
expand_call_goal(L,J,M),
strip_subst_module(M,J,N,O),
'$call_with_inference_counting'('$module_call'(N,O)).
'$module_call'(N,O).
:-non_counted_backtracking call/10.
call(A,B,C,D,E,F,G,H,I,J) :-
@@ -1047,7 +1064,7 @@ call(A,B,C,D,E,F,G,H,I,J) :-
'$prepare_call_clause'(M,L,B,C,D,E,F,G,H,I,J),
expand_call_goal(M,K,N),
strip_subst_module(N,K,O,P),
'$call_with_inference_counting'('$module_call'(O,P)).
'$module_call'(O,P).
:-non_counted_backtracking call/11.
call(A,B,C,D,E,F,G,H,I,J,K) :-
@@ -1060,7 +1077,7 @@ call(A,B,C,D,E,F,G,H,I,J,K) :-
'$prepare_call_clause'(N,M,B,C,D,E,F,G,H,I,J,K),
expand_call_goal(N,L,O),
strip_subst_module(O,L,P,Q),
'$call_with_inference_counting'('$module_call'(P,Q)).
'$module_call'(P,Q).
:-non_counted_backtracking call/12.
call(A,B,C,D,E,F,G,H,I,J,K,L) :-
@@ -1073,7 +1090,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L) :-
'$prepare_call_clause'(O,N,B,C,D,E,F,G,H,I,J,K,L),
expand_call_goal(O,M,P),
strip_subst_module(P,M,Q,R),
'$call_with_inference_counting'('$module_call'(Q,R)).
'$module_call'(Q,R).
:-non_counted_backtracking call/13.
call(A,B,C,D,E,F,G,H,I,J,K,L,M) :-
@@ -1086,7 +1103,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M) :-
'$prepare_call_clause'(P,O,B,C,D,E,F,G,H,I,J,K,L,M),
expand_call_goal(P,N,Q),
strip_subst_module(Q,N,R,S),
'$call_with_inference_counting'('$module_call'(R,S)).
'$module_call'(R,S).
:-non_counted_backtracking call/14.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N) :-
@@ -1099,7 +1116,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N) :-
'$prepare_call_clause'(Q,P,B,C,D,E,F,G,H,I,J,K,L,M,N),
expand_call_goal(Q,O,R),
strip_subst_module(R,O,S,T),
'$call_with_inference_counting'('$module_call'(S,T)).
'$module_call'(S,T).
:-non_counted_backtracking call/15.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) :-
@@ -1112,7 +1129,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) :-
'$prepare_call_clause'(R,Q,B,C,D,E,F,G,H,I,J,K,L,M,N,O),
expand_call_goal(R,P,S),
strip_subst_module(S,P,T,U),
'$call_with_inference_counting'('$module_call'(T,U)).
'$module_call'(T,U).
:-non_counted_backtracking call/16.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :-
@@ -1125,7 +1142,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :-
'$prepare_call_clause'(S,R,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P),
expand_call_goal(S,Q,T),
strip_subst_module(T,Q,U,V),
'$call_with_inference_counting'('$module_call'(U,V)).
'$module_call'(U,V).
:-non_counted_backtracking call/17.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :-
@@ -1138,7 +1155,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :-
'$prepare_call_clause'(T,S,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q),
expand_call_goal(T,R,U),
strip_subst_module(U,R,V,W),
'$call_with_inference_counting'('$module_call'(V,W)).
'$module_call'(V,W).
:-non_counted_backtracking call/18.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :-
@@ -1151,7 +1168,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :-
'$prepare_call_clause'(U,T,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R),
expand_call_goal(U,S,V),
strip_subst_module(V,S,W,X),
'$call_with_inference_counting'('$module_call'(W,X)).
'$module_call'(W,X).
:-non_counted_backtracking call/19.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :-
@@ -1164,7 +1181,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :-
'$prepare_call_clause'(V,U,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S),
expand_call_goal(V,T,W),
strip_subst_module(W,T,X,Y),
'$call_with_inference_counting'('$module_call'(X,Y)).
'$module_call'(X,Y).
:-non_counted_backtracking call/20.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :-
@@ -1177,7 +1194,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :-
'$prepare_call_clause'(W,V,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T),
expand_call_goal(W,U,X),
strip_subst_module(X,U,Y,Z),
'$call_with_inference_counting'('$module_call'(Y,Z)).
'$module_call'(Y,Z).
:-non_counted_backtracking call/21.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :-
@@ -1190,7 +1207,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :-
'$prepare_call_clause'(X,W,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U),
expand_call_goal(X,V,Y),
strip_subst_module(Y,V,Z,A1),
'$call_with_inference_counting'('$module_call'(Z,A1)).
'$module_call'(Z,A1).
:-non_counted_backtracking call/22.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :-
@@ -1203,7 +1220,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :-
'$prepare_call_clause'(Y,X,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V),
expand_call_goal(Y,W,Z),
strip_subst_module(Z,W,A1,B1),
'$call_with_inference_counting'('$module_call'(A1,B1)).
'$module_call'(A1,B1).
:-non_counted_backtracking call/23.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :-
@@ -1216,7 +1233,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :-
'$prepare_call_clause'(Z,Y,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W),
expand_call_goal(Z,X,A1),
strip_subst_module(A1,X,B1,C1),
'$call_with_inference_counting'('$module_call'(B1,C1)).
'$module_call'(B1,C1).
:-non_counted_backtracking call/24.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :-
@@ -1229,7 +1246,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :-
'$prepare_call_clause'(A1,Z,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X),
expand_call_goal(A1,Y,B1),
strip_subst_module(B1,Y,C1,D1),
'$call_with_inference_counting'('$module_call'(C1,D1)).
'$module_call'(C1,D1).
:-non_counted_backtracking call/25.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :-
@@ -1242,7 +1259,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :-
'$prepare_call_clause'(B1,A1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y),
expand_call_goal(B1,Z,C1),
strip_subst_module(C1,Z,D1,E1),
'$call_with_inference_counting'('$module_call'(D1,E1)).
'$module_call'(D1,E1).
:-non_counted_backtracking call/26.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :-
@@ -1255,7 +1272,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :-
'$prepare_call_clause'(C1,B1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z),
expand_call_goal(C1,A1,D1),
strip_subst_module(D1,A1,E1,F1),
'$call_with_inference_counting'('$module_call'(E1,F1)).
'$module_call'(E1,F1).
:-non_counted_backtracking call/27.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :-
@@ -1268,7 +1285,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :-
'$prepare_call_clause'(D1,C1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1),
expand_call_goal(D1,B1,E1),
strip_subst_module(E1,B1,F1,G1),
'$call_with_inference_counting'('$module_call'(F1,G1)).
'$module_call'(F1,G1).
:-non_counted_backtracking call/28.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :-
@@ -1281,7 +1298,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :-
'$prepare_call_clause'(E1,D1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1),
expand_call_goal(E1,C1,F1),
strip_subst_module(F1,C1,G1,H1),
'$call_with_inference_counting'('$module_call'(G1,H1)).
'$module_call'(G1,H1).
:-non_counted_backtracking call/29.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :-
@@ -1294,7 +1311,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :-
'$prepare_call_clause'(F1,E1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1),
expand_call_goal(F1,D1,G1),
strip_subst_module(G1,D1,H1,I1),
'$call_with_inference_counting'('$module_call'(H1,I1)).
'$module_call'(H1,I1).
:-non_counted_backtracking call/30.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :-
@@ -1307,7 +1324,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :-
'$prepare_call_clause'(G1,F1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1),
expand_call_goal(G1,E1,H1),
strip_subst_module(H1,E1,I1,J1),
'$call_with_inference_counting'('$module_call'(I1,J1)).
'$module_call'(I1,J1).
:-non_counted_backtracking call/31.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :-
@@ -1320,7 +1337,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :-
'$prepare_call_clause'(H1,G1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1),
expand_call_goal(H1,F1,I1),
strip_subst_module(I1,F1,J1,K1),
'$call_with_inference_counting'('$module_call'(J1,K1)).
'$module_call'(J1,K1).
:-non_counted_backtracking call/32.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :-
@@ -1333,7 +1350,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :-
'$prepare_call_clause'(I1,H1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1),
expand_call_goal(I1,G1,J1),
strip_subst_module(J1,G1,K1,L1),
'$call_with_inference_counting'('$module_call'(K1,L1)).
'$module_call'(K1,L1).
:-non_counted_backtracking call/33.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :-
@@ -1346,7 +1363,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :
'$prepare_call_clause'(J1,I1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1),
expand_call_goal(J1,H1,K1),
strip_subst_module(K1,H1,L1,M1),
'$call_with_inference_counting'('$module_call'(L1,M1)).
'$module_call'(L1,M1).
:-non_counted_backtracking call/34.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1) :-
@@ -1359,7 +1376,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(K1,J1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1),
expand_call_goal(K1,I1,L1),
strip_subst_module(L1,I1,M1,N1),
'$call_with_inference_counting'('$module_call'(M1,N1)).
'$module_call'(M1,N1).
:-non_counted_backtracking call/35.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1) :-
@@ -1372,7 +1389,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(L1,K1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1),
expand_call_goal(L1,J1,M1),
strip_subst_module(M1,J1,N1,O1),
'$call_with_inference_counting'('$module_call'(N1,O1)).
'$module_call'(N1,O1).
:-non_counted_backtracking call/36.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1) :-
@@ -1385,7 +1402,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(M1,L1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1),
expand_call_goal(M1,K1,N1),
strip_subst_module(N1,K1,O1,P1),
'$call_with_inference_counting'('$module_call'(O1,P1)).
'$module_call'(O1,P1).
:-non_counted_backtracking call/37.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1) :-
@@ -1398,7 +1415,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(N1,M1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1),
expand_call_goal(N1,L1,O1),
strip_subst_module(O1,L1,P1,Q1),
'$call_with_inference_counting'('$module_call'(P1,Q1)).
'$module_call'(P1,Q1).
:-non_counted_backtracking call/38.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1) :-
@@ -1411,7 +1428,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(O1,N1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1),
expand_call_goal(O1,M1,P1),
strip_subst_module(P1,M1,Q1,R1),
'$call_with_inference_counting'('$module_call'(Q1,R1)).
'$module_call'(Q1,R1).
:-non_counted_backtracking call/39.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1) :-
@@ -1424,7 +1441,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(P1,O1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1),
expand_call_goal(P1,N1,Q1),
strip_subst_module(Q1,N1,R1,S1),
'$call_with_inference_counting'('$module_call'(R1,S1)).
'$module_call'(R1,S1).
:-non_counted_backtracking call/40.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1) :-
@@ -1437,7 +1454,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(Q1,P1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1),
expand_call_goal(Q1,O1,R1),
strip_subst_module(R1,O1,S1,T1),
'$call_with_inference_counting'('$module_call'(S1,T1)).
'$module_call'(S1,T1).
:-non_counted_backtracking call/41.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1) :-
@@ -1450,7 +1467,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(R1,Q1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1),
expand_call_goal(R1,P1,S1),
strip_subst_module(S1,P1,T1,U1),
'$call_with_inference_counting'('$module_call'(T1,U1)).
'$module_call'(T1,U1).
:-non_counted_backtracking call/42.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1) :-
@@ -1463,7 +1480,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(S1,R1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1),
expand_call_goal(S1,Q1,T1),
strip_subst_module(T1,Q1,U1,V1),
'$call_with_inference_counting'('$module_call'(U1,V1)).
'$module_call'(U1,V1).
:-non_counted_backtracking call/43.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1) :-
@@ -1476,7 +1493,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(T1,S1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1),
expand_call_goal(T1,R1,U1),
strip_subst_module(U1,R1,V1,W1),
'$call_with_inference_counting'('$module_call'(V1,W1)).
'$module_call'(V1,W1).
:-non_counted_backtracking call/44.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1) :-
@@ -1489,7 +1506,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(U1,T1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1),
expand_call_goal(U1,S1,V1),
strip_subst_module(V1,S1,W1,X1),
'$call_with_inference_counting'('$module_call'(W1,X1)).
'$module_call'(W1,X1).
:-non_counted_backtracking call/45.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1) :-
@@ -1502,7 +1519,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(V1,U1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1),
expand_call_goal(V1,T1,W1),
strip_subst_module(W1,T1,X1,Y1),
'$call_with_inference_counting'('$module_call'(X1,Y1)).
'$module_call'(X1,Y1).
:-non_counted_backtracking call/46.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1) :-
@@ -1515,7 +1532,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(W1,V1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1),
expand_call_goal(W1,U1,X1),
strip_subst_module(X1,U1,Y1,Z1),
'$call_with_inference_counting'('$module_call'(Y1,Z1)).
'$module_call'(Y1,Z1).
:-non_counted_backtracking call/47.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1) :-
@@ -1528,7 +1545,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(X1,W1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1),
expand_call_goal(X1,V1,Y1),
strip_subst_module(Y1,V1,Z1,A2),
'$call_with_inference_counting'('$module_call'(Z1,A2)).
'$module_call'(Z1,A2).
:-non_counted_backtracking call/48.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1) :-
@@ -1541,7 +1558,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(Y1,X1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1),
expand_call_goal(Y1,W1,Z1),
strip_subst_module(Z1,W1,A2,B2),
'$call_with_inference_counting'('$module_call'(A2,B2)).
'$module_call'(A2,B2).
:-non_counted_backtracking call/49.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1) :-
@@ -1554,7 +1571,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(Z1,Y1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1),
expand_call_goal(Z1,X1,A2),
strip_subst_module(A2,X1,B2,C2),
'$call_with_inference_counting'('$module_call'(B2,C2)).
'$module_call'(B2,C2).
:-non_counted_backtracking call/50.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1) :-
@@ -1567,7 +1584,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(A2,Z1,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1),
expand_call_goal(A2,Y1,B2),
strip_subst_module(B2,Y1,C2,D2),
'$call_with_inference_counting'('$module_call'(C2,D2)).
'$module_call'(C2,D2).
:-non_counted_backtracking call/51.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1) :-
@@ -1580,7 +1597,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(B2,A2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1),
expand_call_goal(B2,Z1,C2),
strip_subst_module(C2,Z1,D2,E2),
'$call_with_inference_counting'('$module_call'(D2,E2)).
'$module_call'(D2,E2).
:-non_counted_backtracking call/52.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1) :-
@@ -1593,7 +1610,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(C2,B2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1),
expand_call_goal(C2,A2,D2),
strip_subst_module(D2,A2,E2,F2),
'$call_with_inference_counting'('$module_call'(E2,F2)).
'$module_call'(E2,F2).
:-non_counted_backtracking call/53.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2) :-
@@ -1606,7 +1623,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(D2,C2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2),
expand_call_goal(D2,B2,E2),
strip_subst_module(E2,B2,F2,G2),
'$call_with_inference_counting'('$module_call'(F2,G2)).
'$module_call'(F2,G2).
:-non_counted_backtracking call/54.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2) :-
@@ -1619,7 +1636,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(E2,D2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2),
expand_call_goal(E2,C2,F2),
strip_subst_module(F2,C2,G2,H2),
'$call_with_inference_counting'('$module_call'(G2,H2)).
'$module_call'(G2,H2).
:-non_counted_backtracking call/55.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2) :-
@@ -1632,7 +1649,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(F2,E2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2),
expand_call_goal(F2,D2,G2),
strip_subst_module(G2,D2,H2,I2),
'$call_with_inference_counting'('$module_call'(H2,I2)).
'$module_call'(H2,I2).
:-non_counted_backtracking call/56.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2) :-
@@ -1645,7 +1662,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(G2,F2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2),
expand_call_goal(G2,E2,H2),
strip_subst_module(H2,E2,I2,J2),
'$call_with_inference_counting'('$module_call'(I2,J2)).
'$module_call'(I2,J2).
:-non_counted_backtracking call/57.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2) :-
@@ -1658,7 +1675,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(H2,G2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2),
expand_call_goal(H2,F2,I2),
strip_subst_module(I2,F2,J2,K2),
'$call_with_inference_counting'('$module_call'(J2,K2)).
'$module_call'(J2,K2).
:-non_counted_backtracking call/58.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2) :-
@@ -1671,7 +1688,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(I2,H2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2),
expand_call_goal(I2,G2,J2),
strip_subst_module(J2,G2,K2,L2),
'$call_with_inference_counting'('$module_call'(K2,L2)).
'$module_call'(K2,L2).
:-non_counted_backtracking call/59.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2) :-
@@ -1684,7 +1701,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(J2,I2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2),
expand_call_goal(J2,H2,K2),
strip_subst_module(K2,H2,L2,M2),
'$call_with_inference_counting'('$module_call'(L2,M2)).
'$module_call'(L2,M2).
:-non_counted_backtracking call/60.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2) :-
@@ -1697,7 +1714,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(K2,J2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2),
expand_call_goal(K2,I2,L2),
strip_subst_module(L2,I2,M2,N2),
'$call_with_inference_counting'('$module_call'(M2,N2)).
'$module_call'(M2,N2).
:-non_counted_backtracking call/61.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2) :-
@@ -1710,7 +1727,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(L2,K2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2),
expand_call_goal(L2,J2,M2),
strip_subst_module(M2,J2,N2,O2),
'$call_with_inference_counting'('$module_call'(N2,O2)).
'$module_call'(N2,O2).
:-non_counted_backtracking call/62.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2) :-
@@ -1723,7 +1740,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(M2,L2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2),
expand_call_goal(M2,K2,N2),
strip_subst_module(N2,K2,O2,P2),
'$call_with_inference_counting'('$module_call'(O2,P2)).
'$module_call'(O2,P2).
:-non_counted_backtracking call/63.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2) :-
@@ -1736,7 +1753,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(N2,M2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2),
expand_call_goal(N2,L2,O2),
strip_subst_module(O2,L2,P2,Q2),
'$call_with_inference_counting'('$module_call'(P2,Q2)).
'$module_call'(P2,Q2).
:-non_counted_backtracking call/64.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2) :-
@@ -1749,7 +1766,7 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(O2,N2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2),
expand_call_goal(O2,M2,P2),
strip_subst_module(P2,M2,Q2,R2),
'$call_with_inference_counting'('$module_call'(Q2,R2)).
'$module_call'(Q2,R2).
:-non_counted_backtracking call/65.
call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :-
@@ -1762,4 +1779,4 @@ call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1
'$prepare_call_clause'(P2,O2,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2),
expand_call_goal(P2,N2,Q2),
strip_subst_module(Q2,N2,R2,S2),
'$call_with_inference_counting'('$module_call'(R2,S2)).
'$module_call'(R2,S2).

View File

@@ -52,9 +52,7 @@ macro_rules! drop_iter_on_err {
};
}
fn zero_divisor_eval_error(
stub_gen: impl Fn() -> FunctorStub + 'static,
) -> MachineStubGen {
fn zero_divisor_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen {
Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor);
let stub = stub_gen();
@@ -63,9 +61,7 @@ fn zero_divisor_eval_error(
})
}
fn undefined_eval_error(
stub_gen: impl Fn() -> FunctorStub + 'static,
) -> MachineStubGen {
fn undefined_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen {
Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::Undefined);
let stub = stub_gen();
@@ -171,9 +167,7 @@ pub(crate) fn add(lhs: Number, rhs: Number, arena: &mut Arena) -> Result<Number,
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
}
(Number::Integer(n1), Number::Rational(n2))
| (Number::Rational(n2), Number::Integer(n1)) => {
Ok(Number::arena_from(&*n1 + &*n2, arena))
}
| (Number::Rational(n2), Number::Integer(n1)) => Ok(Number::arena_from(&*n1 + &*n2, arena)),
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
@@ -181,9 +175,7 @@ pub(crate) fn add(lhs: Number, rhs: Number, arena: &mut Arena) -> Result<Number,
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
Ok(Number::Float(add_f(f1, f2)?))
}
(Number::Rational(r1), Number::Rational(r2)) => {
Ok(Number::arena_from(&*r1 + &*r2, arena))
}
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::arena_from(&*r1 + &*r2, arena)),
}
}
@@ -199,12 +191,12 @@ pub(crate) fn neg(n: Number, arena: &mut Arena) -> Number {
Number::Integer(n) => {
let n_clone: Integer = (*n).clone();
Number::arena_from(-Integer::from(n_clone), arena)
},
}
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
Number::Rational(r) => {
let r_clone: Rational = (*r).clone();
Number::arena_from(-Rational::from(r_clone), arena)
},
}
}
}
@@ -221,12 +213,12 @@ pub(crate) fn abs(n: Number, arena: &mut Arena) -> Number {
Number::Integer(n) => {
let n_clone: Integer = (*n).clone();
Number::arena_from(Integer::from(n_clone.abs()), arena)
},
}
Number::Float(f) => Number::Float(f.abs()),
Number::Rational(r) => {
let r_clone: Rational = (*r).clone();
Number::arena_from(Rational::from(r_clone.abs()), arena)
},
}
}
}
@@ -370,7 +362,11 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
(Number::Integer(n1), Number::Fixnum(n2)) => {
let n2_i = n2.get_num();
if !(&*n1 == &Integer::from(1) || &*n1 == &Integer::from(0) || &*n1 == &Integer::from(-1)) && n2_i < 0 {
if !(&*n1 == &Integer::from(1)
|| &*n1 == &Integer::from(0)
|| &*n1 == &Integer::from(-1))
&& n2_i < 0
{
let n = Number::Integer(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else {
@@ -379,7 +375,11 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
}
}
(Number::Integer(n1), Number::Integer(n2)) => {
if !(&*n1 == &Integer::from(1) || &*n1 == &Integer::from(0) || &*n1 == &Integer::from(-1)) && &*n2 < &Integer::from(0) {
if !(&*n1 == &Integer::from(1)
|| &*n1 == &Integer::from(0)
|| &*n1 == &Integer::from(-1))
&& &*n2 < &Integer::from(0)
{
let n = Number::Integer(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else {
@@ -554,7 +554,7 @@ pub fn rational_from_number(
Number::Integer(n) => {
let n_clone: Integer = (*n).clone();
Ok(arena_alloc!(Rational::from(n_clone), arena))
},
}
}
}
@@ -661,7 +661,7 @@ pub(crate) fn shr(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
if let Ok(n2) = usize::try_from(n2_i) {
return Ok(Number::arena_from(n1 >> n2, arena));
} else {
} else {
return Ok(Number::arena_from(n1 >> usize::max_value(), arena));
}
}
@@ -681,9 +681,10 @@ pub(crate) fn shr(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
}
(Number::Integer(n1), Number::Fixnum(n2)) => match usize::try_from(n2.get_num()) {
Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 >> n2), arena)),
_ => {
Ok(Number::arena_from(Integer::from(&*n1 >> usize::max_value()),arena))
},
_ => Ok(Number::arena_from(
Integer::from(&*n1 >> usize::max_value()),
arena,
)),
},
(Number::Integer(n1), Number::Integer(n2)) => {
let result: Result<usize, _> = (&*n2).try_into();
@@ -722,7 +723,7 @@ pub(crate) fn shl(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
if let Ok(n2) = usize::try_from(n2_i) {
return Ok(Number::arena_from(n1 << n2, arena));
} else {
} else {
return Ok(Number::arena_from(n1 << usize::max_value(), arena));
}
}
@@ -741,9 +742,10 @@ pub(crate) fn shl(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
}
(Number::Integer(n1), Number::Fixnum(n2)) => match usize::try_from(n2.get_num()) {
Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 << n2), arena)),
_ => {
Ok(Number::arena_from(Integer::from(&*n1 << usize::max_value()),arena))
}
_ => Ok(Number::arena_from(
Integer::from(&*n1 << usize::max_value()),
arena,
)),
},
(Number::Integer(n1), Number::Integer(n2)) => match (&*n2).try_into() as Result<u32, _> {
Ok(n2) => {
@@ -967,10 +969,7 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
Ok(Number::arena_from(result, arena))
} else {
let value: IBig = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into();
Ok(Number::arena_from(
value,
arena,
))
Ok(Number::arena_from(value, arena))
}
}
(Number::Fixnum(n1), Number::Integer(n2)) | (Number::Integer(n2), Number::Fixnum(n1)) => {
@@ -1069,12 +1068,14 @@ pub(crate) fn atanh(n1: Number) -> Result<f64, MachineStubGen> {
let f1 = try_numeric_result!(result_f(&n1), stub_gen)?;
try_numeric_result!(if f1 == 1.0 || f1 == -1.0 {
Err(EvalError::Undefined)
} else {
result_f(&Number::Float(OrderedFloat(f1.atanh())))
},
stub_gen)
try_numeric_result!(
if f1 == 1.0 || f1 == -1.0 {
Err(EvalError::Undefined)
} else {
result_f(&Number::Float(OrderedFloat(f1.atanh())))
},
stub_gen
)
}
#[inline]
@@ -1126,7 +1127,6 @@ pub(crate) fn floor(n1: Number, arena: &mut Arena) -> Number {
rnd_i(&n1, arena)
}
#[inline]
pub(crate) fn ceiling(n1: Number, arena: &mut Arena) -> Number {
let n1 = neg(n1, arena);
@@ -1179,16 +1179,17 @@ impl MachineState {
pub fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
match at {
&ArithmeticTerm::Reg(r) => {
let value = self.store(self.deref(self[r]));
let value = self.store(self.deref(self[r]));
match Number::try_from(value) {
Ok(n) => Ok(n),
Err(_) => self.arith_eval_by_metacall(value),
}
}
&ArithmeticTerm::Interm(i) => {
Ok(mem::replace(&mut self.interms[i - 1], Number::Fixnum(Fixnum::build_with(0))))
}
&ArithmeticTerm::Interm(i) => Ok(mem::replace(
&mut self.interms[i - 1],
Number::Fixnum(Fixnum::build_with(0)),
)),
&ArithmeticTerm::Number(n) => Ok(n),
}
}
@@ -1202,11 +1203,14 @@ impl MachineState {
match rational_from_number(n, caller, &mut self.arena) {
Ok(r) => Ok(r),
Err(e_gen) => Err(e_gen(self))
Err(e_gen) => Err(e_gen(self)),
}
}
pub(crate) fn arith_eval_by_metacall(&mut self, value: HeapCellValue) -> Result<Number, MachineStub> {
pub(crate) fn arith_eval_by_metacall(
&mut self,
value: HeapCellValue,
) -> Result<Number, MachineStub> {
let stub_gen = || functor_stub(atom!("is"), 2);
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value);
@@ -1512,26 +1516,11 @@ mod tests {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
op_dir.insert(
(atom!("+"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("-"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("-"), Fixity::Pre),
OpDesc::build_with(200, FY as u8),
);
op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert(
(atom!("/"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("-"), Fixity::Pre), OpDesc::build_with(200, FY as u8));
op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
let term_write_result =
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();

View File

@@ -118,12 +118,9 @@ impl MachineState {
and_frame[i] = self.registers[i];
}
and_frame[arity + 1] =
fixnum_as_cell!(Fixnum::build_with(self.b0 as i64));
and_frame[arity + 2] =
fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[arity + 3] =
fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
and_frame[arity + 1] = fixnum_as_cell!(Fixnum::build_with(self.b0 as i64));
and_frame[arity + 2] = fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[arity + 3] = fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
self.verify_attributes();

View File

@@ -8,7 +8,9 @@ fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> b
&Instruction::TryMeElse(offset) if offset > 0 => {
stack.push(index + offset);
}
&Instruction::DefaultRetryMeElse(offset) | &Instruction::RetryMeElse(offset) if offset > 0 => {
&Instruction::DefaultRetryMeElse(offset) | &Instruction::RetryMeElse(offset)
if offset > 0 =>
{
stack.push(index + offset);
}
&Instruction::DynamicElse(_, _, NextOrFail::Next(offset)) if offset > 0 => {

View File

@@ -28,17 +28,15 @@ pub(super) fn bootstrapping_compile(
) -> Result<(), SessionError> {
let (wam_prelude, machine_st) = wam.prelude_view_and_machine_st();
let term_stream = BootstrappingTermStream::from_char_reader(
stream,
machine_st,
listing_src,
);
let term_stream = BootstrappingTermStream::from_char_reader(stream, machine_st, listing_src);
let payload = BootstrappingLoadState(
LoadStatePayload::new(wam_prelude.code.len(), term_stream)
);
let payload =
BootstrappingLoadState(LoadStatePayload::new(wam_prelude.code.len(), term_stream));
let loader: Loader<'_, BootstrappingLoadState> = Loader { payload, wam_prelude };
let loader: Loader<'_, BootstrappingLoadState> = Loader {
payload,
wam_prelude,
};
loader.load()?;
Ok(())
@@ -98,8 +96,8 @@ fn derelictize_try_me_else(
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o));
Some(mem::replace(o, 0))
}
Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => None,
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));
@@ -154,8 +152,8 @@ fn merge_indices(
fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize {
loop {
match &code[index] {
Instruction::DynamicElse(_, _, NextOrFail::Next(i)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(i))
Instruction::DynamicElse(_, _, NextOrFail::Next(i))
| Instruction::DynamicInternalElse(_, _, NextOrFail::Next(i))
if *i > 0 =>
{
index += i;
@@ -170,42 +168,37 @@ 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] {
Instruction::TryMeElse(o) |
Instruction::RetryMeElse(o) => {
Instruction::TryMeElse(o) | Instruction::RetryMeElse(o) => {
if *o > 0 {
return index;
} else {
index = index_loc;
}
}
&Instruction::DynamicElse(_, _, next_or_fail) => {
match next_or_fail {
NextOrFail::Next(i) => {
if i == 0 {
index = index_loc;
} else {
return index;
}
}
NextOrFail::Fail(_) => {
&Instruction::DynamicElse(_, _, next_or_fail) => match next_or_fail {
NextOrFail::Next(i) => {
if i == 0 {
index = index_loc;
}
}
}
&Instruction::DynamicInternalElse(_, _, next_or_fail) => {
match next_or_fail {
NextOrFail::Next(i) => {
if i == 0 {
index = index_loc;
} else {
return index;
}
}
NextOrFail::Fail(_) => {
} else {
return index;
}
}
}
NextOrFail::Fail(_) => {
index = index_loc;
}
},
&Instruction::DynamicInternalElse(_, _, next_or_fail) => match next_or_fail {
NextOrFail::Next(i) => {
if i == 0 {
index = index_loc;
} else {
return index;
}
}
NextOrFail::Fail(_) => {
return index;
}
},
Instruction::TrustMe(_) => {
return index;
}
@@ -215,11 +208,7 @@ fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> u
index += v;
}
IndexingCodePtr::DynamicExternal(v) => match &code[index + v] {
&Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(0),
) => {
&Instruction::DynamicInternalElse(_, _, NextOrFail::Next(0)) => {
return index + v;
}
_ => {
@@ -309,8 +298,7 @@ fn merge_indexed_subsequences(
code[inner_try_me_else_loc] = Instruction::TrustMe(o);
}
_ => {
code[inner_try_me_else_loc] =
Instruction::RetryMeElse(o);
code[inner_try_me_else_loc] = Instruction::RetryMeElse(o);
}
},
}
@@ -376,7 +364,9 @@ fn delete_from_skeleton(
}
if skeleton.core.is_dynamic {
skeleton.core.add_retracted_dynamic_clause_info(clause_index_info);
skeleton
.core
.add_retracted_dynamic_clause_info(clause_index_info);
retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause(
compilation_target,
@@ -409,8 +399,8 @@ fn blunt_leading_choice_instr(
code[instr_loc] = Instruction::TryMeElse(*o);
return instr_loc;
}
Instruction::DynamicElse(_, _, NextOrFail::Next(_)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(_)) => {
Instruction::DynamicElse(_, _, NextOrFail::Next(_))
| Instruction::DynamicInternalElse(_, _, NextOrFail::Next(_)) => {
return instr_loc;
}
&mut Instruction::DynamicElse(b, d, NextOrFail::Fail(o)) => {
@@ -422,26 +412,19 @@ fn blunt_leading_choice_instr(
code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(0));
return instr_loc;
}
&mut Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Fail(o),
) => {
&mut Instruction::DynamicInternalElse(b, d, NextOrFail::Fail(o)) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Fail(o),
));
code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Next(0),
);
code[instr_loc] = Instruction::DynamicInternalElse(b, d, NextOrFail::Next(0));
return instr_loc;
}
Instruction::TrustMe(o) => {
retraction_info.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
retraction_info
.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
code[instr_loc] = Instruction::TryMeElse(0);
return instr_loc + 1;
@@ -481,9 +464,9 @@ fn set_switch_var_offset_to_choice_instr(
};
match &code[index_loc + v] {
Instruction::TryMeElse(_) |
Instruction::DynamicElse(..) |
Instruction::DynamicInternalElse(..) => {}
Instruction::TryMeElse(_)
| Instruction::DynamicElse(..)
| Instruction::DynamicInternalElse(..) => {}
_ => {
set_switch_var_offset(code, index_loc, offset, retraction_info);
}
@@ -523,9 +506,8 @@ fn internalize_choice_instr_at(
retraction_info: &mut RetractionInfo,
) {
match &mut code[instr_loc] {
Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => {
}
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);
@@ -554,18 +536,10 @@ fn internalize_choice_instr_at(
match &mut code[instr_loc + o] {
Instruction::RevJmpBy(p) if *p == 0 => {
code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Fail(o),
);
code[instr_loc] = Instruction::DynamicInternalElse(b, d, NextOrFail::Fail(o));
}
_ => {
code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Next(o),
);
code[instr_loc] = Instruction::DynamicInternalElse(b, d, NextOrFail::Next(o));
}
}
}
@@ -609,23 +583,20 @@ fn thread_choice_instr_at_to(
*o = target_loc - instr_loc;
return;
}
Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)) |
Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
) if target_loc >= instr_loc => {
Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))
| Instruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))
if target_loc >= instr_loc =>
{
retraction_info
.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, *o));
*o = target_loc - instr_loc;
return;
}
Instruction::DynamicElse(_, _, NextOrFail::Next(o)) |
Instruction::DynamicInternalElse(_, _, NextOrFail::Next(o)) => {
Instruction::DynamicElse(_, _, NextOrFail::Next(o))
| Instruction::DynamicInternalElse(_, _, NextOrFail::Next(o)) => {
instr_loc += *o;
}
Instruction::TryMeElse(o)
| Instruction::RetryMeElse(o) => {
Instruction::TryMeElse(o) | Instruction::RetryMeElse(o) => {
instr_loc += *o;
}
Instruction::RevJmpBy(ref mut o) if instr_loc >= target_loc => {
@@ -642,7 +613,8 @@ fn thread_choice_instr_at_to(
{
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
code[instr_loc] = instr!("dynamic_else",
code[instr_loc] = instr!(
"dynamic_else",
birth,
death,
NextOrFail::Next(target_loc - instr_loc)
@@ -653,14 +625,13 @@ fn thread_choice_instr_at_to(
Instruction::DynamicElse(_, _, NextOrFail::Fail(o)) if *o > 0 => {
instr_loc += *o;
}
&mut Instruction::DynamicInternalElse(
birth,
death,
ref mut fail,
) if target_loc >= instr_loc => {
&mut Instruction::DynamicInternalElse(birth, death, ref mut fail)
if target_loc >= instr_loc =>
{
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
code[instr_loc] = instr!("dynamic_internal_else",
code[instr_loc] = instr!(
"dynamic_internal_else",
birth,
death,
NextOrFail::Next(target_loc - instr_loc)
@@ -668,9 +639,7 @@ fn thread_choice_instr_at_to(
return;
}
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(o))
if *o > 0 =>
{
Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(o)) if *o > 0 => {
instr_loc += *o;
}
Instruction::TrustMe(ref mut o) if target_loc >= instr_loc => {
@@ -711,33 +680,31 @@ fn remove_non_leading_clause(
None
}
Instruction::TrustMe(_) => {
match &mut code[preceding_choice_instr_loc] {
Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(
preceding_choice_instr_loc,
*o,
));
Instruction::TrustMe(_) => match &mut code[preceding_choice_instr_loc] {
Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(
preceding_choice_instr_loc,
*o,
));
code[preceding_choice_instr_loc] = Instruction::TrustMe(0);
code[preceding_choice_instr_loc] = Instruction::TrustMe(0);
None
}
Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
preceding_choice_instr_loc,
*o,
));
*o = 0;
Some(IndexPtr::index(preceding_choice_instr_loc + 1))
}
_ => {
unreachable!();
}
None
}
}
Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
preceding_choice_instr_loc,
*o,
));
*o = 0;
Some(IndexPtr::index(preceding_choice_instr_loc + 1))
}
_ => {
unreachable!();
}
},
_ => {
unreachable!();
}
@@ -988,11 +955,7 @@ fn prepend_compiled_clause(
Instruction::TryMeElse(ref mut o) if *o == 0 => {
*o = prepend_queue_len - 2;
}
Instruction::DynamicInternalElse(
_,
_,
ref mut o @ NextOrFail::Next(0),
) => {
Instruction::DynamicInternalElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
*o = NextOrFail::Fail(prepend_queue_len - 2);
}
_ => {
@@ -1258,7 +1221,11 @@ fn print_overwrite_warning(
_ => {}
}
println!("Warning: overwriting {}/{} because the clauses are discontiguous", key.0.as_str(), key.1);
println!(
"Warning: overwriting {}/{} because the clauses are discontiguous",
key.0.as_str(),
key.1
);
}
impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
@@ -1270,8 +1237,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if let Some(path_str) = load_context.path.to_str() {
if !path_str.is_empty() {
return Some(LS::machine_st(&mut self.payload).atom_tbl.build_with(
path_str
return Some(AtomTable::build_with(
&LS::machine_st(&mut self.payload).atom_tbl,
path_str,
));
}
}
@@ -1290,10 +1258,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let clause = self.try_term_to_tl(term, &mut preprocessor)?;
// let queue = preprocessor.parse_queue(self)?;
let mut cg = CodeGenerator::new(
&mut LS::machine_st(&mut self.payload).atom_tbl,
settings,
);
let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
let clause_code = cg.compile_predicate(vec![clause])?;
@@ -1323,10 +1288,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
}
let mut cg = CodeGenerator::new(
&mut LS::machine_st(&mut self.payload).atom_tbl,
settings,
);
let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
let mut code = cg.compile_predicate(clauses)?;
@@ -1361,26 +1323,23 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.clause_clause_locs
.extend(&clause_clause_locs.make_contiguous()[0..]);
self.payload.retraction_info
.push_record(RetractionRecord::SkeletonClauseTruncateBack(
self.payload.retraction_info.push_record(
RetractionRecord::SkeletonClauseTruncateBack(
predicates.compilation_target,
key,
skeleton_clause_len,
));
),
);
}
None => {
cg.skeleton
.core
.clause_clause_locs
.extend(&clause_clause_locs.make_contiguous()[0..]);
.core
.clause_clause_locs
.extend(&clause_clause_locs.make_contiguous()[0..]);
let skeleton = cg.skeleton;
self.add_extensible_predicate(
key,
skeleton,
predicates.compilation_target,
);
self.add_extensible_predicate(key, skeleton, predicates.compilation_target);
}
};
@@ -1450,11 +1409,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new();
skeleton.clause_clause_locs = clause_clause_locs;
self.add_local_extensible_predicate(
*compilation_target,
*key,
skeleton,
);
self.add_local_extensible_predicate(*compilation_target, *key, skeleton);
}
}
}
@@ -1490,11 +1445,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new();
skeleton.clause_clause_locs.push_front(code_len);
self.add_local_extensible_predicate(
*compilation_target,
*key,
skeleton,
);
self.add_local_extensible_predicate(*compilation_target, *key, skeleton);
}
}
}
@@ -1530,11 +1481,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new();
skeleton.clause_clause_locs.push_back(code_len);
self.add_local_extensible_predicate(
*compilation_target,
*key,
skeleton,
);
self.add_local_extensible_predicate(*compilation_target, *key, skeleton);
}
}
}
@@ -1606,7 +1553,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
skeleton.core.clause_clause_locs.push_back(code_len);
self.payload.retraction_info
self.payload
.retraction_info
.push_record(RetractionRecord::SkeletonClausePopBack(
compilation_target,
key,
@@ -1624,8 +1572,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.push_back_to_local_predicate_skeleton(&compilation_target, &key, code_len);
let code_index =
self.get_or_insert_code_index(key, compilation_target);
let code_index = self.get_or_insert_code_index(key, compilation_target);
if let Some(new_code_ptr) = result {
set_code_index(
@@ -1646,7 +1593,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
skeleton.core.clause_clause_locs.push_front(code_len);
skeleton.core.clause_assert_margin += 1;
self.payload.retraction_info
self.payload
.retraction_info
.push_record(RetractionRecord::SkeletonClausePopFront(
compilation_target,
key,
@@ -1666,8 +1614,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.push_front_to_local_predicate_skeleton(&compilation_target, &key, code_len);
let code_index =
self.get_or_insert_code_index(key, compilation_target);
let code_index = self.get_or_insert_code_index(key, compilation_target);
set_code_index(
&mut self.payload.retraction_info,
@@ -1698,19 +1645,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.opt_arg_index_key
.switch_on_term_loc()
{
Some(index_loc) => {
find_inner_choice_instr(
&self.wam_prelude.code,
skeleton.clauses[target_pos].clause_start,
index_loc,
)
}
Some(index_loc) => find_inner_choice_instr(
&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[clause_loc] {
Instruction::DynamicElse(_, ref mut d, _) |
Instruction::DynamicInternalElse(_, ref mut d, _) => {
Instruction::DynamicElse(_, ref mut d, _)
| Instruction::DynamicInternalElse(_, ref mut d, _) => {
*d = Death::Finite(LS::machine_st(&mut self.payload).global_clock);
}
_ => unreachable!(),
@@ -1797,11 +1742,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
skeleton.clauses[target_pos + 1].clause_start =
skeleton.clauses[target_pos].clause_start;
let update_code_index = target_pos == 0 &&
skeleton.clauses[target_pos + 1]
.opt_arg_index_key
.switch_on_term_loc()
.is_none();
let update_code_index = target_pos == 0
&& skeleton.clauses[target_pos + 1]
.opt_arg_index_key
.switch_on_term_loc()
.is_none();
let index_ptr_opt = if update_code_index {
Some(IndexPtr::index(clause_loc))
@@ -1964,7 +1909,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
index_loc,
);
let lower_bound_clause_start = skeleton.clauses[lower_bound].clause_start;
let lower_bound_clause_start =
skeleton.clauses[lower_bound].clause_start;
let preceding_choice_instr_loc;
match &mut code[clause_start] {
@@ -2093,13 +2039,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
clause_clauses: ClauseIter,
append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> {
let clause_predicates = clause_clauses.map(|(head, body)| {
Term::Clause(
Cell::default(),
atom!("$clause"),
vec![head, body],
)
});
let clause_predicates = clause_clauses
.map(|(head, body)| Term::Clause(Cell::default(), atom!("$clause"), vec![head, body]));
let clause_clause_compilation_target = match compilation_target {
CompilationTarget::User => CompilationTarget::Module(atom!("builtins")),
@@ -2132,21 +2073,21 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.cloned()
.collect()
}
Some(skeleton) => {
skeleton.core.clause_clause_locs.make_contiguous()[0..num_clause_predicates]
.iter()
.cloned()
.collect()
}
Some(skeleton) => skeleton.core.clause_clause_locs.make_contiguous()
[0..num_clause_predicates]
.iter()
.cloned()
.collect(),
None => {
unreachable!()
}
};
match self.wam_prelude.indices.get_predicate_skeleton_mut(
&clause_clause_compilation_target,
&(atom!("$clause"), 2),
) {
match self
.wam_prelude
.indices
.get_predicate_skeleton_mut(&clause_clause_compilation_target, &(atom!("$clause"), 2))
{
Some(skeleton) if append_or_prepend.is_append() => {
for _ in 0..num_clause_predicates {
skeleton.core.clause_clause_locs.pop_back();
@@ -2270,25 +2211,25 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
println!(
"Warning: overwriting multifile predicate {}:{}/{} because \
it was not locally declared multifile.",
self.payload.predicates.compilation_target, key.0.as_str(), key.1
self.payload.predicates.compilation_target,
key.0.as_str(),
key.1
);
}
if let Some(skeleton) = self
.wam_prelude
.indices
.remove_predicate_skeleton(&self.payload.predicates.compilation_target, &key)
{
if let Some(skeleton) = self.wam_prelude.indices.remove_predicate_skeleton(
&self.payload.predicates.compilation_target,
&key,
) {
let compilation_target = self.payload.predicates.compilation_target;
if predicate_info.is_dynamic {
let clause_clause_compilation_target =
match compilation_target {
CompilationTarget::User => {
CompilationTarget::Module(atom!("builtins"))
}
module => module,
};
let clause_clause_compilation_target = match compilation_target {
CompilationTarget::User => {
CompilationTarget::Module(atom!("builtins"))
}
module => module,
};
self.retract_local_clauses_by_locs(
clause_clause_compilation_target,
@@ -2301,11 +2242,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
self.payload.retraction_info.push_record(
RetractionRecord::RemovedSkeleton(
compilation_target,
key,
skeleton,
),
RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton),
);
}
}
@@ -2328,9 +2265,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
match self.wam_prelude.indices.modules.get_mut(&filename) {
Some(ref mut module) => {
let index_ptr = code_index.get();
let code_index = module.code_dir.entry(key)
.or_insert(code_index)
.clone();
let code_index = module.code_dir.entry(key).or_insert(code_index).clone();
set_code_index(
&mut self.payload.retraction_info,
@@ -2349,8 +2284,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
LS::machine_st(&mut self.payload).global_clock += 1;
let clause_clauses_len = self.payload.clause_clauses.len();
let clauses_vec: Vec<_> = self.payload
.clause_clauses.drain(0..std::cmp::min(predicates_len, clause_clauses_len))
let clauses_vec: Vec<_> = self
.payload
.clause_clauses
.drain(0..std::cmp::min(predicates_len, clause_clauses_len))
.collect();
let compilation_target = self.payload.predicates.compilation_target;
@@ -2374,10 +2311,7 @@ impl Machine {
module_name: HeapCellValue,
key: PredicateKey,
) -> CodeIndex {
let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new(
self,
InlineTermStream {},
);
let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new(self, InlineTermStream {});
let module_name = if module_name.get_tag() == HeapCellValueTag::Atom {
cell_as_atom!(module_name)
@@ -2394,10 +2328,8 @@ impl Machine {
vars: &[Term],
) -> Result<(), SessionError> {
let mut compile = || {
let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new(
self,
InlineTermStream {},
);
let mut loader: Loader<'_, InlineLoadState<'_>> =
Loader::new(self, InlineTermStream {});
let term = loader.read_term_from_heap(term_loc)?;
let clause = build_rule_body(vars, term);

View File

@@ -91,12 +91,16 @@ impl<T: CopierTarget> CopyTermState<T> {
self.target.push(hcv);
}
let cdr = self.target.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
let cdr = self
.target
.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
if !cdr.is_var() {
self.trail_list_cell(addr + 1, threshold);
} else {
let car = self.target.store(self.target.deref(heap_loc_as_cell!(addr)));
let car = self
.target
.store(self.target.deref(heap_loc_as_cell!(addr)));
if !car.is_var() {
self.trail_list_cell(addr, threshold);
@@ -188,10 +192,10 @@ impl<T: CopierTarget> CopyTermState<T> {
while let HeapCellValueTag::Lis = list_addr.get_tag() {
let threshold = self.target.threshold();
let heap_loc = list_addr.get_value() as usize;
let str_loc = self.target[heap_loc].get_value() as usize;
let str_loc = self.target[heap_loc].get_value() as usize;
self.target.push(heap_loc_as_cell!(threshold+2));
self.target.push(heap_loc_as_cell!(threshold+1));
self.target.push(heap_loc_as_cell!(threshold + 2));
self.target.push(heap_loc_as_cell!(threshold + 1));
read_heap_cell!(self.target[str_loc],
(HeapCellValueTag::Atom) => {
@@ -377,8 +381,9 @@ mod tests {
let a_atom = atom!("a");
let b_atom = atom!("b");
wam.machine_st.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
wam.machine_st
.heap
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -401,20 +406,26 @@ mod tests {
wam.machine_st.heap.clear();
let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &mut wam.machine_st.atom_tbl);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &mut wam.machine_st.atom_tbl);
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{
let wam = TermCopyingMockWAM { wam: &mut wam };
@@ -428,14 +439,20 @@ mod tests {
assert_eq!(wam.machine_st.heap[2], pstr_second_cell);
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(4));
assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
assert_eq!(wam.machine_st.heap[5], fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(
wam.machine_st.heap[5],
fixnum_as_cell!(Fixnum::build_with(0i64))
);
assert_eq!(wam.machine_st.heap[7], pstr_cell);
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(9));
assert_eq!(wam.machine_st.heap[9], pstr_second_cell);
assert_eq!(wam.machine_st.heap[10], pstr_loc_as_cell!(11));
assert_eq!(wam.machine_st.heap[11], pstr_offset_as_cell!(7));
assert_eq!(wam.machine_st.heap[12], fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(
wam.machine_st.heap[12],
fixnum_as_cell!(Fixnum::build_with(0i64))
);
wam.machine_st.heap.clear();

View File

@@ -74,7 +74,7 @@ impl BranchNumber {
fn halve_delta(&self) -> BranchNumber {
BranchNumber {
branch_num: self.branch_num.clone(),
delta : &self.delta / Rational::from(2),
delta: &self.delta / Rational::from(2),
}
}
}
@@ -108,7 +108,10 @@ pub struct BranchInfo {
impl BranchInfo {
fn new(branch_num: BranchNumber) -> Self {
Self { branch_num, chunks: vec![] }
Self {
branch_num,
chunks: vec![],
}
}
}
@@ -149,11 +152,11 @@ enum TraversalState {
// where it leaves off.
BuildFinalDisjunct(usize),
Fail,
GetCutPoint{ var_num: usize, prev_b: bool },
GetCutPoint { var_num: usize, prev_b: bool },
Cut { var_num: usize, is_global: bool },
ResetCallPolicy(CallPolicy),
Term(Term),
RemoveBranchNum, // pop the current_branch_num and from the root set.
RemoveBranchNum, // pop the current_branch_num and from the root set.
AddBranchNum(BranchNumber), // set current_branch_num, add it to the root set
RepBranchNum(BranchNumber), // replace current_branch_num and the latest in the root set
}
@@ -179,22 +182,22 @@ pub struct VarData {
impl VarData {
fn emit_initial_get_level(&mut self, build_stack: &mut ChunkedTermVec) {
let global_cut_var_num =
if let &Some(global_cut_var_num) = &self.global_cut_var_num {
match &self.records[global_cut_var_num].allocation {
VarAlloc::Perm(..) => Some(global_cut_var_num),
VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => {
Some(global_cut_var_num)
}
_ => None
let global_cut_var_num = if let &Some(global_cut_var_num) = &self.global_cut_var_num {
match &self.records[global_cut_var_num].allocation {
VarAlloc::Perm(..) => Some(global_cut_var_num),
VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => {
Some(global_cut_var_num)
}
} else {
None
};
_ => None,
}
} else {
None
};
if let Some(global_cut_var_num) = global_cut_var_num {
let term = QueryTerm::GetLevel(global_cut_var_num);
self.records[global_cut_var_num].allocation = VarAlloc::Perm(0, PermVarAllocation::Pending);
self.records[global_cut_var_num].allocation =
VarAlloc::Perm(0, PermVarAllocation::Pending);
match build_stack.front_mut() {
Some(ChunkedTerms::Branch(_)) => {
@@ -229,7 +232,7 @@ fn merge_branch_seq(branches: impl Iterator<Item = BranchInfo>) -> BranchInfo {
}
fn flatten_into_disjunct(build_stack: &mut ChunkedTermVec, preceding_len: usize) {
let branch_vec = build_stack.drain(preceding_len + 1 ..).collect();
let branch_vec = build_stack.drain(preceding_len + 1..).collect();
if let ChunkedTerms::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] {
disjuncts.push(branch_vec);
@@ -254,11 +257,14 @@ impl VariableClassifier {
pub fn classify_fact(mut self, term: Term) -> Result<ClassifyFactResult, CompilationError> {
self.classify_head_variables(&term)?;
Ok((term, self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
self.current_chunk_num,
)))
Ok((
term,
self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
self.current_chunk_num,
),
))
}
pub fn classify_rule<'a, LS: LoadState<'a>>(
@@ -298,7 +304,7 @@ impl VariableClassifier {
}
}
let iter = old_branches.drain(old_branches_len - 1 ..);
let iter = old_branches.drain(old_branches_len - 1..);
branches.push(merge_branch_seq(iter));
}
@@ -346,9 +352,13 @@ impl VariableClassifier {
}
fn probe_body_var(&mut self, var_info: VarInfo) {
let term_loc = self.current_chunk_type.to_gen_context(self.current_chunk_num);
let term_loc = self
.current_chunk_type
.to_gen_context(self.current_chunk_num);
let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone())
let branch_info_v = self
.branch_map
.entry(var_info.var_ptr.clone())
.or_insert_with(|| vec![]);
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
@@ -396,12 +406,14 @@ impl VariableClassifier {
fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> {
match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => {
}
Term::Clause(..) | Term::Literal(_, Literal::Atom(_)) => {}
_ => return Err(CompilationError::InvalidRuleHead),
}
let mut classify_info = ClassifyInfo { arg_c: 1, arity: term.arity() };
let mut classify_info = ClassifyInfo {
arg_c: 1,
arity: term.arity(),
};
match term {
Term::Clause(_, _, terms) => {
@@ -414,13 +426,16 @@ impl VariableClassifier {
// the body of the if let here is an inlined
// "probe_head_var". note the difference between it
// and "probe_body_var".
let branch_info_v = self.branch_map.entry(var_ptr.clone())
let branch_info_v = self
.branch_map
.entry(var_ptr.clone())
.or_insert_with(|| vec![]);
let needs_new_branch = branch_info_v.is_empty();
if needs_new_branch {
branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
branch_info_v
.push(BranchInfo::new(self.current_branch_num.clone()));
}
let branch_info = branch_info_v.last_mut().unwrap();
@@ -509,13 +524,11 @@ impl VariableClassifier {
self.probe_in_situ_var(var_num);
build_stack.push_chunk_term(
if is_global {
QueryTerm::GlobalCut(var_num)
} else {
QueryTerm::LocalCut(var_num)
}
);
build_stack.push_chunk_term(if is_global {
QueryTerm::GlobalCut(var_num)
} else {
QueryTerm::LocalCut(var_num)
});
}
TraversalState::Fail => {
build_stack.push_chunk_term(QueryTerm::Fail);
@@ -539,22 +552,28 @@ impl VariableClassifier {
classifier.probe_body_term(arg_c + 1, terms.len(), term);
}
build_stack.push_chunk_term(
clause_to_query_term(
loader,
name,
terms,
classifier.call_policy,
),
);
build_stack.push_chunk_term(clause_to_query_term(
loader,
name,
terms,
classifier.call_policy,
));
};
match term {
Term::Clause(_, name @ (atom!("->") | atom!(";") | atom!(",")), mut terms) if terms.len() == 3 => {
Term::Clause(
_,
name @ (atom!("->") | atom!(";") | atom!(",")),
mut terms,
) if terms.len() == 3 => {
if let Some(last_arg) = terms.last() {
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
terms.pop();
state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), name, terms)));
state_stack.push(TraversalState::Term(Term::Clause(
Cell::default(),
name,
terms,
)));
} else {
add_chunk(self, name, terms);
}
@@ -583,7 +602,7 @@ impl VariableClassifier {
let mut branch_numbers = vec![first_branch_num];
for idx in 1 .. branches.len() {
for idx in 1..branches.len() {
let succ_branch_number = branch_numbers[idx - 1].incr_by_delta();
branch_numbers.push(if idx + 1 < branches.len() {
@@ -610,8 +629,11 @@ impl VariableClassifier {
state_stack.push(TraversalState::AddBranchNum(branch_num));
}
if let TraversalState::BuildDisjunct(build_stack_len) = state_stack[final_disjunct_loc] {
state_stack[final_disjunct_loc] = TraversalState::BuildFinalDisjunct(build_stack_len);
if let TraversalState::BuildDisjunct(build_stack_len) =
state_stack[final_disjunct_loc]
{
state_stack[final_disjunct_loc] =
TraversalState::BuildFinalDisjunct(build_stack_len);
}
self.current_chunk_type = ChunkType::Mid;
@@ -621,18 +643,30 @@ impl VariableClassifier {
let then_term = terms.pop().unwrap();
let if_term = terms.pop().unwrap();
let prev_b = if matches!(state_stack.last(), Some(TraversalState::RemoveBranchNum)) {
let prev_b = if matches!(
state_stack.last(),
Some(TraversalState::RemoveBranchNum)
) {
// check if the second-to-last element is a regular BuildDisjunct, as we don't
// want to add GetPrevLevel in case of a TrustMe.
matches!(state_stack.iter().rev().nth(1), Some(TraversalState::BuildDisjunct(..)))
matches!(
state_stack.iter().rev().nth(1),
Some(TraversalState::BuildDisjunct(..))
)
} else {
false
};
state_stack.push(TraversalState::Term(then_term));
state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false });
state_stack.push(TraversalState::Cut {
var_num: self.var_num,
is_global: false,
});
state_stack.push(TraversalState::Term(if_term));
state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b });
state_stack.push(TraversalState::GetCutPoint {
var_num: self.var_num,
prev_b,
});
self.var_num += 1;
}
@@ -643,12 +677,22 @@ impl VariableClassifier {
build_stack.reserve_branch(2);
state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len));
state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), atom!("$succeed"), vec![])));
state_stack.push(TraversalState::Term(Term::Clause(
Cell::default(),
atom!("$succeed"),
vec![],
)));
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
state_stack.push(TraversalState::Fail);
state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false });
state_stack.push(TraversalState::Cut {
var_num: self.var_num,
is_global: false,
});
state_stack.push(TraversalState::Term(not_term));
state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b: true });
state_stack.push(TraversalState::GetCutPoint {
var_num: self.var_num,
prev_b: true,
});
self.current_chunk_type = ChunkType::Mid;
self.current_chunk_num += 1;
@@ -668,15 +712,13 @@ impl VariableClassifier {
build_stack.add_chunk();
}
build_stack.push_chunk_term(
qualified_clause_to_query_term(
loader,
module_name,
predicate_name,
vec![],
self.call_policy,
),
);
build_stack.push_chunk_term(qualified_clause_to_query_term(
loader,
module_name,
predicate_name,
vec![],
self.call_policy,
));
}
(
Term::Literal(_, Literal::Atom(module_name)),
@@ -690,15 +732,13 @@ impl VariableClassifier {
self.probe_body_term(arg_c + 1, terms.len(), term);
}
build_stack.push_chunk_term(
qualified_clause_to_query_term(
loader,
module_name,
name,
terms,
self.call_policy,
),
);
build_stack.push_chunk_term(qualified_clause_to_query_term(
loader,
module_name,
name,
terms,
self.call_policy,
));
}
(module_name, predicate_name) => {
if update_chunk_data(self, atom!("call"), 2) {
@@ -711,18 +751,18 @@ impl VariableClassifier {
terms.push(module_name);
terms.push(predicate_name);
build_stack.push_chunk_term(
clause_to_query_term(
loader,
atom!("call"),
vec![Term::Clause(Cell::default(), atom!(":"), terms)],
self.call_policy,
),
);
build_stack.push_chunk_term(clause_to_query_term(
loader,
atom!("call"),
vec![Term::Clause(Cell::default(), atom!(":"), terms)],
self.call_policy,
));
}
}
}
Term::Clause(_, atom!("$call_with_inference_counting"), mut terms) if terms.len() == 1 => {
Term::Clause(_, atom!("$call_with_inference_counting"), mut terms)
if terms.len() == 1 =>
{
state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
state_stack.push(TraversalState::Term(terms.pop().unwrap()));
@@ -738,14 +778,12 @@ impl VariableClassifier {
self.probe_body_term(1, 1, &var);
build_stack.push_chunk_term(
clause_to_query_term(
loader,
atom!("call"),
vec![var],
self.call_policy,
),
);
build_stack.push_chunk_term(clause_to_query_term(
loader,
atom!("call"),
vec![var],
self.call_policy,
));
}
Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => {
if self.global_cut_var_num.is_none() {
@@ -765,14 +803,12 @@ impl VariableClassifier {
build_stack.add_chunk();
}
build_stack.push_chunk_term(
clause_to_query_term(
loader,
name,
vec![],
self.call_policy,
),
);
build_stack.push_chunk_term(clause_to_query_term(
loader,
name,
vec![],
self.call_policy,
));
}
_ => {
return Err(CompilationError::InadmissibleQueryTerm);
@@ -800,12 +836,11 @@ impl BranchMap {
};
for (var, branches) in self.iter_mut() {
let (mut var_num, var_num_incr) =
if let Var::InSitu(var_num) = *var.borrow() {
(var_num, false)
} else {
(var_data.records.len(), true)
};
let (mut var_num, var_num_incr) = if let Var::InSitu(var_num) = *var.borrow() {
(var_num, false)
} else {
(var_data.records.len(), true)
};
for branch in branches.iter_mut() {
if var_num_incr {
@@ -813,7 +848,8 @@ impl BranchMap {
var_data.records.push(VariableRecord::default());
}
if branch.chunks.len() <= 1 { // true iff var is a temporary variable.
if branch.chunks.len() <= 1 {
// true iff var is a temporary variable.
debug_assert_eq!(branch.chunks.len(), 1);
let chunk = &mut branch.chunks[0];
@@ -822,7 +858,9 @@ impl BranchMap {
for var_info in chunk.vars.iter_mut() {
if var_info.lvl == Level::Shallow {
let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num);
temp_var_data.use_set.insert((term_loc, var_info.classify_info.arg_c));
temp_var_data
.use_set
.insert((term_loc, var_info.classify_info.arg_c));
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -130,11 +130,7 @@ pub fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: u
}
#[inline]
pub(crate) fn put_complete_string(
heap: &mut Heap,
s: &str,
atom_tbl: &mut AtomTable,
) -> HeapCellValue {
pub(crate) fn put_complete_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
match allocate_pstr(heap, s, atom_tbl) {
Some(h) => {
heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr.
@@ -157,11 +153,7 @@ pub(crate) fn put_complete_string(
}
#[inline]
pub(crate) fn put_partial_string(
heap: &mut Heap,
s: &str,
atom_tbl: &mut AtomTable,
) -> HeapCellValue {
pub(crate) fn put_partial_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
match allocate_pstr(heap, s, atom_tbl) {
Some(h) => {
pstr_loc_as_cell!(h)
@@ -173,11 +165,7 @@ pub(crate) fn put_partial_string(
}
#[inline]
pub(crate) fn allocate_pstr(
heap: &mut Heap,
mut src: &str,
atom_tbl: &mut AtomTable,
) -> Option<usize> {
pub(crate) fn allocate_pstr(heap: &mut Heap, mut src: &str, atom_tbl: &AtomTable) -> Option<usize> {
let orig_h = heap.len();
loop {

View File

@@ -63,21 +63,27 @@ fn add_op_decl_as_module_export<'a, LS: LoadState<'a>>(
match op_decl.insert_into_op_dir(wam_op_dir) {
Some(op_desc) => {
payload.retraction_info.push_record(RetractionRecord::ReplacedUserOp(
*op_decl,
op_desc,
));
payload
.retraction_info
.push_record(RetractionRecord::ReplacedUserOp(*op_decl, op_desc));
payload.module_op_exports.push((*op_decl, Some(op_desc)));
}
None => {
payload.retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl));
payload
.retraction_info
.push_record(RetractionRecord::AddedUserOp(*op_decl));
payload.module_op_exports.push((*op_decl, None));
}
}
let compilation_target = payload.compilation_target;
add_op_decl(&mut payload.retraction_info, &compilation_target, module_op_dir, op_decl);
add_op_decl(
&mut payload.retraction_info,
&compilation_target,
module_op_dir,
op_decl,
);
}
pub(super) fn add_op_decl(
@@ -89,10 +95,7 @@ pub(super) fn add_op_decl(
match op_decl.insert_into_op_dir(op_dir) {
Some(op_desc) => match &compilation_target {
CompilationTarget::User => {
retraction_info.push_record(RetractionRecord::ReplacedUserOp(
*op_decl,
op_desc,
));
retraction_info.push_record(RetractionRecord::ReplacedUserOp(*op_decl, op_desc));
}
CompilationTarget::Module(ref module_name) => {
retraction_info.push_record(RetractionRecord::ReplacedModuleOp(
@@ -107,10 +110,8 @@ pub(super) fn add_op_decl(
retraction_info.push_record(RetractionRecord::AddedUserOp(*op_decl));
}
CompilationTarget::Module(ref module_name) => {
retraction_info.push_record(RetractionRecord::AddedModuleOp(
*module_name,
*op_decl,
));
retraction_info
.push_record(RetractionRecord::AddedModuleOp(*module_name, *op_decl));
}
},
}
@@ -160,7 +161,12 @@ pub(super) fn import_module_exports<'a, LS: LoadState<'a>>(
}
}
ModuleExport::OpDecl(ref op_decl) => {
add_op_decl(&mut payload.retraction_info, compilation_target, op_dir, op_decl);
add_op_decl(
&mut payload.retraction_info,
compilation_target,
op_dir,
op_decl,
);
}
}
}
@@ -209,12 +215,7 @@ fn import_module_exports_into_module<'a, LS: LoadState<'a>>(
}
}
ModuleExport::OpDecl(ref op_decl) => {
add_op_decl_as_module_export::<LS>(
payload,
op_dir,
wam_op_dir,
op_decl,
);
add_op_decl_as_module_export::<LS>(payload, op_dir, wam_op_dir, op_decl);
}
}
}
@@ -239,13 +240,18 @@ fn import_qualified_module_exports<'a, LS: LoadState<'a>>(
let key = (*name, *arity);
if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
wam_prelude.indices.meta_predicates.insert(key.clone(), meta_specs.clone());
wam_prelude
.indices
.meta_predicates
.insert(key.clone(), meta_specs.clone());
}
if let Some(src_code_index) = imported_module.code_dir.get(&key) {
let arena = &mut LS::machine_st(payload).arena;
let target_code_index = wam_prelude.indices.code_dir
let target_code_index = wam_prelude
.indices
.code_dir
.entry(key.clone())
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena))
.clone();
@@ -325,12 +331,7 @@ fn import_qualified_module_exports_into_module<'a, LS: LoadState<'a>>(
}
}
ModuleExport::OpDecl(ref op_decl) => {
add_op_decl_as_module_export::<LS>(
payload,
op_dir,
wam_op_dir,
op_decl,
);
add_op_decl_as_module_export::<LS>(payload, op_dir, wam_op_dir, op_decl);
}
}
}
@@ -378,10 +379,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
mut clause_target_poses: Vec<Option<usize>>,
is_dynamic: bool,
) {
let old_compilation_target = mem::replace(
&mut self.payload.compilation_target,
compilation_target,
);
let old_compilation_target =
mem::replace(&mut self.payload.compilation_target, compilation_target);
while let Some(target_pos_opt) = clause_target_poses.pop() {
match target_pos_opt {
@@ -482,7 +481,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let old_index_ptr = code_index.replace(IndexPtr::undefined());
self.payload.retraction_info
self.payload
.retraction_info
.push_record(RetractionRecord::ReplacedModulePredicate(
module_name,
*key,
@@ -491,7 +491,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
for (key, skeleton) in removed_module.extensible_predicates.drain(..) {
self.payload.retraction_info
self.payload
.retraction_info
.push_record(RetractionRecord::RemovedSkeleton(
CompilationTarget::Module(module_name),
key,
@@ -499,7 +500,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
));
}
self.wam_prelude.indices.modules.insert(module_name, removed_module);
self.wam_prelude
.indices
.modules
.insert(module_name, removed_module);
}
pub(super) fn remove_module_exports(&mut self, module_name: Atom) {
@@ -523,15 +527,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
(Some(module_code_index), Some(target_code_index))
if module_code_index.get() == target_code_index.get() =>
{
let old_index_ptr = target_code_index.replace(IndexPtr::undefined());
retraction_info.push_record(predicate_retractor(*key, old_index_ptr));
let old_index_ptr =
target_code_index.replace(IndexPtr::undefined());
retraction_info
.push_record(predicate_retractor(*key, old_index_ptr));
}
_ => {}
}
}
ModuleExport::OpDecl(op_decl) => {
let op_dir_value_opt =
op_dir.remove(&(op_decl.name, fixity(op_decl.op_desc.get_spec() as u32)));
let op_dir_value_opt = op_dir
.remove(&(op_decl.name, fixity(op_decl.op_desc.get_spec() as u32)));
if let Some(op_desc) = op_dir_value_opt {
retraction_info.push_record(op_retractor(*op_decl, op_desc));
@@ -552,9 +558,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::ReplacedUserOp,
);
}
CompilationTarget::Module(target_module_name)
if target_module_name != module_name =>
{
CompilationTarget::Module(target_module_name) if target_module_name != module_name => {
let predicate_retractor = |key, index_ptr| {
RetractionRecord::ReplacedModulePredicate(module_name, key, index_ptr)
};
@@ -563,7 +567,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::ReplacedModuleOp(module_name, op_decl, op_desc)
};
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&target_module_name) {
if let Some(module) = self
.wam_prelude
.indices
.modules
.get_mut(&target_module_name)
{
remove_module_exports(
&removed_module,
&mut module.code_dir,
@@ -579,7 +588,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
CompilationTarget::Module(_) => {}
};
self.wam_prelude.indices.modules.insert(module_name, removed_module);
self.wam_prelude
.indices
.modules
.insert(module_name, removed_module);
}
fn get_or_insert_local_code_index(
@@ -591,10 +603,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
Some(ref mut module) => module
.code_dir
.entry(key)
.or_insert_with(|| CodeIndex::new(
IndexPtr::undefined(),
&mut LS::machine_st(&mut self.payload).arena,
))
.or_insert_with(|| {
CodeIndex::new(
IndexPtr::undefined(),
&mut LS::machine_st(&mut self.payload).arena,
)
})
.clone(),
None => {
self.add_dynamically_generated_module(module_name);
@@ -603,10 +617,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
Some(ref mut module) => module
.code_dir
.entry(key)
.or_insert_with(|| CodeIndex::new(
IndexPtr::undefined(),
&mut LS::machine_st(&mut self.payload).arena,
))
.or_insert_with(|| {
CodeIndex::new(
IndexPtr::undefined(),
&mut LS::machine_st(&mut self.payload).arena,
)
})
.clone(),
None => {
unreachable!()
@@ -771,10 +787,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
ClauseType::Named(arity, name, _) => {
let payload_compilation_target = self.payload.compilation_target;
let idx = self.get_or_insert_code_index(
(name, arity),
payload_compilation_target,
);
let idx = self.get_or_insert_code_index((name, arity), payload_compilation_target);
ClauseType::Named(arity, name, idx)
}
@@ -802,13 +815,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
pub(super) fn get_meta_specs(&self, name: Atom, arity: usize) -> Option<&Vec<MetaSpec>> {
self.wam_prelude
.indices
.get_meta_predicate_spec(
name,
arity,
&self.payload.compilation_target,
)
self.wam_prelude.indices.get_meta_predicate_spec(
name,
arity,
&self.payload.compilation_target,
)
}
pub(super) fn add_meta_predicate_record(
@@ -829,19 +840,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.insert(key, meta_specs)
{
Some(old_meta_specs) => {
self.payload.retraction_info
.push_record(RetractionRecord::ReplacedMetaPredicate(
self.payload.retraction_info.push_record(
RetractionRecord::ReplacedMetaPredicate(
module_name,
key.0,
old_meta_specs,
));
),
);
}
None => {
self.payload.retraction_info
.push_record(RetractionRecord::AddedMetaPredicate(
module_name,
key,
));
self.payload
.retraction_info
.push_record(RetractionRecord::AddedMetaPredicate(module_name, key));
}
}
}
@@ -868,17 +878,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
None => {
self.add_dynamically_generated_module(module_name);
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&module_name) {
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&module_name)
{
module.meta_predicates.insert(key.clone(), meta_specs);
} else {
unreachable!()
}
self.payload.retraction_info
.push_record(RetractionRecord::AddedMetaPredicate(
module_name.clone(),
key,
));
self.payload.retraction_info.push_record(
RetractionRecord::AddedMetaPredicate(module_name.clone(), key),
);
}
}
}
@@ -901,10 +910,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
&mut module.meta_predicates,
);
self.payload.retraction_info
self.payload
.retraction_info
.push_record(RetractionRecord::AddedModule(module_name.clone()));
self.wam_prelude.indices.modules.insert(module_name.clone(), module);
self.wam_prelude
.indices
.modules
.insert(module_name.clone(), module);
}
fn import_builtins_in_module(
@@ -968,9 +981,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if is_dynamic {
let clause_clause_compilation_target = match compilation_target {
CompilationTarget::User => {
CompilationTarget::Module(atom!("builtins"))
}
CompilationTarget::User => CompilationTarget::Module(atom!("builtins")),
module => module.clone(),
};
@@ -981,7 +992,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
self.payload.retraction_info
self.payload
.retraction_info
.push_record(RetractionRecord::ReplacedModule(
old_module_decl,
listing_src.clone(),
@@ -1051,7 +1063,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
)?;
}
CompilationTarget::Module(ref defining_module_name) => {
match self.wam_prelude.indices.modules.get_mut(defining_module_name) {
match self
.wam_prelude
.indices
.modules
.get_mut(defining_module_name)
{
Some(ref mut target_module) => {
import_module_exports_into_module::<LS>(
&mut self.payload,
@@ -1091,17 +1108,20 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let payload_compilation_target = self.payload.compilation_target;
let result = match &payload_compilation_target {
CompilationTarget::User => {
import_qualified_module_exports::<LS>(
&mut self.payload,
&payload_compilation_target,
&module,
&exports,
&mut self.wam_prelude,
)
}
CompilationTarget::User => import_qualified_module_exports::<LS>(
&mut self.payload,
&payload_compilation_target,
&module,
&exports,
&mut self.wam_prelude,
),
CompilationTarget::Module(ref defining_module_name) => {
match self.wam_prelude.indices.modules.get_mut(defining_module_name) {
match self
.wam_prelude
.indices
.modules
.get_mut(defining_module_name)
{
Some(ref mut target_module) => {
import_qualified_module_exports_into_module::<LS>(
&mut self.payload,
@@ -1113,9 +1133,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
&mut self.wam_prelude.indices.op_dir,
)
}
None => {
Err(SessionError::ModuleCannotImportSelf(module_name))
}
None => Err(SessionError::ModuleCannotImportSelf(module_name)),
}
}
};
@@ -1123,29 +1141,38 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.wam_prelude.indices.modules.insert(module_name, module);
result
} else {
Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
Err(SessionError::ExistenceError(ExistenceError::Module(
module_name,
)))
}
}
pub(crate) fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> {
let (stream, listing_src) = match module_src {
ModuleSource::File(filename) => {
let mut path_buf = PathBuf::from(filename.as_str());
let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl");
let file = File::open(&path_buf)?;
(
Stream::from_file_as_input(filename, file, &mut LS::machine_st(&mut self.payload).arena),
Stream::from_file_as_input(
filename,
file,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::File(filename, path_buf),
)
}
ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) {
ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) {
Some(code) => {
if let Some(ref module) = self.wam_prelude.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = &module.listing_src {
(
Stream::from_static_string(*code, &mut LS::machine_st(&mut self.payload).arena),
Stream::from_static_string(
*code,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::User,
)
} else {
@@ -1153,7 +1180,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
} else {
(
Stream::from_static_string(*code, &mut LS::machine_st(&mut self.payload).arena),
Stream::from_static_string(
*code,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::User,
)
}
@@ -1172,9 +1202,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
);
let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState(
LoadStatePayload::new(self.wam_prelude.code.len(), term_stream)
),
payload: BootstrappingLoadState(LoadStatePayload::new(
self.wam_prelude.code.len(),
term_stream,
)),
wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices,
code: self.wam_prelude.code,
@@ -1201,22 +1232,29 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
) -> Result<(), SessionError> {
let (stream, listing_src) = match module_src {
ModuleSource::File(filename) => {
let mut path_buf = PathBuf::from(filename.as_str());
let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl");
let file = File::open(&path_buf)?;
(
Stream::from_file_as_input(filename, file, &mut LS::machine_st(&mut self.payload).arena),
Stream::from_file_as_input(
filename,
file,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::File(filename, path_buf),
)
}
ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) {
ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) {
Some(code) => {
if self.wam_prelude.indices.modules.contains_key(&library) {
return self.import_qualified_module(library, exports);
} else {
(
Stream::from_static_string(*code, &mut LS::machine_st(&mut self.payload).arena),
Stream::from_static_string(
*code,
&mut LS::machine_st(&mut self.payload).arena,
),
ListingSource::User,
)
}
@@ -1235,9 +1273,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
);
let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState(
LoadStatePayload::new(self.wam_prelude.code.len(), term_stream),
),
payload: BootstrappingLoadState(LoadStatePayload::new(
self.wam_prelude.code.len(),
term_stream,
)),
wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices,
code: self.wam_prelude.code,

View File

@@ -230,9 +230,7 @@ macro_rules! predicate_queue {
pub type LiveLoadState = LoadStatePayload<LiveTermStream>;
pub struct BootstrappingLoadState<'a>(
pub LoadStatePayload<BootstrappingTermStream<'a>>
);
pub struct BootstrappingLoadState<'a>(pub LoadStatePayload<BootstrappingTermStream<'a>>);
impl<'a> Deref for BootstrappingLoadState<'a> {
type Target = LoadStatePayload<BootstrappingTermStream<'a>>;
@@ -253,9 +251,12 @@ impl<'a> DerefMut for BootstrappingLoadState<'a> {
pub trait LoadState<'a>: Sized {
type Evacuable;
type TS: TermStream;
type LoaderFieldType: DerefMut<Target=LoadStatePayload<Self::TS>>;
type LoaderFieldType: DerefMut<Target = LoadStatePayload<Self::TS>>;
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType;
fn new(
machine_st: &'a mut MachineState,
payload: LoadStatePayload<Self::TS>,
) -> Self::LoaderFieldType;
fn evacuate(loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError>;
fn should_drop_load_state(loader: &Loader<'a, Self>) -> bool;
fn reset_machine(loader: &mut Loader<'a, Self>);
@@ -293,14 +294,23 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
type Evacuable = TypedArenaPtr<LiveLoadState>;
#[inline(always)]
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType {
fn new(
machine_st: &'a mut MachineState,
payload: LoadStatePayload<Self::TS>,
) -> Self::LoaderFieldType {
let load_state = arena_alloc!(payload, &mut machine_st.arena);
LiveLoadAndMachineState { load_state, machine_st }
LiveLoadAndMachineState {
load_state,
machine_st,
}
}
#[inline(always)]
fn evacuate(mut loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> {
loader.payload.load_state.set_tag(ArenaHeaderTag::InactiveLoadState);
loader
.payload
.load_state
.set_tag(ArenaHeaderTag::InactiveLoadState);
Ok(loader.payload.load_state)
}
@@ -332,7 +342,11 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
}
if let Some(builtins) = loader.wam_prelude.indices.modules.get(&atom!("builtins")) {
if builtins.module_decl.exports.contains(&ModuleExport::PredicateKey(key)) {
if builtins
.module_decl
.exports
.contains(&ModuleExport::PredicateKey(key))
{
return Err(SessionError::CannotOverwriteBuiltIn(key));
}
}
@@ -358,10 +372,7 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
let repo_len = loader.wam_prelude.code.len();
loader
.payload
.retraction_info
.reset(repo_len);
loader.payload.retraction_info.reset(repo_len);
loader.remove_module_op_exports();
@@ -419,22 +430,27 @@ impl<'a> LoadState<'a> for InlineLoadState<'a> {
type Evacuable = ();
#[inline(always)]
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType {
InlineLoadState { machine_st, payload }
fn new(
machine_st: &'a mut MachineState,
payload: LoadStatePayload<Self::TS>,
) -> Self::LoaderFieldType {
InlineLoadState {
machine_st,
payload,
}
}
fn evacuate(_loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> {
Ok(())
Ok(())
}
#[inline(always)]
fn should_drop_load_state(_loader: &Loader<'a, Self>) -> bool {
false
false
}
#[inline(always)]
fn reset_machine(_loader: &mut Loader<'a, Self>) {
}
fn reset_machine(_loader: &mut Loader<'a, Self>) {}
#[inline(always)]
fn machine_st(load_state: &mut Self::LoaderFieldType) -> &mut MachineState {
@@ -548,7 +564,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
atom!("user") => {
self.wam_prelude.indices.meta_predicates.remove(&key);
}
_ => match self.wam_prelude.indices.modules.get_mut(&target_module_name) {
_ => match self
.wam_prelude
.indices
.modules
.get_mut(&target_module_name)
{
Some(ref mut module) => {
module.meta_predicates.remove(&key);
}
@@ -566,7 +587,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.meta_predicates
.insert((name, meta_specs.len()), meta_specs);
}
_ => match self.wam_prelude.indices.modules.get_mut(&target_module_name) {
_ => match self
.wam_prelude
.indices
.modules
.get_mut(&target_module_name)
{
Some(ref mut module) => {
module
.meta_predicates
@@ -773,9 +799,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
RetractionRecord::ReplacedChoiceOffset(instr_loc, offset) => {
match self.wam_prelude.code[instr_loc] {
Instruction::TryMeElse(ref mut o) |
Instruction::RetryMeElse(ref mut o) |
Instruction::DefaultRetryMeElse(ref mut o) => {
Instruction::TryMeElse(ref mut o)
| Instruction::RetryMeElse(ref mut o)
| Instruction::DefaultRetryMeElse(ref mut o) => {
*o = offset;
}
_ => {
@@ -792,16 +818,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v) => {
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,
..,
)) => {
*v = old_v;
Instruction::IndexingCode(ref mut indexing_code) => {
match &mut indexing_code[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_,
ref mut v,
..,
)) => {
*v = old_v;
}
_ => {}
}
_ => {}
},
}
_ => {}
}
}
@@ -941,7 +969,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.get_predicate_skeleton_mut(&compilation_target, &key)
{
Some(skeleton) => {
if let Some(removed_clauses) = &mut skeleton.core.retracted_dynamic_clauses {
if let Some(removed_clauses) =
&mut skeleton.core.retracted_dynamic_clauses
{
let clause_index_info = removed_clauses.pop().unwrap();
skeleton
@@ -1001,10 +1031,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton) => {
match compilation_target {
CompilationTarget::User => {
self.wam_prelude.indices.extensible_predicates.insert(key, skeleton);
self.wam_prelude
.indices
.extensible_predicates
.insert(key, skeleton);
}
CompilationTarget::Module(module_name) => {
if let Some(module) = self.wam_prelude.indices.modules.get_mut(&module_name) {
if let Some(module) =
self.wam_prelude.indices.modules.get_mut(&module_name)
{
module.extensible_predicates.insert(key, skeleton);
}
}
@@ -1012,16 +1047,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
RetractionRecord::ReplacedDynamicElseOffset(instr_loc, next) => {
match self.wam_prelude.code[instr_loc] {
Instruction::DynamicElse(
_,
_,
NextOrFail::Next(ref mut o),
)
| Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
) => {
Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))
| Instruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o)) => {
*o = next;
}
_ => {}
@@ -1029,16 +1056,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
RetractionRecord::AppendedNextOrFail(instr_loc, fail) => {
match self.wam_prelude.code[instr_loc] {
Instruction::DynamicElse(
_,
_,
ref mut next_or_fail,
)
| Instruction::DynamicInternalElse(
_,
_,
ref mut next_or_fail,
) => {
Instruction::DynamicElse(_, _, ref mut next_or_fail)
| Instruction::DynamicInternalElse(_, _, ref mut next_or_fail) => {
*next_or_fail = fail;
}
_ => {}
@@ -1057,15 +1076,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let export_list = machine_st.read_term_from_heap(cell)?;
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
let export_list = setup_module_export_list(export_list, atom_tbl)?;
let export_list = setup_module_export_list(export_list, &atom_tbl)?;
Ok(export_list.into_iter().collect())
}
fn add_clause_clause(&mut self, term: Term) -> Result<(), CompilationError> {
match term {
Term::Clause(_, atom!(":-"), mut terms) if terms.len() == 2 =>
{
Term::Clause(_, atom!(":-"), mut terms) if terms.len() == 2 => {
let body = terms.pop().unwrap();
let head = terms.pop().unwrap();
@@ -1096,20 +1114,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
match &compilation_target {
CompilationTarget::User => {
match self
.wam_prelude
.indices
.extensible_predicates
.get_mut(&key)
{
match self.wam_prelude.indices.extensible_predicates.get_mut(&key) {
Some(skeleton) => {
if !*flag_accessor(&mut skeleton.core) {
*flag_accessor(&mut skeleton.core) = true;
self.payload.retraction_info.push_record(retraction_fn(
compilation_target,
key,
));
self.payload
.retraction_info
.push_record(retraction_fn(compilation_target, key));
}
}
None => {
@@ -1117,11 +1129,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = PredicateSkeleton::new();
*flag_accessor(&mut skeleton.core) = true;
self.add_extensible_predicate(
key,
skeleton,
CompilationTarget::User,
);
self.add_extensible_predicate(key, skeleton, CompilationTarget::User);
} else {
throw_permission_error = true;
}
@@ -1135,10 +1143,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if !*flag_accessor(&mut skeleton.core) {
*flag_accessor(&mut skeleton.core) = true;
self.payload.retraction_info.push_record(retraction_fn(
compilation_target,
key,
));
self.payload
.retraction_info
.push_record(retraction_fn(compilation_target, key));
}
}
None => {
@@ -1146,11 +1153,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = PredicateSkeleton::new();
*flag_accessor(&mut skeleton.core) = true;
self.add_extensible_predicate(
key,
skeleton,
compilation_target,
);
self.add_extensible_predicate(key, skeleton, compilation_target);
} else {
throw_permission_error = true;
}
@@ -1162,11 +1165,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = PredicateSkeleton::new();
*flag_accessor(&mut skeleton.core) = true;
self.add_extensible_predicate(
key,
skeleton,
compilation_target,
);
self.add_extensible_predicate(key, skeleton, compilation_target);
}
}
}
@@ -1178,15 +1177,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
match payload_compilation_target {
CompilationTarget::User => {
match self
.wam_prelude
.indices
.get_local_predicate_skeleton_mut(
payload_compilation_target,
compilation_target,
listing_src_file_name,
key,
) {
match self.wam_prelude.indices.get_local_predicate_skeleton_mut(
payload_compilation_target,
compilation_target,
listing_src_file_name,
key,
) {
Some(skeleton) => {
if !*flag_accessor(skeleton) {
*flag_accessor(skeleton) = true;
@@ -1196,11 +1192,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new();
*flag_accessor(&mut skeleton) = true;
self.add_local_extensible_predicate(
compilation_target,
key,
skeleton,
);
self.add_local_extensible_predicate(compilation_target, key, skeleton);
}
}
}
@@ -1232,11 +1224,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut skeleton = LocalPredicateSkeleton::new();
*flag_accessor(&mut skeleton) = true;
self.add_local_extensible_predicate(
compilation_target,
key,
skeleton,
);
self.add_local_extensible_predicate(compilation_target, key, skeleton);
}
}
}
@@ -1336,10 +1324,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let is_dynamic = self
.wam_prelude
.indices
.get_predicate_skeleton(
&predicates_compilation_target,
&(predicate_name, arity),
)
.get_predicate_skeleton(&predicates_compilation_target, &(predicate_name, arity))
.map(|skeleton| skeleton.core.is_dynamic)
.unwrap_or(false);
@@ -1356,15 +1341,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let predicates_compilation_target = self.payload.predicates.compilation_target;
let listing_src_file_name = self.listing_src_file_name();
let clause_locs = match self
.wam_prelude
.indices
.get_local_predicate_skeleton_mut(
payload_compilation_target,
predicates_compilation_target,
listing_src_file_name,
*key,
) {
let clause_locs = match self.wam_prelude.indices.get_local_predicate_skeleton_mut(
payload_compilation_target,
predicates_compilation_target,
listing_src_file_name,
*key,
) {
Some(skeleton) if !skeleton.clause_clause_locs.is_empty() => {
mem::replace(&mut skeleton.clause_clause_locs, VecDeque::new())
}
@@ -1380,11 +1362,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
),
);
self.retract_local_clauses_impl(
predicates_compilation_target,
*key,
&clause_locs,
);
self.retract_local_clauses_impl(predicates_compilation_target, *key, &clause_locs);
if is_dynamic {
let clause_clause_compilation_target = match predicates_compilation_target {
@@ -1399,7 +1377,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
impl<'a> MachinePreludeView<'a> {
#[inline]
pub(super) fn composite_op_dir(&self, compilation_target: &CompilationTarget) -> CompositeOpDir {
pub(super) fn composite_op_dir(
&self,
compilation_target: &CompilationTarget,
) -> CompositeOpDir {
match compilation_target {
CompilationTarget::User => CompositeOpDir::new(&self.indices.op_dir, None),
CompilationTarget::Module(ref module_name) => {
@@ -1417,7 +1398,10 @@ impl<'a> MachinePreludeView<'a> {
}
impl MachineState {
pub(super) fn read_term_from_heap(&mut self, term_addr: HeapCellValue) -> Result<Term, SessionError> {
pub(super) fn read_term_from_heap(
&mut self,
term_addr: HeapCellValue,
) -> Result<Term, SessionError> {
let mut term_stack = vec![];
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term_addr);
@@ -1436,7 +1420,7 @@ impl MachineState {
term_stack.push(Term::PartialString(Cell::default(), string, tail));
}
Ok((string, None)) => {
let atom = self.atom_tbl.build_with(&string);
let atom = AtomTable::build_with(&self.atom_tbl, &string);
term_stack.push(Term::CompleteString(Cell::default(), atom));
}
Err(cons_term) => term_stack.push(cons_term),
@@ -1550,9 +1534,9 @@ impl Machine {
}
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]))
);
let library = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
if let Some(module) = self.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = module.listing_src {
@@ -1583,9 +1567,9 @@ impl Machine {
}
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]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1695,9 +1679,9 @@ impl Machine {
}
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]))
);
let target_module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1717,7 +1701,8 @@ impl Machine {
if let Some(indexing_term) = indexing_arg {
if let Some(indexing_name) = indexing_term.name() {
loader.wam_prelude
loader
.wam_prelude
.indices
.goal_expansion_indices
.insert((indexing_name, indexing_term.arity()));
@@ -1792,16 +1777,19 @@ impl Machine {
&'a mut self,
r: RegType,
) -> Loader<'a, LiveLoadAndMachineState<'a>> {
let mut load_state = cell_as_load_state_payload!(
self.machine_st.store(self.machine_st.deref(self.machine_st[r]))
);
let mut load_state = cell_as_load_state_payload!(self
.machine_st
.store(self.machine_st.deref(self.machine_st[r])));
load_state.set_tag(ArenaHeaderTag::LiveLoadState);
let (wam_prelude, machine_st) = self.prelude_view_and_machine_st();
Loader {
payload: LiveLoadAndMachineState { load_state, machine_st },
payload: LiveLoadAndMachineState {
load_state,
machine_st,
},
wam_prelude,
}
}
@@ -1809,26 +1797,21 @@ impl Machine {
#[inline]
pub(crate) fn push_load_state_payload(&mut self) {
let payload = arena_alloc!(
LoadStatePayload::new(
self.code.len(),
LiveTermStream::new(ListingSource::User),
),
LoadStatePayload::new(self.code.len(), LiveTermStream::new(ListingSource::User),),
&mut self.machine_st.arena
);
let var = self.machine_st.deref(self.machine_st.registers[1]);
self.machine_st.bind(
var.as_var().unwrap(),
typed_arena_ptr_as_cell!(payload),
);
self.machine_st
.bind(var.as_var().unwrap(), typed_arena_ptr_as_cell!(payload));
}
#[inline]
pub(crate) fn pop_load_state_payload(&mut self) {
let load_state_payload = self.machine_st.store(
self.machine_st.deref(self.machine_st.registers[1])
);
let load_state_payload = self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1]));
// unlike in loader_from_heap_evacuable,
// pop_load_state_payload is allowed to fail to find a
@@ -1866,11 +1849,12 @@ impl Machine {
2,
)?;
let path = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[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));
self.load_contexts
.push(LoadContext::new(&*path.as_str(), stream));
Ok(())
}
@@ -1879,9 +1863,7 @@ impl Machine {
result: Result<TypedArenaPtr<LiveLoadState>, SessionError>,
) -> CallResult {
match result {
Ok(_payload) => {
Ok(())
}
Ok(_payload) => Ok(()),
Err(e) => {
let err = self.machine_st.session_error(e);
let stub = functor_stub(atom!("load"), 1);
@@ -1892,9 +1874,9 @@ impl Machine {
}
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]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1934,9 +1916,10 @@ impl Machine {
pub(crate) fn load_context_source(&mut self) {
if let Some(load_context) = self.load_contexts.last() {
let path_str = load_context.path.to_str().unwrap();
let path_atom = self.machine_st.atom_tbl.build_with(path_str);
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, path_str);
self.machine_st.unify_atom(path_atom, self.machine_st.registers[1]);
self.machine_st
.unify_atom(path_atom, self.machine_st.registers[1]);
} else {
self.machine_st.fail = true;
}
@@ -1947,9 +1930,11 @@ impl Machine {
match load_context.path.file_name() {
Some(file_name) if load_context.path.is_file() => {
let file_name_str = file_name.to_str().unwrap();
let file_name_atom = self.machine_st.atom_tbl.build_with(file_name_str);
let file_name_atom =
AtomTable::build_with(&self.machine_st.atom_tbl, file_name_str);
self.machine_st.unify_atom(file_name_atom, self.machine_st.registers[1]);
self.machine_st
.unify_atom(file_name_atom, self.machine_st.registers[1]);
return;
}
_ => {
@@ -1965,9 +1950,11 @@ impl Machine {
if let Some(load_context) = self.load_contexts.last() {
if let Some(directory) = load_context.path.parent() {
let directory_str = directory.to_str().unwrap();
let directory_atom = self.machine_st.atom_tbl.build_with(directory_str);
let directory_atom =
AtomTable::build_with(&self.machine_st.atom_tbl, directory_str);
self.machine_st.unify_atom(directory_atom, self.machine_st.registers[1]);
self.machine_st
.unify_atom(directory_atom, self.machine_st.registers[1]);
return;
}
}
@@ -2002,11 +1989,9 @@ impl Machine {
_ => CompilationTarget::Module(module_name),
};
let stub_gen = || {
match append_or_prepend {
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
}
let stub_gen = || match append_or_prepend {
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
};
let head = self.deref_register(2);
@@ -2022,7 +2007,8 @@ impl Machine {
loader.payload.compilation_target = compilation_target;
let head = LiveLoadAndMachineState::machine_st(&mut loader.payload).read_term_from_heap(head)?;
let head = LiveLoadAndMachineState::machine_st(&mut loader.payload)
.read_term_from_heap(head)?;
let name = if let Some(name) = head.name() {
name
@@ -2034,32 +2020,24 @@ impl Machine {
let is_builtin = loader.wam_prelude.indices.builtin_property((name, arity));
let is_dynamic_predicate = loader
.wam_prelude
.indices
.is_dynamic_predicate(
module_name,
(name, arity),
);
.wam_prelude
.indices
.is_dynamic_predicate(module_name, (name, arity));
let no_such_predicate =
if !is_dynamic_predicate && !is_builtin {
let idx_tag = loader
.wam_prelude
.indices
.get_predicate_code_index(
name,
arity,
module_name,
)
.map(|code_idx| code_idx.get_tag())
.unwrap_or(IndexPtrTag::DynamicUndefined);
let no_such_predicate = if !is_dynamic_predicate && !is_builtin {
let idx_tag = loader
.wam_prelude
.indices
.get_predicate_code_index(name, arity, module_name)
.map(|code_idx| code_idx.get_tag())
.unwrap_or(IndexPtrTag::DynamicUndefined);
idx_tag == IndexPtrTag::DynamicUndefined || idx_tag == IndexPtrTag::Undefined
} else if is_builtin {
return Err(SessionError::CannotOverwriteBuiltIn((name, arity)));
} else {
is_dynamic_predicate
};
idx_tag == IndexPtrTag::DynamicUndefined || idx_tag == IndexPtrTag::Undefined
} else if is_builtin {
return Err(SessionError::CannotOverwriteBuiltIn((name, arity)));
} else {
is_dynamic_predicate
};
if !no_such_predicate {
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail = true;
@@ -2101,23 +2079,18 @@ impl Machine {
match compile_assert() {
Ok(_) => Ok(()),
Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead |
CompilationError::InadmissibleFact
CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
)) => {
let err = self.machine_st.type_error(
ValidType::Callable,
self.machine_st.registers[2],
);
let err = self
.machine_st
.type_error(ValidType::Callable, self.machine_st.registers[2]);
Err(self.machine_st.error_form(err, stub_gen()))
}
Err(SessionError::CompilationError(
CompilationError::InadmissibleQueryTerm
)) => {
let err = self.machine_st.type_error(
ValidType::Callable,
self.machine_st.registers[3],
);
Err(SessionError::CompilationError(CompilationError::InadmissibleQueryTerm)) => {
let err = self
.machine_st
.type_error(ValidType::Callable, self.machine_st.registers[3]);
Err(self.machine_st.error_form(err, stub_gen()))
}
@@ -2129,9 +2102,9 @@ impl Machine {
}
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 module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self
.machine_st
@@ -2143,8 +2116,8 @@ impl Machine {
};
let mut abolish_clause = || {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>>
= Loader::new(self, LiveTermStream::new(ListingSource::User));
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target;
@@ -2164,9 +2137,11 @@ impl Machine {
.remove_predicate_skeleton(
&clause_clause_compilation_target,
&(atom!("$clause"), 2),
).unwrap();
)
.unwrap();
let result = skeleton.core
let result = skeleton
.core
.clause_clause_locs
.iter()
.map(|clause_clause_loc| {
@@ -2176,11 +2151,7 @@ impl Machine {
})
.collect();
loader.add_extensible_predicate(
key,
skeleton,
compilation_target,
);
loader.add_extensible_predicate(key, skeleton, compilation_target);
loader.add_extensible_predicate(
(atom!("$clause"), 2),
@@ -2189,14 +2160,15 @@ impl Machine {
);
result
}).unwrap();
})
.unwrap();
loader.wam_prelude
loader
.wam_prelude
.indices
.remove_predicate_skeleton(&compilation_target, &key);
let mut code_index = loader
.get_or_insert_code_index(key, compilation_target);
let mut code_index = loader.get_or_insert_code_index(key, compilation_target);
code_index.set(IndexPtr::undefined());
@@ -2237,9 +2209,9 @@ impl Machine {
_ => unreachable!(),
};
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[4])));
let compilation_target = match module_name {
atom!("user") => CompilationTarget::User,
@@ -2292,9 +2264,9 @@ impl Machine {
}
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]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self
.machine_st
@@ -2309,8 +2281,8 @@ impl Machine {
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
(!loader.payload.predicates.is_empty()
&& loader.payload.predicates.compilation_target != compilation_target)
|| !key.is_consistent(&loader.payload.predicates);
&& loader.payload.predicates.compilation_target != compilation_target)
|| !key.is_consistent(&loader.payload.predicates);
let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result)
@@ -2332,9 +2304,9 @@ impl Machine {
}
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]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
@@ -2360,9 +2332,9 @@ impl Machine {
}
pub(crate) fn meta_predicate_property(&mut self) {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let (predicate_name, arity) = self
.machine_st
@@ -2380,9 +2352,12 @@ impl Machine {
Some(meta_specs) => {
let term_loc = self.machine_st.heap.len();
self.machine_st.heap.push(atom_as_cell!(predicate_name, arity));
self.machine_st.heap.extend(
meta_specs.iter().map(|meta_spec| match meta_spec {
self.machine_st
.heap
.push(atom_as_cell!(predicate_name, arity));
self.machine_st
.heap
.extend(meta_specs.iter().map(|meta_spec| match meta_spec {
MetaSpec::Minus => atom_as_cell!(atom!("+")),
MetaSpec::Plus => atom_as_cell!(atom!("-")),
MetaSpec::Either => atom_as_cell!(atom!("?")),
@@ -2390,15 +2365,20 @@ impl Machine {
MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
fixnum_as_cell!(Fixnum::build_with(*arg_num as i64))
}
})
);
}));
let heap_loc = self.machine_st.heap.len();
self.machine_st.heap.push(atom_as_cell!(atom!("meta_predicate"), 1));
self.machine_st
.heap
.push(atom_as_cell!(atom!("meta_predicate"), 1));
self.machine_st.heap.push(str_loc_as_cell!(term_loc));
unify!(self.machine_st, str_loc_as_cell!(heap_loc), self.machine_st.registers[4]);
unify!(
self.machine_st,
str_loc_as_cell!(heap_loc),
self.machine_st.registers[4]
);
}
None => {
self.machine_st.fail = true;
@@ -2407,9 +2387,9 @@ impl Machine {
}
pub(crate) fn dynamic_property(&mut self) {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self
.machine_st
@@ -2434,9 +2414,9 @@ impl Machine {
}
pub(crate) fn multifile_property(&mut self) {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self
.machine_st
@@ -2461,9 +2441,9 @@ impl Machine {
}
pub(crate) fn discontiguous_property(&mut self) {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let module_name = cell_as_atom!(self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let key = self
.machine_st

View File

@@ -44,7 +44,8 @@ pub(crate) enum ValidType {
InCharacter,
Integer,
List,
#[allow(unused)] Number,
#[allow(unused)]
Number,
Pair,
// PredicateIndicator,
// Variable
@@ -254,9 +255,11 @@ pub(super) type FunctorStub = [HeapCellValue; 3];
#[inline(always)]
pub(super) fn functor_stub(name: Atom, arity: usize) -> FunctorStub {
[atom_as_cell!(atom!("/"), 2),
atom_as_cell!(name),
fixnum_as_cell!(Fixnum::build_with(arity as i64))]
[
atom_as_cell!(atom!("/"), 2),
atom_as_cell!(name),
fixnum_as_cell!(Fixnum::build_with(arity as i64)),
]
}
impl MachineState {
@@ -440,11 +443,13 @@ impl MachineState {
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
match err {
SessionError::CannotOverwriteBuiltIn(key) => {
// SessionError::CannotOverwriteImport(pred_atom) => {
// SessionError::CannotOverwriteImport(pred_atom) => {
self.permission_error(
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1).into_iter().collect::<MachineStub>(),
functor_stub(key.0, key.1)
.into_iter()
.collect::<MachineStub>(),
)
}
SessionError::ExistenceError(err) => self.existence_error(err),
@@ -471,7 +476,11 @@ impl MachineState {
}
SessionError::NamelessEntry => {
let error_atom = atom!("nameless_procedure");
self.permission_error(Permission::Create, atom!("static_procedure"), functor!(error_atom))
self.permission_error(
Permission::Create,
atom!("static_procedure"),
functor!(error_atom),
)
}
SessionError::OpIsInfixAndPostFix(op) => {
self.permission_error(Permission::Create, atom!("operator"), functor!(op))
@@ -541,21 +550,21 @@ impl MachineState {
#[cfg(feature = "ffi")]
pub(super) fn ffi_error(&mut self, err: FFIError) -> MachineError {
let error_atom = match err {
FFIError::ValueCast => atom!("value_cast"),
FFIError::ValueDontFit => atom!("value_dont_fit"),
FFIError::InvalidFFIType => atom!("invalid_ffi_type"),
FFIError::InvalidStructName => atom!("invalid_struct_name"),
FFIError::FunctionNotFound => atom!("function_not_found"),
FFIError::StructNotFound => atom!("struct_not_found"),
};
let stub = functor!(atom!("ffi_error"),[atom(error_atom)]);
let error_atom = match err {
FFIError::ValueCast => atom!("value_cast"),
FFIError::ValueDontFit => atom!("value_dont_fit"),
FFIError::InvalidFFIType => atom!("invalid_ffi_type"),
FFIError::InvalidStructName => atom!("invalid_struct_name"),
FFIError::FunctionNotFound => atom!("function_not_found"),
FFIError::StructNotFound => atom!("struct_not_found"),
};
let stub = functor!(atom!("ffi_error"), [atom(error_atom)]);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
pub(super) fn error_form(&mut self, err: MachineError, src: FunctorStub) -> MachineStub {
@@ -682,10 +691,12 @@ impl CompilationError {
&CompilationError::ExpectedRel => {
functor!(atom!("expected_relation"))
}
&CompilationError::InadmissibleFact => { // TODO: type_error(callable, _).
&CompilationError::InadmissibleFact => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_fact"))
}
&CompilationError::InadmissibleQueryTerm => { // TODO: type_error(callable, _).
&CompilationError::InadmissibleQueryTerm => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_query_term"))
}
&CompilationError::InconsistentEntry => {
@@ -820,10 +831,10 @@ pub enum CycleSearchResult {
Cyclic(usize),
EmptyList,
NotList(usize, HeapCellValue), // the list length until the second argument in the heap
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
ProperList(usize), // the list length.
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
ProperList(usize), // the list length.
PStrLocation(usize, usize, usize), // list length (up to max), the heap address of the PStr, the offset
UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address).
UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address).
UntouchedCStr(Atom, usize),
}
@@ -838,7 +849,7 @@ impl MachineState {
match BrentAlgState::detect_cycles(&self.heap, list) {
CycleSearchResult::PartialList(..) => {
let err = self.instantiation_error();
return Err(self.error_form(err, stub_gen()))
return Err(self.error_form(err, stub_gen()));
}
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => {
let err = self.type_error(ValidType::List, list);

View File

@@ -3,15 +3,15 @@ use crate::parser::ast::*;
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
use crate::machine::ClauseType;
use crate::machine::loader::*;
use crate::machine::machine_state::*;
use crate::machine::streams::Stream;
use crate::machine::ClauseType;
use fxhash::FxBuildHasher;
use indexmap::{IndexMap, IndexSet};
use modular_bitfield::{BitfieldSpecifier, bitfield};
use modular_bitfield::specifiers::*;
use modular_bitfield::{bitfield, BitfieldSpecifier};
use std::cmp::Ordering;
use std::collections::BTreeSet;
@@ -86,7 +86,8 @@ pub enum IndexPtrTag {
#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct IndexPtr {
pub p: B56,
#[allow(unused)] m: bool,
#[allow(unused)]
m: bool,
pub tag: IndexPtrTag,
}
@@ -143,10 +144,10 @@ impl IndexPtr {
#[derive(Debug, Clone, Copy, Ord, Hash, PartialOrd, Eq, PartialEq)]
pub struct CodeIndex(TypedArenaPtr<IndexPtr>);
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
const_assert!(std::mem::align_of::<CodeIndex>() == 4);
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
const_assert!(std::mem::align_of::<CodeIndex>() == 8);
impl Deref for CodeIndex {
@@ -293,7 +294,8 @@ impl IndexStore {
let (name, arity) = key;
if !ClauseType::is_inbuilt(name, arity) {
self.modules.get(&(atom!("builtins")))
self.modules
.get(&(atom!("builtins")))
.map(|module| module.code_dir.contains_key(&(name, arity)))
.unwrap_or(false)
} else {
@@ -444,11 +446,7 @@ impl IndexStore {
}
}
pub(crate) fn is_dynamic_predicate(
&self,
module_name: Atom,
key: PredicateKey,
) -> bool {
pub(crate) fn is_dynamic_predicate(&self, module_name: Atom, key: PredicateKey) -> bool {
match module_name {
atom!("user") => self
.extensible_predicates

View File

@@ -3,7 +3,6 @@ use crate::atom_table::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::heap_print::*;
use crate::machine::Machine;
use crate::machine::attributed_variables::*;
use crate::machine::copier::*;
use crate::machine::heap::*;
@@ -11,6 +10,7 @@ use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::stack::*;
use crate::machine::streams::*;
use crate::machine::Machine;
use crate::parser::ast::*;
use crate::read::TermWriteResult;
use crate::types::*;
@@ -22,6 +22,7 @@ use indexmap::IndexMap;
use std::convert::TryFrom;
use std::fmt;
use std::ops::{Index, IndexMut};
use std::sync::Arc;
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
@@ -57,14 +58,14 @@ pub enum OnEOF {
}
pub struct MachineState {
pub atom_tbl: AtomTable,
pub atom_tbl: Arc<AtomTable>,
pub arena: Arena,
pub(super) pdl: Vec<HeapCellValue>,
pub(super) s: HeapPtr,
pub(super) s_offset: usize,
pub(super) p: usize,
pub(super) oip: u32, // first internal code ptr
pub(super) iip : u32, // second internal code ptr
pub(super) iip: u32, // second internal code ptr
pub(super) b: usize,
pub(super) b0: usize,
pub(super) e: usize,
@@ -79,7 +80,7 @@ pub struct MachineState {
pub(super) trail: Vec<TrailEntry>,
pub(super) tr: usize,
pub(super) hb: usize,
pub(super) block: usize, // an offset into the OR stack.
pub(super) block: usize, // an offset into the OR stack.
pub(super) scc_block: usize, // an offset into the OR stack for setup_call_cleanup/3.
pub(super) ball: Ball,
pub(super) ball_stack: Vec<Ball>, // save current ball before jumping via, e.g., verify_attr interrupt.
@@ -203,12 +204,12 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
fn push_var_eq_functors<'a>(
heap: &mut Heap,
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) -> Vec<HeapCellValue> {
let mut list_of_var_eqs = vec![];
for (var, binding) in iter {
let var_atom = atom_tbl.build_with(&var.to_string());
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let h = heap.len();
heap.push(atom_as_cell!(atom!("="), 2));
@@ -243,9 +244,11 @@ impl Ball {
pub(super) fn copy_and_align(&self, h: usize) -> Heap {
let diff = self.boundary as i64 - h as i64;
self.stub.iter().cloned().map(|heap_value| {
heap_value - diff
}).collect()
self.stub
.iter()
.cloned()
.map(|heap_value| heap_value - diff)
.collect()
}
}
@@ -418,9 +421,7 @@ impl MachineState {
if self.cwil.count == *limit {
self.cwil.inference_limit_exceeded = true;
return Err(
functor!(atom!("inference_limit_exceeded"), [fixnum(bp)])
);
return Err(functor!(atom!("inference_limit_exceeded"), [fixnum(bp)]));
} else {
self.cwil.count += 1;
}
@@ -430,7 +431,10 @@ impl MachineState {
}
#[allow(dead_code)]
pub(super) fn try_char_list(&mut self, addrs: Vec<HeapCellValue>) -> Result<String, MachineError> {
pub(super) fn try_char_list(
&mut self,
addrs: Vec<HeapCellValue>,
) -> Result<String, MachineError> {
let mut chars = String::new();
for addr in addrs {
@@ -515,18 +519,25 @@ impl MachineState {
mut var_list: Vec<(VarKey, HeapCellValue, usize)>,
singleton_var_list: Vec<HeapCellValue>,
) -> CallResult {
var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2));
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
let list_of_var_eqs = push_var_eq_functors(
&mut self.heap,
var_list.iter().filter_map(|(var_name, var,_)| if var_name.is_anon() { None } else { Some((var_name,var)) }),
&mut self.atom_tbl,
var_list.iter().filter_map(|(var_name, var, _)| {
if var_name.is_anon() {
None
} else {
Some((var_name, var))
}
}),
&self.atom_tbl,
);
let singleton_addr = self.registers[3];
let singletons_offset = heap_loc_as_cell!(
iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter())
);
let singletons_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
singleton_var_list.into_iter()
));
unify_fn!(*self, singletons_offset, singleton_addr);
@@ -535,9 +546,10 @@ impl MachineState {
}
let vars_addr = self.registers[4];
let vars_offset = heap_loc_as_cell!(
iter_to_heap_list(&mut self.heap, var_list.into_iter().map(|(_,cell,_)| cell))
);
let vars_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
var_list.into_iter().map(|(_, cell, _)| cell)
));
unify_fn!(*self, vars_offset, vars_addr);
@@ -546,9 +558,10 @@ impl MachineState {
}
let var_names_addr = self.registers[5];
let var_names_offset = heap_loc_as_cell!(
iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter())
);
let var_names_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
list_of_var_eqs.into_iter()
));
Ok(unify_fn!(*self, var_names_offset, var_names_addr))
}
@@ -589,18 +602,21 @@ impl MachineState {
let singleton_var_list = push_var_eq_functors(
&mut self.heap,
term_write_result.var_dict.iter().filter(|(var_name, binding)| {
if var_name.is_anon() {
return false;
}
term_write_result
.var_dict
.iter()
.filter(|(var_name, binding)| {
if var_name.is_anon() {
return false;
}
if let Some(r) = binding.as_var() {
*singleton_var_set.get(&r).unwrap_or(&false)
} else {
false
}
}),
&mut self.atom_tbl,
if let Some(r) = binding.as_var() {
*singleton_var_set.get(&r).unwrap_or(&false)
} else {
false
}
}),
&self.atom_tbl,
);
for var in term_write_result.var_dict.values_mut() {
@@ -620,13 +636,11 @@ impl MachineState {
self.write_read_term_options(var_list, singleton_var_list)
}
pub fn read_term_from_user_input_eof_handler(&mut self, stream: Stream) -> Result<OnEOF, MachineStub> {
self.eof_action(
self.registers[2],
stream,
atom!("read_term"),
3,
)?;
pub fn read_term_from_user_input_eof_handler(
&mut self,
stream: Stream,
) -> Result<OnEOF, MachineStub> {
self.eof_action(self.registers[2], stream, atom!("read_term"), 3)?;
if stream.options().eof_action() == EOFAction::Reset {
if self.fail == false {
@@ -639,13 +653,15 @@ impl MachineState {
// Safety: the atom_tbl lives for the lifetime of the machine, as does the helper, so the ptr
// will always be valid.
pub fn read_term_from_user_input(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
let atoms_ptr = (&self.atom_tbl.table) as *const indexmap::IndexSet<Atom>;
pub fn read_term_from_user_input(
&mut self,
stream: Stream,
indices: &mut IndexStore,
) -> CallResult {
if let Stream::Readline(ptr) = stream {
unsafe {
let readline = ptr.as_ptr().as_mut().unwrap();
readline.set_atoms_for_completion(atoms_ptr);
readline.set_atoms_for_completion(&self.atom_tbl);
return self.read_term(
stream,
indices,
@@ -663,12 +679,7 @@ impl MachineState {
stream.set_past_end_of_stream(true);
return Ok(OnEOF::Return);
} else if stream.past_end_of_stream() {
self.eof_action(
self.registers[2],
stream,
atom!("read_term"),
3,
)?;
self.eof_action(self.registers[2], stream, atom!("read_term"), 3)?;
if stream.options().eof_action() == EOFAction::Reset {
if self.fail == false {
@@ -709,7 +720,9 @@ impl MachineState {
match &err {
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? {
OnEOF::Return => return self.write_read_term_options(vec![], vec![]),
OnEOF::Return => {
return self.write_read_term_options(vec![], vec![])
}
OnEOF::Continue => continue,
}
}
@@ -762,14 +775,14 @@ impl MachineState {
}
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
var_names.insert(var, VarPtr::from(name.as_str()));
var_names.insert(var, VarPtr::from(&*name.as_str()));
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
debug_assert_eq!(arity, 0);
var_names.insert(var, VarPtr::from(name.as_str()));
var_names.insert(var, VarPtr::from(&*name.as_str()));
}
_ => {
unreachable!();
@@ -850,7 +863,7 @@ impl MachineState {
let mut printer = HCPrinter::new(
&mut self.heap,
&mut self.atom_tbl,
Arc::clone(&self.atom_tbl),
&mut self.stack,
op_dir,
PrinterOutputter::new(),
@@ -898,7 +911,11 @@ impl MachineState {
Ok(Some(printer))
}
pub(super) fn read_predicate_key(&self, name: HeapCellValue, arity: HeapCellValue) -> (Atom, usize) {
pub(super) fn read_predicate_key(
&self,
name: HeapCellValue,
arity: HeapCellValue,
) -> (Atom, usize) {
let name = cell_as_atom!(self.store(self.deref(name)));
let arity = cell_as_fixnum!(self.store(self.deref(arity)));

View File

@@ -1,6 +1,5 @@
use crate::arena::*;
use crate::atom_table::*;
use crate::types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::attributed_variables::*;
@@ -14,6 +13,7 @@ use crate::machine::stack::*;
use crate::machine::unify::*;
use crate::parser::ast::*;
use crate::parser::dashu::{Integer, Rational};
use crate::types::*;
use indexmap::IndexSet;
use num_order::NumOrd;
@@ -51,7 +51,7 @@ impl MachineState {
ball: Ball::new(),
ball_stack: vec![],
lifted_heap: Heap::new(),
interms: vec![Number::default();256],
interms: vec![Number::default(); 256],
cont_pts: Vec::with_capacity(256),
cwil: CWIL::new(),
flags: MachineFlags::default(),
@@ -60,8 +60,8 @@ impl MachineState {
dynamic_mode: FirstOrNext::First,
unify_fn: MachineState::unify,
bind_fn: MachineState::bind,
run_cleaners_fn: |_| { false },
increment_call_count_fn: |_| { Ok(()) },
run_cleaners_fn: |_| false,
increment_call_count_fn: |_| Ok(()),
}
}
@@ -161,9 +161,8 @@ impl MachineState {
key_atom.index as u64,
));
self.trail.push(TrailEntry::from_bytes(
value_cell.into_bytes(),
));
self.trail
.push(TrailEntry::from_bytes(value_cell.into_bytes()));
self.tr += 2;
}
@@ -249,9 +248,7 @@ impl MachineState {
r: Ref,
value: HeapCellValue,
) {
let mut unifier = CompositeUnifierForOccursCheckWithError::from(
DefaultUnifier::from(self),
);
let mut unifier = CompositeUnifierForOccursCheckWithError::from(DefaultUnifier::from(self));
unifier.bind(r, value);
}
@@ -317,9 +314,7 @@ impl MachineState {
}
pub(super) fn unify_with_occurs_check_with_error(&mut self) {
let mut unifier = CompositeUnifierForOccursCheckWithError::from(
DefaultUnifier::from(self),
);
let mut unifier = CompositeUnifierForOccursCheckWithError::from(DefaultUnifier::from(self));
unifier.unify_internal();
}
@@ -381,8 +376,7 @@ impl MachineState {
}
)
}
&mut HeapPtr::PStrChar(h, ref mut n) |
&mut HeapPtr::PStrLocation(h, ref mut n) => {
&mut HeapPtr::PStrChar(h, ref mut n) | &mut HeapPtr::PStrLocation(h, ref mut n) => {
read_heap_cell!(self.heap[h],
(HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom);
@@ -510,7 +504,7 @@ impl MachineState {
} else {
self.pdl.clear();
return Some(
n1.chars().next().cmp(&Some(c2))
n1.as_str().chars().next().cmp(&Some(c2))
.then(Ordering::Greater)
);
}
@@ -540,7 +534,7 @@ impl MachineState {
} else {
self.pdl.clear();
return Some(
Some(c1).cmp(&n2.chars().next())
Some(c1).cmp(&n2.as_str().chars().next())
.then(Ordering::Less)
);
}
@@ -563,7 +557,7 @@ impl MachineState {
} else {
self.pdl.clear();
return Some(
Some(c1).cmp(&n2.chars().next())
Some(c1).cmp(&n2.as_str().chars().next())
.then(Ordering::Less)
);
}
@@ -593,7 +587,7 @@ impl MachineState {
} else {
self.pdl.clear();
return Some(
n1.chars().next().cmp(&Some(c2))
n1.as_str().chars().next().cmp(&Some(c2))
.then(Ordering::Greater)
);
}
@@ -640,7 +634,7 @@ impl MachineState {
// iter2 is continuable, so it
// has a tail in the heap at
// focus+1.
pdl.push(iter2.heap[focus+1]);
pdl.push(iter2.heap[focus + 1]);
return None;
}
@@ -903,8 +897,12 @@ impl MachineState {
let s = string.as_str();
match heap_pstr_iter.compare_pstr_to_string(s) {
Some(PStrPrefixCmpResult { focus, offset, prefix_len }) if prefix_len == s.len() => {
match heap_pstr_iter.compare_pstr_to_string(&*s) {
Some(PStrPrefixCmpResult {
focus,
offset,
prefix_len,
}) if prefix_len == s.len() => {
let focus_addr = self.heap[focus];
read_heap_cell!(focus_addr,
@@ -951,7 +949,10 @@ impl MachineState {
return;
}
Some(PStrPrefixCmpResult { prefix_len: inner_prefix_len, .. }) => {
Some(PStrPrefixCmpResult {
prefix_len: inner_prefix_len,
..
}) => {
prefix_len = inner_prefix_len;
}
None => {
@@ -1003,9 +1004,9 @@ impl MachineState {
self.s_offset = 0;
self.mode = MachineMode::Read;
put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl)
put_partial_string(&mut self.heap, pstr, &self.atom_tbl)
} else {
put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl)
put_complete_string(&mut self.heap, pstr, &self.atom_tbl)
}
}
@@ -1097,7 +1098,7 @@ impl MachineState {
(name, 0, 0)
}
(HeapCellValueTag::Char, c) => {
(self.atom_tbl.build_with(&c.to_string()), 0, 0)
(AtomTable::build_with(&self.atom_tbl, &c.to_string()), 0, 0)
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let stub = functor_stub(atom!("call"), arity + 1);
@@ -1328,7 +1329,7 @@ impl MachineState {
let f_a = if name == atom!(".") && arity == 2 {
self.heap.push(heap_loc_as_cell!(h));
self.heap.push(heap_loc_as_cell!(h+1));
self.heap.push(heap_loc_as_cell!(h + 1));
list_loc_as_cell!(h)
} else {
@@ -1445,7 +1446,7 @@ impl MachineState {
}
}
(HeapCellValueTag::Char, c) => {
let c = self.atom_tbl.build_with(&c.to_string());
let c = AtomTable::build_with(&self.atom_tbl, &c.to_string());
self.try_functor_fabricate_struct(
c,
@@ -1581,8 +1582,7 @@ impl MachineState {
while let Some(iteratee) = heap_pstr_iter.next() {
match iteratee {
PStrIteratee::Char(_, c) =>
chars.push(char_as_cell!(c)),
PStrIteratee::Char(_, c) => chars.push(char_as_cell!(c)),
PStrIteratee::PStrSegment(_, pstr_atom, n) => {
let pstr = PartialString::from(pstr_atom);
chars.extend(pstr.as_str_from(n).chars().map(|c| char_as_cell!(c)));
@@ -1644,10 +1644,7 @@ impl MachineState {
let mut value = unmark_cell_bits!(value);
if value.is_var() {
value = heap_bound_store(
iter.heap,
heap_bound_deref(iter.heap, value),
);
value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value));
if value.is_var() {
return true;
@@ -1656,7 +1653,7 @@ impl MachineState {
if value.is_compound(iter.heap) {
if visited.contains(&value) {
for _ in stack_len .. iter.stack_len() {
for _ in stack_len..iter.stack_len() {
iter.pop_stack();
}
} else {

View File

@@ -2,15 +2,17 @@ pub use crate::arena::*;
pub use crate::atom_table::*;
use crate::heap_print::*;
pub use crate::machine::heap::*;
pub use crate::machine::*;
pub use crate::machine::machine_state::*;
pub use crate::machine::stack::*;
pub use crate::machine::streams::*;
pub use crate::machine::*;
pub use crate::macros::*;
pub use crate::parser::ast::*;
use crate::read::*;
pub use crate::types::*;
use std::sync::Arc;
#[cfg(test)]
use crate::machine::copier::CopierTarget;
@@ -61,7 +63,7 @@ impl MockWAM {
let mut printer = HCPrinter::new(
&mut self.machine_st.heap,
&mut self.machine_st.atom_tbl,
Arc::clone(&self.machine_st.atom_tbl),
&mut self.machine_st.stack,
&self.op_dir,
PrinterOutputter::new(),
@@ -71,11 +73,9 @@ impl MockWAM {
printer.var_names = term_write_result
.var_dict
.into_iter()
.map(|(var, cell)| {
match var {
VarKey::VarPtr(var) => (cell, var.clone()),
VarKey::AnonVar(_) => (cell, VarPtr::from(var.to_string()))
}
.map(|(var, cell)| match var {
VarKey::VarPtr(var) => (cell, var.clone()),
VarKey::AnonVar(_) => (cell, VarPtr::from(var.to_string())),
})
.collect();
@@ -245,7 +245,7 @@ impl Machine {
load_contexts: vec![],
runtime,
#[cfg(feature = "ffi")]
foreign_function_table: Default::default(),
foreign_function_table: Default::default(),
};
let mut lib_path = current_dir();
@@ -266,17 +266,14 @@ impl Machine {
lib_path.clone(),
),
)
.unwrap();
.unwrap();
bootstrapping_compile(
Stream::from_static_string(
LIBRARIES.borrow()["builtins"],
&mut wam.machine_st.arena,
),
Stream::from_static_string(LIBRARIES.borrow()["builtins"], &mut wam.machine_st.arena),
&mut wam,
ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
)
.unwrap();
.unwrap();
if let Some(ref mut builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
load_module(
@@ -300,7 +297,7 @@ impl Machine {
&mut wam,
ListingSource::from_file_and_path(atom!("loader.pl"), lib_path.clone()),
)
.unwrap();
.unwrap();
wam.configure_modules();
@@ -335,6 +332,19 @@ impl Machine {
self.load_file(file.into(), stream);
self.user_output.bytes().map(|b| b.unwrap()).collect()
}
pub fn test_load_string(&mut self, code: &str) -> Vec<u8> {
use std::io::Read;
let stream = Stream::from_owned_string(
code.to_owned(),
&mut self.machine_st.arena,
);
self.load_file("<stdin>".into(), stream);
self.user_output.bytes().map(|b| b.unwrap()).collect()
}
}
#[cfg(test)]
@@ -346,26 +356,11 @@ mod tests {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
op_dir.insert(
(atom!("+"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("-"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("/"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert(
(atom!("="), Fixity::In),
OpDesc::build_with(700, XFX as u8),
);
op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
op_dir.insert((atom!("="), Fixity::In), OpDesc::build_with(700, XFX as u8));
{
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
@@ -582,22 +577,10 @@ mod tests {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
op_dir.insert(
(atom!("+"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("-"), Fixity::In),
OpDesc::build_with(500, YFX as u8),
);
op_dir.insert(
(atom!("*"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert(
(atom!("/"), Fixity::In),
OpDesc::build_with(400, YFX as u8),
);
op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8));
op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
{
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
@@ -688,20 +671,12 @@ mod tests {
wam.heap.push(heap_loc_as_cell!(1));
assert_eq!(
compare_term_test!(
wam,
heap_loc_as_cell!(0),
heap_loc_as_cell!(0)
),
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
Some(Ordering::Equal)
);
assert_eq!(
compare_term_test!(
wam,
heap_loc_as_cell!(0),
atom_as_cell!(atom!("a"))
),
compare_term_test!(wam, heap_loc_as_cell!(0), atom_as_cell!(atom!("a"))),
Some(Ordering::Greater)
);
@@ -724,29 +699,17 @@ mod tests {
wam.heap.push(empty_list_as_cell!());
assert_eq!(
compare_term_test!(
wam,
heap_loc_as_cell!(7),
heap_loc_as_cell!(7)
),
compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
Some(Ordering::Equal)
);
assert_eq!(
compare_term_test!(
wam,
heap_loc_as_cell!(0),
heap_loc_as_cell!(7)
),
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(7)),
Some(Ordering::Greater)
);
assert_eq!(
compare_term_test!(
wam,
empty_list_as_cell!(),
heap_loc_as_cell!(7)
),
compare_term_test!(wam, empty_list_as_cell!(), heap_loc_as_cell!(7)),
Some(Ordering::Less)
);
@@ -769,40 +732,24 @@ mod tests {
);
assert_eq!(
compare_term_test!(
wam,
empty_list_as_cell!(),
atom_as_cell!(atom!("atom"))
),
compare_term_test!(wam, empty_list_as_cell!(), atom_as_cell!(atom!("atom"))),
Some(Ordering::Less)
);
assert_eq!(
compare_term_test!(
wam,
atom_as_cell!(atom!("atom")),
empty_list_as_cell!()
),
compare_term_test!(wam, atom_as_cell!(atom!("atom")), empty_list_as_cell!()),
Some(Ordering::Greater)
);
let one_p_one = HeapCellValue::from(float_alloc!(1.1, &mut wam.arena));
assert_eq!(
compare_term_test!(
wam,
one_p_one,
fixnum_as_cell!(Fixnum::build_with(1))
),
compare_term_test!(wam, one_p_one, fixnum_as_cell!(Fixnum::build_with(1))),
Some(Ordering::Less)
);
assert_eq!(
compare_term_test!(
wam,
fixnum_as_cell!(Fixnum::build_with(1)),
one_p_one
),
compare_term_test!(wam, fixnum_as_cell!(Fixnum::build_with(1)), one_p_one),
Some(Ordering::Greater)
);
}
@@ -821,7 +768,8 @@ mod tests {
all_cells_unmarked(&wam.heap);
wam.heap.clear();
wam.heap.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))]));
wam.heap
.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))]));
assert!(!wam.is_cyclic_term(str_loc_as_cell!(0)));

View File

@@ -6,6 +6,7 @@ pub mod code_walker;
pub mod loader;
pub mod compile;
pub mod copier;
pub mod disjuncts;
pub mod dispatch;
pub mod gc;
pub mod heap;
@@ -16,7 +17,6 @@ pub mod machine_state;
pub mod machine_state_impl;
pub mod mock_wam;
pub mod partial_string;
pub mod disjuncts;
pub mod preprocessor;
pub mod stack;
pub mod streams;
@@ -27,9 +27,9 @@ pub mod unify;
use crate::arena::*;
use crate::arithmetic::*;
use crate::atom_table::*;
use crate::forms::*;
#[cfg(feature = "ffi")]
use crate::ffi::ForeignFunctionTable;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::args::*;
use crate::machine::compile::*;
@@ -163,7 +163,10 @@ pub(crate) fn import_builtin_impls(code_dir: &CodeDir, builtins: &mut Module) {
for key in keys {
let idx = code_dir.get(&key).unwrap();
builtins.code_dir.insert(key, idx.clone());
builtins.module_decl.exports.push(ModuleExport::PredicateKey(key));
builtins
.module_decl
.exports
.push(ModuleExport::PredicateKey(key));
}
}
@@ -194,7 +197,7 @@ impl Machine {
code: &mut self.code,
load_contexts: &mut self.load_contexts,
},
&mut self.machine_st
&mut self.machine_st,
)
}
@@ -206,7 +209,11 @@ impl Machine {
self.machine_st.throw_exception(err);
}
fn run_module_predicate(&mut self, module_name: Atom, key: PredicateKey) -> std::process::ExitCode {
fn run_module_predicate(
&mut self,
module_name: Atom,
key: PredicateKey,
) -> std::process::ExitCode {
if let Some(module) = self.indices.modules.get(&module_name) {
if let Some(ref code_index) = module.code_dir.get(&key) {
let p = code_index.local().unwrap();
@@ -223,9 +230,8 @@ impl Machine {
pub fn load_file(&mut self, path: &str, stream: Stream) {
self.machine_st.registers[1] = stream_as_cell!(stream);
self.machine_st.registers[2] = atom_as_cell!(
self.machine_st.atom_tbl.build_with(path)
);
self.machine_st.registers[2] =
atom_as_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, path));
self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2));
}
@@ -236,10 +242,8 @@ impl Machine {
path_buf.push("src/toplevel.pl");
let path = path_buf.to_str().unwrap();
let toplevel_stream = Stream::from_static_string(
include_str!("../toplevel.pl"),
&mut self.machine_st.arena,
);
let toplevel_stream =
Stream::from_static_string(include_str!("../toplevel.pl"), &mut self.machine_st.arena);
self.load_file(path, toplevel_stream);
@@ -292,19 +296,24 @@ impl Machine {
arg_pstrs.push(put_complete_string(
&mut self.machine_st.heap,
&arg,
&mut self.machine_st.atom_tbl,
&self.machine_st.atom_tbl,
));
}
self.machine_st.registers[1] = heap_loc_as_cell!(
iter_to_heap_list(&mut self.machine_st.heap, arg_pstrs.into_iter())
);
self.machine_st.registers[1] = heap_loc_as_cell!(iter_to_heap_list(
&mut self.machine_st.heap,
arg_pstrs.into_iter()
));
self.run_module_predicate(atom!("$toplevel"), (atom!("$repl"), 1))
}
pub(crate) fn configure_modules(&mut self) {
fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir, arena: &mut Arena) {
fn update_call_n_indices(
loader: &Module,
target_code_dir: &mut CodeDir,
arena: &mut Arena,
) {
for arity in 1..66 {
let key = (atom!("call"), arity);
@@ -349,10 +358,18 @@ impl Machine {
}
for (_, target_module) in self.indices.modules.iter_mut() {
update_call_n_indices(&loader, &mut target_module.code_dir, &mut self.machine_st.arena);
update_call_n_indices(
&loader,
&mut target_module.code_dir,
&mut self.machine_st.arena,
);
}
update_call_n_indices(&loader, &mut self.indices.code_dir, &mut self.machine_st.arena);
update_call_n_indices(
&loader,
&mut self.indices.code_dir,
&mut self.machine_st.arena,
);
self.indices.modules.insert(atom!("loader"), loader);
} else {
@@ -363,56 +380,65 @@ impl Machine {
pub(crate) fn add_impls_to_indices(&mut self) {
let impls_offset = self.code.len() + 3;
self.code.extend(vec![
Instruction::BreakFromDispatchLoop,
Instruction::InstallVerifyAttr,
Instruction::VerifyAttrInterrupt,
Instruction::ExecuteTermGreaterThan,
Instruction::ExecuteTermLessThan,
Instruction::ExecuteTermGreaterThanOrEqual,
Instruction::ExecuteTermLessThanOrEqual,
Instruction::ExecuteTermEqual,
Instruction::ExecuteTermNotEqual,
Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2))),
Instruction::ExecuteAcyclicTerm,
Instruction::ExecuteArg,
Instruction::ExecuteCompare,
Instruction::ExecuteCopyTerm,
Instruction::ExecuteFunctor,
Instruction::ExecuteGround,
Instruction::ExecuteKeySort,
Instruction::ExecuteSort,
Instruction::ExecuteN(1),
Instruction::ExecuteN(2),
Instruction::ExecuteN(3),
Instruction::ExecuteN(4),
Instruction::ExecuteN(5),
Instruction::ExecuteN(6),
Instruction::ExecuteN(7),
Instruction::ExecuteN(8),
Instruction::ExecuteN(9),
Instruction::ExecuteIsAtom(temp_v!(1)),
Instruction::ExecuteIsAtomic(temp_v!(1)),
Instruction::ExecuteIsCompound(temp_v!(1)),
Instruction::ExecuteIsInteger(temp_v!(1)),
Instruction::ExecuteIsNumber(temp_v!(1)),
Instruction::ExecuteIsRational(temp_v!(1)),
Instruction::ExecuteIsFloat(temp_v!(1)),
Instruction::ExecuteIsNonVar(temp_v!(1)),
Instruction::ExecuteIsVar(temp_v!(1))
].into_iter());
self.code.extend(
vec![
Instruction::BreakFromDispatchLoop,
Instruction::InstallVerifyAttr,
Instruction::VerifyAttrInterrupt,
Instruction::ExecuteTermGreaterThan,
Instruction::ExecuteTermLessThan,
Instruction::ExecuteTermGreaterThanOrEqual,
Instruction::ExecuteTermLessThanOrEqual,
Instruction::ExecuteTermEqual,
Instruction::ExecuteTermNotEqual,
Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberGreaterThanOrEqual(
ar_reg!(temp_v!(1)),
ar_reg!(temp_v!(2)),
),
Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2))),
Instruction::ExecuteAcyclicTerm,
Instruction::ExecuteArg,
Instruction::ExecuteCompare,
Instruction::ExecuteCopyTerm,
Instruction::ExecuteFunctor,
Instruction::ExecuteGround,
Instruction::ExecuteKeySort,
Instruction::ExecuteSort,
Instruction::ExecuteN(1),
Instruction::ExecuteN(2),
Instruction::ExecuteN(3),
Instruction::ExecuteN(4),
Instruction::ExecuteN(5),
Instruction::ExecuteN(6),
Instruction::ExecuteN(7),
Instruction::ExecuteN(8),
Instruction::ExecuteN(9),
Instruction::ExecuteIsAtom(temp_v!(1)),
Instruction::ExecuteIsAtomic(temp_v!(1)),
Instruction::ExecuteIsCompound(temp_v!(1)),
Instruction::ExecuteIsInteger(temp_v!(1)),
Instruction::ExecuteIsNumber(temp_v!(1)),
Instruction::ExecuteIsRational(temp_v!(1)),
Instruction::ExecuteIsFloat(temp_v!(1)),
Instruction::ExecuteIsNonVar(temp_v!(1)),
Instruction::ExecuteIsVar(temp_v!(1)),
]
.into_iter(),
);
for (p, instr) in self.code[impls_offset ..].iter().enumerate() {
for (p, instr) in self.code[impls_offset..].iter().enumerate() {
let key = instr.to_name_and_arity();
self.indices.code_dir.insert(
key,
CodeIndex::new(IndexPtr::index(p + impls_offset), &mut self.machine_st.arena),
CodeIndex::new(
IndexPtr::index(p + impls_offset),
&mut self.machine_st.arena,
),
);
}
}
@@ -427,10 +453,9 @@ impl Machine {
let user_output = Stream::stdout(&mut machine_st.arena);
let user_error = Stream::stderr(&mut machine_st.arena);
#[cfg(not(target_os = "wasi"))]
let runtime = tokio::runtime::Runtime::new()
.unwrap();
#[cfg(target_os = "wasi")]
#[cfg(not(target_arch = "wasm32"))]
let runtime = tokio::runtime::Runtime::new().unwrap();
#[cfg(target_arch = "wasm32")]
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
@@ -446,7 +471,7 @@ impl Machine {
load_contexts: vec![],
runtime,
#[cfg(feature = "ffi")]
foreign_function_table: Default::default(),
foreign_function_table: Default::default(),
};
let mut lib_path = current_dir();
@@ -470,10 +495,7 @@ impl Machine {
.unwrap();
bootstrapping_compile(
Stream::from_static_string(
LIBRARIES.borrow()["builtins"],
&mut wam.machine_st.arena,
),
Stream::from_static_string(LIBRARIES.borrow()["builtins"], &mut wam.machine_st.arena),
&mut wam,
ListingSource::from_file_and_path(atom!("builtins.pl"), lib_path.clone()),
)
@@ -526,7 +548,9 @@ impl Machine {
}
pub(crate) fn configure_streams(&mut self) {
self.user_input.options_mut().set_alias_to_atom_opt(Some(atom!("user_input")));
self.user_input
.options_mut()
.set_alias_to_atom_opt(Some(atom!("user_input")));
self.indices
.stream_aliases
@@ -534,7 +558,9 @@ impl Machine {
self.indices.streams.insert(self.user_input);
self.user_output.options_mut().set_alias_to_atom_opt(Some(atom!("user_output")));
self.user_output
.options_mut()
.set_alias_to_atom_opt(Some(atom!("user_output")));
self.indices
.stream_aliases
@@ -564,9 +590,16 @@ impl Machine {
loop {
let indexing_code_ptr = match &indexing_lines[oip] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, v, c, l, s)) => {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
arg,
v,
c,
l,
s,
)) => {
cell = self.deref_register(arg);
self.machine_st.select_switch_on_term_index(cell, v, c, l, s)
self.machine_st
.select_switch_on_term_index(cell, v, c, l, s)
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
let lit = self.machine_st.constant_to_literal(cell);
@@ -676,7 +709,12 @@ impl Machine {
}
);
}
&Instruction::GetPartialString(Level::Shallow, string, RegType::Temp(t), has_tail) => {
&Instruction::GetPartialString(
Level::Shallow,
string,
RegType::Temp(t),
has_tail,
) => {
let cell = self.deref_register(t);
read_heap_cell!(cell,
@@ -707,17 +745,17 @@ impl Machine {
}
);
}
Instruction::GetConstant(..) |
Instruction::GetList(..) |
Instruction::GetStructure(..) |
Instruction::GetPartialString(..) |
&Instruction::UnifyVoid(..) |
&Instruction::UnifyConstant(..) |
&Instruction::GetVariable(..) |
&Instruction::GetValue(..) |
&Instruction::UnifyVariable(..) |
&Instruction::UnifyValue(..) |
&Instruction::UnifyLocalValue(..) => {
Instruction::GetConstant(..)
| Instruction::GetList(..)
| Instruction::GetStructure(..)
| Instruction::GetPartialString(..)
| &Instruction::UnifyVoid(..)
| &Instruction::UnifyConstant(..)
| &Instruction::GetVariable(..)
| &Instruction::GetValue(..)
| &Instruction::UnifyVariable(..)
| &Instruction::UnifyValue(..)
| &Instruction::UnifyLocalValue(..) => {
offset += 1;
}
_ => {
@@ -732,9 +770,10 @@ impl Machine {
fn next_applicable_clause(&mut self, mut offset: usize) -> Option<usize> {
while !self.next_clause_applicable(self.machine_st.p + offset + 1) {
match &self.code[self.machine_st.p + offset] {
&Instruction::DefaultRetryMeElse(o) | &Instruction::RetryMeElse(o) |
&Instruction::DynamicElse(.., NextOrFail::Next(o)) |
&Instruction::DynamicInternalElse(.., NextOrFail::Next(o)) => offset += o,
&Instruction::DefaultRetryMeElse(o)
| &Instruction::RetryMeElse(o)
| &Instruction::DynamicElse(.., NextOrFail::Next(o))
| &Instruction::DynamicInternalElse(.., NextOrFail::Next(o)) => offset += o,
_ => {
return None;
}
@@ -753,14 +792,16 @@ impl Machine {
match &indexing_lines[self.machine_st.oip as usize] {
IndexingLine::IndexedChoice(indexed_choice) => {
match &indexed_choice[(self.machine_st.iip + inner_offset) as usize] {
&IndexedChoiceInstruction::Retry(o) => {
&IndexedChoiceInstruction::Retry(o)
| &IndexedChoiceInstruction::DefaultRetry(o) => {
if self.next_clause_applicable(self.machine_st.p + o) {
return Some(inner_offset);
}
inner_offset += 1;
}
&IndexedChoiceInstruction::Trust(o) => {
&IndexedChoiceInstruction::Trust(o)
| &IndexedChoiceInstruction::DefaultTrust(o) => {
return if self.next_clause_applicable(self.machine_st.p + o) {
Some(inner_offset)
} else {
@@ -813,12 +854,13 @@ impl Machine {
or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len();
or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len = self.machine_st.attr_var_init.attr_var_queue.len();
or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
self.machine_st.b = b;
for i in 0..n {
or_frame[i] = self.machine_st.registers[i+1];
or_frame[i] = self.machine_st.registers[i + 1];
}
self.machine_st.hb = self.machine_st.heap.len();
@@ -844,12 +886,13 @@ impl Machine {
or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len();
or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len = self.machine_st.attr_var_init.attr_var_queue.len();
or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
self.machine_st.b = b;
for i in 0..n {
or_frame[i] = self.machine_st.registers[i+1];
or_frame[i] = self.machine_st.registers[i + 1];
}
self.machine_st.hb = self.machine_st.heap.len();
@@ -912,7 +955,7 @@ impl Machine {
let curr_tr = self.machine_st.tr;
for i in 0..n {
self.machine_st.registers[i+1] = or_frame[i];
self.machine_st.registers[i + 1] = or_frame[i];
}
self.unwind_trail(old_tr, curr_tr);
@@ -956,7 +999,7 @@ impl Machine {
let curr_tr = self.machine_st.tr;
for i in 0..n {
self.machine_st.registers[i+1] = or_frame[i];
self.machine_st.registers[i + 1] = or_frame[i];
}
self.unwind_trail(old_tr, curr_tr);
@@ -999,7 +1042,7 @@ impl Machine {
let n = or_frame.prelude.num_cells;
for i in 0..n {
self.machine_st.registers[i+1] = or_frame[i];
self.machine_st.registers[i + 1] = or_frame[i];
}
let old_tr = or_frame.prelude.tr;
@@ -1038,15 +1081,17 @@ impl Machine {
#[inline(always)]
fn undefined_procedure(&mut self, name: Atom, arity: usize) -> CallResult {
match self.machine_st.flags.unknown {
Unknown::Error => {
Err(self.machine_st.throw_undefined_error(name, arity))
}
Unknown::Error => Err(self.machine_st.throw_undefined_error(name, arity)),
Unknown::Fail => {
self.machine_st.fail = true;
Ok(())
}
Unknown::Warn => {
println!("warning: predicate {}/{} is undefined", name.as_str(), arity);
println!(
"warning: predicate {}/{} is undefined",
name.as_str(),
arity
);
self.machine_st.fail = true;
Ok(())
}
@@ -1091,9 +1136,7 @@ impl Machine {
self.machine_st.dynamic_mode = FirstOrNext::First;
self.machine_st.execute_at_index(arity, compiled_tl_index);
}
IndexPtrTag::Index => {
self.machine_st.execute_at_index(arity, compiled_tl_index)
}
IndexPtrTag::Index => self.machine_st.execute_at_index(arity, compiled_tl_index),
}
Ok(())
@@ -1118,7 +1161,9 @@ impl Machine {
}
} else {
let stub = functor_stub(name, arity);
let err = self.machine_st.module_resolution_error(module_name, name, arity);
let err = self
.machine_st
.module_resolution_error(module_name, name, arity);
Err(self.machine_st.error_form(err, stub))
}
@@ -1144,7 +1189,9 @@ impl Machine {
}
} else {
let stub = functor_stub(name, arity);
let err = self.machine_st.module_resolution_error(module_name, name, arity);
let err = self
.machine_st
.module_resolution_error(module_name, name, arity);
Err(self.machine_st.error_form(err, stub))
}
@@ -1178,12 +1225,16 @@ impl Machine {
let r_c_wo_h_atom = atom!("run_cleaners_without_handling");
let iso_ext = atom!("iso_ext");
RCWH = self.indices.get_predicate_code_index(r_c_w_h_atom, 0, iso_ext)
.and_then(|item| item.local())
.unwrap();
RCWOH = self.indices.get_predicate_code_index(r_c_wo_h_atom, 1, iso_ext)
.and_then(|item| item.local())
.unwrap();
RCWH = self
.indices
.get_predicate_code_index(r_c_w_h_atom, 0, iso_ext)
.and_then(|item| item.local())
.unwrap();
RCWOH = self
.indices
.get_predicate_code_index(r_c_wo_h_atom, 1, iso_ext)
.and_then(|item| item.local())
.unwrap();
});
(RCWH, RCWOH)
@@ -1194,9 +1245,8 @@ impl Machine {
let (idx, arity) = if self.machine_st.effective_block() > prev_block {
(r_c_w_h, 0)
} else {
self.machine_st.registers[1] = fixnum_as_cell!(
Fixnum::build_with(b_cutoff as i64)
);
self.machine_st.registers[1] =
fixnum_as_cell!(Fixnum::build_with(b_cutoff as i64));
(r_c_wo_h, 1)
};
@@ -1263,9 +1313,8 @@ impl Machine {
None => unreachable!(),
}
}
TrailEntryTag::TrailedAttachedValue => {
}
TrailEntryTag::TrailedAttachedValue => {}
}
}
}
}
}

View File

@@ -43,11 +43,10 @@ impl Into<Atom> for PartialString {
impl PartialString {
#[inline]
pub(super) fn new<'a>(src: &'a str, atom_tbl: &mut AtomTable) -> Option<(Self, &'a str)> {
pub(super) fn new<'a>(src: &'a str, atom_tbl: &AtomTable) -> Option<(Self, &'a str)> {
let terminator_idx = scan_for_terminator(src.chars());
let pstr = PartialString(atom_tbl.build_with(&src[.. terminator_idx]));
Some(if terminator_idx < src.as_bytes().len() {
let pstr = PartialString(AtomTable::build_with(&atom_tbl, &src[..terminator_idx]));
Some(if terminator_idx < src.as_bytes().len() {
(pstr, &src[terminator_idx + 1..])
} else {
(pstr, "")
@@ -55,8 +54,8 @@ impl PartialString {
}
#[inline(always)]
pub(crate) fn as_str_from(&self, n: usize) -> &str {
&self.0.as_str()[n..]
pub(crate) fn as_str_from(&self, n: usize) -> AtomString {
self.0.as_str().map(|str| &str[n..])
}
}
@@ -124,11 +123,15 @@ impl<'a> HeapPStrIter<'a> {
let mut final_result = None;
while let Some(PStrIterStep { iteratee, next_hare }) = self.step(self.brent_st.hare) {
while let Some(PStrIterStep {
iteratee,
next_hare,
}) = self.step(self.brent_st.hare)
{
self.brent_st.hare = next_hare;
self.focus = self.heap[iteratee.focus()];
result.focus = iteratee.focus();
result.focus = iteratee.focus();
result.offset = iteratee.offset();
match iteratee {
@@ -151,7 +154,7 @@ impl<'a> HeapPStrIter<'a> {
let s = &s[result.prefix_len..];
if s.len() >= t.len() {
if s.starts_with(t) {
if (&*s).starts_with(&*t) {
result.prefix_len += t.len();
result.offset += t.len();
} else {
@@ -202,7 +205,7 @@ impl<'a> HeapPStrIter<'a> {
self.brent_st.hare = self.orig_focus;
self.brent_st.tortoise = self.orig_focus;
for _ in 0 .. self.brent_st.lam {
for _ in 0..self.brent_st.lam {
self.brent_st.hare = self.step(self.brent_st.hare).unwrap().next_hare;
}
@@ -225,7 +228,7 @@ impl<'a> HeapPStrIter<'a> {
}
PStrIteratee::PStrSegment(_, pstr_atom, n) => {
let pstr = PartialString::from(pstr_atom);
buf += pstr.as_str_from(n);
buf += &*pstr.as_str_from(n);
}
}
}
@@ -238,43 +241,43 @@ impl<'a> HeapPStrIter<'a> {
let mut focus = self.focus;
loop {
read_heap_cell!(focus,
(HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
return true;
}
(HeapCellValueTag::Atom, (name, arity)) => { // TODO: use Str here?
return name == atom!(".") && arity == 2;
}
(HeapCellValueTag::Lis, h) => {
let value = self.heap[h];
let value = heap_bound_store(
self.heap,
heap_bound_deref(self.heap, value),
);
read_heap_cell!(focus,
(HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
return true;
}
(HeapCellValueTag::Atom, (name, arity)) => { // TODO: use Str here?
return name == atom!(".") && arity == 2;
}
(HeapCellValueTag::Lis, h) => {
let value = self.heap[h];
let value = heap_bound_store(
self.heap,
heap_bound_deref(self.heap, value),
);
return read_heap_cell!(value,
(HeapCellValueTag::Atom, (name, arity)) => {
arity == 0 && name.as_char().is_some()
}
(HeapCellValueTag::Char) => {
true
}
_ => {
false
}
);
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if focus == self.heap[h] {
return false;
}
return read_heap_cell!(value,
(HeapCellValueTag::Atom, (name, arity)) => {
arity == 0 && name.as_char().is_some()
}
(HeapCellValueTag::Char) => {
true
}
_ => {
false
}
);
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if focus == self.heap[h] {
return false;
}
focus = self.heap[h];
}
_ => {
return false;
}
);
focus = self.heap[h];
}
_ => {
return false;
}
);
}
}
@@ -381,13 +384,15 @@ impl<'a> HeapPStrIter<'a> {
}
fn pre_cycle_discovery_stepper(&mut self) -> Option<PStrIteratee> {
let PStrIterStep { iteratee, next_hare } =
match self.step(self.brent_st.hare) {
Some(results) => results,
None => {
return None;
}
};
let PStrIterStep {
iteratee,
next_hare,
} = match self.step(self.brent_st.hare) {
Some(results) => results,
None => {
return None;
}
};
self.focus = self.heap[iteratee.focus()];
@@ -421,13 +426,15 @@ impl<'a> HeapPStrIter<'a> {
return None;
}
let PStrIterStep { iteratee, next_hare } =
match self.step(self.brent_st.hare) {
Some(results) => results,
None => {
return None;
}
};
let PStrIterStep {
iteratee,
next_hare,
} = match self.step(self.brent_st.hare) {
Some(results) => results,
None => {
return None;
}
};
self.focus = self.heap[next_hare];
self.brent_st.hare = next_hare;
@@ -515,11 +522,8 @@ impl<'a> Iterator for PStrCharsIter<'a> {
match pstr.as_str_from(n).chars().next() {
Some(c) => {
self.item = Some(PStrIteratee::PStrSegment(
f1,
pstr_atom,
n + c.len_utf8(),
));
self.item =
Some(PStrIteratee::PStrSegment(f1, pstr_atom, n + c.len_utf8()));
return Some(c);
}
@@ -684,8 +688,10 @@ pub fn compare_pstr_prefixes<'a>(
}
}
}
(PStrIteratee::PStrSegment(f1, pstr1_atom, n1),
PStrIteratee::PStrSegment(f2, pstr2_atom, n2)) => {
(
PStrIteratee::PStrSegment(f1, pstr1_atom, n1),
PStrIteratee::PStrSegment(f2, pstr2_atom, n2),
) => {
if pstr1_atom == pstr2_atom && n1 == n2 {
cycle_detection_step(i1, i2, &step_1);
let both_cyclic = cycle_detection_step(i2, i1, &step_2);
@@ -707,7 +713,7 @@ pub fn compare_pstr_prefixes<'a>(
let str2 = pstr2.as_str_from(n2);
match str1.len().cmp(&str2.len()) {
Ordering::Equal if str1 == str2 => {
Ordering::Equal if &*str1 == &*str2 => {
cycle_detection_step(i1, i2, &step_1);
let both_cyclic = cycle_detection_step(i2, i1, &step_2);
@@ -718,8 +724,9 @@ pub fn compare_pstr_prefixes<'a>(
continue;
}
}
Ordering::Less if str2.starts_with(str1) => {
step_2.iteratee = PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len());
Ordering::Less if str2.starts_with(&*str1) => {
step_2.iteratee =
PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len());
let c1_result = cycle_detection_step(i1, i2, &step_1);
r1 = step(i1, i1.brent_st.hare);
@@ -727,8 +734,9 @@ pub fn compare_pstr_prefixes<'a>(
continue;
}
}
Ordering::Greater if str1.starts_with(str2) => {
step_1.iteratee = PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len());
Ordering::Greater if str1.starts_with(&*str2) => {
step_1.iteratee =
PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len());
let c2_result = cycle_detection_step(i2, i1, &step_2);
r2 = step(i2, i2.brent_st.hare);
@@ -737,7 +745,7 @@ pub fn compare_pstr_prefixes<'a>(
}
}
_ => {
return PStrCmpResult::Ordered(str1.cmp(str2));
return PStrCmpResult::Ordered(str1.cmp(&*str2));
}
}
}
@@ -796,11 +804,8 @@ mod test {
fn pstr_iter_tests() {
let mut wam = MockWAM::new();
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
&mut wam.machine_st.atom_tbl,
);
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
@@ -819,11 +824,8 @@ mod test {
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
&mut wam.machine_st.atom_tbl,
);
let pstr_second_var_cell =
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
@@ -836,7 +838,11 @@ mod test {
);
assert_eq!(
iter.next(),
Some(PStrIteratee::PStrSegment(2, cell_as_atom!(pstr_second_cell), 0))
Some(PStrIteratee::PStrSegment(
2,
cell_as_atom!(pstr_second_cell),
0
))
);
assert_eq!(iter.next(), None);
@@ -855,7 +861,11 @@ mod test {
);
assert_eq!(
iter.next(),
Some(PStrIteratee::PStrSegment(2, cell_as_atom!(pstr_second_cell), 0))
Some(PStrIteratee::PStrSegment(
2,
cell_as_atom!(pstr_second_cell),
0
))
);
assert_eq!(iter.next(), None);
@@ -863,10 +873,14 @@ mod test {
}
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0)));
{
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
@@ -892,31 +906,25 @@ mod test {
// construct a structurally similar but different cyclic partial string
// matching the one beginning at wam.machine_st.heap[0].
put_partial_string(
&mut wam.machine_st.heap,
"ab",
&mut wam.machine_st.atom_tbl,
);
put_partial_string(&mut wam.machine_st.heap, "ab", &wam.machine_st.atom_tbl);
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h+2));
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2));
put_partial_string(
&mut wam.machine_st.heap,
"c ",
&mut wam.machine_st.atom_tbl,
);
put_partial_string(&mut wam.machine_st.heap, "c ", &wam.machine_st.atom_tbl);
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h+4));
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 4));
wam.machine_st.heap.push(pstr_second_cell);
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h+6));
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 6));
wam.machine_st.heap.push(pstr_offset_as_cell!(second_h));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0)));
let mut iter1 = HeapPStrIter::new(&wam.machine_st.heap, 0);
let mut iter2 = HeapPStrIter::new(&wam.machine_st.heap, second_h);
@@ -929,11 +937,7 @@ mod test {
wam.machine_st.heap.clear();
put_partial_string(
&mut wam.machine_st.heap,
"abc ",
&mut wam.machine_st.atom_tbl,
);
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[0];
@@ -963,11 +967,8 @@ mod test {
wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"abc",
&mut wam.machine_st.atom_tbl,
);
let cstr_var_cell =
put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2));
@@ -982,30 +983,18 @@ mod test {
unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1));
assert_eq!(
wam.machine_st.heap[2],
char_as_cell!('a'),
);
assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
assert_eq!(
wam.machine_st.heap[4],
char_as_cell!('b'),
);
assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
assert_eq!(
wam.machine_st.heap[6],
char_as_cell!('c'),
);
assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
// test "abc" = [X,Y,Z|D].
wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"abc",
&mut wam.machine_st.atom_tbl,
);
let cstr_var_cell =
put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2)); // X
@@ -1022,35 +1011,20 @@ mod test {
assert_eq!(wam.machine_st.fail, false);
assert_eq!(
wam.machine_st.heap[2],
char_as_cell!('a'),
);
assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
assert_eq!(
wam.machine_st.heap[4],
char_as_cell!('b'),
);
assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
assert_eq!(
wam.machine_st.heap[6],
char_as_cell!('c'),
);
assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
assert_eq!(
wam.machine_st.heap[7],
empty_list_as_cell!(),
);
assert_eq!(wam.machine_st.heap[7], empty_list_as_cell!(),);
// test "d" = [d].
wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"d",
&mut wam.machine_st.atom_tbl,
);
let cstr_var_cell =
put_complete_string(&mut wam.machine_st.heap, "d", &wam.machine_st.atom_tbl);
wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(char_as_cell!('d'));
@@ -1064,11 +1038,8 @@ mod test {
wam.machine_st.heap.clear();
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"abc",
&mut wam.machine_st.atom_tbl,
);
let cstr_var_cell =
put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(heap_loc_as_cell!(2));
@@ -1085,30 +1056,17 @@ mod test {
assert_eq!(wam.machine_st.fail, false);
assert_eq!(
wam.machine_st.heap[2],
char_as_cell!('a'),
);
assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
assert_eq!(
wam.machine_st.heap[4],
char_as_cell!('b'),
);
assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
assert_eq!(
wam.machine_st.heap[6],
char_as_cell!('c'),
);
assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
// test "abcdef" = [a,b,c|X].
wam.machine_st.heap.clear();
put_complete_string(
&mut wam.machine_st.heap,
"abcdef",
&mut wam.machine_st.atom_tbl,
);
put_complete_string(&mut wam.machine_st.heap, "abcdef", &wam.machine_st.atom_tbl);
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
wam.machine_st.heap.push(heap_loc_as_cell!(2));
@@ -1123,7 +1081,10 @@ mod test {
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[4], atom_as_cstr_cell!(atom!("abcdef")));
assert_eq!(wam.machine_st.heap[5], pstr_offset_as_cell!(4));
assert_eq!(wam.machine_st.heap[6], fixnum_as_cell!(Fixnum::build_with("abc".len() as i64)));
assert_eq!(
wam.machine_st.heap[6],
fixnum_as_cell!(Fixnum::build_with("abc".len() as i64))
);
// test iteration on X = [b,c,b,c,b,c,b,c|...] as an offset.
@@ -1132,7 +1093,9 @@ mod test {
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1)));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(1)));
{
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 2);

View File

@@ -12,11 +12,7 @@ use indexmap::IndexSet;
use std::cell::Cell;
use std::convert::TryFrom;
pub(crate) fn to_op_decl(
prec: u16,
spec: Atom,
name: Atom,
) -> Result<OpDecl, CompilationError> {
pub(crate) fn to_op_decl(prec: u16, spec: Atom, name: Atom) -> Result<OpDecl, CompilationError> {
match spec {
atom!("xfx") => Ok(OpDecl::new(OpDesc::build_with(prec, XFX as u8), name)),
atom!("xfy") => Ok(OpDecl::new(OpDesc::build_with(prec, XFY as u8), name)),
@@ -29,19 +25,16 @@ pub(crate) fn to_op_decl(
}
}
fn setup_op_decl(
mut terms: Vec<Term>,
atom_tbl: &mut AtomTable,
) -> Result<OpDecl, CompilationError> {
fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, CompilationError> {
let name = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name,
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()),
Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
_ => return Err(CompilationError::InconsistentEntry),
};
let spec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name,
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()),
Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
_ => return Err(CompilationError::InconsistentEntry),
};
@@ -71,12 +64,14 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
},
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
_ => None,
}.ok_or(CompilationError::InvalidModuleExport)?;
}
.ok_or(CompilationError::InvalidModuleExport)?;
let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None,
}.ok_or(CompilationError::InvalidModuleExport)?;
}
.ok_or(CompilationError::InvalidModuleExport)?;
if *slash == atom!("/") {
Ok((name, arity))
@@ -90,7 +85,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
fn setup_module_export(
mut term: Term,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) -> Result<ModuleExport, CompilationError> {
setup_predicate_indicator(&mut term)
.map(ModuleExport::PredicateKey)
@@ -116,7 +111,7 @@ pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
pub(super) fn setup_module_export_list(
mut export_list: Term,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) -> Result<Vec<ModuleExport>, CompilationError> {
let mut exports = vec![];
@@ -136,7 +131,7 @@ pub(super) fn setup_module_export_list(
fn setup_module_decl(
mut terms: Vec<Term>,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) -> Result<ModuleDecl, CompilationError> {
let export_list = terms.pop().unwrap();
let name = terms.pop().unwrap();
@@ -144,7 +139,8 @@ fn setup_module_decl(
let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None,
}.ok_or(CompilationError::InvalidModuleDecl)?;
}
.ok_or(CompilationError::InvalidModuleDecl)?;
let exports = setup_module_export_list(export_list, atom_tbl)?;
@@ -153,9 +149,7 @@ fn setup_module_decl(
fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> {
match terms.pop().unwrap() {
Term::Clause(_, name, mut terms)
if name == atom!("library") && terms.len() == 1 =>
{
Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl),
@@ -170,13 +164,11 @@ type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
fn setup_qualified_import(
mut terms: Vec<Term>,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) -> Result<UseModuleExport, CompilationError> {
let mut export_list = terms.pop().unwrap();
let module_src = match terms.pop().unwrap() {
Term::Clause(_, name, mut terms)
if name == atom!("library") && terms.len() == 1 =>
{
Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl),
@@ -321,11 +313,11 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
}
(atom!("module"), 2) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?))
Ok(Declaration::Module(setup_module_decl(terms, &atom_tbl)?))
}
(atom!("op"), 3) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?))
Ok(Declaration::Op(setup_op_decl(terms, &atom_tbl)?))
}
(atom!("non_counted_backtracking"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
@@ -334,7 +326,7 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
(atom!("use_module"), 2) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
let (name, exports) = setup_qualified_import(terms, atom_tbl)?;
let (name, exports) = setup_qualified_import(terms, &atom_tbl)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
@@ -384,19 +376,28 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
}
fn tag_with_module_name(module_name: Atom, term: Term) -> Term {
Term::Clause(Cell::default(), atom!(":"), vec![
Term::Literal(Cell::default(), Literal::Atom(module_name)),
term
])
Term::Clause(
Cell::default(),
atom!(":"),
vec![
Term::Literal(Cell::default(), Literal::Atom(module_name)),
term,
],
)
}
let process_term: fn(Atom, Term) -> Term;
let (module_name, key, term) = match term {
Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => {
if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1]) {
if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1])
{
process_term = tag_with_module_name;
(module_name, (name, terms[1].arity() + supp_args), terms.pop().unwrap())
(
module_name,
(name, terms[1].arity() + supp_args),
terms.pop().unwrap(),
)
} else {
arg_terms.push(Term::Clause(cell, atom!(":"), terms));
continue;
@@ -411,10 +412,8 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
let term = match term {
Term::Clause(cell, name, mut terms) => {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
arg_terms.push(process_term(
module_name,
Term::Clause(cell, name, terms),
));
arg_terms
.push(process_term(module_name, Term::Clause(cell, name, terms)));
continue;
}
@@ -427,11 +426,14 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
Term::Literal(cell, Literal::Atom(name)) => {
let idx = loader.get_or_insert_qualified_code_index(module_name, key);
process_term(module_name, Term::Clause(
cell,
name,
vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
))
process_term(
module_name,
Term::Clause(
cell,
name,
vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
),
)
}
term => term,
};
@@ -465,12 +467,7 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name();
let terms = build_meta_predicate_clause(
loader,
module_name,
terms,
meta_specs,
);
let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
return QueryTerm::Clause(
Cell::default(),
@@ -504,12 +501,7 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let terms = build_meta_predicate_clause(
loader,
module_name,
terms,
meta_specs,
);
let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
return QueryTerm::Clause(
Cell::default(),
@@ -532,17 +524,13 @@ pub(crate) struct Preprocessor {
impl Preprocessor {
pub(super) fn new(settings: CodeGenSettings) -> Self {
Preprocessor {
settings,
}
Preprocessor { settings }
}
fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
let classifier = VariableClassifier::new(
self.settings.default_call_policy(),
);
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let (head, var_data) = classifier.classify_fact(term)?;
Ok((Fact { head }, var_data))
@@ -557,21 +545,25 @@ impl Preprocessor {
head: Term,
body: Term,
) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(
self.settings.default_call_policy(),
);
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
match head {
Term::Clause(_, name, terms) => Ok((Rule {
head: (name, terms),
clauses,
}, var_data)),
Term::Literal(_, Literal::Atom(name)) => Ok((Rule {
head: (name, vec![]),
clauses,
}, var_data)),
Term::Clause(_, name, terms) => Ok((
Rule {
head: (name, terms),
clauses,
},
var_data,
)),
Term::Literal(_, Literal::Atom(name)) => Ok((
Rule {
head: (name, vec![]),
clauses,
},
var_data,
)),
_ => Err(CompilationError::InvalidRuleHead),
}
}

View File

@@ -30,12 +30,6 @@ pub struct Stack {
_marker: PhantomData<HeapCellValue>,
}
impl Drop for Stack {
fn drop(&mut self) {
self.buf.deallocate();
}
}
#[derive(Debug)]
pub(crate) struct AndFramePrelude {
pub(crate) num_cells: usize,
@@ -189,7 +183,7 @@ impl Stack {
let frame_size = AndFrame::size_of(num_cells);
unsafe {
let e = self.buf.ptr as usize - self.buf.base as usize;
let e = (*self.buf.ptr.get_mut()) as usize - self.buf.base as usize;
let new_ptr = self.alloc(frame_size);
let mut offset = prelude_size::<AndFramePrelude>();
@@ -213,7 +207,7 @@ impl Stack {
let frame_size = OrFrame::size_of(num_cells);
unsafe {
let b = self.buf.ptr as usize - self.buf.base as usize;
let b = (*self.buf.ptr.get_mut()) as usize - self.buf.base as usize;
let new_ptr = self.alloc(frame_size);
let mut offset = prelude_size::<OrFramePrelude>();
@@ -269,8 +263,8 @@ impl Stack {
pub(crate) fn truncate(&mut self, b: usize) {
let base = self.buf.base as usize + b;
if base < self.buf.ptr as usize {
self.buf.ptr = base as *mut _;
if base < (*self.buf.ptr.get_mut()) as usize {
*self.buf.ptr.get_mut() = base as *mut _;
}
}
}
@@ -290,7 +284,7 @@ mod tests {
assert_eq!(
e,
0// 10 * mem::size_of::<HeapCellValue>() + prelude_size::<AndFrame>()
0 // 10 * mem::size_of::<HeapCellValue>() + prelude_size::<AndFrame>()
);
assert_eq!(and_frame.prelude.num_cells, 10);
@@ -315,7 +309,10 @@ mod tests {
let and_frame = wam.machine_st.stack.index_and_frame_mut(next_e);
for idx in 0..9 {
assert_eq!(and_frame[idx + 1], stack_loc_as_cell!(AndFrame, next_e, idx + 1));
assert_eq!(
and_frame[idx + 1],
stack_loc_as_cell!(AndFrame, next_e, idx + 1)
);
}
let and_frame = wam.machine_st.stack.index_and_frame(e);

View File

@@ -4,13 +4,13 @@ use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::read::*;
#[cfg(feature = "http")]
use crate::http::HttpResponse;
use crate::machine::heap::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
use crate::types::*;
#[cfg(feature = "http")]
use crate::http::HttpResponse;
pub use modular_bitfield::prelude::*;
@@ -23,7 +23,7 @@ use std::hash::Hash;
use std::io;
use std::io::{BufRead, Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
use std::mem;
use std::net::{TcpStream, Shutdown};
use std::net::{Shutdown, TcpStream};
use std::ops::{Deref, DerefMut};
use std::ptr;
@@ -154,8 +154,10 @@ impl StreamLayout<CharReader<InputFileStream>> {
fn position(&mut self) -> Option<u64> {
// stream is the internal CharReader. subtract
// its pending buffer length from position.
self.get_mut().file.seek(SeekFrom::Current(0))
.map(|pos| pos - self.stream.rem_buf_len() as u64)
self.get_mut()
.file
.seek(SeekFrom::Current(0))
.map(|pos| pos - self.stream.rem_buf_len() as u64)
.ok()
}
}
@@ -195,7 +197,7 @@ impl CharRead for StaticStringStream {
#[inline(always)]
fn peek_char(&mut self) -> Option<std::io::Result<char>> {
let pos = self.stream.position() as usize;
self.stream.get_ref()[pos ..].chars().next().map(Ok)
self.stream.get_ref()[pos..].chars().next().map(Ok)
}
#[inline(always)]
@@ -205,7 +207,9 @@ impl CharRead for StaticStringStream {
#[inline(always)]
fn put_back_char(&mut self, c: char) {
self.stream.seek(SeekFrom::Current(- (c.len_utf8() as i64))).unwrap();
self.stream
.seek(SeekFrom::Current(-(c.len_utf8() as i64)))
.unwrap();
}
}
@@ -294,7 +298,7 @@ pub struct HttpWriteStream {
#[cfg(feature = "http")]
impl Debug for HttpWriteStream {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Http Write Stream")
write!(f, "Http Write Stream")
}
}
@@ -302,28 +306,27 @@ impl Debug for HttpWriteStream {
impl Write for HttpWriteStream {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buffer.extend_from_slice(buf);
Ok(buf.len())
self.buffer.extend_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
let (ready, response, cvar) = &**self.response;
let (ready, response, cvar) = &**self.response;
let mut ready = ready.lock().unwrap();
{
let mut response = response.lock().unwrap();
let bytes = bytes::Bytes::copy_from_slice(&self.buffer);
let mut response_ = hyper::Response::builder()
.status(self.status_code);
*response_.headers_mut().unwrap() = self.headers.clone();
*response = Some(response_.body(http_body_util::Full::new(bytes)).unwrap());
}
*ready = true;
cvar.notify_one();
let mut ready = ready.lock().unwrap();
{
let mut response = response.lock().unwrap();
Ok(())
let bytes = bytes::Bytes::copy_from_slice(&self.buffer);
let mut response_ = hyper::Response::builder().status(self.status_code);
*response_.headers_mut().unwrap() = self.headers.clone();
*response = Some(response_.body(http_body_util::Full::new(bytes)).unwrap());
}
*ready = true;
cvar.notify_one();
Ok(())
}
}
@@ -510,7 +513,9 @@ impl Stream {
#[inline]
pub fn from_owned_string(string: String, arena: &mut Arena) -> Stream {
Stream::Byte(arena_alloc!(
StreamLayout::new(CharReader::new(ByteStream(Cursor::new(string.into_bytes())))),
StreamLayout::new(CharReader::new(ByteStream(Cursor::new(
string.into_bytes()
)))),
arena
))
}
@@ -546,7 +551,7 @@ impl Stream {
#[cfg(feature = "http")]
ArenaHeaderTag::HttpReadStream => Stream::HttpRead(TypedArenaPtr::new(ptr as *mut _)),
#[cfg(feature = "http")]
ArenaHeaderTag::HttpWriteStream => Stream::HttpWrite(TypedArenaPtr::new(ptr as *mut _)),
ArenaHeaderTag::HttpWriteStream => Stream::HttpWrite(TypedArenaPtr::new(ptr as *mut _)),
ArenaHeaderTag::ReadlineStream => Stream::Readline(TypedArenaPtr::new(ptr as *mut _)),
ArenaHeaderTag::StaticStringStream => {
Stream::StaticString(TypedArenaPtr::new(ptr as *mut _))
@@ -603,7 +608,7 @@ impl Stream {
#[cfg(feature = "http")]
Stream::HttpRead(ptr) => ptr.header_ptr(),
#[cfg(feature = "http")]
Stream::HttpWrite(ptr) => ptr.header_ptr(),
Stream::HttpWrite(ptr) => ptr.header_ptr(),
Stream::Null(_) => ptr::null(),
Stream::Readline(ptr) => ptr.header_ptr(),
Stream::StandardOutput(ptr) => ptr.header_ptr(),
@@ -728,14 +733,14 @@ impl CharRead for Stream {
Stream::StaticString(src) => (*src).peek_char(),
Stream::Byte(cursor) => (*cursor).peek_char(),
#[cfg(feature = "http")]
Stream::HttpWrite(_) => Some(Err(std::io::Error::new(
Stream::HttpWrite(_) => Some(Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
))),
Stream::OutputFile(_) |
Stream::StandardError(_) |
Stream::StandardOutput(_) |
Stream::Null(_) => Some(Err(std::io::Error::new(
Stream::OutputFile(_)
| Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::Null(_) => Some(Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
))),
@@ -754,14 +759,14 @@ impl CharRead for Stream {
Stream::StaticString(src) => (*src).read_char(),
Stream::Byte(cursor) => (*cursor).read_char(),
#[cfg(feature = "http")]
Stream::HttpWrite(_) => Some(Err(std::io::Error::new(
Stream::HttpWrite(_) => Some(Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
))),
Stream::OutputFile(_) |
Stream::StandardError(_) |
Stream::StandardOutput(_) |
Stream::Null(_) => Some(Err(std::io::Error::new(
Stream::OutputFile(_)
| Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::Null(_) => Some(Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
))),
@@ -780,11 +785,11 @@ impl CharRead for Stream {
Stream::StaticString(src) => src.put_back_char(c),
Stream::Byte(cursor) => cursor.put_back_char(c),
#[cfg(feature = "http")]
Stream::HttpWrite(_) => {}
Stream::OutputFile(_) |
Stream::StandardError(_) |
Stream::StandardOutput(_) |
Stream::Null(_) => {}
Stream::HttpWrite(_) => {}
Stream::OutputFile(_)
| Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::Null(_) => {}
}
}
@@ -800,11 +805,11 @@ impl CharRead for Stream {
Stream::StaticString(ref mut src) => src.consume(nread),
Stream::Byte(ref mut cursor) => cursor.consume(nread),
#[cfg(feature = "http")]
Stream::HttpWrite(_) => {}
Stream::OutputFile(_) |
Stream::StandardError(_) |
Stream::StandardOutput(_) |
Stream::Null(_) => {}
Stream::HttpWrite(_) => {}
Stream::OutputFile(_)
| Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::Null(_) => {}
}
}
}
@@ -823,17 +828,17 @@ impl Read for Stream {
Stream::StaticString(src) => (*src).read(buf),
Stream::Byte(cursor) => (*cursor).read(buf),
#[cfg(feature = "http")]
Stream::HttpWrite(_) => Err(std::io::Error::new(
Stream::HttpWrite(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
)),
Stream::OutputFile(_)
| Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::Null(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
)),
| Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::Null(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
)),
};
bytes_read
@@ -851,16 +856,16 @@ impl Write for Stream {
Stream::StandardOutput(stream) => stream.write(buf),
Stream::StandardError(stream) => stream.write(buf),
#[cfg(feature = "http")]
Stream::HttpWrite(ref mut stream) => stream.get_mut().write(buf),
Stream::HttpWrite(ref mut stream) => stream.get_mut().write(buf),
#[cfg(feature = "http")]
Stream::HttpRead(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::WriteToInputStream,
)),
Stream::StaticString(_) |
Stream::Readline(_) |
Stream::InputFile(..) |
Stream::Null(_) => Err(std::io::Error::new(
Stream::StaticString(_)
| Stream::Readline(_)
| Stream::InputFile(..)
| Stream::Null(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::WriteToInputStream,
)),
@@ -877,16 +882,16 @@ impl Write for Stream {
Stream::StandardError(stream) => stream.stream.flush(),
Stream::StandardOutput(stream) => stream.stream.flush(),
#[cfg(feature = "http")]
Stream::HttpWrite(ref mut stream) => stream.stream.get_mut().flush(),
#[cfg(feature = "http")]
Stream::HttpWrite(ref mut stream) => stream.stream.get_mut().flush(),
#[cfg(feature = "http")]
Stream::HttpRead(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::FlushToInputStream,
)),
Stream::StaticString(_) |
Stream::Readline(_) |
Stream::InputFile(_) |
Stream::Null(_) => Err(std::io::Error::new(
Stream::StaticString(_)
| Stream::Readline(_)
| Stream::InputFile(_)
| Stream::Null(_) => Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::FlushToInputStream,
)),
@@ -898,8 +903,10 @@ impl Write for Stream {
enum StreamError {
PeekByteFailed,
PeekByteFromNonPeekableStream,
#[allow(unused)] PeekCharFailed,
#[allow(unused)] PeekCharFromNonPeekableStream,
#[allow(unused)]
PeekCharFailed,
#[allow(unused)]
PeekCharFromNonPeekableStream,
ReadFromOutputStream,
WriteToInputStream,
FlushToInputStream,
@@ -958,7 +965,11 @@ impl PartialEq for Stream {
impl Eq for Stream {}
fn cursor_position<T>(past_end_of_stream: &mut bool, cursor: &Cursor<T>, cursor_len: u64) -> AtEndOfStream {
fn cursor_position<T>(
past_end_of_stream: &mut bool,
cursor: &Cursor<T>,
cursor_len: u64,
) -> AtEndOfStream {
let position = cursor.position();
let at_end_of_stream = match position.cmp(&cursor_len) {
@@ -984,17 +995,10 @@ impl Stream {
Stream::StaticString(string_stream_layout) => {
Some(string_stream_layout.stream.stream.position())
}
Stream::InputFile(file_stream) => {
file_stream.position()
}
Stream::InputFile(file_stream) => file_stream.position(),
#[cfg(feature = "tls")]
Stream::NamedTls(..) => {
Some(0)
}
Stream::NamedTcp(..)
| Stream::Readline(..) => {
Some(0)
}
Stream::NamedTls(..) => Some(0),
Stream::NamedTcp(..) | Stream::Readline(..) => Some(0),
_ => None,
};
@@ -1011,7 +1015,11 @@ impl Stream {
..
} = &mut **stream_layout;
stream.get_mut().file.seek(SeekFrom::Start(position)).unwrap();
stream
.get_mut()
.file
.seek(SeekFrom::Start(position))
.unwrap();
stream.reset_buffer(); // flush the internal buffer.
if let Ok(metadata) = stream.get_ref().file.metadata() {
@@ -1127,9 +1135,7 @@ impl Stream {
}
}
}
_ => {
AtEndOfStream::Not
}
_ => AtEndOfStream::Not,
}
}
@@ -1153,14 +1159,16 @@ impl Stream {
#[cfg(feature = "tls")]
Stream::NamedTls(..) => atom!("read_append"),
Stream::Byte(_)
| Stream::Readline(_)
| Stream::StaticString(_)
| Stream::InputFile(..) => atom!("read"),
| Stream::Readline(_)
| Stream::StaticString(_)
| Stream::InputFile(..) => atom!("read"),
Stream::NamedTcp(..) => atom!("read_append"),
Stream::OutputFile(file) if file.is_append => atom!("append"),
#[cfg(feature = "http")]
Stream::HttpWrite(_) => atom!("write"),
Stream::OutputFile(_) | Stream::StandardError(_) | Stream::StandardOutput(_) => atom!("write"),
Stream::OutputFile(_) | Stream::StandardError(_) | Stream::StandardOutput(_) => {
atom!("write")
}
Stream::Null(_) => atom!(""),
}
}
@@ -1182,11 +1190,7 @@ impl Stream {
}
#[inline]
pub(crate) fn from_tcp_stream(
address: Atom,
tcp_stream: TcpStream,
arena: &mut Arena,
) -> Self {
pub(crate) fn from_tcp_stream(address: Atom, tcp_stream: TcpStream, arena: &mut Arena) -> Self {
tcp_stream.set_read_timeout(None).unwrap();
tcp_stream.set_write_timeout(None).unwrap();
@@ -1234,20 +1238,20 @@ impl Stream {
#[cfg(feature = "http")]
#[inline]
pub(crate) fn from_http_sender(
response: TypedArenaPtr<HttpResponse>,
status_code: u16,
headers: hyper::HeaderMap,
arena: &mut Arena,
response: TypedArenaPtr<HttpResponse>,
status_code: u16,
headers: hyper::HeaderMap,
arena: &mut Arena,
) -> Self {
Stream::HttpWrite(arena_alloc!(
StreamLayout::new(CharReader::new(HttpWriteStream {
response,
status_code,
headers,
buffer: Vec::new(),
})),
arena
))
Stream::HttpWrite(arena_alloc!(
StreamLayout::new(CharReader::new(HttpWriteStream {
response,
status_code,
headers,
buffer: Vec::new(),
})),
arena
))
}
#[inline]
@@ -1282,11 +1286,9 @@ impl Stream {
match stream {
Stream::NamedTcp(ref mut tcp_stream) => {
tcp_stream.inner_mut().tcp_stream.shutdown(Shutdown::Both)
},
#[cfg(feature = "tls")]
Stream::NamedTls(ref mut tls_stream) => {
tls_stream.inner_mut().tls_stream.shutdown()
}
#[cfg(feature = "tls")]
Stream::NamedTls(ref mut tls_stream) => tls_stream.inner_mut().tls_stream.shutdown(),
#[cfg(feature = "http")]
Stream::HttpRead(ref mut http_stream) => {
unsafe {
@@ -1297,14 +1299,14 @@ impl Stream {
Ok(())
}
#[cfg(feature = "http")]
Stream::HttpWrite(ref mut http_stream) => {
Stream::HttpWrite(ref mut http_stream) => {
unsafe {
http_stream.set_tag(ArenaHeaderTag::Dropped);
std::ptr::drop_in_place(&mut http_stream.inner_mut().buffer as *mut _);
}
Ok(())
}
}
Stream::InputFile(mut file_stream) => {
// close the stream by dropping the inner File.
unsafe {
@@ -1323,7 +1325,7 @@ impl Stream {
Ok(())
}
_ => Ok(())
_ => Ok(()),
}
}
@@ -1344,10 +1346,10 @@ impl Stream {
#[cfg(feature = "http")]
Stream::HttpRead(..) => true,
Stream::NamedTcp(..)
| Stream::Byte(_)
| Stream::Readline(_)
| Stream::StaticString(_)
| Stream::InputFile(..) => true,
| Stream::Byte(_)
| Stream::Readline(_)
| Stream::StaticString(_)
| Stream::InputFile(..) => true,
_ => false,
}
}
@@ -1360,10 +1362,10 @@ impl Stream {
#[cfg(feature = "http")]
Stream::HttpWrite(..) => true,
Stream::StandardError(_)
| Stream::StandardOutput(_)
| Stream::NamedTcp(..)
| Stream::Byte(_)
| Stream::OutputFile(..) => true,
| Stream::StandardOutput(_)
| Stream::NamedTcp(..)
| Stream::Byte(_)
| Stream::OutputFile(..) => true,
_ => false,
}
}
@@ -1381,7 +1383,12 @@ impl Stream {
return true;
}
Stream::InputFile(ref mut file_stream) => {
file_stream.stream.get_mut().file.seek(SeekFrom::Start(0)).unwrap();
file_stream
.stream
.get_mut()
.file
.seek(SeekFrom::Start(0))
.unwrap();
return true;
}
Stream::Readline(ref mut readline_stream) => {
@@ -1410,17 +1417,13 @@ impl Stream {
_ => Err(std::io::Error::new(ErrorKind::UnexpectedEof, "end of file")),
}
}
Stream::InputFile(ref mut file) => {
match file.peek_byte() {
Some(result) => {
Ok(result?)
}
_ => Err(std::io::Error::new(
ErrorKind::UnexpectedEof,
StreamError::PeekByteFailed,
)),
}
}
Stream::InputFile(ref mut file) => match file.peek_byte() {
Some(result) => Ok(result?),
_ => Err(std::io::Error::new(
ErrorKind::UnexpectedEof,
StreamError::PeekByteFailed,
)),
},
Stream::Readline(ref mut stream) => stream.stream.peek_byte(),
Stream::NamedTcp(ref mut stream) => {
let mut b = [0u8; 1];
@@ -1663,7 +1666,10 @@ impl MachineState {
}
}
pub(crate) fn open_parsing_stream(&mut self, mut stream: Stream) -> Result<Stream, ParserError> {
pub(crate) fn open_parsing_stream(
&mut self,
mut stream: Stream,
) -> Result<Stream, ParserError> {
match stream.peek_char() {
None => Ok(stream), // empty stream is handled gracefully by Lexer::eof
Some(Err(e)) => Err(ParserError::IO(e)),
@@ -1687,7 +1693,7 @@ impl MachineState {
arity: usize,
) -> MachineStub {
let stub = functor_stub(caller, arity);
let err = self.permission_error(
let err = self.permission_error(
perm,
err_atom,
if let Some(alias) = stream.options().get_alias() {
@@ -1723,7 +1729,7 @@ impl MachineState {
stub_arity: usize,
) -> MachineStub {
let stub = functor_stub(stub_name, stub_arity);
let err = self.permission_error(Permission::Open, atom!("source_sink"), culprit);
let err = self.permission_error(Permission::Open, atom!("source_sink"), culprit);
self.error_form(err, stub)
}
@@ -1847,7 +1853,7 @@ impl MachineState {
}
};
let file = match open_options.open(file_spec.as_str()) {
let file = match open_options.open(&*file_spec.as_str()) {
Ok(file) => file,
Err(err) => {
match err.kind() {
@@ -1855,15 +1861,18 @@ impl MachineState {
// 8.11.5.3j)
let stub = functor_stub(atom!("open"), 4);
let err = self.existence_error(
ExistenceError::SourceSink(self[temp_v!(1)]),
);
let err =
self.existence_error(ExistenceError::SourceSink(self[temp_v!(1)]));
return Err(self.error_form(err, stub));
}
ErrorKind::PermissionDenied => {
// 8.11.5.3k)
return Err(self.open_permission_error(self.registers[1], atom!("open"), 4));
return Err(self.open_permission_error(
self.registers[1],
atom!("open"),
4,
));
}
_ => {
let stub = functor_stub(atom!("open"), 4);

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
use crate::forms::*;
use crate::machine::*;
use crate::machine::load_state::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::*;
use crate::parser::ast::*;
use crate::parser::parser::*;
use crate::read::devour_whitespace;
@@ -45,7 +45,10 @@ impl<'a> BootstrappingTermStream<'a> {
listing_src: ListingSource,
) -> Self {
let parser = Parser::new(stream, machine_st);
Self { parser, listing_src }
Self {
parser,
listing_src,
}
}
}
@@ -101,7 +104,7 @@ impl<TS> LoadStatePayload<TS> {
non_counted_bt_preds: IndexSet::with_hasher(FxBuildHasher::default()),
predicates: predicate_queue![],
clause_clauses: vec![],
}
}
}
}
@@ -122,20 +125,18 @@ impl TermStream for LiveTermStream {
}
}
pub struct InlineTermStream {
}
pub struct InlineTermStream {}
impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
Err(CompilationError::from(ParserError::unexpected_eof()))
Err(CompilationError::from(ParserError::unexpected_eof()))
}
fn eof(&mut self) -> Result<bool, CompilationError> {
Ok(true)
Ok(true)
}
fn listing_src(&self) -> &ListingSource {
&ListingSource::User
&ListingSource::User
}
}

View File

@@ -1,9 +1,9 @@
use crate::arena::*;
use crate::forms::*;
use crate::heap_iter::stackful_preorder_iter;
use crate::machine::*;
use crate::machine::machine_state::*;
use crate::machine::partial_string::*;
use crate::machine::*;
use crate::types::*;
use std::cmp::Ordering;
@@ -191,8 +191,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
machine_st.pdl.push(pstr_iter1.focus);
}
}
continuable @ PStrCmpResult::FirstIterContinuable(iteratee) |
continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
continuable @ PStrCmpResult::FirstIterContinuable(iteratee)
| continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
if continuable.is_second_iter() {
std::mem::swap(&mut pstr_iter1, &mut pstr_iter2);
}
@@ -440,10 +440,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
}
fn unify_big_num<N>(&mut self, n1: TypedArenaPtr<N>, value: HeapCellValue)
where N: PartialEq<Rational>
+ PartialEq<Integer>
+ PartialEq<i64>
+ ArenaAllocated
where
N: PartialEq<Rational> + PartialEq<Integer> + PartialEq<i64> + ArenaAllocated,
{
if let Some(r) = value.as_var() {
Self::bind(self, r, typed_arena_ptr_as_cell!(n1));

View File

@@ -88,7 +88,7 @@ macro_rules! cell_as_atom_cell {
macro_rules! cell_as_f64_ptr {
($cell:expr) => {{
let offset = $cell.get_value() as usize;
F64Ptr::from_offset(offset)
F64Ptr::from_offset(F64Offset::new(offset))
}};
}
@@ -236,12 +236,14 @@ macro_rules! cell_as_stream {
}
macro_rules! cell_as_load_state_payload {
($cell:expr) => { unsafe {
let ptr = cell_as_untyped_arena_ptr!($cell);
let ptr = std::mem::transmute::<_, *mut LiveLoadState>(ptr.payload_offset());
($cell:expr) => {
unsafe {
let ptr = cell_as_untyped_arena_ptr!($cell);
let ptr = std::mem::transmute::<_, *mut LiveLoadState>(ptr.payload_offset());
TypedArenaPtr::new(ptr)
}};
TypedArenaPtr::new(ptr)
}
};
}
macro_rules! match_untyped_arena_ptr_pat_body {
@@ -258,13 +260,15 @@ macro_rules! match_untyped_arena_ptr_pat_body {
$code
}};
($ptr:ident, OssifiedOpDir, $n:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut OssifiedOpDir>($ptr.payload_offset()) };
let payload_ptr =
unsafe { std::mem::transmute::<_, *mut OssifiedOpDir>($ptr.payload_offset()) };
let $n = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)]
$code
}};
($ptr:ident, LiveLoadState, $n:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut LiveLoadState>($ptr.payload_offset()) };
let payload_ptr =
unsafe { std::mem::transmute::<_, *mut LiveLoadState>($ptr.payload_offset()) };
let $n = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)]
$code
@@ -275,21 +279,24 @@ macro_rules! match_untyped_arena_ptr_pat_body {
$code
}};
($ptr:ident, TcpListener, $listener:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut TcpListener>($ptr.payload_offset()) };
let payload_ptr =
unsafe { std::mem::transmute::<_, *mut TcpListener>($ptr.payload_offset()) };
#[allow(unused_mut)]
let mut $listener = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)]
$code
}};
($ptr:ident, HttpListener, $listener:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut HttpListener>($ptr.payload_offset()) };
let payload_ptr =
unsafe { std::mem::transmute::<_, *mut HttpListener>($ptr.payload_offset()) };
#[allow(unused_mut)]
let mut $listener = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)]
$code
}};
($ptr:ident, HttpResponse, $listener:ident, $code:expr) => {{
let payload_ptr = unsafe { std::mem::transmute::<_, *mut HttpResponse>($ptr.payload_offset()) };
let payload_ptr =
unsafe { std::mem::transmute::<_, *mut HttpResponse>($ptr.payload_offset()) };
#[allow(unused_mut)]
let mut $listener = TypedArenaPtr::new(payload_ptr);
#[allow(unused_braces)]
@@ -297,7 +304,8 @@ macro_rules! match_untyped_arena_ptr_pat_body {
}};
($ptr:ident, IndexPtr, $ip:ident, $code:expr) => {{
#[allow(unused_mut)]
let mut $ip = TypedArenaPtr::new(unsafe { std::mem::transmute::<_, *mut IndexPtr>($ptr.get_ptr()) });
let mut $ip =
TypedArenaPtr::new(unsafe { std::mem::transmute::<_, *mut IndexPtr>($ptr.get_ptr()) });
#[allow(unused_braces)]
$code
}};
@@ -315,7 +323,7 @@ macro_rules! match_untyped_arena_ptr_pat {
| ArenaHeaderTag::NamedTcpStream
| ArenaHeaderTag::NamedTlsStream
| ArenaHeaderTag::HttpReadStream
| ArenaHeaderTag::HttpWriteStream
| ArenaHeaderTag::HttpWriteStream
| ArenaHeaderTag::ReadlineStream
| ArenaHeaderTag::StaticStringStream
| ArenaHeaderTag::ByteStream
@@ -323,10 +331,10 @@ macro_rules! match_untyped_arena_ptr_pat {
| ArenaHeaderTag::StandardErrorStream
};
(IndexPtr) => {
ArenaHeaderTag::IndexPtrUndefined |
ArenaHeaderTag::IndexPtrDynamicUndefined |
ArenaHeaderTag::IndexPtrDynamicIndex |
ArenaHeaderTag::IndexPtrIndex
ArenaHeaderTag::IndexPtrUndefined
| ArenaHeaderTag::IndexPtrDynamicUndefined
| ArenaHeaderTag::IndexPtrDynamicIndex
| ArenaHeaderTag::IndexPtrIndex
};
($tag:ident) => {
ArenaHeaderTag::$tag
@@ -347,71 +355,71 @@ macro_rules! match_untyped_arena_ptr {
}
macro_rules! read_heap_cell_pat_body {
($cell:ident, Cons, $n:ident, $code:expr) => ({
($cell:ident, Cons, $n:ident, $code:expr) => {{
let $n = cell_as_untyped_arena_ptr!($cell);
#[allow(unused_braces)]
$code
});
($cell:ident, F64, $n:ident, $code:expr) => ({
}};
($cell:ident, F64, $n:ident, $code:expr) => {{
let $n = cell_as_f64_ptr!($cell);
#[allow(unused_braces)]
$code
});
($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => ({
}};
($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => {{
let ($name, $arity) = cell_as_atom_cell!($cell).get_name_and_arity();
#[allow(unused_braces)]
$code
});
($cell:ident, PStr, $atom:ident, $code:expr) => ({
}};
($cell:ident, PStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell);
#[allow(unused_braces)]
$code
});
($cell:ident, CStr, $atom:ident, $code:expr) => ({
}};
($cell:ident, CStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell);
#[allow(unused_braces)]
$code
});
($cell:ident, CStr | PStr, $atom:ident, $code:expr) => ({
}};
($cell:ident, CStr | PStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell);
#[allow(unused_braces)]
$code
});
($cell:ident, PStr | CStr, $atom:ident, $code:expr) => ({
}};
($cell:ident, PStr | CStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell);
#[allow(unused_braces)]
$code
});
($cell:ident, Fixnum, $value:ident, $code:expr) => ({
}};
($cell:ident, Fixnum, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)]
$code
});
($cell:ident, CutPoint, $value:ident, $code:expr) => ({
}};
($cell:ident, CutPoint, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)]
$code
});
($cell:ident, Fixnum | CutPoint, $value:ident, $code:expr) => ({
}};
($cell:ident, Fixnum | CutPoint, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)]
$code
});
($cell:ident, CutPoint | Fixnum, $value:ident, $code:expr) => ({
}};
($cell:ident, CutPoint | Fixnum, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)]
$code
});
($cell:ident, Char, $value:ident, $code:expr) => ({
}};
($cell:ident, Char, $value:ident, $code:expr) => {{
let $value = unsafe { char::from_u32_unchecked($cell.get_value() as u32) };
#[allow(unused_braces)]
$code
});
($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => ({
}};
($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => {{
let $value = $cell.get_value() as usize;
#[allow(unused_braces)]
$code
});
}};
}
macro_rules! read_heap_cell_pat {
@@ -596,7 +604,9 @@ macro_rules! index_store {
IndexStore {
code_dir: $code_dir,
extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()),
local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
FxBuildHasher::default(),
),
global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()),
goal_expansion_indices: GoalExpansionIndices::with_hasher(FxBuildHasher::default()),
meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),

View File

@@ -10,6 +10,7 @@ use std::hash::{Hash, Hasher};
use std::io::{Error as IOError, ErrorKind};
use std::ops::{Deref, Neg};
use std::rc::Rc;
use std::sync::Arc;
use std::vec::Vec;
use crate::parser::dashu::{Integer, Rational};
@@ -258,7 +259,8 @@ impl GenContext {
pub struct OpDesc {
prec: B11,
spec: B8,
#[allow(unused)] padding: B13,
#[allow(unused)]
padding: B13,
}
impl OpDesc {
@@ -417,13 +419,13 @@ pub enum ParserError {
impl ParserError {
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
match self {
&ParserError::BackQuotedString(line_num, col_num) |
&ParserError::IncompleteReduction(line_num, col_num) |
&ParserError::MissingQuote(line_num, col_num) |
&ParserError::NonPrologChar(line_num, col_num) |
&ParserError::ParseBigInt(line_num, col_num) |
&ParserError::UnexpectedChar(_, line_num, col_num) |
&ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
&ParserError::BackQuotedString(line_num, col_num)
| &ParserError::IncompleteReduction(line_num, col_num)
| &ParserError::MissingQuote(line_num, col_num)
| &ParserError::NonPrologChar(line_num, col_num)
| &ParserError::ParseBigInt(line_num, col_num)
| &ParserError::UnexpectedChar(_, line_num, col_num)
| &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
_ => None,
}
}
@@ -432,8 +434,12 @@ impl ParserError {
match self {
ParserError::BackQuotedString(..) => atom!("back_quoted_string"),
ParserError::IncompleteReduction(..) => atom!("incomplete_reduction"),
ParserError::InvalidSingleQuotedCharacter(..) => atom!("invalid_single_quoted_character"),
ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => atom!("unexpected_end_of_file"),
ParserError::InvalidSingleQuotedCharacter(..) => {
atom!("invalid_single_quoted_character")
}
ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => {
atom!("unexpected_end_of_file")
}
ParserError::IO(_) => atom!("input_output_error"),
ParserError::LexicalError(_) => atom!("lexical_error"),
ParserError::MissingQuote(..) => atom!("missing_quote"),
@@ -522,9 +528,12 @@ pub enum Fixity {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct Fixnum {
num: B56,
#[allow(unused)] f: bool,
#[allow(unused)] m: bool,
#[allow(unused)] tag: B6,
#[allow(unused)]
f: bool,
#[allow(unused)]
m: bool,
#[allow(unused)]
tag: B6,
}
impl Fixnum {
@@ -623,7 +632,7 @@ impl fmt::Display for Literal {
}
impl Literal {
pub fn to_atom(&self, atom_tbl: &mut AtomTable) -> Option<Atom> {
pub fn to_atom(&self, atom_tbl: &Arc<AtomTable>) -> Option<Atom> {
match self {
Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)),
_ => None,
@@ -631,7 +640,6 @@ impl Literal {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VarPtr(Rc<RefCell<Var>>);

View File

@@ -20,7 +20,7 @@ use std::str;
pub struct CharReader<R> {
inner: R,
buf: SmallVec<[u8;32]>,
buf: SmallVec<[u8; 32]>,
pos: usize,
}
@@ -78,7 +78,7 @@ pub trait CharRead {
self.consume(c.len_utf8());
Some(Ok(c))
}
result => result
result => result,
}
}
@@ -161,9 +161,7 @@ impl<R: Read> CharRead for CharReader<R> {
return Some(Ok(c));
}
Err(e) => {
e
}
Err(e) => e,
};
if buf.len() - e.valid_up_to() >= 4 {
@@ -192,13 +190,15 @@ impl<R: Read> CharRead for CharReader<R> {
// the buffer, it will be returned on the next
// loop.
return Some(Err(io::Error::new(io::ErrorKind::InvalidData,
BadUtf8Error { bytes: badbytes })));
return Some(Err(io::Error::new(
io::ErrorKind::InvalidData,
BadUtf8Error { bytes: badbytes },
)));
} else {
if self.pos >= self.buf.len() {
return None;
} else if self.buf.len() - self.pos >= 4 {
return match str::from_utf8(&self.buf[self.pos .. e.valid_up_to()]) {
return match str::from_utf8(&self.buf[self.pos..e.valid_up_to()]) {
Ok(s) => {
let mut chars = s.chars();
let c = chars.next().unwrap();
@@ -206,10 +206,12 @@ impl<R: Read> CharRead for CharReader<R> {
Some(Ok(c))
}
Err(e) => {
let badbytes = self.buf[self.pos .. e.valid_up_to()].to_vec();
let badbytes = self.buf[self.pos..e.valid_up_to()].to_vec();
Some(Err(io::Error::new(io::ErrorKind::InvalidData,
BadUtf8Error { bytes: badbytes })))
Some(Err(io::Error::new(
io::ErrorKind::InvalidData,
BadUtf8Error { bytes: badbytes },
)))
}
};
} else {
@@ -223,7 +225,7 @@ impl<R: Read> CharRead for CharReader<R> {
let buf_len = self.buf.len();
let mut word = [0u8;4];
let mut word = [0u8; 4];
let word_slice = &mut word[buf_len..4];
match self.inner.read(word_slice) {
@@ -250,7 +252,7 @@ impl<R: Read> CharRead for CharReader<R> {
let c_len = c.len_utf8();
let mut shifted_slice = [0u8; 32];
shifted_slice[0..src_len].copy_from_slice(&self.buf[self.pos .. self.buf.len()]);
shifted_slice[0..src_len].copy_from_slice(&self.buf[self.pos..self.buf.len()]);
self.buf.resize(c_len, 0);
self.buf.extend_from_slice(&shifted_slice[0..src_len]);
@@ -311,7 +313,10 @@ impl<R: Read> Read for CharReader<R> {
}
if !buf.is_empty() {
Err(io::Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
Err(io::Error::new(
ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else {
Ok(())
}
@@ -364,12 +369,14 @@ where
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("CharReader")
.field("reader", &self.inner)
.field("buf", &format_args!("{}/{}", self.buf.capacity() - self.pos, self.buf.len()))
.field(
"buf",
&format_args!("{}/{}", self.buf.capacity() - self.pos, self.buf.len()),
)
.finish()
}
}
#[cfg(test)]
mod tests {
use crate::parser::char_reader::*;

View File

@@ -86,14 +86,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
pub fn lookahead_char(&mut self) -> Result<char, ParserError> {
match self.reader.peek_char() {
Some(Ok(c)) => Ok(c),
_ => Err(ParserError::unexpected_eof())
_ => Err(ParserError::unexpected_eof()),
}
}
pub fn read_char(&mut self) -> Result<char, ParserError> {
match self.reader.read_char() {
Some(Ok(c)) => Ok(c),
_ => Err(ParserError::unexpected_eof())
_ => Err(ParserError::unexpected_eof()),
}
}
@@ -168,13 +168,15 @@ impl<'a, R: CharRead> Lexer<'a, R> {
match comment_loop() {
Err(e) if e.is_unexpected_eof() => {
return Err(ParserError::IncompleteReduction(self.line_num, self.col_num));
return Err(ParserError::IncompleteReduction(
self.line_num,
self.col_num,
));
}
Err(e) => {
return Err(e);
}
Ok(_) => {
}
Ok(_) => {}
}
if prolog_char!(c) {
@@ -362,7 +364,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if hexadecimal_digit_char!(c) {
self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16)
} else {
Err(ParserError::IncompleteReduction(self.line_num, self.col_num))
Err(ParserError::IncompleteReduction(
self.line_num,
self.col_num,
))
}
}
@@ -395,7 +400,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
},
)
} else {
Err(ParserError::IncompleteReduction(self.line_num, self.col_num))
Err(ParserError::IncompleteReduction(
self.line_num,
self.col_num,
))
}
}
@@ -463,9 +471,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
Integer::from_str_radix(&token, 16)
.map(|n| Token::Literal(Literal::Integer(
arena_alloc!(n, &mut self.machine_st.arena)
)))
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else {
@@ -495,9 +506,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
Integer::from_str_radix(&token, 8)
.map(|n| Token::Literal(Literal::Integer(
arena_alloc!(n, &mut self.machine_st.arena)
)))
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else {
@@ -527,9 +541,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
Integer::from_str_radix(&token, 2)
.map(|n| Token::Literal(Literal::Integer(
arena_alloc!(n, &mut self.machine_st.arena)
)))
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else {
@@ -620,16 +637,20 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if token.as_str() == "[]" {
Ok(Token::Literal(Literal::Atom(atom!("[]"))))
} else {
Ok(Token::Literal(Literal::Atom(
self.machine_st.atom_tbl.build_with(&token),
)))
Ok(Token::Literal(Literal::Atom(AtomTable::build_with(
&self.machine_st.atom_tbl,
&token,
))))
}
}
fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> {
self.return_char(token.pop().unwrap());
let n = parse_lossy::<f64, _>(token.as_bytes())?;
Ok(Token::Literal(Literal::from(float_alloc!(n, self.machine_st.arena))))
Ok(Token::Literal(Literal::from(float_alloc!(
n,
self.machine_st.arena
))))
}
fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
@@ -675,7 +696,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(n, &mut self.machine_st.arena)))
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
@@ -740,17 +764,19 @@ impl<'a, R: CharRead> Lexer<'a, R> {
}
let n = parse_lossy::<f64, _>(token.as_bytes())?;
Ok(Token::Literal(Literal::from(
float_alloc!(n, self.machine_st.arena)
)))
Ok(Token::Literal(Literal::from(float_alloc!(
n,
self.machine_st.arena
))))
} else {
return Ok(self.vacate_with_float(token)?);
}
} else {
let n = parse_lossy::<f64, _>(token.as_bytes())?;
Ok(Token::Literal(Literal::from(
float_alloc!(n, self.machine_st.arena)
)))
Ok(Token::Literal(Literal::from(float_alloc!(
n,
self.machine_st.arena
))))
}
} else {
self.return_char('.');
@@ -761,7 +787,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(n, &mut self.machine_st.arena)))
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
@@ -772,7 +801,9 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.hexadecimal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e {
i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
@@ -794,7 +825,9 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.octal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e {
i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
@@ -816,7 +849,9 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.binary_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e {
i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
@@ -856,15 +891,16 @@ impl<'a, R: CharRead> Lexer<'a, R> {
.map(|c| Token::Literal(Literal::Fixnum(Fixnum::build_with(c as i64))))
.or_else(|err| {
match err {
ParserError::UnexpectedChar('\'', ..) => {
}
ParserError::UnexpectedChar('\'', ..) => {}
err => return Err(err),
}
self.return_char(c);
i64::from_str_radix(&token, 10)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
@@ -901,7 +937,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(n, &mut self.machine_st.arena)))
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
@@ -940,11 +979,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
pub fn scan_for_layout(&mut self) -> Result<bool, ParserError> {
match self.lookahead_char() {
Err(e) => {
Err(e)
}
Err(e) => Err(e),
Ok(c) => {
let mut layout_info = LayoutInfo { inserted: false, more: true };
let mut layout_info = LayoutInfo {
inserted: false,
more: true,
};
let mut cr = Some(c);
loop {
@@ -1044,7 +1084,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if c == '"' {
let s = self.char_code_list_token(c)?;
let atom = self.machine_st.atom_tbl.build_with(&s);
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &s);
return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes {
Ok(Token::Literal(Literal::Atom(atom)))
@@ -1054,7 +1094,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
}
if c == '\u{0}' {
return Err(ParserError::unexpected_eof())
return Err(ParserError::unexpected_eof());
}
self.name_token(c)

View File

@@ -7,13 +7,14 @@ macro_rules! char_class {
#[macro_export]
macro_rules! alpha_char {
($c: expr) => {
(!$c.is_numeric() &&
!$c.is_whitespace() &&
!$c.is_control() &&
!$crate::graphic_token_char!($c) &&
!$crate::layout_char!($c) &&
!$crate::meta_char!($c) &&
!$crate::solo_char!($c)) || $c == '_'
(!$c.is_numeric()
&& !$c.is_whitespace()
&& !$c.is_control()
&& !$crate::graphic_token_char!($c)
&& !$crate::layout_char!($c)
&& !$crate::meta_char!($c)
&& !$crate::solo_char!($c))
|| $c == '_'
};
}

View File

@@ -7,7 +7,6 @@ use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::parser::lexer::*;
use std::cell::Cell;
use std::mem;
use std::ops::Neg;
@@ -108,7 +107,7 @@ pub(crate) fn as_partial_string(
tail_ref = tail;
}
Term::CompleteString(_, cstr) => {
string += cstr.as_str();
string += &*cstr.as_str();
tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
break;
}
@@ -120,26 +119,17 @@ pub(crate) fn as_partial_string(
}
match &tail {
Term::AnonVar | Term::Var(..) => {
Ok((string, Some(Box::new(tail))))
}
Term::Literal(_, Literal::Atom(atom!("[]"))) => {
Ok((string, None))
}
Term::AnonVar | Term::Var(..) => Ok((string, Some(Box::new(tail)))),
Term::Literal(_, Literal::Atom(atom!("[]"))) => Ok((string, None)),
Term::Literal(_, Literal::String(tail)) => {
string += tail.as_str();
string += &*tail.as_str();
Ok((string, None))
}
_ => {
Ok((string, Some(Box::new(tail))))
}
_ => Ok((string, Some(Box::new(tail)))),
}
}
pub fn get_op_desc(
name: Atom,
op_dir: &CompositeOpDir,
) -> Option<CompositeOpDesc> {
pub fn get_op_desc(name: Atom, op_dir: &CompositeOpDir) -> Option<CompositeOpDesc> {
let mut op_desc = CompositeOpDesc {
pre: 0,
inf: 0,
@@ -295,17 +285,17 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
Ok(tokens)
}
fn atomize_term(atom_tbl: &mut AtomTable, term: &Term) -> Option<Atom> {
fn atomize_term(atom_tbl: &AtomTable, term: &Term) -> Option<Atom> {
match term {
Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
_ => None,
}
}
fn atomize_constant(atom_tbl: &mut AtomTable, c: Literal) -> Option<Atom> {
fn atomize_constant(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
match c {
Literal::Atom(ref name) => Some(*name),
Literal::Char(c) => Some(atom_tbl.build_with(&c.to_string())),
Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
_ => None,
}
}
@@ -409,7 +399,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
}
fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
self.terms.push(Term::Literal(Cell::default(), Literal::Atom(atom)));
self.terms
.push(Term::Literal(Cell::default(), Literal::Atom(atom)));
self.stack.push(TokenDesc {
tt: TokenType::Term,
priority,
@@ -419,7 +410,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
fn shift(&mut self, token: Token, priority: usize, spec: Specifier) {
let tt = match token {
Token::Literal(Literal::String(s)) if self.lexer.machine_st.flags.double_quotes.is_codes() => {
Token::Literal(Literal::String(s))
if self.lexer.machine_st.flags.double_quotes.is_codes() =>
{
let mut list = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
for c in s.as_str().chars().rev() {
@@ -436,7 +429,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
self.terms.push(list);
TokenType::Term
}
Token::Literal(Literal::String(s)) if self.lexer.machine_st.flags.double_quotes.is_chars() => {
Token::Literal(Literal::String(s))
if self.lexer.machine_st.flags.double_quotes.is_chars() =>
{
self.terms.push(Term::CompleteString(Cell::default(), s));
TokenType::Term
}
@@ -573,7 +568,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
let idx = self.terms.len() - arity;
if TokenType::Term == self.stack[stack_len].tt {
if atomize_term(&mut self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() {
if atomize_term(&self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() {
self.stack.truncate(stack_len + 1);
let mut subterms: Vec<_> = self.terms.drain(idx..).collect();
@@ -581,27 +576,29 @@ impl<'a, R: CharRead> Parser<'a, R> {
if let Some(name) = self
.terms
.pop()
.and_then(|t| atomize_term(&mut self.lexer.machine_st.atom_tbl, &t))
.and_then(|t| atomize_term(&self.lexer.machine_st.atom_tbl, &t))
{
// reduce the '.' functor to a cons cell if it applies.
if name == atom!(".") && subterms.len() == 2 {
let tail = subterms.pop().unwrap();
let head = subterms.pop().unwrap();
self.terms.push(
match as_partial_string(head, tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
},
);
self.terms.push(match as_partial_string(head, tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
let atom = AtomTable::build_with(
&self.lexer.machine_st.atom_tbl,
&string_buf,
);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
});
} else {
self.terms.push(Term::Clause(Cell::default(), name, subterms));
self.terms
.push(Term::Clause(Cell::default(), name, subterms));
}
if let Some(&mut TokenDesc {
@@ -695,7 +692,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
td.tt = TokenType::Term;
td.priority = 0;
self.terms.push(Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))));
self.terms
.push(Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))));
return Ok(true);
}
}
@@ -736,8 +734,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
if arity > self.terms.len() {
return Err(ParserError::IncompleteReduction(
self.lexer.line_num,
self.lexer.col_num
))
self.lexer.col_num,
));
}
let idx = self.terms.len() - arity;
@@ -755,18 +753,16 @@ impl<'a, R: CharRead> Parser<'a, R> {
});
self.terms.push(match list {
Term::Cons(_, head, tail) => {
match as_partial_string(*head, *tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
Term::Cons(_, head, tail) => match as_partial_string(*head, *tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
}
Ok((string_buf, None)) => {
let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
},
term => term,
});
@@ -784,10 +780,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
td.priority = 0;
td.spec = TERM;
let term = Term::Literal(
Cell::default(),
Literal::Atom(atom!("{}")),
);
let term = Term::Literal(Cell::default(), Literal::Atom(atom!("{}")));
self.terms.push(term);
return Ok(true);
@@ -818,11 +811,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
}
};
self.terms.push(Term::Clause(
Cell::default(),
atom!("{}"),
vec![term],
));
self.terms
.push(Term::Clause(Cell::default(), atom!("{}"), vec![term]));
return Ok(true);
}
@@ -933,7 +923,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
if let Some(term) = self.terms.last().cloned() {
match term {
Term::Literal(_, Literal::Atom(name))
if name == atom!("-") && (is_prefix!(desc.spec) || is_negate!(desc.spec)) =>
if name == atom!("-")
&& (is_prefix!(desc.spec) || is_negate!(desc.spec)) =>
{
self.stack.pop();
self.terms.pop();
@@ -983,7 +974,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
|n, arena| Literal::from(float_alloc!(n, arena)),
),
Token::Literal(c) => {
if let Some(name) = atomize_constant(&mut self.lexer.machine_st.atom_tbl, c) {
let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
if let Some(name) = atomized {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM);
}
@@ -1069,7 +1061,11 @@ impl<'a, R: CharRead> Parser<'a, R> {
}
// on success, returns the parsed term and the number of lines read.
pub fn read_term(&mut self, op_dir: &CompositeOpDir, tokens: Tokens) -> Result<Term, ParserError> {
pub fn read_term(
&mut self,
op_dir: &CompositeOpDir,
tokens: Tokens,
) -> Result<Term, ParserError> {
self.tokens = match tokens {
Tokens::Default => read_tokens(&mut self.lexer)?,
Tokens::Provided(tokens) => tokens,

View File

@@ -1,6 +1,7 @@
use core::marker::PhantomData;
use std::alloc;
use std::cell::UnsafeCell;
use std::ptr;
pub trait RawBlockTraits {
@@ -12,7 +13,7 @@ pub trait RawBlockTraits {
pub struct RawBlock<T: RawBlockTraits> {
pub base: *const u8,
pub top: *const u8,
pub ptr: *mut u8,
pub ptr: UnsafeCell<*mut u8>,
_marker: PhantomData<T>,
}
@@ -22,7 +23,7 @@ impl<T: RawBlockTraits> RawBlock<T> {
RawBlock {
base: ptr::null(),
top: ptr::null(),
ptr: ptr::null_mut(),
ptr: UnsafeCell::new(ptr::null_mut()),
_marker: PhantomData,
}
}
@@ -42,7 +43,7 @@ impl<T: RawBlockTraits> RawBlock<T> {
self.base = alloc::alloc(layout) as *const _;
self.top = (self.base as usize + cap) as *const _;
self.ptr = self.base as *mut _;
*self.ptr.get_mut() = self.base as *mut _;
}
pub unsafe fn grow(&mut self) {
@@ -54,7 +55,25 @@ impl<T: RawBlockTraits> RawBlock<T> {
self.base = alloc::realloc(self.base as *mut _, layout, size * 2) as *const _;
self.top = (self.base as usize + size * 2) as *const _;
self.ptr = (self.base as usize + size) as *mut _;
*self.ptr.get_mut() = (self.base as usize + size) as *mut _;
}
}
pub unsafe fn grow_new(&self) -> Option<Self> {
if self.base.is_null() {
Some(Self::new())
} else {
let mut new_block = Self::empty_block();
new_block.init_at_size(self.size() * 2);
if new_block.base.is_null() {
// allocation failed
None
} else {
let allocated = (*self.ptr.get()) as usize - self.base as usize;
self.base.copy_to(new_block.base.cast_mut(), allocated);
*new_block.ptr.get_mut() = new_block.base.offset(allocated as isize).cast_mut();
Some(new_block)
}
}
}
@@ -64,35 +83,39 @@ impl<T: RawBlockTraits> RawBlock<T> {
}
#[inline(always)]
fn free_space(&self) -> usize {
unsafe fn free_space(&self) -> usize {
debug_assert!(
self.ptr as *const _ >= self.base,
*self.ptr.get() as *const _ >= self.base,
"self.ptr = {:?} < {:?} = self.base",
self.ptr,
*self.ptr.get(),
self.base
);
self.top as usize - self.ptr as usize
self.top as usize - (*self.ptr.get()) as usize
}
pub unsafe fn alloc(&mut self, size: usize) -> *mut u8 {
pub unsafe fn alloc(&self, size: usize) -> *mut u8 {
if self.free_space() >= size {
let ptr = self.ptr;
self.ptr = (self.ptr as usize + size) as *mut _;
let ptr = *self.ptr.get();
*self.ptr.get() = (ptr as usize + size) as *mut _;
ptr
} else {
ptr::null_mut()
}
}
}
pub fn deallocate(&mut self) {
unsafe {
let layout = alloc::Layout::from_size_align_unchecked(self.size(), T::align());
alloc::dealloc(self.base as *mut _, layout);
impl<T: RawBlockTraits> Drop for RawBlock<T> {
fn drop(&mut self) {
if !self.base.is_null() {
unsafe {
let layout = alloc::Layout::from_size_align_unchecked(self.size(), T::align());
alloc::dealloc(self.base as *mut _, layout);
}
self.top = ptr::null();
self.base = ptr::null();
self.ptr = ptr::null_mut();
*self.ptr.get_mut() = ptr::null_mut();
}
}
}

221
src/rcu.rs Normal file
View File

@@ -0,0 +1,221 @@
use std::{
cell::OnceCell,
fmt::Debug,
mem::ManuallyDrop,
ops::Deref,
ptr::NonNull,
sync::{
atomic::{AtomicPtr, AtomicU8},
Arc, Weak,
},
};
use tokio::sync::RwLock;
// the epoch counters of all threads that have ever accessed an Rcu
// threads that have finished will have a dangling Weak reference and can be cleand up
// having this be shared between all Rcu's is a tradeof,
// writes will be slower as more epoch counters need to be waited for
// reads should be faster as a thread only needs to register itself once on the first read
//
static EPOCH_COUNTERS: RwLock<Vec<Weak<AtomicU8>>> = RwLock::const_new(Vec::new());
thread_local! {
// odd value means the current thread is about to access the active_epoch of an Rcu
// a thread has a single epoch counter for all Rcu it accesses,
// as a thread can only access one Rcu at a time
static THREAD_EPOCH_COUNTER: OnceCell<Arc<AtomicU8>> = OnceCell::new();
}
pub struct Rcu<T> {
active_value: AtomicPtr<T>,
}
impl<T: std::fmt::Debug> std::fmt::Debug for Rcu<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let active_epoch = self.active_epoch();
f.debug_struct("Rcu")
.field("active_value", &active_epoch)
.finish()
}
}
impl<T> Rcu<T> {
pub fn new(initial_value: T) -> Self {
Rcu {
active_value: AtomicPtr::new(Arc::into_raw(Arc::new(initial_value)).cast_mut()),
}
}
pub fn active_epoch(&self) -> RcuRef<T, T> {
THREAD_EPOCH_COUNTER.with(|epoch_counter| {
let epoch_counter = epoch_counter.get_or_init(|| {
let epoch_counter = Arc::new(AtomicU8::new(0));
// register the current threads epoch counter on init
EPOCH_COUNTERS
.blocking_write()
.push(Arc::downgrade(&epoch_counter));
epoch_counter
});
let old = epoch_counter.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
assert!(old % 2 == 0, "Old Epoch counter value should be even!");
});
let arc_ptr = self.active_value.load(std::sync::atomic::Ordering::Acquire);
let arc = unsafe {
// Safety:
// - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
// - the Rcu is responsible for of the arc's strong refrences
// - the Rcu is alive as this function takes a reference to the Rcu
// - replace will wait with decrementing the old values strong count until our epoich counter is even again
Arc::increment_strong_count(arc_ptr);
// Safety:
// - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
// - we have just ensured an additional strong count by incrementing the count
Arc::from_raw(arc_ptr)
};
THREAD_EPOCH_COUNTER.with(|epoch_counter| {
let old = epoch_counter
.get().expect("we initialized the OnceCell when we incremented the epoch counter the fist time")
.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
assert!(old % 2 != 0, "Old Epoch counter value should be odd!");
});
RcuRef {
data: arc.deref().into(),
arc,
}
}
/*
* replace the Rcu'S content with a new value
*
* This does not syncronize write and last to update the active_value pointer wins,
* all writes that do not win will be lost, though not leaked.
* This will block untill the old value can be reclaimed,
* i.e. all threads whitnest to be in the read critical sections
* have been witnest to have left the critical section at least once
*/
pub fn replace(&self, new_value: T) {
let arc_ptr = self.active_value.swap(
Arc::into_raw(Arc::new(new_value)).cast_mut(),
std::sync::atomic::Ordering::AcqRel,
);
// maually drop as we need to ensure not to drop the arc while
// we have not witnest all threads to be or have been outside the read critical section
// i.e. even epoch counter or different odd epoch counter
// Safety:
// - the ptr was created in Rcu::new or Rcu::replace with Arc::into_raw
// - the Rcu itself holds one strong count
let arc = unsafe { ManuallyDrop::new(Arc::from_raw(arc_ptr)) };
let epochs = EPOCH_COUNTERS.blocking_read().clone();
let mut epochs = epochs
.into_iter()
.flat_map(|elem| {
let arc = elem.upgrade()?;
let init_val = arc.load(std::sync::atomic::Ordering::Acquire);
if init_val % 2 == 0 {
// already even can be ignored
return None;
}
// odd initial value thread is in read critical section
// need to wait for the value to change before we can drop the arc
Some((init_val, elem))
})
.collect::<Vec<_>>();
while !epochs.is_empty() {
epochs.retain(|elem| {
let Some(arc) = elem.1.upgrade() else {
// as the thread is dead it can't have a ref to old arc
return false;
};
// the epoch counter has not changed so the thread is still in the same instance of the critical section
// any different value is ok as
// - even values indicate the thread is outside the critical section
// - a diffrent odd value indicates the thread has left the critical section and can subsequently only read the new active_value
arc.load(std::sync::atomic::Ordering::Acquire) == elem.0
})
}
// Safety:
// - we have not dropped the arc another way
// - we witnessed all threads either with an even epoch count or with a new odd count
// as such they must have left the critical section at some point
ManuallyDrop::into_inner(arc);
}
}
pub struct RcuRef<T, M>
where
T: ?Sized,
M: ?Sized,
{
arc: Arc<T>,
data: NonNull<M>,
}
impl<T: ?Sized, M: ?Sized + Debug> Debug for RcuRef<T, M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RcuRef")
.field("data", &self.deref())
.finish()
}
}
// use assoiated functions rather than methods so that we don't overlap
// with functions of the Deref Target type
impl<T: ?Sized, M: ?Sized> RcuRef<T, M> {
pub fn map<N: ?Sized, F: for<'a> FnOnce(&'a M) -> &'a N>(referece: Self, f: F) -> RcuRef<T, N> {
RcuRef {
arc: referece.arc,
data: f(unsafe { referece.data.as_ref() }).into(),
}
}
pub fn try_map<N: ?Sized, F: for<'a> FnOnce(&'a M) -> Option<&'a N>>(
referece: Self,
f: F,
) -> Option<RcuRef<T, N>> {
let val = f(unsafe { referece.data.as_ref() })?;
Some(RcuRef {
arc: Arc::clone(&referece.arc),
data: val.into(),
})
}
pub fn same_epoch<M2>(this: &Self, other: &RcuRef<T, M2>) -> bool {
Arc::ptr_eq(&this.arc, &other.arc)
}
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.data == other.data
}
pub fn clone(this: &Self) -> Self {
Self {
arc: Arc::clone(&this.arc),
data: this.data,
}
}
pub fn get_root(this: &Self) -> &T {
&this.arc
}
}
impl<T: ?Sized, M: ?Sized> Deref for RcuRef<T, M> {
type Target = M;
fn deref(&self) -> &Self::Target {
// Safety: The pointer points into the arc we are holding
// while we are alive so is the target
// as the content is in an Rcu no mutable acess is given out
unsafe { self.data.as_ref() }
}
}

View File

@@ -16,8 +16,6 @@ use crate::types::*;
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
#[cfg(feature = "repl")]
use rustyline::error::ReadlineError;
#[cfg(feature = "repl")]
@@ -27,18 +25,17 @@ use rustyline::{Config, Editor};
use std::collections::VecDeque;
use std::io::{Cursor, Error, ErrorKind, Read};
use std::sync::Arc;
type SubtermDeque = VecDeque<(usize, usize)>;
pub(crate) fn devour_whitespace<'a, R: CharRead>(parser: &mut Parser<'a, R>) -> Result<bool, ParserError> {
pub(crate) fn devour_whitespace<'a, R: CharRead>(
parser: &mut Parser<'a, R>,
) -> Result<bool, ParserError> {
match parser.lexer.scan_for_layout() {
Err(e) if e.is_unexpected_eof() => {
Ok(true)
}
Err(e) if e.is_unexpected_eof() => Ok(true),
Err(e) => Err(e),
Ok(_) => {
Ok(false)
}
Ok(_) => Ok(false),
}
}
@@ -60,7 +57,6 @@ pub(crate) fn error_after_read_term<R>(
CompilationError::from(err)
}
impl MachineState {
pub(crate) fn read(
&mut self,
@@ -74,14 +70,15 @@ impl MachineState {
parser.add_lines_read(prior_num_lines_read);
let term = parser.read_term(&op_dir, Tokens::Default)
let term = parser
.read_term(&op_dir, Tokens::Default)
.map_err(|err| error_after_read_term(err, prior_num_lines_read, &parser))?; // CompilationError::from
(term, parser.lines_read() - prior_num_lines_read)
};
inner.add_lines_read(num_lines_read);
write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl)
write_term_to_heap(&term, &mut self.heap, &self.atom_tbl)
}
}
@@ -114,51 +111,48 @@ pub struct ReadlineStream {
}
impl ReadlineStream {
#[cfg(feature = "repl")]
#[inline]
pub fn new(pending_input: &str, add_history: bool) -> Self {
let config = Config::builder()
.check_cursor_position(true)
.build();
#[cfg(feature = "repl")]
{
let config = Config::builder().check_cursor_position(true).build();
let helper = Helper::new();
let helper = Helper::new();
let mut rl = Editor::with_config(config).unwrap();
rl.set_helper(Some(helper));
let mut rl = Editor::with_config(config).unwrap();
rl.set_helper(Some(helper));
if let Some(mut path) = dirs_next::home_dir() {
path.push(HISTORY_FILE);
if path.exists() && rl.load_history(&path).is_err() {
println!("Warning: loading history failed");
if let Some(mut path) = dirs_next::home_dir() {
path.push(HISTORY_FILE);
if path.exists() && rl.load_history(&path).is_err() {
println!("Warning: loading history failed");
}
}
ReadlineStream {
rl,
pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
add_history: add_history,
}
}
ReadlineStream {
rl,
pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
add_history: add_history,
#[cfg(not(feature = "repl"))]
{
ReadlineStream {
pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
add_history: add_history,
}
}
}
#[cfg(not(feature = "repl"))]
#[inline]
pub fn new(pending_input: &str, add_history: bool) -> Self {
ReadlineStream {
pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
add_history: add_history,
pub fn set_atoms_for_completion(&mut self, atoms: &Arc<AtomTable>) {
#[cfg(feature = "repl")]
{
let helper = self.rl.helper_mut().unwrap();
helper.atoms = Arc::downgrade(atoms);
}
}
#[cfg(feature = "repl")]
pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet<Atom>) {
let helper = self.rl.helper_mut().unwrap();
helper.atoms = atoms;
}
#[cfg(not(feature = "repl"))]
pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet<Atom>) {
}
#[inline]
pub fn reset(&mut self) {
self.pending_input.reset_buffer();
@@ -180,7 +174,9 @@ impl ReadlineStream {
unsafe {
if PROMPT {
self.rl.add_history_entry(self.pending_input.get_ref().get_ref()).unwrap();
self.rl
.add_history_entry(self.pending_input.get_ref().get_ref())
.unwrap();
self.save_history();
PROMPT = false;
}
@@ -220,8 +216,7 @@ impl ReadlineStream {
}
#[cfg(not(feature = "repl"))]
fn save_history(&mut self) {
}
fn save_history(&mut self) {}
#[inline]
pub(crate) fn peek_byte(&mut self) -> std::io::Result<u8> {
@@ -253,7 +248,7 @@ impl Read for ReadlineStream {
self.call_readline()?;
self.pending_input.read(buf)
}
result => result
result => result,
}
}
}
@@ -266,16 +261,14 @@ impl CharRead for ReadlineStream {
Some(Ok(c)) => {
return Some(Ok(c));
}
_ => {
match self.call_readline() {
Err(e) => {
return Some(Err(e));
}
_ => {
set_prompt(false);
}
_ => match self.call_readline() {
Err(e) => {
return Some(Err(e));
}
}
_ => {
set_prompt(false);
}
},
}
}
}
@@ -295,7 +288,7 @@ impl CharRead for ReadlineStream {
pub(crate) fn write_term_to_heap<'a, 'b>(
term: &'a Term,
heap: &'b mut Heap,
atom_tbl: &mut AtomTable,
atom_tbl: &AtomTable,
) -> Result<TermWriteResult, CompilationError> {
let term_writer = TermWriter::new(heap, atom_tbl);
term_writer.write_term_to_heap(term)
@@ -304,7 +297,7 @@ pub(crate) fn write_term_to_heap<'a, 'b>(
#[derive(Debug)]
struct TermWriter<'a, 'b> {
heap: &'a mut Heap,
atom_tbl: &'b mut AtomTable,
atom_tbl: &'b AtomTable,
queue: SubtermDeque,
var_dict: HeapVarDict,
}
@@ -317,7 +310,7 @@ pub struct TermWriteResult {
impl<'a, 'b> TermWriter<'a, 'b> {
#[inline]
fn new(heap: &'a mut Heap, atom_tbl: &'b mut AtomTable) -> Self {
fn new(heap: &'a mut Heap, atom_tbl: &'b AtomTable) -> Self {
TermWriter {
heap,
atom_tbl,
@@ -347,17 +340,18 @@ impl<'a, 'b> TermWriter<'a, 'b> {
match term {
&TermRef::Cons(..) => list_loc_as_cell!(h),
&TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h),
&TermRef::CompleteString(_, _, ref src) =>
&TermRef::CompleteString(_, _, ref src) => {
if src.as_str().is_empty() {
empty_list_as_cell!()
} else if self.heap[h].get_tag() == HeapCellValueTag::CStr {
heap_loc_as_cell!(h)
} else {
pstr_loc_as_cell!(h)
},
}
}
&TermRef::PartialString(..) => pstr_loc_as_cell!(h),
&TermRef::Literal(_, _, literal) => HeapCellValue::from(*literal),
&TermRef::Clause(_,_,_,subterms) if subterms.len() == 0 => heap_loc_as_cell!(h),
&TermRef::Clause(_, _, _, subterms) if subterms.len() == 0 => heap_loc_as_cell!(h),
&TermRef::Clause(..) => str_loc_as_cell!(h),
}
}
@@ -427,7 +421,8 @@ impl<'a, 'b> TermWriter<'a, 'b> {
}
&TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = self.queue.pop_front() {
self.var_dict.insert(VarKey::AnonVar(h), heap_loc_as_cell!(site_h));
self.var_dict
.insert(VarKey::AnonVar(h), heap_loc_as_cell!(site_h));
if arity > 1 {
self.queue.push_front((arity - 1, site_h + 1));
@@ -437,7 +432,8 @@ impl<'a, 'b> TermWriter<'a, 'b> {
continue;
}
&TermRef::CompleteString(_, _, ref src) => {
put_complete_string(self.heap, src.as_str(), self.atom_tbl);
let src = src.as_str().to_owned();
put_complete_string(self.heap, &src, self.atom_tbl);
}
&TermRef::PartialString(lvl, _, ref src, _) => {
if let Level::Root = lvl {

View File

@@ -1,23 +1,24 @@
use indexmap::IndexSet;
use rustyline::completion::{Completer, Candidate};
use rustyline::completion::Completer;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::Hinter;
use rustyline::validate::Validator;
use rustyline::highlight::{MatchingBracketHighlighter, Highlighter};
use rustyline::{Helper as RlHelper, Result, Context};
use rustyline::{Context, Helper as RlHelper, Result};
use crate::atom_table::{Atom, STATIC_ATOMS_MAP};
use std::sync::Weak;
use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP};
// TODO: Maybe add validation to the helper
pub struct Helper {
highligher: MatchingBracketHighlighter,
pub atoms: *const IndexSet<Atom>,
pub atoms: Weak<AtomTable>,
}
impl Helper {
pub fn new() -> Self {
Self {
highligher: MatchingBracketHighlighter::new(),
atoms: std::ptr::null(),
atoms: Weak::new(),
}
}
}
@@ -43,7 +44,7 @@ fn get_prefix(line: &str, pos: usize) -> Option<usize> {
}
if i == pos {
break
break;
}
}
@@ -54,39 +55,33 @@ fn get_prefix(line: &str, pos: usize) -> Option<usize> {
start_of_atom
}
pub struct StrPtr(*const str);
impl Candidate for StrPtr {
fn display(&self) -> &str {
unsafe {
self.0.as_ref().unwrap()
}
}
fn replacement(&self) -> &str {
unsafe {
self.0.as_ref().unwrap()
}
}
}
impl Completer for Helper {
type Candidate = StrPtr;
type Candidate = AtomString<'static>;
fn complete(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Result<(usize, Vec<Self::Candidate>)> {
fn complete(
&self,
line: &str,
pos: usize,
_ctx: &Context<'_>,
) -> Result<(usize, Vec<Self::Candidate>)> {
let start_of_prefix = get_prefix(line, pos);
if let Some(idx) = start_of_prefix {
let sub_str = line.get(idx..pos).unwrap();
Ok((idx, unsafe {
let mut matching = (*self.atoms).iter()
.chain(STATIC_ATOMS_MAP.values())
.filter(|a| a.as_str().starts_with(sub_str))
.map(|s| StrPtr(s.as_str()))
.collect::<Vec<_>>();
matching.sort_unstable_by(|a, b| Ord::cmp(&(*a.0).len(), &(*b.0).len()));
matching
}))
let atom_table = self.atoms.upgrade().unwrap();
let index_set = atom_table.active_table();
let mut matching = index_set
.iter()
.chain(STATIC_ATOMS_MAP.values())
.map(|a| a.as_str())
.filter(|a| a.starts_with(sub_str))
.collect::<Vec<_>>();
matching.sort_unstable_by(|a, b| Ord::cmp(&a.len(), &b.len()));
Ok((idx, matching))
} else {
Ok((0, vec![]))
}

View File

@@ -235,8 +235,12 @@ double_quotes_option(DQ) :-
; DQ = false
).
answer_write_options(Os) :-
current_prolog_flag(answer_write_options, Os).
write_goal(G, VarList, MaxDepth) :-
double_quotes_option(DQ),
answer_write_options(Os),
( G = (Var = Value) ->
( var(Value) ->
select((Var = _), VarList, NewVarList)
@@ -246,17 +250,18 @@ write_goal(G, VarList, MaxDepth) :-
write(' = '),
( needs_bracketing(Value, =) ->
write('('),
write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)]),
write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)|Os]),
write(')')
; write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)])
; write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)|Os])
)
; G == [] ->
write('true')
; write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth), double_quotes(DQ)])
; write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth), double_quotes(DQ)|Os])
).
write_last_goal(G, VarList, MaxDepth) :-
double_quotes_option(DQ),
answer_write_options(Os),
( G = (Var = Value) ->
( var(Value) ->
select((Var = _), VarList, NewVarList)
@@ -266,9 +271,9 @@ write_last_goal(G, VarList, MaxDepth) :-
write(' = '),
( needs_bracketing(Value, =) ->
write('('),
write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)]),
write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)|Os]),
write(')')
; write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)]),
; write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(DQ)|Os]),
( trailing_period_is_ambiguous(Value) ->
write(' ')
; true
@@ -276,7 +281,7 @@ write_last_goal(G, VarList, MaxDepth) :-
)
; G == [] ->
write('true')
; write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth), double_quotes(DQ)])
; write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth), double_quotes(DQ)|Os])
).
write_eq((G1, G2), VarList, MaxDepth) :-

View File

@@ -24,7 +24,7 @@ pub enum HeapCellValueTag {
PStrOffset = 0b001111,
// constants.
Cons = 0b0,
F64 = 0b010001,
F64 = 0b010001,
Fixnum = 0b010011,
Char = 0b010101,
Atom = 0b010111,
@@ -45,7 +45,7 @@ pub enum HeapCellValueView {
PStrOffset = 0b001111,
// constants.
Cons = 0b0,
F64 = 0b010001,
F64 = 0b010001,
Fixnum = 0b010011,
Char = 0b010101,
Atom = 0b010111,
@@ -56,9 +56,9 @@ pub enum HeapCellValueView {
TrailedHeapVar = 0b101111,
TrailedStackVar = 0b101011,
TrailedAttrVar = 0b100001,
TrailedAttrVarListLink = 0b100011,
TrailedAttachedValue = 0b100101,
TrailedBlackboardEntry = 0b100111,
TrailedAttrVarListLink = 0b100011,
TrailedAttachedValue = 0b100101,
TrailedBlackboardEntry = 0b100111,
TrailedBlackboardOffset = 0b110011,
}
@@ -88,7 +88,7 @@ impl ConsPtr {
.with_tag(tag)
}
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
#[inline(always)]
pub fn as_ptr(self) -> *mut u8 {
let bytes = self.into_bytes();
@@ -96,7 +96,7 @@ impl ConsPtr {
unsafe { mem::transmute(raw_ptr_bytes) }
}
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
#[inline(always)]
pub fn as_ptr(self) -> *mut u8 {
self.ptr() as *mut _
@@ -121,28 +121,24 @@ pub(crate) enum RefTag {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct Ref {
val: B56,
#[allow(unused)] m: bool,
#[allow(unused)] f: bool,
#[allow(unused)]
m: bool,
#[allow(unused)]
f: bool,
tag: RefTag,
}
impl Ord for Ref {
fn cmp(&self, rhs: &Ref) -> Ordering {
match self.get_tag() {
RefTag::HeapCell | RefTag::AttrVar => {
match rhs.get_tag() {
RefTag::StackCell => Ordering::Less,
_ => self.get_value().cmp(&rhs.get_value()),
}
}
RefTag::StackCell => {
match rhs.get_tag() {
RefTag::StackCell =>
self.get_value().cmp(&rhs.get_value()),
_ =>
Ordering::Greater,
}
}
RefTag::HeapCell | RefTag::AttrVar => match rhs.get_tag() {
RefTag::StackCell => Ordering::Less,
_ => self.get_value().cmp(&rhs.get_value()),
},
RefTag::StackCell => match rhs.get_tag() {
RefTag::StackCell => self.get_value().cmp(&rhs.get_value()),
_ => Ordering::Greater,
},
}
}
}
@@ -204,9 +200,9 @@ pub(crate) enum TrailEntryTag {
TrailedHeapVar = 0b101111,
TrailedStackVar = 0b101011,
TrailedAttrVar = 0b100001,
TrailedAttrVarListLink = 0b100011,
TrailedAttachedValue = 0b100101,
TrailedBlackboardEntry = 0b100111,
TrailedAttrVarListLink = 0b100011,
TrailedAttachedValue = 0b100101,
TrailedBlackboardEntry = 0b100111,
TrailedBlackboardOffset = 0b110011,
}
@@ -215,9 +211,12 @@ pub(crate) enum TrailEntryTag {
#[repr(u64)]
pub(crate) struct TrailEntry {
val: B56,
#[allow(unused)] f: bool,
#[allow(unused)] m: bool,
#[allow(unused)] tag: TrailEntryTag,
#[allow(unused)]
f: bool,
#[allow(unused)]
m: bool,
#[allow(unused)]
tag: TrailEntryTag,
}
impl TrailEntry {
@@ -233,9 +232,9 @@ impl TrailEntry {
#[inline(always)]
pub(crate) fn get_tag(self) -> TrailEntryTag {
match self.tag_or_err() {
Ok(tag) => tag,
Err(_) => TrailEntryTag::TrailedAttachedValue,
}
Ok(tag) => tag,
Err(_) => TrailEntryTag::TrailedAttachedValue,
}
}
#[inline]
@@ -257,14 +256,13 @@ pub struct HeapCellValue {
impl fmt::Debug for HeapCellValue {
fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result {
match self.get_tag() {
HeapCellValueTag::F64 => {
f.debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::F64)
.field("offset", &self.get_value())
.field("m", &self.m())
.field("f", &self.f())
.finish()
}
HeapCellValueTag::F64 => f
.debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::F64)
.field("offset", &self.get_value())
.field("m", &self.m())
.field("f", &self.f())
.finish(),
HeapCellValueTag::Cons => {
let cons_ptr = ConsPtr::from_bytes(self.into_bytes());
@@ -276,8 +274,7 @@ impl fmt::Debug for HeapCellValue {
.finish()
}
HeapCellValueTag::Atom => {
let (name, arity) = cell_as_atom_cell!(self)
.get_name_and_arity();
let (name, arity) = cell_as_atom_cell!(self).get_name_and_arity();
f.debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::Atom)
@@ -288,8 +285,7 @@ impl fmt::Debug for HeapCellValue {
.finish()
}
HeapCellValueTag::PStr => {
let (name, _) = cell_as_atom_cell!(self)
.get_name_and_arity();
let (name, _) = cell_as_atom_cell!(self).get_name_and_arity();
f.debug_struct("HeapCellValue")
.field("tag", &HeapCellValueTag::PStr)
@@ -298,14 +294,13 @@ impl fmt::Debug for HeapCellValue {
.field("f", &self.f())
.finish()
}
tag => {
f.debug_struct("HeapCellValue")
.field("tag", &tag)
.field("value", &self.get_value())
.field("m", &self.get_mark_bit())
.field("f", &self.get_forwarding_bit())
.finish()
}
tag => f
.debug_struct("HeapCellValue")
.field("tag", &tag)
.field("value", &self.get_value())
.field("m", &self.get_mark_bit())
.field("f", &self.get_forwarding_bit())
.finish(),
}
}
}
@@ -320,10 +315,7 @@ impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue {
impl From<F64Ptr> for HeapCellValue {
#[inline]
fn from(f64_ptr: F64Ptr) -> HeapCellValue {
HeapCellValue::build_with(
HeapCellValueTag::F64,
f64_ptr.as_offset().to_u64(),
)
HeapCellValue::build_with(HeapCellValueTag::F64, f64_ptr.as_offset().to_u64())
}
}
@@ -402,9 +394,13 @@ impl HeapCellValue {
#[inline]
pub fn is_ref(self) -> bool {
match self.get_tag() {
HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::Var |
HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar | HeapCellValueTag::PStrLoc |
HeapCellValueTag::PStrOffset => true,
HeapCellValueTag::Str
| HeapCellValueTag::Lis
| HeapCellValueTag::Var
| HeapCellValueTag::StackVar
| HeapCellValueTag::AttrVar
| HeapCellValueTag::PStrLoc
| HeapCellValueTag::PStrOffset => true,
_ => false,
}
}
@@ -431,16 +427,13 @@ impl HeapCellValue {
#[inline]
pub fn is_constant(self) -> bool {
match self.get_tag() {
HeapCellValueTag::Cons | HeapCellValueTag::F64 | HeapCellValueTag::Fixnum |
HeapCellValueTag::Char | HeapCellValueTag::CStr => {
true
}
HeapCellValueTag::Atom => {
cell_as_atom_cell!(self).get_arity() == 0
}
_ => {
false
}
HeapCellValueTag::Cons
| HeapCellValueTag::F64
| HeapCellValueTag::Fixnum
| HeapCellValueTag::Char
| HeapCellValueTag::CStr => true,
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0,
_ => false,
}
}
@@ -455,17 +448,13 @@ impl HeapCellValue {
HeapCellValueTag::Str => {
cell_as_atom_cell!(heap[self.get_value() as usize]).get_arity() > 0
}
HeapCellValueTag::Lis |
HeapCellValueTag::CStr |
HeapCellValueTag::PStr |
HeapCellValueTag::PStrLoc |
HeapCellValueTag::PStrOffset => {
true
}
HeapCellValueTag::Atom => {
cell_as_atom_cell!(self).get_arity() > 0
}
_ => { false }
HeapCellValueTag::Lis
| HeapCellValueTag::CStr
| HeapCellValueTag::PStr
| HeapCellValueTag::PStrLoc
| HeapCellValueTag::PStrOffset => true,
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() > 0,
_ => false,
}
}
@@ -530,9 +519,7 @@ impl HeapCellValue {
#[inline]
pub fn to_pstr(self) -> Option<PartialString> {
match self.tag() {
HeapCellValueTag::PStr => {
Some(PartialString::from(Atom::from(self.val() << 3)))
}
HeapCellValueTag::PStr => Some(PartialString::from(Atom::from(self.val() << 3))),
_ => None,
}
}
@@ -545,26 +532,35 @@ impl HeapCellValue {
}
}
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
#[inline]
pub fn from_raw_ptr_bytes(ptr_bytes: [u8; 4]) -> Self {
HeapCellValue::from_bytes([ptr_bytes[0], ptr_bytes[1], ptr_bytes[2], ptr_bytes[3], 0, 0, 0, 0])
HeapCellValue::from_bytes([
ptr_bytes[0],
ptr_bytes[1],
ptr_bytes[2],
ptr_bytes[3],
0,
0,
0,
0,
])
}
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
#[inline]
pub fn from_raw_ptr_bytes(ptr_bytes: [u8; 8]) -> Self {
HeapCellValue::from_bytes(ptr_bytes)
}
#[inline]
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
pub fn to_raw_ptr_bytes(self) -> [u8; 4] {
let bytes = self.into_bytes();
[bytes[0], bytes[1], bytes[2], bytes[3]]
}
#[inline]
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
pub fn to_raw_ptr_bytes(self) -> [u8; 8] {
self.into_bytes()
}
@@ -577,7 +573,9 @@ impl HeapCellValue {
#[inline]
pub fn to_untyped_arena_ptr(self) -> Option<UntypedArenaPtr> {
match self.get_tag() {
HeapCellValueTag::Cons => Some(UntypedArenaPtr::from_bytes(self.to_untyped_arena_ptr_bytes())),
HeapCellValueTag::Cons => Some(UntypedArenaPtr::from_bytes(
self.to_untyped_arena_ptr_bytes(),
)),
_ => None,
}
}
@@ -586,7 +584,7 @@ impl HeapCellValue {
pub fn get_forwarding_bit(self) -> bool {
match self.get_tag() {
HeapCellValueTag::Cons => ConsPtr::from_bytes(self.into_bytes()).f(),
_ => self.f()
_ => self.f(),
}
}
@@ -604,9 +602,7 @@ impl HeapCellValue {
#[inline(always)]
pub fn get_mark_bit(self) -> bool {
match self.get_tag() {
HeapCellValueTag::Cons => {
ConsPtr::from_bytes(self.into_bytes()).m()
}
HeapCellValueTag::Cons => ConsPtr::from_bytes(self.into_bytes()).m(),
_ => self.m(),
}
}
@@ -633,15 +629,12 @@ impl HeapCellValue {
Some(TermOrderCategory::Variable)
}
HeapCellValueTag::Char => Some(TermOrderCategory::Atom),
HeapCellValueTag::Atom => {
Some(if cell_as_atom_cell!(self).get_arity() > 0 {
TermOrderCategory::Compound
} else {
TermOrderCategory::Atom
})
}
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc |
HeapCellValueTag::CStr => {
HeapCellValueTag::Atom => Some(if cell_as_atom_cell!(self).get_arity() > 0 {
TermOrderCategory::Compound
} else {
TermOrderCategory::Atom
}),
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr => {
Some(TermOrderCategory::Compound)
}
HeapCellValueTag::Str => {
@@ -654,9 +647,7 @@ impl HeapCellValue {
Some(TermOrderCategory::Compound)
}
}
_ => {
None
}
_ => None,
},
}
}
@@ -680,16 +671,17 @@ const_assert!(mem::size_of::<HeapCellValue>() == 8);
#[repr(u64)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct UntypedArenaPtr {
#[allow(unused)] ptr: B61,
#[allow(unused)]
ptr: B61,
m: bool,
#[allow(unused)] padding: B2,
#[allow(unused)]
padding: B2,
}
impl UntypedArenaPtr {
#[inline(always)]
pub fn build_with(ptr: usize) -> Self {
UntypedArenaPtr::new()
.with_ptr(ptr as u64)
UntypedArenaPtr::new().with_ptr(ptr as u64)
}
}
@@ -722,7 +714,7 @@ impl UntypedArenaPtr {
self.set_m(m);
}
#[cfg(target_pointer_width="32")]
#[cfg(target_pointer_width = "32")]
#[inline]
pub fn get_ptr(self) -> *const u8 {
let bytes = self.into_bytes();
@@ -730,10 +722,10 @@ impl UntypedArenaPtr {
unsafe { mem::transmute(raw_ptr_bytes) }
}
#[cfg(target_pointer_width="64")]
#[cfg(target_pointer_width = "64")]
#[inline]
pub fn get_ptr(self) -> *const u8 {
self.ptr() as *const u8
self.ptr() as *const u8
}
#[inline]
@@ -763,17 +755,15 @@ impl Add<usize> for HeapCellValue {
fn add(self, rhs: usize) -> Self::Output {
match self.get_tag() {
tag @ HeapCellValueTag::Str |
tag @ HeapCellValueTag::Lis |
tag @ HeapCellValueTag::PStrOffset |
tag @ HeapCellValueTag::PStrLoc |
tag @ HeapCellValueTag::Var |
tag @ HeapCellValueTag::AttrVar => {
tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis
| tag @ HeapCellValueTag::PStrOffset
| tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, (self.get_value() as usize + rhs) as u64)
}
_ => {
self
}
_ => self,
}
}
}
@@ -783,17 +773,15 @@ impl Sub<usize> for HeapCellValue {
fn sub(self, rhs: usize) -> Self::Output {
match self.get_tag() {
tag @ HeapCellValueTag::Str |
tag @ HeapCellValueTag::Lis |
tag @ HeapCellValueTag::PStrOffset |
tag @ HeapCellValueTag::PStrLoc |
tag @ HeapCellValueTag::Var |
tag @ HeapCellValueTag::AttrVar => {
tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis
| tag @ HeapCellValueTag::PStrOffset
| tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, (self.get_value() as usize - rhs) as u64)
}
_ => {
self
}
_ => self,
}
}
}
@@ -811,21 +799,18 @@ impl Sub<i64> for HeapCellValue {
fn sub(self, rhs: i64) -> Self::Output {
if rhs < 0 {
match self.get_tag() {
tag @ HeapCellValueTag::Str |
tag @ HeapCellValueTag::Lis |
tag @ HeapCellValueTag::PStrOffset |
tag @ HeapCellValueTag::PStrLoc |
tag @ HeapCellValueTag::Var |
tag @ HeapCellValueTag::AttrVar => {
tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis
| tag @ HeapCellValueTag::PStrOffset
| tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, self.get_value() + rhs.abs() as u64)
}
_ => {
self
}
_ => self,
}
} else {
self.sub(rhs as usize)
}
}
}

View File

@@ -56,8 +56,10 @@ impl VarSafetyStatus {
#[derive(Debug, Clone, Copy)]
pub enum PermVarAllocation {
Done { shallow_safety: VarSafetyStatus,
deep_safety: VarSafetyStatus },
Done {
shallow_safety: VarSafetyStatus,
deep_safety: VarSafetyStatus,
},
Pending,
}
@@ -81,11 +83,13 @@ impl PermVarAllocation {
#[derive(Debug, Clone)]
pub enum VarAlloc {
Temp { term_loc: GenContext,
temp_reg: usize,
temp_var_data: TempVarData,
safety: VarSafetyStatus,
to_perm_var_num: Option<usize> },
Temp {
term_loc: GenContext,
temp_reg: usize,
temp_var_data: TempVarData,
safety: VarSafetyStatus,
to_perm_var_num: Option<usize>,
},
Perm(usize, PermVarAllocation), // stack offset, allocation info
}
@@ -102,7 +106,9 @@ impl VarAlloc {
pub(crate) fn set_register(&mut self, reg_num: usize) {
match self {
VarAlloc::Perm(ref mut p, _) => *p = reg_num,
VarAlloc::Temp { ref mut temp_reg, .. } => *temp_reg = reg_num,
VarAlloc::Temp {
ref mut temp_reg, ..
} => *temp_reg = reg_num,
};
}
}
@@ -191,7 +197,8 @@ impl VariableRecords {
// Compute the conflict set of u.
// 1.
let mut use_sets: IndexMap<usize, IndexSet<(GenContext, usize), FxBuildHasher>> = IndexMap::new();
let mut use_sets: IndexMap<usize, IndexSet<(GenContext, usize), FxBuildHasher>> =
IndexMap::new();
for (var_gen_index, record) in self.0.iter_mut().enumerate() {
match &mut record.allocation {
@@ -203,8 +210,7 @@ impl VariableRecords {
use_sets.insert(var_gen_index, use_set);
}
_ => {
}
_ => {}
}
}
@@ -214,7 +220,11 @@ impl VariableRecords {
if let GenContext::Last(cn_u) = term_loc {
for (var_gen_index, record) in self.0.iter_mut().enumerate() {
match &mut record.allocation {
VarAlloc::Temp { term_loc, temp_var_data, .. } => {
VarAlloc::Temp {
term_loc,
temp_var_data,
..
} => {
if cn_u == term_loc.chunk_num() && u != var_gen_index {
if !temp_var_data.uses_reg(reg) {
temp_var_data.no_use_set.insert(reg);
@@ -228,7 +238,7 @@ impl VariableRecords {
}
// 3.
if let VarAlloc::Temp{ temp_var_data, .. } = &mut self[u].allocation {
if let VarAlloc::Temp { temp_var_data, .. } = &mut self[u].allocation {
temp_var_data.use_set = use_set;
temp_var_data.populate_conflict_set();
}

View File

@@ -1,5 +1,4 @@
use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args};
use scryer_prolog::machine::Machine;
use serial_test::serial;
// issue #857
@@ -30,7 +29,7 @@ fn do_not_duplicate_path_components() {
['tests-pl/issue852-throw_e.pl'].\n\
halt.\n\
",
" throw(e).\n false.\n throw(e).\n false.\n",
" throw(e).\n throw(e).\n",
);
}
@@ -171,16 +170,3 @@ fn call_0() {
" error(existence_error(procedure,call/0),call/0).\n",
);
}
// issue #1206
#[serial]
#[test]
#[should_panic(expected = "Overwriting atom table base pointer")]
fn atomtable_is_not_concurrency_safe() {
// this is basically the same test as scryer_prolog::atom_table::atomtable_is_not_concurrency_safe
// but for this integration test scryer_prolog is compiled with cfg!(not(test)) while for the unit test it is compiled with cfg!(test)
// as the atom table implementation differ between cfg!(test) and cfg!(not(test)) both test serve a pourpose
// Note: this integration test itself is compiled with cfg!(test) independent of scryer_prolog itself
let _machine_a = Machine::with_test_streams();
let _machine_b = Machine::with_test_streams();
}

View File

@@ -73,8 +73,5 @@ fn clpz_load() {
#[serial]
#[test]
fn iso_conformity_tests() {
load_module_test(
"tests-pl/iso-conformity-tests.pl",
"All tests passed",
);
load_module_test("tests-pl/iso-conformity-tests.pl", "All tests passed");
}