Merge branch 'master' into library-use-case
# Conflicts: # Cargo.toml # src/atom_table.rs # src/bin/scryer-prolog.rs # src/http.rs # src/machine/mock_wam.rs # src/machine/mod.rs # src/machine/system_calls.rs
This commit is contained in:
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
123
Cargo.lock
generated
123
Cargo.lock
generated
@@ -260,6 +260,26 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_log"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f"
|
||||
dependencies = [
|
||||
"log",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
@@ -378,7 +398,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dashu"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/coasys/dashu.git#f9342190be9062630124e666b001077bb5f02f23"
|
||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
||||
dependencies = [
|
||||
"dashu-base",
|
||||
"dashu-float",
|
||||
@@ -390,37 +410,36 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dashu-base"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/coasys/dashu.git#f9342190be9062630124e666b001077bb5f02f23"
|
||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
||||
|
||||
[[package]]
|
||||
name = "dashu-float"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/coasys/dashu.git#f9342190be9062630124e666b001077bb5f02f23"
|
||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
||||
dependencies = [
|
||||
"dashu-base",
|
||||
"dashu-int",
|
||||
"num-modular",
|
||||
"num-order",
|
||||
"num-traits",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashu-int"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/coasys/dashu.git#f9342190be9062630124e666b001077bb5f02f23"
|
||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dashu-base",
|
||||
"num-modular 0.5.2",
|
||||
"num-modular",
|
||||
"num-order",
|
||||
"num-traits",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashu-macros"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/coasys/dashu.git#f9342190be9062630124e666b001077bb5f02f23"
|
||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
||||
dependencies = [
|
||||
"dashu-base",
|
||||
"dashu-float",
|
||||
@@ -433,13 +452,13 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dashu-ratio"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/coasys/dashu.git#f9342190be9062630124e666b001077bb5f02f23"
|
||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
||||
dependencies = [
|
||||
"dashu-base",
|
||||
"dashu-float",
|
||||
"dashu-int",
|
||||
"num-modular",
|
||||
"num-order",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -683,7 +702,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1343,39 +1362,19 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-modular"
|
||||
version = "0.5.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-modular"
|
||||
version = "0.5.2"
|
||||
source = "git+https://github.com/coasys/num-modular.git#1ae06248ec69390370def3a229b3bf4c209aa6c7"
|
||||
checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
|
||||
|
||||
[[package]]
|
||||
name = "num-order"
|
||||
version = "1.0.4"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e81e321057a0370997b13e6638bba6bd7f6f426e1f8e9a2562490a28eb23e1bc"
|
||||
checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
|
||||
dependencies = [
|
||||
"num-modular 0.5.1",
|
||||
"num-traits",
|
||||
"num-modular",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1441,7 +1440,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1624,7 +1623,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2001,6 +2000,8 @@ dependencies = [
|
||||
"blake2 0.8.1",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"cpu-time",
|
||||
"crossterm",
|
||||
"crrl",
|
||||
@@ -2026,6 +2027,7 @@ dependencies = [
|
||||
"maplit",
|
||||
"modular-bitfield",
|
||||
"native-tls",
|
||||
"num-order",
|
||||
"ordered-float",
|
||||
"phf 0.9.0",
|
||||
"predicates-core",
|
||||
@@ -2042,17 +2044,21 @@ dependencies = [
|
||||
"rustyline",
|
||||
"ryu",
|
||||
"select",
|
||||
"serde-wasm-bindgen",
|
||||
"serial_test",
|
||||
"sha3 0.8.2",
|
||||
"smallvec",
|
||||
"static_assertions",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.32",
|
||||
"to-syn-value",
|
||||
"to-syn-value_derive",
|
||||
"tokio",
|
||||
"walkdir",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2098,6 +2104,17 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.188"
|
||||
@@ -2106,7 +2123,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2154,7 +2171,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2350,9 +2367,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.29"
|
||||
version = "2.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2412,7 +2429,7 @@ checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2443,23 +2460,23 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "to-syn-value"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45dcb7b4108a4793bdd74aa3714296c6eaf43663edf73fa8625d0d7621e68447"
|
||||
checksum = "dfcc684f2ceaec3b4e8689657c9e0944b07bf5e34563e0bd758c4d42c05c82ed"
|
||||
dependencies = [
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.32",
|
||||
"to-syn-value_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "to-syn-value_derive"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd4fdec6de01b568c1d3721c9d46a352623c536cd55a8a5acfefb63d1fccccbc"
|
||||
checksum = "3dfffda778de8443144ff3b042ddf14e8bc5445f0fd9fe937c3d252535dc9212"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2489,7 +2506,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2712,7 +2729,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -2746,7 +2763,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.32",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
31
Cargo.toml
31
Cargo.toml
@@ -10,16 +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]
|
||||
multi_thread = []
|
||||
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"
|
||||
@@ -27,9 +31,9 @@ proc-macro2 = "1.0.36"
|
||||
quote = "1.0.15"
|
||||
strum = "0.23"
|
||||
strum_macros = "0.23"
|
||||
syn = { version = "1.0.88", features = ['full', 'visit', 'extra-traits'] }
|
||||
to-syn-value = "0.1.0"
|
||||
to-syn-value_derive = "0.1.0"
|
||||
syn = { version = "2.0.32", features = ['full', 'visit', 'extra-traits'] }
|
||||
to-syn-value = "0.1.1"
|
||||
to-syn-value_derive = "0.1.1"
|
||||
walkdir = "2"
|
||||
|
||||
[dependencies]
|
||||
@@ -65,7 +69,8 @@ libloading = "0.7"
|
||||
derive_deref = "1.1.1"
|
||||
http-body-util = "0.1.0-rc.2"
|
||||
bytes = "1"
|
||||
dashu = { git = "https://github.com/coasys/dashu.git", version = "0.3.1" }
|
||||
dashu = { version = "0.3.1", git = "https://github.com/cmpute/dashu.git" }
|
||||
num-order = { version = "1.2.0" }
|
||||
rand = "0.8.5"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
@@ -84,6 +89,18 @@ tokio = { version = "1.28.2", features = ["full"] }
|
||||
getrandom = { version = "0.2.10", features = ["js"] }
|
||||
tokio = { version = "1.28.2", features = ["sync", "macros", "io-util", "rt", "time"] }
|
||||
|
||||
[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" }
|
||||
|
||||
|
||||
@@ -20,7 +20,12 @@ COPY --from=cacher /scryer-prolog/target target
|
||||
COPY --from=cacher $CARGO_HOME $CARGO_HOME
|
||||
RUN cargo build --release --bin scryer-prolog
|
||||
|
||||
FROM debian:stable-slim
|
||||
# Newer versions of Debian (i.e. bookworm) contain libssl3 instead of libssl1.1
|
||||
# which we depend on.
|
||||
FROM debian:bullseye-slim
|
||||
COPY --from=builder /scryer-prolog/target/release/scryer-prolog /usr/local/bin
|
||||
ENV RUST_BACKTRACE=1
|
||||
# Sanity check the binary: if it can't be executed (e.g. if there are missing libraries)
|
||||
# then fail the build
|
||||
RUN scryer-prolog --version
|
||||
ENTRYPOINT ["/usr/local/bin/scryer-prolog"]
|
||||
|
||||
12
INDEX.dj
12
INDEX.dj
@@ -26,9 +26,13 @@ Some of the Scryer Prolog features are:
|
||||
* Compact string representation
|
||||
* Network libraries ([TCP sockets](/sockets.html), [HTTP server](/http/http_server.html), [HTTP client](/http/http_open.html), ...)
|
||||
* [Cryptographical predicates](/crypto.html)
|
||||
* [Foreign Function Interface](/ffi.html)
|
||||
* WebAssembly support
|
||||
* WAM based engine, cross-platform made in Rust
|
||||
* _and more..._
|
||||
|
||||
Try Scryer Prolog without any installation! Use [Scryer Playground](https://play.scryer.pl), which uses the WASM version of Scryer Prolog.
|
||||
|
||||
## What is Prolog?
|
||||
|
||||
Prolog is a logic programming language created by [Alain Colmerauer](https://en.wikipedia.org/wiki/Alain_Colmerauer) and [Robert Kowalski](https://en.wikipedia.org/wiki/Robert_Kowalski) in 1972.
|
||||
@@ -57,9 +61,13 @@ the builtin Prolog modules and libraries in Scryer, check the documentation site
|
||||
|
||||
## Downloads
|
||||
|
||||
The latest version of Scryer Prolog is *0.9.1*. And it's already useful for lots of tasks.
|
||||
The latest version of Scryer Prolog is *0.9.2*. And it's already useful for lots of tasks.
|
||||
|
||||
Scryer Prolog can be compiled from source, instructions are on the [GitHub README](https://github.com/mthom/scryer-prolog). It runs on Linux, macOS and Windows. Other operating systems may work but they're not regularly tested.
|
||||
| Windows | [Download](https://github.com/mthom/scryer-prolog/releases/download/v0.9.2/scryer-prolog_windows-latest.zip) |
|
||||
| macOS (Intel) | [Download](https://github.com/mthom/scryer-prolog/releases/download/v0.9.2/scryer-prolog_macos-11.zip) |
|
||||
| Linux | [Download](https://github.com/mthom/scryer-prolog/releases/download/v0.9.2/scryer-prolog_ubuntu-20.04.zip) |
|
||||
|
||||
Scryer Prolog can also be compiled from source, instructions are on the [GitHub README](https://github.com/mthom/scryer-prolog). It runs on Linux, macOS and Windows. Other operating systems may work but they're not regularly tested.
|
||||
|
||||
If you're in Linux, maybe your distribution already has an Scryer Prolog package.
|
||||
|
||||
|
||||
98
README.md
98
README.md
@@ -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 encoding by the engine.
|
||||
|
||||
Without this innovation, storing a list of characters in memory
|
||||
would use one memory cell per character, one memory cell per
|
||||
list constructor, and one memory cell for each tail that occurs
|
||||
in the list. Since one memory cell takes 8 bytes on 64-bit
|
||||
machines, the packed representation used by Scryer Prolog yields
|
||||
an up to **24-fold reduction** of memory usage, and
|
||||
corresponding reduction of memory accesses when creating and
|
||||
processing strings.
|
||||
Without this innovation, storing a list of characters in memory would
|
||||
use one WAM memory cell per character, one cell per list
|
||||
constructor, and one cell for each tail that occurs in the list. Since
|
||||
one cell takes 8 bytes in the WAM as implemented by
|
||||
Scryer Prolog, the packed representation yields an up to
|
||||
**24-fold reduction** of memory usage, and corresponding
|
||||
reduction of memory 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:
|
||||
|
||||
@@ -306,7 +306,7 @@ enum SystemClauseType {
|
||||
GetBValue,
|
||||
#[strum_discriminants(strum(props(Arity = "3", Name = "$get_cont_chunk")))]
|
||||
GetContinuationChunk,
|
||||
#[strum_discriminants(strum(props(Arity = "7", Name = "$get_next_op_db_ref")))]
|
||||
#[strum_discriminants(strum(props(Arity = "4", Name = "$get_next_op_db_ref")))]
|
||||
GetNextOpDBRef,
|
||||
#[strum_discriminants(strum(props(Arity = "3", Name = "$lookup_db_ref")))]
|
||||
LookupDBRef,
|
||||
@@ -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);
|
||||
|
||||
@@ -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
491
flamegraph.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 4.8 MiB |
314
src/arena.rs
314
src/arena.rs
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,14 +169,13 @@ impl F64Table {
|
||||
pub enum ArenaHeaderTag {
|
||||
Integer = 0b10,
|
||||
Rational = 0b11,
|
||||
OssifiedOpDir = 0b0000100,
|
||||
LiveLoadState = 0b0001000,
|
||||
InactiveLoadState = 0b1011000,
|
||||
InputFileStream = 0b10000,
|
||||
OutputFileStream = 0b10100,
|
||||
NamedTcpStream = 0b011100,
|
||||
NamedTlsStream = 0b100000,
|
||||
HttpReadStream = 0b100001,
|
||||
HttpReadStream = 0b100001,
|
||||
HttpWriteStream = 0b100010,
|
||||
ReadlineStream = 0b110000,
|
||||
StaticStringStream = 0b110100,
|
||||
@@ -276,7 +310,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 +349,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 +370,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 +417,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 +456,7 @@ impl F64Offset {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn as_ptr(self) -> F64Ptr {
|
||||
F64Ptr::from_offset(self.0)
|
||||
F64Ptr::from_offset(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -505,28 +545,6 @@ impl ArenaAllocated for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
impl ArenaAllocated for OssifiedOpDir {
|
||||
type PtrToAllocated = TypedArenaPtr<OssifiedOpDir>;
|
||||
|
||||
#[inline]
|
||||
fn tag() -> ArenaHeaderTag {
|
||||
ArenaHeaderTag::OssifiedOpDir
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ArenaAllocated for LiveLoadState {
|
||||
type PtrToAllocated = TypedArenaPtr<LiveLoadState>;
|
||||
|
||||
@@ -577,20 +595,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 +618,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 +682,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 +690,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 +699,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 +733,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>>());
|
||||
}
|
||||
@@ -725,35 +746,32 @@ unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
||||
ArenaHeaderTag::ByteStream => {
|
||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<ByteStream>>>());
|
||||
}
|
||||
ArenaHeaderTag::OssifiedOpDir => {
|
||||
ptr::drop_in_place(value.payload_offset::<OssifiedOpDir>());
|
||||
}
|
||||
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 +819,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 +854,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 +867,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 +883,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 +901,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 +976,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 +987,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 +998,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 +1007,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 +1032,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 +1141,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!() }
|
||||
);
|
||||
|
||||
@@ -14,6 +14,8 @@ use crate::parser::dashu::{Integer, Rational};
|
||||
use crate::machine::machine_errors::*;
|
||||
|
||||
use dashu::base::Abs;
|
||||
use dashu::base::BitTest;
|
||||
use num_order::NumOrd;
|
||||
use ordered_float::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
@@ -158,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)),
|
||||
}
|
||||
@@ -326,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 {
|
||||
@@ -370,8 +363,9 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
pub(crate) fn rnd_i<'a>(n: &'a Number, arena: &mut Arena) -> Number {
|
||||
match n {
|
||||
&Number::Integer(i) => {
|
||||
if let Some(n) = i.to_i64() {
|
||||
fixnum!(Number, n, arena)
|
||||
let result = (&*i).try_into();
|
||||
if let Ok(value) = result{
|
||||
fixnum!(Number, value, arena)
|
||||
} else {
|
||||
*n
|
||||
}
|
||||
@@ -392,8 +386,9 @@ pub(crate) fn rnd_i<'a>(n: &'a Number, arena: &mut Arena) -> Number {
|
||||
&Number::Rational(ref r) => {
|
||||
let (_, floor) = (r.fract(), r.floor());
|
||||
|
||||
if let Some(floor) = floor.to_i64() {
|
||||
fixnum!(Number, floor, arena)
|
||||
let result = floor.clone().try_into();
|
||||
if let Ok(value) = result{
|
||||
fixnum!(Number, value, arena)
|
||||
} else {
|
||||
Number::Integer(arena_alloc!(floor, arena))
|
||||
}
|
||||
@@ -434,7 +429,7 @@ fn classify_float(f: f64) -> Result<f64, EvalError> {
|
||||
}
|
||||
}
|
||||
FpCategory::Nan => Err(EvalError::Undefined),
|
||||
_ => Ok(f)
|
||||
_ => Ok(f),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,15 +537,19 @@ impl PartialEq for Number {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
match (self, rhs) {
|
||||
(&Number::Fixnum(n1), &Number::Fixnum(n2)) => n1.eq(&n2),
|
||||
(&Number::Fixnum(n1), &Number::Integer(ref n2)) => n1.get_num().eq(&**n2),
|
||||
(&Number::Integer(ref n1), &Number::Fixnum(n2)) => (&**n1).eq(&n2.get_num()),
|
||||
(&Number::Fixnum(n1), &Number::Rational(ref n2)) => n1.get_num().eq(&**n2),
|
||||
(&Number::Rational(ref n1), &Number::Fixnum(n2)) => (&**n1).eq(&n2.get_num()),
|
||||
(&Number::Fixnum(n1), &Number::Integer(ref n2)) => n1.get_num().num_eq(&**n2),
|
||||
(&Number::Integer(ref n1), &Number::Fixnum(n2)) => (&**n1).num_eq(&n2.get_num()),
|
||||
(&Number::Fixnum(n1), &Number::Rational(ref n2)) => Integer::from(n1.get_num()).num_eq(&**n2),
|
||||
(&Number::Rational(ref n1), &Number::Fixnum(n2)) => (&**n1).num_eq(&Integer::from(n2.get_num())),
|
||||
(&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")]
|
||||
{
|
||||
@@ -558,7 +557,7 @@ impl PartialEq for Number {
|
||||
}
|
||||
#[cfg(not(feature = "num"))]
|
||||
{
|
||||
&**n1 == &**n2
|
||||
(&**n1).num_eq(&**n2)
|
||||
}
|
||||
}
|
||||
(&Number::Rational(ref n1), &Number::Integer(ref n2)) => {
|
||||
@@ -568,11 +567,15 @@ impl PartialEq for Number {
|
||||
}
|
||||
#[cfg(not(feature = "num"))]
|
||||
{
|
||||
&**n1 == &**n2
|
||||
(&**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),
|
||||
}
|
||||
@@ -594,8 +597,8 @@ impl PartialOrd<usize> for Number {
|
||||
(n as usize).partial_cmp(rhs)
|
||||
}
|
||||
}
|
||||
Number::Integer(n) => (&**n).partial_cmp(rhs),
|
||||
Number::Rational(r) => (&**r).partial_cmp(rhs),
|
||||
Number::Integer(n) => Some((&**n).num_cmp(rhs)),
|
||||
Number::Rational(r) => Some((&**r).num_cmp(&Integer::from(*rhs))),
|
||||
Number::Float(f) => f.partial_cmp(&OrderedFloat(*rhs as f64)),
|
||||
}
|
||||
}
|
||||
@@ -614,8 +617,8 @@ impl PartialEq<usize> for Number {
|
||||
(n as usize).eq(rhs)
|
||||
}
|
||||
}
|
||||
Number::Integer(n) => (&**n).eq(rhs),
|
||||
Number::Rational(r) => (&**r).eq(rhs),
|
||||
Number::Integer(n) => (&**n).num_eq(rhs),
|
||||
Number::Rational(r) => (&**r).num_eq(&Integer::from(*rhs)),
|
||||
Number::Float(f) => f.eq(&OrderedFloat(*rhs as f64)),
|
||||
}
|
||||
}
|
||||
@@ -641,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")]
|
||||
{
|
||||
@@ -649,7 +654,7 @@ impl Ord for Number {
|
||||
}
|
||||
#[cfg(not(feature = "num"))]
|
||||
{
|
||||
(&*n1).partial_cmp(&*n2).unwrap_or(Ordering::Less)
|
||||
(&*n1).num_partial_cmp(&*n2).unwrap_or(Ordering::Less)
|
||||
}
|
||||
}
|
||||
(&Number::Rational(n1), &Number::Integer(n2)) => {
|
||||
@@ -659,11 +664,15 @@ impl Ord for Number {
|
||||
}
|
||||
#[cfg(not(feature = "num"))]
|
||||
{
|
||||
(&*n1).partial_cmp(&*n2).unwrap_or(Ordering::Less)
|
||||
(&*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),
|
||||
}
|
||||
@@ -706,14 +715,14 @@ impl TryFrom<HeapCellValue> for Number {
|
||||
pub(crate) fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
|
||||
let mut power = Integer::from(power.abs());
|
||||
|
||||
if power == 0 {
|
||||
if power.num_eq(&0) {
|
||||
return Integer::from(1);
|
||||
}
|
||||
|
||||
let mut oddand = Integer::from(1);
|
||||
|
||||
while power > 1 {
|
||||
if power.is_odd() {
|
||||
while power.num_gt(&1) {
|
||||
if power.bit(0) {
|
||||
oddand *= &n;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(any(test, feature = "multi_thread"))]
|
||||
thread_local! {
|
||||
static ATOM_TABLE_BUF_BASE: std::cell::RefCell<*const u8> = std::cell::RefCell::new(ptr::null_mut());
|
||||
}
|
||||
|
||||
#[cfg(all(not(test), not(feature = "multi_thread")))]
|
||||
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(any(test, feature = "multi_thread"))]
|
||||
#[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(all(not(test), not(feature = "multi_thread")))]
|
||||
{
|
||||
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(any(test, feature = "multi_thread"))]
|
||||
{
|
||||
ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| *atom_table_buf_base.borrow())
|
||||
// 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(any(test, feature = "multi_thread")))]
|
||||
#[cfg(not(feature = "rust_beta_channel"))]
|
||||
{
|
||||
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 {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
fn main() -> std::process::ExitCode {
|
||||
use std::sync::atomic::Ordering;
|
||||
use scryer_prolog::*;
|
||||
use scryer_prolog::atom_table::Atom;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[cfg(feature = "repl")]
|
||||
ctrlc::set_handler(move || {
|
||||
scryer_prolog::machine::INTERRUPT.store(true, Ordering::Relaxed);
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
|
||||
270
src/codegen.rs
270
src/codegen.rs
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
703
src/ffi.rs
703
src/ffi.rs
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
85
src/forms.rs
85
src/forms.rs
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
553
src/heap_iter.rs
553
src/heap_iter.rs
@@ -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()),
|
||||
|
||||
@@ -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);
|
||||
@@ -1020,7 +1024,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
|
||||
match self.op_dir.get(&(atom!("rdiv"), Fixity::In)) {
|
||||
Some(op_desc) => {
|
||||
if r.is_integer() {
|
||||
if r.denominator().is_one() {
|
||||
let output_str = format!("{}", r);
|
||||
|
||||
push_space_if_amb!(self, &output_str, {
|
||||
@@ -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,15 +1362,15 @@ 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) {
|
||||
Ok(Number::Integer(n)) => &*n >= &Integer::from(0),
|
||||
Ok(Number::Fixnum(n)) => n.get_num() >= 0,
|
||||
Ok(Number::Float(f)) => f >= OrderedFloat(0f64),
|
||||
Ok(Number::Rational(r)) => &*r >= &Integer::from(0),
|
||||
Ok(Number::Rational(r)) => &*r >= &Rational::from(0),
|
||||
_ => false,
|
||||
}
|
||||
}) && needs_bracketing(op_desc, op)
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
@@ -1627,9 +1646,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
(ArenaHeaderTag::Stream, stream) => {
|
||||
self.print_stream(stream, max_depth);
|
||||
}
|
||||
(ArenaHeaderTag::OssifiedOpDir, _op_dir) => {
|
||||
self.print_impromptu_atom(atom!("$ossified_op_dir"));
|
||||
}
|
||||
(ArenaHeaderTag::Dropped, _value) => {
|
||||
self.print_impromptu_atom(atom!("$dropped_value"));
|
||||
}
|
||||
@@ -1668,7 +1684,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 +1753,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 +1789,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 +1813,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 +1826,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 +1859,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 +1878,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 +1895,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 +1927,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 +1945,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 +1978,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 +2022,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");
|
||||
}
|
||||
}
|
||||
|
||||
17
src/http.rs
17
src/http.rs
@@ -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)]
|
||||
@@ -31,7 +31,10 @@ impl Service<Request<IncomingBody>> for HttpService {
|
||||
// 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) };
|
||||
let http_request = HttpRequest {
|
||||
request: req,
|
||||
response: Arc::clone(&response)
|
||||
};
|
||||
self.tx.send(http_request).unwrap();
|
||||
|
||||
// we wait for the Response info from Prolog
|
||||
@@ -39,7 +42,7 @@ impl Service<Request<IncomingBody>> for HttpService {
|
||||
let (ready, _response, cvar) = &*response;
|
||||
let mut ready = ready.lock().unwrap();
|
||||
while !*ready {
|
||||
ready = cvar.wait(ready).unwrap();
|
||||
ready = cvar.wait(ready).unwrap();
|
||||
}
|
||||
}
|
||||
{
|
||||
|
||||
169
src/indexing.rs
169
src/indexing.rs
@@ -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));
|
||||
}
|
||||
/*
|
||||
@@ -1116,8 +1122,9 @@ pub(crate) fn constant_key_alternatives(
|
||||
}
|
||||
*/
|
||||
Literal::Integer(ref n) => {
|
||||
if let Some(n) = n.to_isize() {
|
||||
Fixnum::build_with_checked(n as i64).map(|n| {
|
||||
let result = (&**n).try_into();
|
||||
if let Ok(value) = result {
|
||||
Fixnum::build_with_checked(value).map(|n| {
|
||||
constants.push(Literal::Fixnum(n));
|
||||
}).unwrap();
|
||||
}
|
||||
@@ -1147,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>,
|
||||
@@ -1187,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
|
||||
}
|
||||
|
||||
@@ -1197,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)
|
||||
}
|
||||
@@ -1231,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 {
|
||||
@@ -1318,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
|
||||
}
|
||||
|
||||
@@ -1331,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));
|
||||
@@ -1343,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 {
|
||||
@@ -1370,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
|
||||
@@ -1400,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
|
||||
@@ -1436,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);
|
||||
}
|
||||
@@ -1454,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
|
||||
}
|
||||
|
||||
@@ -1463,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 => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
18
src/lib.rs
18
src/lib.rs
@@ -19,13 +19,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"));
|
||||
@@ -40,3 +40,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()
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
@@ -1342,11 +1376,6 @@ current_predicate(Pred) :-
|
||||
; throw(error(type_error(predicate_indicator, Pred), current_predicate/1))
|
||||
).
|
||||
|
||||
'$iterate_op_db_refs'(RPriority, RSpec, ROp, _, RPriority, RSpec, ROp).
|
||||
'$iterate_op_db_refs'(RPriority, RSpec, ROp, OssifiedOpDir, Priority, Spec, Op) :-
|
||||
'$get_next_op_db_ref'(RPriority, RSpec, ROp, OssifiedOpDir, RRPriority, RRSpec, RROp),
|
||||
'$iterate_op_db_refs'(RRPriority, RRSpec, RROp, OssifiedOpDir, Priority, Spec, Op).
|
||||
|
||||
can_be_op_priority(Priority) :- var(Priority).
|
||||
can_be_op_priority(Priority) :- op_priority(Priority).
|
||||
|
||||
@@ -1362,8 +1391,8 @@ current_op(Priority, Spec, Op) :-
|
||||
( can_be_op_priority(Priority),
|
||||
can_be_op_specifier(Spec),
|
||||
error:can_be(atom, Op) ->
|
||||
'$get_next_op_db_ref'(RPriority, RSpec, ROp, OssifiedOpDir, _, _, Op),
|
||||
'$iterate_op_db_refs'(RPriority, RSpec, ROp, OssifiedOpDir, Priority, Spec, Op)
|
||||
'$get_next_op_db_ref'(Priority, Spec, Op, ListOfOps),
|
||||
lists:member(op(Priority, Spec, Op), ListOfOps)
|
||||
).
|
||||
|
||||
list_of_op_atoms(Var) :-
|
||||
@@ -2186,6 +2215,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
|
||||
|
||||
161
src/lib/clpb.pl
161
src/lib/clpb.pl
@@ -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).
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
),
|
||||
|
||||
169
src/loader.pl
169
src/loader.pl
@@ -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),
|
||||
@@ -591,6 +600,8 @@ consult_stream(Stream, PathFileName) :-
|
||||
file_load(Stream, PathFileName, Subevacuable),
|
||||
'$use_module'(Evacuable, Subevacuable, _).
|
||||
|
||||
:- 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) :-
|
||||
@@ -603,6 +614,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) ->
|
||||
@@ -610,12 +622,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)
|
||||
@@ -652,8 +668,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
|
||||
@@ -661,10 +675,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),
|
||||
@@ -894,7 +912,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],
|
||||
@@ -907,7 +924,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),
|
||||
@@ -934,7 +951,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) :-
|
||||
@@ -947,7 +964,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) :-
|
||||
@@ -960,7 +977,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) :-
|
||||
@@ -973,7 +990,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) :-
|
||||
@@ -986,7 +1003,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) :-
|
||||
@@ -999,7 +1016,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) :-
|
||||
@@ -1012,7 +1029,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) :-
|
||||
@@ -1025,7 +1042,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) :-
|
||||
@@ -1038,7 +1055,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) :-
|
||||
@@ -1051,7 +1068,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) :-
|
||||
@@ -1064,7 +1081,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) :-
|
||||
@@ -1077,7 +1094,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) :-
|
||||
@@ -1090,7 +1107,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) :-
|
||||
@@ -1103,7 +1120,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) :-
|
||||
@@ -1116,7 +1133,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) :-
|
||||
@@ -1129,7 +1146,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) :-
|
||||
@@ -1142,7 +1159,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) :-
|
||||
@@ -1155,7 +1172,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) :-
|
||||
@@ -1168,7 +1185,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) :-
|
||||
@@ -1181,7 +1198,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) :-
|
||||
@@ -1194,7 +1211,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) :-
|
||||
@@ -1207,7 +1224,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) :-
|
||||
@@ -1220,7 +1237,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) :-
|
||||
@@ -1233,7 +1250,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) :-
|
||||
@@ -1246,7 +1263,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) :-
|
||||
@@ -1259,7 +1276,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) :-
|
||||
@@ -1272,7 +1289,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) :-
|
||||
@@ -1285,7 +1302,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) :-
|
||||
@@ -1298,7 +1315,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) :-
|
||||
@@ -1311,7 +1328,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) :-
|
||||
@@ -1324,7 +1341,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) :-
|
||||
@@ -1337,7 +1354,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) :-
|
||||
@@ -1350,7 +1367,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) :-
|
||||
@@ -1363,7 +1380,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) :-
|
||||
@@ -1376,7 +1393,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) :-
|
||||
@@ -1389,7 +1406,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) :-
|
||||
@@ -1402,7 +1419,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) :-
|
||||
@@ -1415,7 +1432,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) :-
|
||||
@@ -1428,7 +1445,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) :-
|
||||
@@ -1441,7 +1458,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) :-
|
||||
@@ -1454,7 +1471,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) :-
|
||||
@@ -1467,7 +1484,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) :-
|
||||
@@ -1480,7 +1497,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) :-
|
||||
@@ -1493,7 +1510,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) :-
|
||||
@@ -1506,7 +1523,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) :-
|
||||
@@ -1519,7 +1536,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) :-
|
||||
@@ -1532,7 +1549,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) :-
|
||||
@@ -1545,7 +1562,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) :-
|
||||
@@ -1558,7 +1575,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) :-
|
||||
@@ -1571,7 +1588,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) :-
|
||||
@@ -1584,7 +1601,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) :-
|
||||
@@ -1597,7 +1614,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) :-
|
||||
@@ -1610,7 +1627,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) :-
|
||||
@@ -1623,7 +1640,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) :-
|
||||
@@ -1636,7 +1653,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) :-
|
||||
@@ -1649,7 +1666,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) :-
|
||||
@@ -1662,7 +1679,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) :-
|
||||
@@ -1675,7 +1692,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) :-
|
||||
@@ -1688,7 +1705,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) :-
|
||||
@@ -1701,7 +1718,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) :-
|
||||
@@ -1714,7 +1731,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) :-
|
||||
@@ -1727,7 +1744,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) :-
|
||||
@@ -1740,7 +1757,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) :-
|
||||
@@ -1753,7 +1770,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) :-
|
||||
@@ -1766,4 +1783,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).
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use dashu::base::Abs;
|
||||
use dashu::base::DivRem;
|
||||
use dashu::base::Gcd;
|
||||
use dashu::integer::IBig;
|
||||
use divrem::*;
|
||||
use num_order::NumOrd;
|
||||
|
||||
use crate::arena::*;
|
||||
use crate::arithmetic::*;
|
||||
@@ -50,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();
|
||||
@@ -61,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();
|
||||
@@ -169,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)?))
|
||||
@@ -179,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)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,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)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,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)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,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 {
|
||||
@@ -377,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 {
|
||||
@@ -454,14 +456,14 @@ pub(crate) fn max(n1: Number, n2: Number) -> Result<Number, MachineStubGen> {
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if &*n2 > &n1.get_num() {
|
||||
if (&*n2).num_gt(&n1.get_num()) {
|
||||
Ok(Number::Integer(n2))
|
||||
} else {
|
||||
Ok(Number::Fixnum(n1))
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Fixnum(n2)) => {
|
||||
if &*n1 > &n2.get_num() {
|
||||
if (&*n1).num_gt(&n2.get_num()) {
|
||||
Ok(Number::Integer(n1))
|
||||
} else {
|
||||
Ok(Number::Fixnum(n2))
|
||||
@@ -498,14 +500,14 @@ pub(crate) fn min(n1: Number, n2: Number) -> Result<Number, MachineStubGen> {
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if &*n2 < &n1.get_num() {
|
||||
if (&*n2).num_lt(&n1.get_num()) {
|
||||
Ok(Number::Integer(n2))
|
||||
} else {
|
||||
Ok(Number::Fixnum(n1))
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Fixnum(n2)) => {
|
||||
if &*n1 < &n2.get_num() {
|
||||
if (&*n1).num_lt(&n2.get_num()) {
|
||||
Ok(Number::Integer(n1))
|
||||
} else {
|
||||
Ok(Number::Fixnum(n2))
|
||||
@@ -552,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))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +562,7 @@ pub(crate) fn rdiv(
|
||||
r1: TypedArenaPtr<Rational>,
|
||||
r2: TypedArenaPtr<Rational>,
|
||||
) -> Result<Rational, MachineStubGen> {
|
||||
if &*r2 == &0 {
|
||||
if &*r2 == &Rational::from(0) {
|
||||
let stub_gen = || {
|
||||
let rdiv_atom = atom!("rdiv");
|
||||
functor_stub(rdiv_atom, 2)
|
||||
@@ -594,7 +596,7 @@ pub(crate) fn idiv(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number,
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
if (&*n2).num_eq(&0) {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(Integer::from(n1) / &*n2, arena))
|
||||
@@ -608,11 +610,11 @@ pub(crate) fn idiv(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number,
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
if (&*n2).num_eq(&0) {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from(n1.div_rem_floor_ref(&*n2)).0,
|
||||
<(Integer, Integer)>::from((&*n1).div_rem(&*n2)).0,
|
||||
arena,
|
||||
))
|
||||
}
|
||||
@@ -659,31 +661,42 @@ 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));
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
let n1 = Integer::from(n1.get_num());
|
||||
|
||||
match n2.to_usize() {
|
||||
Some(n2) => Ok(Number::arena_from(n1 >> n2, arena)),
|
||||
_ => {
|
||||
Ok(Number::arena_from(n1 >> usize::max_value(), arena))
|
||||
},
|
||||
let result: Result<usize, _> = (&*n2).try_into();
|
||||
|
||||
match result {
|
||||
Ok(n2) => {
|
||||
Ok(Number::arena_from(n1 >> n2, arena))
|
||||
}
|
||||
Err(_) => {
|
||||
Ok(Number::arena_from(n1 >> usize::max_value(), arena))
|
||||
}
|
||||
}
|
||||
}
|
||||
(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.to_usize() {
|
||||
Some(n2) => Ok(Number::arena_from(Integer::from(&*n1 >> n2), 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();
|
||||
|
||||
match result {
|
||||
Ok(n2) => {
|
||||
Ok(Number::arena_from(Integer::from(&*n1 >> n2), arena))
|
||||
}
|
||||
Err(_) => {
|
||||
Ok(Number::arena_from(Integer::from(&*n1 >> usize::max_value()), arena))
|
||||
}
|
||||
}
|
||||
},
|
||||
(Number::Integer(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)),
|
||||
(Number::Fixnum(_), n2) => Err(numerical_type_error(ValidType::Integer, n2, stub_gen)),
|
||||
@@ -710,15 +723,18 @@ 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));
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
let n1 = Integer::from(n1.get_num());
|
||||
|
||||
match n2.to_u32() {
|
||||
Some(n2) => Ok(Number::arena_from(n1.to_u64().unwrap() << n2, arena)),
|
||||
match (&*n2).try_into() as Result<u32, _> {
|
||||
Ok(n2) => {
|
||||
let n1: u64 = n1.try_into().unwrap();
|
||||
Ok(Number::arena_from(n1 << n2, arena))
|
||||
},
|
||||
_ => {
|
||||
Ok(Number::arena_from(n1 << usize::max_value(), arena))
|
||||
}
|
||||
@@ -726,12 +742,16 @@ 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.to_u32() {
|
||||
Some(n2) => Ok(Number::arena_from(Integer::from(n1.to_u64().unwrap() << n2), arena)),
|
||||
(Number::Integer(n1), Number::Integer(n2)) => match (&*n2).try_into() as Result<u32, _> {
|
||||
Ok(n2) => {
|
||||
let n1: u64 = (&*n1).try_into().unwrap();
|
||||
Ok(Number::arena_from(Integer::from(n1 << n2), arena))
|
||||
},
|
||||
_ => {
|
||||
Ok(Number::arena_from(Integer::from(&*n1 << usize::max_value()),arena))
|
||||
}
|
||||
@@ -845,12 +865,12 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
if (&*n2).num_eq(&0) {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
let n1 = Integer::from(n1.get_num());
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from(n1.div_rem_floor_ref(&*n2)).1,
|
||||
<(Integer, Integer)>::from(n1.div_rem(&*n2)).1,
|
||||
arena,
|
||||
))
|
||||
}
|
||||
@@ -863,17 +883,17 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
||||
} else {
|
||||
let n2 = Integer::from(n2_i);
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from(n1.div_rem_floor_ref(&n2)).1,
|
||||
<(Integer, Integer)>::from((&*n1).div_rem(&n2)).1,
|
||||
arena,
|
||||
))
|
||||
}
|
||||
}
|
||||
(Number::Integer(x), Number::Integer(y)) => {
|
||||
if &*y == &0 {
|
||||
if (&*y).num_eq(&0) {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1,
|
||||
<(Integer, Integer)>::from((&*x).div_rem(&*y)).1,
|
||||
arena,
|
||||
))
|
||||
}
|
||||
@@ -903,7 +923,7 @@ pub(crate) fn remainder(x: Number, y: Number, arena: &mut Arena) -> Result<Numbe
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
if (&*n2).num_eq(&0) {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
let n1 = Integer::from(n1.get_num());
|
||||
@@ -921,7 +941,7 @@ pub(crate) fn remainder(x: Number, y: Number, arena: &mut Arena) -> Result<Numbe
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
if (&*n2).num_eq(&0) {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(Integer::from(&*n1 % &*n2), arena))
|
||||
@@ -949,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)) => {
|
||||
@@ -962,7 +979,8 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
|
||||
}
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
let n1_clone: Integer = (*n1).clone();
|
||||
Ok(Number::arena_from(Integer::from(n1_clone.gcd(&Integer::from(n2.to_isize().unwrap()))) as IBig, arena))
|
||||
let n2: isize = (&*n2).try_into().unwrap();
|
||||
Ok(Number::arena_from(Integer::from(n1_clone.gcd(&Integer::from(n2))) as IBig, arena))
|
||||
}
|
||||
(Number::Float(f), _) | (_, Number::Float(f)) => {
|
||||
let n = Number::Float(f);
|
||||
@@ -1050,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]
|
||||
@@ -1107,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);
|
||||
@@ -1160,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),
|
||||
}
|
||||
}
|
||||
@@ -1183,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);
|
||||
|
||||
@@ -1493,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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
1186
src/machine/gc.rs
1186
src/machine/gc.rs
File diff suppressed because it is too large
Load Diff
@@ -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 {
|
||||
@@ -258,7 +246,10 @@ pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<usiz
|
||||
let extract_integer = |s: usize| -> Option<usize> {
|
||||
match Number::try_from(heap[s]) {
|
||||
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
|
||||
Ok(Number::Integer(n)) => n.to_usize(),
|
||||
Ok(Number::Integer(n)) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
Some(value)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::atom_table;
|
||||
use crate::machine::BREAK_FROM_DISPATCH_LOOP_LOC;
|
||||
use crate::machine::mock_wam::{CompositeOpDir, Term};
|
||||
use crate::parser::parser::{Parser, Tokens};
|
||||
@@ -58,7 +59,7 @@ impl Machine {
|
||||
pub fn consult_module_string(&mut self, module_name: &str, program: String) {
|
||||
let stream = Stream::from_owned_string(program, &mut self.machine_st.arena);
|
||||
self.machine_st.registers[1] = stream_as_cell!(stream);
|
||||
self.machine_st.registers[2] = atom_as_cell!(self.machine_st.atom_tbl.build_with(module_name));
|
||||
self.machine_st.registers[2] = atom_as_cell!(&atom_table::AtomTable::build_with(&self.machine_st.atom_tbl, module_name));
|
||||
|
||||
self.run_module_predicate(atom!("loader"), (atom!("consult_stream"), 2));
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -1652,7 +1636,10 @@ impl Machine {
|
||||
|
||||
let arity = self.deref_register(3);
|
||||
let arity = match Number::try_from(arity) {
|
||||
Ok(Number::Integer(n)) if &*n >= &Integer::from(0) && &*n <= &Integer::from(MAX_ARITY) => Ok(n.to_usize().unwrap()),
|
||||
Ok(Number::Integer(n)) if &*n >= &Integer::from(0) && &*n <= &Integer::from(MAX_ARITY) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
Ok(value)
|
||||
},
|
||||
Ok(Number::Fixnum(n)) if n.get_num() >= 0 && n.get_num() <= MAX_ARITY as i64 => {
|
||||
Ok(usize::try_from(n.get_num()).unwrap())
|
||||
}
|
||||
@@ -1692,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));
|
||||
|
||||
@@ -1714,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()));
|
||||
@@ -1789,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,
|
||||
}
|
||||
}
|
||||
@@ -1806,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
|
||||
@@ -1863,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(())
|
||||
}
|
||||
|
||||
@@ -1876,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);
|
||||
@@ -1889,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));
|
||||
|
||||
@@ -1931,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;
|
||||
}
|
||||
@@ -1944,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;
|
||||
}
|
||||
_ => {
|
||||
@@ -1962,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;
|
||||
}
|
||||
}
|
||||
@@ -1999,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);
|
||||
@@ -2019,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
|
||||
@@ -2031,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;
|
||||
@@ -2098,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()))
|
||||
}
|
||||
@@ -2126,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
|
||||
@@ -2140,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;
|
||||
|
||||
@@ -2161,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| {
|
||||
@@ -2173,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),
|
||||
@@ -2186,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());
|
||||
|
||||
@@ -2226,14 +2201,17 @@ impl Machine {
|
||||
.store(self.machine_st.deref(self.machine_st[temp_v!(3)]));
|
||||
|
||||
let target_pos = match Number::try_from(target_pos) {
|
||||
Ok(Number::Integer(n)) => n.to_usize().unwrap(),
|
||||
Ok(Number::Integer(n)) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
value
|
||||
},
|
||||
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
|
||||
_ => 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,
|
||||
@@ -2286,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
|
||||
@@ -2303,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)
|
||||
@@ -2326,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));
|
||||
|
||||
@@ -2354,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
|
||||
@@ -2374,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!("?")),
|
||||
@@ -2384,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;
|
||||
@@ -2401,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
|
||||
@@ -2428,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
|
||||
@@ -2455,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -21,14 +21,6 @@ use crate::types::*;
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
|
||||
|
||||
pub(crate) type OssifiedOpDir = IndexMap<(Atom, Fixity), (usize, Specifier)>;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum DBRef {
|
||||
NamedPred(Atom, usize),
|
||||
Op(Atom, Fixity, TypedArenaPtr<OssifiedOpDir>),
|
||||
}
|
||||
|
||||
// 7.2
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum TermOrderCategory {
|
||||
@@ -86,7 +78,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 +136,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 +286,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 +438,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
|
||||
|
||||
@@ -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,
|
||||
@@ -671,12 +687,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 {
|
||||
@@ -717,7 +728,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,
|
||||
}
|
||||
}
|
||||
@@ -771,14 +784,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!();
|
||||
@@ -859,7 +872,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(),
|
||||
@@ -881,8 +894,10 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
if let Some(n) = n.to_usize() {
|
||||
printer.max_depth = n;
|
||||
let result = (&*n).try_into();
|
||||
|
||||
if let Ok(value) = result {
|
||||
printer.max_depth = value;
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(None);
|
||||
@@ -905,7 +920,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)));
|
||||
|
||||
|
||||
@@ -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,8 +13,10 @@ 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;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
@@ -50,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(),
|
||||
@@ -59,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(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,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;
|
||||
}
|
||||
@@ -248,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);
|
||||
}
|
||||
@@ -297,12 +295,12 @@ impl MachineState {
|
||||
|
||||
pub fn unify_big_int(&mut self, n1: TypedArenaPtr<Integer>, value: HeapCellValue) {
|
||||
let mut unifier = DefaultUnifier::from(self);
|
||||
unifier.unify_big_num(n1, value);
|
||||
unifier.unify_big_integer(n1, value);
|
||||
}
|
||||
|
||||
pub fn unify_rational(&mut self, n1: TypedArenaPtr<Rational>, value: HeapCellValue) {
|
||||
let mut unifier = DefaultUnifier::from(self);
|
||||
unifier.unify_big_num(n1, value);
|
||||
unifier.unify_big_rational(n1, value);
|
||||
}
|
||||
|
||||
pub fn unify_f64(&mut self, f1: F64Ptr, value: HeapCellValue) {
|
||||
@@ -316,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();
|
||||
}
|
||||
@@ -380,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);
|
||||
@@ -509,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)
|
||||
);
|
||||
}
|
||||
@@ -539,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)
|
||||
);
|
||||
}
|
||||
@@ -562,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)
|
||||
);
|
||||
}
|
||||
@@ -592,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)
|
||||
);
|
||||
}
|
||||
@@ -639,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;
|
||||
}
|
||||
@@ -902,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,
|
||||
@@ -950,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 => {
|
||||
@@ -1002,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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1096,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);
|
||||
@@ -1181,7 +1183,10 @@ impl MachineState {
|
||||
|
||||
let n = match n {
|
||||
Number::Fixnum(n) => n.get_num() as usize,
|
||||
Number::Integer(n) if *n >= 0 && *n <= std::usize::MAX => n.to_usize().unwrap(),
|
||||
Number::Integer(n) if (*n).num_ge(&0) && (*n).num_le(&std::usize::MAX) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
value
|
||||
},
|
||||
_ => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
@@ -1324,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 {
|
||||
@@ -1398,9 +1403,15 @@ impl MachineState {
|
||||
let err = self.domain_error(DomainErrorType::NotLessThanZero, n);
|
||||
return Err(self.error_form(err, stub_gen()));
|
||||
}
|
||||
Ok(Number::Rational(n)) => n.numerator().to_i64().unwrap(),
|
||||
Ok(Number::Rational(n)) => {
|
||||
let value: i64 = n.numerator().try_into().unwrap();
|
||||
value
|
||||
},
|
||||
Ok(Number::Fixnum(n)) => n.get_num(),
|
||||
Ok(Number::Integer(n)) => n.to_i64().unwrap(),
|
||||
Ok(Number::Integer(n)) => {
|
||||
let value: i64 = (&*n).try_into().unwrap();
|
||||
value
|
||||
},
|
||||
Err(_) => {
|
||||
return type_error(arity);
|
||||
}
|
||||
@@ -1435,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,
|
||||
@@ -1571,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)));
|
||||
@@ -1634,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;
|
||||
@@ -1646,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 {
|
||||
@@ -1681,9 +1688,9 @@ impl MachineState {
|
||||
Err(_) => {}
|
||||
},
|
||||
Ok(Number::Integer(n)) => {
|
||||
if let Some(b) = n.to_u8() {
|
||||
bytes.push(b);
|
||||
}
|
||||
let b: u8 = (&*n).try_into().unwrap();
|
||||
|
||||
bytes.push(b);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -234,6 +234,17 @@ 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> {
|
||||
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)]
|
||||
@@ -245,26 +256,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();
|
||||
@@ -481,22 +477,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();
|
||||
@@ -587,20 +571,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)
|
||||
);
|
||||
|
||||
@@ -623,29 +599,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)
|
||||
);
|
||||
|
||||
@@ -668,40 +632,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)
|
||||
);
|
||||
}
|
||||
@@ -720,7 +668,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)));
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pub mod loader;
|
||||
pub mod compile;
|
||||
pub mod config;
|
||||
pub mod copier;
|
||||
pub mod disjuncts;
|
||||
pub mod dispatch;
|
||||
pub mod gc;
|
||||
pub mod heap;
|
||||
@@ -19,7 +20,6 @@ pub mod machine_state_impl;
|
||||
pub mod mock_wam;
|
||||
pub mod parsed_results;
|
||||
pub mod partial_string;
|
||||
pub mod disjuncts;
|
||||
pub mod preprocessor;
|
||||
pub mod stack;
|
||||
pub mod streams;
|
||||
@@ -30,9 +30,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::*;
|
||||
@@ -168,7 +168,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +202,7 @@ impl Machine {
|
||||
code: &mut self.code,
|
||||
load_contexts: &mut self.load_contexts,
|
||||
},
|
||||
&mut self.machine_st
|
||||
&mut self.machine_st,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -211,7 +214,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();
|
||||
@@ -228,7 +235,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));
|
||||
}
|
||||
@@ -239,7 +247,9 @@ impl Machine {
|
||||
path_buf.push("src/toplevel.pl");
|
||||
|
||||
let path = path_buf.to_str().unwrap();
|
||||
let toplevel_stream = Stream::from_static_string(program, &mut self.machine_st.arena);
|
||||
let toplevel_stream =
|
||||
Stream::from_static_string(program, &mut self.machine_st.arena);
|
||||
|
||||
|
||||
self.load_file(path, toplevel_stream);
|
||||
|
||||
@@ -292,7 +302,7 @@ 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,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -314,7 +324,11 @@ impl Machine {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -359,10 +373,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 {
|
||||
@@ -373,56 +395,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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -455,7 +486,7 @@ impl Machine {
|
||||
user_error,
|
||||
load_contexts: vec![],
|
||||
#[cfg(feature = "ffi")]
|
||||
foreign_function_table: Default::default(),
|
||||
foreign_function_table: Default::default(),
|
||||
};
|
||||
|
||||
let mut lib_path = current_dir();
|
||||
@@ -479,10 +510,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()),
|
||||
)
|
||||
@@ -535,7 +563,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
|
||||
@@ -543,7 +573,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
|
||||
@@ -573,9 +605,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);
|
||||
@@ -685,7 +724,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,
|
||||
@@ -716,17 +760,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;
|
||||
}
|
||||
_ => {
|
||||
@@ -741,9 +785,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;
|
||||
}
|
||||
@@ -762,14 +807,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 {
|
||||
@@ -822,12 +869,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();
|
||||
@@ -853,12 +901,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();
|
||||
@@ -921,7 +970,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);
|
||||
@@ -965,7 +1014,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);
|
||||
@@ -1008,7 +1057,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;
|
||||
@@ -1047,15 +1096,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(())
|
||||
}
|
||||
@@ -1100,9 +1151,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(())
|
||||
@@ -1127,7 +1176,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))
|
||||
}
|
||||
@@ -1153,7 +1204,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))
|
||||
}
|
||||
@@ -1187,12 +1240,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)
|
||||
@@ -1203,9 +1260,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)
|
||||
};
|
||||
@@ -1272,9 +1328,8 @@ impl Machine {
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
TrailEntryTag::TrailedAttachedValue => {
|
||||
}
|
||||
TrailEntryTag::TrailedAttachedValue => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -65,15 +58,20 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
|
||||
let name = terms.pop().unwrap();
|
||||
|
||||
let arity = match arity {
|
||||
Term::Literal(_, Literal::Integer(n)) => n.to_usize(),
|
||||
Term::Literal(_, Literal::Integer(n)) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
Some(value)
|
||||
},
|
||||
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))
|
||||
@@ -87,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)
|
||||
@@ -113,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![];
|
||||
|
||||
@@ -133,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();
|
||||
@@ -141,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)?;
|
||||
|
||||
@@ -150,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),
|
||||
@@ -167,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),
|
||||
@@ -318,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())?;
|
||||
@@ -331,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))
|
||||
}
|
||||
@@ -381,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;
|
||||
@@ -408,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;
|
||||
}
|
||||
@@ -424,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,
|
||||
};
|
||||
@@ -462,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(),
|
||||
@@ -501,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(),
|
||||
@@ -529,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))
|
||||
@@ -554,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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -19,11 +19,11 @@ use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::hash::{Hash};
|
||||
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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -12,6 +12,7 @@ use std::ops::{Deref, DerefMut};
|
||||
use derive_deref::*;
|
||||
use fxhash::FxBuildHasher;
|
||||
use indexmap::IndexSet;
|
||||
use num_order::NumOrd;
|
||||
|
||||
pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
fn unify_structure(&mut self, s1: usize, value: HeapCellValue) {
|
||||
@@ -190,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);
|
||||
}
|
||||
@@ -426,8 +427,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
match Number::try_from(value) {
|
||||
Ok(n2) => match n2 {
|
||||
Number::Fixnum(n2) if n1.get_num() == n2.get_num() => {}
|
||||
Number::Integer(n2) if n1.get_num() == *n2 => {}
|
||||
Number::Rational(n2) if n1.get_num() == *n2 => {}
|
||||
Number::Integer(n2) if (*n2).num_eq(&n1.get_num()) => {}
|
||||
Number::Rational(n2) if (*n2).num_eq(&Integer::from(n1.get_num())) => {}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
@@ -439,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));
|
||||
@@ -464,6 +463,48 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
}
|
||||
}
|
||||
|
||||
fn unify_big_integer(&mut self, n1: TypedArenaPtr<Integer>, value: HeapCellValue) {
|
||||
if let Some(r) = value.as_var() {
|
||||
Self::bind(self, r, typed_arena_ptr_as_cell!(n1));
|
||||
return;
|
||||
}
|
||||
|
||||
match Number::try_from(value) {
|
||||
Ok(n2) => match n2 {
|
||||
Number::Fixnum(n2) if (*n1).num_eq(&n2.get_num()) => {}
|
||||
Number::Integer(n2) if (*n1).num_eq(&*n2) => {}
|
||||
Number::Rational(n2) if (*n2).num_eq(&*n1) => {}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unify_big_rational(&mut self, n1: TypedArenaPtr<Rational>, value: HeapCellValue) {
|
||||
if let Some(r) = value.as_var() {
|
||||
Self::bind(self, r, typed_arena_ptr_as_cell!(n1));
|
||||
return;
|
||||
}
|
||||
|
||||
match Number::try_from(value) {
|
||||
Ok(n2) => match n2 {
|
||||
Number::Fixnum(n2) if (*n1).num_eq(&Integer::from(n2.get_num())) => {}
|
||||
Number::Integer(n2) if (*n1).num_eq(&*n2) => {}
|
||||
Number::Rational(n2) if n1 == n2 => {}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unify_f64(&mut self, f1: F64Ptr, value: HeapCellValue) {
|
||||
if let Some(r) = value.as_var() {
|
||||
Self::bind(self, r, HeapCellValue::from(f1));
|
||||
@@ -489,10 +530,10 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
|
||||
match_untyped_arena_ptr!(ptr,
|
||||
(ArenaHeaderTag::Integer, int_ptr) => {
|
||||
Self::unify_big_num(self, int_ptr, value);
|
||||
Self::unify_big_integer(self, int_ptr, value);
|
||||
}
|
||||
(ArenaHeaderTag::Rational, rat_ptr) => {
|
||||
Self::unify_big_num(self, rat_ptr, value);
|
||||
Self::unify_big_rational(self, rat_ptr, value);
|
||||
}
|
||||
(ArenaHeaderTag::Stream, stream) => {
|
||||
read_heap_cell!(value,
|
||||
|
||||
105
src/macros.rs
105
src/macros.rs
@@ -57,13 +57,6 @@ macro_rules! atom_as_cell {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! cell_as_ossified_op_dir {
|
||||
($cell:expr) => {{
|
||||
let ptr_u64 = cell_as_untyped_arena_ptr!($cell);
|
||||
TypedArenaPtr::new(ptr_u64.payload_offset() as *mut OssifiedOpDir)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! cell_as_string {
|
||||
($cell:expr) => {
|
||||
PartialString::from(cell_as_atom!($cell))
|
||||
@@ -88,7 +81,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 +229,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 +253,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 +272,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 +297,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 +316,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 +324,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 +348,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 +597,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()),
|
||||
|
||||
@@ -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>>);
|
||||
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 == '_'
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
221
src/rcu.rs
Normal 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() }
|
||||
}
|
||||
}
|
||||
124
src/read.rs
124
src/read.rs
@@ -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 {
|
||||
|
||||
@@ -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![]))
|
||||
}
|
||||
|
||||
@@ -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) :-
|
||||
|
||||
265
src/types.rs
265
src/types.rs
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user