Merge branch 'master' into library-use-case
# Conflicts: # Cargo.lock # Cargo.toml # src/http.rs # src/machine/mock_wam.rs # src/machine/mod.rs # src/machine/system_calls.rs
This commit is contained in:
40
.github/workflows/ci.yml
vendored
40
.github/workflows/ci.yml
vendored
@@ -14,22 +14,23 @@ jobs:
|
|||||||
build-test:
|
build-test:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- { os: windows-latest, rust-version: stable, shell: 'msys2 {0}', target: 'x86_64-pc-windows-gnu'}
|
- { os: windows-latest, rust-version: stable, target: 'x86_64-pc-windows-msvc'}
|
||||||
- { os: macos-11, rust-version: stable, shell: bash, target: 'x86_64-apple-darwin' }
|
- { os: macos-11, rust-version: stable, target: 'x86_64-apple-darwin' }
|
||||||
- { os: ubuntu-20.04, rust-version: stable, shell: bash, extra: true, target: 'x86_64-unknown-linux-gnu' }
|
- { os: ubuntu-22.04, rust-version: stable, 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: stable, target: 'x86_64-unknown-linux-gnu', extra: true }
|
||||||
- { os: ubuntu-20.04, rust-version: "1.70", shell: bash, target: 'x86_64-unknown-linux-gnu'}
|
- { os: ubuntu-20.04, rust-version: stable, target: 'i686-unknown-linux-gnu' }
|
||||||
- { os: ubuntu-20.04, rust-version: beta, shell: bash, target: 'x86_64-unknown-linux-gnu'}
|
- { os: ubuntu-20.04, rust-version: "1.70", target: 'x86_64-unknown-linux-gnu'}
|
||||||
- { os: ubuntu-20.04, rust-version: nightly, shell: bash, target: 'x86_64-unknown-linux-gnu'}
|
- { os: ubuntu-20.04, rust-version: beta, target: 'x86_64-unknown-linux-gnu'}
|
||||||
|
- { os: ubuntu-20.04, rust-version: nightly, target: 'x86_64-unknown-linux-gnu'}
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: ${{ matrix.shell }}
|
shell: bash
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: dtolnay/rust-toolchain@master
|
- uses: dtolnay/rust-toolchain@master
|
||||||
if: "!contains(matrix.os,'windows')"
|
|
||||||
id: toolchain
|
id: toolchain
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.rust-version }}
|
toolchain: ${{ matrix.rust-version }}
|
||||||
@@ -37,14 +38,12 @@ jobs:
|
|||||||
components: clippy, rustfmt
|
components: clippy, rustfmt
|
||||||
- name: Install i686 dependencies
|
- name: Install i686 dependencies
|
||||||
if: "contains(matrix.target,'i686')"
|
if: "contains(matrix.target,'i686')"
|
||||||
run: sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt-get install libssl-dev:i386 gcc-multilib clang -y && echo "CC=clang" >> $GITHUB_ENV && echo "PKG_CONFIG_SYSROOT_DIR=/" >> $GITHUB_ENV
|
run: |
|
||||||
- uses: msys2/setup-msys2@v2
|
sudo dpkg --add-architecture i386
|
||||||
if: contains(matrix.os,'windows')
|
sudo apt-get update
|
||||||
with:
|
sudo apt-get install libssl-dev:i386 gcc-multilib clang -y
|
||||||
update: true
|
echo "CC=clang" >> $GITHUB_ENV
|
||||||
install: >-
|
echo "PKG_CONFIG_SYSROOT_DIR=/" >> $GITHUB_ENV
|
||||||
base-devel
|
|
||||||
mingw-w64-x86_64-rust
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -118,6 +117,7 @@ jobs:
|
|||||||
name: scryer-prolog_unknown_wasm32
|
name: scryer-prolog_unknown_wasm32
|
||||||
|
|
||||||
logtalk-test:
|
logtalk-test:
|
||||||
|
# if: false # uncomment to disable job
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs: [build-test]
|
needs: [build-test]
|
||||||
steps:
|
steps:
|
||||||
@@ -131,7 +131,7 @@ jobs:
|
|||||||
- name: Install Logtalk
|
- name: Install Logtalk
|
||||||
uses: logtalk-actions/setup-logtalk@master
|
uses: logtalk-actions/setup-logtalk@master
|
||||||
with:
|
with:
|
||||||
logtalk-version: git
|
logtalk-version: "3.70.0"
|
||||||
logtalk-tool-dependencies: false
|
logtalk-tool-dependencies: false
|
||||||
|
|
||||||
# Run logtalk tests.
|
# Run logtalk tests.
|
||||||
@@ -174,7 +174,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
zip scryer-prolog_macos-11.zip ./scryer-prolog_macos-11_x86_64-apple-darwin/scryer-prolog
|
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_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 scryer-prolog_ubuntu-22.04.zip ./scryer-prolog_ubuntu-22.04_x86_64-unknown-linux-gnu/scryer-prolog
|
||||||
|
zip scryer-prolog_windows-latest.zip ./scryer-prolog_windows-latest_x86_64-pc-windows-msvc/scryer-prolog.exe
|
||||||
zip -r scryer-prolog_unknown-wasm32.zip ./scryer-prolog_unknown_wasm32
|
zip -r scryer-prolog_unknown-wasm32.zip ./scryer-prolog_unknown_wasm32
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
@@ -182,5 +183,6 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
scryer-prolog_macos-11.zip
|
scryer-prolog_macos-11.zip
|
||||||
scryer-prolog_ubuntu-20.04.zip
|
scryer-prolog_ubuntu-20.04.zip
|
||||||
|
scryer-prolog_ubuntu-22.04.zip
|
||||||
scryer-prolog_windows-latest.zip
|
scryer-prolog_windows-latest.zip
|
||||||
scryer-prolog_unknown-wasm32.zip
|
scryer-prolog_unknown-wasm32.zip
|
||||||
|
|||||||
533
Cargo.lock
generated
533
Cargo.lock
generated
@@ -90,9 +90,15 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.21.3"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53"
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
@@ -197,9 +203,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.13.0"
|
version = "3.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byte-tools"
|
name = "byte-tools"
|
||||||
@@ -215,9 +221,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
@@ -236,17 +242,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.26"
|
version = "0.4.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"time",
|
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"winapi",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -374,19 +379,19 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.4.0"
|
version = "3.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
|
checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix 0.27.1",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashmap"
|
name = "dashmap"
|
||||||
version = "5.5.1"
|
version = "5.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edd72493923899c6f10c641bdbdeddc7183d6396641d99c1a0d1597f37f92e28"
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"hashbrown 0.14.0",
|
"hashbrown 0.14.0",
|
||||||
@@ -397,8 +402,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashu"
|
name = "dashu"
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b669b1473cc6b33aba72ab3ddfe1055ff8fc28accd85130c412c2cd922a7c4e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dashu-base",
|
"dashu-base",
|
||||||
"dashu-float",
|
"dashu-float",
|
||||||
@@ -409,13 +415,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashu-base"
|
name = "dashu-base"
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e183fc153511989674ede304b5592c74683393ca09cf20391898c28d6ba04264"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashu-float"
|
name = "dashu-float"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7696675af30ae057b1629d27b153bbafb06461826b7d0ef1858d06b801f355f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dashu-base",
|
"dashu-base",
|
||||||
"dashu-int",
|
"dashu-int",
|
||||||
@@ -426,8 +434,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashu-int"
|
name = "dashu-int"
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc257a884b3e8c9a1a577ff7226dcb4d6bda0ff96dfa76975e2c9d7205e3b8ea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"dashu-base",
|
"dashu-base",
|
||||||
@@ -438,8 +447,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashu-macros"
|
name = "dashu-macros"
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e496c319e615b86b21d6b0ea9e2f96a4f5fb2eb4178293b04a51ffc30a6c3f54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dashu-base",
|
"dashu-base",
|
||||||
"dashu-float",
|
"dashu-float",
|
||||||
@@ -451,8 +461,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashu-ratio"
|
name = "dashu-ratio"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/cmpute/dashu.git#9d1ba4ac98a4675f294e2f2c072bf47f96d33e9b"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f0f73f0ad6cbc94f52306455603e307b065af83bc61101968d53b6870127a05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dashu-base",
|
"dashu-base",
|
||||||
"dashu-float",
|
"dashu-float",
|
||||||
@@ -554,9 +565,9 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"errno-dragonfly",
|
"errno-dragonfly",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -702,7 +713,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -772,7 +783,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -835,6 +846,30 @@ version = "0.14.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.21.4",
|
||||||
|
"bytes",
|
||||||
|
"headers-core",
|
||||||
|
"http",
|
||||||
|
"httpdate",
|
||||||
|
"mime",
|
||||||
|
"sha1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers-core"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -846,9 +881,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
@@ -906,29 +941,6 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http-body"
|
|
||||||
version = "1.0.0-rc.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "951dfc2e32ac02d67c90c0d65bd27009a635dc9b381a2cc7d284ab01e3a0150d"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"http",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http-body-util"
|
|
||||||
version = "0.1.0-rc.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08ef12f041acdd397010e5fb6433270c147d3b8b2d0a840cd7fff8e531dca5c8"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-util",
|
|
||||||
"http",
|
|
||||||
"http-body 1.0.0-rc.2",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@@ -953,7 +965,7 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"h2",
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body 0.4.5",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa",
|
"itoa",
|
||||||
@@ -965,27 +977,6 @@ dependencies = [
|
|||||||
"want",
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper"
|
|
||||||
version = "1.0.0-rc.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d280a71f348bcc670fc55b02b63c53a04ac0bf2daff2980795aeaf53edae10e6"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-util",
|
|
||||||
"h2",
|
|
||||||
"http",
|
|
||||||
"http-body 1.0.0-rc.2",
|
|
||||||
"httparse",
|
|
||||||
"httpdate",
|
|
||||||
"itoa",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
"tracing",
|
|
||||||
"want",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-tls"
|
name = "hyper-tls"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -993,30 +984,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"hyper 0.14.27",
|
"hyper",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper-util"
|
|
||||||
version = "0.0.0"
|
|
||||||
source = "git+https://github.com/hyperium/hyper-util.git#f898015fc9eca9f459ddac521db278d904099e89"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-util",
|
|
||||||
"http",
|
|
||||||
"hyper 1.0.0-rc.4",
|
|
||||||
"once_cell",
|
|
||||||
"pin-project-lite",
|
|
||||||
"socket2 0.4.9",
|
|
||||||
"tokio",
|
|
||||||
"tower",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.57"
|
version = "0.1.57"
|
||||||
@@ -1139,14 +1112,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.147"
|
version = "0.2.148"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libffi"
|
name = "libffi"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
source = "git+https://github.com/coasys/libffi-rs.git?branch=windows-space#f6e9e50efde0aa4e940dd6f709a59bb426875362"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"libffi-sys",
|
"libffi-sys",
|
||||||
@@ -1155,7 +1129,8 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libffi-sys"
|
name = "libffi-sys"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
source = "git+https://github.com/coasys/libffi-rs.git?branch=windows-space#f6e9e50efde0aa4e940dd6f709a59bb426875362"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
@@ -1172,9 +1147,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.5"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -1238,9 +1213,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
@@ -1248,6 +1223,16 @@ version = "0.3.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||||
|
dependencies = [
|
||||||
|
"mime",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -1277,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1309,6 +1294,24 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multer"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"encoding_rs",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"memchr",
|
||||||
|
"mime",
|
||||||
|
"spin 0.9.8",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@@ -1344,9 +1347,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.3"
|
version = "0.26.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "abbbc55ad7b13aac85f9401c796dcda1b864e07fcad40ad47792eaa8932ea502"
|
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.0",
|
"bitflags 2.4.0",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -1398,9 +1412,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.0"
|
version = "0.32.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
|
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@@ -1440,7 +1454,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1451,9 +1465,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.92"
|
version = "0.9.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b"
|
checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1623,7 +1637,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1691,9 +1705,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.66"
|
version = "1.0.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -1829,15 +1843,15 @@ version = "0.11.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
|
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.3",
|
"base64 0.21.4",
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2",
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body 0.4.5",
|
"http-body",
|
||||||
"hyper 0.14.27",
|
"hyper",
|
||||||
"hyper-tls",
|
"hyper-tls",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -1869,7 +1883,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"spin",
|
"spin 0.5.2",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -1885,7 +1899,7 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"spin",
|
"spin 0.5.2",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -1919,9 +1933,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.9"
|
version = "0.38.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49"
|
checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.0",
|
"bitflags 2.4.0",
|
||||||
"errno",
|
"errno",
|
||||||
@@ -1930,6 +1944,27 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"ring",
|
||||||
|
"sct",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pemfile"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.21.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@@ -1950,7 +1985,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
"nix",
|
"nix 0.26.4",
|
||||||
"radix_trie",
|
"radix_trie",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
@@ -1983,6 +2018,12 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped-tls"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -2015,9 +2056,6 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
"git-version",
|
"git-version",
|
||||||
"hostname",
|
"hostname",
|
||||||
"http-body-util",
|
|
||||||
"hyper 1.0.0-rc.4",
|
|
||||||
"hyper-util",
|
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lexical",
|
"lexical",
|
||||||
@@ -2051,16 +2089,27 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
"to-syn-value",
|
"to-syn-value",
|
||||||
"to-syn-value_derive",
|
"to-syn-value_derive",
|
||||||
"tokio",
|
"tokio",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
|
"warp",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sct"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.9.2"
|
version = "2.9.2"
|
||||||
@@ -2123,14 +2172,14 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.105"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -2171,7 +2220,18 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest 0.10.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2255,9 +2315,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.11.0"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@@ -2271,9 +2331,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.3"
|
version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
|
checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
@@ -2285,6 +2345,12 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -2367,9 +2433,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.32"
|
version = "2.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
|
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2414,33 +2480,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.47"
|
version = "1.0.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.47"
|
version = "1.0.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.1.45"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
|
||||||
"winapi",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2464,7 +2519,7 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfcc684f2ceaec3b4e8689657c9e0944b07bf5e34563e0bd758c4d42c05c82ed"
|
checksum = "dfcc684f2ceaec3b4e8689657c9e0944b07bf5e34563e0bd758c4d42c05c82ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
"to-syn-value_derive",
|
"to-syn-value_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2476,7 +2531,7 @@ checksum = "3dfffda778de8443144ff3b042ddf14e8bc5445f0fd9fe937c3d252535dc9212"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2493,7 +2548,7 @@ dependencies = [
|
|||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2 0.5.3",
|
"socket2 0.5.4",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
@@ -2506,7 +2561,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2520,10 +2575,44 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-rustls"
|
||||||
version = "0.7.8"
|
version = "0.23.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
|
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-stream"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -2533,28 +2622,6 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower"
|
|
||||||
version = "0.4.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
|
||||||
"pin-project",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-layer"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@@ -2589,10 +2656,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "tungstenite"
|
||||||
version = "1.16.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand",
|
||||||
|
"sha1",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
@@ -2602,9 +2697,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.11"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-normalization"
|
name = "unicode-normalization"
|
||||||
@@ -2623,9 +2718,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
@@ -2635,9 +2730,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.4.0"
|
version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
|
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
@@ -2679,9 +2774,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.3"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
@@ -2697,10 +2792,36 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "warp"
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-util",
|
||||||
|
"headers",
|
||||||
|
"http",
|
||||||
|
"hyper",
|
||||||
|
"log",
|
||||||
|
"mime",
|
||||||
|
"mime_guess",
|
||||||
|
"multer",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"rustls-pemfile",
|
||||||
|
"scoped-tls",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-tungstenite",
|
||||||
|
"tokio-util",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
@@ -2729,7 +2850,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2763,7 +2884,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.32",
|
"syn 2.0.37",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@@ -2784,6 +2905,16 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -2802,9 +2933,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|||||||
17
Cargo.toml
17
Cargo.toml
@@ -21,7 +21,7 @@ ffi = ["dep:libffi"]
|
|||||||
repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
|
repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"]
|
||||||
hostname = ["dep:hostname"]
|
hostname = ["dep:hostname"]
|
||||||
tls = ["dep:native-tls"]
|
tls = ["dep:native-tls"]
|
||||||
http = ["dep:hyper", "dep:reqwest"]
|
http = ["dep:warp", "dep:reqwest"]
|
||||||
rust_beta_channel = []
|
rust_beta_channel = []
|
||||||
crypto-full = []
|
crypto-full = []
|
||||||
|
|
||||||
@@ -67,21 +67,21 @@ futures = "0.3"
|
|||||||
regex = "1.9.1"
|
regex = "1.9.1"
|
||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
derive_deref = "1.1.1"
|
derive_deref = "1.1.1"
|
||||||
http-body-util = "0.1.0-rc.2"
|
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
dashu = { version = "0.3.1", git = "https://github.com/cmpute/dashu.git" }
|
dashu = "0.4.0"
|
||||||
num-order = { version = "1.2.0" }
|
num-order = { version = "1.2.0" }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
libffi = { git = "https://github.com/coasys/libffi-rs.git", branch = "windows-space", optional = true, version = "3.2.0" }
|
libffi = { version = "3.2.0", optional = true }
|
||||||
hostname = { version = "0.3.1", optional = true }
|
hostname = { version = "0.3.1", optional = true }
|
||||||
crossterm = { version = "0.20.0", optional = true }
|
crossterm = { version = "0.20.0", optional = true }
|
||||||
ctrlc = { version = "3.2.2", optional = true }
|
ctrlc = { version = "3.2.2", optional = true }
|
||||||
rustyline = { version = "12.0.0", optional = true }
|
rustyline = { version = "12.0.0", optional = true }
|
||||||
native-tls = { version = "0.2.4", optional = true }
|
native-tls = { version = "0.2.4", optional = true }
|
||||||
hyper = { version = "=1.0.0-rc.4", features = ["full"], optional = true }
|
#hyper = { version = "=1.0.0-rc.4", features = ["full"], optional = true }
|
||||||
hyper-util = { git = "https://github.com/hyperium/hyper-util.git" }
|
#hyper-util = { git = "https://github.com/hyperium/hyper-util.git" }
|
||||||
|
warp = { version = "=0.3.5", features = ["tls"], optional = true }
|
||||||
reqwest = { version = "0.11.18", features = ["blocking"], optional = true }
|
reqwest = { version = "0.11.18", features = ["blocking"], optional = true }
|
||||||
tokio = { version = "1.28.2", features = ["full"] }
|
tokio = { version = "1.28.2", features = ["full"] }
|
||||||
|
|
||||||
@@ -114,7 +114,4 @@ maplit = "1.0.2"
|
|||||||
serial_test = "2.0.0"
|
serial_test = "2.0.0"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" }
|
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" }
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
debug = true
|
|
||||||
@@ -624,7 +624,7 @@ The modules that ship with Scryer Prolog are also called
|
|||||||
Probabilistic predicates and random number generators.
|
Probabilistic predicates and random number generators.
|
||||||
* [`http/http_open`](src/lib/http/http_open.pl) Open a stream to
|
* [`http/http_open`](src/lib/http/http_open.pl) Open a stream to
|
||||||
read answers from web servers. HTTPS is also supported.
|
read answers from web servers. HTTPS is also supported.
|
||||||
* [`http/http_server`](src/lib/http/http_server.pl) Runs a HTTP/1.1 and HTTP/2.0 web server. Uses [Hyper](https://hyper.rs) as a backend. Supports some query and form handling.
|
* [`http/http_server`](src/lib/http/http_server.pl) Runs a HTTP/1.1 and HTTP/2.0 web server. Uses [Warp](https://github.com/seanmonstar/warp) as a backend. Supports some query and form handling.
|
||||||
* [`sgml`](src/lib/sgml.pl)
|
* [`sgml`](src/lib/sgml.pl)
|
||||||
`load_html/3` and `load_xml/3` represent HTML and XML documents
|
`load_html/3` and `load_xml/3` represent HTML and XML documents
|
||||||
as Prolog terms for convenient and efficient reasoning. Use
|
as Prolog terms for convenient and efficient reasoning. Use
|
||||||
|
|||||||
@@ -558,7 +558,7 @@ enum SystemClauseType {
|
|||||||
DeterministicLengthRundown,
|
DeterministicLengthRundown,
|
||||||
#[strum_discriminants(strum(props(Arity = "7", Name = "$http_open")))]
|
#[strum_discriminants(strum(props(Arity = "7", Name = "$http_open")))]
|
||||||
HttpOpen,
|
HttpOpen,
|
||||||
#[strum_discriminants(strum(props(Arity = "2", Name = "$http_listen")))]
|
#[strum_discriminants(strum(props(Arity = "5", Name = "$http_listen")))]
|
||||||
HttpListen,
|
HttpListen,
|
||||||
#[strum_discriminants(strum(props(Arity = "7", Name = "$http_accept")))]
|
#[strum_discriminants(strum(props(Arity = "7", Name = "$http_accept")))]
|
||||||
HttpAccept,
|
HttpAccept,
|
||||||
@@ -574,7 +574,7 @@ enum SystemClauseType {
|
|||||||
PredicateDefined,
|
PredicateDefined,
|
||||||
#[strum_discriminants(strum(props(Arity = "3", Name = "$strip_module")))]
|
#[strum_discriminants(strum(props(Arity = "3", Name = "$strip_module")))]
|
||||||
StripModule,
|
StripModule,
|
||||||
#[strum_discriminants(strum(props(Arity = "4", Name = "$compile_inline_or_expanded_goal")))]
|
#[strum_discriminants(strum(props(Arity = "5", Name = "$compile_inline_or_expanded_goal")))]
|
||||||
CompileInlineOrExpandedGoal,
|
CompileInlineOrExpandedGoal,
|
||||||
#[strum_discriminants(strum(props(Arity = "arity", Name = "$fast_call")))]
|
#[strum_discriminants(strum(props(Arity = "arity", Name = "$fast_call")))]
|
||||||
FastCallN(usize),
|
FastCallN(usize),
|
||||||
@@ -601,6 +601,8 @@ enum SystemClauseType {
|
|||||||
Name = "$keysort_with_constant_var_ordering"
|
Name = "$keysort_with_constant_var_ordering"
|
||||||
)))]
|
)))]
|
||||||
KeySortWithConstantVarOrdering,
|
KeySortWithConstantVarOrdering,
|
||||||
|
#[strum_discriminants(strum(props(Arity = "0", Name = "$inference_limit_exceeded")))]
|
||||||
|
InferenceLimitExceeded,
|
||||||
REPL(REPLCodePtr),
|
REPL(REPLCodePtr),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,29 +1660,31 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
|
functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
|
||||||
}
|
}
|
||||||
&Instruction::CallIsAtom(_) |
|
&Instruction::CallIsAtom(r) |
|
||||||
&Instruction::CallIsAtomic(_) |
|
&Instruction::CallIsAtomic(r) |
|
||||||
&Instruction::CallIsCompound(_) |
|
&Instruction::CallIsCompound(r) |
|
||||||
&Instruction::CallIsInteger(_) |
|
&Instruction::CallIsInteger(r) |
|
||||||
&Instruction::CallIsNumber(_) |
|
&Instruction::CallIsNumber(r) |
|
||||||
&Instruction::CallIsRational(_) |
|
&Instruction::CallIsRational(r) |
|
||||||
&Instruction::CallIsFloat(_) |
|
&Instruction::CallIsFloat(r) |
|
||||||
&Instruction::CallIsNonVar(_) |
|
&Instruction::CallIsNonVar(r) |
|
||||||
&Instruction::CallIsVar(_) => {
|
&Instruction::CallIsVar(r) => {
|
||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("call"), [atom(name), fixnum(arity)])
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
functor!(atom!("call"), [atom(name), fixnum(arity), str(h, 0)], [rt_stub])
|
||||||
}
|
}
|
||||||
&Instruction::ExecuteIsAtom(_) |
|
&Instruction::ExecuteIsAtom(r) |
|
||||||
&Instruction::ExecuteIsAtomic(_) |
|
&Instruction::ExecuteIsAtomic(r) |
|
||||||
&Instruction::ExecuteIsCompound(_) |
|
&Instruction::ExecuteIsCompound(r) |
|
||||||
&Instruction::ExecuteIsInteger(_) |
|
&Instruction::ExecuteIsInteger(r) |
|
||||||
&Instruction::ExecuteIsNumber(_) |
|
&Instruction::ExecuteIsNumber(r) |
|
||||||
&Instruction::ExecuteIsRational(_) |
|
&Instruction::ExecuteIsRational(r) |
|
||||||
&Instruction::ExecuteIsFloat(_) |
|
&Instruction::ExecuteIsFloat(r) |
|
||||||
&Instruction::ExecuteIsNonVar(_) |
|
&Instruction::ExecuteIsNonVar(r) |
|
||||||
&Instruction::ExecuteIsVar(_) => {
|
&Instruction::ExecuteIsVar(r) => {
|
||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("execute"), [atom(name), fixnum(arity)])
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
functor!(atom!("execute"), [atom(name), fixnum(arity), str(h, 0)], [rt_stub])
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
&Instruction::CallAtomChars |
|
&Instruction::CallAtomChars |
|
||||||
@@ -1727,6 +1731,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::CallUnattributedVar |
|
&Instruction::CallUnattributedVar |
|
||||||
&Instruction::CallGetDBRefs |
|
&Instruction::CallGetDBRefs |
|
||||||
&Instruction::CallKeySortWithConstantVarOrdering |
|
&Instruction::CallKeySortWithConstantVarOrdering |
|
||||||
|
&Instruction::CallInferenceLimitExceeded |
|
||||||
&Instruction::CallFetchGlobalVar |
|
&Instruction::CallFetchGlobalVar |
|
||||||
&Instruction::CallFirstStream |
|
&Instruction::CallFirstStream |
|
||||||
&Instruction::CallFlushOutput |
|
&Instruction::CallFlushOutput |
|
||||||
@@ -1960,6 +1965,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::ExecuteUnattributedVar |
|
&Instruction::ExecuteUnattributedVar |
|
||||||
&Instruction::ExecuteGetDBRefs |
|
&Instruction::ExecuteGetDBRefs |
|
||||||
&Instruction::ExecuteKeySortWithConstantVarOrdering |
|
&Instruction::ExecuteKeySortWithConstantVarOrdering |
|
||||||
|
&Instruction::ExecuteInferenceLimitExceeded |
|
||||||
&Instruction::ExecuteFetchGlobalVar |
|
&Instruction::ExecuteFetchGlobalVar |
|
||||||
&Instruction::ExecuteFirstStream |
|
&Instruction::ExecuteFirstStream |
|
||||||
&Instruction::ExecuteFlushOutput |
|
&Instruction::ExecuteFlushOutput |
|
||||||
|
|||||||
@@ -386,8 +386,7 @@ pub(crate) fn rnd_i<'a>(n: &'a Number, arena: &mut Arena) -> Number {
|
|||||||
&Number::Rational(ref r) => {
|
&Number::Rational(ref r) => {
|
||||||
let (_, floor) = (r.fract(), r.floor());
|
let (_, floor) = (r.fract(), r.floor());
|
||||||
|
|
||||||
let result = floor.clone().try_into();
|
if let Ok(value) = (&floor).try_into() {
|
||||||
if let Ok(value) = result{
|
|
||||||
fixnum!(Number, value, arena)
|
fixnum!(Number, value, arena)
|
||||||
} else {
|
} else {
|
||||||
Number::Integer(arena_alloc!(floor, arena))
|
Number::Integer(arena_alloc!(floor, arena))
|
||||||
@@ -713,13 +712,13 @@ impl TryFrom<HeapCellValue> for Number {
|
|||||||
|
|
||||||
// Computes n ^ power. Ignores the sign of power.
|
// Computes n ^ power. Ignores the sign of power.
|
||||||
pub(crate) fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
|
pub(crate) fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
|
||||||
let mut power = Integer::from(power.abs());
|
let mut power = power.abs();
|
||||||
|
|
||||||
if power.num_eq(&0) {
|
if power.is_zero() {
|
||||||
return Integer::from(1);
|
return Integer::ONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut oddand = Integer::from(1);
|
let mut oddand = Integer::ONE;
|
||||||
|
|
||||||
while power.num_gt(&1) {
|
while power.num_gt(&1) {
|
||||||
if power.bit(0) {
|
if power.bit(0) {
|
||||||
|
|||||||
207
src/heap_iter.rs
207
src/heap_iter.rs
@@ -6,6 +6,7 @@ use crate::machine::heap::*;
|
|||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
use modular_bitfield::prelude::*;
|
use modular_bitfield::prelude::*;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@@ -79,15 +80,40 @@ impl IterStackLoc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ListElisionPolicy {
|
||||||
|
fn elide_lists() -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StackfulPreOrderHeapIter<'a> {
|
pub struct ListElider {}
|
||||||
|
|
||||||
|
impl ListElisionPolicy for ListElider {
|
||||||
|
#[inline(always)]
|
||||||
|
fn elide_lists() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NonListElider {}
|
||||||
|
|
||||||
|
impl ListElisionPolicy for NonListElider {
|
||||||
|
#[inline(always)]
|
||||||
|
fn elide_lists() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
pub heap: &'a mut Vec<HeapCellValue>,
|
pub heap: &'a mut Vec<HeapCellValue>,
|
||||||
pub machine_stack: &'a mut Stack,
|
pub machine_stack: &'a mut Stack,
|
||||||
stack: Vec<IterStackLoc>,
|
stack: Vec<IterStackLoc>,
|
||||||
h: IterStackLoc,
|
h: IterStackLoc,
|
||||||
|
_marker: PhantomData<ElideLists>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for StackfulPreOrderHeapIter<'a> {
|
impl<'a, ElideLists> Drop for StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
while let Some(h) = self.stack.pop() {
|
while let Some(h) = self.stack.pop() {
|
||||||
let cell = self.read_cell_mut(h);
|
let cell = self.read_cell_mut(h);
|
||||||
@@ -104,53 +130,14 @@ pub trait FocusedHeapIter: Iterator<Item = HeapCellValue> {
|
|||||||
fn focus(&self) -> IterStackLoc;
|
fn focus(&self) -> IterStackLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FocusedHeapIter for StackfulPreOrderHeapIter<'a> {
|
impl<'a, ElideLists: ListElisionPolicy> FocusedHeapIter for StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn focus(&self) -> IterStackLoc {
|
fn focus(&self) -> IterStackLoc {
|
||||||
self.h
|
self.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StackfulPreOrderHeapIter<'a> {
|
impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
#[inline]
|
|
||||||
fn new(heap: &'a mut Vec<HeapCellValue>, stack: &'a mut Stack, cell: HeapCellValue) -> Self {
|
|
||||||
let h = IterStackLoc::iterable_loc(heap.len(), HeapOrStackTag::Heap);
|
|
||||||
heap.push(cell);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
heap,
|
|
||||||
h,
|
|
||||||
machine_stack: stack,
|
|
||||||
stack: vec![h],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn forward_if_referent_marked(&mut self, loc: IterStackLoc) {
|
|
||||||
read_heap_cell!(self.read_cell(loc),
|
|
||||||
(HeapCellValueTag::Str |
|
|
||||||
HeapCellValueTag::Lis |
|
|
||||||
HeapCellValueTag::AttrVar |
|
|
||||||
HeapCellValueTag::Var |
|
|
||||||
HeapCellValueTag::PStrLoc, vh) => {
|
|
||||||
if self.heap[vh].get_mark_bit() {
|
|
||||||
self.read_cell_mut(loc).set_forwarding_bit(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::StackVar, vs) => {
|
|
||||||
if self.machine_stack[vs].get_mark_bit() {
|
|
||||||
self.read_cell_mut(loc).set_forwarding_bit(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn push_stack(&mut self, h: IterStackLoc) {
|
|
||||||
self.stack.push(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue {
|
pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue {
|
||||||
match loc.heap_or_stack() {
|
match loc.heap_or_stack() {
|
||||||
@@ -167,6 +154,11 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn push_stack(&mut self, h: IterStackLoc) {
|
||||||
|
self.stack.push(h);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stack_last(&self) -> Option<IterStackLoc> {
|
pub fn stack_last(&self) -> Option<IterStackLoc> {
|
||||||
for h in self.stack.iter().rev() {
|
for h in self.stack.iter().rev() {
|
||||||
@@ -222,6 +214,51 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
|
#[inline]
|
||||||
|
fn new(heap: &'a mut Vec<HeapCellValue>, stack: &'a mut Stack, cell: HeapCellValue) -> Self {
|
||||||
|
let h = IterStackLoc::iterable_loc(heap.len(), HeapOrStackTag::Heap);
|
||||||
|
heap.push(cell);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
heap,
|
||||||
|
h,
|
||||||
|
machine_stack: stack,
|
||||||
|
stack: vec![h],
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn forward_if_referent_marked(&mut self, loc: IterStackLoc) {
|
||||||
|
let cell = self.read_cell(loc);
|
||||||
|
|
||||||
|
read_heap_cell!(cell,
|
||||||
|
(HeapCellValueTag::Lis |
|
||||||
|
HeapCellValueTag::Str |
|
||||||
|
HeapCellValueTag::PStrLoc, vh) => {
|
||||||
|
let forward = if ElideLists::elide_lists() { true } else { cell.get_mark_bit() };
|
||||||
|
|
||||||
|
if forward && self.heap[vh].get_mark_bit() {
|
||||||
|
self.read_cell_mut(loc).set_forwarding_bit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::AttrVar |
|
||||||
|
HeapCellValueTag::Var, vh) => {
|
||||||
|
if self.heap[vh].get_mark_bit() {
|
||||||
|
self.read_cell_mut(loc).set_forwarding_bit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::StackVar, vs) => {
|
||||||
|
if self.machine_stack[vs].get_mark_bit() {
|
||||||
|
self.read_cell_mut(loc).set_forwarding_bit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn follow(&mut self) -> Option<HeapCellValue> {
|
fn follow(&mut self) -> Option<HeapCellValue> {
|
||||||
while let Some(h) = self.stack.pop() {
|
while let Some(h) = self.stack.pop() {
|
||||||
@@ -260,28 +297,27 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
|
|||||||
(HeapCellValueTag::Lis, vh) => {
|
(HeapCellValueTag::Lis, vh) => {
|
||||||
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
||||||
|
|
||||||
|
self.forward_if_referent_marked(loc);
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
|
|
||||||
self.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap));
|
||||||
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
||||||
|
|
||||||
self.forward_if_referent_marked(loc);
|
|
||||||
|
|
||||||
return Some(self.read_cell(h));
|
return Some(self.read_cell(h));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, vh) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, vh) => {
|
||||||
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
||||||
|
|
||||||
|
self.forward_if_referent_marked(loc);
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
||||||
self.forward_if_referent_marked(loc);
|
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::StackVar, vs) => {
|
(HeapCellValueTag::StackVar, vs) => {
|
||||||
let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack);
|
let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack);
|
||||||
|
|
||||||
|
self.forward_if_referent_marked(loc);
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack));
|
self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack));
|
||||||
self.forward_if_referent_marked(loc);
|
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::PStrOffset, offset) => {
|
(HeapCellValueTag::PStrOffset, offset) => {
|
||||||
self.push_if_unmarked(IterStackLoc::iterable_loc(offset, HeapOrStackTag::Heap));
|
self.push_if_unmarked(IterStackLoc::iterable_loc(offset, HeapOrStackTag::Heap));
|
||||||
@@ -325,7 +361,7 @@ impl<'a> StackfulPreOrderHeapIter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for StackfulPreOrderHeapIter<'a> {
|
impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
type Item = HeapCellValue;
|
type Item = HeapCellValue;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -344,11 +380,11 @@ pub(crate) fn stackless_preorder_iter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn stackful_preorder_iter<'a>(
|
pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>(
|
||||||
heap: &'a mut Vec<HeapCellValue>,
|
heap: &'a mut Vec<HeapCellValue>,
|
||||||
stack: &'a mut Stack,
|
stack: &'a mut Stack,
|
||||||
cell: HeapCellValue,
|
cell: HeapCellValue,
|
||||||
) -> StackfulPreOrderHeapIter<'a> {
|
) -> StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
StackfulPreOrderHeapIter::new(heap, stack, cell)
|
StackfulPreOrderHeapIter::new(heap, stack, cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +491,10 @@ impl<Iter: FocusedHeapIter> PostOrderIterator<Iter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type LeftistPostOrderHeapIter<'a> = PostOrderIterator<StackfulPreOrderHeapIter<'a>>;
|
pub(crate) type LeftistPostOrderHeapIter<'a, ElideLists> =
|
||||||
|
PostOrderIterator<StackfulPreOrderHeapIter<'a, ElideLists>>;
|
||||||
|
|
||||||
impl<'a> LeftistPostOrderHeapIter<'a> {
|
impl<'a, ElideLists: ListElisionPolicy> LeftistPostOrderHeapIter<'a, ElideLists> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pop_stack(&mut self) {
|
pub fn pop_stack(&mut self) {
|
||||||
if let Some((child_count, ..)) = self.parent_stack.last() {
|
if let Some((child_count, ..)) = self.parent_stack.last() {
|
||||||
@@ -476,11 +513,11 @@ impl<'a> LeftistPostOrderHeapIter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn stackful_post_order_iter<'a>(
|
pub(crate) fn stackful_post_order_iter<'a, ElideLists: ListElisionPolicy>(
|
||||||
heap: &'a mut Heap,
|
heap: &'a mut Heap,
|
||||||
stack: &'a mut Stack,
|
stack: &'a mut Stack,
|
||||||
cell: HeapCellValue,
|
cell: HeapCellValue,
|
||||||
) -> LeftistPostOrderHeapIter<'a> {
|
) -> LeftistPostOrderHeapIter<'a, ElideLists> {
|
||||||
PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, cell))
|
PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, cell))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1550,7 +1587,7 @@ mod tests {
|
|||||||
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
str_loc_as_cell!(0),
|
str_loc_as_cell!(0),
|
||||||
@@ -1585,7 +1622,7 @@ mod tests {
|
|||||||
));
|
));
|
||||||
|
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
str_loc_as_cell!(0),
|
str_loc_as_cell!(0),
|
||||||
@@ -1617,7 +1654,7 @@ mod tests {
|
|||||||
{
|
{
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||||
|
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1644,7 +1681,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(heap_loc_as_cell!(1));
|
wam.machine_st.heap.push(heap_loc_as_cell!(1));
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||||
|
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1668,7 +1705,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(empty_list_as_cell!());
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1704,7 +1741,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1736,7 +1773,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1775,7 +1812,7 @@ mod tests {
|
|||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1800,7 +1837,7 @@ mod tests {
|
|||||||
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_preorder_iter(
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1827,7 +1864,7 @@ mod tests {
|
|||||||
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_preorder_iter(
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
pstr_loc_as_cell!(0),
|
pstr_loc_as_cell!(0),
|
||||||
@@ -1862,7 +1899,7 @@ mod tests {
|
|||||||
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_preorder_iter(
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
pstr_loc_as_cell!(0),
|
pstr_loc_as_cell!(0),
|
||||||
@@ -1906,7 +1943,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.extend(functor);
|
wam.machine_st.heap.extend(functor);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -1969,7 +2006,7 @@ mod tests {
|
|||||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_preorder_iter(
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2038,7 +2075,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = StackfulPreOrderHeapIter::new(
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2059,6 +2096,10 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(iter.next().unwrap(), cyclic_link);
|
assert_eq!(iter.next().unwrap(), cyclic_link);
|
||||||
|
|
||||||
|
assert_eq!(iter.next().unwrap(), cyclic_link);
|
||||||
|
|
||||||
|
assert_eq!(iter.next().unwrap(), cyclic_link);
|
||||||
|
|
||||||
assert_eq!(iter.next(), None);
|
assert_eq!(iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2070,7 +2111,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(empty_list_as_cell!());
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_preorder_iter(
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2102,7 +2143,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(empty_list_as_cell!());
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_preorder_iter(
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2140,7 +2181,7 @@ mod tests {
|
|||||||
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
str_loc_as_cell!(0),
|
str_loc_as_cell!(0),
|
||||||
@@ -2176,7 +2217,7 @@ mod tests {
|
|||||||
|
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
// 0000 {
|
// 0000 {
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
str_loc_as_cell!(0),
|
str_loc_as_cell!(0),
|
||||||
@@ -2210,7 +2251,7 @@ mod tests {
|
|||||||
{
|
{
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||||
|
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2237,7 +2278,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(heap_loc_as_cell!(1));
|
wam.machine_st.heap.push(heap_loc_as_cell!(1));
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||||
|
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2261,7 +2302,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(empty_list_as_cell!());
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2297,7 +2338,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2329,7 +2370,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2368,7 +2409,7 @@ mod tests {
|
|||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
pstr_loc_as_cell!(0),
|
pstr_loc_as_cell!(0),
|
||||||
@@ -2392,7 +2433,7 @@ mod tests {
|
|||||||
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
pstr_loc_as_cell!(0),
|
pstr_loc_as_cell!(0),
|
||||||
@@ -2419,7 +2460,7 @@ mod tests {
|
|||||||
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
pstr_loc_as_cell!(0),
|
pstr_loc_as_cell!(0),
|
||||||
@@ -2446,7 +2487,7 @@ mod tests {
|
|||||||
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
pstr_loc_as_cell!(0),
|
pstr_loc_as_cell!(0),
|
||||||
@@ -2480,7 +2521,7 @@ mod tests {
|
|||||||
wam.machine_st.heap.extend(functor);
|
wam.machine_st.heap.extend(functor);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
@@ -2544,7 +2585,7 @@ mod tests {
|
|||||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||||
&mut wam.machine_st.heap,
|
&mut wam.machine_st.heap,
|
||||||
&mut wam.machine_st.stack,
|
&mut wam.machine_st.stack,
|
||||||
heap_loc_as_cell!(0),
|
heap_loc_as_cell!(0),
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::parser::dashu::{Integer, Rational};
|
use crate::parser::dashu::{ibig, Integer, Rational};
|
||||||
|
use crate::parser::dashu::base::RemEuclid;
|
||||||
|
use crate::parser::dashu::integer::Sign;
|
||||||
use crate::{
|
use crate::{
|
||||||
alpha_numeric_char, capital_letter_char, cut_char, decimal_digit_char, graphic_token_char,
|
alpha_numeric_char, capital_letter_char, cut_char, decimal_digit_char, graphic_token_char,
|
||||||
is_fx, is_infix, is_postfix, is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char,
|
is_fx, is_infix, is_postfix, is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char,
|
||||||
@@ -18,8 +20,6 @@ use crate::machine::stack::*;
|
|||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use dashu::base::DivRem;
|
|
||||||
use dashu::base::DivRemEuclid;
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
@@ -104,7 +104,7 @@ fn needs_bracketing(child_desc: OpDesc, op: &DirectedOp) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StackfulPreOrderHeapIter<'a> {
|
impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||||
/*
|
/*
|
||||||
* descend into the subtree where the iterator is currently parked
|
* descend into the subtree where the iterator is currently parked
|
||||||
* and check that the leftmost leaf is a number, with every node
|
* and check that the leftmost leaf is a number, with every node
|
||||||
@@ -208,6 +208,15 @@ impl NumberFocus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct CommaSeparatedCharList {
|
||||||
|
pstr: PartialString,
|
||||||
|
offset: usize,
|
||||||
|
max_depth: usize,
|
||||||
|
end_cell: HeapCellValue,
|
||||||
|
end_h: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum TokenOrRedirect {
|
enum TokenOrRedirect {
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
@@ -233,6 +242,8 @@ enum TokenOrRedirect {
|
|||||||
OpenList(Rc<Cell<(bool, usize)>>),
|
OpenList(Rc<Cell<(bool, usize)>>),
|
||||||
CloseList(Rc<Cell<(bool, usize)>>),
|
CloseList(Rc<Cell<(bool, usize)>>),
|
||||||
HeadTailSeparator,
|
HeadTailSeparator,
|
||||||
|
StackPop,
|
||||||
|
CommaSeparatedCharList(CommaSeparatedCharList),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn requires_space(atom: &str, op: &str) -> bool {
|
pub(crate) fn requires_space(atom: &str, op: &str) -> bool {
|
||||||
@@ -396,7 +407,7 @@ fn is_numbered_var(name: Atom, arity: usize) -> bool {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn negated_op_needs_bracketing(
|
fn negated_op_needs_bracketing(
|
||||||
iter: &StackfulPreOrderHeapIter,
|
iter: &StackfulPreOrderHeapIter<ListElider>,
|
||||||
op_dir: &OpDir,
|
op_dir: &OpDir,
|
||||||
op: &Option<DirectedOp>,
|
op: &Option<DirectedOp>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
@@ -480,7 +491,7 @@ pub fn fmt_float(mut fl: f64) -> String {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HCPrinter<'a, Outputter> {
|
pub struct HCPrinter<'a, Outputter> {
|
||||||
outputter: Outputter,
|
outputter: Outputter,
|
||||||
iter: StackfulPreOrderHeapIter<'a>,
|
iter: StackfulPreOrderHeapIter<'a, ListElider>,
|
||||||
atom_tbl: Arc<AtomTable>,
|
atom_tbl: Arc<AtomTable>,
|
||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
state_stack: Vec<TokenOrRedirect>,
|
state_stack: Vec<TokenOrRedirect>,
|
||||||
@@ -515,13 +526,10 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option<String>
|
|||||||
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
];
|
];
|
||||||
|
|
||||||
let n_clone: Integer = n.clone();
|
let i: usize = (&n).rem_euclid(ibig!(26)).try_into().unwrap();
|
||||||
|
let j = n / ibig!(26);
|
||||||
|
|
||||||
let i = n.div_rem_euclid(Integer::from(26)).1.to_f32().value() as usize;
|
if j.is_zero() {
|
||||||
let j = n_clone.div_rem(Integer::from(26));
|
|
||||||
let j = <(Integer, Integer)>::from(j).0;
|
|
||||||
|
|
||||||
if j == Integer::from(0) {
|
|
||||||
CHAR_CODES[i].to_string()
|
CHAR_CODES[i].to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{}{}", CHAR_CODES[i], j)
|
format!("{}{}", CHAR_CODES[i], j)
|
||||||
@@ -646,12 +654,26 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
} else if self.check_max_depth(&mut max_depth) {
|
} else if self.check_max_depth(&mut max_depth) {
|
||||||
self.iter.pop_stack();
|
if is_xfy!(spec.get_spec()) {
|
||||||
self.iter.pop_stack();
|
let left_directed_op = DirectedOp::Left(name, spec);
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
|
||||||
self.state_stack.push(TokenOrRedirect::Op(name, spec));
|
0,
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
left_directed_op,
|
||||||
|
));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Op(name, spec));
|
||||||
|
self.state_stack.push(TokenOrRedirect::StackPop);
|
||||||
|
} else { // is_yfx!
|
||||||
|
let right_directed_op = DirectedOp::Right(name, spec);
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::StackPop);
|
||||||
|
self.state_stack.push(TokenOrRedirect::Op(name, spec));
|
||||||
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
|
||||||
|
0,
|
||||||
|
right_directed_op,
|
||||||
|
));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let left_directed_op = DirectedOp::Left(name, spec);
|
let left_directed_op = DirectedOp::Left(name, spec);
|
||||||
let right_directed_op = DirectedOp::Right(name, spec);
|
let right_directed_op = DirectedOp::Right(name, spec);
|
||||||
@@ -660,6 +682,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
max_depth,
|
max_depth,
|
||||||
left_directed_op,
|
left_directed_op,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Op(name, spec));
|
self.state_stack.push(TokenOrRedirect::Op(name, spec));
|
||||||
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
|
||||||
max_depth,
|
max_depth,
|
||||||
@@ -838,54 +861,80 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_seen(&mut self) -> Option<HeapCellValue> {
|
fn check_for_seen(&mut self, max_depth: &mut usize) -> Option<HeapCellValue> {
|
||||||
if let Some(cell) = self.iter.next() {
|
if let Some(mut orig_cell) = self.iter.next() {
|
||||||
let is_cyclic = cell.get_forwarding_bit();
|
loop {
|
||||||
|
let is_cyclic = orig_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, orig_cell));
|
||||||
let cell = unmark_cell_bits!(cell);
|
let cell = unmark_cell_bits!(cell);
|
||||||
|
|
||||||
match self.var_names.get(&cell).cloned() {
|
match self.var_names.get(&cell).cloned() {
|
||||||
Some(var) if cell.is_var() => {
|
Some(var) if cell.is_var() => {
|
||||||
// If cell is an unbound variable and maps to
|
// If cell is an unbound variable and maps to
|
||||||
// a name via heap_locs, append the name to
|
// a name via heap_locs, append the name to
|
||||||
// the current output, and return None. None
|
// the current output, and return None. None
|
||||||
// short-circuits handle_heap_term.
|
// short-circuits handle_heap_term.
|
||||||
// self.iter.pop_stack();
|
// self.iter.pop_stack();
|
||||||
|
|
||||||
let var_str = var.borrow().to_string();
|
let var_str = var.borrow().to_string();
|
||||||
|
|
||||||
push_space_if_amb!(self, &var_str, {
|
push_space_if_amb!(self, &var_str, {
|
||||||
append_str!(self, &var_str);
|
append_str!(self, &var_str);
|
||||||
});
|
});
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
var_opt => {
|
|
||||||
if is_cyclic && cell.is_compound(self.iter.heap) {
|
|
||||||
// self-referential variables are marked "cyclic".
|
|
||||||
match var_opt {
|
|
||||||
Some(var) => {
|
|
||||||
// If the term is bound to a named variable,
|
|
||||||
// print the variable's name to output.
|
|
||||||
let var_str = var.borrow().to_string();
|
|
||||||
|
|
||||||
push_space_if_amb!(self, &var_str, {
|
|
||||||
append_str!(self, &var_str);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// otherwise, contract it to an ellipsis.
|
|
||||||
push_space_if_amb!(self, "...", {
|
|
||||||
append_str!(self, "...");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
var_opt => {
|
||||||
|
if is_cyclic && cell.is_compound(self.iter.heap) {
|
||||||
|
// self-referential variables are marked "cyclic".
|
||||||
|
match var_opt {
|
||||||
|
Some(var) => {
|
||||||
|
// If the term is bound to a named variable,
|
||||||
|
// print the variable's name to output.
|
||||||
|
let var_str = var.borrow().to_string();
|
||||||
|
|
||||||
Some(cell)
|
push_space_if_amb!(self, &var_str, {
|
||||||
|
append_str!(self, &var_str);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if self.max_depth == 0 || *max_depth == 0 {
|
||||||
|
// otherwise, contract it to an ellipsis.
|
||||||
|
push_space_if_amb!(self, "...", {
|
||||||
|
append_str!(self, "...");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
debug_assert!(cell.is_ref());
|
||||||
|
|
||||||
|
// as usual, the WAM's
|
||||||
|
// optimization of the Lis tag
|
||||||
|
// (conflating the location of
|
||||||
|
// the list and that of its
|
||||||
|
// first element) needs
|
||||||
|
// special consideration here
|
||||||
|
// lest we find ourselves in
|
||||||
|
// an infinite loop.
|
||||||
|
if cell.get_tag() == HeapCellValueTag::Lis {
|
||||||
|
*max_depth -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let h = cell.get_value() as usize;
|
||||||
|
self.iter.push_stack(IterStackLoc::iterable_loc(h, HeapOrStackTag::Heap));
|
||||||
|
|
||||||
|
if let Some(cell) = self.iter.next() {
|
||||||
|
orig_cell = cell;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(cell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1024,7 +1073,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
match self.op_dir.get(&(atom!("rdiv"), Fixity::In)) {
|
match self.op_dir.get(&(atom!("rdiv"), Fixity::In)) {
|
||||||
Some(op_desc) => {
|
Some(op_desc) => {
|
||||||
if r.denominator().is_one() {
|
if r.is_int() {
|
||||||
let output_str = format!("{}", r);
|
let output_str = format!("{}", r);
|
||||||
|
|
||||||
push_space_if_amb!(self, &output_str, {
|
push_space_if_amb!(self, &output_str, {
|
||||||
@@ -1093,10 +1142,19 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if max_depth limit is reached and ellipsis is printed.
|
// returns true if max_depth limit is reached and ellipsis is printed.
|
||||||
fn print_string_as_functor(&mut self, focus: usize, max_depth: usize) -> bool {
|
fn print_string_as_functor(&mut self, focus: usize, max_depth: &mut usize) -> bool {
|
||||||
let iter = HeapPStrIter::new(self.iter.heap, focus);
|
let iter = HeapPStrIter::new(self.iter.heap, focus);
|
||||||
|
|
||||||
for (char_count, c) in iter.chars().enumerate() {
|
for (char_count, c) in iter.chars().enumerate() {
|
||||||
|
if self.check_max_depth(max_depth) {
|
||||||
|
if char_count > 0 {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
append_str!(self, "'.'");
|
append_str!(self, "'.'");
|
||||||
push_char!(self, '(');
|
push_char!(self, '(');
|
||||||
|
|
||||||
@@ -1104,16 +1162,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
push_char!(self, ',');
|
push_char!(self, ',');
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Close);
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
|
|
||||||
if max_depth >= char_count + 1 {
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// proper strings are terminal so there's no need for max_depth to
|
||||||
|
// be a mutable ref here.
|
||||||
fn print_proper_string(&mut self, focus: usize, max_depth: usize) {
|
fn print_proper_string(&mut self, focus: usize, max_depth: usize) {
|
||||||
push_char!(self, '"');
|
push_char!(self, '"');
|
||||||
|
|
||||||
@@ -1201,16 +1256,14 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.at_cdr(",");
|
self.at_cdr(",");
|
||||||
self.remove_list_children(focus.value() as usize);
|
self.remove_list_children(focus.value() as usize);
|
||||||
|
|
||||||
if !self.print_string_as_functor(focus.value() as usize, max_depth) {
|
if !self.print_string_as_functor(focus.value() as usize, &mut max_depth) {
|
||||||
if end_cell == empty_list_as_cell!() {
|
if end_cell == empty_list_as_cell!() {
|
||||||
if !self.at_cdr("") {
|
if !self.at_cdr("") {
|
||||||
append_str!(self, "[]");
|
append_str!(self, "[]");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.state_stack
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
|
||||||
self.iter
|
|
||||||
.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1228,49 +1281,27 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
let switch = self.close_list(switch);
|
let switch = self.close_list(switch);
|
||||||
|
|
||||||
let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus.value() as usize);
|
let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus.value() as usize);
|
||||||
let pstr = cell_as_string!(self.iter.heap[h]);
|
|
||||||
|
|
||||||
let pstr = pstr.as_str_from(offset.get_num() as usize);
|
let offset = offset.get_num() as usize;
|
||||||
let tag = value.get_tag();
|
let tag = value.get_tag();
|
||||||
|
|
||||||
if tag == HeapCellValueTag::PStrOffset {
|
let end_h = if tag == HeapCellValueTag::PStrOffset {
|
||||||
// remove the fixnum offset from the iterator stack so we don't
|
// remove the fixnum offset from the iterator stack so we don't
|
||||||
// print an extraneous number. pstr offset value cells are never
|
// print an extraneous number. pstr offset value cells are never
|
||||||
// used by the iterator to mark cyclic terms so the removal is safe.
|
// used by the iterator to mark cyclic terms so the removal is safe.
|
||||||
self.iter.pop_stack();
|
self.iter.pop_stack();
|
||||||
}
|
Some(end_h)
|
||||||
|
} else {
|
||||||
if max_depth > 0 && pstr.chars().count() + 1 >= max_depth {
|
None
|
||||||
if tag != HeapCellValueTag::PStrOffset && tag != HeapCellValueTag::CStr {
|
};
|
||||||
self.iter.pop_stack();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if !self.max_depth_exhausted(max_depth) {
|
||||||
|
let pstr = cell_as_string!(self.iter.heap[h]);
|
||||||
|
self.state_stack.push(TokenOrRedirect::CommaSeparatedCharList(CommaSeparatedCharList {
|
||||||
|
pstr, offset, max_depth, end_cell, end_h,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
|
||||||
} else if end_cell != empty_list_as_cell!() {
|
|
||||||
if tag == HeapCellValueTag::PStrOffset {
|
|
||||||
self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
let state_stack_len = self.state_stack.len();
|
|
||||||
|
|
||||||
for (char_count, c) in pstr.chars().enumerate() {
|
|
||||||
if max_depth > 0 && char_count + 1 >= max_depth {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Comma);
|
|
||||||
self.state_stack.push(TokenOrRedirect::Char(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.state_stack[state_stack_len ..].reverse();
|
|
||||||
|
|
||||||
if let Some(TokenOrRedirect::Comma) = self.state_stack.last() {
|
|
||||||
self.state_stack.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.open_list(switch);
|
self.open_list(switch);
|
||||||
@@ -1342,11 +1373,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
let switch = self.close_list(cell);
|
let switch = self.close_list(cell);
|
||||||
|
|
||||||
self.state_stack
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
||||||
self.state_stack
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
||||||
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
|
||||||
|
|
||||||
self.open_list(switch);
|
self.open_list(switch);
|
||||||
}
|
}
|
||||||
@@ -1367,10 +1396,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
if self.numbervars && arity == 1 && name == atom!("$VAR") {
|
if self.numbervars && arity == 1 && name == atom!("$VAR") {
|
||||||
!self.iter.immediate_leaf_has_property(|addr| {
|
!self.iter.immediate_leaf_has_property(|addr| {
|
||||||
match Number::try_from(addr) {
|
match Number::try_from(addr) {
|
||||||
Ok(Number::Integer(n)) => &*n >= &Integer::from(0),
|
Ok(Number::Integer(n)) => (*n).sign() == Sign::Positive,
|
||||||
Ok(Number::Fixnum(n)) => n.get_num() >= 0,
|
Ok(Number::Fixnum(n)) => n.get_num() >= 0,
|
||||||
Ok(Number::Float(f)) => f >= OrderedFloat(0f64),
|
Ok(Number::Float(f)) => f >= OrderedFloat(0f64),
|
||||||
Ok(Number::Rational(r)) => &*r >= &Rational::from(0),
|
Ok(Number::Rational(r)) => (*r).sign() == Sign::Positive,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}) && needs_bracketing(op_desc, op)
|
}) && needs_bracketing(op_desc, op)
|
||||||
@@ -1502,20 +1531,68 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_comma_separated_char_list(&mut self, char_list: CommaSeparatedCharList) {
|
||||||
|
let CommaSeparatedCharList { pstr, offset, max_depth, end_cell, end_h } = char_list;
|
||||||
|
let pstr_str = pstr.as_str_from(offset);
|
||||||
|
|
||||||
|
if let Some(c) = pstr_str.chars().next() {
|
||||||
|
let offset = offset + c.len_utf8();
|
||||||
|
|
||||||
|
if !self.max_depth_exhausted(max_depth) {
|
||||||
|
self.state_stack.push(TokenOrRedirect::CommaSeparatedCharList(CommaSeparatedCharList {
|
||||||
|
pstr,
|
||||||
|
offset,
|
||||||
|
max_depth: max_depth.saturating_sub(1),
|
||||||
|
end_cell,
|
||||||
|
end_h,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let max_depth_allows = self.max_depth == 0 || max_depth > 1;
|
||||||
|
|
||||||
|
if max_depth_allows && pstr_str.chars().skip(1).next().is_some() {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Comma);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Char(c));
|
||||||
|
} else {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||||
|
}
|
||||||
|
} else if self.max_depth_exhausted(max_depth) {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||||
|
} else if end_cell != empty_list_as_cell!() {
|
||||||
|
if let Some(end_h) = end_h {
|
||||||
|
self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
||||||
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_heap_term(
|
fn handle_heap_term(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: Option<DirectedOp>,
|
op: Option<DirectedOp>,
|
||||||
is_functor_redirect: bool,
|
is_functor_redirect: bool,
|
||||||
max_depth: usize,
|
mut max_depth: usize,
|
||||||
) {
|
) {
|
||||||
let negated_operand = negated_op_needs_bracketing(&self.iter, self.op_dir, &op);
|
let negated_operand = negated_op_needs_bracketing(&self.iter, self.op_dir, &op);
|
||||||
|
|
||||||
|
let addr = match self.check_for_seen(&mut max_depth) {
|
||||||
|
Some(addr) => addr,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
let print_struct = |printer: &mut Self, name: Atom, arity: usize| {
|
let print_struct = |printer: &mut Self, name: Atom, arity: usize| {
|
||||||
if name == atom!("[]") && arity == 0 {
|
if name == atom!("[]") && arity == 0 {
|
||||||
if let Some(TokenOrRedirect::CloseList(_)) = printer.state_stack.last() {
|
match printer.state_stack.last() {
|
||||||
if printer.at_cdr("") {
|
Some(TokenOrRedirect::CloseList(_) | TokenOrRedirect::ChildCloseList) => {
|
||||||
return;
|
if printer.at_cdr("") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
append_str!(printer, "[]");
|
append_str!(printer, "[]");
|
||||||
@@ -1568,16 +1645,14 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let addr = match self.check_for_seen() {
|
|
||||||
Some(addr) => addr,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
if !addr.is_var()
|
if !addr.is_var()
|
||||||
&& !addr.is_compound(&self.iter.heap)
|
&& !addr.is_compound(&self.iter.heap)
|
||||||
&& self.max_depth_exhausted(max_depth)
|
&& self.max_depth_exhausted(max_depth)
|
||||||
{
|
{
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
if !(addr == atom_as_cell!(atom!("[]")) && self.at_cdr("")) {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1731,6 +1806,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
TokenOrRedirect::Space => push_char!(self, ' '),
|
TokenOrRedirect::Space => push_char!(self, ' '),
|
||||||
TokenOrRedirect::LeftCurly => push_char!(self, '{'),
|
TokenOrRedirect::LeftCurly => push_char!(self, '{'),
|
||||||
TokenOrRedirect::RightCurly => push_char!(self, '}'),
|
TokenOrRedirect::RightCurly => push_char!(self, '}'),
|
||||||
|
TokenOrRedirect::StackPop => {
|
||||||
|
self.iter.pop_stack();
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
|
}
|
||||||
|
TokenOrRedirect::CommaSeparatedCharList(char_list) => {
|
||||||
|
self.print_comma_separated_char_list(char_list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/http.rs
58
src/http.rs
@@ -1,57 +1,23 @@
|
|||||||
use bytes::Bytes;
|
use std::sync::{Arc, Mutex, Condvar};
|
||||||
use http_body_util::Full;
|
use std::io::BufRead;
|
||||||
use hyper::service::Service;
|
|
||||||
use hyper::{body::Incoming as IncomingBody, Request, Response};
|
use warp::http;
|
||||||
use std::future::Future;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
|
||||||
|
|
||||||
pub struct HttpListener {
|
pub struct HttpListener {
|
||||||
pub incoming: std::sync::mpsc::Receiver<HttpRequest>,
|
pub incoming: std::sync::mpsc::Receiver<HttpRequest>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct HttpRequest {
|
pub struct HttpRequest {
|
||||||
pub request: Request<IncomingBody>,
|
pub request_data: HttpRequestData,
|
||||||
pub response: HttpResponse,
|
pub response: HttpResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HttpResponse = Arc<(Mutex<bool>, Mutex<Option<Response<Full<Bytes>>>>, Condvar)>;
|
pub type HttpResponse = Arc<(Mutex<bool>, Mutex<Option<warp::reply::Response>>, Condvar)>;
|
||||||
|
|
||||||
pub struct HttpService {
|
pub struct HttpRequestData {
|
||||||
pub tx: std::sync::mpsc::SyncSender<HttpRequest>,
|
pub method: http::Method,
|
||||||
}
|
pub headers: http::HeaderMap,
|
||||||
|
pub path: String,
|
||||||
impl Service<Request<IncomingBody>> for HttpService {
|
pub query: String,
|
||||||
type Response = Response<Full<Bytes>>;
|
pub body: Box<dyn BufRead + Send>,
|
||||||
type Error = hyper::Error;
|
|
||||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
|
||||||
|
|
||||||
fn call(self: &HttpService, req: Request<IncomingBody>) -> Self::Future {
|
|
||||||
// new connection!
|
|
||||||
// we send the Request info to Prolog
|
|
||||||
let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
|
|
||||||
let http_request = HttpRequest {
|
|
||||||
request: req,
|
|
||||||
response: Arc::clone(&response)
|
|
||||||
};
|
|
||||||
self.tx.send(http_request).unwrap();
|
|
||||||
|
|
||||||
// we wait for the Response info from Prolog
|
|
||||||
{
|
|
||||||
let (ready, _response, cvar) = &*response;
|
|
||||||
let mut ready = ready.lock().unwrap();
|
|
||||||
while !*ready {
|
|
||||||
ready = cvar.wait(ready).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let (_, response, _) = &*response;
|
|
||||||
let response = response.lock().unwrap().take();
|
|
||||||
let res = response.expect("Data race error in HTTP Server");
|
|
||||||
Box::pin(async move {
|
|
||||||
Ok(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ call(_, _, _, _, _, _, _, _, _).
|
|||||||
% while others can be set with `set_prolog_flag/2`.
|
% while others can be set with `set_prolog_flag/2`.
|
||||||
%
|
%
|
||||||
% The flags that Scryer Prolog support are:
|
% The flags that Scryer Prolog support are:
|
||||||
%
|
%
|
||||||
% * `max_arity`: The max arity a predicate can have in Prolog. On Scryer is set to 1023. Read only.
|
% * `max_arity`: The max arity a predicate can have in Prolog. On Scryer is set to 1023. Read only.
|
||||||
% * `bounded`: `true` if integer arithmethic is bounded between some min/max values. On Scryer is always set
|
% * `bounded`: `true` if integer arithmethic is bounded between some min/max values. On Scryer is always set
|
||||||
% to `false` since it supports unbounded integer arithmethic. Read only.
|
% to `false` since it supports unbounded integer arithmethic. Read only.
|
||||||
@@ -184,7 +184,7 @@ answer_write_options(Value) :-
|
|||||||
%% set_prolog_flag(Flag, Value).
|
%% set_prolog_flag(Flag, Value).
|
||||||
%
|
%
|
||||||
% Sets the internal value of the flag. To see the list of flags supported by Scryer Prolog,
|
% Sets the internal value of the flag. To see the list of flags supported by Scryer Prolog,
|
||||||
% check `current_prolog_flag/2`. The flags that are read only will fail if you try to change their values
|
% check `current_prolog_flag/2`. The flags that are read only will fail if you try to change their values
|
||||||
set_prolog_flag(Flag, Value) :-
|
set_prolog_flag(Flag, Value) :-
|
||||||
(var(Flag) ; var(Value)),
|
(var(Flag) ; var(Value)),
|
||||||
throw(error(instantiation_error, set_prolog_flag/2)). % 8.17.1.3 a, b
|
throw(error(instantiation_error, set_prolog_flag/2)). % 8.17.1.3 a, b
|
||||||
@@ -574,26 +574,30 @@ parse_write_options(Options, OptionValues, Stub) :-
|
|||||||
|
|
||||||
|
|
||||||
parse_write_options_(double_quotes(DoubleQuotes), double_quotes-DoubleQuotes) :-
|
parse_write_options_(double_quotes(DoubleQuotes), double_quotes-DoubleQuotes) :-
|
||||||
( nonvar(DoubleQuotes),
|
( var(DoubleQuotes) ->
|
||||||
lists:member(DoubleQuotes, [true, false]),
|
throw(error(instantiation_error, _))
|
||||||
|
; lists:member(DoubleQuotes, [true, false]),
|
||||||
!
|
!
|
||||||
; throw(error(domain_error(write_option, double_quotes(DoubleQuotes)), _))
|
; throw(error(domain_error(write_option, double_quotes(DoubleQuotes)), _))
|
||||||
).
|
).
|
||||||
parse_write_options_(ignore_ops(IgnoreOps), ignore_ops-IgnoreOps) :-
|
parse_write_options_(ignore_ops(IgnoreOps), ignore_ops-IgnoreOps) :-
|
||||||
( nonvar(IgnoreOps),
|
( var(IgnoreOps) ->
|
||||||
lists:member(IgnoreOps, [true, false]),
|
throw(error(instantiation_error, _))
|
||||||
|
; lists:member(IgnoreOps, [true, false]),
|
||||||
!
|
!
|
||||||
; throw(error(domain_error(write_option, ignore_ops(IgnoreOps)), _))
|
; throw(error(domain_error(write_option, ignore_ops(IgnoreOps)), _))
|
||||||
).
|
).
|
||||||
parse_write_options_(quoted(Quoted), quoted-Quoted) :-
|
parse_write_options_(quoted(Quoted), quoted-Quoted) :-
|
||||||
( nonvar(Quoted),
|
( var(Quoted) ->
|
||||||
lists:member(Quoted, [true, false]),
|
throw(error(instantiation_error, _))
|
||||||
|
; lists:member(Quoted, [true, false]),
|
||||||
!
|
!
|
||||||
; throw(error(domain_error(write_option, quoted(Quoted)), _))
|
; throw(error(domain_error(write_option, quoted(Quoted)), _))
|
||||||
).
|
).
|
||||||
parse_write_options_(numbervars(NumberVars), numbervars-NumberVars) :-
|
parse_write_options_(numbervars(NumberVars), numbervars-NumberVars) :-
|
||||||
( nonvar(NumberVars),
|
( var(NumberVars) ->
|
||||||
lists:member(NumberVars, [true, false]),
|
throw(error(instantiation_error, _))
|
||||||
|
; lists:member(NumberVars, [true, false]),
|
||||||
!
|
!
|
||||||
; throw(error(domain_error(write_option, numbervars(NumberVars)), _))
|
; throw(error(domain_error(write_option, numbervars(NumberVars)), _))
|
||||||
).
|
).
|
||||||
@@ -601,7 +605,9 @@ parse_write_options_(variable_names(VNNames), variable_names-VNNames) :-
|
|||||||
must_be_var_names_list(VNNames),
|
must_be_var_names_list(VNNames),
|
||||||
!.
|
!.
|
||||||
parse_write_options_(max_depth(MaxDepth), max_depth-MaxDepth) :-
|
parse_write_options_(max_depth(MaxDepth), max_depth-MaxDepth) :-
|
||||||
( integer(MaxDepth),
|
( var(MaxDepth) ->
|
||||||
|
throw(error(instantiation_error, _))
|
||||||
|
; integer(MaxDepth),
|
||||||
MaxDepth >= 0,
|
MaxDepth >= 0,
|
||||||
!
|
!
|
||||||
; throw(error(domain_error(write_option, max_depth(MaxDepth)), _))
|
; throw(error(domain_error(write_option, max_depth(MaxDepth)), _))
|
||||||
@@ -715,30 +721,9 @@ parse_read_term_options(Options, OptionValues, Stub) :-
|
|||||||
parse_options_list(Options, builtins:parse_read_term_options_, DefaultOptions, OptionValues, Stub).
|
parse_options_list(Options, builtins:parse_read_term_options_, DefaultOptions, OptionValues, Stub).
|
||||||
|
|
||||||
|
|
||||||
parse_read_term_options_(singletons(Vars), singletons-Vars) :-
|
parse_read_term_options_(singletons(Vars), singletons-Vars) :- !.
|
||||||
( ( var(Vars)
|
parse_read_term_options_(variables(Vars), variables-Vars) :- !.
|
||||||
; '$skip_max_list'(_, _, Vars, Rs),
|
parse_read_term_options_(variable_names(Vars), variable_names-Vars) :- !.
|
||||||
Rs == []
|
|
||||||
) ->
|
|
||||||
!
|
|
||||||
; throw(error(domain_error(read_option, singletons(Vars)), read_term/2))
|
|
||||||
).
|
|
||||||
parse_read_term_options_(variables(Vars), variables-Vars) :-
|
|
||||||
( ( var(Vars)
|
|
||||||
; '$skip_max_list'(_, _, Vars, Rs),
|
|
||||||
Rs == []
|
|
||||||
) ->
|
|
||||||
!
|
|
||||||
; throw(error(domain_error(read_option, variables(Vars)), read_term/2))
|
|
||||||
).
|
|
||||||
parse_read_term_options_(variable_names(Vars), variable_names-Vars) :-
|
|
||||||
( ( var(Vars)
|
|
||||||
; '$skip_max_list'(_, _, Vars, Rs),
|
|
||||||
Rs == []
|
|
||||||
) ->
|
|
||||||
!
|
|
||||||
; throw(error(domain_error(read_option, variable_names(Vars)), read_term/2))
|
|
||||||
).
|
|
||||||
parse_read_term_options_(E,_) :-
|
parse_read_term_options_(E,_) :-
|
||||||
throw(error(domain_error(read_option, E), _)).
|
throw(error(domain_error(read_option, E), _)).
|
||||||
|
|
||||||
@@ -748,7 +733,7 @@ parse_read_term_options_(E,_) :-
|
|||||||
% Read Term from the stream Stream. It supports several options:
|
% Read Term from the stream Stream. It supports several options:
|
||||||
% * `variables(-Vars)` unifies Vars with a list of variables in the term. Similar to do `term_variables/2` with the new term.
|
% * `variables(-Vars)` unifies Vars with a list of variables in the term. Similar to do `term_variables/2` with the new term.
|
||||||
% * `variable_names(-Vars)` unifies Vars with a list `Name=Var` with Name describing the variable name and Var the variable itself that appears in Term.
|
% * `variable_names(-Vars)` unifies Vars with a list `Name=Var` with Name describing the variable name and Var the variable itself that appears in Term.
|
||||||
% * `singletons` similar to `variable_names` but only reports variables occurring only once in Term.
|
% * `singletons` similar to `variable_names` but only reports variables occurring only once in Term.
|
||||||
read_term(Stream, Term, Options) :-
|
read_term(Stream, Term, Options) :-
|
||||||
parse_read_term_options(Options, [Singletons, VariableNames, Variables], read_term/3),
|
parse_read_term_options(Options, [Singletons, VariableNames, Variables], read_term/3),
|
||||||
'$read_term'(Stream, Term, Singletons, Variables, VariableNames).
|
'$read_term'(Stream, Term, Singletons, Variables, VariableNames).
|
||||||
@@ -1616,7 +1601,7 @@ atom_concat(Atom_1, Atom_2, Atom_12) :-
|
|||||||
%% sub_atom(+Atom, ?Before, ?Length, ?After, ?SubAtom).
|
%% sub_atom(+Atom, ?Before, ?Length, ?After, ?SubAtom).
|
||||||
%
|
%
|
||||||
% Relates an atom to a subatom inside with some key properties:
|
% Relates an atom to a subatom inside with some key properties:
|
||||||
%
|
%
|
||||||
% * SubAtom starts at Before characters (0-based) from Atom
|
% * SubAtom starts at Before characters (0-based) from Atom
|
||||||
% * SubAtom has Length characters
|
% * SubAtom has Length characters
|
||||||
% * After SubAtom there are After characters in Atom
|
% * After SubAtom there are After characters in Atom
|
||||||
@@ -2241,4 +2226,7 @@ nl(Stream) :-
|
|||||||
%
|
%
|
||||||
% Throws an exception of the following structure: `error(ErrorTerm, ImpDef)`.
|
% Throws an exception of the following structure: `error(ErrorTerm, ImpDef)`.
|
||||||
error(Error_term, Imp_def) :-
|
error(Error_term, Imp_def) :-
|
||||||
throw(error(Error_term, Imp_def)).
|
( var(Error_term) ->
|
||||||
|
throw(error(instantiation_error, error/2))
|
||||||
|
; throw(error(Error_term, Imp_def))
|
||||||
|
).
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ arguments are different terms.
|
|||||||
|
|
||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(dcgs)).
|
:- use_module(library(dcgs)).
|
||||||
:- use_module(library(lists), [append/3]).
|
:- use_module(library(lists), [append/3, maplist/3]).
|
||||||
|
|
||||||
:- attribute dif/1.
|
:- attribute dif/1.
|
||||||
|
|
||||||
@@ -23,6 +23,32 @@ dif_set_variables([Var|Vars], X, Y) :-
|
|||||||
put_dif_att(Var, X, Y),
|
put_dif_att(Var, X, Y),
|
||||||
dif_set_variables(Vars, X, Y).
|
dif_set_variables(Vars, X, Y).
|
||||||
|
|
||||||
|
remove_goal([], _, []).
|
||||||
|
remove_goal([G0|G0s], Goal0, Goals) :-
|
||||||
|
( G0 == Goal0 ->
|
||||||
|
remove_goal(G0s, Goal0, Goals)
|
||||||
|
; Goals = [G0|Goals1],
|
||||||
|
remove_goal(G0s, Goal0, Goals1)
|
||||||
|
).
|
||||||
|
|
||||||
|
vars_remove_goal([], _).
|
||||||
|
vars_remove_goal([Var|Vars], Goal0) :-
|
||||||
|
get_atts(Var, +dif(Goals0)),
|
||||||
|
remove_goal(Goals0, Goal0, Goals),
|
||||||
|
( Goals = [] ->
|
||||||
|
put_atts(Var, -dif(_))
|
||||||
|
; put_atts(Var, +dif(Goals))
|
||||||
|
),
|
||||||
|
vars_remove_goal(Vars, Goal0).
|
||||||
|
|
||||||
|
reinforce_goal(Goal0, Goal) :-
|
||||||
|
Goal = (
|
||||||
|
term_variables(Goal0, Vars),
|
||||||
|
dif:vars_remove_goal(Vars, Goal0),
|
||||||
|
Goal0 = (L \== R),
|
||||||
|
dif(L, R)
|
||||||
|
).
|
||||||
|
|
||||||
append_goals([], _).
|
append_goals([], _).
|
||||||
append_goals([Var|Vars], Goals) :-
|
append_goals([Var|Vars], Goals) :-
|
||||||
( get_atts(Var, +dif(VarGoals)) ->
|
( get_atts(Var, +dif(VarGoals)) ->
|
||||||
@@ -34,9 +60,10 @@ append_goals([Var|Vars], Goals) :-
|
|||||||
append_goals(Vars, Goals).
|
append_goals(Vars, Goals).
|
||||||
|
|
||||||
verify_attributes(Var, Value, Goals) :-
|
verify_attributes(Var, Value, Goals) :-
|
||||||
( get_atts(Var, +dif(Goals)) ->
|
( get_atts(Var, +dif(Goals0)) ->
|
||||||
term_variables(Value, ValueVars),
|
term_variables(Value, ValueVars),
|
||||||
append_goals(ValueVars, Goals)
|
append_goals(ValueVars, Goals0),
|
||||||
|
maplist(reinforce_goal, Goals0, Goals)
|
||||||
; Goals = []
|
; Goals = []
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** This library provides an starting point to build HTTP server based applications.
|
/** This library provides an starting point to build HTTP server based applications.
|
||||||
It is based on [Hyper](https://hyper.rs/), which allows for HTTP/1.0, HTTP/1.1 and HTTP/2. However,
|
It is based on [Warp](https://github.com/seanmonstar/warp), which allows for HTTP/1.0, HTTP/1.1 and HTTP/2. However,
|
||||||
some advanced features that Hyper provides are still not accesible.
|
some advanced features that Warp provides are still not accesible.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -46,7 +46,6 @@ recommeded to use the helper predicates, which are easier to understand and clea
|
|||||||
Some things that are still missing:
|
Some things that are still missing:
|
||||||
|
|
||||||
- Read forms in multipart format
|
- Read forms in multipart format
|
||||||
- HTTP Basic Auth
|
|
||||||
- Session handling via cookies
|
- Session handling via cookies
|
||||||
- HTML Templating (but you can use [Teruel](https://github.com/aarroyoc/teruel/), [Marquete](https://github.com/aarroyoc/marquete/) or [Djota](https://github.com/aarroyoc/djota) for that)
|
- HTML Templating (but you can use [Teruel](https://github.com/aarroyoc/teruel/), [Marquete](https://github.com/aarroyoc/marquete/) or [Djota](https://github.com/aarroyoc/djota) for that)
|
||||||
*/
|
*/
|
||||||
@@ -54,14 +53,19 @@ Some things that are still missing:
|
|||||||
|
|
||||||
:- module(http_server, [
|
:- module(http_server, [
|
||||||
http_listen/2,
|
http_listen/2,
|
||||||
|
http_listen/3,
|
||||||
http_headers/2,
|
http_headers/2,
|
||||||
http_status_code/2,
|
http_status_code/2,
|
||||||
http_body/2,
|
http_body/2,
|
||||||
http_redirect/2,
|
http_redirect/2,
|
||||||
http_query/3
|
http_query/3,
|
||||||
|
http_basic_auth/4
|
||||||
]).
|
]).
|
||||||
|
|
||||||
:- meta_predicate http_listen(?, :).
|
:- meta_predicate http_listen(?, :).
|
||||||
|
:- meta_predicate http_listen(?, :, ?).
|
||||||
|
|
||||||
|
:- meta_predicate http_basic_auth(:, :, ?, ?).
|
||||||
|
|
||||||
:- use_module(library(charsio)).
|
:- use_module(library(charsio)).
|
||||||
:- use_module(library(crypto)).
|
:- use_module(library(crypto)).
|
||||||
@@ -74,25 +78,58 @@ Some things that are still missing:
|
|||||||
|
|
||||||
%% http_listen(+Port, +Handlers).
|
%% http_listen(+Port, +Handlers).
|
||||||
%
|
%
|
||||||
% Listens for HTTP connections on port Port. Each handler on the list Handlers should be of the form: `HttpVerb(PathUnification, Predicate)`.
|
% Equivalent to `http_listen(Port, Handlers, [])`.
|
||||||
% For example: `get(user/User, get_info(User))` will match an HTTP request that is a GET, the path unifies with /user/User (where User is a variable)
|
|
||||||
% and it will call `get_info` with three arguments: an `http_request` term, an `http_response` term and User.
|
|
||||||
http_listen(Port, Module:Handlers0) :-
|
http_listen(Port, Module:Handlers0) :-
|
||||||
must_be(integer, Port),
|
must_be(integer, Port),
|
||||||
must_be(list, Handlers0),
|
must_be(list, Handlers0),
|
||||||
maplist(module_qualification(Module), Handlers0, Handlers),
|
maplist(module_qualification(Module), Handlers0, Handlers),
|
||||||
http_listen_(Port, Handlers).
|
http_listen_(Port, Handlers, []).
|
||||||
|
|
||||||
|
%% http_listen(+Port, +Handlers, +Options).
|
||||||
|
%
|
||||||
|
% Listens for HTTP connections on port Port. Each handler on the list Handlers should be of the form: `HttpVerb(PathUnification, Predicate)`.
|
||||||
|
% For example: `get(user/User, get_info(User))` will match an HTTP request that is a GET, the path unifies with /user/User (where User is a variable)
|
||||||
|
% and it will call `get_info` with three arguments: an `http_request` term, an `http_response` term and User.
|
||||||
|
%
|
||||||
|
% The following options are supported:
|
||||||
|
%
|
||||||
|
% - `tls_key(+Key)` - a TLS key for HTTPS (string)
|
||||||
|
% - `tls_cert(+Cert)` - a TLS cert for HTTPS (string)
|
||||||
|
% - `content_length_limit(+Limit)` - maximum length (in bytes) for the incoming bodies. By default, 32KB.
|
||||||
|
%
|
||||||
|
% In order to have a HTTPS server (instead of plain HTTP), both `tls_key` and `tls_cert` options must be provided.
|
||||||
|
http_listen(Port, Module:Handlers0, Options) :-
|
||||||
|
must_be(integer, Port),
|
||||||
|
must_be(list, Handlers0),
|
||||||
|
must_be(list, Options),
|
||||||
|
maplist(module_qualification(Module), Handlers0, Handlers),
|
||||||
|
http_listen_(Port, Handlers, Options).
|
||||||
|
|
||||||
module_qualification(M, H0, H) :-
|
module_qualification(M, H0, H) :-
|
||||||
H0 =.. [Method, Path, Goal],
|
H0 =.. [Method, Path, Goal],
|
||||||
H =.. [Method, Path, M:Goal].
|
H =.. [Method, Path, M:Goal].
|
||||||
|
|
||||||
http_listen_(Port, Handlers) :-
|
http_listen_(Port, Handlers, Options) :-
|
||||||
|
parse_options(Options, TLSKey, TLSCert, ContentLengthLimit),
|
||||||
phrase(format_("0.0.0.0:~d", [Port]), Addr),
|
phrase(format_("0.0.0.0:~d", [Port]), Addr),
|
||||||
'$http_listen'(Addr, HttpListener),!,
|
'$http_listen'(Addr, HttpListener, TLSKey, TLSCert, ContentLengthLimit),!,
|
||||||
format("Listening at ~s\n", [Addr]),
|
format("Listening at ~s\n", [Addr]),
|
||||||
http_loop(HttpListener, Handlers).
|
http_loop(HttpListener, Handlers).
|
||||||
|
|
||||||
|
parse_options(Options, TLSKey, TLSCert, ContentLengthLimit) :-
|
||||||
|
member_option_default(tls_key, Options, "", TLSKey),
|
||||||
|
member_option_default(tls_cert, Options, "", TLSCert),
|
||||||
|
member_option_default(content_length_limit, Options, 32768, ContentLengthLimit),
|
||||||
|
must_be(integer, ContentLengthLimit).
|
||||||
|
|
||||||
|
member_option_default(Key, List, _Default, Value) :-
|
||||||
|
X =.. [Key, Value],
|
||||||
|
member(X, List).
|
||||||
|
member_option_default(Key, List, Default, Default) :-
|
||||||
|
X =.. [Key, _],
|
||||||
|
\+ member(X, List).
|
||||||
|
|
||||||
|
|
||||||
http_loop(HttpListener, Handlers) :-
|
http_loop(HttpListener, Handlers) :-
|
||||||
'$http_accept'(HttpListener, RequestMethod, RequestPath, RequestHeaders, RequestQuery, RequestStream, ResponseHandle),
|
'$http_accept'(HttpListener, RequestMethod, RequestPath, RequestHeaders, RequestQuery, RequestStream, ResponseHandle),
|
||||||
current_time(Time),
|
current_time(Time),
|
||||||
@@ -114,7 +151,7 @@ http_loop(HttpListener, Handlers) :-
|
|||||||
)
|
)
|
||||||
; (
|
; (
|
||||||
'$http_answer'(ResponseHandle, 404, [], ResponseStream),
|
'$http_answer'(ResponseHandle, 404, [], ResponseStream),
|
||||||
call_cleanup(format(ResponseStream, "Not Found"), close(ResponseStream)))
|
call_cleanup(format(ResponseStream, "Not Found", []), close(ResponseStream)))
|
||||||
),
|
),
|
||||||
http_loop(HttpListener, Handlers).
|
http_loop(HttpListener, Handlers).
|
||||||
|
|
||||||
@@ -263,25 +300,21 @@ http_query(http_request(_, _, Queries), Key, Value) :- member(Key-Value, Queries
|
|||||||
|
|
||||||
parse_queries([Key-Value|Queries]) -->
|
parse_queries([Key-Value|Queries]) -->
|
||||||
string_without("=", Key0),
|
string_without("=", Key0),
|
||||||
{
|
|
||||||
phrase(url_decode(Key), Key0)
|
|
||||||
},
|
|
||||||
"=",
|
"=",
|
||||||
string_without("&", Value0),
|
string_without("&", Value0),
|
||||||
{
|
|
||||||
phrase(url_decode(Value), Value0)
|
|
||||||
},
|
|
||||||
"&",
|
"&",
|
||||||
parse_queries(Queries).
|
parse_queries(Queries),
|
||||||
|
{
|
||||||
|
phrase(url_decode(Key), Key0),
|
||||||
|
phrase(url_decode(Value), Value0)
|
||||||
|
}.
|
||||||
|
|
||||||
parse_queries([Key-Value]) -->
|
parse_queries([Key-Value]) -->
|
||||||
string_without("=", Key0),
|
string_without("=", Key0),
|
||||||
{
|
|
||||||
phrase(url_decode(Key), Key0)
|
|
||||||
},
|
|
||||||
"=",
|
"=",
|
||||||
string_without(" ", Value0),
|
string_without(" ", Value0),
|
||||||
{
|
{
|
||||||
|
phrase(url_decode(Key), Key0),
|
||||||
phrase(url_decode(Value), Value0)
|
phrase(url_decode(Value), Value0)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
@@ -292,9 +325,13 @@ parse_queries([]) -->
|
|||||||
url_decode([Char|Chars]) -->
|
url_decode([Char|Chars]) -->
|
||||||
[Char],
|
[Char],
|
||||||
{
|
{
|
||||||
Char \= '%'
|
Char \= '%',
|
||||||
|
Char \= (+)
|
||||||
},
|
},
|
||||||
url_decode(Chars).
|
url_decode(Chars).
|
||||||
|
url_decode([' '|Chars]) -->
|
||||||
|
"+",
|
||||||
|
url_decode(Chars).
|
||||||
url_decode([Char|Chars]) -->
|
url_decode([Char|Chars]) -->
|
||||||
"%",
|
"%",
|
||||||
[A],
|
[A],
|
||||||
@@ -352,3 +389,49 @@ url_decode([Char|Chars]) -->
|
|||||||
url_decode(Chars).
|
url_decode(Chars).
|
||||||
|
|
||||||
url_decode([]) --> [].
|
url_decode([]) --> [].
|
||||||
|
|
||||||
|
%% http_basic_auth(+LoginPredicate, +Handler, +Request, -Response)
|
||||||
|
%
|
||||||
|
% Metapredicate that wraps an existing Handler with an HTTP Basic Auth flow.
|
||||||
|
% Checks if a given user + password is authorized to execute that handler, returning 401
|
||||||
|
% if it's not satisfied.
|
||||||
|
%
|
||||||
|
% `LoginPredicate` must be a predicate of arity 2 that takes a User and a Password.
|
||||||
|
% `Handler` will have, in addition to the Request and Response arguments, a User argument
|
||||||
|
% containing the User given in the authentication.
|
||||||
|
%
|
||||||
|
% Example:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
|
% main :-
|
||||||
|
% http_listen(8800,[get('/', http_basic_auth(login, inside_handler("data")))]).
|
||||||
|
%
|
||||||
|
% login(User, Pass) :-
|
||||||
|
% User = "aarroyoc",
|
||||||
|
% Pass = "123456".
|
||||||
|
%
|
||||||
|
% inside_handler(Data, User, Request, Response) :-
|
||||||
|
% http_body(Response, text(User)).
|
||||||
|
% ```
|
||||||
|
http_basic_auth(LoginPredicate, Handler, Request, Response) :-
|
||||||
|
http_headers(Request, Headers),
|
||||||
|
member("authorization"-AuthorizationStr, Headers),
|
||||||
|
append("Basic ", Coded, AuthorizationStr),
|
||||||
|
chars_base64(UserPass, Coded, []),
|
||||||
|
append(User, [':'|Password], UserPass),
|
||||||
|
(
|
||||||
|
call(LoginPredicate, User, Password) ->
|
||||||
|
call(Handler, User, Request, Response)
|
||||||
|
; http_basic_auth_unauthorized_response(Response)
|
||||||
|
).
|
||||||
|
|
||||||
|
http_basic_auth(_LoginPredicate, _Handler, Request, Response) :-
|
||||||
|
http_headers(Request, Headers),
|
||||||
|
\+ member("authorization"-_, Headers),
|
||||||
|
http_basic_auth_unauthorized_response(Response).
|
||||||
|
|
||||||
|
http_basic_auth_unauthorized_response(Response) :-
|
||||||
|
http_status_code(Response, 401),
|
||||||
|
http_headers(Response, ["www-authenticate"-"Basic realm=\"Scryer Prolog\", charset=\"UTF-8\""]),
|
||||||
|
http_body(Response, text("Unauthorized")).
|
||||||
|
|
||||||
|
|||||||
@@ -214,27 +214,6 @@ run_cleaners_without_handling(Cp) :-
|
|||||||
|
|
||||||
% call_with_inference_limit
|
% call_with_inference_limit
|
||||||
|
|
||||||
:- non_counted_backtracking end_block/4.
|
|
||||||
|
|
||||||
end_block(_, Bb, NBb, _L) :-
|
|
||||||
'$clean_up_block'(NBb),
|
|
||||||
'$reset_block'(Bb).
|
|
||||||
end_block(B, _Bb, NBb, L) :-
|
|
||||||
'$install_inference_counter'(B, L, _),
|
|
||||||
'$reset_block'(NBb),
|
|
||||||
'$fail'.
|
|
||||||
|
|
||||||
:- non_counted_backtracking handle_ile/3.
|
|
||||||
|
|
||||||
handle_ile(B, inference_limit_exceeded(B), R) :-
|
|
||||||
!,
|
|
||||||
R = inference_limit_exceeded,
|
|
||||||
'$pop_ball_stack'.
|
|
||||||
handle_ile(B, _, _) :-
|
|
||||||
'$remove_call_policy_check'(B),
|
|
||||||
'$pop_from_ball_stack',
|
|
||||||
'$unwind_stack'.
|
|
||||||
|
|
||||||
:- meta_predicate(call_with_inference_limit(0, ?, ?)).
|
:- meta_predicate(call_with_inference_limit(0, ?, ?)).
|
||||||
|
|
||||||
:- non_counted_backtracking call_with_inference_limit/3.
|
:- non_counted_backtracking call_with_inference_limit/3.
|
||||||
@@ -257,8 +236,6 @@ call_with_inference_limit(G, L, R) :-
|
|||||||
call_with_inference_limit(G, L, R, Bb, B),
|
call_with_inference_limit(G, L, R, Bb, B),
|
||||||
'$remove_call_policy_check'(B).
|
'$remove_call_policy_check'(B).
|
||||||
|
|
||||||
install_inference_counter(B, L, Count0) :-
|
|
||||||
'$install_inference_counter'(B, L, Count0).
|
|
||||||
|
|
||||||
:- meta_predicate(call_with_inference_limit(0,?,?,?,?)).
|
:- meta_predicate(call_with_inference_limit(0,?,?,?,?)).
|
||||||
|
|
||||||
@@ -266,23 +243,34 @@ install_inference_counter(B, L, Count0) :-
|
|||||||
|
|
||||||
call_with_inference_limit(G, L, R, Bb, B) :-
|
call_with_inference_limit(G, L, R, Bb, B) :-
|
||||||
'$install_new_block'(NBb),
|
'$install_new_block'(NBb),
|
||||||
'$install_inference_counter'(B, L, Count0),
|
'$install_inference_counter'(NBb, L, Count0),
|
||||||
'$call_with_inference_counting'(call(G)),
|
'$call_with_inference_counting'(call(G)),
|
||||||
'$inference_level'(R, B),
|
'$inference_level'(R, B),
|
||||||
'$remove_inference_counter'(B, Count1),
|
'$remove_inference_counter'(NBb, Count1),
|
||||||
Diff is L - (Count1 - Count0),
|
Diff is L - (Count1 - Count0),
|
||||||
end_block(B, Bb, NBb, Diff).
|
( '$clean_up_block'(NBb),
|
||||||
|
'$reset_block'(Bb)
|
||||||
|
; '$install_inference_counter'(NBb, Diff, _),
|
||||||
|
'$reset_block'(NBb),
|
||||||
|
'$fail'
|
||||||
|
).
|
||||||
call_with_inference_limit(_, _, R, Bb, B) :-
|
call_with_inference_limit(_, _, R, Bb, B) :-
|
||||||
|
( '$inference_limit_exceeded' ->
|
||||||
|
R = inference_limit_exceeded
|
||||||
|
; true
|
||||||
|
),
|
||||||
|
'$get_current_block'(NBb),
|
||||||
|
'$remove_inference_counter'(NBb, _),
|
||||||
'$reset_block'(Bb),
|
'$reset_block'(Bb),
|
||||||
'$remove_inference_counter'(B, _),
|
'$remove_call_policy_check'(B),
|
||||||
( '$get_ball'(Ball),
|
( '$get_ball'(_),
|
||||||
'$push_ball_stack',
|
'$push_ball_stack',
|
||||||
'$get_cp'(Cp),
|
'$get_cp'(Cp),
|
||||||
'$set_cp_by_default'(Cp)
|
'$set_cp_by_default'(Cp),
|
||||||
; '$remove_call_policy_check'(B),
|
'$pop_from_ball_stack',
|
||||||
'$fail'
|
'$unwind_stack'
|
||||||
),
|
; nonvar(R)
|
||||||
handle_ile(B, Ball, R).
|
).
|
||||||
|
|
||||||
%% partial_string(String, L, L0)
|
%% partial_string(String, L, L0)
|
||||||
%
|
%
|
||||||
|
|||||||
147
src/lib/pio.pl
147
src/lib/pio.pl
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
:- module(pio, [phrase_from_file/2,
|
:- module(pio, [phrase_from_file/2,
|
||||||
phrase_from_file/3,
|
phrase_from_file/3,
|
||||||
|
phrase_from_stream/2,
|
||||||
phrase_to_file/2,
|
phrase_to_file/2,
|
||||||
phrase_to_file/3,
|
phrase_to_file/3,
|
||||||
phrase_to_stream/2
|
phrase_to_stream/2
|
||||||
@@ -17,16 +18,30 @@
|
|||||||
:- use_module(library(dcgs)).
|
:- use_module(library(dcgs)).
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
:- use_module(library(freeze)).
|
:- use_module(library(freeze)).
|
||||||
:- use_module(library(iso_ext), [setup_call_cleanup/3, partial_string/3]).
|
:- use_module(library(gensym)).
|
||||||
:- use_module(library(lists), [member/2, maplist/2]).
|
:- use_module(library(iso_ext), [
|
||||||
|
bb_get/2, bb_put/2, setup_call_cleanup/3, partial_string/3, partial_string_tail/2
|
||||||
|
]).
|
||||||
|
:- use_module(library(lists), [append/3, length/2, member/2, maplist/2]).
|
||||||
:- use_module(library(charsio), [get_n_chars/3]).
|
:- use_module(library(charsio), [get_n_chars/3]).
|
||||||
|
|
||||||
:- meta_predicate(phrase_from_file(2, ?)).
|
:- meta_predicate(phrase_from_file(2, ?)).
|
||||||
:- meta_predicate(phrase_from_file(2, ?, ?)).
|
:- meta_predicate(phrase_from_file(2, ?, ?)).
|
||||||
|
:- meta_predicate(phrase_from_stream(2, ?)).
|
||||||
:- meta_predicate(phrase_to_file(2, ?)).
|
:- meta_predicate(phrase_to_file(2, ?)).
|
||||||
:- meta_predicate(phrase_to_file(2, ?, ?)).
|
:- meta_predicate(phrase_to_file(2, ?, ?)).
|
||||||
:- meta_predicate(phrase_to_stream(2, ?)).
|
:- meta_predicate(phrase_to_stream(2, ?)).
|
||||||
|
|
||||||
|
|
||||||
|
%% phrase_from_stream(+GRBody, +Stream)
|
||||||
|
%
|
||||||
|
% True if grammar rule body GRBody covers the contents of the stream,
|
||||||
|
% represented as a list of characters.
|
||||||
|
|
||||||
|
phrase_from_stream(GRBody, Stream) :-
|
||||||
|
stream_to_lazy_list(Stream, Ls),
|
||||||
|
phrase(GRBody, Ls).
|
||||||
|
|
||||||
%% phrase_from_file(+GRBody, +File)
|
%% phrase_from_file(+GRBody, +File)
|
||||||
%
|
%
|
||||||
% True if grammar rule body GRBody covers the contents of File,
|
% True if grammar rule body GRBody covers the contents of File,
|
||||||
@@ -48,25 +63,121 @@ phrase_from_file(NT, File, Options) :-
|
|||||||
member(Type, [text,binary])
|
member(Type, [text,binary])
|
||||||
; Type = text
|
; Type = text
|
||||||
),
|
),
|
||||||
setup_call_cleanup(open(File, read, Stream, [reposition(true)|Options]),
|
setup_call_cleanup(
|
||||||
( stream_to_lazy_list(Stream, Xs),
|
open(File, read, Stream, Options),
|
||||||
phrase(NT, Xs) ),
|
phrase_from_stream(NT, Stream),
|
||||||
close(Stream))
|
close(Stream)
|
||||||
).
|
)
|
||||||
|
).
|
||||||
|
|
||||||
|
% How many chars to read from stream and buffer in each step
|
||||||
|
chars_to_read(4096).
|
||||||
|
|
||||||
stream_to_lazy_list(Stream, Xs) :-
|
stream_to_lazy_list(Stream, Ls) :-
|
||||||
stream_property(Stream, position(Pos)),
|
get_stream_buffer_position(Stream, Pos),
|
||||||
freeze(Xs, reader_step(Stream, Pos, Xs)).
|
freeze(Ls, render_step(Stream, Pos, Ls)).
|
||||||
|
|
||||||
reader_step(Stream, Pos, Xs0) :-
|
render_step(Stream, Pos, Ls) :-
|
||||||
set_stream_position(Stream, Pos),
|
set_stream_buffer_position(Stream, Pos),
|
||||||
( at_end_of_stream(Stream)
|
( buffer_at_end_of_stream(Stream) ->
|
||||||
-> Xs0 = []
|
Ls = []
|
||||||
; get_n_chars(Stream, 4096, Cs),
|
; chars_to_read(CharsToRead),
|
||||||
partial_string(Cs, Xs0, Xs),
|
buffer_get_n_chars(Stream, CharsToRead, Chars),
|
||||||
stream_to_lazy_list(Stream, Xs)
|
partial_string(Chars, Ls, Ls0),
|
||||||
).
|
stream_to_lazy_list(Stream, Ls0)
|
||||||
|
).
|
||||||
|
|
||||||
|
buffer_at_end_of_stream(Stream) :-
|
||||||
|
stream_bufferids(Stream, _, BufferPosId, _),
|
||||||
|
bb_get(BufferPosId, Pos),
|
||||||
|
Pos = eof.
|
||||||
|
|
||||||
|
get_stream_buffer_position(Stream, Pos) :-
|
||||||
|
stream_bufferids(Stream, _, BufferPosId, _),
|
||||||
|
bb_get(BufferPosId, Pos).
|
||||||
|
|
||||||
|
set_stream_buffer_position(Stream, Pos) :-
|
||||||
|
stream_bufferids(Stream, _, BufferPosId, _),
|
||||||
|
bb_put(BufferPosId, Pos).
|
||||||
|
|
||||||
|
buffer_get_n_chars(Stream, N, Chars) :-
|
||||||
|
stream_bufferids(Stream, BufferId, BufferPosId, BufferLenId),
|
||||||
|
buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N),
|
||||||
|
bb_get(BufferId, Buffer),
|
||||||
|
bb_get(BufferPosId, BufferPos),
|
||||||
|
( BufferPos = eof ->
|
||||||
|
Chars = []
|
||||||
|
; string_get_n_chars(Buffer, BufferPos, N, Chars),
|
||||||
|
length(Chars, NChars),
|
||||||
|
( NChars = 0 ->
|
||||||
|
BufferPos1 = eof
|
||||||
|
; BufferPos1 is BufferPos + NChars
|
||||||
|
),
|
||||||
|
bb_put(BufferPosId, BufferPos1)
|
||||||
|
).
|
||||||
|
|
||||||
|
buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N) :-
|
||||||
|
bb_get(BufferPosId, BufferPos),
|
||||||
|
bb_get(BufferLenId, BufferLen),
|
||||||
|
( BufferLen < BufferPos + N ->
|
||||||
|
bb_get(BufferId, Buffer),
|
||||||
|
(
|
||||||
|
( var(Buffer) ->
|
||||||
|
BufferTail = Buffer
|
||||||
|
; partial_string_last_tail(Buffer, BufferTail)
|
||||||
|
) ->
|
||||||
|
( at_end_of_stream(Stream) ->
|
||||||
|
BufferTail = [],
|
||||||
|
bb_put(BufferId, Buffer)
|
||||||
|
; chars_to_read(CharsToRead),
|
||||||
|
get_n_chars(Stream, CharsToRead, Chars),
|
||||||
|
length(Chars, NChars),
|
||||||
|
partial_string(Chars, BufferTail, _),
|
||||||
|
bb_put(BufferId, Buffer),
|
||||||
|
BufferLen1 is BufferLen + NChars,
|
||||||
|
bb_put(BufferLenId, BufferLen1),
|
||||||
|
buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N)
|
||||||
|
)
|
||||||
|
; true
|
||||||
|
)
|
||||||
|
; true
|
||||||
|
).
|
||||||
|
|
||||||
|
partial_string_last_tail(PartialString, PartialStringTail) :-
|
||||||
|
partial_string_tail(PartialString, PartialStringTail0),
|
||||||
|
( var(PartialStringTail0) ->
|
||||||
|
PartialStringTail = PartialStringTail0
|
||||||
|
; partial_string_last_tail(PartialStringTail0, PartialStringTail)
|
||||||
|
).
|
||||||
|
|
||||||
|
string_get_n_chars(String, Pos, N, Chars) :-
|
||||||
|
'$skip_max_list'(_, Pos, String, String1),
|
||||||
|
'$skip_max_list'(N1, N, String1, _),
|
||||||
|
length(Chars, N1),
|
||||||
|
append(Chars, _, String1).
|
||||||
|
|
||||||
|
stream_bufferids(Stream, BufferId, BufferPosId, BufferLenId) :-
|
||||||
|
( bb_get(streams_buffers, _) ->
|
||||||
|
true
|
||||||
|
; bb_put(streams_buffers, [])
|
||||||
|
),
|
||||||
|
bb_get(streams_buffers, StreamsBuffers),
|
||||||
|
( member(
|
||||||
|
stream_buffer(Stream, BufferId, BufferPosId, BufferLenId),
|
||||||
|
StreamsBuffers
|
||||||
|
) ->
|
||||||
|
true
|
||||||
|
; gensym(buffer, BufferId),
|
||||||
|
gensym(buffer_pos, BufferPosId),
|
||||||
|
gensym(buffer_len, BufferLenId),
|
||||||
|
bb_put(
|
||||||
|
streams_buffers,
|
||||||
|
[stream_buffer(Stream, BufferId, BufferPosId, BufferLenId)|StreamsBuffers]
|
||||||
|
),
|
||||||
|
bb_put(BufferId, _),
|
||||||
|
bb_put(BufferPosId, 0),
|
||||||
|
bb_put(BufferLenId, 0)
|
||||||
|
).
|
||||||
|
|
||||||
%% phrase_to_stream(+GRBody, +Stream)
|
%% phrase_to_stream(+GRBody, +Stream)
|
||||||
%
|
%
|
||||||
|
|||||||
@@ -380,6 +380,59 @@ remove_module(Module, Evacuable) :-
|
|||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
|
predicate_indicator(PI) :-
|
||||||
|
( var(PI) ->
|
||||||
|
throw(error(instantiation_error, _))
|
||||||
|
; PI = Name/Arity,
|
||||||
|
must_be(atom, Name),
|
||||||
|
must_be(integer, Arity),
|
||||||
|
Arity >= 0
|
||||||
|
).
|
||||||
|
|
||||||
|
predicate_indicator_sequence(PI_Seq) :-
|
||||||
|
( var(PI_Seq) ->
|
||||||
|
throw(error(instantiation_error, load/1))
|
||||||
|
; PI_Seq = (PI, PIs),
|
||||||
|
predicate_indicator(PI),
|
||||||
|
( predicate_indicator(PIs) ->
|
||||||
|
true
|
||||||
|
; predicate_indicator_sequence(PIs)
|
||||||
|
)
|
||||||
|
).
|
||||||
|
|
||||||
|
:- meta_predicate add_predicate_declaration(3, ?).
|
||||||
|
|
||||||
|
add_predicate_declaration(Handler, Name/Arity) :-
|
||||||
|
predicate_indicator(Name/Arity),
|
||||||
|
prolog_load_context(module, Module),
|
||||||
|
call(Handler, Module, Name, Arity).
|
||||||
|
add_predicate_declaration(Handler, Module:Name/Arity) :-
|
||||||
|
must_be(atom, Module),
|
||||||
|
predicate_indicator(Name/Arity),
|
||||||
|
call(Handler, Module, Name, Arity).
|
||||||
|
add_predicate_declaration(Handler, [PI|PIs]) :-
|
||||||
|
'$skip_max_list'(_, _, PIs, Tail),
|
||||||
|
( Tail == [],
|
||||||
|
maplist(loader:predicate_indicator, PIs) ->
|
||||||
|
maplist(loader:add_predicate_declaration(Handler), [PI|PIs])
|
||||||
|
; throw(error(type_error(predicate_indicator_list, [PI|PIs]), load/1))
|
||||||
|
).
|
||||||
|
add_predicate_declaration(Handler, (PI, PIs)) :-
|
||||||
|
( predicate_indicator_sequence((PI, PIs)) ->
|
||||||
|
add_predicate_declaration(Handler, PI),
|
||||||
|
add_predicate_declaration(Handler, PIs)
|
||||||
|
; throw(error(type_error(predicate_indicator_sequence, (PI, PIs)), load/1))
|
||||||
|
).
|
||||||
|
|
||||||
|
add_dynamic_predicate(Evacuable, Module, Name, Arity) :-
|
||||||
|
'$add_dynamic_predicate'(Module, Name, Arity, Evacuable).
|
||||||
|
|
||||||
|
add_multifile_predicate(Evacuable, Module, Name, Arity) :-
|
||||||
|
'$add_multifile_predicate'(Module, Name, Arity, Evacuable).
|
||||||
|
|
||||||
|
add_discontiguous_predicate(Evacuable, Module, Name, Arity) :-
|
||||||
|
'$add_discontiguous_predicate'(Module, Name, Arity, Evacuable).
|
||||||
|
|
||||||
compile_declaration(use_module(Module), Evacuable) :-
|
compile_declaration(use_module(Module), Evacuable) :-
|
||||||
use_module(Module, [], Evacuable).
|
use_module(Module, [], Evacuable).
|
||||||
compile_declaration(use_module(Module, Exports), Evacuable) :-
|
compile_declaration(use_module(Module, Exports), Evacuable) :-
|
||||||
@@ -392,39 +445,12 @@ compile_declaration(module(Module, Exports), Evacuable) :-
|
|||||||
'$declare_module'(Module, Exports, Evacuable)
|
'$declare_module'(Module, Exports, Evacuable)
|
||||||
; type_error(atom, Module, load/1)
|
; type_error(atom, Module, load/1)
|
||||||
).
|
).
|
||||||
compile_declaration(dynamic(Module:Name/Arity), Evacuable) :-
|
compile_declaration(dynamic(PIs), Evacuable) :-
|
||||||
!,
|
add_predicate_declaration(loader:add_dynamic_predicate(Evacuable), PIs).
|
||||||
must_be(atom, Module),
|
compile_declaration(multifile(PIs), Evacuable) :-
|
||||||
must_be(atom, Name),
|
add_predicate_declaration(loader:add_multifile_predicate(Evacuable), PIs).
|
||||||
must_be(integer, Arity),
|
compile_declaration(discontiguous(PIs), Evacuable) :-
|
||||||
'$add_dynamic_predicate'(Module, Name, Arity, Evacuable).
|
add_predicate_declaration(loader:add_discontiguous_predicate(Evacuable), PIs).
|
||||||
compile_declaration(dynamic(Name/Arity), Evacuable) :-
|
|
||||||
must_be(atom, Name),
|
|
||||||
must_be(integer, Arity),
|
|
||||||
prolog_load_context(module, Module),
|
|
||||||
'$add_dynamic_predicate'(Module, Name, Arity, Evacuable).
|
|
||||||
compile_declaration(multifile(Module:Name/Arity), Evacuable) :-
|
|
||||||
!,
|
|
||||||
must_be(atom, Module),
|
|
||||||
must_be(atom, Name),
|
|
||||||
must_be(integer, Arity),
|
|
||||||
'$add_multifile_predicate'(Module, Name, Arity, Evacuable).
|
|
||||||
compile_declaration(multifile(Name/Arity), Evacuable) :-
|
|
||||||
must_be(atom, Name),
|
|
||||||
must_be(integer, Arity),
|
|
||||||
prolog_load_context(module, Module),
|
|
||||||
'$add_multifile_predicate'(Module, Name, Arity, Evacuable).
|
|
||||||
compile_declaration(discontiguous(Module:Name/Arity), Evacuable) :-
|
|
||||||
!,
|
|
||||||
must_be(atom, Module),
|
|
||||||
must_be(atom, Name),
|
|
||||||
must_be(integer, Arity),
|
|
||||||
'$add_discontiguous_predicate'(Module, Name, Arity, Evacuable).
|
|
||||||
compile_declaration(discontiguous(Name/Arity), Evacuable) :-
|
|
||||||
must_be(atom, Name),
|
|
||||||
must_be(integer, Arity),
|
|
||||||
prolog_load_context(module, Module),
|
|
||||||
'$add_discontiguous_predicate'(Module, Name, Arity, Evacuable).
|
|
||||||
compile_declaration(initialization(Goal), Evacuable) :-
|
compile_declaration(initialization(Goal), Evacuable) :-
|
||||||
prolog_load_context(module, Module),
|
prolog_load_context(module, Module),
|
||||||
assertz(Module:'$initialization_goals'(Goal)).
|
assertz(Module:'$initialization_goals'(Goal)).
|
||||||
@@ -717,7 +743,7 @@ expand_subgoal(UnexpandedGoals, MS, M, ExpandedGoals, HeadVars) :-
|
|||||||
expand_module_names(UnexpandedGoals4, MetaSpecs, Module1, ExpandedGoals0, HeadVars)
|
expand_module_names(UnexpandedGoals4, MetaSpecs, Module1, ExpandedGoals0, HeadVars)
|
||||||
; ExpandedGoals0 = UnexpandedGoals4
|
; ExpandedGoals0 = UnexpandedGoals4
|
||||||
),
|
),
|
||||||
'$compile_inline_or_expanded_goal'(ExpandedGoals0, SuppArgs, ExpandedGoals1, Module1),
|
'$compile_inline_or_expanded_goal'(ExpandedGoals0, SuppArgs, ExpandedGoals1, Module1, UnexpandedGoals0),
|
||||||
expand_module_name(ExpandedGoals1, MS, Module1, ExpandedGoals).
|
expand_module_name(ExpandedGoals1, MS, Module1, ExpandedGoals).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use dashu::base::Abs;
|
use dashu::base::Abs;
|
||||||
use dashu::base::DivRem;
|
|
||||||
use dashu::base::Gcd;
|
use dashu::base::Gcd;
|
||||||
use dashu::integer::IBig;
|
|
||||||
use divrem::*;
|
use divrem::*;
|
||||||
use num_order::NumOrd;
|
use num_order::NumOrd;
|
||||||
|
|
||||||
@@ -562,7 +560,7 @@ pub(crate) fn rdiv(
|
|||||||
r1: TypedArenaPtr<Rational>,
|
r1: TypedArenaPtr<Rational>,
|
||||||
r2: TypedArenaPtr<Rational>,
|
r2: TypedArenaPtr<Rational>,
|
||||||
) -> Result<Rational, MachineStubGen> {
|
) -> Result<Rational, MachineStubGen> {
|
||||||
if &*r2 == &Rational::from(0) {
|
if r2.is_zero() {
|
||||||
let stub_gen = || {
|
let stub_gen = || {
|
||||||
let rdiv_atom = atom!("rdiv");
|
let rdiv_atom = atom!("rdiv");
|
||||||
functor_stub(rdiv_atom, 2)
|
functor_stub(rdiv_atom, 2)
|
||||||
@@ -596,7 +594,7 @@ pub(crate) fn idiv(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||||
if (&*n2).num_eq(&0) {
|
if n2.is_zero() {
|
||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
Ok(Number::arena_from(Integer::from(n1) / &*n2, arena))
|
Ok(Number::arena_from(Integer::from(n1) / &*n2, arena))
|
||||||
@@ -610,13 +608,10 @@ pub(crate) fn idiv(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
if (&*n2).num_eq(&0) {
|
if n2.is_zero() {
|
||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
Ok(Number::arena_from(
|
Ok(Number::arena_from(&*n1 / &*n2, arena))
|
||||||
<(Integer, Integer)>::from((&*n1).div_rem(&*n2)).0,
|
|
||||||
arena,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Fixnum(_), n2) | (Number::Integer(_), n2) => {
|
(Number::Fixnum(_), n2) | (Number::Integer(_), n2) => {
|
||||||
@@ -853,6 +848,16 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
|||||||
functor_stub(mod_atom, 2)
|
functor_stub(mod_atom, 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn ibig_rem_floor(n1: &Integer, n2: &Integer) -> Integer {
|
||||||
|
if n1 > &Integer::ZERO && n2 < &Integer::ZERO {
|
||||||
|
((n1 - Integer::ONE) / n2) - Integer::ONE
|
||||||
|
} else if n1 < &Integer::ZERO && n2 > &Integer::ZERO {
|
||||||
|
((n1 + Integer::ONE) / n2) - Integer::ONE
|
||||||
|
} else {
|
||||||
|
n1 / n2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match (x, y) {
|
match (x, y) {
|
||||||
(Number::Fixnum(n1), Number::Fixnum(n2)) => {
|
(Number::Fixnum(n1), Number::Fixnum(n2)) => {
|
||||||
let n2_i = n2.get_num();
|
let n2_i = n2.get_num();
|
||||||
@@ -865,14 +870,11 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||||
if (&*n2).num_eq(&0) {
|
if n2.is_zero() {
|
||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
let n1 = Integer::from(n1.get_num());
|
let n1 = Integer::from(n1.get_num());
|
||||||
Ok(Number::arena_from(
|
Ok(Number::arena_from(ibig_rem_floor(&n1, &*n2), arena))
|
||||||
<(Integer, Integer)>::from(n1.div_rem(&*n2)).1,
|
|
||||||
arena,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Fixnum(n2)) => {
|
(Number::Integer(n1), Number::Fixnum(n2)) => {
|
||||||
@@ -882,20 +884,14 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
|||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
let n2 = Integer::from(n2_i);
|
let n2 = Integer::from(n2_i);
|
||||||
Ok(Number::arena_from(
|
Ok(Number::arena_from(ibig_rem_floor(&*n1, &n2), arena))
|
||||||
<(Integer, Integer)>::from((&*n1).div_rem(&n2)).1,
|
|
||||||
arena,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Integer(x), Number::Integer(y)) => {
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
if (&*y).num_eq(&0) {
|
if n2.is_zero() {
|
||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
Ok(Number::arena_from(
|
Ok(Number::arena_from(ibig_rem_floor(&*n1, &*n2), arena))
|
||||||
<(Integer, Integer)>::from((&*x).div_rem(&*y)).1,
|
|
||||||
arena,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
|
(Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
|
||||||
@@ -923,7 +919,7 @@ pub(crate) fn remainder(x: Number, y: Number, arena: &mut Arena) -> Result<Numbe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||||
if (&*n2).num_eq(&0) {
|
if n2.is_zero() {
|
||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
let n1 = Integer::from(n1.get_num());
|
let n1 = Integer::from(n1.get_num());
|
||||||
@@ -941,7 +937,7 @@ pub(crate) fn remainder(x: Number, y: Number, arena: &mut Arena) -> Result<Numbe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
if (&*n2).num_eq(&0) {
|
if n2.is_zero() {
|
||||||
Err(zero_divisor_eval_error(stub_gen))
|
Err(zero_divisor_eval_error(stub_gen))
|
||||||
} else {
|
} else {
|
||||||
Ok(Number::arena_from(Integer::from(&*n1 % &*n2), arena))
|
Ok(Number::arena_from(Integer::from(&*n1 % &*n2), arena))
|
||||||
@@ -968,7 +964,7 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
|
|||||||
if let Some(result) = isize_gcd(n1_i, n2_i) {
|
if let Some(result) = isize_gcd(n1_i, n2_i) {
|
||||||
Ok(Number::arena_from(result, arena))
|
Ok(Number::arena_from(result, arena))
|
||||||
} else {
|
} else {
|
||||||
let value: IBig = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into();
|
let value: Integer = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into();
|
||||||
Ok(Number::arena_from(value, arena))
|
Ok(Number::arena_from(value, arena))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -978,9 +974,9 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
|
|||||||
Ok(Number::arena_from(Integer::from(n2_clone.gcd(&n1)), arena))
|
Ok(Number::arena_from(Integer::from(n2_clone.gcd(&n1)), arena))
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
let n1_clone: Integer = (*n1).clone();
|
|
||||||
let n2: isize = (&*n2).try_into().unwrap();
|
let n2: isize = (&*n2).try_into().unwrap();
|
||||||
Ok(Number::arena_from(Integer::from(n1_clone.gcd(&Integer::from(n2))) as IBig, arena))
|
let value: Integer = (&*n1).gcd(&Integer::from(n2)).into();
|
||||||
|
Ok(Number::arena_from(value, arena))
|
||||||
}
|
}
|
||||||
(Number::Float(f), _) | (_, Number::Float(f)) => {
|
(Number::Float(f), _) | (_, Number::Float(f)) => {
|
||||||
let n = Number::Float(f);
|
let n = Number::Float(f);
|
||||||
@@ -1212,7 +1208,8 @@ impl MachineState {
|
|||||||
value: HeapCellValue,
|
value: HeapCellValue,
|
||||||
) -> Result<Number, MachineStub> {
|
) -> Result<Number, MachineStub> {
|
||||||
let stub_gen = || functor_stub(atom!("is"), 2);
|
let stub_gen = || functor_stub(atom!("is"), 2);
|
||||||
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value);
|
let mut iter = stackful_post_order_iter::<NonListElider>
|
||||||
|
(&mut self.heap, &mut self.stack, value);
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
while let Some(value) = iter.next() {
|
||||||
if value.get_forwarding_bit() {
|
if value.get_forwarding_bit() {
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ impl MachineState {
|
|||||||
let mut seen_set = IndexSet::new();
|
let mut seen_set = IndexSet::new();
|
||||||
let mut seen_vars = vec![];
|
let mut seen_vars = vec![];
|
||||||
|
|
||||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, cell);
|
let mut iter = stackful_preorder_iter::<NonListElider>
|
||||||
|
(&mut self.heap, &mut self.stack, cell);
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
while let Some(value) = iter.next() {
|
||||||
read_heap_cell!(value,
|
read_heap_cell!(value,
|
||||||
|
|||||||
@@ -2331,7 +2331,7 @@ impl Machine {
|
|||||||
let mut loader: Loader<'_, InlineLoadState<'_>> =
|
let mut loader: Loader<'_, InlineLoadState<'_>> =
|
||||||
Loader::new(self, InlineTermStream {});
|
Loader::new(self, InlineTermStream {});
|
||||||
|
|
||||||
let term = loader.read_term_from_heap(term_loc)?;
|
let term = loader.read_term_from_heap(term_loc);
|
||||||
let clause = build_rule_body(vars, term);
|
let clause = build_rule_body(vars, term);
|
||||||
|
|
||||||
let settings = CodeGenSettings {
|
let settings = CodeGenSettings {
|
||||||
|
|||||||
@@ -34,6 +34,15 @@ macro_rules! try_or_throw {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! increment_call_count {
|
||||||
|
($s:expr) => {{
|
||||||
|
if !($s.increment_call_count_fn)(&mut $s) {
|
||||||
|
$s.backtrack();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! try_or_throw_gen {
|
macro_rules! try_or_throw_gen {
|
||||||
($s:expr, $e:expr) => {{
|
($s:expr, $e:expr) => {{
|
||||||
match $e {
|
match $e {
|
||||||
@@ -1096,12 +1105,7 @@ impl Machine {
|
|||||||
self.trust_me();
|
self.trust_me();
|
||||||
}
|
}
|
||||||
|
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1174,12 +1178,7 @@ impl Machine {
|
|||||||
self.trust_me();
|
self.trust_me();
|
||||||
}
|
}
|
||||||
|
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1205,19 +1204,11 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
&Instruction::RetryMeElse(offset) => {
|
&Instruction::RetryMeElse(offset) => {
|
||||||
self.retry_me_else(offset);
|
self.retry_me_else(offset);
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
&Instruction::TrustMe(_) => {
|
&Instruction::TrustMe(_) => {
|
||||||
self.trust_me();
|
self.trust_me();
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
&Instruction::NeckCut => {
|
&Instruction::NeckCut => {
|
||||||
self.machine_st.neck_cut();
|
self.machine_st.neck_cut();
|
||||||
@@ -1521,11 +1512,7 @@ impl Machine {
|
|||||||
if self.machine_st.is_cyclic_term(addr) {
|
if self.machine_st.is_cyclic_term(addr) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1535,11 +1522,7 @@ impl Machine {
|
|||||||
if self.machine_st.is_cyclic_term(addr) {
|
if self.machine_st.is_cyclic_term(addr) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1549,11 +1532,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1563,11 +1542,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1577,11 +1552,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1591,11 +1562,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1605,11 +1572,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
||||||
{
|
{
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -1621,11 +1584,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
||||||
{
|
{
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -1636,11 +1595,7 @@ impl Machine {
|
|||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -1651,11 +1606,7 @@ impl Machine {
|
|||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -1667,11 +1618,7 @@ impl Machine {
|
|||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match compare_term_test!(self.machine_st, a1, a2) {
|
||||||
Some(Ordering::Greater | Ordering::Equal) => {
|
Some(Ordering::Greater | Ordering::Equal) => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1685,11 +1632,7 @@ impl Machine {
|
|||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match compare_term_test!(self.machine_st, a1, a2) {
|
||||||
Some(Ordering::Greater | Ordering::Equal) => {
|
Some(Ordering::Greater | Ordering::Equal) => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1703,11 +1646,7 @@ impl Machine {
|
|||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match compare_term_test!(self.machine_st, a1, a2) {
|
||||||
Some(Ordering::Less | Ordering::Equal) => {
|
Some(Ordering::Less | Ordering::Equal) => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1721,11 +1660,7 @@ impl Machine {
|
|||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match compare_term_test!(self.machine_st, a1, a2) {
|
||||||
Some(Ordering::Less | Ordering::Equal) => {
|
Some(Ordering::Less | Ordering::Equal) => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1739,11 +1674,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1753,11 +1684,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1768,11 +1695,7 @@ impl Machine {
|
|||||||
if self.machine_st.eq_test(a1, a2) {
|
if self.machine_st.eq_test(a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1783,11 +1706,7 @@ impl Machine {
|
|||||||
if self.machine_st.eq_test(a1, a2) {
|
if self.machine_st.eq_test(a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1795,11 +1714,7 @@ impl Machine {
|
|||||||
if self.machine_st.ground_test() {
|
if self.machine_st.ground_test() {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1807,11 +1722,7 @@ impl Machine {
|
|||||||
if self.machine_st.ground_test() {
|
if self.machine_st.ground_test() {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1821,11 +1732,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1835,11 +1742,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1850,11 +1753,7 @@ impl Machine {
|
|||||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1865,11 +1764,7 @@ impl Machine {
|
|||||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1879,11 +1774,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1893,11 +1784,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1910,11 +1797,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1927,11 +1810,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1944,11 +1823,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1961,11 +1836,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1975,11 +1846,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1989,11 +1856,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2003,11 +1866,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2017,11 +1876,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2039,10 +1894,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::ExecuteN(arity) => {
|
&Instruction::ExecuteN(arity) => {
|
||||||
@@ -2059,10 +1911,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::DefaultCallN(arity) => {
|
&Instruction::DefaultCallN(arity) => {
|
||||||
@@ -2101,11 +1950,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Less | Ordering::Equal => {
|
Ordering::Less | Ordering::Equal => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2119,11 +1964,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Less | Ordering::Equal => {
|
Ordering::Less | Ordering::Equal => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2137,11 +1978,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2155,11 +1992,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2176,11 +2009,7 @@ impl Machine {
|
|||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2194,11 +2023,7 @@ impl Machine {
|
|||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2209,11 +2034,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Greater | Ordering::Equal => {
|
Ordering::Greater | Ordering::Equal => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2227,11 +2048,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Greater | Ordering::Equal => {
|
Ordering::Greater | Ordering::Equal => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2245,11 +2062,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2263,11 +2076,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2281,11 +2090,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2299,11 +2104,7 @@ impl Machine {
|
|||||||
|
|
||||||
match n1.cmp(&n2) {
|
match n1.cmp(&n2) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -2878,10 +2679,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::ExecuteNamed(arity, name, ref idx) => {
|
&Instruction::ExecuteNamed(arity, name, ref idx) => {
|
||||||
@@ -2892,10 +2690,7 @@ impl Machine {
|
|||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
try_or_throw!(
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::DefaultCallNamed(arity, name, ref idx) => {
|
&Instruction::DefaultCallNamed(arity, name, ref idx) => {
|
||||||
@@ -3224,26 +3019,14 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Retry(l) => {
|
&IndexedChoiceInstruction::Retry(l) => {
|
||||||
self.retry(l);
|
self.retry(l);
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::DefaultRetry(l) => {
|
&IndexedChoiceInstruction::DefaultRetry(l) => {
|
||||||
self.retry(l);
|
self.retry(l);
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Trust(l) => {
|
&IndexedChoiceInstruction::Trust(l) => {
|
||||||
self.trust(l);
|
self.trust(l);
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::DefaultTrust(l) => {
|
&IndexedChoiceInstruction::DefaultTrust(l) => {
|
||||||
self.trust(l);
|
self.trust(l);
|
||||||
@@ -3318,38 +3101,16 @@ impl Machine {
|
|||||||
// this is true iff ii + 1 < len.
|
// this is true iff ii + 1 < len.
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
self.retry(offset);
|
self.retry(offset);
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self
|
|
||||||
.machine_st
|
|
||||||
.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.trust(offset);
|
self.trust(offset);
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self
|
|
||||||
.machine_st
|
|
||||||
.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.trust(offset);
|
self.trust(offset);
|
||||||
|
increment_call_count!(self.machine_st);
|
||||||
try_or_throw!(
|
|
||||||
self.machine_st,
|
|
||||||
(self.machine_st.increment_call_count_fn)(
|
|
||||||
&mut self.machine_st
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5484,6 +5245,14 @@ impl Machine {
|
|||||||
self.get_db_refs();
|
self.get_db_refs();
|
||||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
}
|
}
|
||||||
|
&Instruction::CallInferenceLimitExceeded => {
|
||||||
|
self.inference_limit_exceeded();
|
||||||
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
|
}
|
||||||
|
&Instruction::ExecuteInferenceLimitExceeded => {
|
||||||
|
self.inference_limit_exceeded();
|
||||||
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5499,6 +5268,17 @@ impl Machine {
|
|||||||
if interruption {
|
if interruption {
|
||||||
self.machine_st.throw_interrupt_exception();
|
self.machine_st.throw_interrupt_exception();
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let old_runtime = std::mem::replace(&mut self.runtime, runtime);
|
||||||
|
old_runtime.shutdown_background();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => unreachable!(),
|
Err(_) => unreachable!(),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::parser::ast::*;
|
|||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use ref_thread_local::RefThreadLocal;
|
pub use ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -1004,10 +1004,22 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
|
pub(crate) fn add_module(
|
||||||
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
&mut self,
|
||||||
|
module_decl: ModuleDecl,
|
||||||
|
listing_src: ListingSource,
|
||||||
|
) -> Result<(), SessionError> {
|
||||||
let module_name = module_decl.name;
|
let module_name = module_decl.name;
|
||||||
|
|
||||||
|
if let Some(module) = self.wam_prelude.indices.modules.get(&module_name) {
|
||||||
|
if let ListingSource::DynamicallyGenerated = module.listing_src {
|
||||||
|
} else {
|
||||||
|
LS::err_on_builtin_module_overwrite(module_name)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
||||||
|
|
||||||
let mut module = match self.wam_prelude.indices.modules.remove(&module_name) {
|
let mut module = match self.wam_prelude.indices.modules.remove(&module_name) {
|
||||||
Some(mut module) => {
|
Some(mut module) => {
|
||||||
module.listing_src = listing_src;
|
module.listing_src = listing_src;
|
||||||
@@ -1045,6 +1057,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.wam_prelude.indices.modules.insert(module_name, module);
|
self.wam_prelude.indices.modules.insert(module_name, module);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> {
|
pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> {
|
||||||
|
|||||||
@@ -265,6 +265,10 @@ pub trait LoadState<'a>: Sized {
|
|||||||
loader: &Loader<'a, Self>,
|
loader: &Loader<'a, Self>,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
) -> Result<(), SessionError>;
|
) -> Result<(), SessionError>;
|
||||||
|
|
||||||
|
fn err_on_builtin_module_overwrite(_module_name: Atom) -> Result<(), SessionError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LiveLoadAndMachineState<'a> {
|
pub struct LiveLoadAndMachineState<'a> {
|
||||||
@@ -353,6 +357,15 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn err_on_builtin_module_overwrite(module_name: Atom) -> Result<(), SessionError> {
|
||||||
|
if LIBRARIES.borrow().contains_key(&*module_name.as_str()) {
|
||||||
|
Err(SessionError::CannotOverwriteBuiltInModule(module_name))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
|
impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
|
||||||
@@ -483,7 +496,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Result<Term, SessionError> {
|
pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Term {
|
||||||
let machine_st = LS::machine_st(&mut self.payload);
|
let machine_st = LS::machine_st(&mut self.payload);
|
||||||
let cell = machine_st[r];
|
let cell = machine_st[r];
|
||||||
|
|
||||||
@@ -533,11 +546,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
self.add_meta_predicate_record(module_name, name, meta_specs);
|
self.add_meta_predicate_record(module_name, name, meta_specs);
|
||||||
}
|
}
|
||||||
Declaration::Module(module_decl) => {
|
Declaration::Module(module_decl) => {
|
||||||
self.payload.compilation_target = CompilationTarget::Module(module_decl.name);
|
let module_name = module_decl.name;
|
||||||
|
|
||||||
|
self.payload.compilation_target = CompilationTarget::Module(module_name);
|
||||||
self.payload.predicates.compilation_target = self.payload.compilation_target;
|
self.payload.predicates.compilation_target = self.payload.compilation_target;
|
||||||
|
|
||||||
let listing_src = self.payload.term_stream.listing_src().clone();
|
let listing_src = self.payload.term_stream.listing_src().clone();
|
||||||
self.add_module(module_decl, listing_src);
|
self.add_module(module_decl, listing_src)?;
|
||||||
}
|
}
|
||||||
Declaration::NonCountedBacktracking(name, arity) => {
|
Declaration::NonCountedBacktracking(name, arity) => {
|
||||||
self.payload.non_counted_bt_preds.insert((name, arity));
|
self.payload.non_counted_bt_preds.insert((name, arity));
|
||||||
@@ -1074,7 +1089,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
let machine_st = LS::machine_st(&mut self.payload);
|
let machine_st = LS::machine_st(&mut self.payload);
|
||||||
let cell = machine_st[r];
|
let cell = machine_st[r];
|
||||||
|
|
||||||
let export_list = machine_st.read_term_from_heap(cell)?;
|
let export_list = machine_st.read_term_from_heap(cell);
|
||||||
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
|
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)?;
|
||||||
|
|
||||||
@@ -1401,9 +1416,10 @@ impl MachineState {
|
|||||||
pub(super) fn read_term_from_heap(
|
pub(super) fn read_term_from_heap(
|
||||||
&mut self,
|
&mut self,
|
||||||
term_addr: HeapCellValue,
|
term_addr: HeapCellValue,
|
||||||
) -> Result<Term, SessionError> {
|
) -> Term {
|
||||||
let mut term_stack = vec![];
|
let mut term_stack = vec![];
|
||||||
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term_addr);
|
let mut iter = stackful_post_order_iter::<NonListElider>
|
||||||
|
(&mut self.heap, &mut self.stack, term_addr);
|
||||||
|
|
||||||
while let Some(addr) = iter.next() {
|
while let Some(addr) = iter.next() {
|
||||||
let addr = unmark_cell_bits!(addr);
|
let addr = unmark_cell_bits!(addr);
|
||||||
@@ -1494,7 +1510,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(term_stack.len() == 1);
|
debug_assert!(term_stack.len() == 1);
|
||||||
Ok(term_stack.pop().unwrap())
|
term_stack.pop().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1636,7 +1652,7 @@ impl Machine {
|
|||||||
|
|
||||||
let arity = self.deref_register(3);
|
let arity = self.deref_register(3);
|
||||||
let arity = match Number::try_from(arity) {
|
let arity = match Number::try_from(arity) {
|
||||||
Ok(Number::Integer(n)) if &*n >= &Integer::from(0) && &*n <= &Integer::from(MAX_ARITY) => {
|
Ok(Number::Integer(n)) if &*n >= &Integer::ZERO && &*n <= &Integer::from(MAX_ARITY) => {
|
||||||
let value: usize = (&*n).try_into().unwrap();
|
let value: usize = (&*n).try_into().unwrap();
|
||||||
Ok(value)
|
Ok(value)
|
||||||
},
|
},
|
||||||
@@ -1661,7 +1677,7 @@ impl Machine {
|
|||||||
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
|
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
|
||||||
|
|
||||||
let add_clause = || {
|
let add_clause = || {
|
||||||
let term = loader.read_term_from_heap(temp_v!(1))?;
|
let term = loader.read_term_from_heap(temp_v!(1));
|
||||||
|
|
||||||
loader.incremental_compile_clause(
|
loader.incremental_compile_clause(
|
||||||
(atom!("term_expansion"), 2),
|
(atom!("term_expansion"), 2),
|
||||||
@@ -1691,7 +1707,7 @@ impl Machine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let add_clause = || {
|
let add_clause = || {
|
||||||
let term = loader.read_term_from_heap(temp_v!(2))?;
|
let term = loader.read_term_from_heap(temp_v!(2));
|
||||||
|
|
||||||
let indexing_arg = match term.name() {
|
let indexing_arg = match term.name() {
|
||||||
Some(atom!(":-")) => term.first_arg().and_then(Term::first_arg),
|
Some(atom!(":-")) => term.first_arg().and_then(Term::first_arg),
|
||||||
@@ -1849,9 +1865,7 @@ impl Machine {
|
|||||||
2,
|
2,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let path = cell_as_atom!(self
|
let path = cell_as_atom!(self.deref_register(2));
|
||||||
.machine_st
|
|
||||||
.store(self.machine_st.deref(self.machine_st.registers[2])));
|
|
||||||
|
|
||||||
self.load_contexts
|
self.load_contexts
|
||||||
.push(LoadContext::new(&*path.as_str(), stream));
|
.push(LoadContext::new(&*path.as_str(), stream));
|
||||||
@@ -2008,7 +2022,7 @@ impl Machine {
|
|||||||
loader.payload.compilation_target = compilation_target;
|
loader.payload.compilation_target = compilation_target;
|
||||||
|
|
||||||
let head = LiveLoadAndMachineState::machine_st(&mut loader.payload)
|
let head = LiveLoadAndMachineState::machine_st(&mut loader.payload)
|
||||||
.read_term_from_heap(head)?;
|
.read_term_from_heap(head);
|
||||||
|
|
||||||
let name = if let Some(name) = head.name() {
|
let name = if let Some(name) = head.name() {
|
||||||
name
|
name
|
||||||
@@ -2044,7 +2058,7 @@ impl Machine {
|
|||||||
return LiveLoadAndMachineState::evacuate(loader);
|
return LiveLoadAndMachineState::evacuate(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = loader.read_term_from_heap(temp_v!(3))?;
|
let body = loader.read_term_from_heap(temp_v!(3));
|
||||||
|
|
||||||
let asserted_clause = Term::Clause(
|
let asserted_clause = Term::Clause(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
@@ -2482,7 +2496,7 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
|
|||||||
self.payload.predicates.compilation_target = compilation_target;
|
self.payload.predicates.compilation_target = compilation_target;
|
||||||
}
|
}
|
||||||
|
|
||||||
let term = self.read_term_from_heap(term_reg)?;
|
let term = self.read_term_from_heap(term_reg);
|
||||||
|
|
||||||
self.add_clause_clause_if_dynamic(&term)?;
|
self.add_clause_clause_if_dynamic(&term)?;
|
||||||
self.payload.term_stream.term_queue.push_back(term);
|
self.payload.term_stream.term_queue.push_back(term);
|
||||||
|
|||||||
@@ -77,6 +77,12 @@ impl ValidType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub(crate) enum ResourceError {
|
||||||
|
FiniteMemory(HeapCellValue),
|
||||||
|
OutOfFiles
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) trait TypeError {
|
pub(crate) trait TypeError {
|
||||||
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError;
|
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError;
|
||||||
}
|
}
|
||||||
@@ -155,6 +161,26 @@ pub(crate) trait PermissionError {
|
|||||||
) -> MachineError;
|
) -> MachineError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PermissionError for Atom {
|
||||||
|
fn permission_error(
|
||||||
|
self,
|
||||||
|
_machine_st: &mut MachineState,
|
||||||
|
index_atom: Atom,
|
||||||
|
perm: Permission,
|
||||||
|
) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
atom!("permission_error"),
|
||||||
|
[atom(perm.as_atom()), atom(index_atom), cell(atom_as_cell!(self))]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PermissionError for HeapCellValue {
|
impl PermissionError for HeapCellValue {
|
||||||
fn permission_error(
|
fn permission_error(
|
||||||
self,
|
self,
|
||||||
@@ -284,11 +310,21 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn resource_error(&mut self, value: HeapCellValue) -> MachineError {
|
pub(super) fn resource_error(&mut self, err: ResourceError) -> MachineError {
|
||||||
let stub = functor!(
|
let stub = match err {
|
||||||
atom!("resource_error"),
|
ResourceError::FiniteMemory(size_requested) => {
|
||||||
[atom(atom!("finite_memory")), cell(value)]
|
functor!(
|
||||||
);
|
atom!("resource_error"),
|
||||||
|
[atom(atom!("finite_memory")), cell(size_requested)]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ResourceError::OutOfFiles => {
|
||||||
|
functor!(
|
||||||
|
atom!("resource_error"),
|
||||||
|
[atom(atom!("file_descriptors"))]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -305,26 +341,6 @@ impl MachineState {
|
|||||||
culprit.type_error(self, valid_type)
|
culprit.type_error(self, valid_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn module_resolution_error(
|
|
||||||
&mut self,
|
|
||||||
mod_name: Atom,
|
|
||||||
name: Atom,
|
|
||||||
arity: usize,
|
|
||||||
) -> MachineError {
|
|
||||||
let h = self.heap.len();
|
|
||||||
|
|
||||||
let res_stub = functor!(atom!(":"), [atom(mod_name), atom(name)]);
|
|
||||||
let ind_stub = functor!(atom!("/"), [str(h + 2, 0), fixnum(arity)], [res_stub]);
|
|
||||||
|
|
||||||
let stub = functor!(atom!("evaluation_error"), [str(h, 0)], [ind_stub]);
|
|
||||||
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Constructed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn existence_error(&mut self, err: ExistenceError) -> MachineError {
|
pub(super) fn existence_error(&mut self, err: ExistenceError) -> MachineError {
|
||||||
match err {
|
match err {
|
||||||
ExistenceError::Module(name) => {
|
ExistenceError::Module(name) => {
|
||||||
@@ -339,6 +355,20 @@ impl MachineState {
|
|||||||
from: ErrorProvenance::Received,
|
from: ErrorProvenance::Received,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExistenceError::QualifiedProcedure { module_name, name, arity } => {
|
||||||
|
let h = self.heap.len();
|
||||||
|
|
||||||
|
let ind_stub = functor!(atom!("/"), [atom(name), fixnum(arity)]);
|
||||||
|
let res_stub = functor!(atom!(":"), [atom(module_name), str(h + 3, 0)], [ind_stub]);
|
||||||
|
|
||||||
|
let stub = functor!(atom!("existence_error"), [atom(atom!("procedure")), str(h, 0)], [res_stub]);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed,
|
||||||
|
}
|
||||||
|
}
|
||||||
ExistenceError::Procedure(name, arity) => {
|
ExistenceError::Procedure(name, arity) => {
|
||||||
let culprit = functor!(atom!("/"), [atom(name), fixnum(arity)]);
|
let culprit = functor!(atom!("/"), [atom(name), fixnum(arity)]);
|
||||||
|
|
||||||
@@ -443,7 +473,6 @@ impl MachineState {
|
|||||||
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
|
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
|
||||||
match err {
|
match err {
|
||||||
SessionError::CannotOverwriteBuiltIn(key) => {
|
SessionError::CannotOverwriteBuiltIn(key) => {
|
||||||
// SessionError::CannotOverwriteImport(pred_atom) => {
|
|
||||||
self.permission_error(
|
self.permission_error(
|
||||||
Permission::Modify,
|
Permission::Modify,
|
||||||
atom!("static_procedure"),
|
atom!("static_procedure"),
|
||||||
@@ -452,10 +481,14 @@ impl MachineState {
|
|||||||
.collect::<MachineStub>(),
|
.collect::<MachineStub>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
SessionError::CannotOverwriteBuiltInModule(module) => {
|
||||||
|
self.permission_error(
|
||||||
|
Permission::Modify,
|
||||||
|
atom!("static_module"),
|
||||||
|
module,
|
||||||
|
)
|
||||||
|
}
|
||||||
SessionError::ExistenceError(err) => self.existence_error(err),
|
SessionError::ExistenceError(err) => self.existence_error(err),
|
||||||
// SessionError::InvalidFileName(filename) => {
|
|
||||||
// Self::existence_error(h, ExistenceError::Module(filename))
|
|
||||||
// }
|
|
||||||
SessionError::ModuleDoesNotContainExport(..) => {
|
SessionError::ModuleDoesNotContainExport(..) => {
|
||||||
let error_atom = atom!("module_does_not_contain_claimed_export");
|
let error_atom = atom!("module_does_not_contain_claimed_export");
|
||||||
|
|
||||||
@@ -953,6 +986,7 @@ pub enum ExistenceError {
|
|||||||
Module(Atom),
|
Module(Atom),
|
||||||
ModuleSource(ModuleSource),
|
ModuleSource(ModuleSource),
|
||||||
Procedure(Atom, usize),
|
Procedure(Atom, usize),
|
||||||
|
QualifiedProcedure { module_name: Atom, name: Atom, arity: usize },
|
||||||
SourceSink(HeapCellValue),
|
SourceSink(HeapCellValue),
|
||||||
Stream(HeapCellValue),
|
Stream(HeapCellValue),
|
||||||
}
|
}
|
||||||
@@ -961,6 +995,7 @@ pub enum ExistenceError {
|
|||||||
pub enum SessionError {
|
pub enum SessionError {
|
||||||
CompilationError(CompilationError),
|
CompilationError(CompilationError),
|
||||||
CannotOverwriteBuiltIn(PredicateKey),
|
CannotOverwriteBuiltIn(PredicateKey),
|
||||||
|
CannotOverwriteBuiltInModule(Atom),
|
||||||
ExistenceError(ExistenceError),
|
ExistenceError(ExistenceError),
|
||||||
ModuleDoesNotContainExport(Atom, PredicateKey),
|
ModuleDoesNotContainExport(Atom, PredicateKey),
|
||||||
ModuleCannotImportSelf(Atom),
|
ModuleCannotImportSelf(Atom),
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ pub struct MachineState {
|
|||||||
pub(crate) unify_fn: fn(&mut MachineState),
|
pub(crate) unify_fn: fn(&mut MachineState),
|
||||||
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
||||||
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
||||||
pub(crate) increment_call_count_fn: fn(&mut MachineState) -> CallResult,
|
pub(crate) increment_call_count_fn: fn(&mut MachineState) -> bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MachineState {
|
impl fmt::Debug for MachineState {
|
||||||
@@ -412,22 +412,24 @@ impl MachineState {
|
|||||||
self.fail = false;
|
self.fail = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn increment_call_count(&mut self) -> CallResult {
|
pub(crate) fn increment_call_count(&mut self) -> bool {
|
||||||
if self.cwil.inference_limit_exceeded || self.ball.stub.len() > 0 {
|
if self.cwil.inference_limit_exceeded || self.ball.stub.len() > 0 {
|
||||||
return Ok(());
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(&(ref limit, bp)) = self.cwil.limits.last() {
|
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
|
||||||
if self.cwil.count == *limit {
|
if self.cwil.count == *limit {
|
||||||
self.cwil.inference_limit_exceeded = true;
|
self.cwil.inference_limit_exceeded = true;
|
||||||
|
self.block = block;
|
||||||
|
self.unwind_stack();
|
||||||
|
|
||||||
return Err(functor!(atom!("inference_limit_exceeded"), [fixnum(bp)]));
|
return false;
|
||||||
} else {
|
} else {
|
||||||
self.cwil.count += 1;
|
self.cwil.count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -588,7 +590,7 @@ impl MachineState {
|
|||||||
|
|
||||||
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
|
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
|
||||||
|
|
||||||
for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, heap_loc) {
|
for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, heap_loc) {
|
||||||
let cell = unmark_cell_bits!(cell);
|
let cell = unmark_cell_bits!(cell);
|
||||||
|
|
||||||
if let Some(var) = cell.as_var() {
|
if let Some(var) = cell.as_var() {
|
||||||
@@ -953,7 +955,7 @@ impl MachineState {
|
|||||||
pub(crate) struct CWIL {
|
pub(crate) struct CWIL {
|
||||||
count: Integer,
|
count: Integer,
|
||||||
limits: Vec<(Integer, usize)>,
|
limits: Vec<(Integer, usize)>,
|
||||||
inference_limit_exceeded: bool,
|
pub(crate) inference_limit_exceeded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CWIL {
|
impl CWIL {
|
||||||
@@ -965,22 +967,22 @@ impl CWIL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_limit(&mut self, limit: usize, b: usize) -> &Integer {
|
pub(crate) fn add_limit(&mut self, limit: usize, block: usize) -> &Integer {
|
||||||
let mut limit = Integer::from(limit);
|
let mut limit = Integer::from(limit);
|
||||||
limit += &self.count;
|
limit += &self.count;
|
||||||
|
|
||||||
match self.limits.last() {
|
match self.limits.last() {
|
||||||
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
||||||
_ => self.limits.push((limit, b)),
|
_ => self.limits.push((limit, block)),
|
||||||
};
|
};
|
||||||
|
|
||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
pub(crate) fn remove_limit(&mut self, block: usize) -> &Integer {
|
||||||
if let Some((_, bp)) = self.limits.last() {
|
if let Some((_, bl)) = self.limits.last() {
|
||||||
if bp == &b {
|
if bl == &block {
|
||||||
self.limits.pop();
|
self.limits.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ use crate::parser::dashu::{Integer, Rational};
|
|||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use num_order::NumOrd;
|
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -61,7 +60,7 @@ impl MachineState {
|
|||||||
unify_fn: MachineState::unify,
|
unify_fn: MachineState::unify,
|
||||||
bind_fn: MachineState::bind,
|
bind_fn: MachineState::bind,
|
||||||
run_cleaners_fn: |_| false,
|
run_cleaners_fn: |_| false,
|
||||||
increment_call_count_fn: |_| Ok(()),
|
increment_call_count_fn: |_| true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1136,7 +1135,8 @@ impl MachineState {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value);
|
let mut iter = stackful_preorder_iter::<NonListElider>
|
||||||
|
(&mut self.heap, &mut self.stack, value);
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
while let Some(value) = iter.next() {
|
||||||
if value.get_forwarding_bit() {
|
if value.get_forwarding_bit() {
|
||||||
@@ -1183,10 +1183,7 @@ impl MachineState {
|
|||||||
|
|
||||||
let n = match n {
|
let n = match n {
|
||||||
Number::Fixnum(n) => n.get_num() as usize,
|
Number::Fixnum(n) => n.get_num() as usize,
|
||||||
Number::Integer(n) if (*n).num_ge(&0) && (*n).num_le(&std::usize::MAX) => {
|
Number::Integer(n) if usize::try_from(&*n).is_ok() => (&*n).try_into().unwrap(),
|
||||||
let value: usize = (&*n).try_into().unwrap();
|
|
||||||
value
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1637,24 +1634,36 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut visited = IndexSet::with_hasher(FxBuildHasher::default());
|
let mut visited = IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value);
|
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
|
||||||
let mut stack_len = 0;
|
let mut stack_len = 0;
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
let is_var = |heap: &Heap, value: HeapCellValue| -> bool {
|
||||||
let mut value = unmark_cell_bits!(value);
|
let value = unmark_cell_bits!(value);
|
||||||
|
|
||||||
if value.is_var() {
|
if value.is_var() {
|
||||||
value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value));
|
let value = heap_bound_store(heap, heap_bound_deref(heap, value));
|
||||||
|
|
||||||
if value.is_var() {
|
if value.is_var() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.is_compound(iter.heap) {
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(value) = iter.next() {
|
||||||
|
if is_var(iter.heap, value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.is_ref() {
|
||||||
if visited.contains(&value) {
|
if visited.contains(&value) {
|
||||||
for _ in stack_len..iter.stack_len() {
|
while iter.stack_len() > stack_len {
|
||||||
iter.pop_stack();
|
if let Some(value) = iter.pop_stack() {
|
||||||
|
if is_var(iter.heap, value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
visited.insert(value);
|
visited.insert(value);
|
||||||
@@ -1689,7 +1698,7 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
Ok(Number::Integer(n)) => {
|
Ok(Number::Integer(n)) => {
|
||||||
let b: u8 = (&*n).try_into().unwrap();
|
let b: u8 = (&*n).try_into().unwrap();
|
||||||
|
|
||||||
bytes.push(b);
|
bytes.push(b);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ use std::sync::atomic::AtomicBool;
|
|||||||
|
|
||||||
use self::config::MachineConfig;
|
use self::config::MachineConfig;
|
||||||
use self::parsed_results::*;
|
use self::parsed_results::*;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use rand::rngs::StdRng;
|
||||||
|
use rand::SeedableRng;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
||||||
@@ -76,6 +79,7 @@ pub struct Machine {
|
|||||||
pub(super) load_contexts: Vec<LoadContext>,
|
pub(super) load_contexts: Vec<LoadContext>,
|
||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
pub(super) foreign_function_table: ForeignFunctionTable,
|
pub(super) foreign_function_table: ForeignFunctionTable,
|
||||||
|
pub(super) rng: StdRng,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -487,6 +491,7 @@ impl Machine {
|
|||||||
load_contexts: vec![],
|
load_contexts: vec![],
|
||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
foreign_function_table: Default::default(),
|
foreign_function_table: Default::default(),
|
||||||
|
rng: StdRng::from_entropy(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut lib_path = current_dir();
|
let mut lib_path = current_dir();
|
||||||
@@ -1178,7 +1183,7 @@ impl Machine {
|
|||||||
let stub = functor_stub(name, arity);
|
let stub = functor_stub(name, arity);
|
||||||
let err = self
|
let err = self
|
||||||
.machine_st
|
.machine_st
|
||||||
.module_resolution_error(module_name, name, arity);
|
.existence_error(ExistenceError::QualifiedProcedure { module_name, name, arity });
|
||||||
|
|
||||||
Err(self.machine_st.error_form(err, stub))
|
Err(self.machine_st.error_form(err, stub))
|
||||||
}
|
}
|
||||||
@@ -1206,7 +1211,7 @@ impl Machine {
|
|||||||
let stub = functor_stub(name, arity);
|
let stub = functor_stub(name, arity);
|
||||||
let err = self
|
let err = self
|
||||||
.machine_st
|
.machine_st
|
||||||
.module_resolution_error(module_name, name, arity);
|
.existence_error(ExistenceError::QualifiedProcedure { module_name, name, arity });
|
||||||
|
|
||||||
Err(self.machine_st.error_form(err, stub))
|
Err(self.machine_st.error_form(err, stub))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,10 +58,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
|
|||||||
let name = terms.pop().unwrap();
|
let name = terms.pop().unwrap();
|
||||||
|
|
||||||
let arity = match arity {
|
let arity = match arity {
|
||||||
Term::Literal(_, Literal::Integer(n)) => {
|
Term::Literal(_, Literal::Integer(n)) => (&*n).try_into().ok(),
|
||||||
let value: usize = (&*n).try_into().unwrap();
|
|
||||||
Some(value)
|
|
||||||
},
|
|
||||||
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
|
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ use std::ptr;
|
|||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use native_tls::TlsStream;
|
use native_tls::TlsStream;
|
||||||
|
|
||||||
|
#[cfg(feature = "http")]
|
||||||
|
use warp::hyper;
|
||||||
|
|
||||||
#[derive(Debug, BitfieldSpecifier, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, BitfieldSpecifier, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[bits = 1]
|
#[bits = 1]
|
||||||
pub enum StreamType {
|
pub enum StreamType {
|
||||||
@@ -290,9 +293,9 @@ impl Read for HttpReadStream {
|
|||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
pub struct HttpWriteStream {
|
pub struct HttpWriteStream {
|
||||||
status_code: u16,
|
status_code: u16,
|
||||||
headers: hyper::HeaderMap,
|
headers: mem::ManuallyDrop<hyper::HeaderMap>,
|
||||||
response: TypedArenaPtr<HttpResponse>,
|
response: TypedArenaPtr<HttpResponse>,
|
||||||
buffer: Vec<u8>,
|
buffer: mem::ManuallyDrop<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
@@ -312,24 +315,33 @@ impl Write for HttpWriteStream {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn flush(&mut self) -> std::io::Result<()> {
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
let (ready, response, cvar) = &**self.response;
|
Ok(())
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "http")]
|
||||||
|
impl HttpWriteStream {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let headers = unsafe { mem::ManuallyDrop::take(&mut self.headers) };
|
||||||
|
let buffer = unsafe { mem::ManuallyDrop::take(&mut self.buffer) };
|
||||||
|
|
||||||
|
let (ready, response, cvar) = &**self.response;
|
||||||
|
|
||||||
|
let mut ready = ready.lock().unwrap();
|
||||||
|
{
|
||||||
|
let mut response = response.lock().unwrap();
|
||||||
|
|
||||||
|
let mut response_ = warp::http::Response::builder()
|
||||||
|
.status(self.status_code);
|
||||||
|
*response_.headers_mut().unwrap() = headers;
|
||||||
|
*response = Some(response_.body(warp::hyper::Body::from(buffer)).unwrap());
|
||||||
|
}
|
||||||
|
*ready = true;
|
||||||
|
cvar.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StandardOutputStream {}
|
pub struct StandardOutputStream {}
|
||||||
|
|
||||||
@@ -1243,15 +1255,15 @@ impl Stream {
|
|||||||
headers: hyper::HeaderMap,
|
headers: hyper::HeaderMap,
|
||||||
arena: &mut Arena,
|
arena: &mut Arena,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Stream::HttpWrite(arena_alloc!(
|
Stream::HttpWrite(arena_alloc!(
|
||||||
StreamLayout::new(CharReader::new(HttpWriteStream {
|
StreamLayout::new(CharReader::new(HttpWriteStream {
|
||||||
response,
|
response,
|
||||||
status_code,
|
status_code,
|
||||||
headers,
|
headers: mem::ManuallyDrop::new(headers),
|
||||||
buffer: Vec::new(),
|
buffer: mem::ManuallyDrop::new(Vec::new()),
|
||||||
})),
|
})),
|
||||||
arena
|
arena
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1299,7 +1311,8 @@ impl Stream {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
Stream::HttpWrite(ref mut http_stream) => {
|
Stream::HttpWrite(ref mut http_stream) => {
|
||||||
|
http_stream.inner_mut().drop();
|
||||||
unsafe {
|
unsafe {
|
||||||
http_stream.set_tag(ArenaHeaderTag::Dropped);
|
http_stream.set_tag(ArenaHeaderTag::Dropped);
|
||||||
std::ptr::drop_in_place(&mut http_stream.inner_mut().buffer as *mut _);
|
std::ptr::drop_in_place(&mut http_stream.inner_mut().buffer as *mut _);
|
||||||
@@ -1804,7 +1817,7 @@ impl MachineState {
|
|||||||
) -> Result<Stream, MachineStub> {
|
) -> Result<Stream, MachineStub> {
|
||||||
if file_spec == atom!("") {
|
if file_spec == atom!("") {
|
||||||
let stub = functor_stub(atom!("open"), 4);
|
let stub = functor_stub(atom!("open"), 4);
|
||||||
let err = self.domain_error(DomainErrorType::SourceSink, self[temp_v!(1)]);
|
let err = self.domain_error(DomainErrorType::SourceSink, self.registers[1]);
|
||||||
|
|
||||||
return Err(self.error_form(err, stub));
|
return Err(self.error_form(err, stub));
|
||||||
}
|
}
|
||||||
@@ -1816,9 +1829,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode = MachineState::deref(self, self[temp_v!(2)]);
|
let mode = cell_as_atom!(self.store(MachineState::deref(self, self.registers[2])));
|
||||||
let mode = cell_as_atom!(self.store(mode));
|
|
||||||
|
|
||||||
let mut open_options = OpenOptions::new();
|
let mut open_options = OpenOptions::new();
|
||||||
|
|
||||||
let (is_input_file, in_append_mode) = match mode {
|
let (is_input_file, in_append_mode) = match mode {
|
||||||
@@ -1875,8 +1886,9 @@ impl MachineState {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
// assume the OS is out of file descriptors.
|
||||||
let stub = functor_stub(atom!("open"), 4);
|
let stub = functor_stub(atom!("open"), 4);
|
||||||
let err = self.syntax_error(ParserError::IO(err));
|
let err = self.resource_error(ResourceError::OutOfFiles);
|
||||||
|
|
||||||
return Err(self.error_form(err, stub));
|
return Err(self.error_form(err, stub));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::forms::*;
|
|||||||
use crate::heap_iter::*;
|
use crate::heap_iter::*;
|
||||||
use crate::heap_print::*;
|
use crate::heap_print::*;
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use crate::http::{HttpListener, HttpResponse, HttpService};
|
use crate::http::{HttpRequestData, HttpListener, HttpResponse, HttpRequest};
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine;
|
use crate::machine;
|
||||||
use crate::machine::code_walker::*;
|
use crate::machine::code_walker::*;
|
||||||
@@ -42,17 +42,16 @@ use indexmap::IndexSet;
|
|||||||
|
|
||||||
pub(crate) use ref_thread_local::RefThreadLocal;
|
pub(crate) use ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
use std::borrow::BorrowMut;
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::{BTreeSet};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::env;
|
use std::env;
|
||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::hash::{BuildHasher, BuildHasherDefault};
|
use std::hash::{BuildHasher, BuildHasherDefault};
|
||||||
use std::io::{ErrorKind, Read, Write};
|
use std::io::{ErrorKind, Read, BufRead, Write};
|
||||||
use std::iter::{once, FromIterator};
|
use std::iter::{once, FromIterator};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
|
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
|
||||||
@@ -60,6 +59,7 @@ use std::num::NonZeroU32;
|
|||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::sync::{Mutex, Arc, Condvar};
|
||||||
|
|
||||||
use chrono::{offset::Local, DateTime};
|
use chrono::{offset::Local, DateTime};
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -77,7 +77,7 @@ use ring::{digest, hkdf, pbkdf2};
|
|||||||
|
|
||||||
#[cfg(feature = "crypto-full")]
|
#[cfg(feature = "crypto-full")]
|
||||||
use ring::{
|
use ring::{
|
||||||
aead,
|
aead,
|
||||||
signature::{self, KeyPair},
|
signature::{self, KeyPair},
|
||||||
};
|
};
|
||||||
use ripemd160::{Digest, Ripemd160};
|
use ripemd160::{Digest, Ripemd160};
|
||||||
@@ -92,17 +92,16 @@ use base64;
|
|||||||
use roxmltree;
|
use roxmltree;
|
||||||
use select;
|
use select;
|
||||||
|
|
||||||
use bytes::Buf;
|
|
||||||
use http_body_util::BodyExt;
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use hyper::header::{HeaderName, HeaderValue};
|
use warp::hyper::header::{HeaderValue, HeaderName};
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use hyper::server::conn::http1;
|
use warp::hyper::{HeaderMap, Method};
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use hyper::{HeaderMap, Method};
|
use warp::{Buf, Filter};
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use hyper_util::rt::TokioIo;
|
//use hyper_util::rt::TokioIo;
|
||||||
|
use futures::future;
|
||||||
|
|
||||||
#[cfg(feature = "repl")]
|
#[cfg(feature = "repl")]
|
||||||
pub(crate) fn get_key() -> KeyEvent {
|
pub(crate) fn get_key() -> KeyEvent {
|
||||||
@@ -182,12 +181,6 @@ impl BrentAlgState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_result(mut self, heap: &[HeapCellValue]) -> CycleSearchResult {
|
pub fn to_result(mut self, heap: &[HeapCellValue]) -> CycleSearchResult {
|
||||||
/*
|
|
||||||
if let Some(var) = heap[self.hare].as_var() {
|
|
||||||
return CycleSearchResult::PartialList(self.num_steps(), var);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
read_heap_cell!(heap[self.hare],
|
read_heap_cell!(heap[self.hare],
|
||||||
(HeapCellValueTag::PStrOffset) => {
|
(HeapCellValueTag::PStrOffset) => {
|
||||||
@@ -250,7 +243,7 @@ impl BrentAlgState {
|
|||||||
let cstr = PartialString::from(cstr_atom);
|
let cstr = PartialString::from(cstr_atom);
|
||||||
let num_chars = cstr.as_str_from(offset).chars().count();
|
let num_chars = cstr.as_str_from(offset).chars().count();
|
||||||
|
|
||||||
if self.max_steps == -1 || self.num_steps() + num_chars < self.max_steps as usize {
|
if self.max_steps == -1 || self.num_steps() + num_chars <= self.max_steps as usize {
|
||||||
self.pstr_chars += num_chars;
|
self.pstr_chars += num_chars;
|
||||||
Some(CycleSearchResult::ProperList(self.num_steps()))
|
Some(CycleSearchResult::ProperList(self.num_steps()))
|
||||||
} else {
|
} else {
|
||||||
@@ -263,7 +256,7 @@ impl BrentAlgState {
|
|||||||
let pstr = PartialString::from(pstr_atom);
|
let pstr = PartialString::from(pstr_atom);
|
||||||
let num_chars = pstr.as_str_from(offset).chars().count();
|
let num_chars = pstr.as_str_from(offset).chars().count();
|
||||||
|
|
||||||
if self.max_steps == -1 || self.num_steps() + num_chars < self.max_steps as usize {
|
if self.max_steps == -1 || self.num_steps() + num_chars <= self.max_steps as usize {
|
||||||
self.pstr_chars += num_chars - 1;
|
self.pstr_chars += num_chars - 1;
|
||||||
self.step(h+1)
|
self.step(h+1)
|
||||||
} else {
|
} else {
|
||||||
@@ -591,7 +584,7 @@ impl MachineState {
|
|||||||
seen_set: &mut IndexSet<HeapCellValue, S>,
|
seen_set: &mut IndexSet<HeapCellValue, S>,
|
||||||
value: HeapCellValue,
|
value: HeapCellValue,
|
||||||
) {
|
) {
|
||||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value);
|
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
while let Some(value) = iter.next() {
|
||||||
let value = unmark_cell_bits!(value);
|
let value = unmark_cell_bits!(value);
|
||||||
@@ -801,7 +794,7 @@ impl MachineState {
|
|||||||
let mut seen_set = IndexSet::new();
|
let mut seen_set = IndexSet::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term);
|
let mut iter = stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, term);
|
||||||
|
|
||||||
while let Some(value) = iter.next() {
|
while let Some(value) = iter.next() {
|
||||||
if iter.parent_stack_len() >= max_depth {
|
if iter.parent_stack_len() >= max_depth {
|
||||||
@@ -1419,7 +1412,6 @@ impl Machine {
|
|||||||
is_simple_goal: bool,
|
is_simple_goal: bool,
|
||||||
goal: HeapCellValue,
|
goal: HeapCellValue,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
expanded_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
|
||||||
supp_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
supp_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,7 +1436,7 @@ impl Machine {
|
|||||||
// insertion as well as the previous
|
// insertion as well as the previous
|
||||||
// supp_vars.len() argument's variables being
|
// supp_vars.len() argument's variables being
|
||||||
// disjoint from them. if they are not, the
|
// disjoint from them. if they are not, the
|
||||||
// expanded goal are not simple.
|
// expanded goal is not simple.
|
||||||
|
|
||||||
let post_supp_args = self.machine_st.heap[s+arity-supp_vars.len()+1 .. s+arity+1]
|
let post_supp_args = self.machine_st.heap[s+arity-supp_vars.len()+1 .. s+arity+1]
|
||||||
.iter()
|
.iter()
|
||||||
@@ -1490,7 +1482,6 @@ impl Machine {
|
|||||||
is_simple_goal,
|
is_simple_goal,
|
||||||
goal,
|
goal,
|
||||||
key: (name, arity),
|
key: (name, arity),
|
||||||
expanded_vars,
|
|
||||||
supp_vars
|
supp_vars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1504,7 +1495,6 @@ impl Machine {
|
|||||||
is_simple_goal: true,
|
is_simple_goal: true,
|
||||||
goal: str_loc_as_cell!(h),
|
goal: str_loc_as_cell!(h),
|
||||||
key: (name, 0),
|
key: (name, 0),
|
||||||
expanded_vars: IndexSet::with_hasher(FxBuildHasher::default()),
|
|
||||||
supp_vars,
|
supp_vars,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1518,7 +1508,6 @@ impl Machine {
|
|||||||
is_simple_goal: true,
|
is_simple_goal: true,
|
||||||
goal: str_loc_as_cell!(h),
|
goal: str_loc_as_cell!(h),
|
||||||
key: (name, 0),
|
key: (name, 0),
|
||||||
expanded_vars: IndexSet::with_hasher(FxBuildHasher::default()),
|
|
||||||
supp_vars,
|
supp_vars,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1540,9 +1529,12 @@ impl Machine {
|
|||||||
.push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
|
.push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
|
||||||
result.goal
|
result.goal
|
||||||
} else {
|
} else {
|
||||||
|
let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
|
self.machine_st.variable_set(&mut unexpanded_vars, self.machine_st.registers[5]);
|
||||||
|
|
||||||
// all supp_vars must appear later!
|
// all supp_vars must appear later!
|
||||||
let vars = IndexSet::<HeapCellValue, BuildHasherDefault<FxHasher>>::from_iter(
|
let vars = IndexSet::<HeapCellValue, BuildHasherDefault<FxHasher>>::from_iter(
|
||||||
result.expanded_vars.difference(&result.supp_vars).cloned(),
|
unexpanded_vars.difference(&result.supp_vars).cloned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let vars: Vec<_> = vars
|
let vars: Vec<_> = vars
|
||||||
@@ -1564,7 +1556,7 @@ impl Machine {
|
|||||||
|
|
||||||
self.machine_st.heap.push(atom_as_cell!(atom!("$aux"), 0));
|
self.machine_st.heap.push(atom_as_cell!(atom!("$aux"), 0));
|
||||||
|
|
||||||
for value in result.expanded_vars.difference(&result.supp_vars).cloned() {
|
for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
|
||||||
self.machine_st.heap.push(value);
|
self.machine_st.heap.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3265,7 +3257,7 @@ impl Machine {
|
|||||||
match Number::try_from(addr) {
|
match Number::try_from(addr) {
|
||||||
Ok(Number::Integer(n)) => {
|
Ok(Number::Integer(n)) => {
|
||||||
let n: u8 = (&*n).try_into().unwrap();
|
let n: u8 = (&*n).try_into().unwrap();
|
||||||
|
|
||||||
match n {
|
match n {
|
||||||
nb => {
|
nb => {
|
||||||
match stream.write(&mut [nb]) {
|
match stream.write(&mut [nb]) {
|
||||||
@@ -3916,6 +3908,11 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if self.indices.builtin_property((name, arity)) {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.machine_st.fail = self
|
self.machine_st.fail = self
|
||||||
.indices
|
.indices
|
||||||
.get_predicate_code_index(name, arity, module_name)
|
.get_predicate_code_index(name, arity, module_name)
|
||||||
@@ -3995,6 +3992,10 @@ impl Machine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (name, arity) in code_dir.keys() {
|
for (name, arity) in code_dir.keys() {
|
||||||
|
if self.indices.builtin_property((*name, *arity)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if name_match(pred_atom, *name) && arity_match(pred_arity, *arity) {
|
if name_match(pred_atom, *name) && arity_match(pred_arity, *arity) {
|
||||||
self.machine_st.heap.extend(functor!(
|
self.machine_st.heap.extend(functor!(
|
||||||
atom!("/"),
|
atom!("/"),
|
||||||
@@ -4217,25 +4218,7 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn maybe(&mut self) {
|
pub(crate) fn maybe(&mut self) {
|
||||||
fn generate_random_bits(num_bits: usize) -> u64 {
|
self.machine_st.fail = self.rng.gen();
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
let rand = rng.borrow_mut();
|
|
||||||
let mut random_bits: u64 = 0;
|
|
||||||
|
|
||||||
for _ in 0..num_bits {
|
|
||||||
random_bits <<= 1;
|
|
||||||
|
|
||||||
if rand.gen_bool(0.5) {
|
|
||||||
random_bits |= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
random_bits
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = { generate_random_bits(1) == 0 };
|
|
||||||
|
|
||||||
self.machine_st.fail = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@@ -4264,7 +4247,7 @@ impl Machine {
|
|||||||
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let err = self.machine_st.resource_error(len);
|
let err = self.machine_st.resource_error(ResourceError::FiniteMemory(len));
|
||||||
return Err(self.machine_st.error_form(err, stub_gen()));
|
return Err(self.machine_st.error_form(err, stub_gen()));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4429,64 +4412,128 @@ impl Machine {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn http_listen(&mut self) -> CallResult {
|
pub(crate) fn http_listen(&mut self) -> CallResult {
|
||||||
let address_sink = self.deref_register(1);
|
let address_sink = self.deref_register(1);
|
||||||
if let Some(address_str) = self.machine_st.value_to_str_like(address_sink) {
|
let tls_key = self.deref_register(3);
|
||||||
let address_string = address_str.as_str();
|
let tls_cert = self.deref_register(4);
|
||||||
let addr: SocketAddr = match address_string
|
let content_length_limit = self.deref_register(5);
|
||||||
.to_socket_addrs()
|
const CONTENT_LENGTH_LIMIT_DEFAULT: u64 = 32768;
|
||||||
.ok()
|
let content_length_limit = match Number::try_from(content_length_limit) {
|
||||||
.and_then(|mut s| s.next())
|
Ok(Number::Fixnum(n)) => if n.get_num() >= 0 {
|
||||||
{
|
n.get_num() as u64
|
||||||
Some(addr) => addr,
|
} else {
|
||||||
_ => {
|
CONTENT_LENGTH_LIMIT_DEFAULT
|
||||||
self.machine_st.fail = true;
|
},
|
||||||
return Ok(());
|
Ok(Number::Integer(n)) => {
|
||||||
}
|
let n: Result<u64, _> = (&*n).try_into();
|
||||||
};
|
match n {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(_) => CONTENT_LENGTH_LIMIT_DEFAULT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => CONTENT_LENGTH_LIMIT_DEFAULT,
|
||||||
|
};
|
||||||
|
|
||||||
let (tx, rx) = std::sync::mpsc::sync_channel(1024);
|
let ssl_server: Option<(String,String)> = {
|
||||||
|
match self.machine_st.value_to_str_like(tls_key) {
|
||||||
|
Some(key) => {
|
||||||
|
match self.machine_st.value_to_str_like(tls_cert) {
|
||||||
|
Some(cert) => {
|
||||||
|
let key_str = key.as_str();
|
||||||
|
let cert_str = cert.as_str();
|
||||||
|
|
||||||
|
if key_str.is_empty() || cert_str.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((key_str.to_string(), cert_str.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let runtime = tokio::runtime::Handle::current();
|
if let Some(address_str) = self.machine_st.value_to_str_like(address_sink) {
|
||||||
let _guard = runtime.enter();
|
let address_string = address_str.as_str();
|
||||||
|
let addr: SocketAddr = match address_string.to_socket_addrs().ok().and_then(|mut s| s.next()) {
|
||||||
|
Some(addr) => addr,
|
||||||
|
_ => {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let listener = match runtime
|
let (tx, rx) = std::sync::mpsc::sync_channel(1024);
|
||||||
.block_on(async { tokio::net::TcpListener::bind(addr).await })
|
|
||||||
{
|
|
||||||
Ok(listener) => listener,
|
|
||||||
Err(_) => {
|
|
||||||
return Err(self.machine_st.open_permission_error(
|
|
||||||
address_sink,
|
|
||||||
atom!("http_listen"),
|
|
||||||
2,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
runtime.spawn(async move {
|
let runtime = tokio::runtime::Handle::current();
|
||||||
loop {
|
let _guard = runtime.enter();
|
||||||
let tx = tx.clone();
|
|
||||||
let (stream, _) = listener.accept().await.unwrap();
|
|
||||||
|
|
||||||
tokio::task::spawn(async move {
|
|
||||||
let io = TokioIo::new(stream);
|
|
||||||
|
|
||||||
if let Err(err) = http1::Builder::new()
|
|
||||||
.serve_connection(io, HttpService {tx})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
eprintln!("Error serving connection: {:?}", err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let http_listener = HttpListener { incoming: rx };
|
|
||||||
let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
|
|
||||||
|
|
||||||
let addr = self.deref_register(2);
|
fn get_reader(body: impl Buf + Send + 'static) -> Box<dyn BufRead + Send> {
|
||||||
self.machine_st.bind(
|
Box::new(body.reader())
|
||||||
addr.as_var().unwrap(),
|
}
|
||||||
typed_arena_ptr_as_cell!(http_listener),
|
|
||||||
);
|
let serve = warp::body::aggregate()
|
||||||
|
.and(warp::header::optional::<u64>(warp::http::header::CONTENT_LENGTH.as_str()))
|
||||||
|
.and(warp::method())
|
||||||
|
.and(warp::header::headers_cloned())
|
||||||
|
.and(warp::path::full())
|
||||||
|
.and(warp::query::raw().or_else(|_| future::ready(Ok::<(String,), warp::Rejection>(("".to_string(),)))))
|
||||||
|
.map(move |body, content_length, method, headers: warp::http::HeaderMap, path: warp::filters::path::FullPath, query| {
|
||||||
|
if let Some(content_length) = content_length {
|
||||||
|
if content_length > content_length_limit {
|
||||||
|
return warp::http::Response::builder()
|
||||||
|
.status(413)
|
||||||
|
.body(warp::hyper::Body::empty())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let http_request_data = HttpRequestData {
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
path: path.as_str().to_string(),
|
||||||
|
query,
|
||||||
|
body: get_reader(body),
|
||||||
|
};
|
||||||
|
let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
|
||||||
|
let http_request = HttpRequest { request_data: http_request_data, response: Arc::clone(&response) };
|
||||||
|
// we send the request to http_accept
|
||||||
|
tx.send(http_request).unwrap();
|
||||||
|
|
||||||
|
// we wait for the Response info from Prolog
|
||||||
|
{
|
||||||
|
let (ready, _response, cvar) = &*response;
|
||||||
|
let mut ready = ready.lock().unwrap();
|
||||||
|
while !*ready {
|
||||||
|
ready = cvar.wait(ready).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let (_, response, _) = &*response;
|
||||||
|
let response = response.lock().unwrap().take();
|
||||||
|
response.expect("Data race error in HTTP server")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
runtime.spawn(async move {
|
||||||
|
match ssl_server {
|
||||||
|
Some((key, cert)) => {
|
||||||
|
warp::serve(serve).tls().key(key).cert(cert).run(addr).await
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
warp::serve(serve).run(addr).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let http_listener = HttpListener { incoming: rx };
|
||||||
|
let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
|
||||||
|
|
||||||
|
let addr = self.deref_register(2);
|
||||||
|
self.machine_st.bind(
|
||||||
|
addr.as_var().unwrap(),
|
||||||
|
typed_arena_ptr_as_cell!(http_listener),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -4494,75 +4541,94 @@ impl Machine {
|
|||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn http_accept(&mut self) -> CallResult {
|
pub(crate) fn http_accept(&mut self) -> CallResult {
|
||||||
let culprit = self.deref_register(1);
|
let culprit = self.deref_register(1);
|
||||||
let method = self.deref_register(2);
|
let method = self.deref_register(2);
|
||||||
let path = self.deref_register(3);
|
let path = self.deref_register(3);
|
||||||
let query = self.deref_register(5);
|
let query = self.deref_register(5);
|
||||||
let stream_addr = self.deref_register(6);
|
let stream_addr = self.deref_register(6);
|
||||||
let handle_addr = self.deref_register(7);
|
let handle_addr = self.deref_register(7);
|
||||||
read_heap_cell!(culprit,
|
read_heap_cell!(culprit,
|
||||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||||
match_untyped_arena_ptr!(cons_ptr,
|
match_untyped_arena_ptr!(cons_ptr,
|
||||||
(ArenaHeaderTag::HttpListener, http_listener) => {
|
(ArenaHeaderTag::HttpListener, http_listener) => {
|
||||||
match http_listener.incoming.recv() {
|
loop {
|
||||||
Ok(request) => {
|
match http_listener.incoming.recv_timeout(std::time::Duration::from_millis(200)) {
|
||||||
let method_atom = match *request.request.method() {
|
Ok(request) => {
|
||||||
Method::GET => atom!("get"),
|
let method_atom = match request.request_data.method {
|
||||||
Method::POST => atom!("post"),
|
Method::GET => atom!("get"),
|
||||||
Method::PUT => atom!("put"),
|
Method::POST => atom!("post"),
|
||||||
Method::DELETE => atom!("delete"),
|
Method::PUT => atom!("put"),
|
||||||
Method::PATCH => atom!("patch"),
|
Method::DELETE => atom!("delete"),
|
||||||
Method::HEAD => atom!("head"),
|
Method::PATCH => atom!("patch"),
|
||||||
_ => unreachable!(),
|
Method::HEAD => atom!("head"),
|
||||||
};
|
Method::OPTIONS => atom!("options"),
|
||||||
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, request.request.uri().path());
|
Method::TRACE => atom!("trace"),
|
||||||
let path_cell = atom_as_cstr_cell!(path_atom);
|
Method::CONNECT => atom!("connect"),
|
||||||
let headers: Vec<HeapCellValue> = request.request.headers().iter().map(|(header_name, header_value)| {
|
_ => atom!("unsupported_extension"),
|
||||||
let h = self.machine_st.heap.len();
|
};
|
||||||
|
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &request.request_data.path);
|
||||||
|
let path_cell = atom_as_cstr_cell!(path_atom);
|
||||||
|
let headers: Vec<HeapCellValue> = request.request_data.headers.iter().map(|(header_name, header_value)| {
|
||||||
|
let h = self.machine_st.heap.len();
|
||||||
|
let header_term = functor!(AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()), [cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]);
|
||||||
|
|
||||||
let header_term = functor!(
|
self.machine_st.heap.extend(header_term.into_iter());
|
||||||
AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()),
|
str_loc_as_cell!(h)
|
||||||
[cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]
|
}).collect();
|
||||||
);
|
|
||||||
|
|
||||||
self.machine_st.heap.extend(header_term.into_iter());
|
let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
|
||||||
str_loc_as_cell!(h)
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
|
let query_str = request.request_data.query;
|
||||||
|
let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &query_str);
|
||||||
|
let query_cell = string_as_cstr_cell!(query_atom);
|
||||||
|
|
||||||
let query_str = request.request.uri().query().unwrap_or("");
|
let mut stream = Stream::from_http_stream(
|
||||||
let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, query_str);
|
path_atom,
|
||||||
let query_cell = string_as_cstr_cell!(query_atom);
|
request.request_data.body,
|
||||||
|
&mut self.machine_st.arena
|
||||||
|
);
|
||||||
|
*stream.options_mut() = StreamOptions::default();
|
||||||
|
stream.options_mut().set_stream_type(StreamType::Binary);
|
||||||
|
self.indices.streams.insert(stream);
|
||||||
|
let stream = stream_as_cell!(stream);
|
||||||
|
|
||||||
let hyper_req = request.request;
|
let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
|
||||||
let runtime = tokio::runtime::Handle::current();
|
|
||||||
let buf = runtime.block_on(async {hyper_req.collect().await.unwrap().aggregate()});
|
|
||||||
let reader = buf.reader();
|
|
||||||
|
|
||||||
let mut stream = Stream::from_http_stream(
|
self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
|
||||||
path_atom,
|
self.machine_st.bind(path.as_var().unwrap(), path_cell);
|
||||||
Box::new(reader),
|
unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
|
||||||
&mut self.machine_st.arena
|
self.machine_st.bind(query.as_var().unwrap(), query_cell);
|
||||||
);
|
self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
|
||||||
*stream.options_mut() = StreamOptions::default();
|
self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
|
||||||
stream.options_mut().set_stream_type(StreamType::Binary);
|
break
|
||||||
self.indices.streams.insert(stream);
|
}
|
||||||
let stream = stream_as_cell!(stream);
|
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
|
||||||
|
let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
|
match machine::INTERRUPT.compare_exchange(
|
||||||
|
interrupted,
|
||||||
|
false,
|
||||||
|
std::sync::atomic::Ordering::Relaxed,
|
||||||
|
std::sync::atomic::Ordering::Relaxed,
|
||||||
|
) {
|
||||||
|
Ok(interruption) => {
|
||||||
|
if interruption {
|
||||||
|
self.machine_st.throw_interrupt_exception();
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
|
||||||
|
old_runtime.shutdown_background();
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
|
}
|
||||||
self.machine_st.bind(path.as_var().unwrap(), path_cell);
|
Err(_) => {
|
||||||
unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
|
self.machine_st.fail = true;
|
||||||
self.machine_st.bind(query.as_var().unwrap(), query_cell);
|
}
|
||||||
self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
|
}
|
||||||
self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
|
|
||||||
}
|
}
|
||||||
Err(_) => {
|
|
||||||
self.machine_st.fail = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@@ -4585,7 +4651,7 @@ impl Machine {
|
|||||||
Ok(Number::Fixnum(n)) => n.get_num() as u16,
|
Ok(Number::Fixnum(n)) => n.get_num() as u16,
|
||||||
Ok(Number::Integer(n)) => {
|
Ok(Number::Integer(n)) => {
|
||||||
let n: Result<u16, _> = (&*n).try_into();
|
let n: Result<u16, _> = (&*n).try_into();
|
||||||
|
|
||||||
if let Ok(value) = n {
|
if let Ok(value) = n {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@@ -5597,7 +5663,9 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn redo_attr_var_binding(&mut self) {
|
pub(crate) fn redo_attr_var_binding(&mut self) {
|
||||||
let var = self.deref_register(1);
|
// registers[1] MUST NOT be dereferenced here. the original
|
||||||
|
// AttrVar binding site must be preserved.
|
||||||
|
let var = self.machine_st.registers[1];
|
||||||
let value = self.deref_register(2);
|
let value = self.deref_register(2);
|
||||||
|
|
||||||
debug_assert_eq!(HeapCellValueTag::AttrVar, var.get_tag());
|
debug_assert_eq!(HeapCellValueTag::AttrVar, var.get_tag());
|
||||||
@@ -5631,7 +5699,7 @@ impl Machine {
|
|||||||
|
|
||||||
if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
|
if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
|
||||||
self.machine_st.cwil.reset();
|
self.machine_st.cwil.reset();
|
||||||
self.machine_st.increment_call_count_fn = |_| Ok(());
|
self.machine_st.increment_call_count_fn = |_| true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5640,11 +5708,10 @@ impl Machine {
|
|||||||
let a1 = self.deref_register(1);
|
let a1 = self.deref_register(1);
|
||||||
let a2 = self.deref_register(2);
|
let a2 = self.deref_register(2);
|
||||||
|
|
||||||
let bp = cell_as_fixnum!(a1).get_num() as usize;
|
let block = cell_as_fixnum!(a1).get_num() as usize;
|
||||||
|
let count = self.machine_st.cwil.remove_limit(block).clone();
|
||||||
let count = self.machine_st.cwil.remove_limit(bp).clone();
|
|
||||||
|
|
||||||
let result = count.clone().try_into();
|
let result = count.clone().try_into();
|
||||||
|
|
||||||
if let Ok(value) = result{
|
if let Ok(value) = result{
|
||||||
self.machine_st.unify_fixnum(Fixnum::build_with(value), a2);
|
self.machine_st.unify_fixnum(Fixnum::build_with(value), a2);
|
||||||
} else {
|
} else {
|
||||||
@@ -5811,6 +5878,11 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn inference_limit_exceeded(&mut self) {
|
||||||
|
self.machine_st.fail = !self.machine_st.cwil.inference_limit_exceeded;
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn clean_up_block(&mut self) {
|
pub(crate) fn clean_up_block(&mut self) {
|
||||||
let nb = self.deref_register(1);
|
let nb = self.deref_register(1);
|
||||||
@@ -6191,16 +6263,19 @@ impl Machine {
|
|||||||
match Number::try_from(seed) {
|
match Number::try_from(seed) {
|
||||||
Ok(Number::Fixnum(n)) => {
|
Ok(Number::Fixnum(n)) => {
|
||||||
let n: u64 = Integer::from(n).try_into().unwrap();
|
let n: u64 = Integer::from(n).try_into().unwrap();
|
||||||
let _: StdRng = SeedableRng::seed_from_u64(n);
|
let rng: StdRng = SeedableRng::seed_from_u64(n);
|
||||||
|
self.rng = rng;
|
||||||
},
|
},
|
||||||
Ok(Number::Integer(n)) => {
|
Ok(Number::Integer(n)) => {
|
||||||
let n: u64 = (&*n).try_into().unwrap();
|
let n: u64 = (&*n).try_into().unwrap();
|
||||||
let _: StdRng = SeedableRng::seed_from_u64(n);
|
let rng: StdRng = SeedableRng::seed_from_u64(n);
|
||||||
|
self.rng = rng;
|
||||||
},
|
},
|
||||||
Ok(Number::Rational(n)) => {
|
Ok(Number::Rational(n)) => {
|
||||||
if n.denominator() == &UBig::from(1 as u32) {
|
if n.denominator() == &UBig::from(1 as u32) {
|
||||||
let n: u64 = n.numerator().try_into().unwrap();
|
let n: u64 = n.numerator().try_into().unwrap();
|
||||||
let _: StdRng = SeedableRng::seed_from_u64(n);
|
let rng: StdRng = SeedableRng::seed_from_u64(n);
|
||||||
|
self.rng = rng;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -7330,7 +7405,7 @@ impl Machine {
|
|||||||
let iterations = match Number::try_from(iterations) {
|
let iterations = match Number::try_from(iterations) {
|
||||||
Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
|
Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
|
||||||
Ok(Number::Integer(n)) => {
|
Ok(Number::Integer(n)) => {
|
||||||
let n: Result<u64, _> = (&*n).try_into();
|
let n: Result<u64, _> = (&*n).try_into();
|
||||||
match n {
|
match n {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
_ => {
|
_ => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::heap_iter::stackful_preorder_iter;
|
use crate::heap_iter::{NonListElider, stackful_preorder_iter};
|
||||||
use crate::machine::machine_state::*;
|
use crate::machine::machine_state::*;
|
||||||
use crate::machine::partial_string::*;
|
use crate::machine::partial_string::*;
|
||||||
use crate::machine::*;
|
use crate::machine::*;
|
||||||
@@ -717,7 +717,7 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
|
|||||||
if !value.is_constant() {
|
if !value.is_constant() {
|
||||||
let machine_st: &mut MachineState = unifier.deref_mut();
|
let machine_st: &mut MachineState = unifier.deref_mut();
|
||||||
|
|
||||||
for cell in stackful_preorder_iter(&mut machine_st.heap, &mut machine_st.stack, value) {
|
for cell in stackful_preorder_iter::<NonListElider>(&mut machine_st.heap, &mut machine_st.stack, value) {
|
||||||
let cell = unmark_cell_bits!(cell);
|
let cell = unmark_cell_bits!(cell);
|
||||||
|
|
||||||
if let Some(inner_r) = cell.as_var() {
|
if let Some(inner_r) = cell.as_var() {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ pub const FY: u32 = 0x0080;
|
|||||||
pub const DELIMITER: u32 = 0x0100;
|
pub const DELIMITER: u32 = 0x0100;
|
||||||
pub const TERM: u32 = 0x1000;
|
pub const TERM: u32 = 0x1000;
|
||||||
pub const LTERM: u32 = 0x3000;
|
pub const LTERM: u32 = 0x3000;
|
||||||
|
pub const BTERM: u32 = 0x11000;
|
||||||
|
|
||||||
pub const NEGATIVE_SIGN: u32 = 0x0200;
|
pub const NEGATIVE_SIGN: u32 = 0x0200;
|
||||||
|
|
||||||
@@ -808,7 +809,7 @@ pub fn source_arity(terms: &[Term]) -> usize {
|
|||||||
terms.len()
|
terms.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unfold_by_str_once(term: &mut Term, s: Atom) -> Option<(Term, Term)> {
|
pub(crate) fn unfold_by_str_once(term: &mut Term, s: Atom) -> Option<(Term, Term)> {
|
||||||
if let Term::Clause(_, ref name, ref mut subterms) = term {
|
if let Term::Clause(_, ref name, ref mut subterms) = term {
|
||||||
if let Some(last_arg) = subterms.last() {
|
if let Some(last_arg) = subterms.last() {
|
||||||
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
|
if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ macro_rules! hexadecimal_digit_char {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! layout_char {
|
macro_rules! layout_char {
|
||||||
($c: expr) => {
|
($c: expr) => {
|
||||||
$crate::char_class!($c, [' ', '\n', '\t', '\u{0B}', '\u{0C}'])
|
$crate::char_class!($c, [' ', '\r', '\n', '\t', '\u{0B}', '\u{0C}'])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ struct TokenDesc {
|
|||||||
tt: TokenType,
|
tt: TokenType,
|
||||||
priority: usize,
|
priority: usize,
|
||||||
spec: u32,
|
spec: u32,
|
||||||
|
unfold_bounds: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_partial_string(
|
pub(crate) fn as_partial_string(
|
||||||
@@ -371,6 +372,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
tt: TokenType::Term,
|
tt: TokenType::Term,
|
||||||
priority: td.priority,
|
priority: td.priority,
|
||||||
spec,
|
spec,
|
||||||
|
unfold_bounds: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -392,6 +394,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
tt: TokenType::Term,
|
tt: TokenType::Term,
|
||||||
priority: td.priority,
|
priority: td.priority,
|
||||||
spec,
|
spec,
|
||||||
|
unfold_bounds: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,6 +408,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
tt: TokenType::Term,
|
tt: TokenType::Term,
|
||||||
priority,
|
priority,
|
||||||
spec: assoc,
|
spec: assoc,
|
||||||
|
unfold_bounds: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +464,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
Token::End => TokenType::End,
|
Token::End => TokenType::End,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.stack.push(TokenDesc { tt, priority, spec });
|
self.stack.push(TokenDesc { tt, priority, spec, unfold_bounds: 0, });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_op(&mut self, priority: usize) {
|
fn reduce_op(&mut self, priority: usize) {
|
||||||
@@ -602,14 +606,20 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(&mut TokenDesc {
|
if let Some(&mut TokenDesc {
|
||||||
|
ref mut tt,
|
||||||
ref mut priority,
|
ref mut priority,
|
||||||
ref mut spec,
|
ref mut spec,
|
||||||
ref mut tt,
|
ref mut unfold_bounds,
|
||||||
}) = self.stack.last_mut()
|
}) = self.stack.last_mut()
|
||||||
{
|
{
|
||||||
|
if *spec == BTERM {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*tt = TokenType::Term;
|
*tt = TokenType::Term;
|
||||||
*priority = 0;
|
*priority = 0;
|
||||||
*spec = TERM;
|
*spec = TERM;
|
||||||
|
*unfold_bounds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -625,8 +635,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
|
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
|
||||||
if let Some(term) = self.terms.pop() {
|
if let Some(mut term) = self.terms.pop() {
|
||||||
let op_desc = self.stack[index - 1];
|
let mut op_desc = self.stack[index - 1];
|
||||||
|
|
||||||
if 0 < op_desc.priority && op_desc.priority < self.stack[index].priority {
|
if 0 < op_desc.priority && op_desc.priority < self.stack[index].priority {
|
||||||
/* '|' is a head-tail separator here, not
|
/* '|' is a head-tail separator here, not
|
||||||
@@ -634,7 +644,26 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
* terms it compacted out again. */
|
* terms it compacted out again. */
|
||||||
match (term.name(), term.arity()) {
|
match (term.name(), term.arity()) {
|
||||||
(Some(name), 2) if name == atom!(",") => {
|
(Some(name), 2) if name == atom!(",") => {
|
||||||
let terms = unfold_by_str(term, name); // notice: name == "," here.
|
let terms = if op_desc.unfold_bounds == 0 {
|
||||||
|
unfold_by_str(term, atom!(","))
|
||||||
|
} else {
|
||||||
|
let mut terms = vec![];
|
||||||
|
|
||||||
|
while let Some((fst, snd)) = unfold_by_str_once(&mut term, atom!(",")) {
|
||||||
|
terms.push(fst);
|
||||||
|
term = snd;
|
||||||
|
|
||||||
|
op_desc.unfold_bounds -= 2;
|
||||||
|
|
||||||
|
if op_desc.unfold_bounds == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terms.push(term);
|
||||||
|
terms
|
||||||
|
};
|
||||||
|
|
||||||
let arity = terms.len() - 1;
|
let arity = terms.len() - 1;
|
||||||
|
|
||||||
self.terms.extend(terms.into_iter());
|
self.terms.extend(terms.into_iter());
|
||||||
@@ -750,6 +779,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
tt: TokenType::Term,
|
tt: TokenType::Term,
|
||||||
priority: 0,
|
priority: 0,
|
||||||
spec: TERM,
|
spec: TERM,
|
||||||
|
unfold_bounds: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.terms.push(match list {
|
self.terms.push(match list {
|
||||||
@@ -852,7 +882,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
.push(Term::Literal(Cell::default(), Literal::Atom(atom)));
|
.push(Term::Literal(Cell::default(), Literal::Atom(atom)));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.stack[idx].spec = TERM;
|
self.stack[idx].spec = if self.stack[idx].priority > 0 { TERM } else { BTERM };
|
||||||
self.stack[idx].tt = TokenType::Term;
|
self.stack[idx].tt = TokenType::Term;
|
||||||
self.stack[idx].priority = 0;
|
self.stack[idx].priority = 0;
|
||||||
|
|
||||||
@@ -975,6 +1005,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
),
|
),
|
||||||
Token::Literal(c) => {
|
Token::Literal(c) => {
|
||||||
let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
|
let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
|
||||||
|
|
||||||
if let Some(name) = atomized {
|
if let Some(name) = atomized {
|
||||||
if !self.shift_op(name, op_dir)? {
|
if !self.shift_op(name, op_dir)? {
|
||||||
self.shift(Token::Literal(c), 0, TERM);
|
self.shift(Token::Literal(c), 0, TERM);
|
||||||
@@ -1018,13 +1049,20 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
/* '|' as an operator must have priority > 1000 and can only be infix.
|
/* '|' as an operator must have priority > 1000 and can only be infix.
|
||||||
* See: http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#Res_A78
|
* See: http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#Res_A78
|
||||||
*/
|
*/
|
||||||
let bar_atom = atom!("|");
|
let (priority, spec) = get_op_desc(atom!("|"), op_dir)
|
||||||
|
|
||||||
let (priority, spec) = get_op_desc(bar_atom, op_dir)
|
|
||||||
.map(|CompositeOpDesc { inf, spec, .. }| (inf, spec))
|
.map(|CompositeOpDesc { inf, spec, .. }| (inf, spec))
|
||||||
.unwrap_or((1000, DELIMITER));
|
.unwrap_or((1000, DELIMITER));
|
||||||
|
|
||||||
|
let old_stack_len = self.stack.len();
|
||||||
|
|
||||||
self.reduce_op(priority);
|
self.reduce_op(priority);
|
||||||
|
|
||||||
|
let new_stack_len = self.stack.len();
|
||||||
|
|
||||||
|
if let Some(term_desc) = self.stack.last_mut() {
|
||||||
|
term_desc.unfold_bounds = old_stack_len - new_stack_len;
|
||||||
|
}
|
||||||
|
|
||||||
self.shift(Token::HeadTailSeparator, priority, spec);
|
self.shift(Token::HeadTailSeparator, priority, spec);
|
||||||
}
|
}
|
||||||
Token::Comma => {
|
Token::Comma => {
|
||||||
|
|||||||
270
src/tests/dif.pl
Normal file
270
src/tests/dif.pl
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
/**/
|
||||||
|
|
||||||
|
:- use_module(library(format)).
|
||||||
|
:- use_module(library(dcgs)).
|
||||||
|
:- use_module(library(lists)).
|
||||||
|
:- use_module(library(debug)).
|
||||||
|
:- use_module(library(atts)).
|
||||||
|
:- use_module(library(dif)).
|
||||||
|
|
||||||
|
% Tests from https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dif
|
||||||
|
|
||||||
|
test("dif#1",(
|
||||||
|
call_residual_goals(dif(1,2), Res),
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#2",(
|
||||||
|
\+ (dif(1,Y), Y = 1)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#3",(
|
||||||
|
call_residual_goals((dif(1,Y), Y=2), Res),
|
||||||
|
Y == 2,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#4",(
|
||||||
|
\+ (dif(X,-Y), X= -Y)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#5",(
|
||||||
|
\+ (dif(X,Y), X=Y)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#6",(
|
||||||
|
\+ (dif(X,Y), X=Y, X=1)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#7",(
|
||||||
|
\+ (dif(-X,-Y), X=Y)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#8",(
|
||||||
|
\+ (dif(-X,-Y), X=Y, X=1)
|
||||||
|
)).
|
||||||
|
|
||||||
|
% I don't understand exactly what is expected for dif#9 and dif#10
|
||||||
|
|
||||||
|
test("dif#11",(
|
||||||
|
call_residual_goals((X=Y, dif(X-Y,1-2)), Res),
|
||||||
|
X == Y,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#12",(
|
||||||
|
call_residual_goals((dif(X-Y,1-2), X=Y), Res),
|
||||||
|
X == Y,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#13",(
|
||||||
|
call_residual_goals((X=Y, Y=1, dif(X-Y,1-2)), Res),
|
||||||
|
X == 1,
|
||||||
|
Y == 1,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#14",(
|
||||||
|
call_residual_goals((dif(X-Y,1-2), X=Y, Y=1), Res),
|
||||||
|
X == 1,
|
||||||
|
Y == 1,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#15",(
|
||||||
|
call_residual_goals((dif(X-Y,1-2), X=Y, X=2), Res),
|
||||||
|
X == 2,
|
||||||
|
Y == 2,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#16",(
|
||||||
|
call_residual_goals((dif(A-C,B-D), C-D=z-z, A-B=1-2), Res),
|
||||||
|
A == 1,
|
||||||
|
B == 2,
|
||||||
|
C == z,
|
||||||
|
D == z,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#17",(
|
||||||
|
call_residual_goals((A-B=1-2, C-D=z-z, dif(A-C,B-D)), Res),
|
||||||
|
A == 1,
|
||||||
|
B == 2,
|
||||||
|
C == z,
|
||||||
|
D == z,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#18",(
|
||||||
|
call_residual_goals((dif(A,[C|B]), A=[[]|_], A=[B]), Res),
|
||||||
|
A == [[]],
|
||||||
|
B == [],
|
||||||
|
Res = [dif:dif([[]], [C])]
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#19",(
|
||||||
|
call_residual_goals((dif([E],[/]), E=1), Res),
|
||||||
|
E == 1,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#20",(
|
||||||
|
call_residual_goals((dif([a],B), B=[_|_], B=[b]), Res),
|
||||||
|
B == [b],
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#21",(
|
||||||
|
call_residual_goals((dif([],A), A = [_]), Res),
|
||||||
|
A = [_],
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#22",(
|
||||||
|
call_residual_goals((A = [_], dif([],A)), Res),
|
||||||
|
A = [_],
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t1",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
\+ \+ -X=X
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t2",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
\+ (-X=X, -Y=Y, X\=Y)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t3",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
call_residual_goals((-X=X, dif(X,1)), Res),
|
||||||
|
X == -X,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t4",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
\+ (-X=X, -Y=Y, dif(X,Y))
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t5",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
\+ (dif(X,Y), -X=X, -Y=Y)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t6",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
\+ (A=[[]|A],dif(A,B),B=[[]|A])
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#t7",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
\+ (dif(-X,X),-Y=Y,X=Y)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#o1",(
|
||||||
|
set_prolog_flag(occurs_check, true),
|
||||||
|
\+ (-X = X)
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#o2",(
|
||||||
|
set_prolog_flag(occurs_check, true),
|
||||||
|
call_residual_goals((dif(-X,X)), Res),
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#o3",(
|
||||||
|
set_prolog_flag(occurs_check, true),
|
||||||
|
call_residual_goals((dif(-X,Y), X=Y), Res),
|
||||||
|
X == Y,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
test("dif#12 but with multiple variables in the residuals",(
|
||||||
|
call_residual_goals((dif(X-Y-_, 1-2-3), X = Y), Res),
|
||||||
|
X == Y,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
% https://github.com/mthom/scryer-prolog/issues/1956
|
||||||
|
test("scryer-prolog#1956",(
|
||||||
|
call_residue_vars((dif(a-a,X-_),X=b), Res),
|
||||||
|
X == b,
|
||||||
|
Res = []
|
||||||
|
)).
|
||||||
|
|
||||||
|
% https://github.com/mthom/scryer-prolog/issues/2056
|
||||||
|
test("scryer-prolog#2056",(
|
||||||
|
set_prolog_flag(occurs_check, false),
|
||||||
|
C=[D|E],
|
||||||
|
D=[C],
|
||||||
|
A=[A],
|
||||||
|
dif(A,[D]),
|
||||||
|
|
||||||
|
\+ E=[]
|
||||||
|
)).
|
||||||
|
|
||||||
|
main :-
|
||||||
|
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||||
|
run_tests(Tests, Failed),
|
||||||
|
show_failed(Failed),
|
||||||
|
halt.
|
||||||
|
|
||||||
|
main_quiet :-
|
||||||
|
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||||
|
run_tests_quiet(Tests, Failed),
|
||||||
|
( Failed = [] ->
|
||||||
|
format("All tests passed", [])
|
||||||
|
; format("Some tests failed", [])
|
||||||
|
),
|
||||||
|
halt.
|
||||||
|
|
||||||
|
portray_failed_([]) --> [].
|
||||||
|
portray_failed_([F|Fs]) -->
|
||||||
|
"\"", F, "\"", "\n", portray_failed_(Fs).
|
||||||
|
|
||||||
|
portray_failed([]) --> [].
|
||||||
|
portray_failed([F|Fs]) -->
|
||||||
|
"\n", "Failed tests:", "\n", portray_failed_([F|Fs]).
|
||||||
|
|
||||||
|
show_failed(Failed) :-
|
||||||
|
phrase(portray_failed(Failed), F),
|
||||||
|
format("~s", [F]).
|
||||||
|
|
||||||
|
run_tests([], []).
|
||||||
|
run_tests([test(Name, Goal)|Tests], Failed) :-
|
||||||
|
format("Running test \"~s\"~n", [Name]),
|
||||||
|
( call(Goal) ->
|
||||||
|
Failed = Failed1
|
||||||
|
; format("Failed test \"~s\"~n", [Name]),
|
||||||
|
Failed = [Name|Failed1]
|
||||||
|
),
|
||||||
|
run_tests(Tests, Failed1).
|
||||||
|
|
||||||
|
run_tests_quiet([], []).
|
||||||
|
run_tests_quiet([test(Name, Goal)|Tests], Failed) :-
|
||||||
|
( call(Goal) ->
|
||||||
|
Failed = Failed1
|
||||||
|
; Failed = [Name|Failed1]
|
||||||
|
),
|
||||||
|
run_tests_quiet(Tests, Failed1).
|
||||||
|
|
||||||
|
assert_p(A, B) :-
|
||||||
|
phrase(portray_clause_(A), Portrayed),
|
||||||
|
phrase((B, ".\n"), Portrayed).
|
||||||
|
|
||||||
|
call_residual_goals(Goal, ResidualGoals) :-
|
||||||
|
call_residue_vars(Goal, Vars),
|
||||||
|
variables_residual_goals(Vars, ResidualGoals).
|
||||||
|
|
||||||
|
variables_residual_goals(Vars, Goals) :-
|
||||||
|
phrase(variables_residual_goals(Vars), Goals).
|
||||||
|
|
||||||
|
variables_residual_goals([]) --> [].
|
||||||
|
variables_residual_goals([Var|Vars]) -->
|
||||||
|
dif:attribute_goals(Var),
|
||||||
|
variables_residual_goals(Vars).
|
||||||
|
|
||||||
@@ -467,13 +467,14 @@ test_195_205_196_197 :-
|
|||||||
setup_call_cleanup(op(100,xf,''),
|
setup_call_cleanup(op(100,xf,''),
|
||||||
( read_from_chars("(0 '') = ''(X).", T0),
|
( read_from_chars("(0 '') = ''(X).", T0),
|
||||||
call(T0),
|
call(T0),
|
||||||
T0 = (_ = ('')(0)),
|
writeq_term_to_chars(T0, C0),
|
||||||
|
C0 == "0 ''=0 ''",
|
||||||
read_from_chars("0 ''.", T1),
|
read_from_chars("0 ''.", T1),
|
||||||
writeq_term_to_chars(T1, C0),
|
writeq_term_to_chars(T1, C1),
|
||||||
C0 == "0 ''",
|
C1 == "0 ''",
|
||||||
read_from_chars("0''.", T2),
|
read_from_chars("0''.", T2),
|
||||||
writeq_term_to_chars(T2, C1),
|
writeq_term_to_chars(T2, C2),
|
||||||
C1 == "0 ''" ),
|
C2 == "0 ''" ),
|
||||||
op(0,xf,'')).
|
op(0,xf,'')).
|
||||||
|
|
||||||
test_118_119_120 :-
|
test_118_119_120 :-
|
||||||
@@ -774,7 +775,7 @@ test_175 :- T = t(0b1,0o1,0x1),
|
|||||||
test_176 :- X is 0b1mod 2,
|
test_176 :- X is 0b1mod 2,
|
||||||
X == 1.
|
X == 1.
|
||||||
|
|
||||||
test_217_181_290 :-
|
test_217_181_290_317 :-
|
||||||
setup_call_cleanup(( current_op(P, xfy, '|') ->
|
setup_call_cleanup(( current_op(P, xfy, '|') ->
|
||||||
true
|
true
|
||||||
; P = 0
|
; P = 0
|
||||||
@@ -785,7 +786,10 @@ test_217_181_290 :-
|
|||||||
C0 == "a-->b,c | d",
|
C0 == "a-->b,c | d",
|
||||||
read_from_chars("[(a|b)].", T1),
|
read_from_chars("[(a|b)].", T1),
|
||||||
writeq_term_to_chars(T1, C1),
|
writeq_term_to_chars(T1, C1),
|
||||||
C1 == "[(a | b)]"
|
C1 == "[(a | b)]",
|
||||||
|
read_from_chars("[a,(b,c)|[]].", T2),
|
||||||
|
writeq_term_to_chars(T2, C2),
|
||||||
|
C2 == "[a,(b,c)]"
|
||||||
),
|
),
|
||||||
op(P, xfy, '|')).
|
op(P, xfy, '|')).
|
||||||
|
|
||||||
|
|||||||
@@ -75,3 +75,12 @@ fn clpz_load() {
|
|||||||
fn iso_conformity_tests() {
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dif_tests() {
|
||||||
|
run_top_level_test_with_args(
|
||||||
|
&["src/tests/dif.pl", "-f", "-g", "main_quiet"],
|
||||||
|
"",
|
||||||
|
"All tests passed",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user