diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9fa463a4..e35ce825 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -63,10 +63,11 @@ jobs:
# Build and test.
- name: Build library
- run: cargo rustc --lib --target ${{ matrix.target }} ${{ matrix.args }} --verbose
+ continue-on-error: ${{ contains(matrix.target,'wasm32') }} # allow wasm builds to fail tests for now
+ run: cargo build --all-targets --target ${{ matrix.target }} ${{ matrix.args }} --verbose
- name: Test
continue-on-error: ${{ contains(matrix.target,'wasm32') }} # allow wasm builds to fail tests for now
- run: cargo test --target ${{ matrix.target }} ${{ matrix.args }} --all --verbose
+ run: cargo test --target ${{ matrix.target }} ${{ matrix.args }} --all
# On stable rust builds, build a binary and publish as a github actions
# artifact. These binaries could be useful for testing the pipeline but
diff --git a/Cargo.lock b/Cargo.lock
index 122966be..dd6b1d84 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,9 +32,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.0.2"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
@@ -60,12 +60,54 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
+[[package]]
+name = "anstream"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
[[package]]
name = "anstyle"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "arrayvec"
version = "0.5.2"
@@ -127,9 +169,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
-version = "0.21.4"
+version = "0.21.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
+checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
[[package]]
name = "bincode"
@@ -163,9 +205,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "bitvec"
@@ -261,9 +303,9 @@ checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
[[package]]
name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
@@ -303,7 +345,7 @@ dependencies = [
"js-sys",
"num-traits",
"wasm-bindgen",
- "windows-targets",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -335,18 +377,18 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.4.7"
+version = "4.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
+checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
-version = "4.4.7"
+version = "4.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
+checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
dependencies = [
"anstyle",
"clap_lex",
@@ -369,6 +411,12 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
@@ -380,10 +428,19 @@ dependencies = [
]
[[package]]
-name = "core-foundation"
-version = "0.9.3"
+name = "content_inspector"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
@@ -391,9 +448,9 @@ dependencies = [
[[package]]
name = "core-foundation-sys"
-version = "0.8.4"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpp_demangle"
@@ -416,9 +473,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
-version = "0.2.9"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
dependencies = [
"libc",
]
@@ -461,9 +518,9 @@ dependencies = [
[[package]]
name = "crossbeam-deque"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
dependencies = [
"cfg-if",
"crossbeam-epoch",
@@ -472,22 +529,20 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.15"
+version = "0.9.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
- "memoffset",
- "scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.16"
+version = "0.8.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
dependencies = [
"cfg-if",
]
@@ -551,12 +606,12 @@ dependencies = [
[[package]]
name = "ctrlc"
-version = "3.4.1"
+version = "3.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
+checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
dependencies = [
"nix 0.27.1",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -566,10 +621,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.3",
"lock_api",
"once_cell",
- "parking_lot_core 0.9.8",
+ "parking_lot_core 0.9.9",
]
[[package]]
@@ -593,9 +648,9 @@ checksum = "e183fc153511989674ede304b5592c74683393ca09cf20391898c28d6ba04264"
[[package]]
name = "dashu-float"
-version = "0.4.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7696675af30ae057b1629d27b153bbafb06461826b7d0ef1858d06b801f355f"
+checksum = "a672ddc5e64033c8279692d973a89831eb3c3f0ebb1def47435aee0401b6269d"
dependencies = [
"dashu-base",
"dashu-int",
@@ -723,6 +778,12 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+[[package]]
+name = "dunce"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+
[[package]]
name = "either"
version = "1.9.0"
@@ -752,23 +813,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
-version = "0.3.3"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys",
-]
-
-[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
"libc",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -783,9 +833,9 @@ dependencies = [
[[package]]
name = "fastrand"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "fd-lock"
@@ -795,7 +845,19 @@ checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5"
dependencies = [
"cfg-if",
"rustix",
- "windows-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "filetime"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.4.1",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -833,9 +895,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
@@ -858,9 +920,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
@@ -873,9 +935,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
@@ -883,15 +945,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
@@ -900,38 +962,38 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
name = "futures-sink"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
-version = "0.3.28"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
@@ -975,9 +1037,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.10"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [
"cfg-if",
"js-sys",
@@ -988,37 +1050,41 @@ dependencies = [
[[package]]
name = "gimli"
-version = "0.28.0"
+version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "git-version"
-version = "0.3.5"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899"
+checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19"
dependencies = [
"git-version-macro",
- "proc-macro-hack",
]
[[package]]
name = "git-version-macro"
-version = "0.3.5"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f"
+checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0"
dependencies = [
- "proc-macro-hack",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.43",
]
[[package]]
-name = "h2"
-version = "0.3.21"
+name = "glob"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "h2"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
dependencies = [
"bytes",
"fnv",
@@ -1026,7 +1092,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
- "indexmap 1.9.3",
+ "indexmap 2.1.0",
"slab",
"tokio",
"tokio-util",
@@ -1047,9 +1113,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
-version = "0.14.0"
+version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "headers"
@@ -1057,7 +1123,7 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
dependencies = [
- "base64 0.21.4",
+ "base64 0.21.5",
"bytes",
"headers-core",
"http",
@@ -1092,11 +1158,11 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "home"
-version = "0.5.5"
+version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -1126,9 +1192,9 @@ dependencies = [
[[package]]
name = "http"
-version = "0.2.9"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
@@ -1137,9 +1203,9 @@ dependencies = [
[[package]]
name = "http-body"
-version = "0.4.5"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
"http",
@@ -1159,10 +1225,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
-name = "hyper"
-version = "0.14.27"
+name = "humantime"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "humantime-serde"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c"
+dependencies = [
+ "humantime",
+ "serde",
+]
+
+[[package]]
+name = "hyper"
+version = "0.14.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [
"bytes",
"futures-channel",
@@ -1175,7 +1257,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "socket2 0.4.9",
+ "socket2",
"tokio",
"tower-service",
"tracing",
@@ -1213,7 +1295,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
@@ -1226,16 +1308,16 @@ dependencies = [
[[package]]
name = "iana-time-zone"
-version = "0.1.57"
+version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
+checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
- "windows",
+ "windows-core",
]
[[package]]
@@ -1249,9 +1331,9 @@ dependencies = [
[[package]]
name = "idna"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -1269,22 +1351,22 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.0.1"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e"
+checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.3",
]
[[package]]
name = "inferno"
-version = "0.11.17"
+version = "0.11.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50453ec3a6555fad17b1cd1a80d16af5bc7cb35094f64e429fd46549018c6a3"
+checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9"
dependencies = [
"ahash",
- "indexmap 2.0.1",
+ "indexmap 2.1.0",
"is-terminal",
"itoa",
"log",
@@ -1306,9 +1388,9 @@ dependencies = [
[[package]]
name = "ipnet"
-version = "2.8.0"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
+checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
[[package]]
name = "is-terminal"
@@ -1318,7 +1400,7 @@ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi",
"rustix",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -1332,15 +1414,15 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.9"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
-version = "0.3.64"
+version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
+checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
dependencies = [
"wasm-bindgen",
]
@@ -1385,9 +1467,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.148"
+version = "0.2.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
+checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
[[package]]
name = "libffi"
@@ -1419,16 +1501,27 @@ dependencies = [
]
[[package]]
-name = "linux-raw-sys"
-version = "0.4.11"
+name = "libredox"
+version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
+checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
+dependencies = [
+ "bitflags 2.4.1",
+ "libc",
+ "redox_syscall 0.4.1",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
[[package]]
name = "lock_api"
-version = "0.4.10"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
@@ -1486,28 +1579,19 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "memchr"
-version = "2.6.3"
+version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memmap2"
-version = "0.8.0"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
+checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92"
dependencies = [
"libc",
]
-[[package]]
-name = "memoffset"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
-dependencies = [
- "autocfg",
-]
-
[[package]]
name = "mime"
version = "0.3.17"
@@ -1548,13 +1632,13 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.8"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
+checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
"libc",
"wasi",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -1653,11 +1737,17 @@ version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
"cfg-if",
"libc",
]
+[[package]]
+name = "normalize-line-endings"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
+
[[package]]
name = "ntapi"
version = "0.3.7"
@@ -1713,18 +1803,18 @@ dependencies = [
[[package]]
name = "object"
-version = "0.32.1"
+version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oorandom"
@@ -1740,11 +1830,11 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "openssl"
-version = "0.10.60"
+version = "0.10.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800"
+checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
"cfg-if",
"foreign-types",
"libc",
@@ -1761,7 +1851,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
@@ -1772,9 +1862,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.96"
+version = "0.9.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f"
+checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
dependencies = [
"cc",
"libc",
@@ -1784,13 +1874,23 @@ dependencies = [
[[package]]
name = "ordered-float"
-version = "2.10.0"
+version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
dependencies = [
"num-traits",
]
+[[package]]
+name = "os_pipe"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177"
+dependencies = [
+ "libc",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "parking_lot"
version = "0.11.2"
@@ -1809,7 +1909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
- "parking_lot_core 0.9.8",
+ "parking_lot_core 0.9.9",
]
[[package]]
@@ -1828,22 +1928,22 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.8"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.3.5",
+ "redox_syscall 0.4.1",
"smallvec",
- "windows-targets",
+ "windows-targets 0.48.5",
]
[[package]]
name = "percent-encoding"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
@@ -1944,7 +2044,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
@@ -1961,9 +2061,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
[[package]]
name = "plotters"
@@ -2086,9 +2186,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
-version = "1.0.67"
+version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
+checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
dependencies = [
"unicode-ident",
]
@@ -2188,21 +2288,21 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.3.5"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
-version = "0.4.3"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
dependencies = [
"getrandom",
- "redox_syscall 0.2.16",
+ "libredox",
"thiserror",
]
@@ -2214,13 +2314,13 @@ checksum = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6"
[[package]]
name = "regex"
-version = "1.9.1"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
- "regex-automata 0.3.3",
+ "regex-automata 0.4.3",
"regex-syntax",
]
@@ -2232,9 +2332,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-automata"
-version = "0.3.3"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
@@ -2243,17 +2343,17 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.7.4"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "reqwest"
-version = "0.11.20"
+version = "0.11.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
+checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41"
dependencies = [
- "base64 0.21.4",
+ "base64 0.21.5",
"bytes",
"encoding_rs",
"futures-core",
@@ -2274,6 +2374,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
+ "system-configuration",
"tokio",
"tokio-native-tls",
"tower-service",
@@ -2303,25 +2404,23 @@ dependencies = [
"libc",
"once_cell",
"spin 0.5.2",
- "untrusted",
+ "untrusted 0.7.1",
"web-sys",
"winapi",
]
[[package]]
-name = "ring-wasi"
-version = "0.16.25"
+name = "ring"
+version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db1418b2535ed5e71a9fc73d3fede8596792fd7cb4b4a0f8ecf412cfddaaedd4"
+checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
dependencies = [
"cc",
"getrandom",
"libc",
- "once_cell",
- "spin 0.5.2",
- "untrusted",
- "web-sys",
- "winapi",
+ "spin 0.9.8",
+ "untrusted 0.9.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -2352,15 +2451,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
-version = "0.38.21"
+version = "0.38.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
+checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
"errno",
"libc",
"linux-raw-sys",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2370,18 +2469,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
dependencies = [
"log",
- "ring",
+ "ring 0.16.20",
"sct",
"webpki",
]
[[package]]
name = "rustls-pemfile"
-version = "1.0.3"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
dependencies = [
- "base64 0.21.4",
+ "base64 0.21.5",
]
[[package]]
@@ -2396,7 +2495,7 @@ version = "12.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "994eca4bca05c87e86e15d90fc7a91d1be64b4482b38cb2d27474568fe7c9db9"
dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
"cfg-if",
"clipboard-win",
"fd-lock",
@@ -2415,9 +2514,9 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.15"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "same-file"
@@ -2430,11 +2529,11 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
+checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
dependencies = [
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2497,8 +2596,7 @@ dependencies = [
"ref_thread_local",
"regex",
"reqwest",
- "ring",
- "ring-wasi",
+ "ring 0.17.7",
"ripemd160",
"roxmltree",
"rustyline",
@@ -2513,10 +2611,11 @@ dependencies = [
"static_assertions",
"strum",
"strum_macros",
- "syn 2.0.37",
+ "syn 2.0.43",
"to-syn-value",
"to-syn-value_derive",
"tokio",
+ "trycmd",
"walkdir",
"warp",
"wasm-bindgen",
@@ -2526,12 +2625,12 @@ dependencies = [
[[package]]
name = "sct"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
- "ring",
- "untrusted",
+ "ring 0.17.7",
+ "untrusted 0.9.0",
]
[[package]]
@@ -2570,9 +2669,9 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.188"
+version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
@@ -2590,26 +2689,35 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.188"
+version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
name = "serde_json"
-version = "1.0.107"
+version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
+checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [
"itoa",
"ryu",
"serde",
]
+[[package]]
+name = "serde_spanned"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@@ -2644,7 +2752,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
@@ -2660,9 +2768,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.10.7"
+version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -2692,6 +2800,12 @@ dependencies = [
"keccak",
]
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
[[package]]
name = "signal-hook"
version = "0.3.17"
@@ -2722,6 +2836,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "similar"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
+
[[package]]
name = "siphasher"
version = "0.3.11"
@@ -2739,28 +2859,49 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.11.1"
+version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
+checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
-name = "socket2"
-version = "0.4.9"
+name = "snapbox"
+version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+checksum = "c4f1976ee8fd1be27d5f72c98be0aac4397a882a4736935d47418a5fbbd12042"
dependencies = [
+ "anstream",
+ "anstyle",
+ "content_inspector",
+ "dunce",
+ "filetime",
"libc",
- "winapi",
+ "normalize-line-endings",
+ "os_pipe",
+ "similar",
+ "snapbox-macros",
+ "tempfile",
+ "wait-timeout",
+ "walkdir",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "snapbox-macros"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed1559baff8a696add3322b9be3e940d433e7bb4e38d79017205fd37ff28b28e"
+dependencies = [
+ "anstream",
]
[[package]]
name = "socket2"
-version = "0.5.4"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
+checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -2858,9 +2999,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "symbolic-common"
-version = "12.6.0"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "405af7bd5edd866cef462e22ef73f11cf9bf506c9d62824fef8364eb69d4d4ad"
+checksum = "1cccfffbc6bb3bb2d3a26cd2077f4d055f6808d266f9d4d158797a4c60510dfe"
dependencies = [
"debugid",
"memmap2",
@@ -2870,9 +3011,9 @@ dependencies = [
[[package]]
name = "symbolic-demangle"
-version = "12.6.0"
+version = "12.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bcd041ccfb77d9c70639efcd5b804b508ac7a273e9224d227379e225625daf9"
+checksum = "76a99812da4020a67e76c4eb41f08c87364c14170495ff780f30dd519c221a68"
dependencies = [
"cpp_demangle",
"rustc-demangle",
@@ -2892,15 +3033,36 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.37"
+version = "2.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
+checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "tap"
version = "1.0.1"
@@ -2909,15 +3071,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
-version = "3.8.0"
+version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
+checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if",
"fastrand",
- "redox_syscall 0.3.5",
+ "redox_syscall 0.4.1",
"rustix",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2939,22 +3101,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "thiserror"
-version = "1.0.48"
+version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
+checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.48"
+version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
+checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
@@ -2988,7 +3150,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfcc684f2ceaec3b4e8689657c9e0944b07bf5e34563e0bd758c4d42c05c82ed"
dependencies = [
- "syn 2.0.37",
+ "syn 2.0.43",
"to-syn-value_derive",
]
@@ -3000,37 +3162,37 @@ checksum = "3dfffda778de8443144ff3b042ddf14e8bc5445f0fd9fe937c3d252535dc9212"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
name = "tokio"
-version = "1.32.0"
+version = "1.35.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
+checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
dependencies = [
"backtrace",
"bytes",
"libc",
- "mio 0.8.8",
+ "mio 0.8.10",
"num_cpus",
"parking_lot 0.12.1",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.5.4",
+ "socket2",
"tokio-macros",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
[[package]]
@@ -3079,9 +3241,9 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.9"
+version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
+checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
"bytes",
"futures-core",
@@ -3091,6 +3253,28 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "toml_datetime"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.20.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
+dependencies = [
+ "indexmap 2.1.0",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
[[package]]
name = "tower-service"
version = "0.3.2"
@@ -3099,11 +3283,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
-version = "0.1.37"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "cfg-if",
"log",
"pin-project-lite",
"tracing-core",
@@ -3111,18 +3294,34 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.31"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]]
name = "try-lock"
-version = "0.2.4"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "trycmd"
+version = "0.14.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed009372a42fb103e6f8767b9222925485e03cca032b700d203e2c5b67bee4fb"
+dependencies = [
+ "glob",
+ "humantime",
+ "humantime-serde",
+ "rayon",
+ "serde",
+ "shlex",
+ "snapbox",
+ "toml_edit",
+]
[[package]]
name = "tungstenite"
@@ -3160,9 +3359,9 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.13"
+version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416"
[[package]]
name = "unicode-ident"
@@ -3198,10 +3397,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
-name = "url"
-version = "2.4.1"
+name = "untrusted"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
+[[package]]
+name = "url"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
@@ -3222,9 +3427,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
-version = "1.5.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
+checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
[[package]]
name = "vcpkg"
@@ -3306,9 +3511,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
+checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -3316,24 +3521,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
+checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.37"
+version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
+checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
dependencies = [
"cfg-if",
"js-sys",
@@ -3343,9 +3548,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
+checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -3353,28 +3558,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
+checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
+checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]]
name = "web-sys"
-version = "0.3.64"
+version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
+checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -3382,12 +3587,12 @@ dependencies = [
[[package]]
name = "webpki"
-version = "0.22.1"
+version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e"
+checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53"
dependencies = [
- "ring",
- "untrusted",
+ "ring 0.17.7",
+ "untrusted 0.9.0",
]
[[package]]
@@ -3422,12 +3627,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "windows"
-version = "0.48.0"
+name = "windows-core"
+version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -3436,7 +3641,16 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
]
[[package]]
@@ -3445,13 +3659,28 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
]
[[package]]
@@ -3460,42 +3689,93 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+
+[[package]]
+name = "winnow"
+version = "0.5.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "winreg"
version = "0.50.0"
@@ -3503,7 +3783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
"cfg-if",
- "windows-sys",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -3528,26 +3808,26 @@ dependencies = [
[[package]]
name = "xmlparser"
-version = "0.13.5"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd"
+checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
[[package]]
name = "zerocopy"
-version = "0.7.25"
+version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.7.25"
+version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.37",
+ "syn 2.0.43",
]
diff --git a/Cargo.toml b/Cargo.toml
index 2b4f103b..62fab35f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -71,6 +71,7 @@ bytes = "1"
dashu = "0.4.0"
num-order = { version = "1.2.0" }
rand = "0.8.5"
+ring = { version = "0.17.5", features = ["wasm32_unknown_unknown_js"] }
serde_json = "1.0.95"
serde = "1.0.159"
@@ -83,7 +84,7 @@ ctrlc = { version = "3.2.2", optional = true }
rustyline = { version = "12.0.0", optional = true }
native-tls = { version = "0.2.4", optional = true }
warp = { version = "=0.3.5", features = ["tls"], optional = true }
-reqwest = { version = "0.11.18", features = ["blocking"], optional = true }
+reqwest = { version = "0.11.18", optional = true }
tokio = { version = "1.28.2", features = ["full"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
@@ -104,12 +105,6 @@ serde-wasm-bindgen = "0.5"
web-sys = { version = "0.3", features = ["Document", "Window", "Element", "Performance"] }
js-sys = "0.3"
-[target.'cfg(target_os = "wasi")'.dependencies]
-ring-wasi = { version = "0.16.25" }
-
-[target.'cfg(not(target_os = "wasi"))'.dependencies]
-ring = { version = "0.16.13" }
-
[dev-dependencies]
assert_cmd = "1.0.3"
predicates-core = "1.0.2"
@@ -117,6 +112,7 @@ maplit = "1.0.2"
serial_test = "2.0.0"
iai-callgrind = { git = "https://github.com/iai-callgrind/iai-callgrind.git", rev = "c77bc3c83d7f4e976cc42d4597236a8db259e772" }
criterion = "0.5.1"
+trycmd = "0.14.19"
[target.'cfg(not(target_os = "windows"))'.dev-dependencies]
pprof = { version = "0.13.0", features = ["criterion", "flamegraph"] }
diff --git a/README.md b/README.md
index ce8f16bb..10358f21 100644
--- a/README.md
+++ b/README.md
@@ -316,6 +316,35 @@ To quit Scryer Prolog, use the standard predicate `halt/0`:
?- halt.
```
+### Starting Scryer Prolog
+
+Scryer Prolog can be started from the command line by specifying
+options, files and additional arguments. All components are optional:
+
+
+scryer-prolog [OPTIONS] [FILES] [-- ARGUMENTS]
+
+
+The supported options are:
+
+```
+ -h, --help Display help message
+ -v, --version Print version information and exit
+ -g, --goal GOAL Run the query GOAL after consulting files
+ -f Fast startup. Do not load initialization file (~/.scryerrc)
+ --no-add-history Prevent adding input to history file (~/.scryer_history)
+```
+
+All specified Prolog files are consulted.
+
+After Prolog files, application-specific arguments can be specified on
+the command line. These arguments can be accessed from within Prolog
+applications with the predicate `argv/1`, which yields the list
+of arguments represented as strings.
+
+Prolog files can also be turned into *shell scripts* as explained in
+https://github.com/mthom/scryer-prolog/issues/2170#issuecomment-1821713993.
+
### Dynamic operators
Scryer supports dynamic operators. Using the built-in
diff --git a/build/instructions_template.rs b/build/instructions_template.rs
index db0baae3..1840341b 100644
--- a/build/instructions_template.rs
+++ b/build/instructions_template.rs
@@ -511,18 +511,12 @@ enum SystemClauseType {
#[cfg(feature = "crypto-full")]
#[strum_discriminants(strum(props(Arity = "6", Name = "$crypto_data_decrypt")))]
CryptoDataDecrypt,
- #[cfg(feature = "crypto-full")]
- #[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_sign")))]
- Ed25519Sign,
- #[cfg(feature = "crypto-full")]
- #[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_verify")))]
- Ed25519Verify,
- #[cfg(feature = "crypto-full")]
- #[strum_discriminants(strum(props(Arity = "1", Name = "$ed25519_new_keypair")))]
- Ed25519NewKeyPair,
- #[cfg(feature = "crypto-full")]
- #[strum_discriminants(strum(props(Arity = "2", Name = "$ed25519_keypair_public_key")))]
- Ed25519KeyPairPublicKey,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_sign_raw")))]
+ Ed25519SignRaw,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_verify_raw")))]
+ Ed25519VerifyRaw,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$ed25519_seed_to_public_key")))]
+ Ed25519SeedToPublicKey,
#[strum_discriminants(strum(props(Arity = "2", Name = "$first_non_octet")))]
FirstNonOctet,
#[strum_discriminants(strum(props(Arity = "3", Name = "$load_html")))]
@@ -610,6 +604,8 @@ enum SystemClauseType {
KeySortWithConstantVarOrdering,
#[strum_discriminants(strum(props(Arity = "0", Name = "$inference_limit_exceeded")))]
InferenceLimitExceeded,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$argv")))]
+ Argv,
REPL(REPLCodePtr),
}
@@ -796,8 +792,8 @@ enum InstructionTemplate {
#[strum_discriminants(strum(props(Arity = "0", Name = "install_verify_attr")))]
InstallVerifyAttr,
// call verify_attrs.
- #[strum_discriminants(strum(props(Arity = "0", Name = "verify_attr_interrupt")))]
- VerifyAttrInterrupt,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "verify_attr_interrupt")))]
+ VerifyAttrInterrupt(usize),
// procedures
CallClause(ClauseType, usize, usize, bool, bool), // ClauseType,
// arity,
@@ -1157,6 +1153,33 @@ fn generate_instruction_preface() -> TokenStream {
pub type CodeDeque = VecDeque;
impl Instruction {
+ #[inline]
+ pub fn registers(&self) -> Vec {
+ match self {
+ &Instruction::GetConstant(_, _, r) => vec![r],
+ &Instruction::GetList(_, r) => vec![r],
+ &Instruction::GetPartialString(_, _, r, _) => vec![r],
+ &Instruction::GetStructure(_, _, _, r) => vec![r],
+ &Instruction::GetVariable(r, t) => vec![r, temp_v!(t)],
+ &Instruction::GetValue(r, t) => vec![r, temp_v!(t)],
+ &Instruction::UnifyLocalValue(r) => vec![r],
+ &Instruction::UnifyVariable(r) => vec![r],
+ &Instruction::PutConstant(_, _, r) => vec![r],
+ &Instruction::PutList(_, r) => vec![r],
+ &Instruction::PutPartialString(_, _, r, _) => vec![r],
+ &Instruction::PutStructure(_, _, r) => vec![r],
+ &Instruction::PutValue(r, t) => vec![r, temp_v!(t)],
+ &Instruction::PutVariable(r, t) => vec![r, temp_v!(t)],
+ &Instruction::SetLocalValue(r) => vec![r],
+ &Instruction::SetVariable(r) => vec![r],
+ &Instruction::SetValue(r) => vec![r],
+ &Instruction::GetLevel(r) => vec![r],
+ &Instruction::GetPrevLevel(r) => vec![r],
+ &Instruction::GetCutPoint(r) => vec![r],
+ _ => vec![],
+ }
+ }
+
#[inline]
pub fn to_indexing_line_mut(&mut self) -> Option<&mut Vec> {
match self {
@@ -1199,7 +1222,10 @@ fn generate_instruction_preface() -> TokenStream {
Instruction::SetLocalValue(..) |
Instruction::SetVariable(..) |
Instruction::SetValue(..) |
- Instruction::SetVoid(..))
+ Instruction::SetVoid(..) |
+ Instruction::GetLevel(..) |
+ Instruction::GetPrevLevel(..) |
+ Instruction::GetCutPoint(..))
}
pub fn enqueue_functors(
@@ -1244,8 +1270,8 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::InstallVerifyAttr => {
functor!(atom!("install_verify_attr"))
}
- &Instruction::VerifyAttrInterrupt => {
- functor!(atom!("verify_attr_interrupt"))
+ &Instruction::VerifyAttrInterrupt(arity) => {
+ functor!(atom!("verify_attr_interrupt"), [fixnum(arity)])
}
&Instruction::DynamicElse(birth, death, next_or_fail) => {
match (death, next_or_fail) {
@@ -1874,18 +1900,18 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallFlushTermQueue |
&Instruction::CallRemoveModuleExports |
&Instruction::CallAddNonCountedBacktracking |
- &Instruction::CallPopCount => {
+ &Instruction::CallPopCount |
+ &Instruction::CallArgv |
+ &Instruction::CallEd25519SignRaw |
+ &Instruction::CallEd25519VerifyRaw |
+ &Instruction::CallEd25519SeedToPublicKey => {
let (name, arity) = self.to_name_and_arity();
functor!(atom!("call"), [atom(name), fixnum(arity)])
}
//
#[cfg(feature = "crypto-full")]
&Instruction::CallCryptoDataEncrypt |
- &Instruction::CallCryptoDataDecrypt |
- &Instruction::CallEd25519Sign |
- &Instruction::CallEd25519Verify |
- &Instruction::CallEd25519NewKeyPair |
- &Instruction::CallEd25519KeyPairPublicKey => {
+ &Instruction::CallCryptoDataDecrypt => {
let (name, arity) = self.to_name_and_arity();
functor!(atom!("call"), [atom(name), fixnum(arity)])
}
@@ -2110,18 +2136,18 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteFlushTermQueue |
&Instruction::ExecuteRemoveModuleExports |
&Instruction::ExecuteAddNonCountedBacktracking |
- &Instruction::ExecutePopCount => {
+ &Instruction::ExecutePopCount |
+ &Instruction::ExecuteArgv |
+ &Instruction::ExecuteEd25519SignRaw |
+ &Instruction::ExecuteEd25519VerifyRaw |
+ &Instruction::ExecuteEd25519SeedToPublicKey => {
let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute"), [atom(name), fixnum(arity)])
}
//
#[cfg(feature = "crypto-full")]
&Instruction::ExecuteCryptoDataEncrypt |
- &Instruction::ExecuteCryptoDataDecrypt |
- &Instruction::ExecuteEd25519Sign |
- &Instruction::ExecuteEd25519Verify |
- &Instruction::ExecuteEd25519NewKeyPair |
- &Instruction::ExecuteEd25519KeyPairPublicKey => {
+ &Instruction::ExecuteCryptoDataDecrypt => {
let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute"), [atom(name), fixnum(arity)])
}
diff --git a/src/allocator.rs b/src/allocator.rs
index e20bf2cf..e961b975 100644
--- a/src/allocator.rs
+++ b/src/allocator.rs
@@ -53,40 +53,5 @@ pub(crate) trait Allocator {
fn reset_contents(&mut self);
fn advance_arg(&mut self);
-
- /*
- fn bindings(&self) -> &AllocVarDict;
- fn bindings_mut(&mut self) -> &mut AllocVarDict;
- fn take_bindings(self) -> AllocVarDict;
- */
-
fn max_reg_allocated(&self) -> usize;
-
- // TODO: wha.. why?? grrr. it drains the VarStatus data from vs (which it owns!)
- // into self.bindings and perm_vs after all is computed (i.e. vs.populate_restricting_sets()
- // and vs.set_perm_vals(has_deep_cut) have both been called).
- /*
- fn drain_var_data<'a>(
- &mut self,
- vs: VariableFixtures,
- num_of_chunks: usize,
- ) -> VariableFixtures {
- let mut perm_vs = VariableFixtures::new();
-
- for (var, var_status) in vs.into_iter() {
- match var_status {
- VarStatus::Temp(chunk_num, tvd) => {
- self.bindings_mut()
- .insert(var.clone(), VarAlloc::Temp(chunk_num, 0, tvd));
- }
- VarStatus::Perm(_) => {
- self.bindings_mut().insert(var.clone(), VarAlloc::Perm(0));
- perm_vs.insert(var, var_status);
- }
- };
- }
-
- perm_vs
- }
- */
}
diff --git a/src/arena.rs b/src/arena.rs
index 40c1b029..172e6e9d 100644
--- a/src/arena.rs
+++ b/src/arena.rs
@@ -821,9 +821,9 @@ impl AllocSlab {
}
fn payload_offset(&self) -> *mut T {
- let mut ptr = (self as *const AllocSlab) as usize;
- ptr += mem::size_of::();
- ptr as *mut T
+ // This looks really scary, should this method be marked as unsafe?
+ // Also, this seems to cause UB.
+ unsafe { (self as *const AllocSlab).add(1) as *mut T }
}
}
@@ -864,6 +864,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn heap_cell_value_const_cast() {
let mut wam = MockWAM::new();
#[cfg(target_pointer_width = "32")]
@@ -907,6 +908,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on arena.rs UB")]
fn heap_put_literal_tests() {
let mut wam = MockWAM::new();
diff --git a/src/atom_table.rs b/src/atom_table.rs
index e62ca927..3f60eca6 100644
--- a/src/atom_table.rs
+++ b/src/atom_table.rs
@@ -239,6 +239,7 @@ impl Atom {
} else if let Some(ptr) = self.as_ptr() {
AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| {
let header =
+ // Miri seems to hit this line a lot
unsafe { ptr::read::(ptr as *const u8 as *const AtomHeader) };
let len = header.len() as usize;
let buf = unsafe { (ptr as *const u8).add(mem::size_of::()) };
@@ -265,7 +266,7 @@ impl Atom {
unsafe fn write_to_ptr(string: &str, ptr: *mut u8) {
ptr::write(ptr as *mut _, AtomHeader::build_with(string.len() as u64));
- let str_ptr = (ptr as usize + mem::size_of::()) as *mut u8;
+ let str_ptr = ptr.add(mem::size_of::());
ptr::copy_nonoverlapping(string.as_ptr(), str_ptr, string.len());
}
diff --git a/src/bin/scryer-prolog.rs b/src/bin/scryer-prolog.rs
index 572eb2fa..9ae80773 100644
--- a/src/bin/scryer-prolog.rs
+++ b/src/bin/scryer-prolog.rs
@@ -23,6 +23,6 @@ fn main() -> std::process::ExitCode {
runtime.block_on(async move {
let mut wam = machine::Machine::new(Default::default());
- wam.run_top_level(atom!("$toplevel"), (atom!("$repl"), 1))
+ wam.run_module_predicate(atom!("$toplevel"), (atom!("$repl"), 0))
})
}
diff --git a/src/codegen.rs b/src/codegen.rs
index fd0d21f9..23c59238 100644
--- a/src/codegen.rs
+++ b/src/codegen.rs
@@ -860,6 +860,9 @@ impl<'b> CodeGenerator<'b> {
self.marker.mark_safe_var_unconditionally(var_num);
compile_expr!(self, &terms[1], term_loc, code)
} else {
+ self.marker
+ .mark_anon_var::(Level::Shallow, term_loc, code);
+
if let Term::Var(ref vr, ref var) = &terms[1] {
let var_num = var.to_var_num().unwrap();
diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs
index ed905ec0..d44c36cb 100644
--- a/src/debray_allocator.rs
+++ b/src/debray_allocator.rs
@@ -604,16 +604,9 @@ impl DebrayAllocator {
Target::unsafe_argument_to_value(r, arg_c)
}
}
- VarAlloc::Temp { ref mut safety, .. } => {
- if self
- .branch_stack
- .safety_unneeded_in_branch(safety, &branch_designator)
- {
- Target::argument_to_value(r, arg_c)
- } else {
- *safety = VarSafetyStatus::GloballyUnneeded;
- Target::unsafe_argument_to_value(r, arg_c)
- }
+ VarAlloc::Temp { .. } => {
+ debug_assert!(matches!(r, RegType::Temp(_)));
+ Target::argument_to_value(r, arg_c)
}
_ => {
unreachable!()
diff --git a/src/heap_iter.rs b/src/heap_iter.rs
index 4713aa63..cada66cf 100644
--- a/src/heap_iter.rs
+++ b/src/heap_iter.rs
@@ -108,7 +108,7 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> {
let var_value = self.heap[h];
self.heap[h].set_mark_bit(self.mark_phase);
- if !(self.heap[h].is_var() && self.heap[h].get_value() as usize == h) {
+ if var_value.get_mark_bit() || !(self.heap[h].is_var() && self.heap[h].get_value() as usize == h) {
self.iter_stack.push(var_value);
continue;
}
@@ -125,12 +125,13 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> {
continue;
}
- let value = self.heap[h+1];
-
self.heap[h].set_mark_bit(self.mark_phase);
- self.heap[h+1].set_mark_bit(self.mark_phase);
- self.iter_stack.push(value);
+ if self.heap[h].get_tag() == HeapCellValueTag::PStr {
+ let value = self.heap[h+1];
+ self.heap[h+1].set_mark_bit(self.mark_phase);
+ self.iter_stack.push(value);
+ }
}
_ => {
}
@@ -685,6 +686,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "it takes too long to run")]
fn heap_stackless_iter_tests() {
let mut wam = MockWAM::new();
@@ -1756,6 +1758,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on atom_table.rs UB")]
fn heap_stackful_iter_tests() {
let mut wam = MockWAM::new();
@@ -2348,6 +2351,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on atom_table.rs UB")]
fn heap_stackful_post_order_iter() {
let mut wam = MockWAM::new();
@@ -2831,6 +2835,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on atom_table.rs UB")]
fn heap_stackless_post_order_iter() {
let mut wam = MockWAM::new();
diff --git a/src/heap_print.rs b/src/heap_print.rs
index 14ee274d..515ebef6 100644
--- a/src/heap_print.rs
+++ b/src/heap_print.rs
@@ -1444,7 +1444,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
}
}
- #[allow(dead_code)]
fn print_tcp_listener(&mut self, tcp_listener: &TcpListener, max_depth: usize) {
let (ip, port) = if let Ok(addr) = tcp_listener.local_addr() {
(addr.ip(), addr.port())
@@ -1727,6 +1726,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
(ArenaHeaderTag::Stream, stream) => {
self.print_stream(stream, max_depth);
}
+ (ArenaHeaderTag::TcpListener, listener) => {
+ self.print_tcp_listener(&*listener, max_depth);
+ }
(ArenaHeaderTag::Dropped, _value) => {
self.print_impromptu_atom(atom!("$dropped_value"));
}
@@ -1833,6 +1835,7 @@ mod tests {
use crate::machine::mock_wam::*;
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn term_printing_tests() {
let mut wam = MockWAM::new();
diff --git a/src/lib/atts.pl b/src/lib/atts.pl
index d6ee47a3..f251b57d 100644
--- a/src/lib/atts.pl
+++ b/src/lib/atts.pl
@@ -1,8 +1,8 @@
:- module(atts, [op(1199, fx, attribute),
- call_residue_vars/2,
term_attributed_variables/2]).
:- use_module(library(dcgs)).
+:- use_module(library(error)).
:- use_module(library(terms)).
/* represent the list of attributes belonging to a variable,
@@ -110,12 +110,5 @@ user:goal_expansion(Term, M:get_atts(Var, Attr)) :-
nonvar(Term),
Term = get_atts(Var, M, Attr).
-:- meta_predicate call_residue_vars(0, ?).
-
-call_residue_vars(Goal, Vars) :-
- '$get_attr_var_queue_delim'(B),
- call(Goal),
- '$get_attr_var_queue_beyond'(B, Vars).
-
term_attributed_variables(Term, Vars) :-
'$term_attributed_variables'(Term, Vars).
diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl
index 9cb533d1..b24244d6 100644
--- a/src/lib/builtins.pl
+++ b/src/lib/builtins.pl
@@ -1239,7 +1239,10 @@ call_retract_helper(Head, Body, P, Module) :-
; ClauseQualifier = Module
),
ClauseQualifier:'$clause'(Head, Body),
- '$get_clause_p'(Head, P, Module).
+ % ensure '$get_clause_p'/3 is not the last clause so it can
+ % recover the choice point of '$clause' if necessary.
+ '$get_clause_p'(Head, P, Module),
+ true.
call_retract(Head, Body, Name, Arity, Module) :-
findall(P, builtins:call_retract_helper(Head, Body, P, Module), Ps),
diff --git a/src/lib/clpb.pl b/src/lib/clpb.pl
index 4dde600b..a20694d0 100644
--- a/src/lib/clpb.pl
+++ b/src/lib/clpb.pl
@@ -189,18 +189,18 @@ A _Boolean expression_ is one of:
| `1` | true |
| _variable_ | unknown truth value |
| _atom_ | universally quantified variable |
-| ~ _Expr_ | logical NOT |
-| _Expr_ + _Expr_ | logical OR |
-| _Expr_ * _Expr_ | logical AND |
-| _Expr_ # _Expr_ | exclusive OR |
-| _Var_ ^ _Expr_ | existential quantification |
-| _Expr_ =:= _Expr_ | equality |
-| _Expr_ =\= _Expr_ | disequality (same as #) |
-| _Expr_ =< _Expr_ | less or equal (implication) |
-| _Expr_ >= _Expr_ | greater or equal |
-| _Expr_ < _Expr_ | less than |
-| _Expr_ > _Expr_ | greater than |
-| card(Is,Exprs) | cardinality constraint (_see below_) |
+| `~` _Expr_ | logical NOT |
+| _Expr_ `+` _Expr_ | logical OR |
+| _Expr_ `*` _Expr_ | logical AND |
+| _Expr_ `#` _Expr_ | exclusive OR |
+| _Var_ `^` _Expr_ | existential quantification |
+| _Expr_ `=:=` _Expr_ | equality |
+| _Expr_ `=\=` _Expr_ | disequality (same as #) |
+| _Expr_ `=<` _Expr_ | less or equal (implication) |
+| _Expr_ `>=` _Expr_ | greater or equal |
+| _Expr_ `<` _Expr_ | less than |
+| _Expr_ `>` _Expr_ | greater than |
+| `card(Is,Exprs)` | cardinality constraint (_see below_) |
| `+(Exprs)` | n-fold disjunction (_see below_) |
| `*(Exprs)` | n-fold conjunction (_see below_) |
@@ -1251,7 +1251,7 @@ bdd_restriction_(Node, VI, Value, Res) -->
node_id(Node, ID) },
( { I0 =:= VI } ->
( { Value =:= 0 } -> { Res = Low }
- ; { Value =:= 1 } -> { Res = High }
+ ; { Res = High }
)
; { I0 > VI } -> { Res = Node }
; state(G0), { get_assoc(ID, G0, Res) } -> []
diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl
index 23c909e9..07768da5 100644
--- a/src/lib/clpz.pl
+++ b/src/lib/clpz.pl
@@ -3,7 +3,7 @@
Author: Markus Triska
E-mail: triska@metalevel.at
WWW: https://www.metalevel.at
- Copyright (C): 2016-2023 Markus Triska
+ Copyright (C): 2016-2024 Markus Triska
This library provides CLP(ℤ):
@@ -1015,6 +1015,9 @@ X in inf..sup.
needed to schedule the propagators!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+:- meta_predicate(duophrase(4, ?, ?)).
+:- meta_predicate(duophrase(4, ?, ?, ?, ?)).
+
duophrase(NT, As, Bs) :-
duophrase(NT, As, [], Bs, []).
@@ -1735,7 +1738,7 @@ intervals_to_domain(Is, D) :-
% _Lower_ must be an integer or the atom *inf*, which
% denotes negative infinity. _Upper_ must be an integer or
% the atom *sup*, which denotes positive infinity.
-% * Domain1 \/ Domain2
+% * Domain1 `\/` Domain2
% The union of Domain1 and Domain2.
Var in Dom :- clpz_in(Var, Dom).
@@ -2409,22 +2412,22 @@ sum_finite_domains([C|Cs], [V|Vs], Inf0, Sup0, Inf, Sup) ++>
),
sum_finite_domains(Cs, Vs, Inf2, Sup2, Inf, Sup).
-remove_dist_upper_lower([], _, _, _).
-remove_dist_upper_lower([C|Cs], [V|Vs], D1, D2) :-
- ( fd_get(V, VD, VPs) ->
+remove_dist_upper_lower([], _, _, _) --> [].
+remove_dist_upper_lower([C|Cs], [V|Vs], D1, D2) -->
+ ( { fd_get(V, VD, VPs) } ->
( C < 0 ->
- domain_supremum(VD, n(Sup)),
- L is Sup + D1//C,
- domain_remove_smaller_than(VD, L, VD1),
- domain_infimum(VD1, n(Inf)),
- G is Inf - D2//C,
- domain_remove_greater_than(VD1, G, VD2)
- ; domain_infimum(VD, n(Inf)),
- G is Inf + D1//C,
- domain_remove_greater_than(VD, G, VD1),
- domain_supremum(VD1, n(Sup)),
- L is Sup - D2//C,
- domain_remove_smaller_than(VD1, L, VD2)
+ { domain_supremum(VD, n(Sup)),
+ L is Sup + D1//C,
+ domain_remove_smaller_than(VD, L, VD1),
+ domain_infimum(VD1, n(Inf)),
+ G is Inf - D2//C,
+ domain_remove_greater_than(VD1, G, VD2) }
+ ; { domain_infimum(VD, n(Inf)),
+ G is Inf + D1//C,
+ domain_remove_greater_than(VD, G, VD1),
+ domain_supremum(VD1, n(Sup)),
+ L is Sup - D2//C,
+ domain_remove_smaller_than(VD1, L, VD2) }
),
fd_put(V, VD2, VPs)
; true
@@ -2432,16 +2435,16 @@ remove_dist_upper_lower([C|Cs], [V|Vs], D1, D2) :-
remove_dist_upper_lower(Cs, Vs, D1, D2).
-remove_dist_upper_leq([], _, _).
-remove_dist_upper_leq([C|Cs], [V|Vs], D1) :-
- ( fd_get(V, VD, VPs) ->
+remove_dist_upper_leq([], _, _) --> [].
+remove_dist_upper_leq([C|Cs], [V|Vs], D1) -->
+ ( { fd_get(V, VD, VPs) } ->
( C < 0 ->
- domain_supremum(VD, n(Sup)),
- L is Sup + D1//C,
- domain_remove_smaller_than(VD, L, VD1)
- ; domain_infimum(VD, n(Inf)),
- G is Inf + D1//C,
- domain_remove_greater_than(VD, G, VD1)
+ { domain_supremum(VD, n(Sup)),
+ L is Sup + D1//C,
+ domain_remove_smaller_than(VD, L, VD1) }
+ ; { domain_infimum(VD, n(Inf)),
+ G is Inf + D1//C,
+ domain_remove_greater_than(VD, G, VD1) }
),
fd_put(V, VD1, VPs)
; true
@@ -2449,18 +2452,18 @@ remove_dist_upper_leq([C|Cs], [V|Vs], D1) :-
remove_dist_upper_leq(Cs, Vs, D1).
-remove_dist_upper([], _).
-remove_dist_upper([C*V|CVs], D) :-
- ( fd_get(V, VD, VPs) ->
+remove_dist_upper([], _) --> [].
+remove_dist_upper([C*V|CVs], D) -->
+ ( { fd_get(V, VD, VPs) } ->
( C < 0 ->
- ( domain_supremum(VD, n(Sup)) ->
- L is Sup + D//C,
- domain_remove_smaller_than(VD, L, VD1)
+ ( { domain_supremum(VD, n(Sup)) } ->
+ { L is Sup + D//C,
+ domain_remove_smaller_than(VD, L, VD1) }
; VD1 = VD
)
- ; ( domain_infimum(VD, n(Inf)) ->
- G is Inf + D//C,
- domain_remove_greater_than(VD, G, VD1)
+ ; ( { domain_infimum(VD, n(Inf)) } ->
+ { G is Inf + D//C,
+ domain_remove_greater_than(VD, G, VD1) }
; VD1 = VD
)
),
@@ -2469,18 +2472,18 @@ remove_dist_upper([C*V|CVs], D) :-
),
remove_dist_upper(CVs, D).
-remove_dist_lower([], _).
-remove_dist_lower([C*V|CVs], D) :-
- ( fd_get(V, VD, VPs) ->
+remove_dist_lower([], _) --> [].
+remove_dist_lower([C*V|CVs], D) -->
+ ( { fd_get(V, VD, VPs) } ->
( C < 0 ->
- ( domain_infimum(VD, n(Inf)) ->
- G is Inf - D//C,
- domain_remove_greater_than(VD, G, VD1)
+ ( { domain_infimum(VD, n(Inf)) } ->
+ { G is Inf - D//C,
+ domain_remove_greater_than(VD, G, VD1) }
; VD1 = VD
)
- ; ( domain_supremum(VD, n(Sup)) ->
- L is Sup - D//C,
- domain_remove_smaller_than(VD, L, VD1)
+ ; ( { domain_supremum(VD, n(Sup)) } ->
+ { L is Sup - D//C,
+ domain_remove_smaller_than(VD, L, VD1) }
; VD1 = VD
)
),
@@ -2489,26 +2492,26 @@ remove_dist_lower([C*V|CVs], D) :-
),
remove_dist_lower(CVs, D).
-remove_upper([], _).
-remove_upper([C*X|CXs], Max) :-
- ( fd_get(X, XD, XPs) ->
+remove_upper([], _) --> [].
+remove_upper([C*X|CXs], Max) -->
+ ( { fd_get(X, XD, XPs) } ->
D is Max//C,
( C < 0 ->
- domain_remove_smaller_than(XD, D, XD1)
- ; domain_remove_greater_than(XD, D, XD1)
+ { domain_remove_smaller_than(XD, D, XD1) }
+ ; { domain_remove_greater_than(XD, D, XD1) }
),
fd_put(X, XD1, XPs)
; true
),
remove_upper(CXs, Max).
-remove_lower([], _).
-remove_lower([C*X|CXs], Min) :-
- ( fd_get(X, XD, XPs) ->
+remove_lower([], _) --> [].
+remove_lower([C*X|CXs], Min) -->
+ ( { fd_get(X, XD, XPs) } ->
D is -Min//C,
( C < 0 ->
- domain_remove_greater_than(XD, D, XD1)
- ; domain_remove_smaller_than(XD, D, XD1)
+ { domain_remove_greater_than(XD, D, XD1) }
+ ; { domain_remove_smaller_than(XD, D, XD1) }
),
fd_put(X, XD1, XPs)
; true
@@ -2747,20 +2750,24 @@ propagator_init_trigger(Vs, P) :-
prop_init(Prop, V) :- init_propagator(V, Prop).
geq(A, B) :-
- ( fd_get(A, AD, APs) ->
- domain_infimum(AD, AI),
- ( fd_get(B, BD, _) ->
- domain_supremum(BD, BS),
- ( AI cis_geq BS -> true
- ; propagator_init_trigger(pgeq(A,B))
+ new_queue(Q),
+ phrase((geq(A, B),do_queue), [Q], _).
+
+geq(A, B) -->
+ ( { fd_get(A, AD, APs) } ->
+ { domain_infimum(AD, AI) },
+ ( { fd_get(B, BD, _) } ->
+ { domain_supremum(BD, BS) },
+ ( { AI cis_geq BS } -> true
+ ; { propagator_init_trigger(pgeq(A,B)) }
)
- ; ( AI cis_geq n(B) -> true
- ; domain_remove_smaller_than(AD, B, AD1),
+ ; ( { AI cis_geq n(B) } -> true
+ ; { domain_remove_smaller_than(AD, B, AD1) },
fd_put(A, AD1, APs)
)
)
- ; fd_get(B, BD, BPs) ->
- domain_remove_greater_than(BD, A, BD1),
+ ; { fd_get(B, BD, BPs) } ->
+ { domain_remove_greater_than(BD, A, BD1) },
fd_put(B, BD1, BPs)
; A >= B
).
@@ -4164,6 +4171,7 @@ var(V) --> { var(V) }.
ground(T) --> { ground(T) }.
true --> [].
+false --> { false }.
X >= Y --> { X >= Y }.
X =< Y --> { X =< Y }.
@@ -4221,10 +4229,7 @@ activate_propagator(propagator(P,State)) -->
)
).
-enable_queue :- true. % NOP
-disable_queue :- true. % NOP
-
-%do_queue --> print_queue, { false }.
+%do_queue --> print_queue, false.
do_queue -->
( queue_enabled ->
( queue_get_goal(Goal) -> { call(Goal) }, do_queue
@@ -4507,13 +4512,13 @@ run_propagator(pelement(N, Is, V), MState) -->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-run_propagator(pgcc_single(Vs, Pairs), _) --> { gcc_global(Vs, Pairs) }.
+run_propagator(pgcc_single(Vs, Pairs), _) --> gcc_global(Vs, Pairs).
-run_propagator(pgcc_check_single(Pairs), _) --> { gcc_check(Pairs) }.
+run_propagator(pgcc_check_single(Pairs), _) --> gcc_check(Pairs).
-run_propagator(pgcc_check(Pairs), _) --> { gcc_check(Pairs) }.
+run_propagator(pgcc_check(Pairs), _) --> gcc_check(Pairs).
-run_propagator(pgcc(Vs, _, Pairs), _) --> { gcc_global(Vs, Pairs) }.
+run_propagator(pgcc(Vs, _, Pairs), _) --> gcc_global(Vs, Pairs).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4588,7 +4593,7 @@ run_propagator(pserialized(S_I, D_I, S_J, D_J, _), MState) -->
kill(MState),
( S_I + D_I =< S_J -> []
; S_J + D_J =< S_I -> []
- ; { false }
+ ; false
)
; serialize_lower_upper(S_I, D_I, S_J, D_J, MState),
serialize_lower_upper(S_J, D_J, S_I, D_I, MState)
@@ -4661,7 +4666,7 @@ run_propagator(x_eq_abs_plus_v(X,V), MState) -->
( nonvar(V) ->
( V =:= 0 -> kill(MState), { X in 0..sup }
; V < 0 -> kill(MState), { X #= V / 2 }
- ; V > 0 -> { false }
+ ; false % V > 0
)
; nonvar(X) ->
kill(MState),
@@ -4753,55 +4758,55 @@ run_propagator(scalar_product_neq(Cs0,Vs0,P0), MState) -->
) }.
run_propagator(scalar_product_leq(Cs0,Vs0,P0), MState) -->
- { coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I),
- P is P0 - I,
- ( Vs = [] -> kill(MState), P >= 0
- ; duophrase(sum_finite_domains(Cs, Vs, 0, 0, Inf, Sup), Infs, Sups),
- D1 is P - Inf,
- disable_queue,
- ( Infs == [], Sups == [] ->
- Inf =< P,
- ( Sup =< P -> kill(MState)
- ; remove_dist_upper_leq(Cs, Vs, D1)
- )
- ; Infs == [] -> Inf =< P, remove_dist_upper(Sups, D1)
- ; Infs = [_] -> remove_upper(Infs, D1)
- ; true
- ),
- enable_queue
- ) }.
+ { coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I) },
+ P is P0 - I,
+ ( Vs = [] -> kill(MState), P >= 0
+ ; { duophrase(sum_finite_domains(Cs, Vs, 0, 0, Inf, Sup), Infs, Sups) },
+ D1 is P - Inf,
+ disable_queue,
+ ( Infs == [], Sups == [] ->
+ Inf =< P,
+ ( Sup =< P -> kill(MState)
+ ; remove_dist_upper_leq(Cs, Vs, D1)
+ )
+ ; Infs == [] -> Inf =< P, remove_dist_upper(Sups, D1)
+ ; Infs = [_] -> remove_upper(Infs, D1)
+ ; true
+ ),
+ enable_queue
+ ).
run_propagator(scalar_product_eq(Cs0,Vs0,P0), MState) -->
- { coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I),
- P is P0 - I,
- ( Vs = [] -> kill(MState), P =:= 0
- ; Vs = [V], Cs = [C] -> kill(MState), P mod C =:= 0, V is P // C
- ; Cs == [1,1] -> kill(MState), Vs = [A,B], A + B #= P
- ; Cs == [1,-1] -> kill(MState), Vs = [A,B], A #= P + B
- ; Cs == [-1,1] -> kill(MState), Vs = [A,B], B #= P + A
- ; Cs == [-1,-1] -> kill(MState), Vs = [A,B], P1 is -P, A + B #= P1
- ; P =:= 0, Cs == [1,1,-1] -> kill(MState), Vs = [A,B,C], A + B #= C
- ; P =:= 0, Cs == [1,-1,1] -> kill(MState), Vs = [A,B,C], A + C #= B
- ; P =:= 0, Cs == [-1,1,1] -> kill(MState), Vs = [A,B,C], B + C #= A
- ; duophrase(sum_finite_domains(Cs, Vs, 0, 0, Inf, Sup), Infs, Sups),
- % nl, writeln(Infs-Sups-Inf-Sup),
- D1 is P - Inf,
- D2 is Sup - P,
- disable_queue,
- ( Infs == [], Sups == [] ->
- between(Inf, Sup, P),
- remove_dist_upper_lower(Cs, Vs, D1, D2)
- ; Sups = [] -> P =< Sup, remove_dist_lower(Infs, D2)
- ; Infs = [] -> Inf =< P, remove_dist_upper(Sups, D1)
- ; Sups = [_], Infs = [_] ->
- remove_lower(Sups, D2),
- remove_upper(Infs, D1)
- ; Infs = [_] -> remove_upper(Infs, D1)
- ; Sups = [_] -> remove_lower(Sups, D2)
- ; true
- ),
- enable_queue
- ) }.
+ { coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I) },
+ P is P0 - I,
+ ( Vs = [] -> kill(MState), P =:= 0
+ ; Vs = [V], Cs = [C] -> kill(MState), P mod C =:= 0, V is P // C
+ ; Cs == [1,1] -> kill(MState), Vs = [A,B], { A + B #= P }
+ ; Cs == [1,-1] -> kill(MState), Vs = [A,B], { A #= P + B }
+ ; Cs == [-1,1] -> kill(MState), Vs = [A,B], { B #= P + A }
+ ; Cs == [-1,-1] -> kill(MState), Vs = [A,B], P1 is -P, { A + B #= P1 }
+ ; P =:= 0, Cs == [1,1,-1] -> kill(MState), Vs = [A,B,C], { A + B #= C }
+ ; P =:= 0, Cs == [1,-1,1] -> kill(MState), Vs = [A,B,C], { A + C #= B }
+ ; P =:= 0, Cs == [-1,1,1] -> kill(MState), Vs = [A,B,C], { B + C #= A }
+ ; { duophrase(sum_finite_domains(Cs, Vs, 0, 0, Inf, Sup), Infs, Sups) },
+ % { nl, writeln(Infs-Sups-Inf-Sup) },
+ D1 is P - Inf,
+ D2 is Sup - P,
+ disable_queue,
+ ( Infs == [], Sups == [] ->
+ { between(Inf, Sup, P) },
+ remove_dist_upper_lower(Cs, Vs, D1, D2)
+ ; Sups = [] -> P =< Sup, remove_dist_lower(Infs, D2)
+ ; Infs = [] -> Inf =< P, remove_dist_upper(Sups, D1)
+ ; Sups = [_], Infs = [_] ->
+ remove_lower(Sups, D2),
+ remove_upper(Infs, D1)
+ ; Infs = [_] -> remove_upper(Infs, D1)
+ ; Sups = [_] -> remove_lower(Sups, D2)
+ ; true
+ ),
+ enable_queue
+ ).
% X + Y = Z
run_propagator(pplus(X,Y,Z,Morph), MState) -->
@@ -5048,8 +5053,8 @@ run_propagator(ptzdiv(X,Y,Z,Morph), MState) -->
%% % Z = X mod Y
run_propagator(pmod(X,Y,Z), MState) -->
- ( Y == 0 -> { false }
- ; Y == Z -> { false }
+ ( Y == 0 -> false
+ ; Y == Z -> false
; X == Y -> kill(MState), queue_goal(Z = 0)
; true
),
@@ -5058,7 +5063,7 @@ run_propagator(pmod(X,Y,Z), MState) -->
Z is X mod Y
; nonvar(Y), nonvar(Z) ->
( Y > 0 -> Z >= 0, Z < Y
- ; Y < 0 -> Z =< 0, Z > Y
+ ; Z =< 0, Z > Y % Y < 0
),
( { fd_get(X, _, n(XL), _, _) } ->
( (XL - Z) mod Y =\= 0 ->
@@ -5127,7 +5132,7 @@ run_propagator(pmodz(X,Y,Z), MState) -->
fd_put(Z, ZD2, ZPs)
% queue_goal(Z #=< X)
)
- ; X < 0 ->
+ ; X < 0,
( { fd_get(Y, _, _, n(YU), _), YU < X } ->
kill(MState),
queue_goal(Z = X)
@@ -5167,7 +5172,7 @@ run_propagator(pmodz(X,Y,Z), MState) -->
fd_put(Z, ZD5, ZPs)
% queue_goal(Z in ZMin..0)
)
- ; Y > 0 ->
+ ; Y > 0,
( { fd_get(X, _, n(XL), n(XU), _), XL >= 0, Y > XU } ->
kill(MState),
queue_goal(Z = X)
@@ -5378,8 +5383,9 @@ run_propagator(pmax(X,Y,Z), MState) -->
; nonvar(Z) ->
( Z =:= X -> kill(MState), queue_goal(X #>= Y)
; Z > X -> queue_goal(Z = Y)
- ; { false } % Z < X
+ ; false % Z < X
)
+ ; Y == Z -> kill(MState), queue_goal(Y #>= X)
; { fd_get(Y, _, YInf, YSup, _) },
( { YInf cis_gt n(X) } -> queue_goal(Z = Y)
; { YSup cis_lt n(X) } -> queue_goal(Z = X)
@@ -5394,7 +5400,7 @@ run_propagator(pmax(X,Y,Z), MState) -->
; { fd_get(Z, ZD, ZPs) } ->
{ fd_get(X, _, XInf, XSup, _),
fd_get(Y, _, YInf, YSup, _) },
- ( { YInf cis_gt YSup } -> kill(MState), queue_goal(Z = Y)
+ ( { YInf cis_gt XSup } -> kill(MState), queue_goal(Z = Y)
; { YSup cis_lt XInf } -> kill(MState), queue_goal(Z = X)
; { n(M) cis max(XSup, YSup) } ->
{ domain_remove_greater_than(ZD, M, ZD1) },
@@ -5413,8 +5419,9 @@ run_propagator(pmin(X,Y,Z), MState) -->
; nonvar(Z) ->
( Z =:= X -> kill(MState), { X #=< Y }
; Z < X -> Z = Y
- ; { false } % Z > X
+ ; false % Z > X
)
+ ; Y == Z -> kill(MState), queue_goal(Y #=< X)
; { fd_get(Y, _, YInf, YSup, _) },
( { YSup cis_lt n(X) } -> Z = Y
; { YInf cis_gt n(X) } -> Z = X
@@ -5429,7 +5436,7 @@ run_propagator(pmin(X,Y,Z), MState) -->
; { fd_get(Z, ZD, ZPs) } ->
{ fd_get(X, _, XInf, XSup, _),
fd_get(Y, _, YInf, YSup, _) },
- ( { YSup cis_lt YInf } -> kill(MState), Z = Y
+ ( { YSup cis_lt XInf } -> kill(MState), Z = Y
; { YInf cis_gt XSup } -> kill(MState), Z = X
; { n(M) cis min(XInf, YInf) } ->
{ domain_remove_smaller_than(ZD, M, ZD1) },
@@ -5448,6 +5455,7 @@ run_propagator(pexp(X,Y,Z,Morph), MState) -->
morph_into_propagator(MState, [Y,Z], reified_eq(1,Y,1,0,[],Z), Morph)
; Y == 0 -> kill(MState), Z = 1
; Y == 1 -> kill(MState), Z = X
+ ; Y == Z -> kill(MState), X = Y, queue_goal(X in -1\/1)
; nonvar(X) ->
( nonvar(Y) ->
( Y >= 0 -> true ; X =:= -1 ),
@@ -5536,7 +5544,7 @@ run_propagator(pexp(X,Y,Z,Morph), MState) -->
fd_put(Z, ZD2, ZPs),
{ ( even(Y), ZU = n(Num) ->
integer_kth_root_leq(Num, Y, RU),
- ( XL cis_geq n(0), ZL = n(Num1) ->
+ ( XL cis_geq n(0), ZL = n(Num1), Num1 >= 0 ->
integer_kth_root_leq(Num1, Y, RL0),
( RL0^Y < Num1 -> RL is RL0 + 1
; RL = RL0
@@ -5726,8 +5734,7 @@ run_propagator(reified_fd(V,B), MState) -->
B = 1
; { B == 0 } ->
( { fd_inf(V, inf) } -> []
- ; { fd_sup(V, sup) } -> []
- ; { false }
+ ; { fd_sup(V, sup) }
)
; []
).
@@ -6788,13 +6795,20 @@ gcc_pairs([Key-Num0|KNs], Vs, [Key-Num|Rest]) :-
Constraint", AAAI-96 Portland, OR, USA, pp 209--215, 1996
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-gcc_global(Vs, KNs) :-
- gcc_check(KNs),
- % previously: call do_queue/0 (now a NOP) here to reach a
- % fix-point: all elements of clpz_gcc_vs must be variables. We
- % must ensure this holds if gcc_check/1 is later rewritten to
- % actually disable the queue.
- with_local_attributes(Vs,
+gcc_global(Vs, KNs) -->
+ % at this point, all elements of clpz_gcc_vs must be
+ % variables, which a previously scheduled and called
+ % gcc_check//1 ensures. Note that gcc_check//1 disables the
+ % queue and accumulates constraints in the queue. Do we need
+ % to insert a call of do_queue//0 here to reach a fixpoint? I
+ % think not, because verify_attributes/3 gives each variable
+ % that is involved in a unification an opportunity to schedule
+ % its propagators, even if the unifications happen
+ % simultaneously (such as [A,B] = [0,1], which can happen in
+ % the propagator of tuples_in/2). Hence: We need this only if
+ % an example shows it, ideally found by a systematic search
+ % that can be used to test the implementation.
+ { with_local_attributes(Vs,
(gcc_arcs(KNs, S, Vals),
variables_with_num_occurrences(Vs, VNs),
maplist(target_to_v(T), VNs),
@@ -6805,9 +6819,9 @@ gcc_global(Vs, KNs) :-
gcc_consistent(T),
scc(Vals, gcc_successors),
phrase(gcc_goals(Vals), Gs)
- ; Gs = [] )), Gs),
+ ; Gs = [] )), Gs) },
disable_queue,
- maplist(call, Gs),
+ neq_nums(Gs),
enable_queue.
gcc_consistent(T) :-
@@ -6834,7 +6848,7 @@ gcc_edge_goal(arc_to(_,_,V,F), Val) -->
get_attr(Val, lowlink, L2),
L1 =\= L2,
get_attr(Val, value, Value) } ->
- [clpz:neq_num(V, Value)]
+ [neq_num(V, Value)]
; []
).
@@ -7004,7 +7018,7 @@ gcc_succ_edge(arc_from(_,_,V,F)) -->
consistency.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-gcc_check(Pairs) :-
+gcc_check(Pairs) -->
disable_queue,
gcc_check_(Pairs),
enable_queue.
@@ -7014,36 +7028,36 @@ gcc_done(Num) :-
del_attr(Num, clpz_gcc_num),
del_attr(Num, clpz_gcc_occurred).
-gcc_check_([]).
-gcc_check_([Key-Num0|KNs]) :-
- ( get_attr(Num0, clpz_gcc_vs, Vs) ->
- get_attr(Num0, clpz_gcc_num, Num),
- get_attr(Num0, clpz_gcc_occurred, Occ0),
- vs_key_min_others(Vs, Key, 0, Min, Os),
- put_attr(Num0, clpz_gcc_vs, Os),
- put_attr(Num0, clpz_gcc_occurred, Occ1),
- Occ1 is Occ0 + Min,
+gcc_check_([]) --> [].
+gcc_check_([Key-Num0|KNs]) -->
+ ( { get_attr(Num0, clpz_gcc_vs, Vs) } ->
+ { get_attr(Num0, clpz_gcc_num, Num),
+ get_attr(Num0, clpz_gcc_occurred, Occ0),
+ vs_key_min_others(Vs, Key, 0, Min, Os),
+ put_attr(Num0, clpz_gcc_vs, Os),
+ put_attr(Num0, clpz_gcc_occurred, Occ1),
+ Occ1 is Occ0 + Min },
geq(Num, Occ1),
% The queue is disabled for efficiency here in any case.
% If it were enabled, make sure to retain the invariant
% that gcc_global is never triggered during an
% inconsistent state (after gcc_done/1 but before all
% relevant constraints are posted).
- ( Occ1 == Num -> all_neq(Os, Key), gcc_done(Num0)
- ; Os == [] -> gcc_done(Num0), Num = Occ1
- ; length(Os, L),
- Max is Occ1 + L,
+ ( Occ1 == Num -> all_neq(Os, Key), { gcc_done(Num0) }
+ ; Os == [] -> { gcc_done(Num0) }, Num = Occ1
+ ; { length(Os, L),
+ Max is Occ1 + L },
geq(Max, Num),
- ( nonvar(Num) -> Diff is Num - Occ1
- ; fd_get(Num, ND, _),
- domain_infimum(ND, n(NInf)),
+ ( { nonvar(Num) } -> Diff is Num - Occ1
+ ; { fd_get(Num, ND, _),
+ domain_infimum(ND, n(NInf)) },
Diff is NInf - Occ1
),
L >= Diff,
( L =:= Diff ->
Num is Occ1 + Diff,
- maplist(=(Key), Os),
- gcc_done(Num0)
+ { maplist(=(Key), Os),
+ gcc_done(Num0) }
; true
)
)
diff --git a/src/lib/crypto.pl b/src/lib/crypto.pl
index bec12d51..bcd2bb9d 100644
--- a/src/lib/crypto.pl
+++ b/src/lib/crypto.pl
@@ -25,6 +25,7 @@
crypto_password_hash/3, % +Password, -Hash, +Options
crypto_data_encrypt/6, % +PlainText, +Algorithm, +Key, +IV, -CipherText, +Options
crypto_data_decrypt/6, % +CipherText, +Algorithm, +Key, +IV, -PlainText, +Options
+ ed25519_seed_keypair/2, % +Seed, -KeyPair
ed25519_new_keypair/1, % -KeyPair
ed25519_keypair_public_key/2, % +KeyPair, +PublicKey
ed25519_sign/4, % +KeyPair, +Data, -Signature, +Options
@@ -612,6 +613,50 @@ encoding_chars(utf8, Cs, Cs) :-
===============================
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+%% ed25519_seed_keypair(+Seed, -Pair)
+%
+% Use Seed to deterministically generate an Ed25519 key pair Pair, a
+% list of characters. Seed must be a list of 32 bytes. It can be
+% chosen at random (using for example `crypto_n_random_bytes/2`) or
+% derived from input keying material (IKM) using for example
+% `crypto_data_hkdf/4`. The pair contains the private key and must be
+% kept absolutely secret. Pair can be used for signing. Its public
+% key can be obtained with `ed25519_keypair_public_key/2`.
+
+ed25519_seed_keypair(Seed, Pair) :-
+ must_be_bytes(Seed, ed25519_keypair_from_seed/2),
+ length(Seed, 32),
+ '$ed25519_seed_to_public_key'(Seed, Public),
+ maplist(char_code, Public, PublicBytes),
+ phrase(ed25519_PKCS8v2(Seed,PublicBytes), DERs),
+ maplist(char_code, Pair, DERs).
+
+% DER (and hence BER) encoding of an Ed25519 private key and
+% corresponding public key in PKCS#8v2 format (RFC 5958) as specified
+% in RFC 8410.
+
+ed25519_PKCS8v2(Seed, PublicBytes) -->
+ [0x30,81], % a SEQUENCE of 81 bytes follows
+
+ % the publicKey is present, hence we set version to v2
+ [2,1,1], % the integer 1 denoting version 2 (awesome design!)
+
+ % privateKeyAlgorithm: SEQUENCE
+ [0x30,5], % a SEQUENCE of 5 bytes follows
+ [6,3], % an OBJECT IDENTIFIER of 3 bytes follows
+ [43,101,112], % OID of Ed25519
+
+ % privateKey: OCTET STRING
+ [4,34], % an OCTET STRING of 34 bytes follows
+ [4,32], % an OCTET STRING of 32 bytes follows
+ seq(Seed), % the seed is the private key
+
+ % publicKey: [1] IMPLICIT BIT STRING; context-specific, hence bit 7 set
+ [0b10000001], % the public key follows
+ [33], % a BIT STRING of length 33 follows
+ [0], % 32 bytes is divisible by 8, hence 0 unused bits
+ seq(PublicBytes).
+
%% ed25519_new_keypair(-Pair)
%
% Yields a new Ed25519 key pair Pair, a list of characters. The
@@ -620,7 +665,8 @@ encoding_chars(utf8, Cs, Cs) :-
% with `ed25519_keypair_public_key/2`.
ed25519_new_keypair(Pair) :-
- '$ed25519_new_keypair'(Pair).
+ crypto_n_random_bytes(32, Bytes),
+ ed25519_seed_keypair(Bytes, Pair).
%% ed25519_keypair_public_key(+Pair, -PublicKey)
%
@@ -629,8 +675,11 @@ ed25519_new_keypair(Pair) :-
% The public key is represented as a list of characters.
ed25519_keypair_public_key(Pair, PublicKey) :-
- must_be_octet_chars(Pair, ed25519_keypair_public_key),
- '$ed25519_keypair_public_key'(Pair, PublicKey).
+ must_be_octet_chars(Pair, ed25519_keypair_public_key/2),
+ reverse(Pair, RPs),
+ length(RPublicKey, 32),
+ phrase((seq(RPublicKey),...), RPs),
+ reverse(RPublicKey, PublicKey).
%% ed25519_sign(+Key, +Data, -Signature, +Options)
%
@@ -638,10 +687,14 @@ ed25519_keypair_public_key(Pair, PublicKey) :-
% PKCS#8 v2 format as generated by `ed25519_new_keypair/1`. Sign Data
% with Key, yielding Signature as a list of hexadecimal characters.
-ed25519_sign(Key, Data0, Signature, Options) :-
- must_be_octet_chars(Key, ed25519_sign),
+ed25519_sign(KeyPair, Data0, Signature, Options) :-
+ must_be_octet_chars(KeyPair, ed25519_sign/4),
+ length(Prefix, 16),
+ length(PrivateKeyChars, 32),
+ phrase((seq(Prefix),seq(PrivateKeyChars),...), KeyPair),
+ maplist(char_code, PrivateKeyChars, PrivateKey),
options_data_chars(Options, Data0, Data, Encoding),
- '$ed25519_sign'(Key, Data, Encoding, Signature0),
+ '$ed25519_sign_raw'(PrivateKey, Data, Encoding, Signature0),
hex_bytes(Signature, Signature0).
%% ed25519_verify(+Key, +Data, +Signature, +Options)
@@ -658,10 +711,10 @@ ed25519_sign(Key, Data0, Signature, Options) :-
% which treats Data as a list of raw bytes.
ed25519_verify(Key, Data0, Signature0, Options) :-
- must_be_octet_chars(Key, ed25519_verify),
+ must_be_octet_chars(Key, ed25519_verify/4),
options_data_chars(Options, Data0, Data, Encoding),
hex_bytes(Signature0, Signature),
- '$ed25519_verify'(Key, Data, Encoding, Signature).
+ '$ed25519_verify_raw'(Key, Data, Encoding, Signature).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
X25519: ECDH key exchange over Curve25519
diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl
index 1767d2bb..4ee763f0 100644
--- a/src/lib/dcgs.pl
+++ b/src/lib/dcgs.pl
@@ -12,9 +12,12 @@ to learn more about them.
[op(1105, xfy, '|'),
phrase/2,
phrase/3,
+ phrase/4,
+ phrase/5,
seq//1,
seqq//1,
- ... //0
+ ... //0,
+ (-->)/2
]).
:- use_module(library(error)).
@@ -26,6 +29,10 @@ to learn more about them.
:- meta_predicate phrase(2, ?, ?).
+:- meta_predicate phrase(2, ?, ?, ?).
+
+:- meta_predicate phrase(2, ?, ?, ?, ?).
+
%% phrase(+Body, ?Ls).
%
% True iff Body describes the list Ls. Body must be a DCG body.
@@ -75,6 +82,34 @@ phrase(GRBody, S0, S) :-
; call(M:GRBody1, S0, S)
).
+phrase(GRBody, Arg, S0, S) :-
+ strip_module(GRBody, M, GRBody1),
+ ( var(GRBody) ->
+ instantiation_error(phrase/4)
+ ; nonvar(GRBody1),
+ GRBody1 =.. GRBodys1,
+ append(GRBodys1, [Arg], GRBodys2),
+ GRBody2 =.. GRBodys2,
+ dcg_constr(GRBody2),
+ dcg_body(GRBody2, S0, S, GRBody3) ->
+ call(M:GRBody3)
+ ; call(M:GRBody1, Arg, S0, S)
+ ).
+
+phrase(GRBody, Arg1, Arg2, S0, S) :-
+ strip_module(GRBody, M, GRBody1),
+ ( var(GRBody) ->
+ instantiation_error(phrase/5)
+ ; nonvar(GRBody1),
+ GRBody1 =.. GRBodys1,
+ append(GRBodys1, [Arg1,Arg2], GRBodys2),
+ GRBody2 =.. GRBodys2,
+ dcg_constr(GRBody2),
+ dcg_body(GRBody2, S0, S, GRBody3) ->
+ call(M:GRBody3)
+ ; call(M:GRBody1, Arg1, Arg2, S0, S)
+ ).
+
% The same version of the below two dcg_rule clauses, but with module scoping.
dcg_rule(( M:NonTerminal, Terminals --> GRBody ), ( M:Head :- Body )) :-
dcg_non_terminal(NonTerminal, S0, S, Head),
@@ -101,7 +136,10 @@ dcg_rule(( NonTerminal --> GRBody ), ( Head :- Body )) :-
dcg_non_terminal(NonTerminal, S0, S, Goal) :-
NonTerminal =.. NonTerminalUniv,
append(NonTerminalUniv, [S0, S], GoalUniv),
- Goal =.. GoalUniv.
+ ( callable(NonTerminal) ->
+ Goal =.. GoalUniv
+ ; Goal = NonTerminal % let call/N throw an error instead of throwing one here.
+ ).
dcg_terminals(Terminals, S0, S, S0 = List) :-
append(Terminals, S, List).
@@ -116,8 +154,6 @@ dcg_body(GRBody, S0, S, Body) :-
dcg_body(NonTerminal, S0, S, Goal1) :-
nonvar(NonTerminal),
\+ dcg_constr(NonTerminal),
- NonTerminal \= ( _ -> _ ),
- NonTerminal \= ( \+ _ ),
loader:strip_module(NonTerminal, M, NonTerminal0),
dcg_non_terminal(NonTerminal0, S0, S, Goal0),
( functor(NonTerminal, (:), 2) ->
@@ -135,9 +171,13 @@ dcg_constr(( _'|'_ )). % 7.14.6 - alternative
dcg_constr({_}). % 7.14.7
dcg_constr(call(_)). % 7.14.8
dcg_constr(phrase(_)). % 7.14.9
+dcg_constr(phrase(_,_)). % extension of 7.14.9
+dcg_constr(phrase(_,_,_)). % extension of 7.14.9
dcg_constr(!). % 7.14.10
-%% dcg_constr(\+ _). % 7.14.11 - not (existence implementation dep.)
-dcg_constr((_->_)). % 7.14.12 - if-then (existence implementation dep.)
+dcg_constr(\+ G_0) :- % 7.14.11 - not (existence implementation def.)
+ throw(error(representation_error(dcg_body), [culprit- (\+ G_0)])).
+dcg_constr((If->Then)) :- % 7.14.12 - if-then (existence implementation def.)
+ throw(error(representation_error(dcg_body), [culprit- (If->Then)])).
% The principal functor of the first argument indicates
% the construct to be expanded.
@@ -162,8 +202,10 @@ dcg_cbody(( GREither '|' GROr ), S0, S, ( Either ; Or )) :-
dcg_cbody({Goal}, S0, S, ( Goal, S0 = S )).
dcg_cbody(call(Cont), S0, S, call(Cont, S0, S)).
dcg_cbody(phrase(Body), S0, S, phrase(Body, S0, S)).
+dcg_cbody(phrase(Body, Arg), S0, S, phrase(Body, Arg, S0, S)).
+dcg_cbody(phrase(Body, Arg1, Arg2), S0, S, phrase(Body, Arg1, Arg2, S0, S)).
dcg_cbody(!, S0, S, ( !, S0 = S )).
-dcg_cbody(\+ GRBody, S0, S, ( \+ phrase(GRBody,S0,_), S0 = S )).
+% dcg_cbody(\+ GRBody, S0, S, ( \+ phrase(GRBody,S0,_), S0 = S )).
dcg_cbody(( GRIf -> GRThen ), S0, S, ( If -> Then )) :-
dcg_body(GRIf, S0, S1, If),
dcg_body(GRThen, S1, S, Then).
@@ -202,6 +244,8 @@ seqq([Es|Ess]) --> seq(Es), seqq(Ess).
error_goal(error(E, must_be/2), error(E, must_be/2)).
error_goal(error(E, (=..)/2), error(E, (=..)/2)).
+error_goal(error(representation_error(dcg_body), Context),
+ error(representation_error(dcg_body), Context)).
error_goal(E, _) :- throw(E).
user:goal_expansion(phrase(GRBody, S, S0), GRBody2) :-
@@ -217,3 +261,10 @@ user:goal_expansion(phrase(GRBody, S, S0), GRBody2) :-
).
user:goal_expansion(phrase(GRBody, S), phrase(GRBody, S, [])).
+
+
+% (-->)/2 behaves as if it didn't exist. We export (and define) it
+% only so that clauses for (-->)/2 cannot be asserted when
+% library(dcgs) is loaded.
+
+(_-->_) :- throw(error(existence_error(procedure,(-->)/2),(-->)/2)).
diff --git a/src/lib/files.pl b/src/lib/files.pl
index 6d89eaad..6c50aeeb 100644
--- a/src/lib/files.pl
+++ b/src/lib/files.pl
@@ -178,7 +178,7 @@ directory_must_exist(Directory, Context) :-
; throw(error(existence_error(directory, Directory), Context))
).
-%% workind_directory(Dir0, Dir).
+%% working_directory(Dir0, Dir).
%
% Dir0 is the current working directory, and the working directory
% is changed to Dir.
diff --git a/src/lib/format.pl b/src/lib/format.pl
index 9280156f..3b3d1dc4 100644
--- a/src/lib/format.pl
+++ b/src/lib/format.pl
@@ -1,5 +1,5 @@
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Written 2020-2023 by Markus Triska (triska@metalevel.at)
+ Written 2020-2024 by Markus Triska (triska@metalevel.at)
Part of Scryer Prolog.
I place this code in the public domain. Use it in any way you want.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -302,14 +302,14 @@ format_number_chars(N0, Chars) :-
N is N0, % evaluate compound expression
number_chars(N, Chars).
-n_newlines(0) --> !.
n_newlines(N0) --> { N0 > 0, N is N0 - 1 }, [newline], n_newlines(N).
+n_newlines(0) --> [].
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-?- phrase(upto_what(Cs, ~), "abc~test", Rest).
-Cs = [a,b,c], Rest = [~,t,e,s,t].
-?- phrase(upto_what(Cs, ~), "abc", Rest).
-Cs = [a,b,c], Rest = [].
+?- phrase(format:upto_what(Cs, ~), "abc~test", Rest).
+ Cs = "abc", Rest = "~test".
+?- phrase(format:upto_what(Cs, ~), "abc", Rest).
+ Cs = "abc", Rest = [].
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
separate_digits_fractional(Arg, Sep, Num, Cs) :-
@@ -444,9 +444,9 @@ format(Stream, Fs, Args) :-
?- phrase(format:cells("~`at~50|", [], 0, [], []), Cs),
phrase(format:format_cells(Cs), Ls).
?- phrase(format:cells("~ta~t~tb~tc~21|", [], 0, [], []), Cs).
-Cs = [cell(0,21,[glue(' ',_A),chars("a"),glue(' ',_B),glue(' ',_C),chars("b"),glue(' ',_D),chars("c ...")])]
+ Cs = [cell(0,21,[glue(' ',_A),chars("a"),glue(' ',_B),glue(' ',_C),chars("b"),glue(' ',_D),chars("c")])].
?- phrase(format:cells("~ta~t~4|", [], 0, [], []), Cs).
-Cs = [cell(0,4,[glue(' ',_A),chars("a"),glue(' ',_B)])]
+ Cs = [cell(0,4,[glue(' ',_A),chars("a"),glue(' ',_B)])].
?- phrase(format:format_cell(cell(0,1,[glue(a,_94)])), Ls).
diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl
index 15c05fd2..3eb00a3e 100644
--- a/src/lib/iso_ext.pl
+++ b/src/lib/iso_ext.pl
@@ -9,6 +9,7 @@ but they're not part of the ISO Prolog standard at the moment.
bb_put/2,
call_cleanup/2,
call_with_inference_limit/3,
+ call_residue_vars/2,
forall/2,
partial_string/1,
partial_string/3,
@@ -17,7 +18,8 @@ but they're not part of the ISO Prolog standard at the moment.
succ/2,
call_nth/2,
countall/2,
- copy_term_nat/2]).
+ copy_term_nat/2,
+ copy_term/3]).
:- use_module(library(error), [can_be/2,
domain_error/3,
@@ -26,6 +28,8 @@ but they're not part of the ISO Prolog standard at the moment.
:- use_module(library(lists), [maplist/3]).
+:- use_module(library('$project_atts')).
+
:- meta_predicate(forall(0, 0)).
%% forall(Generate, Test).
@@ -382,3 +386,23 @@ countall(Goal, N) :-
copy_term_nat(Source, Dest) :-
'$copy_term_without_attr_vars'(Source, Dest).
+%% copy_term(+Term, -Copy, -Gs).
+%
+% Produce a deep copy of Term and unify it to Copy, without attributes.
+% Unify Gs with a list of goals that represent the attributes of Term.
+% Similar to `copy_term/2` but splitting the attributes.
+copy_term(Term, Copy, Gs) :-
+ can_be(list, Gs),
+ findall(Term-Rs, '$project_atts':term_residual_goals(Term,Rs), [Copy-Gs]),
+ ( var(Gs) ->
+ Gs = []
+ ; true
+ ).
+
+:- meta_predicate call_residue_vars(0, ?).
+
+call_residue_vars(Goal, Vars) :-
+ can_be(list, Vars),
+ '$get_attr_var_queue_delim'(B),
+ call(Goal),
+ '$get_attr_var_queue_beyond'(B, Vars).
diff --git a/src/lib/os.pl b/src/lib/os.pl
index 5d31b5ce..aa955e9b 100644
--- a/src/lib/os.pl
+++ b/src/lib/os.pl
@@ -23,7 +23,9 @@ finding out the PID of the running system.
unsetenv/1,
shell/1,
shell/2,
- pid/1]).
+ pid/1,
+ raw_argv/1,
+ argv/1]).
:- use_module(library(error)).
:- use_module(library(charsio)).
@@ -110,3 +112,34 @@ permitted('_').
must_be_chars(Cs) :-
must_be(list, Cs),
maplist(must_be(character), Cs).
+
+%% raw_argv(-Argv)
+%
+% True iff Argv is the list of arguments that this program was started with (usually passed via command line).
+% In contrast to `argv/1`, this version includes every argument, without any postprocessing, just as the operating
+% system reports it to the system. This includes-flags of Scryer itself, which are not needed in general.
+raw_argv(Argv) :-
+ can_be(list, Argv),
+ '$argv'(Argv).
+
+%% argv(-Argv)
+%
+% True if Argv is the list of arguments that this program was started with (usually passed via command line).
+% In this version, only arguments specific to the program are passed. To differentiate between the system
+% arguments and the program arguments, we use `--` as a separator.
+%
+% Example:
+%
+% ```
+% % Call with scryer-prolog -f -- -t hello
+% ?- argv(X).
+% X = ["-t", "hello"].
+% ```
+argv(Argv) :-
+ can_be(list, Argv),
+ '$argv'(Argv0),
+ ( append(_, ["--"|Argv1], Argv0) ->
+ Argv = Argv1
+ ;
+ Argv = []
+ ).
diff --git a/src/lib/si.pl b/src/lib/si.pl
index ac28b43c..0e29c190 100644
--- a/src/lib/si.pl
+++ b/src/lib/si.pl
@@ -39,7 +39,8 @@
character_si/1,
term_si/1,
chars_si/1,
- dif_si/2]).
+ dif_si/2,
+ when_si/2]).
:- use_module(library(lists)).
@@ -98,3 +99,31 @@ dif_si(X, Y) :-
( X \= Y -> true
; throw(error(instantiation_error,dif_si/2))
).
+
+:- meta_predicate(when_si(+, 0)).
+
+%% when_si(Condition, Goal).
+%
+% Executes Goal when Condition becomes true. Throws an instantiation error if
+% it can't decide.
+when_si(Condition, Goal) :-
+ % Taken from https://stackoverflow.com/a/40449516
+ ( when_condition_si(Condition) ->
+ ( Condition ->
+ Goal
+ ; throw(error(instantiation_error,when_si/2))
+ )
+ ; throw(error(domain_error(when_condition_si, Condition),_))
+ ).
+
+when_condition_si(Cond) :-
+ var(Cond), !, throw(error(instantiation_error,when_condition_si/2)).
+when_condition_si(ground(_)).
+when_condition_si(nonvar(_)).
+when_condition_si((A, B)) :-
+ when_condition_si(A),
+ when_condition_si(B).
+when_condition_si((A ; B)) :-
+ when_condition_si(A),
+ when_condition_si(B).
+
diff --git a/src/lib/when.pl b/src/lib/when.pl
new file mode 100644
index 00000000..56734057
--- /dev/null
+++ b/src/lib/when.pl
@@ -0,0 +1,106 @@
+/**
+Provides the predicate `when/2`.
+*/
+
+:- module(when, [when/2]).
+
+:- use_module(library(atts)).
+:- use_module(library(dcgs)).
+:- use_module(library(lists)).
+:- use_module(library(lambda)).
+
+:- use_module(library(format)).
+:- use_module(library(debug)).
+
+:- attribute when_list/1.
+
+:- meta_predicate(when(+, 0)).
+
+%% when(Condition, Goal).
+%
+% Executes Goal when Condition becomes true.
+when(Condition, Goal) :-
+ ( when_condition(Condition) ->
+ ( Condition ->
+ Goal
+ ; term_variables(Condition, Vars),
+ maplist(
+ [Goal, Condition]+\Var^(
+ get_atts(Var, when_list(Whens0)) ->
+ Whens = [when(Condition, Goal) | Whens0],
+ put_atts(Var, when_list(Whens))
+ ; put_atts(Var, when_list([when(Condition, Goal)]))
+ ),
+ Vars
+ )
+ )
+ ; throw(error(domain_error(when_condition, Condition),_))
+ ).
+
+when_condition(Cond) :-
+ % Should this be delayed?
+ var(Cond), !, throw(error(instantiation_error,when_condition/1)).
+when_condition(ground(_)).
+when_condition(nonvar(_)).
+when_condition((A, B)) :-
+ when_condition(A),
+ when_condition(B).
+when_condition((A ; B)) :-
+ when_condition(A),
+ when_condition(B).
+
+remove_goal([], _, []).
+remove_goal([G0|G0s], Goal, Goals) :-
+ ( G0 == Goal ->
+ remove_goal(G0s, Goal, Goals)
+ ; Goals = [G0|Goals1],
+ remove_goal(G0s, Goal, Goals1)
+ ).
+
+vars_remove_goal(Vars, Goal) :-
+ maplist(
+ Goal+\Var^(
+ get_atts(Var, when_list(Whens0)) ->
+ remove_goal(Whens0, Goal, Whens),
+ ( Whens = [] ->
+ put_atts(Var, -when_list(_))
+ ; put_atts(Var, when_list(Whens))
+ )
+ ; true
+ ),
+ Vars
+ ).
+
+reinforce_goal(Goal0, Goal) :-
+ Goal = (
+ term_variables(Goal0, Vars),
+ when:vars_remove_goal(Vars, Goal0),
+ Goal0
+ ).
+
+verify_attributes(Var, Value, Goals) :-
+ ( get_atts(Var, when_list(Whens)) ->
+ ( var(Value) ->
+ ( get_atts(Value, when_list(WhensValue)) ->
+ append(Whens, WhensValue, WhensNew),
+ put_atts(Value, when_list(WhensNew))
+ ; put_atts(Value, when_list(Whens))
+ ),
+ Goals = []
+ ; maplist(reinforce_goal, Whens, Goals)
+ )
+ ; Goals = []
+ ).
+
+gather_when_goals([], _) --> [].
+gather_when_goals([When|Whens], Var) -->
+ ( { term_variables(When, [V0|_]), Var == V0 } ->
+ [when:When]
+ ; []
+ ),
+ gather_when_goals(Whens, Var).
+
+attribute_goals(Var) -->
+ { get_atts(Var, when_list(Whens)) },
+ gather_when_goals(Whens, Var),
+ { put_atts(Var, -when_list(_)) }.
diff --git a/src/loader.pl b/src/loader.pl
index d1b718b0..c282301c 100644
--- a/src/loader.pl
+++ b/src/loader.pl
@@ -112,7 +112,7 @@ success_or_warning(Goal) :-
( call(Goal) ->
true
; %% initialization goals can fail without thwarting the load.
- write('Warning: initialization/1 failed for: '),
+ write('% Warning: initialization/1 failed for: '),
writeq(Goal),
nl
).
@@ -138,7 +138,7 @@ file_load_cleanup(Evacuable, Error) :-
load_context(Module),
abolish(Module:'$initialization_goals'/1),
unload_evacuable(Evacuable),
- ( clause('$toplevel':argv(_), _) ->
+ ( clause('$toplevel':started, _) ->
% let the toplevel call loader:write_error/1
throw(Error)
; '$print_message_and_fail'(Error)
@@ -188,7 +188,7 @@ warn_about_singletons([], _).
warn_about_singletons([Singleton|Singletons], LinesRead) :-
( filter_anonymous_vars([Singleton|Singletons], VarEqs),
VarEqs \== [] ->
- write('Warning: singleton variables '),
+ write('% Warning: singleton variables '),
print_comma_separated_list(VarEqs),
write(' at line '),
write(LinesRead),
@@ -231,14 +231,17 @@ complete_partial_goal(N, HeadArg, InnerHeadArgs, SuppArgs, CompleteHeadArg) :-
integer(N),
N >= 0,
HeadArg =.. [Functor | InnerHeadArgs],
- % the next two lines are equivalent to length(SuppArgs, N) but
- % avoid length/2 so that copy_term/3 (which is invoked by
- % length/2) can be bootstrapped without self-reference.
- functor(SuppArgsFunctor, '.', N),
- SuppArgsFunctor =.. [_ | SuppArgs],
- % length(SuppArgs, N),
- append(InnerHeadArgs, SuppArgs, InnerHeadArgs0),
- CompleteHeadArg =.. [Functor | InnerHeadArgs0].
+ ( callable(Functor) ->
+ % the next two lines are equivalent to length(SuppArgs, N) but
+ % avoid length/2 so that copy_term/3 (which is invoked by
+ % length/2) can be bootstrapped without self-reference.
+ functor(SuppArgsFunctor, '.', N),
+ SuppArgsFunctor =.. [_ | SuppArgs],
+ % length(SuppArgs, N),
+ append(InnerHeadArgs, SuppArgs, InnerHeadArgs0),
+ CompleteHeadArg =.. [Functor | InnerHeadArgs0]
+ ; type_error(callable, Functor, _)
+ ).
inner_meta_specs(0, HeadArg, InnerHeadArgs, InnerMetaSpecs) :-
!,
@@ -283,7 +286,7 @@ module_expanded_head_variables(Head, HeadVars) :-
print_goal_expansion_warning(Pred) :-
nl,
- write('Warning: clause body goal expansion failed because '),
+ write('% Warning: clause body goal expansion failed because '),
writeq(Pred),
write(' is not callable.'),
nl.
@@ -296,7 +299,7 @@ expand_term_goals(Terms0, Terms) :-
( atom(Module) ->
prolog_load_context(module, Target),
module_expanded_head_variables(Head2, HeadVars),
- catch(expand_goal(Body0, Target, Body1, HeadVars),
+ catch(expand_goal(Body0, Target, Body1, HeadVars, []),
error(type_error(callable, Pred), _),
( loader:print_goal_expansion_warning(Pred),
builtins:(Body1 = Body0)
@@ -306,7 +309,7 @@ expand_term_goals(Terms0, Terms) :-
)
; module_expanded_head_variables(Head1, HeadVars),
prolog_load_context(module, Target),
- catch(expand_goal(Body0, Target, Body1, HeadVars),
+ catch(expand_goal(Body0, Target, Body1, HeadVars, []),
error(type_error(callable, Pred), _),
( loader:print_goal_expansion_warning(Pred),
builtins:(Body1 = Body0)
@@ -726,9 +729,9 @@ subgoal_expansion(Goal, Module, ExpandedGoal) :-
).
-:- non_counted_backtracking expand_subgoal/5.
+:- non_counted_backtracking expand_subgoal/6.
-expand_subgoal(UnexpandedGoals, MS, M, ExpandedGoals, HeadVars) :-
+expand_subgoal(UnexpandedGoals, MS, M, ExpandedGoals, HeadVars, TGs) :-
strip_subst_module(UnexpandedGoals, M, Module, UnexpandedGoals0),
nonvar(UnexpandedGoals0),
complete_partial_goal(MS, UnexpandedGoals0, _, SuppArgs, UnexpandedGoals1),
@@ -740,7 +743,7 @@ expand_subgoal(UnexpandedGoals, MS, M, ExpandedGoals, HeadVars) :-
),
strip_subst_module(UnexpandedGoals3, Module, Module1, UnexpandedGoals4),
( inner_meta_specs(0, UnexpandedGoals4, _, MetaSpecs) ->
- expand_module_names(UnexpandedGoals4, MetaSpecs, Module1, ExpandedGoals0, HeadVars)
+ expand_module_names(UnexpandedGoals4, MetaSpecs, Module1, ExpandedGoals0, HeadVars, TGs)
; ExpandedGoals0 = UnexpandedGoals4
),
'$compile_inline_or_expanded_goal'(ExpandedGoals0, SuppArgs, ExpandedGoals1, Module1, UnexpandedGoals0),
@@ -769,10 +772,10 @@ expand_module_name(ESG0, MS, M, ESG) :-
:- non_counted_backtracking eq_member/2.
-eq_member(V, [L-_|Ls]) :-
+eq_member(V-M, [L-M|Ls]) :-
V == L.
-eq_member(V, [_|Ls]) :-
- eq_member(V, Ls).
+eq_member(V-M, [_|Ls]) :-
+ eq_member(V-M, Ls).
:- non_counted_backtracking qualified_spec/1.
@@ -782,11 +785,19 @@ qualified_spec(MS) :- integer(MS), MS >= 0.
:- non_counted_backtracking expand_meta_predicate_subgoals/5.
-expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars) :-
+expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars, TGs) :-
( var(SG) ->
( qualified_spec(MS) ->
- ( eq_member(SG, HeadVars) ->
+ ( eq_member(SG-_, HeadVars) ->
ESG = SG
+ ; eq_member(SG-TG, TGs),
+ % transitive goals come about from previous equalities:
+ % if SG was bound by (=)/2 to a potential goal TG earlier
+ % in the goal sequence, expand TG and substitute SG with it
+ % in this subgoal context. the binding to SG must not be
+ % changed.
+ expand_subgoal(TG, MS, M, ESG, HeadVars, TGs) ->
+ true
; expand_module_name(SG, MS, M, ESG)
)
; ESG = SG
@@ -795,26 +806,26 @@ expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars
expand_module_name(SG, MS, M, ESG)
; '$is_expanded_or_inlined'(SG) ->
ESG = SG
- ; expand_subgoal(SG, MS, M, ESG, HeadVars) ->
+ ; expand_subgoal(SG, MS, M, ESG, HeadVars, TGs) ->
true
; integer(MS),
MS >= 0 ->
expand_module_name(SG, MS, M, ESG)
; SG = ESG
),
- expand_meta_predicate_subgoals(SGs, MSs, M, ESGs, HeadVars).
+ expand_meta_predicate_subgoals(SGs, MSs, M, ESGs, HeadVars, TGs).
-expand_meta_predicate_subgoals([], _, _, [], _).
+expand_meta_predicate_subgoals([], _, _, [], _, _).
-:- non_counted_backtracking expand_module_names/5.
+:- non_counted_backtracking expand_module_names/6.
-expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :-
+expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars, TGs) :-
Goals =.. [GoalFunctor | SubGoals],
( GoalFunctor == (:),
SubGoals = [M, SubGoal] ->
- expand_module_names(SubGoal, MetaSpecs, M, ExpandedSubGoal, HeadVars),
+ expand_module_names(SubGoal, MetaSpecs, M, ExpandedSubGoal, HeadVars, TGs),
expand_module_name(ExpandedSubGoal, 0, M, ExpandedGoals)
- ; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars),
+ ; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars, TGs),
ExpandedGoals =.. [GoalFunctor | ExpandedGoalList]
).
@@ -822,26 +833,26 @@ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :-
:- non_counted_backtracking expand_goal/3.
expand_goal(UnexpandedGoals, Module, ExpandedGoals) :-
- catch(loader:expand_goal(UnexpandedGoals, Module, ExpandedGoals, []),
+ catch(loader:expand_goal(UnexpandedGoals, Module, ExpandedGoals, [], []),
error(type_error(callable, _), _),
UnexpandedGoals = ExpandedGoals),
!.
-:- non_counted_backtracking expand_goal/4.
+:- non_counted_backtracking expand_goal/5.
-expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :-
+expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars, TGs) :-
( var(UnexpandedGoals) ->
- expand_module_names(call(UnexpandedGoals), [0], Module, ExpandedGoals, HeadVars)
+ expand_module_names(call(UnexpandedGoals), [0], Module, ExpandedGoals, HeadVars, TGs)
; goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
( Module \== user ->
goal_expansion(UnexpandedGoals1, user, Goals)
; Goals = UnexpandedGoals1
),
- ( expand_goal_cases(Goals, Module, ExpandedGoals, HeadVars) ->
+ ( expand_goal_cases(Goals, Module, ExpandedGoals, HeadVars, TGs) ->
true
; predicate_property(Module:Goals, meta_predicate(MetaSpecs0)),
MetaSpecs0 =.. [_ | MetaSpecs] ->
- expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars)
+ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars, TGs)
; thread_goals(Goals, ExpandedGoals, (','))
; Goals = ExpandedGoals
)
@@ -874,28 +885,40 @@ expand_call_goal_(UnexpandedGoals, Module, ExpandedGoals) :-
)
).
-:- non_counted_backtracking expand_goal_cases/4.
+:- non_counted_backtracking transitive_goal/3.
-expand_goal_cases((Goal0, Goals0), Module, ExpandedGoals, HeadVars) :-
- ( expand_goal(Goal0, Module, Goal1, HeadVars) ->
- expand_goal(Goals0, Module, Goals1, HeadVars),
+transitive_goal(G, TGs0, TGs1) :-
+ ( G = (G1 = PotentialGoal),
+ callable(PotentialGoal),
+ subsumes_term(G1, PotentialGoal) ->
+ TGs1 = [G1-PotentialGoal|TGs0]
+ ; TGs1 = TGs0
+ ).
+
+:- non_counted_backtracking expand_goal_cases/5.
+
+expand_goal_cases((Goal0, Goals0), Module, ExpandedGoals, HeadVars, TGs) :-
+ ( expand_goal(Goal0, Module, Goal1, HeadVars, TGs) ->
+ transitive_goal(Goal0, TGs, TGs1),
+ expand_goal(Goals0, Module, Goals1, HeadVars, TGs1),
thread_goals(Goal1, ExpandedGoals, Goals1, (','))
- ; expand_goal(Goals0, Module, Goals1, HeadVars),
+ ; expand_goal(Goals0, Module, Goals1, HeadVars, TGs),
ExpandedGoals = (Goal0, Goals1)
).
-expand_goal_cases((Goals0 -> Goals1), Module, ExpandedGoals, HeadVars) :-
- expand_goal(Goals0, Module, ExpandedGoals0, HeadVars),
- expand_goal(Goals1, Module, ExpandedGoals1, HeadVars),
+expand_goal_cases((Goals0 -> Goals1), Module, ExpandedGoals, HeadVars, TGs) :-
+ expand_goal(Goals0, Module, ExpandedGoals0, HeadVars, TGs),
+ transitive_goal(ExpandedGoals0, TGs, TGs1),
+ expand_goal(Goals1, Module, ExpandedGoals1, HeadVars, TGs1),
ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1).
-expand_goal_cases((Goals0 ; Goals1), Module, ExpandedGoals, HeadVars) :-
- expand_goal(Goals0, Module, ExpandedGoals0, HeadVars),
- expand_goal(Goals1, Module, ExpandedGoals1, HeadVars),
+expand_goal_cases((Goals0 ; Goals1), Module, ExpandedGoals, HeadVars, TGs) :-
+ expand_goal(Goals0, Module, ExpandedGoals0, HeadVars, TGs),
+ expand_goal(Goals1, Module, ExpandedGoals1, HeadVars, TGs),
ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1).
-expand_goal_cases((\+ Goals0), Module, ExpandedGoals, HeadVars) :-
- expand_goal(Goals0, Module, Goals1, HeadVars),
+expand_goal_cases((\+ Goals0), Module, ExpandedGoals, HeadVars, TGs) :-
+ expand_goal(Goals0, Module, Goals1, HeadVars, TGs),
ExpandedGoals = (\+ Goals1).
-expand_goal_cases((Module:Goals0), _, ExpandedGoals, HeadVars) :-
- expand_goal(Goals0, Module, Goals1, HeadVars),
+expand_goal_cases((Module:Goals0), _, ExpandedGoals, HeadVars, TGs) :-
+ expand_goal(Goals0, Module, Goals1, HeadVars, TGs),
ExpandedGoals = (Module:Goals1).
:- non_counted_backtracking thread_goals/3.
diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs
index 8380c130..3de47a60 100644
--- a/src/machine/arithmetic_ops.rs
+++ b/src/machine/arithmetic_ops.rs
@@ -1423,6 +1423,7 @@ mod tests {
use crate::machine::mock_wam::*;
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn arith_eval_by_metacall_tests() {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
diff --git a/src/machine/compile.rs b/src/machine/compile.rs
index 296d076f..7f967e8b 100644
--- a/src/machine/compile.rs
+++ b/src/machine/compile.rs
@@ -42,42 +42,35 @@ pub(super) fn bootstrapping_compile(
Ok(())
}
-fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize {
+fn lower_bound_of_target_clause(skeleton: &mut PredicateSkeleton, target_pos: usize) -> usize {
if target_pos == 0 {
return 0;
}
- let arg_num = skeleton.clauses[target_pos - 1].opt_arg_index_key.arg_num();
+ debug_assert!(skeleton.clauses.len() >= 2);
- if arg_num == 0 {
- return target_pos - 1;
- }
+ let index = target_pos - 1;
- let mut index_loc_opt = None;
+ let index = if let Some(index_loc) = skeleton.clauses[index]
+ .opt_arg_index_key
+ .switch_on_term_loc()
+ {
+ let search_result = skeleton.clauses.make_contiguous()
+ [0..skeleton.core.clause_assert_margin]
+ .partition_point(|clause_index_info| clause_index_info.clause_start > index_loc);
- for index in (0..target_pos).rev() {
- let current_arg_num = skeleton.clauses[index].opt_arg_index_key.arg_num();
-
- if current_arg_num == 0 || current_arg_num != arg_num {
- return index + 1;
- }
-
- if let Some(index_loc) = index_loc_opt {
- let current_index_loc = skeleton.clauses[index]
- .opt_arg_index_key
- .switch_on_term_loc();
-
- if Some(index_loc) != current_index_loc {
- return index + 1;
- }
+ if search_result < skeleton.core.clause_assert_margin {
+ search_result
} else {
- index_loc_opt = skeleton.clauses[index]
- .opt_arg_index_key
- .switch_on_term_loc();
+ skeleton.clauses.make_contiguous()[skeleton.core.clause_assert_margin..]
+ .partition_point(|clause_index_info| clause_index_info.clause_start < index_loc)
+ + skeleton.core.clause_assert_margin
}
- }
+ } else {
+ index
+ };
- 0
+ index.clamp(0, skeleton.clauses.len() - 2)
}
fn derelictize_try_me_else(
@@ -1215,7 +1208,7 @@ fn print_overwrite_warning(
}
println!(
- "Warning: overwriting {}/{} because the clauses are discontiguous",
+ "% Warning: overwriting {}/{} because the clauses are discontiguous",
key.0.as_str(),
key.1
);
@@ -1327,7 +1320,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.clause_clause_locs
.extend(&clause_clause_locs.make_contiguous()[0..]);
- let skeleton = cg.skeleton;
+ let mut skeleton = cg.skeleton;
+ skeleton.core.is_dynamic = settings.is_dynamic();
self.add_extensible_predicate(key, skeleton, predicates.compilation_target);
}
@@ -1527,6 +1521,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let code_len = self.wam_prelude.code.len();
+ standalone_skeleton.clauses[0].clause_start += code_len;
+
let skeleton = match self
.wam_prelude
.indices
@@ -1539,8 +1535,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
match append_or_prepend {
AppendOrPrepend::Append => {
let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap();
- skeleton.clauses.push_back(clause_index_info);
+ skeleton.clauses.push_back(clause_index_info);
skeleton.core.clause_clause_locs.push_back(code_len);
self.payload
@@ -2148,7 +2144,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.map(|skeleton| skeleton.predicate_info())
.unwrap_or_default();
- let mut predicate_info = self
+ let predicate_info = self
.wam_prelude
.indices
.get_predicate_skeleton(&self.payload.predicates.compilation_target, &key)
@@ -2183,7 +2179,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
if is_cross_module_clause && !local_predicate_info.is_extensible {
if predicate_info.is_multifile {
println!(
- "Warning: overwriting multifile predicate {}:{}/{} because \
+ "% Warning: overwriting multifile predicate {}:{}/{} because \
it was not locally declared multifile.",
self.payload.predicates.compilation_target,
key.0.as_str(),
@@ -2210,8 +2206,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
(0..skeleton.clauses.len()).map(Some).collect(),
false, // the builtin M:'$clause'/2 is never dynamic.
);
-
- predicate_info.is_dynamic = false;
}
self.payload
diff --git a/src/machine/copier.rs b/src/machine/copier.rs
index c02854ff..b64be4a0 100644
--- a/src/machine/copier.rs
+++ b/src/machine/copier.rs
@@ -398,6 +398,7 @@ mod tests {
use crate::machine::mock_wam::*;
#[test]
+ #[cfg_attr(miri, ignore = "blocked on atom_table.rs UB")]
fn copier_tests() {
let mut wam = MockWAM::new();
diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs
index ff7d0188..f3a73e6c 100644
--- a/src/machine/dispatch.rs
+++ b/src/machine/dispatch.rs
@@ -557,20 +557,29 @@ impl Machine {
}
let mut p = self.machine_st.p;
+ let mut arity = 0;
while self.code[p].is_head_instr() {
+ for r in self.code[p].registers() {
+ if let RegType::Temp(t) = r {
+ arity = std::cmp::max(arity, t);
+ }
+ }
+
p += 1;
}
- let instr =
- std::mem::replace(&mut self.code[p], Instruction::VerifyAttrInterrupt);
+ let instr = std::mem::replace(
+ &mut self.code[p],
+ Instruction::VerifyAttrInterrupt(arity),
+ );
self.code[VERIFY_ATTR_INTERRUPT_LOC] = instr;
self.machine_st.attr_var_init.cp = p;
}
- &Instruction::VerifyAttrInterrupt => {
- let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity();
- let arity = std::cmp::max(arity, self.machine_st.num_of_args);
+ &Instruction::VerifyAttrInterrupt(arity) => {
+ // let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity();
+ // let arity = std::cmp::max(arity, self.machine_st.num_of_args);
self.run_verify_attr_interrupt(arity);
}
&Instruction::Add(ref a1, ref a2, t) => {
@@ -4147,6 +4156,14 @@ impl Machine {
try_or_throw!(self.machine_st, self.js_eval());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
+ &Instruction::CallArgv => {
+ try_or_throw!(self.machine_st, self.argv());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteArgv => {
+ try_or_throw!(self.machine_st, self.argv());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
&Instruction::CallCurrentTime => {
self.current_time();
step_or_fail!(self, self.machine_st.p += 1);
@@ -4491,44 +4508,28 @@ impl Machine {
self.crypto_curve_scalar_mult();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
- #[cfg(feature = "crypto-full")]
- &Instruction::CallEd25519Sign => {
- self.ed25519_sign();
+ &Instruction::CallEd25519SignRaw => {
+ self.ed25519_sign_raw();
step_or_fail!(self, self.machine_st.p += 1);
}
- #[cfg(feature = "crypto-full")]
- &Instruction::ExecuteEd25519Sign => {
- self.ed25519_sign();
+ &Instruction::ExecuteEd25519SignRaw => {
+ self.ed25519_sign_raw();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
- #[cfg(feature = "crypto-full")]
- &Instruction::CallEd25519Verify => {
- self.ed25519_verify();
+ &Instruction::CallEd25519VerifyRaw => {
+ self.ed25519_verify_raw();
step_or_fail!(self, self.machine_st.p += 1);
}
- #[cfg(feature = "crypto-full")]
- &Instruction::ExecuteEd25519Verify => {
- self.ed25519_verify();
+ &Instruction::ExecuteEd25519VerifyRaw => {
+ self.ed25519_verify_raw();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
- #[cfg(feature = "crypto-full")]
- &Instruction::CallEd25519NewKeyPair => {
- self.ed25519_new_key_pair();
+ &Instruction::CallEd25519SeedToPublicKey => {
+ self.ed25519_seed_to_public_key();
step_or_fail!(self, self.machine_st.p += 1);
}
- #[cfg(feature = "crypto-full")]
- &Instruction::ExecuteEd25519NewKeyPair => {
- self.ed25519_new_key_pair();
- step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
- }
- #[cfg(feature = "crypto-full")]
- &Instruction::CallEd25519KeyPairPublicKey => {
- self.ed25519_key_pair_public_key();
- step_or_fail!(self, self.machine_st.p += 1);
- }
- #[cfg(feature = "crypto-full")]
- &Instruction::ExecuteEd25519KeyPairPublicKey => {
- self.ed25519_key_pair_public_key();
+ &Instruction::ExecuteEd25519SeedToPublicKey => {
+ self.ed25519_seed_to_public_key();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallCurve25519ScalarMult => {
diff --git a/src/machine/gc.rs b/src/machine/gc.rs
index 32142e1d..f62231ea 100644
--- a/src/machine/gc.rs
+++ b/src/machine/gc.rs
@@ -369,6 +369,7 @@ mod tests {
use crate::machine::mock_wam::*;
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn heap_marking_tests() {
let mut wam = MockWAM::new();
diff --git a/src/machine/lib_machine.rs b/src/machine/lib_machine.rs
index 44c5d727..d355ee7e 100644
--- a/src/machine/lib_machine.rs
+++ b/src/machine/lib_machine.rs
@@ -236,6 +236,7 @@ mod tests {
use crate::machine::{QueryMatch, QueryResolution, Value};
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn programatic_query() {
let mut machine = Machine::new_lib();
@@ -275,6 +276,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn failing_query() {
let mut machine = Machine::new_lib();
let query = String::from(r#"triple("a",P,"b")."#);
@@ -288,6 +290,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore)]
fn complex_results() {
let mut machine = Machine::new_lib();
machine.load_module_string(
@@ -344,6 +347,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn empty_predicate() {
let mut machine = Machine::new_lib();
machine.load_module_string(
@@ -359,6 +363,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn list_results() {
let mut machine = Machine::new_lib();
machine.load_module_string(
@@ -387,6 +392,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn consult() {
let mut machine = Machine::new_lib();
@@ -445,6 +451,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn integration_test() {
let mut machine = Machine::new_lib();
@@ -495,6 +502,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn findall() {
let mut machine = Machine::new_lib();
diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs
index 3cdc10aa..f340ad03 100644
--- a/src/machine/load_state.rs
+++ b/src/machine/load_state.rs
@@ -466,24 +466,48 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
None => return,
};
- for (key, code_index) in removed_module.code_dir.iter_mut() {
- match removed_module
- .local_extensible_predicates
- .get(&(CompilationTarget::User, *key))
- {
- Some(skeleton) if skeleton.is_multifile => continue,
- _ => {}
+ let mut skipped_local_predicates = IndexSet::with_hasher(FxBuildHasher::default());
+
+ for ((local_compilation_target, key), skeleton) in
+ removed_module.local_extensible_predicates.iter()
+ {
+ skipped_local_predicates.insert(key);
+
+ if skeleton.is_multifile {
+ continue;
}
- let old_index_ptr = code_index.replace(IndexPtr::undefined());
+ if let Some(code_index) = removed_module.code_dir.get_mut(key) {
+ if let Some(global_skeleton) = self
+ .wam_prelude
+ .indices
+ .get_predicate_skeleton(local_compilation_target, key)
+ {
+ let old_index_ptr = code_index.replace(if global_skeleton.core.is_dynamic {
+ IndexPtr::dynamic_undefined()
+ } else {
+ IndexPtr::undefined()
+ });
- self.payload
- .retraction_info
- .push_record(RetractionRecord::ReplacedModulePredicate(
- module_name,
- *key,
- old_index_ptr,
- ));
+ self.payload.retraction_info.push_record(
+ RetractionRecord::ReplacedModulePredicate(module_name, *key, old_index_ptr),
+ );
+ }
+ }
+ }
+
+ for (key, code_index) in removed_module.code_dir.iter_mut() {
+ if skipped_local_predicates.contains(key) {
+ continue;
+ }
+
+ if !code_index.is_undefined() && !code_index.is_dynamic_undefined() {
+ let old_index_ptr = code_index.replace(IndexPtr::undefined());
+
+ self.payload.retraction_info.push_record(
+ RetractionRecord::ReplacedModulePredicate(module_name, *key, old_index_ptr),
+ );
+ }
}
for (key, skeleton) in removed_module.extensible_predicates.drain(..) {
diff --git a/src/machine/loader.rs b/src/machine/loader.rs
index fb200f03..cd4f419a 100644
--- a/src/machine/loader.rs
+++ b/src/machine/loader.rs
@@ -1833,9 +1833,33 @@ impl Machine {
}
pub(crate) fn scoped_clause_to_evacuable(&mut self) -> CallResult {
- let module_name = cell_as_atom!(self
- .machine_st
- .store(self.machine_st.deref(self.machine_st.registers[1])));
+ let target = self.deref_register(1);
+
+ let mut permission_error = || {
+ let err = self.machine_st.permission_error(
+ Permission::Modify,
+ atom!("static_procedure"),
+ functor_stub(atom!(":"), 2)
+ .into_iter()
+ .collect::(),
+ );
+
+ self.machine_st
+ .error_form(err, functor_stub(atom!("load"), 1))
+ };
+
+ let module_name = read_heap_cell!(target,
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ if arity == 0 {
+ name
+ } else {
+ return Err(permission_error());
+ }
+ }
+ _ => {
+ return Err(permission_error());
+ }
+ );
let loader = self.loader_from_heap_evacuable(temp_v!(3));
@@ -1948,11 +1972,13 @@ impl Machine {
_ => CompilationTarget::Module(module_name),
};
- let stub_gen = || match append_or_prepend {
- AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
- AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
+ let key = match append_or_prepend {
+ AppendOrPrepend::Append => (atom!("assertz"), 1),
+ AppendOrPrepend::Prepend => (atom!("asserta"), 1),
};
+ let stub_gen = || functor_stub(key.0, key.1);
+
let head = self.deref_register(2);
if head.is_var() {
@@ -1991,7 +2017,11 @@ impl Machine {
.map(|code_idx| code_idx.get_tag())
.unwrap_or(IndexPtrTag::DynamicUndefined);
- idx_tag == IndexPtrTag::DynamicUndefined || idx_tag == IndexPtrTag::Undefined
+ if idx_tag == IndexPtrTag::Index {
+ return Err(SessionError::CannotOverwriteStaticProcedure((name, arity)));
+ } else {
+ idx_tag == IndexPtrTag::Undefined || idx_tag == IndexPtrTag::DynamicUndefined
+ }
} else if is_builtin {
return Err(SessionError::CannotOverwriteBuiltIn((name, arity)));
} else {
diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs
index 49d56510..c2cbb405 100644
--- a/src/machine/machine_errors.rs
+++ b/src/machine/machine_errors.rs
@@ -488,6 +488,13 @@ impl MachineState {
.into_iter()
.collect::(),
),
+ SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
+ Permission::Modify,
+ atom!("static_procedure"),
+ functor_stub(key.0, key.1)
+ .into_iter()
+ .collect::(),
+ ),
SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(Permission::Modify, atom!("static_module"), module)
}
@@ -1005,6 +1012,7 @@ pub enum SessionError {
CompilationError(CompilationError),
CannotOverwriteBuiltIn(PredicateKey),
CannotOverwriteBuiltInModule(Atom),
+ CannotOverwriteStaticProcedure(PredicateKey),
ExistenceError(ExistenceError),
ModuleDoesNotContainExport(Atom, PredicateKey),
ModuleCannotImportSelf(Atom),
diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs
index edd6b673..459db1d7 100644
--- a/src/machine/machine_state_impl.rs
+++ b/src/machine/machine_state_impl.rs
@@ -1450,10 +1450,15 @@ impl MachineState {
a1.as_var().unwrap(),
);
}
+ (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum |
+ HeapCellValueTag::F64) if arity != 0 => {
+ let err = self.type_error(ValidType::Atom, store_name);
+ return Err(self.error_form(err, stub_gen())); // 8.5.1.3 e)
+ }
_ => {
let err = self.type_error(ValidType::Atomic, store_name);
- return Err(self.error_form(err, stub_gen()));
- } // 8.5.1.3 c)
+ return Err(self.error_form(err, stub_gen())); // 8.5.1.3 c)
+ }
);
}
_ => {
diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs
index 0da42e08..2679be43 100644
--- a/src/machine/mock_wam.rs
+++ b/src/machine/mock_wam.rs
@@ -260,6 +260,7 @@ mod tests {
use super::*;
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn unify_tests() {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
@@ -481,6 +482,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn test_unify_with_occurs_check() {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
diff --git a/src/machine/mod.rs b/src/machine/mod.rs
index b25627db..5326c83c 100644
--- a/src/machine/mod.rs
+++ b/src/machine/mod.rs
@@ -228,7 +228,7 @@ impl Machine {
self.machine_st.throw_exception(err);
}
- fn run_module_predicate(
+ pub fn run_module_predicate(
&mut self,
module_name: Atom,
key: PredicateKey,
@@ -307,29 +307,6 @@ impl Machine {
}
}
- pub fn run_top_level(
- &mut self,
- module_name: Atom,
- key: PredicateKey,
- ) -> std::process::ExitCode {
- let mut arg_pstrs = vec![];
-
- for arg in env::args() {
- arg_pstrs.push(put_complete_string(
- &mut self.machine_st.heap,
- &arg,
- &self.machine_st.atom_tbl,
- ));
- }
-
- self.machine_st.registers[1] = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- arg_pstrs.into_iter()
- ));
-
- self.run_module_predicate(module_name, key)
- }
-
pub fn set_user_input(&mut self, input: String) {
self.user_input = Stream::from_owned_string(input, &mut self.machine_st.arena);
}
@@ -414,7 +391,7 @@ impl Machine {
self.code.extend(vec![
Instruction::BreakFromDispatchLoop,
Instruction::InstallVerifyAttr,
- Instruction::VerifyAttrInterrupt,
+ Instruction::VerifyAttrInterrupt(0),
Instruction::BreakFromDispatchLoop, // the location of LIB_QUERY_SUCCESS
Instruction::ExecuteTermGreaterThan,
Instruction::ExecuteTermLessThan,
@@ -925,8 +902,8 @@ impl Machine {
self.machine_st.hb = self.machine_st.heap.len();
- self.machine_st.oip = 0;
- self.machine_st.iip = 0;
+ // self.machine_st.oip = 0;
+ // self.machine_st.iip = 0;
}
self.machine_st.p += offset;
@@ -1010,8 +987,22 @@ impl Machine {
self.machine_st.heap.truncate(target_h);
- self.machine_st.oip = 0;
- self.machine_st.iip = 0;
+ // these registers don't need to be reset here and MUST
+ // NOT be (nor in indexed_try! trust_epilogue is an
+ // exception, see next paragraph)! oip could be reset
+ // without any adverse effects but iip is needed by
+ // get_clause_p to find the last executed clause/2 clause.
+
+ // trust_epilogue must reset these for the sake of
+ // subsequent predicates beginning with
+ // switch_to_term. get_clause_p copes by checking
+ // self.machine_st.b > self.machine.e: if true, it is safe
+ // to use self.machine_st.iip; if false, use the choice
+ // point left at the top of the stack by '$clause'
+ // (specifically its biip value).
+
+ // self.machine_st.oip = 0;
+ // self.machine_st.iip = 0;
} else {
self.trust_epilogue(offset);
}
@@ -1116,7 +1107,7 @@ impl Machine {
}
Unknown::Warn => {
println!(
- "warning: predicate {}/{} is undefined",
+ "% Warning: predicate {}/{} is undefined",
name.as_str(),
arity
);
diff --git a/src/machine/partial_string.rs b/src/machine/partial_string.rs
index cfbd4d8b..80d86e69 100644
--- a/src/machine/partial_string.rs
+++ b/src/machine/partial_string.rs
@@ -351,9 +351,9 @@ impl<'a> HeapPStrIter<'a> {
);
value.as_char().map(|c| PStrIterStep {
- iteratee: PStrIteratee::Char(curr_hare, c),
- next_hare: s+2,
- })
+ iteratee: PStrIteratee::Char(curr_hare, c),
+ next_hare: s+2,
+ })
} else {
None
};
@@ -764,13 +764,29 @@ pub fn compare_pstr_prefixes<'a>(
if i1.focus == empty_list_as_cell!() {
PStrCmpResult::Ordered(Ordering::Less)
} else {
- PStrCmpResult::SecondIterContinuable(r2.unwrap().iteratee)
+ let r2_step = r2.unwrap();
+
+ // advance i2 to the next character so the same character
+ // isn't repeated
+ if matches!(r2_step.iteratee, PStrIteratee::Char(..)) {
+ cycle_detection_step(i2, i1, &r2_step);
+ }
+
+ PStrCmpResult::SecondIterContinuable(r2_step.iteratee)
}
} else if r2_at_end {
if i2.focus == empty_list_as_cell!() {
PStrCmpResult::Ordered(Ordering::Greater)
} else {
- PStrCmpResult::FirstIterContinuable(r1.unwrap().iteratee)
+ let r1_step = r1.unwrap();
+
+ // advance i1 to the next character so the same character
+ // isn't repeated
+ if matches!(r1_step.iteratee, PStrIteratee::Char(..)) {
+ cycle_detection_step(i1, i2, &r1_step);
+ }
+
+ PStrCmpResult::FirstIterContinuable(r1_step.iteratee)
}
} else if i1.is_continuable() && i2.is_continuable() {
PStrCmpResult::Ordered(Ordering::Equal)
@@ -785,6 +801,7 @@ mod test {
use crate::machine::mock_wam::*;
#[test]
+ #[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn pstr_iter_tests() {
let mut wam = MockWAM::new();
@@ -1089,9 +1106,119 @@ mod test {
Some(PStrIteratee::PStrSegment(2, atom!("abc"), 1))
);
- // assert!(iter.next().is_none());
-
for _ in iter {}
}
+
+ // #2293, test1.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("a ")));
+ wam.machine_st.heap.push(heap_loc_as_cell!(1));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
+
+ // #2293, test2.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!(" a")));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(heap_loc_as_cell!(3));
+ wam.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
+
+ // #2293, test3.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("a b")));
+ wam.machine_st.heap.push(heap_loc_as_cell!(1));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(list_loc_as_cell!(5));
+ wam.machine_st.heap.push(heap_loc_as_cell!(5));
+ wam.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
+
+ // #2293, test4.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!(" a ")));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(heap_loc_as_cell!(3));
+ wam.machine_st.heap.push(list_loc_as_cell!(5));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
+
+ // #2293, test5.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!(" a bc")));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(heap_loc_as_cell!(3));
+ wam.machine_st.heap.push(list_loc_as_cell!(5));
+ wam.machine_st.heap.push(char_as_cell!(' '));
+ wam.machine_st.heap.push(heap_loc_as_cell!(6));
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
+
+ // #2293, test6.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("abc")));
+ wam.machine_st.heap.push(heap_loc_as_cell!(1));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(char_as_cell!('b'));
+ wam.machine_st.heap.push(list_loc_as_cell!(5));
+ wam.machine_st.heap.push(heap_loc_as_cell!(5));
+ wam.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
+
+ // #2293, test7.
+
+ wam.machine_st.heap.clear();
+
+ wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("abcde")));
+ wam.machine_st.heap.push(char_as_cell!('a'));
+ wam.machine_st.heap.push(list_loc_as_cell!(3));
+ wam.machine_st.heap.push(heap_loc_as_cell!(3));
+ wam.machine_st.heap.push(list_loc_as_cell!(5));
+ wam.machine_st.heap.push(char_as_cell!('c'));
+ wam.machine_st.heap.push(list_loc_as_cell!(7));
+ wam.machine_st.heap.push(heap_loc_as_cell!(7));
+ wam.machine_st.heap.push(list_loc_as_cell!(9));
+ wam.machine_st.heap.push(char_as_cell!('e'));
+ wam.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+
+ assert!(!wam.machine_st.fail);
}
}
diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs
index 2681e8c0..b6e82ab7 100644
--- a/src/machine/preprocessor.rs
+++ b/src/machine/preprocessor.rs
@@ -565,21 +565,6 @@ impl Preprocessor {
}
}
- /*
- fn try_term_to_query<'a, LS: LoadState<'a>>(
- &mut self,
- loader: &mut Loader<'a, LS>,
- terms: Vec,
- cut_context: CutContext,
- ) -> Result {
- Ok(TopLevel::Query(self.setup_query(
- loader,
- terms,
- cut_context,
- )?))
- }
- */
-
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
@@ -607,20 +592,4 @@ impl Preprocessor {
}
}
}
-
- /*
- fn try_terms_to_tls<'a, I: IntoIterator- , LS: LoadState<'a>>(
- &mut self,
- loader: &mut Loader<'a, LS>,
- terms: I,
- ) -> Result, CompilationError> {
- let mut results = VecDeque::new();
-
- for term in terms.into_iter() {
- results.push_back(self.try_term_to_tl(loader, term)?);
- }
-
- Ok(results)
- }
- */
}
diff --git a/src/machine/project_attributes.pl b/src/machine/project_attributes.pl
index f54797c8..1ad0c47f 100644
--- a/src/machine/project_attributes.pl
+++ b/src/machine/project_attributes.pl
@@ -1,4 +1,4 @@
-:- module('$project_atts', [copy_term/3]).
+:- module('$project_atts', []).
:- use_module(library(dcgs)).
:- use_module(library(error), [can_be/2]).
@@ -100,14 +100,6 @@ gather_residual_goals([V|Vs]) -->
delete_all_attributes_from_var(V) :- '$delete_all_attributes_from_var'(V).
-copy_term(Term, Copy, Gs) :-
- can_be(list, Gs),
- findall(Term-Rs, term_residual_goals(Term,Rs), [Copy-Gs]),
- ( var(Gs) ->
- Gs = []
- ; true
- ).
-
term_residual_goals(Term,Rs) :-
'$term_attributed_variables'(Term, Vs),
phrase(gather_residual_goals(Vs), Rs),
diff --git a/src/machine/stack.rs b/src/machine/stack.rs
index 46638bee..12aba456 100644
--- a/src/machine/stack.rs
+++ b/src/machine/stack.rs
@@ -189,7 +189,7 @@ impl Stack {
for idx in 0..num_cells {
ptr::write(
- (new_ptr as usize + offset) as *mut HeapCellValue,
+ new_ptr.add(offset) as *mut HeapCellValue,
stack_loc_as_cell!(AndFrame, e, idx + 1),
);
@@ -203,6 +203,10 @@ impl Stack {
}
}
+ pub(crate) fn top(&self) -> usize {
+ unsafe { (*self.buf.ptr.get()) as usize - self.buf.base as usize }
+ }
+
pub(crate) fn allocate_or_frame(&mut self, num_cells: usize) -> usize {
let frame_size = OrFrame::size_of(num_cells);
@@ -238,7 +242,8 @@ impl Stack {
#[inline(always)]
pub(crate) fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
unsafe {
- let ptr = self.buf.base as usize + e;
+ // This is doing alignment wrong
+ let ptr = self.buf.base.add(e);
&mut *(ptr as *mut AndFrame)
}
}
@@ -276,6 +281,7 @@ mod tests {
use crate::machine::mock_wam::*;
#[test]
+ #[cfg_attr(miri, ignore)]
fn stack_tests() {
let mut wam = MockWAM::new();
diff --git a/src/machine/streams.rs b/src/machine/streams.rs
index fc957ade..53269bf4 100644
--- a/src/machine/streams.rs
+++ b/src/machine/streams.rs
@@ -469,6 +469,7 @@ macro_rules! arena_allocated_impl_for_stream {
#[inline]
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
unsafe {
+ // Miri seems to hit this a lot
ptr::write(dst, self);
TypedArenaPtr::new(dst as *mut Self)
}
diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs
index 758bbc9d..5a10358d 100644
--- a/src/machine/system_calls.rs
+++ b/src/machine/system_calls.rs
@@ -81,14 +81,11 @@ use ring::rand::{SecureRandom, SystemRandom};
use ring::{digest, hkdf, pbkdf2};
#[cfg(feature = "crypto-full")]
-use ring::{
- aead,
- signature::{self, KeyPair},
-};
+use ring::aead;
use ripemd160::{Digest, Ripemd160};
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
-use crrl::{secp256k1, x25519};
+use crrl::{ed25519, secp256k1, x25519};
#[cfg(feature = "tls")]
use native_tls::{Identity, TlsAcceptor, TlsConnector};
@@ -1171,63 +1168,33 @@ impl Machine {
.get_predicate_skeleton(&compilation_target, &key)
.unwrap();
- if self.machine_st.b > self.machine_st.e {
- let or_frame = self.machine_st.stack.index_or_frame(self.machine_st.b);
- let bp = or_frame.prelude.bp;
+ let module_name = match compilation_target {
+ CompilationTarget::User => atom!("builtins"),
+ CompilationTarget::Module(target) => target,
+ };
- match &self.code[bp] {
- Instruction::IndexingCode(ref indexing_code) => {
- match &indexing_code[or_frame.prelude.boip as usize] {
- IndexingLine::IndexedChoice(ref indexed_choice) => {
- let p = or_frame.prelude.biip as usize - 1;
+ let mut bp = self
+ .indices
+ .get_predicate_code_index(atom!("$clause"), 2, module_name)
+ .and_then(|idx| idx.local())
+ .unwrap();
- match &indexed_choice[p] {
- &IndexedChoiceInstruction::Try(offset)
- | &IndexedChoiceInstruction::Retry(offset)
- | &IndexedChoiceInstruction::DefaultRetry(offset) => {
- let clause_clause_loc = skeleton.core.clause_clause_locs[p];
- (clause_clause_loc, bp + offset)
- }
- &IndexedChoiceInstruction::Trust(_)
- | &IndexedChoiceInstruction::DefaultTrust(_) => {
- unreachable!()
- }
- }
- }
- _ => {
- unreachable!()
- }
+ macro_rules! extract_ptr {
+ ($ptr: expr) => {
+ match $ptr {
+ IndexingCodePtr::External(p) => {
+ return (
+ skeleton.core.clause_clause_locs.back().cloned().unwrap(),
+ bp + p,
+ )
}
+ IndexingCodePtr::Internal(boip) => boip,
+ _ => unreachable!(),
}
- _ => unreachable!(),
- }
- } else {
- let module_name = match compilation_target {
- CompilationTarget::User => atom!("builtins"),
- CompilationTarget::Module(target) => target,
};
+ }
- let bp = self
- .indices
- .get_predicate_code_index(atom!("$clause"), 2, module_name)
- .and_then(|idx| idx.local())
- .unwrap();
-
- macro_rules! extract_ptr {
- ($ptr: expr) => {
- match $ptr {
- IndexingCodePtr::External(p) => {
- return (
- skeleton.core.clause_clause_locs.back().cloned().unwrap(),
- bp + p,
- )
- }
- IndexingCodePtr::Internal(boip) => boip,
- _ => unreachable!(),
- }
- };
- }
-
+ loop {
match &self.code[bp] {
Instruction::IndexingCode(ref indexing_code) => {
let indexing_code_ptr = match &indexing_code[0] {
@@ -1263,14 +1230,38 @@ impl Machine {
match &indexing_code[boip] {
IndexingLine::IndexedChoice(indexed_choice) => {
+ let p = if self.machine_st.b > self.machine_st.e {
+ // this means the last
+ // self.machine_st.iip value has yet
+ // to be overwritten by the Trust
+ // instruction. In this case, return
+ // it.
+ self.machine_st.iip as usize
+ } else {
+ // otherwise, read the '$clause'
+ // choicepoint from the top of the
+ // stack. this is very volatile in
+ // that it depends on '$clause'
+ // immediately preceding
+ // '$get_clause_p', which cannot be
+ // the last clause of the retract
+ // helper to delay deallocation of its
+ // environment frame.
+ let clause_b = self.machine_st.stack.top();
+ self.machine_st.stack.index_or_frame(clause_b).prelude.biip as usize
+ };
+
return (
- skeleton.core.clause_clause_locs.back().cloned().unwrap(),
- bp + indexed_choice.back().unwrap().offset(),
+ skeleton.core.clause_clause_locs[p],
+ bp + indexed_choice[p].offset(),
);
}
_ => unreachable!(),
}
}
+ &Instruction::RevJmpBy(offset) => {
+ bp -= offset;
+ }
_ => {
return (
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
@@ -3501,6 +3492,12 @@ impl Machine {
Some(Ok(c)) => {
string.push(c);
}
+ Some(Err(e)) => {
+ let stub = functor_stub(atom!("$get_n_chars"), 3);
+ let err = self.machine_st.session_error(SessionError::from(e));
+
+ return Err(self.machine_st.error_form(err, stub));
+ }
_ => {
break;
}
@@ -4291,18 +4288,18 @@ impl Machine {
let address_string = address_sink.as_str(); //to_string();
let address: Url = address_string.parse().unwrap();
- let client = reqwest::blocking::Client::builder().build().unwrap();
+ let client = reqwest::Client::builder().build().unwrap();
// request
- let mut req = reqwest::blocking::Request::new(method, address);
+ let mut req = reqwest::Request::new(method, address);
*req.headers_mut() = headers;
if !bytes.is_empty() {
- *req.body_mut() = Some(reqwest::blocking::Body::from(bytes));
+ *req.body_mut() = Some(reqwest::Body::from(bytes));
}
// do it!
- match client.execute(req) {
+ match futures::executor::block_on(client.execute(req)) {
Ok(resp) => {
// status code
let status = resp.status().as_u16();
@@ -4339,7 +4336,7 @@ impl Machine {
self.machine_st.registers[6]
);
// body
- let reader = resp.bytes().unwrap().reader();
+ let reader = futures::executor::block_on(resp.bytes()).unwrap().reader();
let mut stream = Stream::from_http_stream(
AtomTable::build_with(&self.machine_st.atom_tbl, &address_string),
@@ -4953,6 +4950,27 @@ impl Machine {
}
}
+ #[inline(always)]
+ pub(crate) fn argv(&mut self) -> CallResult {
+ let args = self.deref_register(1);
+
+ let mut args_pstrs = vec![];
+ for arg in env::args() {
+ args_pstrs.push(put_complete_string(
+ &mut self.machine_st.heap,
+ &arg,
+ &self.machine_st.atom_tbl,
+ ));
+ }
+ let cell = heap_loc_as_cell!(iter_to_heap_list(
+ &mut self.machine_st.heap,
+ args_pstrs.into_iter()
+ ));
+
+ unify!(self.machine_st, args, cell);
+ Ok(())
+ }
+
#[inline(always)]
pub(crate) fn current_time(&mut self) {
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
@@ -5721,11 +5739,11 @@ impl Machine {
#[inline(always)]
pub(super) fn restore_instr_at_verify_attr_interrupt(&mut self) {
match &self.code[VERIFY_ATTR_INTERRUPT_LOC] {
- &Instruction::VerifyAttrInterrupt => {}
+ &Instruction::VerifyAttrInterrupt(_) => {}
_ => {
let instr = mem::replace(
&mut self.code[VERIFY_ATTR_INTERRUPT_LOC],
- Instruction::VerifyAttrInterrupt,
+ Instruction::VerifyAttrInterrupt(0),
);
self.code[self.machine_st.attr_var_init.cp] = instr;
@@ -6520,10 +6538,8 @@ impl Machine {
);
if had_zero_port {
- self.machine_st.unify_fixnum(
- Fixnum::build_with(port as i64),
- self.machine_st.registers[2],
- );
+ self.machine_st
+ .unify_fixnum(Fixnum::build_with(port as i64), self.deref_register(2));
}
Ok(())
@@ -7625,33 +7641,16 @@ impl Machine {
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
}
- #[cfg(feature = "crypto-full")]
#[inline(always)]
- pub(crate) fn ed25519_new_key_pair(&mut self) {
- let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
- let complete_string = self.u8s_to_string(pkcs8_bytes.as_ref());
+ pub(crate) fn ed25519_seed_to_public_key(&mut self) {
+ let stub_gen = || functor_stub(atom!("ed25519_seed_keypair"), 2);
+ let seed_bytes = self
+ .machine_st
+ .integers_to_bytevec(self.machine_st.registers[1], stub_gen);
- unify!(
- self.machine_st,
- self.machine_st.registers[1],
- complete_string
- )
- }
+ let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
- #[cfg(feature = "crypto-full")]
- #[inline(always)]
- pub(crate) fn ed25519_key_pair_public_key(&mut self) {
- let bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
-
- let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&bytes) {
- Ok(kp) => kp,
- _ => {
- self.machine_st.fail = true;
- return;
- }
- };
-
- let complete_string = self.u8s_to_string(key_pair.public_key().as_ref());
+ let complete_string = self.u8s_to_string(skey.public_key.encoded.as_ref());
unify!(
self.machine_st,
@@ -7660,22 +7659,19 @@ impl Machine {
);
}
- #[cfg(feature = "crypto-full")]
#[inline(always)]
- pub(crate) fn ed25519_sign(&mut self) {
- let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
+ pub(crate) fn ed25519_sign_raw(&mut self) {
+ let stub_gen = || functor_stub(atom!("ed25519_sign"), 4);
+ let seed_bytes = self
+ .machine_st
+ .integers_to_bytevec(self.machine_st.registers[1], stub_gen);
+
+ let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
+
let encoding = cell_as_atom!(self.deref_register(3));
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
- let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&key) {
- Ok(kp) => kp,
- _ => {
- self.machine_st.fail = true;
- return;
- }
- };
-
- let sig = key_pair.sign(&data);
+ let sig = skey.sign_raw(&data);
let sig_list = heap_loc_as_cell!(iter_to_heap_list(
&mut self.machine_st.heap,
@@ -7687,25 +7683,21 @@ impl Machine {
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
}
- #[cfg(feature = "crypto-full")]
#[inline(always)]
- pub(crate) fn ed25519_verify(&mut self) {
- let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
+ pub(crate) fn ed25519_verify_raw(&mut self) {
+ let key_bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
+ let pkey = ed25519::PublicKey::decode(&key_bytes).unwrap();
+
let encoding = cell_as_atom!(self.deref_register(3));
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
- let stub_gen = || functor_stub(atom!("ed25519_verify"), 5);
+
+ let stub_gen = || functor_stub(atom!("ed25519_verify"), 4);
+
let signature = self
.machine_st
.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
- let peer_public_key = signature::UnparsedPublicKey::new(&signature::ED25519, &key);
-
- match peer_public_key.verify(&data, &signature) {
- Ok(_) => {}
- _ => {
- self.machine_st.fail = true;
- }
- }
+ self.machine_st.fail = !pkey.verify_raw(&signature, &data);
}
#[inline(always)]
diff --git a/src/machine/unify.rs b/src/machine/unify.rs
index 3c100ce4..b045552b 100644
--- a/src/machine/unify.rs
+++ b/src/machine/unify.rs
@@ -173,6 +173,98 @@ pub(crate) trait Unifier: DerefMut {
let mut pstr_iter1 = HeapPStrIter::new(&machine_st.heap, s1);
let mut pstr_iter2 = HeapPStrIter::new(&machine_st.heap, s1 + 1);
+ fn unify_sequence(
+ machine_st: &mut MachineState,
+ iter: PStrIteratee,
+ source_cell: HeapCellValue,
+ ) -> bool {
+ match iter {
+ PStrIteratee::Char(focus, _) => {
+ machine_st.pdl.push(machine_st.heap[focus]);
+ machine_st.pdl.push(source_cell);
+ }
+ PStrIteratee::PStrSegment(focus, _, n) => {
+ read_heap_cell!(machine_st.heap[focus],
+ (HeapCellValueTag::CStr | HeapCellValueTag::PStr, pstr_atom) => {
+ if focus < machine_st.heap.len() - 2 {
+ machine_st.heap.pop();
+ machine_st.heap.pop();
+ }
+
+ if n == 0 {
+ let target_cell = match machine_st.heap[focus].get_tag() {
+ HeapCellValueTag::CStr => {
+ atom_as_cstr_cell!(pstr_atom)
+ }
+ HeapCellValueTag::PStr => {
+ pstr_loc_as_cell!(focus)
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ machine_st.pdl.push(target_cell);
+ machine_st.pdl.push(source_cell);
+ } else {
+ let h_len = machine_st.heap.len();
+
+ machine_st.heap.push(pstr_offset_as_cell!(focus));
+ machine_st.heap.push(fixnum_as_cell!(
+ Fixnum::build_with(n as i64)
+ ));
+
+ machine_st.pdl.push(pstr_loc_as_cell!(h_len));
+ machine_st.pdl.push(source_cell);
+ }
+
+ return true;
+ }
+ (HeapCellValueTag::PStrOffset, pstr_loc) => {
+ let n0 = cell_as_fixnum!(machine_st.heap[focus+1])
+ .get_num() as usize;
+
+ if pstr_loc < machine_st.heap.len() - 2 {
+ machine_st.heap.pop();
+ machine_st.heap.pop();
+ }
+
+ if n == n0 {
+ machine_st.pdl.push(pstr_loc_as_cell!(focus));
+ machine_st.pdl.push(source_cell);
+ } else {
+ let h_len = machine_st.heap.len();
+
+ machine_st.heap.push(pstr_offset_as_cell!(pstr_loc));
+ machine_st.heap.push(fixnum_as_cell!(
+ Fixnum::build_with(n as i64)
+ ));
+
+ machine_st.pdl.push(pstr_loc_as_cell!(h_len));
+ machine_st.pdl.push(source_cell);
+ }
+
+ return true;
+ }
+ _ => {
+ }
+ );
+
+ if focus < machine_st.heap.len() - 2 {
+ machine_st.heap.pop();
+ machine_st.heap.pop();
+ }
+
+ machine_st.pdl.push(machine_st.heap[focus]);
+ machine_st.pdl.push(source_cell);
+
+ return true;
+ }
+ }
+
+ false
+ }
+
match compare_pstr_prefixes(&mut pstr_iter1, &mut pstr_iter2) {
PStrCmpResult::Ordered(Ordering::Equal) => {}
PStrCmpResult::Ordered(Ordering::Less) => {
@@ -229,89 +321,13 @@ pub(crate) trait Unifier: DerefMut {
break 'outer;
}
}
+ (HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
+ unify_sequence(machine_st, chars_iter.item.unwrap(), focus);
+ return;
+ }
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- match chars_iter.item.unwrap() {
- PStrIteratee::Char(focus, _) => {
- machine_st.pdl.push(machine_st.heap[focus]);
- machine_st.pdl.push(heap_loc_as_cell!(h));
- }
- PStrIteratee::PStrSegment(focus, _, n) => {
- read_heap_cell!(machine_st.heap[focus],
- (HeapCellValueTag::CStr | HeapCellValueTag::PStr, pstr_atom) => {
- if focus < machine_st.heap.len() - 2 {
- machine_st.heap.pop();
- machine_st.heap.pop();
- }
-
- if n == 0 {
- let target_cell = match machine_st.heap[focus].get_tag() {
- HeapCellValueTag::CStr => {
- atom_as_cstr_cell!(pstr_atom)
- }
- HeapCellValueTag::PStr => {
- pstr_loc_as_cell!(focus)
- }
- _ => {
- unreachable!()
- }
- };
-
- machine_st.pdl.push(target_cell);
- machine_st.pdl.push(heap_loc_as_cell!(h));
- } else {
- let h_len = machine_st.heap.len();
-
- machine_st.heap.push(pstr_offset_as_cell!(focus));
- machine_st.heap.push(fixnum_as_cell!(
- Fixnum::build_with(n as i64)
- ));
-
- machine_st.pdl.push(pstr_loc_as_cell!(h_len));
- machine_st.pdl.push(heap_loc_as_cell!(h));
- }
-
- return;
- }
- (HeapCellValueTag::PStrOffset, pstr_loc) => {
- let n0 = cell_as_fixnum!(machine_st.heap[focus+1])
- .get_num() as usize;
-
- if pstr_loc < machine_st.heap.len() - 2 {
- machine_st.heap.pop();
- machine_st.heap.pop();
- }
-
- if n == n0 {
- machine_st.pdl.push(pstr_loc_as_cell!(focus));
- machine_st.pdl.push(heap_loc_as_cell!(h));
- } else {
- let h_len = machine_st.heap.len();
-
- machine_st.heap.push(pstr_offset_as_cell!(pstr_loc));
- machine_st.heap.push(fixnum_as_cell!(
- Fixnum::build_with(n as i64)
- ));
-
- machine_st.pdl.push(pstr_loc_as_cell!(h_len));
- machine_st.pdl.push(heap_loc_as_cell!(h));
- }
-
- return;
- }
- _ => {
- }
- );
-
- if focus < machine_st.heap.len() - 2 {
- machine_st.heap.pop();
- machine_st.heap.pop();
- }
-
- machine_st.pdl.push(machine_st.heap[focus]);
- machine_st.pdl.push(heap_loc_as_cell!(h));
-
- return;
- }
+ if unify_sequence(machine_st, chars_iter.item.unwrap(), heap_loc_as_cell!(h)) {
+ return;
}
break 'outer;
diff --git a/src/parser/ast.rs b/src/parser/ast.rs
index ec46a74f..04d6fc99 100644
--- a/src/parser/ast.rs
+++ b/src/parser/ast.rs
@@ -417,6 +417,9 @@ impl ParserError {
ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => {
atom!("unexpected_end_of_file")
}
+ ParserError::IO(e) if e.kind() == ErrorKind::InvalidData => {
+ atom!("invalid_data")
+ }
ParserError::IO(_) => atom!("input_output_error"),
ParserError::LexicalError(_) => atom!("lexical_error"),
ParserError::MissingQuote(..) => atom!("missing_quote"),
diff --git a/src/parser/char_reader.rs b/src/parser/char_reader.rs
index bf3b8f8e..aa1813a9 100644
--- a/src/parser/char_reader.rs
+++ b/src/parser/char_reader.rs
@@ -144,6 +144,35 @@ impl CharRead for CharReader {
Err(e) => return Some(Err(e)),
}
+ let bad_bytes_error = |buf: &[u8]| {
+ // If we have 4 bytes that still don't make up
+ // a valid code point, then we have garbage.
+
+ // We have bad data in the buffer. Remove
+ // leading bytes until either the buffer is
+ // empty, or we have a valid code point.
+
+ let mut split_point = 1;
+ let mut badbytes = vec![];
+
+ loop {
+ let (bad, rest) = buf.split_at(split_point);
+
+ if rest.is_empty() || str::from_utf8(rest).is_ok() {
+ badbytes.extend_from_slice(bad);
+ break;
+ }
+
+ split_point += 1;
+ }
+
+ // Raise the error. If we still have data in
+ // the buffer, it will be returned on the next
+ // loop.
+
+ io::Error::new(io::ErrorKind::InvalidData, BadUtf8Error { bytes: badbytes })
+ };
+
loop {
let buf = &self.buf[self.pos..];
@@ -159,38 +188,10 @@ impl CharRead for CharReader {
};
if buf.len() - e.valid_up_to() >= 4 {
- // If we have 4 bytes that still don't make up
- // a valid code point, then we have garbage.
-
- // We have bad data in the buffer. Remove
- // leading bytes until either the buffer is
- // empty, or we have a valid code point.
-
- let mut split_point = 1;
- let mut badbytes = vec![];
-
- loop {
- let (bad, rest) = buf.split_at(split_point);
-
- if rest.is_empty() || str::from_utf8(rest).is_ok() {
- badbytes.extend_from_slice(bad);
- break;
- }
-
- split_point += 1;
- }
-
- // Raise the error. If we still have data in
- // the buffer, it will be returned on the next
- // loop.
-
- return Some(Err(io::Error::new(
- io::ErrorKind::InvalidData,
- BadUtf8Error { bytes: badbytes },
- )));
+ return Some(Err(bad_bytes_error(buf)));
} else if self.pos >= self.buf.len() {
return None;
- } else if self.buf.len() - self.pos >= 4 {
+ } else if self.buf.len() - self.pos >= 4 && self.pos < e.valid_up_to() {
return match str::from_utf8(&self.buf[self.pos..e.valid_up_to()]) {
Ok(s) => {
let mut chars = s.chars();
@@ -217,18 +218,22 @@ impl CharRead for CharReader {
self.buf.truncate(buf_len - self.pos);
let buf_len = self.buf.len();
+ self.pos = 0;
+
+ if buf_len >= 4 {
+ continue;
+ }
let mut word = [0u8; 4];
let word_slice = &mut word[buf_len..4];
match self.inner.read(word_slice) {
Err(e) => return Some(Err(e)),
+ Ok(nread) if nread == 0 => return Some(Err(bad_bytes_error(&self.buf))),
Ok(nread) => {
self.buf.extend_from_slice(&word_slice[0..nread]);
}
}
-
- self.pos = 0;
}
} else {
return None;
@@ -375,6 +380,7 @@ mod tests {
use std::io::Cursor;
#[test]
+ #[cfg_attr(miri, ignore = "slow and not very relevant")]
fn plain_string() {
let mut read_string = CharReader::new(Cursor::new("a string"));
@@ -387,6 +393,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "slow and not very relevant")]
fn greek_string() {
let mut read_string = CharReader::new(Cursor::new("λέξη"));
@@ -399,6 +406,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "slow and not very relevant")]
fn russian_string() {
let mut read_string = CharReader::new(Cursor::new("слово"));
@@ -411,6 +419,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "slow and not very relevant")]
fn greek_lorem_ipsum() {
let lorem_ipsum = "Λορεμ ιπσθμ δολορ σιτ αμετ, οφφενδιτ
εφφιcιενδι σιτ ει, ηαρθμ λεγερε qθαερενδθμ ιθσ νε. Ηασ νο εροσ
@@ -482,6 +491,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "slow and not very relevant")]
fn armenian_lorem_ipsum() {
let lorem_ipsum = "լոռեմ իպսում դոլոռ սիթ ամեթ, նովում գռաեծո
սեա եա, աբհոռռեանթ դիսպութանդո եի քուի. իդ քուոդ ինդոծթում
@@ -555,6 +565,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(miri, ignore = "slow and not very relevant")]
fn russian_lorem_ipsum() {
let lorem_ipsum = "Лорем ипсум долор сит амет, атяуи дицам еи
сит, ид сеа фацилис елаборарет. Меа еу яуас алияуид, те яуи
diff --git a/src/parser/parser.rs b/src/parser/parser.rs
index de2b04a0..3637df24 100644
--- a/src/parser/parser.rs
+++ b/src/parser/parser.rs
@@ -97,7 +97,12 @@ pub(crate) fn as_partial_string(
string.push(*c);
}
_ => {
- return Err(Term::Cons(Cell::default(), Box::new(head), orig_tail));
+ tail = Term::Cons(
+ Cell::default(),
+ Box::new((**prev).clone()),
+ Box::new((**succ).clone()),
+ );
+ break;
}
}
@@ -880,11 +885,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
.push(Term::Literal(Cell::default(), Literal::Atom(atom)));
}
- self.stack[idx].spec = if self.stack[idx].priority > 0 {
- TERM
- } else {
- BTERM
- };
+ self.stack[idx].spec = BTERM;
self.stack[idx].tt = TokenType::Term;
self.stack[idx].priority = 0;
diff --git a/src/raw_block.rs b/src/raw_block.rs
index 41be0706..2c10f494 100644
--- a/src/raw_block.rs
+++ b/src/raw_block.rs
@@ -43,7 +43,7 @@ impl RawBlock {
let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
self.base = alloc::alloc(layout) as *const _;
- self.top = (self.base as usize + cap) as *const _;
+ self.top = self.base.add(cap);
*self.ptr.get_mut() = self.base as *mut _;
}
@@ -98,7 +98,7 @@ impl RawBlock {
pub unsafe fn alloc(&self, size: usize) -> *mut u8 {
if self.free_space() >= size {
let ptr = *self.ptr.get();
- *self.ptr.get() = (ptr as usize + size) as *mut _;
+ *self.ptr.get() = ptr.add(size) as *mut _;
ptr
} else {
ptr::null_mut()
diff --git a/src/read.rs b/src/read.rs
index 1115bf1a..c13c0250 100644
--- a/src/read.rs
+++ b/src/read.rs
@@ -130,7 +130,7 @@ impl ReadlineStream {
if let Some(mut path) = dirs_next::home_dir() {
path.push(HISTORY_FILE);
if path.exists() && rl.load_history(&path).is_err() {
- println!("Warning: loading history failed");
+ println!("% Warning: loading history failed");
}
}
@@ -213,10 +213,10 @@ impl ReadlineStream {
path.push(HISTORY_FILE);
if path.exists() {
if self.rl.append_history(&path).is_err() {
- println!("Warning: couldn't append history (existing file)");
+ println!("% Warning: couldn't append history (existing file)");
}
} else if self.rl.save_history(&path).is_err() {
- println!("Warning: couldn't save history (new file)");
+ println!("% Warning: couldn't save history (new file)");
}
}
}
diff --git a/src/tests/dif.pl b/src/tests/dif.pl
index f0836007..c7dfbdd7 100644
--- a/src/tests/dif.pl
+++ b/src/tests/dif.pl
@@ -1,10 +1,10 @@
/**/
-:- use_module(library(format)).
:- use_module(library(dcgs)).
+:- use_module(library(format)).
:- use_module(library(lists)).
:- use_module(library(debug)).
-:- use_module(library(atts)).
+:- use_module(library(iso_ext)).
:- use_module(library(dif)).
% Tests from https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dif
diff --git a/src/tests/when.pl b/src/tests/when.pl
new file mode 100644
index 00000000..7356e42e
--- /dev/null
+++ b/src/tests/when.pl
@@ -0,0 +1,145 @@
+/**/
+
+:- use_module(library(iso_ext)).
+:- use_module(library(format)).
+:- use_module(library(dcgs)).
+:- use_module(library(lists)).
+:- use_module(library(debug)).
+
+:- use_module(library(when)).
+
+test("condition true before ground/1",(
+ A = 1,
+ when(ground(A), Run = true),
+ Run == true
+)).
+
+test("condition true before nonvar/1",(
+ A = a(_),
+ when(nonvar(A), Run = true),
+ Run == true
+)).
+
+test("condition true before ','/2",(
+ A = 1,
+ B = a(_),
+ when((ground(A), nonvar(B)), Run = true),
+ Run == true
+)).
+
+test("condition true before (;)/2",(
+ A = 1,
+ when((ground(A) ; nonvar(_)), Run1 = true),
+ Run1 == true,
+
+ B = a(_),
+ when((ground(_) ; nonvar(B)), Run2 = true),
+ Run2 == true
+)).
+
+test("condition true after ground/1",(
+ when(ground(A), Run = true),
+ var(Run),
+ A = 1,
+ Run == true
+)).
+
+test("condition true after nonvar/1",(
+ when(nonvar(A), Run = true),
+ var(Run),
+ A = a(_),
+ Run == true
+)).
+
+test("condition true after ','/2",(
+ when((ground(A), nonvar(B)), Run = true),
+ var(Run),
+ A = 1,
+ var(Run),
+ B = a(_),
+ Run == true
+)).
+
+test("condition true after (;)/2",(
+ when((ground(A) ; nonvar(_)), Run1 = true),
+ var(Run1),
+ A = 1,
+ Run1 == true,
+
+ when((ground(_) ; nonvar(B)), Run2 = true),
+ var(Run2),
+ B = a(_),
+ Run2 == true
+)).
+
+test("multiple when/2 on same variable",(
+ when(nonvar(A), Run1 = true),
+ when(ground(A), Run2 = true),
+ var(Run1), var(Run2),
+ A = a(B),
+ Run1 == true, var(Run2),
+ B = 1,
+ Run2 == true
+)).
+
+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).
+
diff --git a/src/toplevel.pl b/src/toplevel.pl
index a9a423c4..820d91d0 100644
--- a/src/toplevel.pl
+++ b/src/toplevel.pl
@@ -1,7 +1,5 @@
-:- module('$toplevel', [argv/1,
- copy_term/3]).
+:- module('$toplevel', []).
-:- use_module(library(atts), [call_residue_vars/2]).
:- use_module(library(charsio)).
:- use_module(library(error)).
:- use_module(library(files)).
@@ -9,11 +7,13 @@
:- use_module(library(lambda)).
:- use_module(library(lists)).
:- use_module(library(si)).
+:- use_module(library(os)).
:- use_module(library('$project_atts')).
:- use_module(library('$atts')).
:- dynamic(disabled_init_file/0).
+:- dynamic(started/0).
load_scryerrc :-
( '$home_directory'(HomeDir) ->
@@ -26,24 +26,18 @@ load_scryerrc :-
; true
).
-:- dynamic(argv/1).
-
-'$repl'([_|Args0]) :-
- \+ argv(_),
- ( append(Args1, ["--"|Args2], Args0) ->
- asserta('$toplevel':argv(Args2)),
+'$repl' :-
+ asserta('$toplevel':started),
+ raw_argv(Args0),
+ ( append(Args1, ["--"|_], Args0) ->
Args = Args1
- ; asserta('$toplevel':argv([])),
- Args = Args0
+ ; Args = Args0
),
- delegate_task(Args, []),
- (\+ disabled_init_file -> load_scryerrc ; true),
- repl.
-'$repl'(_) :-
- ( \+ argv(_) -> asserta('$toplevel':argv([]))
+ ( Args = [_|TaskArgs] ->
+ delegate_task(TaskArgs, [])
; true
),
- load_scryerrc,
+ (\+ disabled_init_file -> load_scryerrc ; true),
repl.
delegate_task([], []).
@@ -134,7 +128,7 @@ run_goals([g(Gs0)|Goals]) :- !,
write_term(Exception, [double_quotes(DQ)]), nl % halt?
)
) -> true
- ; write('Warning: initialization failed for: '),
+ ; write('% Warning: initialization failed for: '),
write_term(Goal, [variable_names(VNs),double_quotes(DQ)]), nl
),
run_goals(Goals).
@@ -191,7 +185,7 @@ submit_query_and_print_results_(Term, VarList) :-
bb_put('$report_all', false),
bb_put('$report_n_more', 0),
expand_goal(Term, user, Term0),
- atts:call_residue_vars(user:Term0, AttrVars),
+ call_residue_vars(user:Term0, AttrVars),
write_eqs_and_read_input(B, VarList, AttrVars),
!.
submit_query_and_print_results_(_, _) :-
@@ -314,7 +308,11 @@ write_eqs_and_read_input(B, VarList, AttrVars) :-
% one layer of depth added for (=/2) functor
'$term_variables_under_max_depth'(OrigVars, 22, Vars0),
'$project_atts':project_attributes(Vars0, AttrVars),
- copy_term(AttrVars, AttrVars, AttrGoals),
+ % Need to copy all the visible Vars here so that they appear
+ % properly in AttrGoals, even the non-attributed. Need to also
+ % copy all the attributed variables here so that anonymous
+ % attributed variables also appear properly in AttrGoals.
+ copy_term([Vars0, AttrVars], [Vars0, AttrVars], AttrGoals),
term_variables(AttrGoals, AttrGoalVars),
append([Vars0, AttrGoalVars, AttrVars], Vars),
charsio:extend_var_list(Vars, VarList, NewVarList, fabricated),
@@ -452,4 +450,3 @@ print_exception_with_check(E) :-
% is expected to be printed instead.
; print_exception(E)
).
-
diff --git a/tests-pl/iso-conformity-tests.pl b/tests-pl/iso-conformity-tests.pl
index bfd74c61..dc08ce2d 100644
--- a/tests-pl/iso-conformity-tests.pl
+++ b/tests-pl/iso-conformity-tests.pl
@@ -1005,6 +1005,18 @@ test_311 :- test_syntax_error("Finis ().", syntax_error(incomplete_reduction)).
test_318 :- writeq_term_to_chars(+((1*2)^3), C),
C == "+ (1*2)^3".
+test_320 :- writeq_term_to_chars([a|\+2], C),
+ C == "[a|\\+2]".
+
+test_321 :- test_syntax_error("writeq((a)(b)).", syntax_error(incomplete_reduction)).
+
+test_324 :- writeq_term_to_chars('%', C),
+ C == "'%'".
+
+test_325 :- test_syntax_error("writeq({[y}]).", syntax_error(incomplete_reduction)).
+
+test_326 :- test_syntax_error("(>)(1,2).", syntax_error(incomplete_reduction)).
+
run_tests([Test|Tests]) -->
( { call(Test) } ->
[]
diff --git a/tests/scryer/cli/issues/display_constraints.stderr b/tests/scryer/cli/issues/display_constraints.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/display_constraints.stdin b/tests/scryer/cli/issues/display_constraints.stdin
new file mode 100644
index 00000000..5a3e1dfc
--- /dev/null
+++ b/tests/scryer/cli/issues/display_constraints.stdin
@@ -0,0 +1,5 @@
+X = 1.
+use_module(library(dif)).
+X = 1.
+dif(X,1).
+halt.
diff --git a/tests/scryer/cli/issues/display_constraints.stdout b/tests/scryer/cli/issues/display_constraints.stdout
new file mode 100644
index 00000000..c96fa9ec
--- /dev/null
+++ b/tests/scryer/cli/issues/display_constraints.stdout
@@ -0,0 +1,4 @@
+ X = 1.
+ true.
+ X = 1.
+ dif:dif(X,1).
diff --git a/tests/scryer/cli/issues/display_constraints.toml b/tests/scryer/cli/issues/display_constraints.toml
new file mode 100644
index 00000000..266266c4
--- /dev/null
+++ b/tests/scryer/cli/issues/display_constraints.toml
@@ -0,0 +1,2 @@
+# issue 857
+args = ["-f", "--no-add-history"]
diff --git a/tests-pl/issue852-throw_e.pl b/tests/scryer/cli/issues/do_not_duplicate_path_components.in/throw_e.pl
similarity index 100%
rename from tests-pl/issue852-throw_e.pl
rename to tests/scryer/cli/issues/do_not_duplicate_path_components.in/throw_e.pl
diff --git a/tests/scryer/cli/issues/do_not_duplicate_path_components.stderr b/tests/scryer/cli/issues/do_not_duplicate_path_components.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/do_not_duplicate_path_components.stdin b/tests/scryer/cli/issues/do_not_duplicate_path_components.stdin
new file mode 100644
index 00000000..cf9a3782
--- /dev/null
+++ b/tests/scryer/cli/issues/do_not_duplicate_path_components.stdin
@@ -0,0 +1,3 @@
+['throw_e.pl'].
+['throw_e.pl'].
+halt.
diff --git a/tests/scryer/cli/issues/do_not_duplicate_path_components.stdout b/tests/scryer/cli/issues/do_not_duplicate_path_components.stdout
new file mode 100644
index 00000000..02d7a2d2
--- /dev/null
+++ b/tests/scryer/cli/issues/do_not_duplicate_path_components.stdout
@@ -0,0 +1,2 @@
+ throw(e).
+ throw(e).
diff --git a/tests/scryer/cli/issues/do_not_duplicate_path_components.toml b/tests/scryer/cli/issues/do_not_duplicate_path_components.toml
new file mode 100644
index 00000000..f49e807c
--- /dev/null
+++ b/tests/scryer/cli/issues/do_not_duplicate_path_components.toml
@@ -0,0 +1,2 @@
+# issue 852
+args = ["-f", "--no-add-history"]
diff --git a/tests-pl/issue820-goals.pl b/tests/scryer/cli/issues/goals_compound_goal.in/goals.pl
similarity index 100%
rename from tests-pl/issue820-goals.pl
rename to tests/scryer/cli/issues/goals_compound_goal.in/goals.pl
diff --git a/tests/scryer/cli/issues/goals_compound_goal.stderr b/tests/scryer/cli/issues/goals_compound_goal.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/goals_compound_goal.stdout b/tests/scryer/cli/issues/goals_compound_goal.stdout
new file mode 100644
index 00000000..31e0fce5
--- /dev/null
+++ b/tests/scryer/cli/issues/goals_compound_goal.stdout
@@ -0,0 +1 @@
+helloworld
diff --git a/tests/scryer/cli/issues/goals_compound_goal.toml b/tests/scryer/cli/issues/goals_compound_goal.toml
new file mode 100644
index 00000000..4fd7d5ba
--- /dev/null
+++ b/tests/scryer/cli/issues/goals_compound_goal.toml
@@ -0,0 +1,2 @@
+# issue 820
+args = ["-f", "--no-add-history", "-g", "test,halt", "goals.pl"]
diff --git a/tests/scryer/cli/issues/goals_multiple_goals.in/goals.pl b/tests/scryer/cli/issues/goals_multiple_goals.in/goals.pl
new file mode 100644
index 00000000..fc94b92e
--- /dev/null
+++ b/tests/scryer/cli/issues/goals_multiple_goals.in/goals.pl
@@ -0,0 +1,3 @@
+test :- write(world), nl.
+
+:- initialization(write(hello)).
\ No newline at end of file
diff --git a/tests/scryer/cli/issues/goals_multiple_goals.stderr b/tests/scryer/cli/issues/goals_multiple_goals.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/goals_multiple_goals.stdout b/tests/scryer/cli/issues/goals_multiple_goals.stdout
new file mode 100644
index 00000000..31e0fce5
--- /dev/null
+++ b/tests/scryer/cli/issues/goals_multiple_goals.stdout
@@ -0,0 +1 @@
+helloworld
diff --git a/tests/scryer/cli/issues/goals_multiple_goals.toml b/tests/scryer/cli/issues/goals_multiple_goals.toml
new file mode 100644
index 00000000..25e739dd
--- /dev/null
+++ b/tests/scryer/cli/issues/goals_multiple_goals.toml
@@ -0,0 +1,2 @@
+# issue 820
+args = ["-f", "--no-add-history", "-g", "test", "-g", "halt", "goals.pl"]
diff --git a/tests/scryer/cli/issues/handle_residual_goal.stderr b/tests/scryer/cli/issues/handle_residual_goal.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/handle_residual_goal.stdin b/tests/scryer/cli/issues/handle_residual_goal.stdin
new file mode 100644
index 00000000..1d7849f3
--- /dev/null
+++ b/tests/scryer/cli/issues/handle_residual_goal.stdin
@@ -0,0 +1,11 @@
+use_module(library(dif)).
+use_module(library(iso_ext)).
+-X\=X.
+-X=X.
+dif(-X,X).
+dif(-X,X), -X=X.
+call_residue_vars(dif(-X,X), Vars).
+set_prolog_flag(occurs_check, true).
+-X\=X.
+dif(-X,X).
+halt.
diff --git a/tests/scryer/cli/issues/handle_residual_goal.stdout b/tests/scryer/cli/issues/handle_residual_goal.stdout
new file mode 100644
index 00000000..288981d9
--- /dev/null
+++ b/tests/scryer/cli/issues/handle_residual_goal.stdout
@@ -0,0 +1,10 @@
+ true.
+ true.
+ false.
+ X = -X.
+ dif:dif(-X,X).
+ false.
+ Vars = [X], dif:dif(-X,X).
+ true.
+ true.
+ true.
diff --git a/tests/scryer/cli/issues/handle_residual_goal.toml b/tests/scryer/cli/issues/handle_residual_goal.toml
new file mode 100644
index 00000000..6f3cb49f
--- /dev/null
+++ b/tests/scryer/cli/issues/handle_residual_goal.toml
@@ -0,0 +1,2 @@
+# issue 844
+args = ["-f", "--no-add-history"]
diff --git a/tests/scryer/cli/issues/ignored_constraint.stderr b/tests/scryer/cli/issues/ignored_constraint.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/ignored_constraint.stdin b/tests/scryer/cli/issues/ignored_constraint.stdin
new file mode 100644
index 00000000..d6123a48
--- /dev/null
+++ b/tests/scryer/cli/issues/ignored_constraint.stdin
@@ -0,0 +1,2 @@
+use_module(library(freeze)), freeze(X,false), X \=a.
+halt.
diff --git a/tests/scryer/cli/issues/ignored_constraint.stdout b/tests/scryer/cli/issues/ignored_constraint.stdout
new file mode 100644
index 00000000..051058c9
--- /dev/null
+++ b/tests/scryer/cli/issues/ignored_constraint.stdout
@@ -0,0 +1 @@
+ freeze:freeze(X,false).
diff --git a/tests/scryer/cli/issues/ignored_constraint.toml b/tests/scryer/cli/issues/ignored_constraint.toml
new file mode 100644
index 00000000..9b1ed769
--- /dev/null
+++ b/tests/scryer/cli/issues/ignored_constraint.toml
@@ -0,0 +1,2 @@
+# issue 807
+args = ["-f", "--no-add-history"]
diff --git a/tests/scryer/cli/issues/no_stutter.stderr b/tests/scryer/cli/issues/no_stutter.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/no_stutter.stdin b/tests/scryer/cli/issues/no_stutter.stdin
new file mode 100644
index 00000000..f7ff0e90
--- /dev/null
+++ b/tests/scryer/cli/issues/no_stutter.stdin
@@ -0,0 +1,2 @@
+write(a), write(b), false.
+halt.
diff --git a/tests/scryer/cli/issues/no_stutter.stdout b/tests/scryer/cli/issues/no_stutter.stdout
new file mode 100644
index 00000000..1e8d7051
--- /dev/null
+++ b/tests/scryer/cli/issues/no_stutter.stdout
@@ -0,0 +1 @@
+ab false.
diff --git a/tests/scryer/cli/issues/no_stutter.toml b/tests/scryer/cli/issues/no_stutter.toml
new file mode 100644
index 00000000..bf523922
--- /dev/null
+++ b/tests/scryer/cli/issues/no_stutter.toml
@@ -0,0 +1,2 @@
+# issue 815
+args = ["-f", "--no-add-history"]
diff --git a/tests-pl/issue841-occurs-check.pl b/tests/scryer/cli/issues/occurs_check_flag.in/occurs_check_example.pl
similarity index 100%
rename from tests-pl/issue841-occurs-check.pl
rename to tests/scryer/cli/issues/occurs_check_flag.in/occurs_check_example.pl
diff --git a/tests/scryer/cli/issues/occurs_check_flag.stderr b/tests/scryer/cli/issues/occurs_check_flag.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/occurs_check_flag.stdin b/tests/scryer/cli/issues/occurs_check_flag.stdin
new file mode 100644
index 00000000..8f652a7f
--- /dev/null
+++ b/tests/scryer/cli/issues/occurs_check_flag.stdin
@@ -0,0 +1,2 @@
+f(X, X).
+halt.
diff --git a/tests/scryer/cli/issues/occurs_check_flag.stdout b/tests/scryer/cli/issues/occurs_check_flag.stdout
new file mode 100644
index 00000000..53fd87fa
--- /dev/null
+++ b/tests/scryer/cli/issues/occurs_check_flag.stdout
@@ -0,0 +1 @@
+ false.
diff --git a/tests/scryer/cli/issues/occurs_check_flag.toml b/tests/scryer/cli/issues/occurs_check_flag.toml
new file mode 100644
index 00000000..b5013924
--- /dev/null
+++ b/tests/scryer/cli/issues/occurs_check_flag.toml
@@ -0,0 +1,2 @@
+# issue 841
+args = ["-f", "--no-add-history", "occurs_check_example.pl"]
diff --git a/tests/scryer/cli/issues/occurs_check_flag2.stderr b/tests/scryer/cli/issues/occurs_check_flag2.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/occurs_check_flag2.stdin b/tests/scryer/cli/issues/occurs_check_flag2.stdin
new file mode 100644
index 00000000..19cf9481
--- /dev/null
+++ b/tests/scryer/cli/issues/occurs_check_flag2.stdin
@@ -0,0 +1,6 @@
+set_prolog_flag(occurs_check, true).
+X = -X.
+asserta(f(X,g(X))).
+f(X,X).
+X-X = X-g(X).
+halt.
diff --git a/tests/scryer/cli/issues/occurs_check_flag2.stdout b/tests/scryer/cli/issues/occurs_check_flag2.stdout
new file mode 100644
index 00000000..2203b5e0
--- /dev/null
+++ b/tests/scryer/cli/issues/occurs_check_flag2.stdout
@@ -0,0 +1,5 @@
+ true.
+ false.
+ true.
+ false.
+ false.
diff --git a/tests/scryer/cli/issues/occurs_check_flag2.toml b/tests/scryer/cli/issues/occurs_check_flag2.toml
new file mode 100644
index 00000000..8d1da0ed
--- /dev/null
+++ b/tests/scryer/cli/issues/occurs_check_flag2.toml
@@ -0,0 +1,2 @@
+# issue 841
+args = ["-f", "--no-add-history"]
diff --git a/tests-pl/issue839-op3.pl b/tests/scryer/cli/issues/op3.in/op3.pl
similarity index 100%
rename from tests-pl/issue839-op3.pl
rename to tests/scryer/cli/issues/op3.in/op3.pl
diff --git a/tests/scryer/cli/issues/op3.stderr b/tests/scryer/cli/issues/op3.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/op3.stdout b/tests/scryer/cli/issues/op3.stdout
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/op3.toml b/tests/scryer/cli/issues/op3.toml
new file mode 100644
index 00000000..864081c2
--- /dev/null
+++ b/tests/scryer/cli/issues/op3.toml
@@ -0,0 +1,2 @@
+# issue 839
+args = ["-f", "--no-add-history", "op3.pl", "-g", "halt"]
diff --git a/tests/scryer/cli/issues/os_argv-no-final--.stderr b/tests/scryer/cli/issues/os_argv-no-final--.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/os_argv-no-final--.stdin b/tests/scryer/cli/issues/os_argv-no-final--.stdin
new file mode 100644
index 00000000..59ba556c
--- /dev/null
+++ b/tests/scryer/cli/issues/os_argv-no-final--.stdin
@@ -0,0 +1,6 @@
+os:argv(V).
+os:argv(["test1"|_]).
+os:argv(["--"|_]).
+os:argv([V, "--"|_]).
+os:argv(["test2"|_]).
+os:argv([]).
diff --git a/tests/scryer/cli/issues/os_argv-no-final--.stdout b/tests/scryer/cli/issues/os_argv-no-final--.stdout
new file mode 100644
index 00000000..9558ca7f
--- /dev/null
+++ b/tests/scryer/cli/issues/os_argv-no-final--.stdout
@@ -0,0 +1,6 @@
+ V = ["test1","--","test2"].
+ true.
+ false.
+ V = "test1".
+ false.
+ false.
diff --git a/tests/scryer/cli/issues/os_argv-no-final--.toml b/tests/scryer/cli/issues/os_argv-no-final--.toml
new file mode 100644
index 00000000..831d0fdd
--- /dev/null
+++ b/tests/scryer/cli/issues/os_argv-no-final--.toml
@@ -0,0 +1,2 @@
+# https://github.com/mthom/scryer-prolog/pull/2263#issuecomment-1874400820
+args = ["-f", "--no-add-history", "--", "test1", "--", "test2"]
diff --git a/tests/scryer/cli/issues/os_argv.stderr b/tests/scryer/cli/issues/os_argv.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/os_argv.stdin b/tests/scryer/cli/issues/os_argv.stdin
new file mode 100644
index 00000000..59ba556c
--- /dev/null
+++ b/tests/scryer/cli/issues/os_argv.stdin
@@ -0,0 +1,6 @@
+os:argv(V).
+os:argv(["test1"|_]).
+os:argv(["--"|_]).
+os:argv([V, "--"|_]).
+os:argv(["test2"|_]).
+os:argv([]).
diff --git a/tests/scryer/cli/issues/os_argv.stdout b/tests/scryer/cli/issues/os_argv.stdout
new file mode 100644
index 00000000..2916310c
--- /dev/null
+++ b/tests/scryer/cli/issues/os_argv.stdout
@@ -0,0 +1,6 @@
+ V = ["test1","--","test2","--"].
+ true.
+ false.
+ V = "test1".
+ false.
+ false.
diff --git a/tests/scryer/cli/issues/os_argv.toml b/tests/scryer/cli/issues/os_argv.toml
new file mode 100644
index 00000000..62b83a7a
--- /dev/null
+++ b/tests/scryer/cli/issues/os_argv.toml
@@ -0,0 +1,2 @@
+# https://github.com/mthom/scryer-prolog/pull/2263#issuecomment-1874400820
+args = ["-f", "--no-add-history", "--", "test1", "--", "test2", "--"]
diff --git a/tests-pl/issue812-singleton-warning.pl b/tests/scryer/cli/issues/singleton_warning.in/singleton_example.pl
similarity index 60%
rename from tests-pl/issue812-singleton-warning.pl
rename to tests/scryer/cli/issues/singleton_warning.in/singleton_example.pl
index 9c8673b9..f8207fa7 100644
--- a/tests-pl/issue812-singleton-warning.pl
+++ b/tests/scryer/cli/issues/singleton_warning.in/singleton_example.pl
@@ -1,4 +1,4 @@
% hello
% line!
-a :- b(X).
\ No newline at end of file
+a :- b(X).
diff --git a/tests/scryer/cli/issues/singleton_warning.stderr b/tests/scryer/cli/issues/singleton_warning.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/issues/singleton_warning.stdin b/tests/scryer/cli/issues/singleton_warning.stdin
new file mode 100644
index 00000000..9e58bda5
--- /dev/null
+++ b/tests/scryer/cli/issues/singleton_warning.stdin
@@ -0,0 +1,2 @@
+['singleton_example.pl'].
+halt.
diff --git a/tests/scryer/cli/issues/singleton_warning.stdout b/tests/scryer/cli/issues/singleton_warning.stdout
new file mode 100644
index 00000000..4c8b7182
--- /dev/null
+++ b/tests/scryer/cli/issues/singleton_warning.stdout
@@ -0,0 +1,2 @@
+% Warning: singleton variables X at line 4 of singleton_example.pl
+ true.
diff --git a/tests/scryer/cli/issues/singleton_warning.toml b/tests/scryer/cli/issues/singleton_warning.toml
new file mode 100644
index 00000000..1d30dde6
--- /dev/null
+++ b/tests/scryer/cli/issues/singleton_warning.toml
@@ -0,0 +1,2 @@
+# issue 812
+args = ["-f", "--no-add-history"]
diff --git a/tests/scryer/cli/src_tests/acyclic_term_tests.stderr b/tests/scryer/cli/src_tests/acyclic_term_tests.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/src_tests/acyclic_term_tests.stdout b/tests/scryer/cli/src_tests/acyclic_term_tests.stdout
new file mode 100644
index 00000000..4952cede
--- /dev/null
+++ b/tests/scryer/cli/src_tests/acyclic_term_tests.stdout
@@ -0,0 +1 @@
+All tests passed
\ No newline at end of file
diff --git a/tests/scryer/cli/src_tests/acyclic_term_tests.toml b/tests/scryer/cli/src_tests/acyclic_term_tests.toml
new file mode 100644
index 00000000..042039ef
--- /dev/null
+++ b/tests/scryer/cli/src_tests/acyclic_term_tests.toml
@@ -0,0 +1 @@
+args = ["-f", "--no-add-history", "src/tests/acyclic_term.pl", "-f", "-g", "main_quiet"]
diff --git a/tests/scryer/cli/src_tests/dif_tests.stderr b/tests/scryer/cli/src_tests/dif_tests.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/src_tests/dif_tests.stdout b/tests/scryer/cli/src_tests/dif_tests.stdout
new file mode 100644
index 00000000..4952cede
--- /dev/null
+++ b/tests/scryer/cli/src_tests/dif_tests.stdout
@@ -0,0 +1 @@
+All tests passed
\ No newline at end of file
diff --git a/tests/scryer/cli/src_tests/dif_tests.toml b/tests/scryer/cli/src_tests/dif_tests.toml
new file mode 100644
index 00000000..62665be2
--- /dev/null
+++ b/tests/scryer/cli/src_tests/dif_tests.toml
@@ -0,0 +1 @@
+args = ["-f", "--no-add-history", "src/tests/dif.pl", "-f", "-g", "main_quiet"]
diff --git a/tests/scryer/cli/src_tests/ground_tests.stderr b/tests/scryer/cli/src_tests/ground_tests.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/src_tests/ground_tests.stdout b/tests/scryer/cli/src_tests/ground_tests.stdout
new file mode 100644
index 00000000..4952cede
--- /dev/null
+++ b/tests/scryer/cli/src_tests/ground_tests.stdout
@@ -0,0 +1 @@
+All tests passed
\ No newline at end of file
diff --git a/tests/scryer/cli/src_tests/ground_tests.toml b/tests/scryer/cli/src_tests/ground_tests.toml
new file mode 100644
index 00000000..d7925bb7
--- /dev/null
+++ b/tests/scryer/cli/src_tests/ground_tests.toml
@@ -0,0 +1 @@
+args = ["-f", "--no-add-history", "src/tests/ground.pl", "-f", "-g", "main_quiet"]
diff --git a/tests/scryer/cli/src_tests/setup_call_cleanup_process.stderr b/tests/scryer/cli/src_tests/setup_call_cleanup_process.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/src_tests/setup_call_cleanup_process.stdout b/tests/scryer/cli/src_tests/setup_call_cleanup_process.stdout
new file mode 100644
index 00000000..380c3a78
--- /dev/null
+++ b/tests/scryer/cli/src_tests/setup_call_cleanup_process.stdout
@@ -0,0 +1 @@
+1+21+31+2>A+B1+G1+2>41+2>B1+2>31+2>31+2>4ba
\ No newline at end of file
diff --git a/tests/scryer/cli/src_tests/setup_call_cleanup_process.toml b/tests/scryer/cli/src_tests/setup_call_cleanup_process.toml
new file mode 100644
index 00000000..40a47e98
--- /dev/null
+++ b/tests/scryer/cli/src_tests/setup_call_cleanup_process.toml
@@ -0,0 +1 @@
+args = ["-f", "--no-add-history", "src/tests/setup_call_cleanup.pl", "-f", "-g", "halt"]
diff --git a/tests/scryer/cli/src_tests/term_variables_tests.stderr b/tests/scryer/cli/src_tests/term_variables_tests.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/src_tests/term_variables_tests.stdout b/tests/scryer/cli/src_tests/term_variables_tests.stdout
new file mode 100644
index 00000000..4952cede
--- /dev/null
+++ b/tests/scryer/cli/src_tests/term_variables_tests.stdout
@@ -0,0 +1 @@
+All tests passed
\ No newline at end of file
diff --git a/tests/scryer/cli/src_tests/term_variables_tests.toml b/tests/scryer/cli/src_tests/term_variables_tests.toml
new file mode 100644
index 00000000..6d75921e
--- /dev/null
+++ b/tests/scryer/cli/src_tests/term_variables_tests.toml
@@ -0,0 +1 @@
+args = ["-f", "--no-add-history", "src/tests/term_variables.pl", "-f", "-g", "main_quiet"]
diff --git a/tests/scryer/cli/src_tests/when_tests.stderr b/tests/scryer/cli/src_tests/when_tests.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/scryer/cli/src_tests/when_tests.stdout b/tests/scryer/cli/src_tests/when_tests.stdout
new file mode 100644
index 00000000..4952cede
--- /dev/null
+++ b/tests/scryer/cli/src_tests/when_tests.stdout
@@ -0,0 +1 @@
+All tests passed
\ No newline at end of file
diff --git a/tests/scryer/cli/src_tests/when_tests.toml b/tests/scryer/cli/src_tests/when_tests.toml
new file mode 100644
index 00000000..ff0a5330
--- /dev/null
+++ b/tests/scryer/cli/src_tests/when_tests.toml
@@ -0,0 +1 @@
+args = ["-f", "--no-add-history", "src/tests/when.pl", "-f", "-g", "main_quiet"]
diff --git a/tests/scryer/helper.rs b/tests/scryer/helper.rs
index 243952f2..f4d54fb8 100644
--- a/tests/scryer/helper.rs
+++ b/tests/scryer/helper.rs
@@ -1,6 +1,3 @@
-use assert_cmd::Command;
-use std::ffi::OsStr;
-
pub(crate) trait Expectable {
#[track_caller]
fn assert_eq(self, other: &[u8]);
@@ -34,41 +31,3 @@ pub(crate) fn load_module_test(file: &str, expected: T) {
let mut wam = Machine::with_test_streams();
expected.assert_eq(wam.test_load_file(file).as_slice());
}
-
-pub const SCRYER_PROLOG: &str = "scryer-prolog";
-
-pub fn run_top_level_test_no_args<
- S: Into>,
- O: assert_cmd::assert::IntoOutputPredicate
,
- P: predicates_core::Predicate<[u8]>,
->(
- stdin: S,
- expected_stdout: O,
-) {
- run_top_level_test_with_args::<&[&str], _, _, _, _>(&[], stdin, expected_stdout)
-}
-
-/// Test whether scryer-prolog
-/// produces the expected output when called with the supplied
-/// arguments and fed the supplied input
-pub fn run_top_level_test_with_args<
- A: IntoIterator- ,
- S: Into>,
- O: assert_cmd::assert::IntoOutputPredicate
,
- AS: AsRef,
- P: predicates_core::Predicate<[u8]>,
->(
- args: A,
- stdin: S,
- expected_stdout: O,
-) {
- Command::cargo_bin(SCRYER_PROLOG)
- .unwrap()
- .arg("-f")
- .arg("--no-add-history")
- .args(args)
- .write_stdin(stdin)
- .assert()
- .stdout(expected_stdout.into_output())
- .success();
-}
diff --git a/tests/scryer/issues.rs b/tests/scryer/issues.rs
index f7a71007..39e30378 100644
--- a/tests/scryer/issues.rs
+++ b/tests/scryer/issues.rs
@@ -1,169 +1,10 @@
-use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args};
+use crate::helper::load_module_test;
use serial_test::serial;
-// issue #857
-#[test]
-fn display_constraints() {
- run_top_level_test_no_args(
- "\
- X = 1.\n\
- use_module(library(dif)).\n\
- X = 1.\n\
- dif(X,1).\n
- halt.\n",
- " \
- X = 1.\n \
- true.\n \
- X = 1.\n \
- dif:dif(X,1).\n\
- ",
- );
-}
-
-// issue #852
-#[test]
-fn do_not_duplicate_path_components() {
- run_top_level_test_no_args(
- "\
- ['tests-pl/issue852-throw_e.pl'].\n\
- ['tests-pl/issue852-throw_e.pl'].\n\
- halt.\n\
- ",
- " throw(e).\n throw(e).\n",
- );
-}
-
-// issue #844
-#[test]
-fn handle_residual_goal() {
- run_top_level_test_no_args(
- "\
- use_module(library(dif)).\n\
- use_module(library(atts)).\n\
- -X\\=X.\n\
- -X=X.\n\
- dif(-X,X).\n\
- dif(-X,X), -X=X.\n\
- call_residue_vars(dif(-X,X), Vars).\n\
- set_prolog_flag(occurs_check, true).\n\
- -X\\=X.\n\
- dif(-X,X).\n\
- halt.\n\
- ",
- " \
- true.\n \
- true.\n \
- false.\n \
- X = -X.\n \
- dif:dif(-X,X).\n \
- false.\n \
- Vars = [X], dif:dif(-X,X).\n \
- true.\n \
- true.\n \
- true.\n\
- ",
- )
-}
-
-// issue #841
-#[test]
-fn occurs_check_flag() {
- run_top_level_test_with_args(
- ["tests-pl/issue841-occurs-check.pl"],
- "\
- f(X, X).\n\
- halt.\n\
- ",
- " false.\n",
- )
-}
-
-#[test]
-fn occurs_check_flag2() {
- run_top_level_test_no_args(
- "\
- set_prolog_flag(occurs_check, true).\n\
- X = -X.\n\
- asserta(f(X,g(X))).\n\
- f(X,X).\n\
- X-X = X-g(X).\n\
- halt.\n\
- ",
- " \
- true.\n \
- false.\n \
- true.\n \
- false.\n \
- false.\n\
- ",
- )
-}
-
-// issue #839
-#[test]
-fn op3() {
- run_top_level_test_with_args(["tests-pl/issue839-op3.pl", "-g", "halt"], "", "")
-}
-
-// issue #820
-#[test]
-fn multiple_goals() {
- run_top_level_test_with_args(
- ["-g", "test", "-g", "halt", "tests-pl/issue820-goals.pl"],
- "",
- "helloworld\n",
- );
-}
-
-// issue #820
-#[test]
-fn compound_goal() {
- run_top_level_test_with_args(
- ["-g", "test,halt", "tests-pl/issue820-goals.pl"],
- "",
- "helloworld\n",
- )
-}
-
-// issue #815
-#[test]
-fn no_stutter() {
- run_top_level_test_no_args(
- "write(a), write(b), false.\n\
- halt.\n\
- ",
- "ab false.\n",
- )
-}
-
-/*
-// issue #812
-#[test] // FIXME: the line number is of by one (should be 4), empty line not accounted for or starting to count at line 0?
-fn singleton_warning() {
- run_top_level_test_no_args(
- "['tests-pl/issue812-singleton-warning.pl'].\n\
- halt.\n",
- "\
- Warning: singleton variables X at line 3 of issue812-singleton-warning.pl\n \
- true.\n\
- ",
- );
-}
-*/
-
-// issue #807
-#[test]
-fn ignored_constraint() {
- run_top_level_test_no_args(
- "use_module(library(freeze)), freeze(X,false), X \\=a.\n\
- halt.",
- " freeze:freeze(X,false).\n",
- );
-}
-
// issue #831
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn call_0() {
load_module_test(
"tests-pl/issue831-call0.pl",
diff --git a/tests/scryer/main.rs b/tests/scryer/main.rs
index 7865c0b3..d1e826f0 100644
--- a/tests/scryer/main.rs
+++ b/tests/scryer/main.rs
@@ -1,3 +1,23 @@
mod helper;
mod issues;
mod src_tests;
+
+/// To add new cli test copy an existing .toml file in `tests/scryer/cli/issues/` or `tests/scryer/cli/issues/src_tests/`,
+/// adjust as necessary the `-f` and `--no-add-history` args should be kept but additional args may be added.
+/// For input on stdin add a .stdin file with the same filename.
+/// Then to generate new reference output files into dump/ run `TRYCMD=dump cargo test -- cli_test`
+/// check that the output in the .stdout and .stderr file is as expected, then move them next to the .toml file.
+///
+/// If a test does not have a .stderr or .stdout the corresponding output is ignored i.e. any and no output is accepted
+///
+/// to re-generate all reference output files run `TRYCMD=overwrite cargo test -- cli_test`
+/// then check that the changes are as expected e.g. by looking at the `git diff`
+#[test]
+#[cfg_attr(miri, ignore = "blocked on crossbeam UB")]
+fn cli_tests() {
+ trycmd::TestCases::new()
+ .default_bin_name("scryer-prolog")
+ .case("tests/scryer/cli/issues/*.toml")
+ .skip("tests/scryer/cli/issues/singleton_warning.toml") // wrong line number
+ .case("tests/scryer/cli/src_tests/*.toml");
+}
diff --git a/tests/scryer/src_tests.rs b/tests/scryer/src_tests.rs
index ba68e5dd..a3d6ddbf 100644
--- a/tests/scryer/src_tests.rs
+++ b/tests/scryer/src_tests.rs
@@ -1,32 +1,37 @@
-use crate::helper::{load_module_test, run_top_level_test_with_args};
+use crate::helper::load_module_test;
use serial_test::serial;
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn builtins() {
load_module_test("src/tests/builtins.pl", "");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn call_with_inference_limit() {
load_module_test("src/tests/call_with_inference_limit.pl", "");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn facts() {
load_module_test("src/tests/facts.pl", "");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn hello_world() {
load_module_test("src/tests/hello_world.pl", "Hello World!\n");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn syntax_error() {
load_module_test(
"tests-pl/syntax_error.pl",
@@ -36,18 +41,21 @@ fn syntax_error() {
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn predicates() {
load_module_test("src/tests/predicates.pl", "");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn rules() {
load_module_test("src/tests/rules.pl", "");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn setup_call_cleanup_load() {
load_module_test(
"src/tests/setup_call_cleanup.pl",
@@ -55,59 +63,16 @@ fn setup_call_cleanup_load() {
);
}
-#[test]
-fn setup_call_cleanup_process() {
- run_top_level_test_with_args(
- ["src/tests/setup_call_cleanup.pl", "-f", "-g", "halt"],
- "",
- "1+21+31+2>A+B1+G1+2>41+2>B1+2>31+2>31+2>4ba",
- );
-}
-
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn clpz_load() {
load_module_test("src/tests/clpz/test_clpz.pl", "");
}
#[serial]
#[test]
+#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
fn iso_conformity_tests() {
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",
- );
-}
-
-#[test]
-fn ground_tests() {
- run_top_level_test_with_args(
- ["src/tests/ground.pl", "-f", "-g", "main_quiet"],
- "",
- "All tests passed",
- );
-}
-
-#[test]
-fn term_variables_tests() {
- run_top_level_test_with_args(
- ["src/tests/term_variables.pl", "-f", "-g", "main_quiet"],
- "",
- "All tests passed",
- );
-}
-
-#[test]
-fn acyclic_term_tests() {
- run_top_level_test_with_args(
- ["src/tests/acyclic_term.pl", "-f", "-g", "main_quiet"],
- "",
- "All tests passed",
- );
-}