Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e54b1406c | ||
|
|
f52c9772a7 | ||
|
|
ea5203d8c3 | ||
|
|
0fad2f9953 | ||
|
|
d3a9392421 | ||
|
|
208927544d | ||
|
|
7621155a89 | ||
|
|
4ddc4ebf46 | ||
|
|
786f0b5ca2 | ||
|
|
b4ff429bfa | ||
|
|
f2cf0ec459 | ||
|
|
0380d70a46 | ||
|
|
28099b9812 | ||
|
|
2ce4f602c0 | ||
|
|
5e81fb4754 | ||
|
|
c9f1a95343 | ||
|
|
97d8d07947 | ||
|
|
4f0adad78e | ||
|
|
0499005db5 | ||
|
|
aedffb3cfe | ||
|
|
fff96e69db | ||
|
|
abc99c9dd8 | ||
|
|
6e4b76a3b4 | ||
|
|
92d8642133 | ||
|
|
184124586b | ||
|
|
4d32b6976a | ||
|
|
45a99e576d | ||
|
|
fac6d54986 | ||
|
|
036c35729c | ||
|
|
e442fddc66 | ||
|
|
a3c3afba48 | ||
|
|
794ceac440 | ||
|
|
6299d41cda | ||
|
|
2e5ce0249e | ||
|
|
560298655b | ||
|
|
4086df27b2 | ||
|
|
d76ae413c4 | ||
|
|
8b1df2e9ca | ||
|
|
c8855f97e8 | ||
|
|
bbf1aa1668 | ||
|
|
141f3bcec3 | ||
|
|
8f11fd7c62 | ||
|
|
9f960c25a5 | ||
|
|
11a616917a | ||
|
|
a89f03f27d | ||
|
|
3faf36440c | ||
|
|
45d4f46024 | ||
|
|
896f2aeb74 | ||
|
|
7de39611f3 | ||
|
|
7e6be23287 | ||
|
|
cac76d4739 | ||
|
|
194e5dc94e | ||
|
|
f7629362d7 | ||
|
|
ea0c396114 | ||
|
|
057e2d8056 | ||
|
|
487fe21e25 | ||
|
|
54dce9b60e | ||
|
|
f09a3142a6 | ||
|
|
121c8d8a48 | ||
|
|
b9561ec8db | ||
|
|
b1d8eff019 | ||
|
|
f9c4a40d60 | ||
|
|
8e318f76a7 | ||
|
|
7d21ea93a6 | ||
|
|
8630ba4a2d | ||
|
|
17a448e045 | ||
|
|
7ff11dce35 | ||
|
|
e2a4854bcf | ||
|
|
bef96e231d | ||
|
|
325df8a6e3 | ||
|
|
3620f72b6c | ||
|
|
42a90b2d40 | ||
|
|
97aab6950c | ||
|
|
31258247b3 | ||
|
|
beed4e8aa8 | ||
|
|
c60a0bc062 | ||
|
|
733c2d4152 | ||
|
|
79b5857f72 | ||
|
|
7260eba26a | ||
|
|
7e7a1b2caf | ||
|
|
99181e3302 | ||
|
|
d57d2b96d6 | ||
|
|
24bed8c548 | ||
|
|
6c9e704aa8 | ||
|
|
d3eb31e4c3 | ||
|
|
698b01f85a | ||
|
|
4c88e97330 | ||
|
|
25babff827 | ||
|
|
23e833c69e | ||
|
|
22bb3fe876 | ||
|
|
eee10d3ee7 | ||
|
|
c7591045af | ||
|
|
6ddfef6383 | ||
|
|
9852e30b39 | ||
|
|
2d3ce32314 | ||
|
|
d8e0bea110 | ||
|
|
b2cf6a6ea8 | ||
|
|
2ebcd673c8 | ||
|
|
aa5f186a96 | ||
|
|
934f73f696 | ||
|
|
993c6f0e7b | ||
|
|
1d79e22468 | ||
|
|
8ba92d8b99 | ||
|
|
af23258152 | ||
|
|
b2e50b42a3 | ||
|
|
003b4d0218 | ||
|
|
545472f9c4 | ||
|
|
8f781c27f9 | ||
|
|
589dc34b99 | ||
|
|
564622e38b | ||
|
|
d3744d6f66 | ||
|
|
2613ef0633 | ||
|
|
be3cdcd71a | ||
|
|
d48ac09e25 | ||
|
|
e5a0ba7bf3 |
333
Cargo.lock
generated
333
Cargo.lock
generated
@@ -1,5 +1,10 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "arc-swap"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
@@ -24,7 +29,7 @@ version = "0.3.35"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
"backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -48,7 +53,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.1.0"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -73,7 +78,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.7"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -81,7 +86,7 @@ name = "cloudabi"
|
|||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -94,16 +99,39 @@ name = "crossbeam-utils"
|
|||||||
version = "0.6.6"
|
version = "0.6.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossterm_winapi 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"signal-hook 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm_winapi"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -112,7 +140,7 @@ name = "dirs-sys"
|
|||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -148,6 +176,40 @@ name = "fuchsia-cprng"
|
|||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon-sys"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "git-version"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"git-version-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "git-version-macro"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gmp-mpfr-sys"
|
name = "gmp-mpfr-sys"
|
||||||
version = "1.1.14"
|
version = "1.1.14"
|
||||||
@@ -162,6 +224,23 @@ name = "indexmap"
|
|||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iovec"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kernel32-sys"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -172,7 +251,7 @@ name = "lexical"
|
|||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -181,7 +260,7 @@ name = "lexical-core"
|
|||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"stackvector 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"stackvector 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -192,12 +271,20 @@ name = "libc"
|
|||||||
version = "0.2.62"
|
version = "0.2.62"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -210,14 +297,53 @@ name = "memchr"
|
|||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.6.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miow"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "net2"
|
||||||
|
version = "0.2.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -227,9 +353,9 @@ name = "nix"
|
|||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -306,6 +432,33 @@ dependencies = [
|
|||||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-hack"
|
||||||
|
version = "0.5.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "0.4.30"
|
version = "0.4.30"
|
||||||
@@ -314,9 +467,17 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prolog_parser"
|
name = "prolog_parser"
|
||||||
version = "0.8.40"
|
version = "0.8.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -334,6 +495,14 @@ dependencies = [
|
|||||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -373,14 +542,6 @@ name = "redox_syscall"
|
|||||||
version = "0.1.51"
|
version = "0.1.51"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_termios"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -422,9 +583,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustyline"
|
name = "rustyline"
|
||||||
version = "5.0.3"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -441,25 +603,55 @@ name = "ryu"
|
|||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.118"
|
version = "0.8.118"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crossterm 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"downcast 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"downcast 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"git-version 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"prolog_parser 0.8.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"prolog_parser 0.8.49 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustyline 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
@@ -468,6 +660,11 @@ dependencies = [
|
|||||||
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stackvector"
|
name = "stackvector"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -491,6 +688,16 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "synstructure"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
@@ -502,16 +709,6 @@ dependencies = [
|
|||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "termion"
|
|
||||||
version = "1.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@@ -527,6 +724,11 @@ name = "unicode-xid"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode_reader"
|
name = "unicode_reader"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@@ -554,6 +756,11 @@ name = "void"
|
|||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
@@ -563,6 +770,11 @@ dependencies = [
|
|||||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-build"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -573,36 +785,58 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ws2_32-sys"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
|
"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff"
|
||||||
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
|
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
|
||||||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
||||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||||
"checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55"
|
"checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55"
|
||||||
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
|
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
|
||||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
"checksum blake2b_simd 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bf775a81bb2d464e20ff170ac20316c7b08a43d11dbc72f0f82e8e8d3d6d0499"
|
"checksum blake2b_simd 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bf775a81bb2d464e20ff170ac20316c7b08a43d11dbc72f0f82e8e8d3d6d0499"
|
||||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||||
"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
|
"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
|
||||||
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
|
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
|
"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
|
||||||
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||||
|
"checksum crossterm 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8a3223215bc00c666d6be730e88aef245ad4a4f837e87a16c347e8acf701643"
|
||||||
|
"checksum crossterm_winapi 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "057b7146d02fb50175fd7dbe5158f6097f33d02831f43b4ee8ae4ddf67b68f5c"
|
||||||
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||||
"checksum downcast 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d"
|
"checksum downcast 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d"
|
||||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
|
"checksum git-version 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "94918e83f1e01dedc2e361d00ce9487b14c58c7f40bab148026fa39d42cb41e2"
|
||||||
|
"checksum git-version-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "34a97a52fdee1870a34fa6e4b77570cba531b27d1838874fef4429a791a3d657"
|
||||||
"checksum gmp-mpfr-sys 1.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72592cd7513feefa5e41414825c42e839120d2f09e10c6094105d066072955fb"
|
"checksum gmp-mpfr-sys 1.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72592cd7513feefa5e41414825c42e839120d2f09e10c6094105d066072955fb"
|
||||||
"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356"
|
"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356"
|
||||||
|
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||||
|
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
"checksum lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c106ed999697325a540c43d66a8d5175668cd96d7eb0bdba03a3bd98256cd698"
|
"checksum lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c106ed999697325a540c43d66a8d5175668cd96d7eb0bdba03a3bd98256cd698"
|
||||||
"checksum lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e82e023e062f1d25f807ad182008fba1b46538e999f908a08cc0c29e084462e"
|
"checksum lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e82e023e062f1d25f807ad182008fba1b46538e999f908a08cc0c29e084462e"
|
||||||
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
||||||
|
"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b"
|
||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||||
|
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
||||||
|
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||||
|
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||||
"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
|
"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
|
||||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||||
@@ -613,35 +847,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||||
"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6"
|
"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6"
|
||||||
"checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
|
"checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
|
||||||
|
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
|
||||||
|
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
|
||||||
|
"checksum proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420"
|
||||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||||
"checksum prolog_parser 0.8.40 (registry+https://github.com/rust-lang/crates.io-index)" = "013131c03328aef02b069e6b325b01fb47597034af169b8b8a1bb8f2cfab0868"
|
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
||||||
|
"checksum prolog_parser 0.8.49 (registry+https://github.com/rust-lang/crates.io-index)" = "82f46113e58039861f82f6b6cdaca94c0997eda2c7317a4c4f13d549c4601eec"
|
||||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||||
|
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
|
"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
|
||||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
|
||||||
"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
|
"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
|
||||||
"checksum ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6"
|
"checksum ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6"
|
||||||
"checksum rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "592f3a1bba452fcfb91127354012c2b3aa580b266caef1923b16638057c038b5"
|
"checksum rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "592f3a1bba452fcfb91127354012c2b3aa580b266caef1923b16638057c038b5"
|
||||||
"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
|
"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
|
||||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||||
"checksum rustyline 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4795e277e6e57dec9df62b515cd4991371daa80e8dc8d80d596e58722b89c417"
|
"checksum rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de64be8eecbe428b6924f1d8430369a01719fbb182c26fa431ddbb0a95f5315d"
|
||||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||||
|
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
"checksum signal-hook 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "10b9f3a1686a29f53cfd91ee5e3db3c12313ec02d33765f02c1a9645a1811e2c"
|
||||||
|
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
||||||
|
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
||||||
|
"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc"
|
||||||
"checksum stackvector 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c049c77bf85fbc036484c97b008276d539d9ebff9dfbde37b632ebcd5b8746b6"
|
"checksum stackvector 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c049c77bf85fbc036484c97b008276d539d9ebff9dfbde37b632ebcd5b8746b6"
|
||||||
"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5"
|
"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5"
|
||||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||||
|
"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
|
||||||
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
|
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
|
||||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
|
||||||
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
|
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
|
||||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
"checksum unicode_reader 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f886d405a2be65db804cb1088f969dbd99528a9eec9bcf941584b17de4cd3034"
|
"checksum unicode_reader 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f886d405a2be65db804cb1088f969dbd99528a9eec9bcf941584b17de4cd3034"
|
||||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||||
"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
|
"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||||
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||||
|
|||||||
@@ -16,16 +16,17 @@ default = ["rug", "prolog_parser/rug"]
|
|||||||
num = ["num-rug-adapter", "prolog_parser/num"]
|
num = ["num-rug-adapter", "prolog_parser/num"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
crossterm = "0.16.0"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
downcast = "0.10.0"
|
downcast = "0.10.0"
|
||||||
|
git-version = "0.3.4"
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2.62"
|
libc = "0.2.62"
|
||||||
nix = "0.15.0"
|
nix = "0.15.0"
|
||||||
num-rug-adapter = { optional = true, version = "0.1.1" }
|
num-rug-adapter = { optional = true, version = "0.1.1" }
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = { version = "0.8.40", default-features = false }
|
prolog_parser = { version = "0.8.49", default-features = false }
|
||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
rug = { version = "1.4.0", optional = true }
|
rug = { version = "1.4.0", optional = true }
|
||||||
rustyline = "5.0.3"
|
rustyline = "6.0.0"
|
||||||
termion = "1.4.0"
|
|
||||||
163
README.md
163
README.md
@@ -30,7 +30,7 @@ Extend Scryer Prolog to include the following, among other features:
|
|||||||
- [x] Built-in predicates for list processing and top-level declarative
|
- [x] Built-in predicates for list processing and top-level declarative
|
||||||
control (`setup_call_cleanup/3`, `call_with_inference_limit/3`,
|
control (`setup_call_cleanup/3`, `call_with_inference_limit/3`,
|
||||||
etc.)
|
etc.)
|
||||||
- [x] ~~Default representation of strings as list of chars, using a packed
|
- [x] ~~Default representation of strings as lists of characters, using a packed
|
||||||
internal representation.~~
|
internal representation.~~
|
||||||
- [x] `term_expansion/2` and `goal_expansion/2`.
|
- [x] `term_expansion/2` and `goal_expansion/2`.
|
||||||
- [x] Definite Clause Grammars.
|
- [x] Definite Clause Grammars.
|
||||||
@@ -52,11 +52,11 @@ Extend Scryer Prolog to include the following, among other features:
|
|||||||
"Delimited Continuations for Prolog").
|
"Delimited Continuations for Prolog").
|
||||||
- [x] Tabling library based on delimited continuations
|
- [x] Tabling library based on delimited continuations
|
||||||
(documented in "Tabling as a Library with Delimited Control").
|
(documented in "Tabling as a Library with Delimited Control").
|
||||||
- [x] A _redone_ representation of strings as difference list of
|
- [x] A _redone_ representation of strings as difference lists of
|
||||||
chars, using a packed internal representation.
|
characters, using a packed internal representation.
|
||||||
- [ ] clp(B) and clp(ℤ) as builtin libraries (_in progress_).
|
- [x] clp(B) and clp(ℤ) as builtin libraries.
|
||||||
- [ ] Streams and predicates for stream control (_in progress_).
|
- [ ] Streams and predicates for stream control (_in progress_).
|
||||||
- [ ] An incremental compacting garbage collector satisfying the five
|
- [ ] A compacting garbage collector satisfying the five
|
||||||
properties of "Precise Garbage Collection in Prolog."
|
properties of "Precise Garbage Collection in Prolog."
|
||||||
- [ ] Mode declarations.
|
- [ ] Mode declarations.
|
||||||
|
|
||||||
@@ -92,8 +92,14 @@ strings.
|
|||||||
|
|
||||||
First, install the latest stable version of
|
First, install the latest stable version of
|
||||||
[Rust](https://www.rust-lang.org/en-US/install.html) using your
|
[Rust](https://www.rust-lang.org/en-US/install.html) using your
|
||||||
preferred method. Then install Scryer Prolog with cargo,
|
preferred method. Scryer tends to use features from newer Rust
|
||||||
like so:
|
releases, whereas Rust packages in Linux distributions, Macports,
|
||||||
|
etc. tend to lag behind. [rustup](http://rustup.rs) will keep your
|
||||||
|
Rust updated to the latest stable release; any existing Rust
|
||||||
|
distribution should be uninstalled from your system before rustup is
|
||||||
|
used.
|
||||||
|
|
||||||
|
Scryer Prolog can be installed with cargo, like so:
|
||||||
|
|
||||||
```
|
```
|
||||||
$> cargo install scryer-prolog
|
$> cargo install scryer-prolog
|
||||||
@@ -117,11 +123,6 @@ $> cargo run [--release]
|
|||||||
The optional `--release` flag will perform various optimizations,
|
The optional `--release` flag will perform various optimizations,
|
||||||
producing a faster executable.
|
producing a faster executable.
|
||||||
|
|
||||||
Note on compatibility: Scryer Prolog should work on Linux, Mac OS X,
|
|
||||||
and BSD variants on which Rust runs. Windows support hinges on
|
|
||||||
rustyline and Termion being functional in that environment, which to
|
|
||||||
my knowledge is not presently the case.
|
|
||||||
|
|
||||||
## Tutorial
|
## Tutorial
|
||||||
To enter a multi-clause predicate, the directive "[user]" is used.
|
To enter a multi-clause predicate, the directive "[user]" is used.
|
||||||
|
|
||||||
@@ -155,11 +156,10 @@ Wildcards work as well:
|
|||||||
member(X, [X|_]).
|
member(X, [X|_]).
|
||||||
member(X, [_|Xs]) :- member(X, Xs).
|
member(X, [_|Xs]) :- member(X, Xs).
|
||||||
?- member(X, [a, b, c]).
|
?- member(X, [a, b, c]).
|
||||||
true .
|
X = a
|
||||||
X = a ;
|
; X = b
|
||||||
X = b ;
|
; X = c
|
||||||
X = c ;
|
; false.
|
||||||
false.
|
|
||||||
```
|
```
|
||||||
and so do conjunctive queries:
|
and so do conjunctive queries:
|
||||||
```
|
```
|
||||||
@@ -169,10 +169,9 @@ f(X) :- g(X).
|
|||||||
g(x). g(y). g(z).
|
g(x). g(y). g(z).
|
||||||
h(call(f, X)).
|
h(call(f, X)).
|
||||||
?- h(X), X.
|
?- h(X), X.
|
||||||
true .
|
X = call(f,x)
|
||||||
X = call(f, x) ;
|
; X = call(f,y)
|
||||||
X = call(f, y) ;
|
; X = call(f,z).
|
||||||
X = call(f, z).
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the values of variables belonging to successful queries are
|
Note that the values of variables belonging to successful queries are
|
||||||
@@ -190,46 +189,128 @@ Scryer supports dynamic operators. Using the built-in
|
|||||||
arithmetic operators with the usual precedences,
|
arithmetic operators with the usual precedences,
|
||||||
|
|
||||||
```
|
```
|
||||||
?- write_canonical(-5 + 3 - (2 * 4) // 8).
|
?- write_canonical(-5 + 3 - (2 * 4) // 8), nl.
|
||||||
-(+(-(5), 3), //(*(2, 4), 8))
|
-(+(-5,3),//(*(2,4),8))
|
||||||
true.
|
true.
|
||||||
```
|
```
|
||||||
|
|
||||||
New operators can be defined using the `op` declaration.
|
New operators can be defined using the `op` declaration.
|
||||||
|
|
||||||
### Partial strings
|
### Strings and partial strings
|
||||||
|
|
||||||
Scryer has three specialized non-ISO predicates for handling so-called
|
In Scryer Prolog, the default value of the Prolog flag `double_quotes`
|
||||||
"partial strings." Partial strings imitate difference lists of
|
is `chars`, which is also the recommended setting. This means that
|
||||||
characters, but their characters are packed in UTF-8 format, a much
|
double-quoted strings are interpreted as lists of *characters*, in the
|
||||||
more efficient alternative to how lists of characters are represented
|
tradition of Marseille Prolog.
|
||||||
in many other Prologs.
|
|
||||||
|
|
||||||
To use partial strings, the `non_iso` library must be loaded:
|
For example, the following query succeeds:
|
||||||
|
|
||||||
`?- use_module(library(non_iso)).`
|
```
|
||||||
|
?- "abc" = [a,b,c].
|
||||||
|
true.
|
||||||
|
```
|
||||||
|
|
||||||
If `X` is a free variable, the query
|
Internally, strings are represented very compactly in packed
|
||||||
|
UTF-8 encoding. A naive representation of strings as lists of
|
||||||
|
characters would use one memory cell per character, one
|
||||||
|
memory cell per list constructor, and one memory cell for
|
||||||
|
each tail that occurs in the list. Since one memory cell takes
|
||||||
|
8 bytes on 64-bit machines, the packed representation used by
|
||||||
|
Scryer Prolog yields an up to **24-fold reduction** of
|
||||||
|
memory usage, and corresponding reduction of memory accesses when
|
||||||
|
creating and processing strings.
|
||||||
|
|
||||||
`?- partial_string("abc", X, _), X = [a, b, c | Y], partial_string(X),
|
Scryer Prolog uses the same efficient encoding for *partial* strings,
|
||||||
partial_string_tail(X, Tail), Tail == Y.`
|
which appear to Prolog code as partial lists of characters. The
|
||||||
|
predicate `partial_string/3` from `library(iso_ext)` lets you
|
||||||
|
construct partial strings explicitly. For example:
|
||||||
|
|
||||||
will succeed, posting:
|
```
|
||||||
|
?- partial_string("abc", Ls0, Ls).
|
||||||
|
Ls0 = [a,b,c|Ls].
|
||||||
|
```
|
||||||
|
|
||||||
`Tail = Y, X = [a,b,c|Y].`
|
In this case, and as the answer illustrates, `Ls0` is
|
||||||
|
indistinguishable from a partial list with tail `Ls`, while
|
||||||
|
the efficient packed representation is used internally.
|
||||||
|
|
||||||
By all appearances, partial strings are plain Prolog lists.
|
An important design goal of Scryer Prolog is to *automatically* use
|
||||||
|
the efficient string representation whenever possible. Therefore, it
|
||||||
|
is only very rarely necessary to use `partial_string/3` explicitly. In
|
||||||
|
the above example, posting <tt>Ls0 = [a,b,c|Ls]</tt> yields
|
||||||
|
the exact same internal representation, and has the advantage that
|
||||||
|
only the standard predicate `(=)/2` is used.
|
||||||
|
|
||||||
|
Definite clause grammars as provided by `library(dcgs)` are ideally
|
||||||
|
suited for reasoning about strings.
|
||||||
|
|
||||||
### Modules
|
### Modules
|
||||||
|
|
||||||
Scryer has a simple predicate-based module system. It provides a
|
Scryer has a simple predicate-based module system. It provides a
|
||||||
way to separate units of code into distinct namespaces, for both
|
way to separate units of code into distinct namespaces, for both
|
||||||
predicates and operators. See the files `src/prolog/lib/*.pl` for
|
predicates and operators. See the files
|
||||||
|
[`src/prolog/lib/*.pl`](src/prolog/lib) for
|
||||||
examples.
|
examples.
|
||||||
|
|
||||||
At the time of this writing, several control and list processing
|
At the time of this writing, many predicates reside in their own
|
||||||
operators and predicates are hidden in their own modules that have not
|
modules that need to be imported before they can be used.
|
||||||
been exported to the toplevel. To export them, write
|
The modules that ship with Scryer Prolog are also called
|
||||||
|
*library* modules or *libraries*, and include:
|
||||||
|
|
||||||
|
* [`lists`](src/prolog/lib/lists.pl)
|
||||||
|
providing `length/2`, `member/2`, `select/3`, `append/[2,3]`,
|
||||||
|
`foldl/[4,5]`, `maplist/[2-9]`, `same_length/2`, `transpose/2` etc.
|
||||||
|
* [`dcgs`](src/prolog/lib/dcgs.pl)
|
||||||
|
Definite Clause Grammars (DCGs), a built-in grammar mechanism
|
||||||
|
that uses the operator `(-->)/2` to define grammar rules,
|
||||||
|
and the predicates `phrase/[2,3]` to invoke them.
|
||||||
|
* [`dif`](src/prolog/lib/dif.pl)
|
||||||
|
The predicate `dif/2` provides declarative disequality:
|
||||||
|
It is true if and only if its arguments are different, and
|
||||||
|
delays the test until a sound decision can be made.
|
||||||
|
* [`reif`](src/prolog/lib/reif.pl)
|
||||||
|
providing `if_/3`, `tfilter/3` and related predicates
|
||||||
|
as described in *Indexing dif/2*.
|
||||||
|
* [`clpz`](src/prolog/lib/clpz.pl)
|
||||||
|
CLP(ℤ): Constraint Logic Programming over Integers,
|
||||||
|
providing declarative integer arithmetic via `(#=)/2`, `(#\=)/2`,
|
||||||
|
`(#>=)/2` etc., and various global constraints and
|
||||||
|
enumeration predicates for solving combinatorial tasks.
|
||||||
|
* [`pairs`](src/prolog/lib/pairs.pl)
|
||||||
|
By convention, *pairs* are Prolog terms with
|
||||||
|
principal functor `(-)/2`, written as `Key-Value`.
|
||||||
|
This library provides `pairs_keys_values/3`,
|
||||||
|
`pairs_keys/2`, and other predicates to reason about pairs.
|
||||||
|
* [`si`](src/prolog/lib/si.pl)
|
||||||
|
The predicates `atom_si/1`, `integer_si/1`, `atomic_si/1`
|
||||||
|
and `list_si/1` implement sound type checks. They raise
|
||||||
|
instantiation errors if no decision can be made.
|
||||||
|
They are declarative replacements for logically flawed
|
||||||
|
lower-level type tests. For instance, instead of `integer(X)`,
|
||||||
|
write `integer_si(X)` to ensure soundness of your programs.
|
||||||
|
"si" stands for *sufficiently instantiated*, and also for
|
||||||
|
*sound inference*.
|
||||||
|
* [`error`](src/prolog/lib/error.pl)
|
||||||
|
`must_be/2` and `can_be/2` complement the type checks provided
|
||||||
|
by `library(si)`, and are especially useful for Prolog library
|
||||||
|
authors.
|
||||||
|
* [`tabling`](src/prolog/lib/tabling.pl)
|
||||||
|
The operator `(table)/1` is used in directives that prepare
|
||||||
|
predicates for tabled execution (SLG resolution).
|
||||||
|
* [`format`](src/prolog/lib/format.pl)
|
||||||
|
The nonterminal `format_//2` is used to describe formatted output,
|
||||||
|
arranging arguments according to a given format string.
|
||||||
|
The predicate `format/2` is provided for impure output.
|
||||||
|
* [`assoc`](src/prolog/lib/assoc.pl)
|
||||||
|
providing `empty_assoc/1`, `get_assoc/3`, `put_assoc/4` etc.
|
||||||
|
to manage elements in AVL trees which ensure
|
||||||
|
*O*(log(*N*)) access.
|
||||||
|
* [`clpb`](src/prolog/lib/clpb.pl)
|
||||||
|
CLP(B): Constraint Logic Programming over Boolean variables,
|
||||||
|
a BDD-based SAT solver provided via the predicates
|
||||||
|
`sat/1`, `taut/2`, `labeling/1` etc.
|
||||||
|
|
||||||
|
To use predicates provided by the `lists` library, write:
|
||||||
|
|
||||||
```
|
```
|
||||||
?- use_module(library(lists)).
|
?- use_module(library(lists)).
|
||||||
|
|||||||
6
build.rs
6
build.rs
@@ -52,5 +52,9 @@ fn main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
libraries.write_all(b"\n\n m\n };
|
libraries.write_all(b"\n\n m\n };
|
||||||
}").unwrap();
|
}\n").unwrap();
|
||||||
|
|
||||||
|
libraries.write_all(b"\npub static PROJECT_DIR: &'static str = \"").unwrap();
|
||||||
|
libraries.write_all(env::var("CARGO_MANIFEST_DIR").unwrap().as_bytes()).unwrap();
|
||||||
|
libraries.write_all(b"\";\n").unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/main.rs
13
src/main.rs
@@ -1,5 +1,7 @@
|
|||||||
|
extern crate crossterm;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate downcast;
|
extern crate downcast;
|
||||||
|
extern crate git_version;
|
||||||
extern crate indexmap;
|
extern crate indexmap;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
@@ -9,15 +11,17 @@ extern crate nix;
|
|||||||
extern crate prolog_parser;
|
extern crate prolog_parser;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate ref_thread_local;
|
extern crate ref_thread_local;
|
||||||
extern crate termion;
|
|
||||||
|
|
||||||
|
use git_version::git_version;
|
||||||
use nix::sys::signal;
|
use nix::sys::signal;
|
||||||
|
|
||||||
mod prolog;
|
mod prolog;
|
||||||
|
|
||||||
use crate::prolog::machine::*;
|
use crate::prolog::machine::*;
|
||||||
|
use crate::prolog::machine::streams::*;
|
||||||
use crate::prolog::read::*;
|
use crate::prolog::read::*;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
extern fn handle_sigint(signal: libc::c_int) {
|
extern fn handle_sigint(signal: libc::c_int) {
|
||||||
@@ -31,6 +35,11 @@ fn main() {
|
|||||||
let handler = signal::SigHandler::Handler(handle_sigint);
|
let handler = signal::SigHandler::Handler(handle_sigint);
|
||||||
unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap();
|
unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap();
|
||||||
|
|
||||||
let mut wam = Machine::new(readline::input_stream());
|
if env::args().skip(1).any(|a| a == "-v" || a == "--version") {
|
||||||
|
println!("{:}", git_version!());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut wam = Machine::new(readline::input_stream(), Stream::stdout());
|
||||||
wam.run_top_level();
|
wam.run_top_level();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::prolog::forms::*;
|
|||||||
use crate::prolog::instructions::*;
|
use crate::prolog::instructions::*;
|
||||||
use crate::prolog::iterators::*;
|
use crate::prolog::iterators::*;
|
||||||
|
|
||||||
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_errors::*;
|
use crate::prolog::machine::machine_errors::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ use crate::prolog::rug::{Assign, Integer, Rational};
|
|||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::{max, min, Ordering};
|
use std::cmp::{max, min, Ordering};
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::f64;
|
use std::f64;
|
||||||
use std::num::FpCategory;
|
use std::num::FpCategory;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||||
@@ -262,6 +264,9 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
|
|
||||||
fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> {
|
fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> {
|
||||||
match c {
|
match c {
|
||||||
|
&Constant::Fixnum(n) => self
|
||||||
|
.interm
|
||||||
|
.push(ArithmeticTerm::Number(Number::Fixnum(n))),
|
||||||
&Constant::Integer(ref n) => self
|
&Constant::Integer(ref n) => self
|
||||||
.interm
|
.interm
|
||||||
.push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
|
.push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
|
||||||
@@ -316,18 +321,25 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// integer division rounding function -- 9.1.3.1.
|
// integer division rounding function -- 9.1.3.1.
|
||||||
pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> {
|
pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Number> {
|
||||||
match n {
|
match n {
|
||||||
&Number::Integer(ref n) => RefOrOwned::Borrowed(n),
|
&Number::Integer(_) => {
|
||||||
|
RefOrOwned::Borrowed(n)
|
||||||
|
}
|
||||||
&Number::Float(OrderedFloat(f)) => {
|
&Number::Float(OrderedFloat(f)) => {
|
||||||
RefOrOwned::Owned(Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0)))
|
RefOrOwned::Owned(Number::from(
|
||||||
|
Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
&Number::Fixnum(n) => {
|
||||||
|
RefOrOwned::Owned(Number::from(n))
|
||||||
}
|
}
|
||||||
&Number::Rational(ref r) => {
|
&Number::Rational(ref r) => {
|
||||||
let r_ref = r.fract_floor_ref();
|
let r_ref = r.fract_floor_ref();
|
||||||
let (mut fract, mut floor) = (Rational::new(), Integer::new());
|
let (mut fract, mut floor) = (Rational::new(), Integer::new());
|
||||||
|
|
||||||
(&mut fract, &mut floor).assign(r_ref);
|
(&mut fract, &mut floor).assign(r_ref);
|
||||||
RefOrOwned::Owned(floor)
|
|
||||||
|
RefOrOwned::Owned(Number::from(floor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,6 +347,7 @@ pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> {
|
|||||||
// floating point rounding function -- 9.1.4.1.
|
// floating point rounding function -- 9.1.4.1.
|
||||||
pub fn rnd_f(n: &Number) -> f64 {
|
pub fn rnd_f(n: &Number) -> f64 {
|
||||||
match n {
|
match n {
|
||||||
|
&Number::Fixnum(n) => n as f64,
|
||||||
&Number::Integer(ref n) => n.to_f64(),
|
&Number::Integer(ref n) => n.to_f64(),
|
||||||
&Number::Float(OrderedFloat(f)) => f,
|
&Number::Float(OrderedFloat(f)) => f,
|
||||||
&Number::Rational(ref r) => r.to_f64(),
|
&Number::Rational(ref r) => r.to_f64(),
|
||||||
@@ -370,22 +383,32 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn float_fn_to_f(n: isize) -> Result<f64, EvalError> {
|
||||||
|
classify_float(n as f64, rnd_f)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn float_i_to_f(n: &Integer) -> Result<f64, EvalError> {
|
fn float_i_to_f(n: &Integer) -> Result<f64, EvalError> {
|
||||||
classify_float(n.to_f64(), rnd_f)
|
classify_float(n.to_f64(), rnd_f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn float_r_to_f(r: &Rational) -> Result<f64, EvalError> {
|
fn float_r_to_f(r: &Rational) -> Result<f64, EvalError> {
|
||||||
classify_float(r.to_f64(), rnd_f)
|
classify_float(r.to_f64(), rnd_f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn add_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
|
fn add_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
|
||||||
Ok(OrderedFloat(classify_float(f1 + f2, rnd_f)?))
|
Ok(OrderedFloat(classify_float(f1 + f2, rnd_f)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn mul_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
|
fn mul_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
|
||||||
Ok(OrderedFloat(classify_float(f1 * f2, rnd_f)?))
|
Ok(OrderedFloat(classify_float(f1 * f2, rnd_f)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn div_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
|
fn div_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
|
||||||
if FpCategory::Zero == f2.classify() {
|
if FpCategory::Zero == f2.classify() {
|
||||||
Err(EvalError::ZeroDivisor)
|
Err(EvalError::ZeroDivisor)
|
||||||
@@ -399,14 +422,35 @@ impl Add<Number> for Number {
|
|||||||
|
|
||||||
fn add(self, rhs: Number) -> Self::Output {
|
fn add(self, rhs: Number) -> Self::Output {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 + n2)), // add_i
|
(Number::Fixnum(n1), Number::Fixnum(n2)) => {
|
||||||
|
Ok(if let Some(result) = n1.checked_add(n2) {
|
||||||
|
Number::Fixnum(result)
|
||||||
|
} else {
|
||||||
|
Number::from(Integer::from(n1) + Integer::from(n2))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Integer(n2)) |
|
||||||
|
(Number::Integer(n2), Number::Fixnum(n1)) => {
|
||||||
|
Ok(Number::from(Integer::from(n1) + &*n2))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Rational(n2)) |
|
||||||
|
(Number::Rational(n2), Number::Fixnum(n1)) => {
|
||||||
|
Ok(Number::from(Rational::from(n1) + &*n2))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) |
|
||||||
|
(Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => {
|
||||||
|
Ok(Number::Float(add_f(float_fn_to_f(n1)?, n2)?))
|
||||||
|
}
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::from(Integer::from(&*n1) + &*n2)) // add_i
|
||||||
|
}
|
||||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||||
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
|
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Rational(n2))
|
(Number::Integer(n1), Number::Rational(n2))
|
||||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||||
Ok(Number::Rational(Rational::from(n1) + n2))
|
Ok(Number::from(Rational::from(&*n1) + &*n2))
|
||||||
}
|
}
|
||||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||||
@@ -415,7 +459,9 @@ impl Add<Number> for Number {
|
|||||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||||
Ok(Number::Float(add_f(f1, f2)?))
|
Ok(Number::Float(add_f(f1, f2)?))
|
||||||
}
|
}
|
||||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 + r2)),
|
(Number::Rational(r1), Number::Rational(r2)) => {
|
||||||
|
Ok(Number::from(Rational::from(&*r1) + &*r2))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,9 +471,10 @@ impl Neg for Number {
|
|||||||
|
|
||||||
fn neg(self) -> Self::Output {
|
fn neg(self) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
Number::Integer(n) => Number::Integer(-n),
|
Number::Fixnum(n) => Number::Fixnum(-n),
|
||||||
|
Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*n))),
|
||||||
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
|
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
|
||||||
Number::Rational(r) => Number::Rational(-r),
|
Number::Rational(r) => Number::Rational(Rc::new(-Rational::from(&*r))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,14 +492,35 @@ impl Mul<Number> for Number {
|
|||||||
|
|
||||||
fn mul(self, rhs: Number) -> Self::Output {
|
fn mul(self, rhs: Number) -> Self::Output {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 * n2)), // mul_i
|
(Number::Fixnum(n1), Number::Fixnum(n2)) => {
|
||||||
|
Ok(if let Some(result) = n1.checked_mul(n2) {
|
||||||
|
Number::Fixnum(result)
|
||||||
|
} else {
|
||||||
|
Number::from(Integer::from(n1) * Integer::from(n2))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Integer(n2)) |
|
||||||
|
(Number::Integer(n2), Number::Fixnum(n1)) => {
|
||||||
|
Ok(Number::from(Integer::from(n1) * &*n2))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Rational(n2)) |
|
||||||
|
(Number::Rational(n2), Number::Fixnum(n1)) => {
|
||||||
|
Ok(Number::from(Rational::from(n1) * &*n2))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) |
|
||||||
|
(Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => {
|
||||||
|
Ok(Number::Float(mul_f(float_fn_to_f(n1)?, n2)?))
|
||||||
|
}
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::Integer(Rc::new(Integer::from(&*n1) * &*n2))) // mul_i
|
||||||
|
}
|
||||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||||
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
|
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Rational(n2))
|
(Number::Integer(n1), Number::Rational(n2))
|
||||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||||
Ok(Number::Rational(Rational::from(n1) * n2))
|
Ok(Number::Rational(Rc::new(Rational::from(&*n1) * &*n2)))
|
||||||
}
|
}
|
||||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||||
@@ -461,7 +529,9 @@ impl Mul<Number> for Number {
|
|||||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||||
Ok(Number::Float(mul_f(f1, f2)?))
|
Ok(Number::Float(mul_f(f1, f2)?))
|
||||||
}
|
}
|
||||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 * r2)),
|
(Number::Rational(r1), Number::Rational(r2)) => {
|
||||||
|
Ok(Number::Rational(Rc::new(Rational::from(&*r1) * &*r2)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,24 +541,72 @@ impl Div<Number> for Number {
|
|||||||
|
|
||||||
fn div(self, rhs: Number) -> Self::Output {
|
fn div(self, rhs: Number) -> Self::Output {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Float(div_f(
|
(Number::Fixnum(n1), Number::Fixnum(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
float_fn_to_f(n1)?,
|
||||||
|
float_fn_to_f(n2)?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
float_fn_to_f(n1)?,
|
||||||
|
float_i_to_f(&n2)?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Integer(n1), Number::Fixnum(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
float_i_to_f(&n1)?,
|
||||||
|
float_fn_to_f(n2)?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Rational(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
float_fn_to_f(n1)?,
|
||||||
|
float_r_to_f(&n2)?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Rational(n1), Number::Fixnum(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
float_r_to_f(&n1)?,
|
||||||
|
float_fn_to_f(n2)?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
float_fn_to_f(n1)?,
|
||||||
|
n2,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Float(OrderedFloat(n1)), Number::Fixnum(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
|
n1,
|
||||||
|
float_fn_to_f(n2)?,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
float_i_to_f(&n1)?,
|
float_i_to_f(&n1)?,
|
||||||
float_i_to_f(&n2)?,
|
float_i_to_f(&n2)?,
|
||||||
)?)),
|
)?))
|
||||||
|
}
|
||||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) => {
|
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) => {
|
||||||
Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?))
|
Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
(Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
(Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||||
Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?))
|
Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?))
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Rational(n2)) => Ok(Number::Float(div_f(
|
(Number::Integer(n1), Number::Rational(n2)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
float_i_to_f(&n1)?,
|
float_i_to_f(&n1)?,
|
||||||
float_r_to_f(&n2)?,
|
float_r_to_f(&n2)?,
|
||||||
)?)),
|
)?))
|
||||||
(Number::Rational(n2), Number::Integer(n1)) => Ok(Number::Float(div_f(
|
}
|
||||||
|
(Number::Rational(n2), Number::Integer(n1)) => {
|
||||||
|
Ok(Number::Float(div_f(
|
||||||
float_r_to_f(&n2)?,
|
float_r_to_f(&n2)?,
|
||||||
float_i_to_f(&n1)?,
|
float_i_to_f(&n1)?,
|
||||||
)?)),
|
)?))
|
||||||
|
}
|
||||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) => {
|
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) => {
|
||||||
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?))
|
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
@@ -506,25 +624,47 @@ impl Div<Number> for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Number {
|
||||||
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
|
match (self, rhs) {
|
||||||
|
(&Number::Fixnum(n1), &Number::Fixnum(n2)) => n1.eq(&n2),
|
||||||
|
(&Number::Fixnum(n1), &Number::Integer(ref n2)) => n1.eq(&**n2),
|
||||||
|
(&Number::Integer(ref n1), &Number::Fixnum(n2)) => (&**n1).eq(&n2),
|
||||||
|
(&Number::Fixnum(n1), &Number::Rational(ref n2)) => n1.eq(&**n2),
|
||||||
|
(&Number::Rational(ref n1), &Number::Fixnum(n2)) => (&**n1).eq(&n2),
|
||||||
|
(&Number::Fixnum(_), &Number::Float(OrderedFloat(_))) => false,
|
||||||
|
(&Number::Float(OrderedFloat(_)), &Number::Fixnum(_)) => false,
|
||||||
|
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.eq(n2),
|
||||||
|
(&Number::Integer(_), Number::Float(_)) => false,
|
||||||
|
(&Number::Float(_), &Number::Integer(_)) => false,
|
||||||
|
(&Number::Integer(_), &Number::Rational(_)) => false,
|
||||||
|
(&Number::Rational(_), &Number::Integer(_)) => false,
|
||||||
|
(&Number::Rational(_), Number::Float(_)) => false,
|
||||||
|
(&Number::Float(_), &Number::Rational(_)) => false,
|
||||||
|
(&Number::Float(f1), &Number::Float(f2)) => f1.eq(&f2),
|
||||||
|
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.eq(&r2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Number {}
|
||||||
|
|
||||||
impl PartialOrd for Number {
|
impl PartialOrd for Number {
|
||||||
fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
|
fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
|
||||||
match (self, rhs) {
|
Some(self.cmp(rhs))
|
||||||
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => Some(n1.cmp(n2)),
|
|
||||||
(&Number::Integer(_), Number::Float(_)) => Some(Ordering::Greater),
|
|
||||||
(&Number::Float(_), &Number::Integer(_)) => Some(Ordering::Less),
|
|
||||||
(&Number::Integer(_), &Number::Rational(_)) => Some(Ordering::Greater),
|
|
||||||
(&Number::Rational(_), &Number::Integer(_)) => Some(Ordering::Less),
|
|
||||||
(&Number::Rational(_), Number::Float(_)) => Some(Ordering::Greater),
|
|
||||||
(&Number::Float(_), &Number::Rational(_)) => Some(Ordering::Less),
|
|
||||||
(&Number::Float(f1), &Number::Float(f2)) => Some(f1.cmp(&f2)),
|
|
||||||
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => Some(r1.cmp(&r2)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for Number {
|
impl Ord for Number {
|
||||||
fn cmp(&self, rhs: &Number) -> Ordering {
|
fn cmp(&self, rhs: &Number) -> Ordering {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
|
(&Number::Fixnum(n1), &Number::Fixnum(n2)) => n1.cmp(&n2),
|
||||||
|
(&Number::Fixnum(n1), Number::Integer(n2)) => Integer::from(n1).cmp(&*n2),
|
||||||
|
(Number::Integer(n1), &Number::Fixnum(n2)) => (&**n1).cmp(&Integer::from(n2)),
|
||||||
|
(&Number::Fixnum(n1), Number::Rational(n2)) => Rational::from(n1).cmp(&*n2),
|
||||||
|
(Number::Rational(n1), &Number::Fixnum(n2)) => (&**n1).cmp(&Rational::from(n2)),
|
||||||
|
(&Number::Fixnum(_), &Number::Float(OrderedFloat(_))) => Ordering::Greater,
|
||||||
|
(&Number::Float(OrderedFloat(_)), &Number::Fixnum(_)) => Ordering::Less,
|
||||||
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.cmp(n2),
|
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.cmp(n2),
|
||||||
(&Number::Integer(_), Number::Float(_)) => Ordering::Greater,
|
(&Number::Integer(_), Number::Float(_)) => Ordering::Greater,
|
||||||
(&Number::Float(_), &Number::Integer(_)) => Ordering::Less,
|
(&Number::Float(_), &Number::Integer(_)) => Ordering::Less,
|
||||||
@@ -538,9 +678,81 @@ impl Ord for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<(Addr, &'a Heap)> for Number {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from((addr, heap): (Addr, &'a Heap)) -> Result<Number, Self::Error> {
|
||||||
|
match addr {
|
||||||
|
Addr::CharCode(c) => {
|
||||||
|
Ok(Number::from(c as isize))
|
||||||
|
}
|
||||||
|
Addr::Fixnum(n) => {
|
||||||
|
Ok(Number::from(n))
|
||||||
|
}
|
||||||
|
Addr::Float(n) => {
|
||||||
|
Ok(Number::Float(n))
|
||||||
|
}
|
||||||
|
Addr::Usize(n) => {
|
||||||
|
if let Ok(n) = isize::try_from(n) {
|
||||||
|
Ok(Number::from(n))
|
||||||
|
} else {
|
||||||
|
Ok(Number::from(Integer::from(n)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Con(h) => {
|
||||||
|
Number::try_from(&heap[h])
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a HeapCellValue> for Number {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: &'a HeapCellValue) -> Result<Number, Self::Error> {
|
||||||
|
match value {
|
||||||
|
HeapCellValue::Addr(addr) => {
|
||||||
|
match addr {
|
||||||
|
&Addr::CharCode(c) => {
|
||||||
|
Ok(Number::from(c as isize))
|
||||||
|
}
|
||||||
|
&Addr::Fixnum(n) => {
|
||||||
|
Ok(Number::from(n))
|
||||||
|
}
|
||||||
|
&Addr::Float(n) => {
|
||||||
|
Ok(Number::Float(n))
|
||||||
|
}
|
||||||
|
&Addr::Usize(n) => {
|
||||||
|
if let Ok(n) = isize::try_from(n) {
|
||||||
|
Ok(Number::from(n))
|
||||||
|
} else {
|
||||||
|
Ok(Number::from(Integer::from(n)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HeapCellValue::Integer(n) => {
|
||||||
|
Ok(Number::Integer(n.clone()))
|
||||||
|
}
|
||||||
|
HeapCellValue::Rational(n) => {
|
||||||
|
Ok(Number::Rational(n.clone()))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Computes n ^ power. Ignores the sign of power.
|
// Computes n ^ power. Ignores the sign of power.
|
||||||
pub fn binary_pow(mut n: Integer, power: Integer) -> Integer {
|
pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
|
||||||
let mut power = power.abs();
|
let mut power = Integer::from(power.abs_ref());
|
||||||
|
|
||||||
if power == 0 {
|
if power == 0 {
|
||||||
return Integer::from(1);
|
return Integer::from(1);
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ pub enum InlinedClauseType {
|
|||||||
IsCompound(RegType),
|
IsCompound(RegType),
|
||||||
IsInteger(RegType),
|
IsInteger(RegType),
|
||||||
IsRational(RegType),
|
IsRational(RegType),
|
||||||
IsString(RegType),
|
|
||||||
IsFloat(RegType),
|
IsFloat(RegType),
|
||||||
IsNonVar(RegType),
|
IsNonVar(RegType),
|
||||||
IsVar(RegType),
|
IsVar(RegType),
|
||||||
@@ -105,7 +104,6 @@ ref_thread_local! {
|
|||||||
m.insert(("compound", 1), ClauseType::Inlined(InlinedClauseType::IsCompound(r1)));
|
m.insert(("compound", 1), ClauseType::Inlined(InlinedClauseType::IsCompound(r1)));
|
||||||
m.insert(("integer", 1), ClauseType::Inlined(InlinedClauseType::IsInteger(r1)));
|
m.insert(("integer", 1), ClauseType::Inlined(InlinedClauseType::IsInteger(r1)));
|
||||||
m.insert(("rational", 1), ClauseType::Inlined(InlinedClauseType::IsRational(r1)));
|
m.insert(("rational", 1), ClauseType::Inlined(InlinedClauseType::IsRational(r1)));
|
||||||
m.insert(("string", 1), ClauseType::Inlined(InlinedClauseType::IsString(r1)));
|
|
||||||
m.insert(("float", 1), ClauseType::Inlined(InlinedClauseType::IsFloat(r1)));
|
m.insert(("float", 1), ClauseType::Inlined(InlinedClauseType::IsFloat(r1)));
|
||||||
m.insert(("nonvar", 1), ClauseType::Inlined(InlinedClauseType::IsNonVar(r1)));
|
m.insert(("nonvar", 1), ClauseType::Inlined(InlinedClauseType::IsNonVar(r1)));
|
||||||
m.insert(("var", 1), ClauseType::Inlined(InlinedClauseType::IsVar(r1)));
|
m.insert(("var", 1), ClauseType::Inlined(InlinedClauseType::IsVar(r1)));
|
||||||
@@ -117,7 +115,6 @@ ref_thread_local! {
|
|||||||
m.insert(("@>=", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual)));
|
m.insert(("@>=", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual)));
|
||||||
m.insert(("@=<", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)));
|
m.insert(("@=<", 2), ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)));
|
||||||
m.insert(("copy_term", 2), ClauseType::BuiltIn(BuiltInClauseType::CopyTerm));
|
m.insert(("copy_term", 2), ClauseType::BuiltIn(BuiltInClauseType::CopyTerm));
|
||||||
m.insert(("cyclic_term", 1), ClauseType::BuiltIn(BuiltInClauseType::CyclicTerm));
|
|
||||||
m.insert(("==", 2), ClauseType::BuiltIn(BuiltInClauseType::Eq));
|
m.insert(("==", 2), ClauseType::BuiltIn(BuiltInClauseType::Eq));
|
||||||
m.insert(("functor", 3), ClauseType::BuiltIn(BuiltInClauseType::Functor));
|
m.insert(("functor", 3), ClauseType::BuiltIn(BuiltInClauseType::Functor));
|
||||||
m.insert(("ground", 1), ClauseType::BuiltIn(BuiltInClauseType::Ground));
|
m.insert(("ground", 1), ClauseType::BuiltIn(BuiltInClauseType::Ground));
|
||||||
@@ -141,7 +138,6 @@ impl InlinedClauseType {
|
|||||||
&InlinedClauseType::IsCompound(..) => "compound",
|
&InlinedClauseType::IsCompound(..) => "compound",
|
||||||
&InlinedClauseType::IsInteger(..) => "integer",
|
&InlinedClauseType::IsInteger(..) => "integer",
|
||||||
&InlinedClauseType::IsRational(..) => "rational",
|
&InlinedClauseType::IsRational(..) => "rational",
|
||||||
&InlinedClauseType::IsString(..) => "string",
|
|
||||||
&InlinedClauseType::IsFloat(..) => "float",
|
&InlinedClauseType::IsFloat(..) => "float",
|
||||||
&InlinedClauseType::IsNonVar(..) => "nonvar",
|
&InlinedClauseType::IsNonVar(..) => "nonvar",
|
||||||
&InlinedClauseType::IsVar(..) => "var",
|
&InlinedClauseType::IsVar(..) => "var",
|
||||||
@@ -160,11 +156,9 @@ pub enum SystemClauseType {
|
|||||||
AtomCodes,
|
AtomCodes,
|
||||||
AtomLength,
|
AtomLength,
|
||||||
BindFromRegister,
|
BindFromRegister,
|
||||||
CallAttributeGoals,
|
|
||||||
CallContinuation,
|
CallContinuation,
|
||||||
CharCode,
|
CharCode,
|
||||||
CharsToNumber,
|
CharsToNumber,
|
||||||
ClearAttrVarBindings,
|
|
||||||
ClearAttributeGoals,
|
ClearAttributeGoals,
|
||||||
CloneAttributeGoals,
|
CloneAttributeGoals,
|
||||||
CodesToNumber,
|
CodesToNumber,
|
||||||
@@ -172,6 +166,8 @@ pub enum SystemClauseType {
|
|||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
CopyToLiftedHeap,
|
CopyToLiftedHeap,
|
||||||
CreatePartialString,
|
CreatePartialString,
|
||||||
|
CurrentInput,
|
||||||
|
CurrentOutput,
|
||||||
DeleteAttribute,
|
DeleteAttribute,
|
||||||
DeleteHeadAttribute,
|
DeleteHeadAttribute,
|
||||||
DynamicModuleResolution(usize),
|
DynamicModuleResolution(usize),
|
||||||
@@ -179,7 +175,6 @@ pub enum SystemClauseType {
|
|||||||
EnqueueAttributedVar,
|
EnqueueAttributedVar,
|
||||||
ExpandGoal,
|
ExpandGoal,
|
||||||
ExpandTerm,
|
ExpandTerm,
|
||||||
FetchAttributeGoals,
|
|
||||||
FetchGlobalVar,
|
FetchGlobalVar,
|
||||||
FetchGlobalVarWithOffset,
|
FetchGlobalVarWithOffset,
|
||||||
GetChar,
|
GetChar,
|
||||||
@@ -231,6 +226,8 @@ pub enum SystemClauseType {
|
|||||||
RetractClause,
|
RetractClause,
|
||||||
RestoreCutPolicy,
|
RestoreCutPolicy,
|
||||||
SetCutPoint(RegType),
|
SetCutPoint(RegType),
|
||||||
|
SetInput,
|
||||||
|
SetOutput,
|
||||||
StoreGlobalVar,
|
StoreGlobalVar,
|
||||||
StoreGlobalVarWithOffset,
|
StoreGlobalVarWithOffset,
|
||||||
InferenceLevel,
|
InferenceLevel,
|
||||||
@@ -243,7 +240,9 @@ pub enum SystemClauseType {
|
|||||||
GetDoubleQuotes,
|
GetDoubleQuotes,
|
||||||
InstallNewBlock,
|
InstallNewBlock,
|
||||||
Maybe,
|
Maybe,
|
||||||
|
QuotedToken,
|
||||||
RawInputReadChar,
|
RawInputReadChar,
|
||||||
|
ReadTermFromChars,
|
||||||
ResetBlock,
|
ResetBlock,
|
||||||
ReturnFromVerifyAttr,
|
ReturnFromVerifyAttr,
|
||||||
SetBall,
|
SetBall,
|
||||||
@@ -260,6 +259,7 @@ pub enum SystemClauseType {
|
|||||||
Variant,
|
Variant,
|
||||||
WAMInstructions,
|
WAMInstructions,
|
||||||
WriteTerm,
|
WriteTerm,
|
||||||
|
WriteTermToChars,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemClauseType {
|
impl SystemClauseType {
|
||||||
@@ -274,7 +274,6 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
|
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
|
||||||
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
||||||
&SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"),
|
&SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"),
|
||||||
&SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
|
|
||||||
&SystemClauseType::CallContinuation => clause_name!("$call_continuation"),
|
&SystemClauseType::CallContinuation => clause_name!("$call_continuation"),
|
||||||
&SystemClauseType::CharCode => clause_name!("$char_code"),
|
&SystemClauseType::CharCode => clause_name!("$char_code"),
|
||||||
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
|
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
|
||||||
@@ -284,6 +283,8 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"),
|
&SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"),
|
||||||
&SystemClauseType::CopyTermWithoutAttrVars => clause_name!("$copy_term_without_attr_vars"),
|
&SystemClauseType::CopyTermWithoutAttrVars => clause_name!("$copy_term_without_attr_vars"),
|
||||||
&SystemClauseType::CreatePartialString => clause_name!("$create_partial_string"),
|
&SystemClauseType::CreatePartialString => clause_name!("$create_partial_string"),
|
||||||
|
&SystemClauseType::CurrentInput => clause_name!("$current_input"),
|
||||||
|
&SystemClauseType::CurrentOutput => clause_name!("$current_output"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
|
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
|
||||||
@@ -295,7 +296,6 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
|
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
|
||||||
clause_name!("$use_qualified_module_from_file")
|
clause_name!("$use_qualified_module_from_file")
|
||||||
}
|
}
|
||||||
&SystemClauseType::ClearAttrVarBindings => clause_name!("$clear_attr_var_bindings"),
|
|
||||||
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
||||||
@@ -304,7 +304,6 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
|
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
|
||||||
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
||||||
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
||||||
&SystemClauseType::FetchAttributeGoals => clause_name!("$fetch_attribute_goals"),
|
|
||||||
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
|
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
|
||||||
&SystemClauseType::FetchGlobalVarWithOffset => {
|
&SystemClauseType::FetchGlobalVarWithOffset => {
|
||||||
clause_name!("$fetch_global_var_with_offset")
|
clause_name!("$fetch_global_var_with_offset")
|
||||||
@@ -362,12 +361,17 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::PointsToContinuationResetMarker => {
|
&SystemClauseType::PointsToContinuationResetMarker => {
|
||||||
clause_name!("$points_to_cont_reset_marker")
|
clause_name!("$points_to_cont_reset_marker")
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::QuotedToken => {
|
||||||
|
clause_name!("$quoted_token")
|
||||||
|
}
|
||||||
&SystemClauseType::RawInputReadChar => clause_name!("$raw_input_read_char"),
|
&SystemClauseType::RawInputReadChar => clause_name!("$raw_input_read_char"),
|
||||||
&SystemClauseType::RedoAttrVarBinding => clause_name!("$redo_attr_var_binding"),
|
&SystemClauseType::RedoAttrVarBinding => clause_name!("$redo_attr_var_binding"),
|
||||||
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
|
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
|
||||||
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
|
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
|
||||||
&SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"),
|
&SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"),
|
||||||
&SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"),
|
&SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"),
|
||||||
|
&SystemClauseType::SetInput => clause_name!("$set_input"),
|
||||||
|
&SystemClauseType::SetOutput => clause_name!("$set_output"),
|
||||||
&SystemClauseType::SetSeed => clause_name!("$set_seed"),
|
&SystemClauseType::SetSeed => clause_name!("$set_seed"),
|
||||||
&SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"),
|
&SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"),
|
||||||
&SystemClauseType::StoreGlobalVarWithOffset => {
|
&SystemClauseType::StoreGlobalVarWithOffset => {
|
||||||
@@ -385,6 +389,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::NextEP => clause_name!("$nextEP"),
|
&SystemClauseType::NextEP => clause_name!("$nextEP"),
|
||||||
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
|
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
|
||||||
&SystemClauseType::ReadTerm => clause_name!("$read_term"),
|
&SystemClauseType::ReadTerm => clause_name!("$read_term"),
|
||||||
|
&SystemClauseType::ReadTermFromChars => clause_name!("$read_term_from_chars"),
|
||||||
&SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
|
&SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
|
||||||
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
|
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
|
||||||
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
||||||
@@ -404,6 +409,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::Variant => clause_name!("$variant"),
|
&SystemClauseType::Variant => clause_name!("$variant"),
|
||||||
&SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
|
&SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
|
||||||
&SystemClauseType::WriteTerm => clause_name!("$write_term"),
|
&SystemClauseType::WriteTerm => clause_name!("$write_term"),
|
||||||
|
&SystemClauseType::WriteTermToChars => clause_name!("$write_term_to_chars"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,11 +426,9 @@ impl SystemClauseType {
|
|||||||
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
||||||
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
||||||
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
||||||
("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
|
|
||||||
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
|
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
|
||||||
("$char_code", 2) => Some(SystemClauseType::CharCode),
|
("$char_code", 2) => Some(SystemClauseType::CharCode),
|
||||||
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
|
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
|
||||||
("$clear_attr_var_bindings", 0) => Some(SystemClauseType::ClearAttrVarBindings),
|
|
||||||
("$clear_attribute_goals", 0) => Some(SystemClauseType::ClearAttributeGoals),
|
("$clear_attribute_goals", 0) => Some(SystemClauseType::ClearAttributeGoals),
|
||||||
("$clone_attribute_goals", 1) => Some(SystemClauseType::CloneAttributeGoals),
|
("$clone_attribute_goals", 1) => Some(SystemClauseType::CloneAttributeGoals),
|
||||||
("$codes_to_number", 2) => Some(SystemClauseType::CodesToNumber),
|
("$codes_to_number", 2) => Some(SystemClauseType::CodesToNumber),
|
||||||
@@ -433,6 +437,8 @@ impl SystemClauseType {
|
|||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
|
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
|
||||||
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
||||||
|
("$current_input", 1) => Some(SystemClauseType::CurrentInput),
|
||||||
|
("$current_output", 1) => Some(SystemClauseType::CurrentOutput),
|
||||||
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
||||||
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
|
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
|
||||||
("$get_next_db_ref", 2) => Some(SystemClauseType::GetNextDBRef),
|
("$get_next_db_ref", 2) => Some(SystemClauseType::GetNextDBRef),
|
||||||
@@ -446,7 +452,6 @@ impl SystemClauseType {
|
|||||||
("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
|
("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
|
||||||
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
||||||
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
||||||
("$fetch_attribute_goals", 1) => Some(SystemClauseType::FetchAttributeGoals),
|
|
||||||
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
||||||
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
|
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
|
||||||
("$get_char", 1) => Some(SystemClauseType::GetChar),
|
("$get_char", 1) => Some(SystemClauseType::GetChar),
|
||||||
@@ -487,6 +492,8 @@ impl SystemClauseType {
|
|||||||
("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter),
|
("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter),
|
||||||
("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy),
|
("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy),
|
||||||
("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))),
|
("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))),
|
||||||
|
("$set_input", 1) => Some(SystemClauseType::SetInput),
|
||||||
|
("$set_output", 1) => Some(SystemClauseType::SetOutput),
|
||||||
("$inference_level", 2) => Some(SystemClauseType::InferenceLevel),
|
("$inference_level", 2) => Some(SystemClauseType::InferenceLevel),
|
||||||
("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock),
|
("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock),
|
||||||
("$erase_ball", 0) => Some(SystemClauseType::EraseBall),
|
("$erase_ball", 0) => Some(SystemClauseType::EraseBall),
|
||||||
@@ -498,10 +505,12 @@ impl SystemClauseType {
|
|||||||
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
|
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
|
||||||
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
|
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
|
||||||
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
|
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
|
||||||
|
("$quoted_token", 1) => Some(SystemClauseType::QuotedToken),
|
||||||
("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar),
|
("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar),
|
||||||
("$nextEP", 3) => Some(SystemClauseType::NextEP),
|
("$nextEP", 3) => Some(SystemClauseType::NextEP),
|
||||||
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
|
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
|
||||||
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
|
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
|
||||||
|
("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars),
|
||||||
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
|
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
|
||||||
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
||||||
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
|
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
|
||||||
@@ -528,8 +537,9 @@ impl SystemClauseType {
|
|||||||
("$use_qualified_module_from_file", 2) =>
|
("$use_qualified_module_from_file", 2) =>
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
||||||
("$variant", 2) => Some(SystemClauseType::Variant),
|
("$variant", 2) => Some(SystemClauseType::Variant),
|
||||||
("$write_term", 5) => Some(SystemClauseType::WriteTerm),
|
|
||||||
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
||||||
|
("$write_term", 6) => Some(SystemClauseType::WriteTerm),
|
||||||
|
("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,7 +551,6 @@ pub enum BuiltInClauseType {
|
|||||||
Arg,
|
Arg,
|
||||||
Compare,
|
Compare,
|
||||||
CompareTerm(CompareTermQT),
|
CompareTerm(CompareTermQT),
|
||||||
CyclicTerm,
|
|
||||||
CopyTerm,
|
CopyTerm,
|
||||||
Eq,
|
Eq,
|
||||||
Functor,
|
Functor,
|
||||||
@@ -572,7 +581,6 @@ impl BuiltInClauseType {
|
|||||||
&BuiltInClauseType::Arg => clause_name!("arg"),
|
&BuiltInClauseType::Arg => clause_name!("arg"),
|
||||||
&BuiltInClauseType::Compare => clause_name!("compare"),
|
&BuiltInClauseType::Compare => clause_name!("compare"),
|
||||||
&BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()),
|
&BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()),
|
||||||
&BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"),
|
|
||||||
&BuiltInClauseType::CopyTerm => clause_name!("copy_term"),
|
&BuiltInClauseType::CopyTerm => clause_name!("copy_term"),
|
||||||
&BuiltInClauseType::Eq => clause_name!("=="),
|
&BuiltInClauseType::Eq => clause_name!("=="),
|
||||||
&BuiltInClauseType::Functor => clause_name!("functor"),
|
&BuiltInClauseType::Functor => clause_name!("functor"),
|
||||||
@@ -592,7 +600,6 @@ impl BuiltInClauseType {
|
|||||||
&BuiltInClauseType::Arg => 3,
|
&BuiltInClauseType::Arg => 3,
|
||||||
&BuiltInClauseType::Compare => 2,
|
&BuiltInClauseType::Compare => 2,
|
||||||
&BuiltInClauseType::CompareTerm(_) => 2,
|
&BuiltInClauseType::CompareTerm(_) => 2,
|
||||||
&BuiltInClauseType::CyclicTerm => 1,
|
|
||||||
&BuiltInClauseType::CopyTerm => 2,
|
&BuiltInClauseType::CopyTerm => 2,
|
||||||
&BuiltInClauseType::Eq => 2,
|
&BuiltInClauseType::Eq => 2,
|
||||||
&BuiltInClauseType::Functor => 3,
|
&BuiltInClauseType::Functor => 3,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::prolog::iterators::*;
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::targets::*;
|
use crate::prolog::targets::*;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -50,56 +50,45 @@ impl<'a> ConjunctInfo<'a> {
|
|||||||
self.has_deep_cut as usize
|
self.has_deep_cut as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_unsafe_vars<Alloc: Allocator<'a>>(
|
fn mark_unsafe_vars(
|
||||||
&self,
|
&self,
|
||||||
mut unsafe_var_marker: UnsafeVarMarker,
|
mut unsafe_var_marker: UnsafeVarMarker,
|
||||||
marker: &Alloc,
|
code: &mut Code,
|
||||||
code: &mut Code
|
|
||||||
) {
|
) {
|
||||||
// target the last goal of the rule for handling unsafe variables.
|
if code.is_empty() {
|
||||||
// we use this weird logic to find the last goal.
|
|
||||||
let right_index = if let Some(Line::Control(_)) = code.last() {
|
|
||||||
if code.len() >= 2 {
|
|
||||||
code.len() - 2
|
|
||||||
} else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if code.len() >= 1 {
|
let mut code_index = 0;
|
||||||
code.len() - 1
|
|
||||||
} else {
|
for phase in 0 .. {
|
||||||
return;
|
while let Line::Query(ref query_instr) = &code[code_index] {
|
||||||
|
if !unsafe_var_marker.mark_safe_vars(query_instr) {
|
||||||
|
unsafe_var_marker.mark_phase(query_instr, phase);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let mut index = right_index;
|
code_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if let Line::Query(_) = &code[right_index] {
|
if code_index + 1 < code.len() {
|
||||||
while let Line::Query(_) = &code[index] {
|
code_index += 1;
|
||||||
if index == 0 {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code_index = 0;
|
||||||
|
|
||||||
|
for phase in 0 .. {
|
||||||
|
while let Line::Query(ref mut query_instr) = &mut code[code_index] {
|
||||||
|
unsafe_var_marker.mark_unsafe_vars(query_instr, phase);
|
||||||
|
code_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if code_index + 1 < code.len() {
|
||||||
|
code_index += 1;
|
||||||
} else {
|
} else {
|
||||||
index -= 1;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Line::Query(_) = &code[index] {
|
|
||||||
} else {
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe_var_marker.record_unsafe_vars(&self.perm_vs, marker);
|
|
||||||
|
|
||||||
for line in code.iter() {
|
|
||||||
if let Line::Query(ref query_instr) = line {
|
|
||||||
unsafe_var_marker.mark_safe_vars(query_instr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for index in index..right_index + 1 {
|
|
||||||
if let &mut Line::Query(ref mut query_instr) = &mut code[index] {
|
|
||||||
unsafe_var_marker.mark_unsafe_vars(query_instr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,35 +163,44 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
target.push(Target::to_void(1));
|
target.push(Target::to_void(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subterm_to_instr<Target>(
|
fn deep_var_instr<Target: CompilationTarget<'a>>(
|
||||||
|
&mut self,
|
||||||
|
cell: &'a Cell<VarReg>,
|
||||||
|
var: &'a Rc<Var>,
|
||||||
|
term_loc: GenContext,
|
||||||
|
is_exposed: bool,
|
||||||
|
target: &mut Vec<Target>,
|
||||||
|
) {
|
||||||
|
if is_exposed || self.get_var_count(var.as_ref()) > 1 {
|
||||||
|
self.marker.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
|
||||||
|
} else {
|
||||||
|
Self::add_or_increment_void_instr(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subterm_to_instr<Target: CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
subterm: &'a Term,
|
subterm: &'a Term,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
is_exposed: bool,
|
is_exposed: bool,
|
||||||
target: &mut Vec<Target>,
|
target: &mut Vec<Target>,
|
||||||
) where
|
) {
|
||||||
Target: CompilationTarget<'a>,
|
|
||||||
{
|
|
||||||
match subterm {
|
match subterm {
|
||||||
&Term::AnonVar if is_exposed => {
|
&Term::AnonVar if is_exposed => {
|
||||||
self.marker.mark_anon_var(Level::Deep, term_loc, target)
|
self.marker.mark_anon_var(Level::Deep, term_loc, target);
|
||||||
|
}
|
||||||
|
&Term::AnonVar => {
|
||||||
|
Self::add_or_increment_void_instr(target);
|
||||||
}
|
}
|
||||||
&Term::AnonVar => Self::add_or_increment_void_instr(target),
|
|
||||||
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => {
|
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => {
|
||||||
self.marker
|
self.marker.mark_non_var(Level::Deep, term_loc, cell, target);
|
||||||
.mark_non_var(Level::Deep, term_loc, cell, target);
|
|
||||||
target.push(Target::clause_arg_to_instr(cell.get()));
|
target.push(Target::clause_arg_to_instr(cell.get()));
|
||||||
}
|
}
|
||||||
&Term::Constant(_, ref constant) => {
|
&Term::Constant(_, ref constant) => {
|
||||||
target.push(Target::constant_subterm(constant.clone()))
|
target.push(Target::constant_subterm(constant.clone()));
|
||||||
}
|
}
|
||||||
&Term::Var(ref cell, ref var) => {
|
&Term::Var(ref cell, ref var) => {
|
||||||
if is_exposed || self.get_var_count(var) > 1 {
|
self.deep_var_instr(cell, var, term_loc, is_exposed, target);
|
||||||
self.marker
|
|
||||||
.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
|
|
||||||
} else {
|
|
||||||
Self::add_or_increment_void_instr(target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -221,6 +219,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
|
|
||||||
for term in iter {
|
for term in iter {
|
||||||
match term {
|
match term {
|
||||||
|
TermRef::AnonVar(lvl @ Level::Shallow) => {
|
||||||
|
if let GenContext::Head = term_loc {
|
||||||
|
self.marker.advance_arg();
|
||||||
|
} else {
|
||||||
|
self.marker.mark_anon_var(lvl, term_loc, &mut target);
|
||||||
|
}
|
||||||
|
}
|
||||||
TermRef::Clause(lvl, cell, ct, terms) => {
|
TermRef::Clause(lvl, cell, ct, terms) => {
|
||||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||||
target.push(Target::to_structure(ct, terms.len(), cell.get()));
|
target.push(Target::to_structure(ct, terms.len(), cell.get()));
|
||||||
@@ -236,15 +241,22 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
|
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
|
||||||
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
|
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
|
||||||
}
|
}
|
||||||
|
TermRef::Constant(lvl @ Level::Shallow, cell, Constant::String(ref string)) => {
|
||||||
|
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||||
|
target.push(Target::to_pstr(lvl, string.to_string(), cell.get(), false));
|
||||||
|
}
|
||||||
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
|
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
|
||||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||||
target.push(Target::to_constant(lvl, constant.clone(), cell.get()));
|
target.push(Target::to_constant(lvl, constant.clone(), cell.get()));
|
||||||
}
|
}
|
||||||
TermRef::AnonVar(lvl @ Level::Shallow) => {
|
TermRef::PartialString(lvl, cell, string, tail) => {
|
||||||
if let GenContext::Head = term_loc {
|
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||||
self.marker.advance_arg();
|
|
||||||
|
if let Some(tail) = tail {
|
||||||
|
target.push(Target::to_pstr(lvl, string, cell.get(), true));
|
||||||
|
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
|
||||||
} else {
|
} else {
|
||||||
self.marker.mark_anon_var(lvl, term_loc, &mut target);
|
target.push(Target::to_pstr(lvl, string, cell.get(), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
|
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
|
||||||
@@ -263,14 +275,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.marker
|
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
|
||||||
.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
|
|
||||||
}
|
}
|
||||||
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
|
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
|
||||||
self.marker
|
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
|
||||||
.mark_var(var.clone(), lvl, cell, term_loc, &mut target)
|
}
|
||||||
|
_ => {
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,18 +443,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
code.push(fail!());
|
code.push(fail!());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&InlinedClauseType::IsString(..) => match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::String(..)) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
}
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_string!(r));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsNonVar(..) => match terms[0].as_ref() {
|
&InlinedClauseType::IsNonVar(..) => match terms[0].as_ref() {
|
||||||
&Term::AnonVar => {
|
&Term::AnonVar => {
|
||||||
code.push(fail!());
|
code.push(fail!());
|
||||||
@@ -457,7 +456,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&InlinedClauseType::IsInteger(..) => match terms[0].as_ref() {
|
&InlinedClauseType::IsInteger(..) => match terms[0].as_ref() {
|
||||||
&Term::Constant(_, Constant::Integer(_)) => {
|
&Term::Constant(_, Constant::Integer(_)) |
|
||||||
|
&Term::Constant(_, Constant::Fixnum(_)) => {
|
||||||
code.push(succeed!());
|
code.push(succeed!());
|
||||||
}
|
}
|
||||||
&Term::Var(ref vr, ref name) => {
|
&Term::Var(ref vr, ref name) => {
|
||||||
@@ -522,7 +522,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
|
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Term::Constant(_, ref c @ Constant::Integer(_)) => {
|
&Term::Constant(_, ref c @ Constant::Integer(_)) |
|
||||||
|
&Term::Constant(_, ref c @ Constant::Fixnum(_)) => {
|
||||||
code.push(Line::Query(put_constant!(
|
code.push(Line::Query(put_constant!(
|
||||||
Level::Shallow,
|
Level::Shallow,
|
||||||
c.clone(),
|
c.clone(),
|
||||||
@@ -684,6 +685,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
head: (_, ref args, ref p1),
|
head: (_, ref args, ref p1),
|
||||||
ref clauses,
|
ref clauses,
|
||||||
} = rule;
|
} = rule;
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
self.marker.reset_at_head(args);
|
self.marker.reset_at_head(args);
|
||||||
@@ -705,39 +707,31 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
let iter = ChunkedIterator::from_rule_body(p1, clauses);
|
let iter = ChunkedIterator::from_rule_body(p1, clauses);
|
||||||
self.compile_seq(iter, &conjunct_info, &mut code, false)?;
|
self.compile_seq(iter, &conjunct_info, &mut code, false)?;
|
||||||
|
|
||||||
conjunct_info.mark_unsafe_vars(unsafe_var_marker, &self.marker, &mut code);
|
conjunct_info.mark_unsafe_vars(unsafe_var_marker, &mut code);
|
||||||
|
|
||||||
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
|
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
|
||||||
Ok(code)
|
Ok(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker {
|
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker {
|
||||||
let mut unsafe_vars = IndexMap::new();
|
let mut safe_vars = IndexSet::new();
|
||||||
|
|
||||||
for var_status in self.marker.bindings().values() {
|
|
||||||
unsafe_vars.insert(var_status.as_reg_type(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for fact_instr in fact.iter_mut() {
|
for fact_instr in fact.iter_mut() {
|
||||||
match fact_instr {
|
match fact_instr {
|
||||||
&mut FactInstruction::UnifyValue(reg) => {
|
&mut FactInstruction::UnifyValue(r) => {
|
||||||
if let Some(found) = unsafe_vars.get_mut(®) {
|
if !safe_vars.contains(&r) {
|
||||||
if !*found {
|
*fact_instr = FactInstruction::UnifyLocalValue(r);
|
||||||
*found = true;
|
safe_vars.insert(r);
|
||||||
*fact_instr = FactInstruction::UnifyLocalValue(reg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
&mut FactInstruction::UnifyVariable(r) => {
|
||||||
&mut FactInstruction::UnifyVariable(reg) => {
|
safe_vars.insert(r);
|
||||||
if let Some(found) = unsafe_vars.get_mut(®) {
|
|
||||||
*found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsafeVarMarker { unsafe_vars }
|
UnsafeVarMarker::from_safe_vars(safe_vars)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code {
|
pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code {
|
||||||
@@ -802,7 +796,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
let iter = ChunkedIterator::from_term_sequence(query);
|
let iter = ChunkedIterator::from_term_sequence(query);
|
||||||
self.compile_seq(iter, &conjunct_info, &mut code, true)?;
|
self.compile_seq(iter, &conjunct_info, &mut code, true)?;
|
||||||
|
|
||||||
conjunct_info.mark_unsafe_vars(UnsafeVarMarker::new(), &self.marker, &mut code);
|
conjunct_info.mark_unsafe_vars(UnsafeVarMarker::new(), &mut code);
|
||||||
|
|
||||||
if let Some(query_term) = query.last() {
|
if let Some(query_term) = query.last() {
|
||||||
Self::compile_cleanup(&mut code, &conjunct_info, query_term);
|
Self::compile_cleanup(&mut code, &conjunct_info, query_term);
|
||||||
|
|||||||
1202
src/prolog/examples/bimetatrans_ruleml.pl
Normal file
1202
src/prolog/examples/bimetatrans_ruleml.pl
Normal file
File diff suppressed because it is too large
Load Diff
64
src/prolog/examples/least_time.pl
Normal file
64
src/prolog/examples/least_time.pl
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* least_time.pl
|
||||||
|
*
|
||||||
|
* By Mark Thom, 2020
|
||||||
|
*
|
||||||
|
* find_min_time/2 solves a problem sometimes posed in the first round
|
||||||
|
* of Google interviews: given a time of day in 24 H format, what is the
|
||||||
|
* lexicographically least permutation of the time that is itself a
|
||||||
|
* valid time in 24 H format?
|
||||||
|
*
|
||||||
|
* Full generality is achieved using the reif library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:- module(least_time, [find_min_time/2,
|
||||||
|
write_time_nl/1]).
|
||||||
|
|
||||||
|
|
||||||
|
:- use_module(library(dcgs)).
|
||||||
|
:- use_module(library(format)).
|
||||||
|
:- use_module(library(reif)).
|
||||||
|
|
||||||
|
|
||||||
|
permutation([], []).
|
||||||
|
permutation([X|Xs], Ys) :-
|
||||||
|
permutation(Xs, Yss),
|
||||||
|
select(X, Ys, Yss).
|
||||||
|
|
||||||
|
|
||||||
|
valid_time([H1,H2,M1,M2], T) :-
|
||||||
|
memberd_t(H1, [0,1,2], TH1),
|
||||||
|
memberd_t(H2, [0,1,2,3,4,5,6,7,8,9], TH2),
|
||||||
|
memberd_t(M1, [0,1,2,3,4,5], TM1),
|
||||||
|
memberd_t(M2, [0,1,2,3,4,5,6,7,8,9], TM2),
|
||||||
|
( maplist(=(true), [TH1, TH2, TM1, TM2]) ->
|
||||||
|
( H1 =:= 2 ->
|
||||||
|
( H2 =< 3 ->
|
||||||
|
T = true
|
||||||
|
; T = false
|
||||||
|
)
|
||||||
|
; T = true
|
||||||
|
)
|
||||||
|
; T = false
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
permuted_times(Time, PermutedTimes) :-
|
||||||
|
setof(P, permutation(Time, P), PermutedTimes0),
|
||||||
|
tfilter(valid_time, PermutedTimes0, PermutedTimes).
|
||||||
|
|
||||||
|
|
||||||
|
find_min_time(Time, Min) :-
|
||||||
|
valid_time(Time, true),
|
||||||
|
permuted_times(Time, PermutedTimes),
|
||||||
|
find_min_time_(PermutedTimes, Time, Min).
|
||||||
|
|
||||||
|
find_min_time_([], Min, Min).
|
||||||
|
find_min_time_([Time|Times], MinSoFar, Min) :-
|
||||||
|
( Time @< MinSoFar ->
|
||||||
|
find_min_time_(Times, Time, Min)
|
||||||
|
; find_min_time_(Times, MinSoFar, Min)
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
write_time_nl(Time) :-
|
||||||
|
format("\"~w~w:~w~w\"~n", Time).
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::allocator::*;
|
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
use crate::prolog::instructions::*;
|
use crate::prolog::instructions::*;
|
||||||
use crate::prolog::iterators::*;
|
use crate::prolog::iterators::*;
|
||||||
@@ -250,67 +249,67 @@ impl<'a> VariableFixtures<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnsafeVarMarker {
|
pub struct UnsafeVarMarker {
|
||||||
pub unsafe_vars: IndexMap<RegType, bool>,
|
pub unsafe_vars: IndexMap<RegType, usize>,
|
||||||
|
pub safe_vars: IndexSet<RegType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnsafeVarMarker {
|
impl UnsafeVarMarker {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
UnsafeVarMarker {
|
UnsafeVarMarker {
|
||||||
unsafe_vars: IndexMap::new(),
|
unsafe_vars: IndexMap::new(),
|
||||||
|
safe_vars: IndexSet::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_unsafe_vars<'a, Alloc: Allocator<'a>>(
|
pub fn from_safe_vars(safe_vars: IndexSet<RegType>) -> Self {
|
||||||
&mut self,
|
UnsafeVarMarker {
|
||||||
fixtures: &VariableFixtures,
|
unsafe_vars: IndexMap::new(),
|
||||||
marker: &Alloc
|
safe_vars
|
||||||
) {
|
|
||||||
for &(_, ref cb) in fixtures.values() {
|
|
||||||
if let Some(index) = cb.first() {
|
|
||||||
if !self.unsafe_vars.contains_key(&index.get().norm()) {
|
|
||||||
self.unsafe_vars.insert(index.get().norm(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for var in fixtures.last_chunk_temp_vars.iter().cloned() {
|
|
||||||
let r = marker.get(var);
|
|
||||||
self.unsafe_vars.insert(r, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) {
|
pub fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) -> bool {
|
||||||
match query_instr {
|
match query_instr {
|
||||||
QueryInstruction::PutVariable(RegType::Temp(r), _) => {
|
&QueryInstruction::PutVariable(r @ RegType::Temp(_), _)
|
||||||
if let Some(found) = self.unsafe_vars.get_mut(&RegType::Temp(*r)) {
|
| &QueryInstruction::SetVariable(r) => {
|
||||||
*found = true;
|
self.safe_vars.insert(r);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueryInstruction::SetVariable(reg) => {
|
|
||||||
if let Some(found) = self.unsafe_vars.get_mut(reg) {
|
|
||||||
*found = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mark_phase(&mut self, query_instr: &QueryInstruction, phase: usize) {
|
||||||
|
match query_instr {
|
||||||
|
&QueryInstruction::PutValue(r @ RegType::Perm(_), _)
|
||||||
|
| &QueryInstruction::SetValue(r) => {
|
||||||
|
let p = self.unsafe_vars.entry(r).or_insert(0);
|
||||||
|
*p = phase;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction) {
|
pub fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction, phase: usize) {
|
||||||
match query_instr {
|
match query_instr {
|
||||||
&mut QueryInstruction::PutValue(RegType::Perm(i), arg) => {
|
&mut QueryInstruction::PutValue(RegType::Perm(i), arg) => {
|
||||||
if let Some(found) = self.unsafe_vars.get_mut(&RegType::Perm(i)) {
|
if let Some(p) = self.unsafe_vars.swap_remove(&RegType::Perm(i)) {
|
||||||
if !*found {
|
if p == phase {
|
||||||
*found = true;
|
|
||||||
*query_instr = QueryInstruction::PutUnsafeValue(i, arg);
|
*query_instr = QueryInstruction::PutUnsafeValue(i, arg);
|
||||||
|
self.safe_vars.insert(RegType::Perm(i));
|
||||||
|
} else {
|
||||||
|
self.unsafe_vars.insert(RegType::Perm(i), p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&mut QueryInstruction::SetValue(reg) => {
|
&mut QueryInstruction::SetValue(r) => {
|
||||||
if let Some(found) = self.unsafe_vars.get_mut(®) {
|
if !self.safe_vars.contains(&r) {
|
||||||
if !*found {
|
*query_instr = QueryInstruction::SetLocalValue(r);
|
||||||
*found = true;
|
|
||||||
*query_instr = QueryInstruction::SetLocalValue(reg);
|
self.safe_vars.insert(r);
|
||||||
}
|
self.unsafe_vars.remove(&r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use indexmap::IndexMap;
|
|||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@@ -376,6 +377,19 @@ pub enum ModuleSource {
|
|||||||
File(ClauseName),
|
File(ClauseName),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ModuleSource {
|
||||||
|
pub fn as_functor_stub(&self) -> MachineStub {
|
||||||
|
match self {
|
||||||
|
ModuleSource::Library(ref name) => {
|
||||||
|
functor!("library", [clause_name(name.clone())])
|
||||||
|
}
|
||||||
|
ModuleSource::File(ref name) => {
|
||||||
|
functor!(clause_name(name.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator.
|
pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator.
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -394,6 +408,7 @@ pub enum Declaration {
|
|||||||
MultiFile(MultiFileIndicator),
|
MultiFile(MultiFileIndicator),
|
||||||
NonCountedBacktracking(ClauseName, usize), // name, arity
|
NonCountedBacktracking(ClauseName, usize), // name, arity
|
||||||
Op(OpDecl),
|
Op(OpDecl),
|
||||||
|
SetPrologFlag(DoubleQuotes),
|
||||||
UseModule(ModuleSource),
|
UseModule(ModuleSource),
|
||||||
UseQualifiedModule(ModuleSource, Vec<ModuleExport>),
|
UseQualifiedModule(ModuleSource, Vec<ModuleExport>),
|
||||||
}
|
}
|
||||||
@@ -572,11 +587,33 @@ pub struct Module {
|
|||||||
pub listing_src: ListingSource,
|
pub listing_src: ListingSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone)]
|
||||||
pub enum Number {
|
pub enum Number {
|
||||||
Float(OrderedFloat<f64>),
|
Float(OrderedFloat<f64>),
|
||||||
Integer(Integer),
|
Integer(Rc<Integer>),
|
||||||
Rational(Rational),
|
Rational(Rc<Rational>),
|
||||||
|
Fixnum(isize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Integer> for Number {
|
||||||
|
#[inline]
|
||||||
|
fn from(n: Integer) -> Self {
|
||||||
|
Number::Integer(Rc::new(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Rational> for Number {
|
||||||
|
#[inline]
|
||||||
|
fn from(n: Rational) -> Self {
|
||||||
|
Number::Rational(Rc::new(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<isize> for Number {
|
||||||
|
#[inline]
|
||||||
|
fn from(n: isize) -> Self {
|
||||||
|
Number::Fixnum(n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Number {
|
impl Default for Number {
|
||||||
@@ -585,48 +622,89 @@ impl Default for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Number {
|
impl Into<Constant> for Number {
|
||||||
pub fn to_constant(self) -> Constant {
|
#[inline]
|
||||||
|
fn into(self) -> Constant {
|
||||||
match self {
|
match self {
|
||||||
|
Number::Fixnum(n) => Constant::Fixnum(n),
|
||||||
Number::Integer(n) => Constant::Integer(n),
|
Number::Integer(n) => Constant::Integer(n),
|
||||||
Number::Float(f) => Constant::Float(f),
|
Number::Float(f) => Constant::Float(f),
|
||||||
Number::Rational(r) => Constant::Rational(r),
|
Number::Rational(r) => Constant::Rational(r),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<HeapCellValue> for Number {
|
||||||
|
#[inline]
|
||||||
|
fn into(self) -> HeapCellValue {
|
||||||
|
match self {
|
||||||
|
Number::Fixnum(n) => HeapCellValue::Addr(Addr::Fixnum(n)),
|
||||||
|
Number::Integer(n) => HeapCellValue::Integer(n),
|
||||||
|
Number::Float(f) => HeapCellValue::Addr(Addr::Float(f)),
|
||||||
|
Number::Rational(r) => HeapCellValue::Rational(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Number {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_u32(&self) -> Option<u32> {
|
||||||
|
match self {
|
||||||
|
&Number::Fixnum(n) => u32::try_from(n).ok(),
|
||||||
|
&Number::Integer(ref n) => n.to_u32(),
|
||||||
|
&Number::Float(_) => None,
|
||||||
|
&Number::Rational(ref r) =>
|
||||||
|
if r.denom() == &1 {
|
||||||
|
r.numer().to_u32()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_positive(&self) -> bool {
|
pub fn is_positive(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Number::Integer(ref n) => n > &0,
|
&Number::Fixnum(n) => n > 0,
|
||||||
|
&Number::Integer(ref n) => &**n > &0,
|
||||||
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
|
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
|
||||||
&Number::Rational(ref r) => r > &0,
|
&Number::Rational(ref r) => &**r > &0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_negative(&self) -> bool {
|
pub fn is_negative(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Number::Integer(ref n) => n < &0,
|
&Number::Fixnum(n) => n < 0,
|
||||||
|
&Number::Integer(ref n) => &**n < &0,
|
||||||
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
|
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
|
||||||
&Number::Rational(ref r) => r < &0,
|
&Number::Rational(ref r) => &**r < &0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Number::Integer(ref n) => n == &0,
|
&Number::Fixnum(n) => n == 0,
|
||||||
|
&Number::Integer(ref n) => &**n == &0,
|
||||||
&Number::Float(f) => f == OrderedFloat(0f64),
|
&Number::Float(f) => f == OrderedFloat(0f64),
|
||||||
&Number::Rational(ref r) => r == &0,
|
&Number::Rational(ref r) => &**r == &0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn abs(self) -> Self {
|
pub fn abs(self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Number::Integer(n) => Number::Integer(n.abs()),
|
Number::Fixnum(n) =>
|
||||||
|
if let Some(n) = n.checked_abs() {
|
||||||
|
Number::from(n)
|
||||||
|
} else {
|
||||||
|
Number::from(Integer::from(n).abs())
|
||||||
|
}
|
||||||
|
Number::Integer(n) => Number::from(Integer::from(n.abs_ref())),
|
||||||
Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
|
Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
|
||||||
Number::Rational(r) => Number::Rational(r.abs()),
|
Number::Rational(r) => Number::from(Rational::from(r.abs_ref())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use prolog_parser::ast::*;
|
|
||||||
|
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
|
|
||||||
@@ -22,25 +20,33 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn machine_st(&self) -> &MachineState {
|
pub fn machine_st(&self) -> &MachineState {
|
||||||
&self.machine_st
|
&self.machine_st
|
||||||
}
|
}
|
||||||
|
|
||||||
fn follow_heap(&mut self, h: usize) -> Addr {
|
fn follow_heap(&mut self, h: usize) -> Addr {
|
||||||
match &self.machine_st.heap[h] {
|
match &self.machine_st.heap[h] {
|
||||||
HeapCellValue::NamedStr(arity, _, _) => {
|
&HeapCellValue::NamedStr(arity, _, _) => {
|
||||||
for idx in (1 .. arity + 1).rev() {
|
for idx in (1 .. arity + 1).rev() {
|
||||||
self.state_stack.push(Addr::HeapCell(h + idx));
|
self.state_stack.push(Addr::HeapCell(h + idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr::Str(h)
|
Addr::Str(h)
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(ref a) => {
|
&HeapCellValue::Addr(a) => {
|
||||||
self.follow(a.clone())
|
self.follow(a)
|
||||||
}
|
}
|
||||||
HeapCellValue::PartialString(_) => {
|
HeapCellValue::PartialString(..) => {
|
||||||
self.follow(Addr::PStrLocation(h, 0))
|
self.follow(Addr::PStrLocation(h, 0))
|
||||||
}
|
}
|
||||||
|
HeapCellValue::Atom(..) | HeapCellValue::DBRef(_)
|
||||||
|
| HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
|
||||||
|
Addr::Con(h)
|
||||||
|
}
|
||||||
|
HeapCellValue::Stream(_) => {
|
||||||
|
Addr::Stream(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,30 +57,6 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
let da = self.machine_st.store(self.machine_st.deref(addr));
|
let da = self.machine_st.store(self.machine_st.deref(addr));
|
||||||
|
|
||||||
match da {
|
match da {
|
||||||
Addr::Con(Constant::String(n, s)) => {
|
|
||||||
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
|
||||||
if s.len() > n {
|
|
||||||
if let Some(c) = s[n ..].chars().next() {
|
|
||||||
let o = c.len_utf8();
|
|
||||||
|
|
||||||
self.state_stack.push(Addr::Con(Constant::String(n+o, s.clone())));
|
|
||||||
|
|
||||||
if self.machine_st.machine_flags().double_quotes.is_codes() {
|
|
||||||
self.state_stack.push(Addr::Con(Constant::CharCode(c as u32)));
|
|
||||||
} else {
|
|
||||||
self.state_stack.push(Addr::Con(Constant::Char(c)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Addr::Con(Constant::EmptyList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Addr::Con(Constant::String(n, s))
|
|
||||||
}
|
|
||||||
Addr::Con(_) | Addr::DBRef(_) => {
|
|
||||||
da
|
|
||||||
}
|
|
||||||
Addr::Lis(a) => {
|
Addr::Lis(a) => {
|
||||||
self.state_stack.push(Addr::HeapCell(a + 1));
|
self.state_stack.push(Addr::HeapCell(a + 1));
|
||||||
self.state_stack.push(Addr::HeapCell(a));
|
self.state_stack.push(Addr::HeapCell(a));
|
||||||
@@ -82,19 +64,19 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
da
|
da
|
||||||
}
|
}
|
||||||
Addr::PStrLocation(h, n) => {
|
Addr::PStrLocation(h, n) => {
|
||||||
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] {
|
||||||
let s = pstr.block_as_str();
|
if let Some(c) = pstr.range_from(n ..).next() {
|
||||||
|
if !pstr.at_end(n + c.len_utf8()) {
|
||||||
if let Some(c) = s[n ..].chars().next() {
|
|
||||||
if pstr.len() > n + c.len_utf8() {
|
|
||||||
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
||||||
|
} else if has_tail {
|
||||||
|
self.state_stack.push(Addr::HeapCell(h + 1));
|
||||||
} else {
|
} else {
|
||||||
self.state_stack.push(Addr::PStrTail(h, n + c.len_utf8()));
|
self.state_stack.push(Addr::EmptyList);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state_stack.push(Addr::Con(Constant::Char(c)));
|
self.state_stack.push(Addr::Char(c));
|
||||||
} else {
|
} else if has_tail {
|
||||||
unreachable!()
|
return self.follow(Addr::HeapCell(h + 1));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -102,80 +84,63 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
|
|
||||||
Addr::PStrLocation(h, n)
|
Addr::PStrLocation(h, n)
|
||||||
}
|
}
|
||||||
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::PStrTail(..) => {
|
|
||||||
da
|
|
||||||
}
|
|
||||||
Addr::Str(s) => {
|
Addr::Str(s) => {
|
||||||
self.follow_heap(s) // record terms of structure.
|
self.follow_heap(s) // record terms of structure.
|
||||||
}
|
}
|
||||||
|
Addr::Con(h) => {
|
||||||
|
if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] {
|
||||||
|
if !self.machine_st.flags.double_quotes.is_atom() {
|
||||||
|
return if let Some(c) = pstr.range_from(0 ..).next() {
|
||||||
|
self.state_stack.push(Addr::PStrLocation(h, c.len_utf8()));
|
||||||
|
self.state_stack.push(Addr::Char(c));
|
||||||
|
|
||||||
|
Addr::PStrLocation(h, 0)
|
||||||
|
} else if has_tail {
|
||||||
|
self.follow(Addr::HeapCell(h + 1))
|
||||||
|
} else {
|
||||||
|
Addr::EmptyList
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr::Con(h)
|
||||||
|
}
|
||||||
|
da => {
|
||||||
|
da
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for HCPreOrderIterator<'a> {
|
impl<'a> Iterator for HCPreOrderIterator<'a> {
|
||||||
type Item = HeapCellValue;
|
type Item = Addr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.state_stack.pop().map(|a| match self.follow(a) {
|
self.state_stack.pop().map(|a| self.follow(a))
|
||||||
Addr::HeapCell(h) => {
|
|
||||||
HeapCellValue::Addr(self.machine_st.heap[h].as_addr(h))
|
|
||||||
}
|
|
||||||
Addr::Str(s) => {
|
|
||||||
match &self.machine_st.heap[s] {
|
|
||||||
val @ HeapCellValue::NamedStr(..) => {
|
|
||||||
val.clone()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::PStrTail(h, n) => {
|
|
||||||
match &self.machine_st.heap[h] {
|
|
||||||
HeapCellValue::PartialString(ref pstr) => {
|
|
||||||
if pstr.len() > n {
|
|
||||||
HeapCellValue::Addr(Addr::PStrLocation(h, n))
|
|
||||||
} else {
|
|
||||||
HeapCellValue::Addr(pstr.tail_addr().clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::StackCell(fr, sc) => {
|
|
||||||
HeapCellValue::Addr(self.machine_st.stack.index_and_frame(fr)[sc].clone())
|
|
||||||
}
|
|
||||||
da => {
|
|
||||||
HeapCellValue::Addr(da)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MutStackHCIterator
|
pub trait MutStackHCIterator
|
||||||
where
|
where Self: Iterator<Item = Addr>
|
||||||
Self: Iterator<Item = HeapCellValue>,
|
|
||||||
{
|
{
|
||||||
fn stack(&mut self) -> &mut Vec<Addr>;
|
fn stack(&mut self) -> &mut Vec<Addr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HCPostOrderIterator<HCIter> {
|
pub struct HCPostOrderIterator<'a> {
|
||||||
base_iter: HCIter,
|
base_iter: HCPreOrderIterator<'a>,
|
||||||
parent_stack: Vec<(usize, HeapCellValue)>, // number of children, parent node.
|
parent_stack: Vec<(usize, Addr)>, // number of children, parent node.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Deref for HCPostOrderIterator<HCIter> {
|
impl<'a> Deref for HCPostOrderIterator<'a> {
|
||||||
type Target = HCIter;
|
type Target = HCPreOrderIterator<'a>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.base_iter
|
&self.base_iter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
|
impl<'a> HCPostOrderIterator<'a> {
|
||||||
pub fn new(base_iter: HCIter) -> Self {
|
pub fn new(base_iter: HCPreOrderIterator<'a>) -> Self {
|
||||||
HCPostOrderIterator {
|
HCPostOrderIterator {
|
||||||
base_iter,
|
base_iter,
|
||||||
parent_stack: vec![],
|
parent_stack: vec![],
|
||||||
@@ -183,8 +148,8 @@ impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HCIter> {
|
impl<'a> Iterator for HCPostOrderIterator<'a> {
|
||||||
type Item = HeapCellValue;
|
type Item = Addr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
@@ -197,15 +162,30 @@ impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HC
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(item) = self.base_iter.next() {
|
if let Some(item) = self.base_iter.next() {
|
||||||
match item {
|
match self.base_iter.machine_st.heap.index_addr(&item).as_ref() {
|
||||||
HeapCellValue::NamedStr(arity, name, fix) => self
|
&HeapCellValue::NamedStr(arity, ..) => {
|
||||||
.parent_stack
|
self.parent_stack.push((arity, item));
|
||||||
.push((arity, HeapCellValue::NamedStr(arity, name, fix))),
|
}
|
||||||
HeapCellValue::Addr(Addr::Lis(a)) => self
|
&HeapCellValue::Addr(Addr::Lis(a)) => {
|
||||||
.parent_stack
|
self.parent_stack.push((2, Addr::Lis(a)));
|
||||||
.push((2, HeapCellValue::Addr(Addr::Lis(a)))),
|
}
|
||||||
child_node => {
|
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
||||||
return Some(child_node);
|
match &self.machine_st.heap[h] {
|
||||||
|
&HeapCellValue::PartialString(ref pstr, _) => {
|
||||||
|
let c = pstr.range_from(n ..).next().unwrap();
|
||||||
|
let next_n = n + c.len_utf8();
|
||||||
|
|
||||||
|
if !pstr.at_end(next_n) {
|
||||||
|
self.parent_stack.push((2, Addr::PStrLocation(h, next_n)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Some(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -215,21 +195,16 @@ impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HCProperPostOrderIterator<'a> = HCPostOrderIterator<HCPreOrderIterator<'a>>;
|
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
|
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
|
||||||
HCPreOrderIterator::new(self, a)
|
HCPreOrderIterator::new(self, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCProperPostOrderIterator<'a> {
|
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCPostOrderIterator<'a> {
|
||||||
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
|
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acyclic_pre_order_iter<'a>(
|
pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr,) -> HCAcyclicIterator<'a> {
|
||||||
&'a self,
|
|
||||||
a: Addr,
|
|
||||||
) -> HCAcyclicIterator<HCPreOrderIterator<'a>> {
|
|
||||||
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
|
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +212,7 @@ impl MachineState {
|
|||||||
&'a self,
|
&'a self,
|
||||||
a1: Addr,
|
a1: Addr,
|
||||||
a2: Addr,
|
a2: Addr,
|
||||||
) -> HCZippedAcyclicIterator<HCPreOrderIterator<'a>> {
|
) -> HCZippedAcyclicIterator<'a> {
|
||||||
HCZippedAcyclicIterator::new(
|
HCZippedAcyclicIterator::new(
|
||||||
HCPreOrderIterator::new(self, a1),
|
HCPreOrderIterator::new(self, a1),
|
||||||
HCPreOrderIterator::new(self, a2),
|
HCPreOrderIterator::new(self, a2),
|
||||||
@@ -251,13 +226,13 @@ impl<'a> MutStackHCIterator for HCPreOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HCAcyclicIterator<HCIter> {
|
pub struct HCAcyclicIterator<'a> {
|
||||||
iter: HCIter,
|
iter: HCPreOrderIterator<'a>,
|
||||||
seen: IndexSet<Addr>,
|
seen: IndexSet<Addr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
|
impl<'a> HCAcyclicIterator<'a> {
|
||||||
pub fn new(iter: HCIter) -> Self {
|
pub fn new(iter: HCPreOrderIterator<'a>) -> Self {
|
||||||
HCAcyclicIterator {
|
HCAcyclicIterator {
|
||||||
iter,
|
iter,
|
||||||
seen: IndexSet::new(),
|
seen: IndexSet::new(),
|
||||||
@@ -265,19 +240,17 @@ impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Deref for HCAcyclicIterator<HCIter> {
|
impl<'a> Deref for HCAcyclicIterator<'a> {
|
||||||
type Target = HCIter;
|
type Target = HCPreOrderIterator<'a>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.iter
|
&self.iter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Iterator for HCAcyclicIterator<HCIter>
|
impl<'a> Iterator for HCAcyclicIterator<'a>
|
||||||
where
|
|
||||||
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
|
|
||||||
{
|
{
|
||||||
type Item = HeapCellValue;
|
type Item = Addr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let Some(addr) = self.iter.stack().pop() {
|
while let Some(addr) = self.iter.stack().pop() {
|
||||||
@@ -293,15 +266,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HCZippedAcyclicIterator<HCIter> {
|
pub struct HCZippedAcyclicIterator<'a> {
|
||||||
i1: HCIter,
|
i1: HCPreOrderIterator<'a>,
|
||||||
i2: HCIter,
|
i2: HCPreOrderIterator<'a>,
|
||||||
seen: IndexSet<(Addr, Addr)>,
|
seen: IndexSet<(Addr, Addr)>,
|
||||||
pub first_to_expire: Ordering,
|
pub first_to_expire: Ordering,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
|
impl<'a> HCZippedAcyclicIterator<'a> {
|
||||||
pub fn new(i1: HCIter, i2: HCIter) -> Self {
|
pub fn new(i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>) -> Self {
|
||||||
HCZippedAcyclicIterator {
|
HCZippedAcyclicIterator {
|
||||||
i1,
|
i1,
|
||||||
i2,
|
i2,
|
||||||
@@ -311,11 +284,9 @@ impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter>
|
impl<'a> Iterator for HCZippedAcyclicIterator<'a>
|
||||||
where
|
|
||||||
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
|
|
||||||
{
|
{
|
||||||
type Item = (HeapCellValue, HeapCellValue);
|
type Item = (Addr, Addr);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let (Some(a1), Some(a2)) = (self.i1.stack().pop(), self.i2.stack().pop()) {
|
while let (Some(a1), Some(a2)) = (self.i1.stack().pop(), self.i2.stack().pop()) {
|
||||||
@@ -338,7 +309,9 @@ where
|
|||||||
self.first_to_expire = Ordering::Less;
|
self.first_to_expire = Ordering::Less;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,13 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::instructions::*;
|
use crate::prolog::instructions::*;
|
||||||
|
use crate::prolog::rug::Integer;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum IntIndex {
|
enum IntIndex {
|
||||||
@@ -48,6 +50,41 @@ impl CodeOffsets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercept_constant(&mut self, constant: &Constant, index: usize) {
|
||||||
|
match constant {
|
||||||
|
&Constant::Atom(ref name, _) if name.is_char() => {
|
||||||
|
let c = name.as_str().chars().next().unwrap();
|
||||||
|
let code = self.constants
|
||||||
|
.entry(Constant::Char(c))
|
||||||
|
.or_insert(vec![]);
|
||||||
|
|
||||||
|
code.push(Self::add_index(code.is_empty(), index));
|
||||||
|
}
|
||||||
|
&Constant::Fixnum(n) => {
|
||||||
|
let code = self.constants
|
||||||
|
.entry(Constant::Integer(Rc::new(Integer::from(n))))
|
||||||
|
.or_insert(vec![]);
|
||||||
|
|
||||||
|
code.push(Self::add_index(code.is_empty(), index));
|
||||||
|
}
|
||||||
|
&Constant::Integer(ref n) => {
|
||||||
|
if let Some(n) = n.to_isize() {
|
||||||
|
let code = self.constants
|
||||||
|
.entry(Constant::Fixnum(n))
|
||||||
|
.or_insert(vec![]);
|
||||||
|
|
||||||
|
code.push(Self::add_index(code.is_empty(), index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Constant::String(_) => {
|
||||||
|
let is_initial_index = self.lists.is_empty();
|
||||||
|
self.lists.push(Self::add_index(is_initial_index, index));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn index_term(&mut self, first_arg: &Term, index: usize) {
|
pub fn index_term(&mut self, first_arg: &Term, index: usize) {
|
||||||
match first_arg {
|
match first_arg {
|
||||||
&Term::Clause(_, ref name, ref terms, _) => {
|
&Term::Clause(_, ref name, ref terms, _) => {
|
||||||
@@ -63,18 +100,12 @@ impl CodeOffsets {
|
|||||||
let is_initial_index = self.lists.is_empty();
|
let is_initial_index = self.lists.is_empty();
|
||||||
self.lists.push(Self::add_index(is_initial_index, index));
|
self.lists.push(Self::add_index(is_initial_index, index));
|
||||||
}
|
}
|
||||||
&Term::Constant(_, Constant::String(n, ref s)) => {
|
|
||||||
let is_initial_index = self.lists.is_empty();
|
|
||||||
self.lists.push(Self::add_index(is_initial_index, index));
|
|
||||||
|
|
||||||
let constant = Constant::String(n, s.clone());
|
|
||||||
let code = self.constants.entry(constant).or_insert(Vec::new());
|
|
||||||
|
|
||||||
let is_initial_index = code.is_empty();
|
|
||||||
code.push(Self::add_index(is_initial_index, index));
|
|
||||||
}
|
|
||||||
&Term::Constant(_, ref constant) => {
|
&Term::Constant(_, ref constant) => {
|
||||||
let code = self.constants.entry(constant.clone()).or_insert(Vec::new());
|
self.intercept_constant(constant, index);
|
||||||
|
|
||||||
|
let code = self.constants
|
||||||
|
.entry(constant.clone())
|
||||||
|
.or_insert(vec![]);
|
||||||
|
|
||||||
let is_initial_index = code.is_empty();
|
let is_initial_index = code.is_empty();
|
||||||
code.push(Self::add_index(is_initial_index, index));
|
code.push(Self::add_index(is_initial_index, index));
|
||||||
@@ -227,12 +258,11 @@ impl CodeOffsets {
|
|||||||
fn switch_on_lst_offset_from(
|
fn switch_on_lst_offset_from(
|
||||||
lst_loc: IntIndex,
|
lst_loc: IntIndex,
|
||||||
prelude_len: usize,
|
prelude_len: usize,
|
||||||
lst_offset: usize,
|
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match lst_loc {
|
match lst_loc {
|
||||||
IntIndex::External(o) => o + prelude_len + 1,
|
IntIndex::External(o) => o + prelude_len + 1,
|
||||||
IntIndex::Fail => 0,
|
IntIndex::Fail => 0,
|
||||||
IntIndex::Internal(_) => prelude_len - lst_offset + 1,
|
IntIndex::Internal(_) => 1, // this internal is always 0.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,8 +275,6 @@ impl CodeOffsets {
|
|||||||
let mut prelude = VecDeque::new();
|
let mut prelude = VecDeque::new();
|
||||||
|
|
||||||
let lst_loc = Self::switch_on_list(self.lists, &mut prelude);
|
let lst_loc = Self::switch_on_list(self.lists, &mut prelude);
|
||||||
let lst_offset = prelude.len();
|
|
||||||
|
|
||||||
let str_loc = Self::switch_on_structure(self.structures, &mut prelude);
|
let str_loc = Self::switch_on_structure(self.structures, &mut prelude);
|
||||||
let con_loc = Self::switch_on_constant(self.constants, &mut prelude);
|
let con_loc = Self::switch_on_constant(self.constants, &mut prelude);
|
||||||
|
|
||||||
@@ -254,18 +282,19 @@ impl CodeOffsets {
|
|||||||
|
|
||||||
for (index, line) in prelude.iter_mut().enumerate() {
|
for (index, line) in prelude.iter_mut().enumerate() {
|
||||||
match line {
|
match line {
|
||||||
&mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i))
|
&mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i)) |
|
||||||
| &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i))
|
&mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i)) |
|
||||||
| &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => {
|
&mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => {
|
||||||
*i += prelude_length - index
|
*i += prelude_length - index;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let str_loc = Self::switch_on_str_offset_from(str_loc, prelude.len(), con_loc);
|
let str_loc = Self::switch_on_str_offset_from(str_loc, prelude.len(), con_loc);
|
||||||
let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len());
|
let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len());
|
||||||
let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len(), lst_offset);
|
let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len());
|
||||||
|
|
||||||
let switch_instr =
|
let switch_instr =
|
||||||
IndexingInstruction::SwitchOnTerm(prelude.len() + 1, con_loc, lst_loc, str_loc);
|
IndexingInstruction::SwitchOnTerm(prelude.len() + 1, con_loc, lst_loc, str_loc);
|
||||||
|
|||||||
@@ -2,28 +2,29 @@ use prolog_parser::ast::*;
|
|||||||
|
|
||||||
use crate::prolog::clause_types::*;
|
use crate::prolog::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_errors::MachineStub;
|
use crate::prolog::machine::machine_errors::MachineStub;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
||||||
match r {
|
match r {
|
||||||
RegType::Temp(r) => functor!("x", 1, [heap_integer!(Integer::from(r))]),
|
RegType::Temp(r) => functor!("x", [integer(r)]),
|
||||||
RegType::Perm(r) => functor!("y", 1, [heap_integer!(Integer::from(r))]),
|
RegType::Perm(r) => functor!("y", [integer(r)]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Level {
|
impl Level {
|
||||||
fn into_functor(self) -> MachineStub {
|
fn into_functor(self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
Level::Root => functor!("level", 1, [heap_atom!("root")]),
|
Level::Root => functor!("level", [atom("root")]),
|
||||||
Level::Shallow => functor!("level", 1, [heap_atom!("shallow")]),
|
Level::Shallow => functor!("level", [atom("shallow")]),
|
||||||
Level::Deep => functor!("level", 1, [heap_atom!("deep")]),
|
Level::Deep => functor!("level", [atom("deep")]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,11 +32,15 @@ impl Level {
|
|||||||
impl ArithmeticTerm {
|
impl ArithmeticTerm {
|
||||||
fn into_functor(&self) -> MachineStub {
|
fn into_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
|
&ArithmeticTerm::Reg(r) => {
|
||||||
&ArithmeticTerm::Interm(i) => {
|
reg_type_into_functor(r)
|
||||||
functor!("intermediate", 1, [heap_integer!(Integer::from(i))])
|
}
|
||||||
|
&ArithmeticTerm::Interm(i) => {
|
||||||
|
functor!("intermediate", [integer(i)])
|
||||||
|
}
|
||||||
|
&ArithmeticTerm::Number(ref n) => {
|
||||||
|
vec![n.clone().into()]
|
||||||
}
|
}
|
||||||
&ArithmeticTerm::Number(ref n) => vec![heap_con!(n.clone().to_constant())],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,18 +57,20 @@ impl ChoiceInstruction {
|
|||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&ChoiceInstruction::TryMeElse(offset) => {
|
&ChoiceInstruction::TryMeElse(offset) => {
|
||||||
functor!("try_me_else", 1, [heap_integer!(Integer::from(offset))])
|
functor!("try_me_else", [integer(offset)])
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::RetryMeElse(offset) => {
|
&ChoiceInstruction::RetryMeElse(offset) => {
|
||||||
functor!("retry_me_else", 1, [heap_integer!(Integer::from(offset))])
|
functor!("retry_me_else", [integer(offset)])
|
||||||
|
}
|
||||||
|
&ChoiceInstruction::TrustMe => {
|
||||||
|
functor!("trust_me")
|
||||||
|
}
|
||||||
|
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
||||||
|
functor!("default_retry_me_else", [integer(offset)])
|
||||||
|
}
|
||||||
|
&ChoiceInstruction::DefaultTrustMe => {
|
||||||
|
functor!("default_trust_me")
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::TrustMe => vec![heap_atom!("trust_me")],
|
|
||||||
&ChoiceInstruction::DefaultRetryMeElse(offset) => functor!(
|
|
||||||
"default_retry_me_else",
|
|
||||||
1,
|
|
||||||
[heap_integer!(Integer::from(offset))]
|
|
||||||
),
|
|
||||||
&ChoiceInstruction::DefaultTrustMe => vec![heap_atom!("default_trust_me")],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,21 +86,20 @@ impl CutInstruction {
|
|||||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
pub fn to_functor(&self, h: usize) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&CutInstruction::Cut(r) => {
|
&CutInstruction::Cut(r) => {
|
||||||
let mut stub = functor!("cut", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!("cut", [aux(h, 0)], [rt_stub])
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&CutInstruction::GetLevel(r) => {
|
&CutInstruction::GetLevel(r) => {
|
||||||
let mut stub = functor!("get_level", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!("get_level", [aux(h, 0)], [rt_stub])
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&CutInstruction::GetLevelAndUnify(r) => {
|
&CutInstruction::GetLevelAndUnify(r) => {
|
||||||
let mut stub = functor!("get_level_and_unify", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!("get_level_and_unify", [aux(h, 0)], [rt_stub])
|
||||||
stub
|
}
|
||||||
|
&CutInstruction::NeckCut => {
|
||||||
|
functor!("neck_cut")
|
||||||
}
|
}
|
||||||
&CutInstruction::NeckCut => vec![heap_atom!("neck_cut")],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,13 +128,13 @@ impl IndexedChoiceInstruction {
|
|||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&IndexedChoiceInstruction::Try(offset) => {
|
&IndexedChoiceInstruction::Try(offset) => {
|
||||||
functor!("try", 1, [heap_integer!(Integer::from(offset))])
|
functor!("try", [integer(offset)])
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Trust(offset) => {
|
&IndexedChoiceInstruction::Trust(offset) => {
|
||||||
functor!("trust", 1, [heap_integer!(Integer::from(offset))])
|
functor!("trust", [integer(offset)])
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Retry(offset) => {
|
&IndexedChoiceInstruction::Retry(offset) => {
|
||||||
functor!("retry", 1, [heap_integer!(Integer::from(offset))])
|
functor!("retry", [integer(offset)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,14 +226,11 @@ fn arith_instr_unary_functor(
|
|||||||
) -> MachineStub {
|
) -> MachineStub {
|
||||||
let at_stub = at.into_functor();
|
let at_stub = at.into_functor();
|
||||||
|
|
||||||
let mut stub = functor!(
|
functor!(
|
||||||
name,
|
name,
|
||||||
2,
|
[aux(h, 0), integer(t)],
|
||||||
[heap_cell!(h + 4), heap_integer!(Integer::from(t))]
|
[at_stub]
|
||||||
);
|
)
|
||||||
|
|
||||||
stub.extend(at_stub.into_iter());
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arith_instr_bin_functor(
|
fn arith_instr_bin_functor(
|
||||||
@@ -240,20 +243,11 @@ fn arith_instr_bin_functor(
|
|||||||
let at_1_stub = at_1.into_functor();
|
let at_1_stub = at_1.into_functor();
|
||||||
let at_2_stub = at_2.into_functor();
|
let at_2_stub = at_2.into_functor();
|
||||||
|
|
||||||
let mut stub = functor!(
|
functor!(
|
||||||
name,
|
name,
|
||||||
3,
|
[aux(h, 0), aux(h, 1), integer(t)],
|
||||||
[
|
[at_1_stub, at_2_stub]
|
||||||
heap_cell!(h + 4),
|
)
|
||||||
heap_cell!(h + 4 + at_1_stub.len()),
|
|
||||||
heap_integer!(Integer::from(t))
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.extend(at_1_stub.into_iter());
|
|
||||||
stub.extend(at_2_stub.into_iter());
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArithmeticInstruction {
|
impl ArithmeticInstruction {
|
||||||
@@ -319,17 +313,39 @@ impl ArithmeticInstruction {
|
|||||||
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
|
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
|
||||||
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
|
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
|
||||||
}
|
}
|
||||||
&ArithmeticInstruction::Sign(ref at, t) => arith_instr_unary_functor(h, "sign", at, t),
|
&ArithmeticInstruction::Sign(ref at, t) => {
|
||||||
&ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t),
|
arith_instr_unary_functor(h, "sign", at, t)
|
||||||
&ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t),
|
}
|
||||||
&ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t),
|
&ArithmeticInstruction::Cos(ref at, t) => {
|
||||||
&ArithmeticInstruction::Log(ref at, t) => arith_instr_unary_functor(h, "log", at, t),
|
arith_instr_unary_functor(h, "cos", at, t)
|
||||||
&ArithmeticInstruction::Exp(ref at, t) => arith_instr_unary_functor(h, "exp", at, t),
|
}
|
||||||
&ArithmeticInstruction::ACos(ref at, t) => arith_instr_unary_functor(h, "acos", at, t),
|
&ArithmeticInstruction::Sin(ref at, t) => {
|
||||||
&ArithmeticInstruction::ASin(ref at, t) => arith_instr_unary_functor(h, "asin", at, t),
|
arith_instr_unary_functor(h, "sin", at, t)
|
||||||
&ArithmeticInstruction::ATan(ref at, t) => arith_instr_unary_functor(h, "atan", at, t),
|
}
|
||||||
&ArithmeticInstruction::Sqrt(ref at, t) => arith_instr_unary_functor(h, "sqrt", at, t),
|
&ArithmeticInstruction::Tan(ref at, t) => {
|
||||||
&ArithmeticInstruction::Abs(ref at, t) => arith_instr_unary_functor(h, "abs", at, t),
|
arith_instr_unary_functor(h, "tan", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Log(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "log", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Exp(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "exp", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::ACos(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "acos", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::ASin(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "asin", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::ATan(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "atan", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Sqrt(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "sqrt", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Abs(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "abs", at, t)
|
||||||
|
}
|
||||||
&ArithmeticInstruction::Float(ref at, t) => {
|
&ArithmeticInstruction::Float(ref at, t) => {
|
||||||
arith_instr_unary_functor(h, "float", at, t)
|
arith_instr_unary_functor(h, "float", at, t)
|
||||||
}
|
}
|
||||||
@@ -345,8 +361,12 @@ impl ArithmeticInstruction {
|
|||||||
&ArithmeticInstruction::Floor(ref at, t) => {
|
&ArithmeticInstruction::Floor(ref at, t) => {
|
||||||
arith_instr_unary_functor(h, "floor", at, t)
|
arith_instr_unary_functor(h, "floor", at, t)
|
||||||
}
|
}
|
||||||
&ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(h, "-", at, t),
|
&ArithmeticInstruction::Neg(ref at, t) => {
|
||||||
&ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(h, "+", at, t),
|
arith_instr_unary_functor(h, "-", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Plus(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "+", at, t)
|
||||||
|
}
|
||||||
&ArithmeticInstruction::BitwiseComplement(ref at, t) => {
|
&ArithmeticInstruction::BitwiseComplement(ref at, t) => {
|
||||||
arith_instr_unary_functor(h, "\\", at, t)
|
arith_instr_unary_functor(h, "\\", at, t)
|
||||||
}
|
}
|
||||||
@@ -378,29 +398,23 @@ impl ControlInstruction {
|
|||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&ControlInstruction::Allocate(num_frames) => {
|
&ControlInstruction::Allocate(num_frames) => {
|
||||||
functor!("allocate", 1, [heap_integer!(Integer::from(num_frames))])
|
functor!("allocate", [integer(num_frames)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => {
|
||||||
|
functor!("call", [clause_name(ct.name()), integer(arity)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => {
|
||||||
|
functor!("execute", [clause_name(ct.name()), integer(arity)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::Deallocate => {
|
||||||
|
functor!("deallocate")
|
||||||
}
|
}
|
||||||
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => functor!(
|
|
||||||
"call",
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => functor!(
|
|
||||||
"execute",
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
&ControlInstruction::Deallocate => vec![heap_atom!("deallocate")],
|
|
||||||
&ControlInstruction::JmpBy(_, offset, ..) => {
|
&ControlInstruction::JmpBy(_, offset, ..) => {
|
||||||
functor!("jmp_by", 1, [heap_integer!(Integer::from(offset))])
|
functor!("jmp_by", [integer(offset)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::Proceed => {
|
||||||
|
functor!("proceed")
|
||||||
}
|
}
|
||||||
&ControlInstruction::Proceed => vec![heap_atom!("proceed")],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,26 +434,27 @@ impl From<IndexingInstruction> for Line {
|
|||||||
impl IndexingInstruction {
|
impl IndexingInstruction {
|
||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => functor!(
|
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => {
|
||||||
|
functor!(
|
||||||
"switch_on_term",
|
"switch_on_term",
|
||||||
4,
|
[integer(vars),
|
||||||
[
|
integer(constants),
|
||||||
heap_integer!(Integer::from(vars)),
|
integer(lists),
|
||||||
heap_integer!(Integer::from(constants)),
|
integer(structures)]
|
||||||
heap_integer!(Integer::from(lists)),
|
)
|
||||||
heap_integer!(Integer::from(structures))
|
}
|
||||||
]
|
&IndexingInstruction::SwitchOnConstant(constants, _) => {
|
||||||
),
|
functor!(
|
||||||
&IndexingInstruction::SwitchOnConstant(constants, _) => functor!(
|
|
||||||
"switch_on_constant",
|
"switch_on_constant",
|
||||||
1,
|
[integer(constants)]
|
||||||
[heap_integer!(Integer::from(constants))]
|
)
|
||||||
),
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(structures, _) => functor!(
|
&IndexingInstruction::SwitchOnStructure(structures, _) => {
|
||||||
|
functor!(
|
||||||
"switch_on_structure",
|
"switch_on_structure",
|
||||||
1,
|
[integer(structures)]
|
||||||
[heap_integer!(Integer::from(structures))]
|
)
|
||||||
),
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,6 +463,7 @@ impl IndexingInstruction {
|
|||||||
pub enum FactInstruction {
|
pub enum FactInstruction {
|
||||||
GetConstant(Level, Constant, RegType),
|
GetConstant(Level, Constant, RegType),
|
||||||
GetList(Level, RegType),
|
GetList(Level, RegType),
|
||||||
|
GetPartialString(Level, String, RegType, bool),
|
||||||
GetStructure(ClauseType, usize, RegType),
|
GetStructure(ClauseType, usize, RegType),
|
||||||
GetValue(RegType, usize),
|
GetValue(RegType, usize),
|
||||||
GetVariable(RegType, usize),
|
GetVariable(RegType, usize),
|
||||||
@@ -461,86 +477,95 @@ pub enum FactInstruction {
|
|||||||
impl FactInstruction {
|
impl FactInstruction {
|
||||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
pub fn to_functor(&self, h: usize) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&FactInstruction::GetConstant(lvl, ref constant, r) => {
|
&FactInstruction::GetConstant(lvl, ref c, r) => {
|
||||||
let mut stub = functor!(
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
|
functor!(
|
||||||
"get_constant",
|
"get_constant",
|
||||||
3,
|
[aux(h, 0), constant(h, c), aux(h, 1)],
|
||||||
[
|
[lvl_stub, rt_stub]
|
||||||
heap_str!(h + 4),
|
)
|
||||||
heap_con!(constant.clone()),
|
|
||||||
heap_str!(h + 6)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut lvl.into_functor());
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&FactInstruction::GetList(lvl, r) => {
|
&FactInstruction::GetList(lvl, r) => {
|
||||||
let mut stub = functor!("get_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
|
let lvl_stub = lvl.into_functor();
|
||||||
stub.append(&mut lvl.into_functor());
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_list",
|
||||||
|
[aux(h, 0), aux(h, 1)],
|
||||||
|
[lvl_stub, rt_stub]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
&FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => {
|
||||||
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
|
functor!(
|
||||||
|
"get_partial_string",
|
||||||
|
[aux(h, 0), string(h, s), aux(h, 1), boolean(has_tail)],
|
||||||
|
[lvl_stub, rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetStructure(ref ct, arity, r) => {
|
&FactInstruction::GetStructure(ref ct, arity, r) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_structure",
|
|
||||||
3,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity)),
|
|
||||||
heap_str!(h + 4)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_structure",
|
||||||
|
[clause_name(ct.name()), integer(arity), aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetValue(r, arg) => {
|
&FactInstruction::GetValue(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_value",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_value",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetVariable(r, arg) => {
|
&FactInstruction::GetVariable(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_variable",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_variable",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyConstant(ref constant) => {
|
&FactInstruction::UnifyConstant(ref c) => {
|
||||||
functor!("unify_constant", 1, [heap_con!(constant.clone())])
|
functor!("unify_constant", [constant(h, c)], [])
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyLocalValue(r) => {
|
&FactInstruction::UnifyLocalValue(r) => {
|
||||||
let mut stub = functor!("unify_local_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"unify_local_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVariable(r) => {
|
&FactInstruction::UnifyVariable(r) => {
|
||||||
let mut stub = functor!("unify_variable", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"unify_variable",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyValue(r) => {
|
&FactInstruction::UnifyValue(r) => {
|
||||||
let mut stub = functor!("unify_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"unify_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVoid(vars) => {
|
&FactInstruction::UnifyVoid(vars) => {
|
||||||
functor!("unify_void", 1, [heap_integer!(Integer::from(vars))])
|
functor!("unify_void", [integer(vars)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -551,6 +576,7 @@ pub enum QueryInstruction {
|
|||||||
GetVariable(RegType, usize),
|
GetVariable(RegType, usize),
|
||||||
PutConstant(Level, Constant, RegType),
|
PutConstant(Level, Constant, RegType),
|
||||||
PutList(Level, RegType),
|
PutList(Level, RegType),
|
||||||
|
PutPartialString(Level, String, RegType, bool),
|
||||||
PutStructure(ClauseType, usize, RegType),
|
PutStructure(ClauseType, usize, RegType),
|
||||||
PutUnsafeValue(usize, usize),
|
PutUnsafeValue(usize, usize),
|
||||||
PutValue(RegType, usize),
|
PutValue(RegType, usize),
|
||||||
@@ -567,103 +593,106 @@ impl QueryInstruction {
|
|||||||
match self {
|
match self {
|
||||||
&QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
|
&QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
|
||||||
"put_unsafe_value",
|
"put_unsafe_value",
|
||||||
2,
|
[integer(norm), integer(arg)]
|
||||||
[
|
|
||||||
heap_integer!(Integer::from(norm)),
|
|
||||||
heap_integer!(Integer::from(arg))
|
|
||||||
]
|
|
||||||
),
|
),
|
||||||
&QueryInstruction::PutConstant(lvl, ref constant, r) => {
|
&QueryInstruction::PutConstant(lvl, ref c, r) => {
|
||||||
let mut stub = functor!(
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
|
functor!(
|
||||||
"put_constant",
|
"put_constant",
|
||||||
3,
|
[aux(h, 0), constant(h, c), aux(h, 1)],
|
||||||
[
|
[lvl_stub, rt_stub]
|
||||||
heap_str!(h + 4),
|
)
|
||||||
heap_con!(constant.clone()),
|
|
||||||
heap_str!(h + 6)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut lvl.into_functor());
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutList(lvl, r) => {
|
&QueryInstruction::PutList(lvl, r) => {
|
||||||
let mut stub = functor!("put_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut lvl.into_functor());
|
functor!(
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
"put_list",
|
||||||
|
[aux(h, 0), aux(h, 1)],
|
||||||
|
[lvl_stub, rt_stub]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
&QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => {
|
||||||
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"put_partial_string",
|
||||||
|
[aux(h, 0), string(h, s), aux(h, 1), boolean(has_tail)],
|
||||||
|
[lvl_stub, rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutStructure(ref ct, arity, r) => {
|
&QueryInstruction::PutStructure(ref ct, arity, r) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"put_structure",
|
|
||||||
3,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity)),
|
|
||||||
heap_str!(h + 4)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"put_structure",
|
||||||
|
[clause_name(ct.name()), integer(arity), aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutValue(r, arg) => {
|
&QueryInstruction::PutValue(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"put_value",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"put_value",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::GetVariable(r, arg) => {
|
&QueryInstruction::GetVariable(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_variable",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"get_variable",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutVariable(r, arg) => {
|
&QueryInstruction::PutVariable(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"put_variable",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"put_variable",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetConstant(ref constant) => {
|
&QueryInstruction::SetConstant(ref c) => {
|
||||||
functor!("set_constant", 1, [heap_con!(constant.clone())])
|
functor!("set_constant", [constant(h, c)], [])
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetLocalValue(r) => {
|
&QueryInstruction::SetLocalValue(r) => {
|
||||||
let mut stub = functor!("set_local_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"set_local_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetVariable(r) => {
|
&QueryInstruction::SetVariable(r) => {
|
||||||
let mut stub = functor!("set_variable", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"set_variable",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetValue(r) => {
|
&QueryInstruction::SetValue(r) => {
|
||||||
let mut stub = functor!("set_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"set_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetVoid(vars) => {
|
&QueryInstruction::SetVoid(vars) => {
|
||||||
functor!("set_void", 1, [heap_integer!(Integer::from(vars))])
|
functor!("set_void", [integer(vars)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub enum TermRef<'a> {
|
|||||||
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||||
Constant(Level, &'a Cell<RegType>, &'a Constant),
|
Constant(Level, &'a Cell<RegType>, &'a Constant),
|
||||||
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
|
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
|
||||||
|
PartialString(Level, &'a Cell<RegType>, String, Option<&'a Term>),
|
||||||
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ impl<'a> TermRef<'a> {
|
|||||||
| TermRef::Constant(lvl, ..)
|
| TermRef::Constant(lvl, ..)
|
||||||
| TermRef::Var(lvl, ..)
|
| TermRef::Var(lvl, ..)
|
||||||
| TermRef::Clause(lvl, ..) => lvl,
|
| TermRef::Clause(lvl, ..) => lvl,
|
||||||
|
| TermRef::PartialString(lvl, ..) => lvl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,13 +45,63 @@ pub enum TermIterState<'a> {
|
|||||||
),
|
),
|
||||||
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||||
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||||
|
PartialString(Level, &'a Cell<RegType>, String, Option<&'a Term>),
|
||||||
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_partial_string<'a>(
|
||||||
|
head: &'a Term,
|
||||||
|
mut tail: &'a Term,
|
||||||
|
) -> Option<(String, Option<&'a Term>)>
|
||||||
|
{
|
||||||
|
let mut string =
|
||||||
|
match head {
|
||||||
|
&Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => {
|
||||||
|
atom.as_str().chars().next().unwrap().to_string()
|
||||||
|
}
|
||||||
|
&Term::Constant(_, Constant::Char(c)) => {
|
||||||
|
c.to_string()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Term::Cons(_, ref head, ref succ) = tail {
|
||||||
|
match head.as_ref() {
|
||||||
|
&Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => {
|
||||||
|
string.push(atom.as_str().chars().next().unwrap());
|
||||||
|
}
|
||||||
|
&Term::Constant(_, Constant::Char(c)) => {
|
||||||
|
string.push(c);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tail = succ.as_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
match tail {
|
||||||
|
Term::AnonVar | Term::Var(..) => {
|
||||||
|
return Some((string, Some(tail)));
|
||||||
|
}
|
||||||
|
Term::Constant(_, Constant::EmptyList) => {
|
||||||
|
return Some((string, None));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> TermIterState<'a> {
|
impl<'a> TermIterState<'a> {
|
||||||
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
|
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
|
||||||
match term {
|
match term {
|
||||||
&Term::AnonVar => TermIterState::AnonVar(lvl),
|
&Term::AnonVar => {
|
||||||
|
TermIterState::AnonVar(lvl)
|
||||||
|
}
|
||||||
&Term::Clause(ref cell, ref name, ref subterms, ref spec) => {
|
&Term::Clause(ref cell, ref name, ref subterms, ref spec) => {
|
||||||
let ct = if let Some(spec) = spec {
|
let ct = if let Some(spec) = spec {
|
||||||
ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default())
|
ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default())
|
||||||
@@ -62,8 +114,12 @@ impl<'a> TermIterState<'a> {
|
|||||||
&Term::Cons(ref cell, ref head, ref tail) => {
|
&Term::Cons(ref cell, ref head, ref tail) => {
|
||||||
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
|
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
|
||||||
}
|
}
|
||||||
&Term::Constant(ref cell, ref constant) => TermIterState::Constant(lvl, cell, constant),
|
&Term::Constant(ref cell, ref constant) => {
|
||||||
&Term::Var(ref cell, ref var) => TermIterState::Var(lvl, cell, var.clone()),
|
TermIterState::Constant(lvl, cell, constant)
|
||||||
|
}
|
||||||
|
&Term::Var(ref cell, ref var) => {
|
||||||
|
TermIterState::Var(lvl, cell, var.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,7 +225,9 @@ impl<'a> Iterator for QueryIterator<'a> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let Some(iter_state) = self.state_stack.pop() {
|
while let Some(iter_state) = self.state_stack.pop() {
|
||||||
match iter_state {
|
match iter_state {
|
||||||
TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
|
TermIterState::AnonVar(lvl) => {
|
||||||
|
return Some(TermRef::AnonVar(lvl));
|
||||||
|
}
|
||||||
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
|
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
|
||||||
if child_num == child_terms.len() {
|
if child_num == child_terms.len() {
|
||||||
match ct {
|
match ct {
|
||||||
@@ -182,7 +240,9 @@ impl<'a> Iterator for QueryIterator<'a> {
|
|||||||
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)),
|
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return None,
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
self.state_stack.push(TermIterState::Clause(
|
self.state_stack.push(TermIterState::Clause(
|
||||||
@@ -192,23 +252,41 @@ impl<'a> Iterator for QueryIterator<'a> {
|
|||||||
ct,
|
ct,
|
||||||
child_terms,
|
child_terms,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
|
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||||
self.state_stack
|
if let Some((string, tail)) = is_partial_string(head, tail) {
|
||||||
.push(TermIterState::FinalCons(lvl, cell, head, tail));
|
self.state_stack.push(TermIterState::PartialString(
|
||||||
|
lvl,
|
||||||
|
cell,
|
||||||
|
string,
|
||||||
|
tail,
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Some(tail) = tail {
|
||||||
|
self.push_subterm(lvl.child_level(), tail);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
|
||||||
|
|
||||||
self.push_subterm(lvl.child_level(), tail);
|
self.push_subterm(lvl.child_level(), tail);
|
||||||
self.push_subterm(lvl.child_level(), head);
|
self.push_subterm(lvl.child_level(), head);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
TermIterState::PartialString(lvl, cell, string, tail) => {
|
||||||
|
return Some(TermRef::PartialString(lvl, cell, string, tail));
|
||||||
|
}
|
||||||
TermIterState::FinalCons(lvl, cell, head, tail) => {
|
TermIterState::FinalCons(lvl, cell, head, tail) => {
|
||||||
return Some(TermRef::Cons(lvl, cell, head, tail))
|
return Some(TermRef::Cons(lvl, cell, head, tail));
|
||||||
}
|
}
|
||||||
TermIterState::Constant(lvl, cell, constant) => {
|
TermIterState::Constant(lvl, cell, constant) => {
|
||||||
return Some(TermRef::Constant(lvl, cell, constant))
|
return Some(TermRef::Constant(lvl, cell, constant));
|
||||||
|
}
|
||||||
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
|
return Some(TermRef::Var(lvl, cell, var));
|
||||||
}
|
}
|
||||||
TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,8 +301,7 @@ pub struct FactIterator<'a> {
|
|||||||
|
|
||||||
impl<'a> FactIterator<'a> {
|
impl<'a> FactIterator<'a> {
|
||||||
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
||||||
self.state_queue
|
self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
|
||||||
.push_back(TermIterState::subterm_to_state(lvl, term));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
|
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
|
||||||
@@ -241,7 +318,9 @@ impl<'a> FactIterator<'a> {
|
|||||||
|
|
||||||
fn new(term: &'a Term, iterable_root: bool) -> Self {
|
fn new(term: &'a Term, iterable_root: bool) -> Self {
|
||||||
let states = match term {
|
let states = match term {
|
||||||
&Term::AnonVar => vec![TermIterState::AnonVar(Level::Root)],
|
&Term::AnonVar => {
|
||||||
|
vec![TermIterState::AnonVar(Level::Root)]
|
||||||
|
}
|
||||||
&Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
|
&Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
|
||||||
let ct = ClauseType::from(name.clone(), terms.len(), fixity.clone());
|
let ct = ClauseType::from(name.clone(), terms.len(), fixity.clone());
|
||||||
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
|
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
|
||||||
@@ -273,7 +352,9 @@ impl<'a> Iterator for FactIterator<'a> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let Some(state) = self.state_queue.pop_front() {
|
while let Some(state) = self.state_queue.pop_front() {
|
||||||
match state {
|
match state {
|
||||||
TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
|
TermIterState::AnonVar(lvl) => {
|
||||||
|
return Some(TermRef::AnonVar(lvl));
|
||||||
|
}
|
||||||
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
|
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
|
||||||
for child_term in child_terms {
|
for child_term in child_terms {
|
||||||
self.push_subterm(lvl.child_level(), child_term);
|
self.push_subterm(lvl.child_level(), child_term);
|
||||||
@@ -285,16 +366,27 @@ impl<'a> Iterator for FactIterator<'a> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||||
|
if let Some((string, tail)) = is_partial_string(head, tail) {
|
||||||
|
if let Some(tail) = tail {
|
||||||
|
self.push_subterm(Level::Deep, tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(TermRef::PartialString(lvl, cell, string, tail));
|
||||||
|
} else {
|
||||||
self.push_subterm(Level::Deep, head);
|
self.push_subterm(Level::Deep, head);
|
||||||
self.push_subterm(Level::Deep, tail);
|
self.push_subterm(Level::Deep, tail);
|
||||||
|
|
||||||
return Some(TermRef::Cons(lvl, cell, head, tail));
|
return Some(TermRef::Cons(lvl, cell, head, tail));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
TermIterState::Constant(lvl, cell, constant) => {
|
TermIterState::Constant(lvl, cell, constant) => {
|
||||||
return Some(TermRef::Constant(lvl, cell, constant))
|
return Some(TermRef::Constant(lvl, cell, constant))
|
||||||
}
|
}
|
||||||
TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
_ => {}
|
return Some(TermRef::Var(lvl, cell, var));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,4 +158,3 @@ call_residue_vars(Goal, Vars) :-
|
|||||||
'$get_attr_var_queue_delim'(B),
|
'$get_attr_var_queue_delim'(B),
|
||||||
call(Goal),
|
call(Goal),
|
||||||
'$get_attr_var_queue_beyond'(B, Vars).
|
'$get_attr_var_queue_beyond'(B, Vars).
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,10 @@
|
|||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
|
|
||||||
between(Lower, Upper, X) :-
|
between(Lower, Upper, X) :-
|
||||||
( Upper == inf ->
|
|
||||||
must_be(integer, Lower),
|
must_be(integer, Lower),
|
||||||
can_be(integer, X),
|
|
||||||
enumerate_nats(Lower, X)
|
|
||||||
; must_be(integer, Lower),
|
|
||||||
must_be(integer, Upper),
|
must_be(integer, Upper),
|
||||||
can_be(integer, X),
|
can_be(integer, X),
|
||||||
between_(Lower, Upper, X)
|
between_(Lower, Upper, X).
|
||||||
).
|
|
||||||
|
|
||||||
between_(Lower, Upper, Lower) :-
|
between_(Lower, Upper, Lower) :-
|
||||||
Lower =< Upper.
|
Lower =< Upper.
|
||||||
|
|||||||
@@ -44,15 +44,16 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
|
|||||||
abolish/1, asserta/1, assertz/1, atom_chars/2,
|
abolish/1, asserta/1, assertz/1, atom_chars/2,
|
||||||
atom_codes/2, atom_concat/3, atom_length/2,
|
atom_codes/2, atom_concat/3, atom_length/2,
|
||||||
bagof/3, catch/3, char_code/2, clause/2,
|
bagof/3, catch/3, char_code/2, clause/2,
|
||||||
current_op/3, current_predicate/1,
|
current_input/1, current_output/1, current_op/3,
|
||||||
current_prolog_flag/2, expand_goal/2,
|
current_predicate/1, current_prolog_flag/2,
|
||||||
expand_term/2, fail/0, false/0, findall/3,
|
expand_goal/2, expand_term/2, fail/0, false/0,
|
||||||
findall/4, get_char/1, halt/0, max_arity/1,
|
findall/3, findall/4, get_char/1, halt/0,
|
||||||
number_chars/2, number_codes/2, once/1, op/3,
|
max_arity/1, number_chars/2, number_codes/2,
|
||||||
read_term/2, repeat/0, retract/1,
|
once/1, op/3, read_term/2, repeat/0, retract/1,
|
||||||
set_prolog_flag/2, setof/3, sub_atom/5,
|
set_prolog_flag/2, set_input/1, set_output/1,
|
||||||
subsumes_term/2, term_variables/2, throw/1,
|
setof/3, sub_atom/5, subsumes_term/2,
|
||||||
true/0, unify_with_occurs_check/2, write/1,
|
term_variables/2, throw/1, true/0,
|
||||||
|
unify_with_occurs_check/2, write/1,
|
||||||
write_canonical/1, write_term/2, writeq/1]).
|
write_canonical/1, write_term/2, writeq/1]).
|
||||||
|
|
||||||
|
|
||||||
@@ -261,8 +262,11 @@ univ_errors(Term, List, N) :-
|
|||||||
Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
|
Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
|
||||||
'$call_with_default_policy'(univ_worker(Term, List, N)).
|
'$call_with_default_policy'(univ_worker(Term, List, N)).
|
||||||
|
|
||||||
|
|
||||||
:- non_counted_backtracking univ_worker/3.
|
:- non_counted_backtracking univ_worker/3.
|
||||||
univ_worker(Term, List, _) :- atomic(Term), !, '$call_with_default_policy'(List = [Term]).
|
|
||||||
|
univ_worker(Term, List, _) :-
|
||||||
|
atomic(Term), !, '$call_with_default_policy'(List = [Term]).
|
||||||
univ_worker(Term, [Name|Args], N) :-
|
univ_worker(Term, [Name|Args], N) :-
|
||||||
var(Term), !,
|
var(Term), !,
|
||||||
'$call_with_default_policy'(Arity is N-1),
|
'$call_with_default_policy'(Arity is N-1),
|
||||||
@@ -273,7 +277,9 @@ univ_worker(Term, List, _) :-
|
|||||||
'$call_with_default_policy'(get_args(Args, Term, 1, Arity)),
|
'$call_with_default_policy'(get_args(Args, Term, 1, Arity)),
|
||||||
'$call_with_default_policy'(List = [Name|Args]).
|
'$call_with_default_policy'(List = [Name|Args]).
|
||||||
|
|
||||||
|
|
||||||
:- non_counted_backtracking get_args/4.
|
:- non_counted_backtracking get_args/4.
|
||||||
|
|
||||||
get_args(Args, _, _, 0) :-
|
get_args(Args, _, _, 0) :-
|
||||||
!, '$call_with_default_policy'(Args = []).
|
!, '$call_with_default_policy'(Args = []).
|
||||||
get_args([Arg], Func, N, N) :-
|
get_args([Arg], Func, N, N) :-
|
||||||
@@ -289,6 +295,7 @@ is_write_option(Functor) :-
|
|||||||
( Arg == true -> true
|
( Arg == true -> true
|
||||||
; Arg == false -> true
|
; Arg == false -> true
|
||||||
; Name == variable_names -> must_be_var_names_list(Arg)
|
; Name == variable_names -> must_be_var_names_list(Arg)
|
||||||
|
; Name == max_depth -> integer(Arg), Arg >= 0
|
||||||
; var(Arg) -> throw(error(instantiation_error, write_term/2))
|
; var(Arg) -> throw(error(instantiation_error, write_term/2))
|
||||||
; throw(error(domain_error(write_option, Functor), write_term/2))
|
; throw(error(domain_error(write_option, Functor), write_term/2))
|
||||||
), % 8.14.2.3 e)
|
), % 8.14.2.3 e)
|
||||||
@@ -296,6 +303,7 @@ is_write_option(Functor) :-
|
|||||||
; Name == quoted -> true
|
; Name == quoted -> true
|
||||||
; Name == numbervars -> true
|
; Name == numbervars -> true
|
||||||
; Name == variable_names -> true
|
; Name == variable_names -> true
|
||||||
|
; Name == max_depth -> true
|
||||||
; throw(error(domain_error(write_option, Functor), write_term/2))
|
; throw(error(domain_error(write_option, Functor), write_term/2))
|
||||||
). % 8.14.2.3 e)
|
). % 8.14.2.3 e)
|
||||||
|
|
||||||
@@ -338,7 +346,8 @@ write_term(Term, Options) :-
|
|||||||
inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
|
inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
|
||||||
inst_member_or(Options, quoted(Quoted), quoted(false)),
|
inst_member_or(Options, quoted(Quoted), quoted(false)),
|
||||||
inst_member_or(Options, variable_names(VarNames), variable_names([])),
|
inst_member_or(Options, variable_names(VarNames), variable_names([])),
|
||||||
'$write_term'(Term, IgnoreOps, NumberVars, Quoted, VarNames).
|
inst_member_or(Options, max_depth(MaxDepth), max_depth(0)),
|
||||||
|
'$write_term'(Term, IgnoreOps, NumberVars, Quoted, VarNames, MaxDepth).
|
||||||
|
|
||||||
write(Term) :- write_term(Term, [numbervars(true)]).
|
write(Term) :- write_term(Term, [numbervars(true)]).
|
||||||
|
|
||||||
@@ -448,7 +457,7 @@ set_difference([], _, []) :- !.
|
|||||||
set_difference(Xs, [], Xs).
|
set_difference(Xs, [], Xs).
|
||||||
|
|
||||||
group_by_variant([V2-S2 | Pairs], V1-S1, [S2 | Solutions], Pairs0) :-
|
group_by_variant([V2-S2 | Pairs], V1-S1, [S2 | Solutions], Pairs0) :-
|
||||||
non_iso:variant(V1, V2), !, V1 = V2, group_by_variant(Pairs, V2-S2, Solutions, Pairs0).
|
iso_ext:variant(V1, V2), !, V1 = V2, group_by_variant(Pairs, V2-S2, Solutions, Pairs0).
|
||||||
group_by_variant(Pairs, _, [], Pairs).
|
group_by_variant(Pairs, _, [], Pairs).
|
||||||
|
|
||||||
group_by_variants([V-S|Pairs], [V-Solution|Solutions]) :-
|
group_by_variants([V-S|Pairs], [V-Solution|Solutions]) :-
|
||||||
@@ -456,7 +465,10 @@ group_by_variants([V-S|Pairs], [V-Solution|Solutions]) :-
|
|||||||
group_by_variants(Pairs0, Solutions).
|
group_by_variants(Pairs0, Solutions).
|
||||||
group_by_variants([], []).
|
group_by_variants([], []).
|
||||||
|
|
||||||
iterate_variants([V-Solution|GroupSolutions], V, Solution).
|
iterate_variants([V-Solution|GroupSolutions], V, Solution) :-
|
||||||
|
( GroupSolutions == [] -> !
|
||||||
|
; true
|
||||||
|
).
|
||||||
iterate_variants([_|GroupSolutions], Ws, Solution) :-
|
iterate_variants([_|GroupSolutions], Ws, Solution) :-
|
||||||
iterate_variants(GroupSolutions, Ws, Solution).
|
iterate_variants(GroupSolutions, Ws, Solution).
|
||||||
|
|
||||||
@@ -472,7 +484,9 @@ findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses)
|
|||||||
( nonvar(Goal), Goal = _ ^ _ ->
|
( nonvar(Goal), Goal = _ ^ _ ->
|
||||||
rightmost_power(Goal, Goal1, ExistentialVars0),
|
rightmost_power(Goal, Goal1, ExistentialVars0),
|
||||||
term_variables(ExistentialVars0, ExistentialVars),
|
term_variables(ExistentialVars0, ExistentialVars),
|
||||||
set_difference(Witnesses0, ExistentialVars, Witnesses),
|
sort(Witnesses0, Witnesses1),
|
||||||
|
sort(ExistentialVars, ExistentialVars1),
|
||||||
|
set_difference(Witnesses1, ExistentialVars1, Witnesses),
|
||||||
findall(Witnesses-Template, Goal1, PairedSolutions)
|
findall(Witnesses-Template, Goal1, PairedSolutions)
|
||||||
; Witnesses = Witnesses0,
|
; Witnesses = Witnesses0,
|
||||||
findall(Witnesses-Template, Goal, PairedSolutions)
|
findall(Witnesses-Template, Goal, PairedSolutions)
|
||||||
@@ -491,7 +505,10 @@ bagof(Template, Goal, Solution) :-
|
|||||||
iterate_variants(GroupedSolutions, Witnesses, Solution).
|
iterate_variants(GroupedSolutions, Witnesses, Solution).
|
||||||
|
|
||||||
iterate_variants_and_sort([V-Solution0|GroupSolutions], V, Solution) :-
|
iterate_variants_and_sort([V-Solution0|GroupSolutions], V, Solution) :-
|
||||||
sort(Solution0, Solution).
|
sort(Solution0, Solution),
|
||||||
|
( GroupSolutions == [] -> !
|
||||||
|
; true
|
||||||
|
).
|
||||||
iterate_variants_and_sort([_|GroupSolutions], Ws, Solution) :-
|
iterate_variants_and_sort([_|GroupSolutions], Ws, Solution) :-
|
||||||
iterate_variants_and_sort(GroupSolutions, Ws, Solution).
|
iterate_variants_and_sort(GroupSolutions, Ws, Solution).
|
||||||
|
|
||||||
@@ -1006,3 +1023,19 @@ subsumes_term(General, Specific) :-
|
|||||||
).
|
).
|
||||||
|
|
||||||
unify_with_occurs_check(X, Y) :- '$unify_with_occurs_check'(X, Y).
|
unify_with_occurs_check(X, Y) :- '$unify_with_occurs_check'(X, Y).
|
||||||
|
|
||||||
|
current_input(S) :- '$current_input'(S).
|
||||||
|
|
||||||
|
current_output(S) :- '$current_output'(S).
|
||||||
|
|
||||||
|
set_input(S) :-
|
||||||
|
( var(S) ->
|
||||||
|
throw(error(instantiation_error, set_input/1))
|
||||||
|
; '$set_input'(S)
|
||||||
|
).
|
||||||
|
|
||||||
|
set_output(S) :-
|
||||||
|
( var(S) ->
|
||||||
|
throw(error(instantiation_error, set_output/1))
|
||||||
|
; '$set_output'(S)
|
||||||
|
).
|
||||||
|
|||||||
39
src/prolog/lib/charsio.pl
Normal file
39
src/prolog/lib/charsio.pl
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
:- module(charsio, [read_term_from_chars/2,
|
||||||
|
write_term_to_chars/3]).
|
||||||
|
|
||||||
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
|
read_term_from_chars(Chars, Term) :-
|
||||||
|
( var(Chars) ->
|
||||||
|
throw(error(instantiation_error, read_term_from_chars/2))
|
||||||
|
; nonvar(Term) ->
|
||||||
|
throw(error(uninstantiation_error(Term), read_term_from_chars/2))
|
||||||
|
; '$skip_max_list'(_, -1, Chars, Chars0),
|
||||||
|
Chars0 == [],
|
||||||
|
partial_string(Chars) ->
|
||||||
|
true
|
||||||
|
;
|
||||||
|
throw(error(type_error(complete_string, Chars), read_term_from_chars/2))
|
||||||
|
),
|
||||||
|
'$read_term_from_chars'(Chars, Term).
|
||||||
|
|
||||||
|
|
||||||
|
write_term_to_chars(_, Options, _) :-
|
||||||
|
var(Options), throw(error(instantiation_error, write_term_to_chars/3)).
|
||||||
|
write_term_to_chars(Term, Options, Chars) :-
|
||||||
|
'$skip_max_list'(_, -1, Options, Options0),
|
||||||
|
( var(Options0) ->
|
||||||
|
throw(error(instantiation_error, write_term_to_chars/3))
|
||||||
|
; nonvar(Chars) ->
|
||||||
|
throw(error(uninstantiation_error(Chars), write_term_to_chars/3))
|
||||||
|
; Options0 == [] ->
|
||||||
|
true
|
||||||
|
;
|
||||||
|
throw(error(type_error(list, Options), write_term_to_chars/3))
|
||||||
|
),
|
||||||
|
builtins:inst_member_or(Options, ignore_ops(IgnoreOps), ignore_ops(false)),
|
||||||
|
builtins:inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
|
||||||
|
builtins:inst_member_or(Options, quoted(Quoted), quoted(false)),
|
||||||
|
builtins:inst_member_or(Options, variable_names(VarNames), variable_names([])),
|
||||||
|
builtins:inst_member_or(Options, max_depth(MaxDepth), max_depth(0)),
|
||||||
|
'$write_term_to_chars'(Term, IgnoreOps, NumberVars, Quoted, VarNames, MaxDepth, Chars).
|
||||||
@@ -30,7 +30,8 @@
|
|||||||
:- use_module(library(between)).
|
:- use_module(library(between)).
|
||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
:- use_module(library(pairs)).
|
||||||
:- use_module(library(dcgs)).
|
:- use_module(library(dcgs)).
|
||||||
:- use_module(library(error), []).
|
:- use_module(library(error), []).
|
||||||
|
|
||||||
@@ -106,65 +107,10 @@ type_error(Expectation, Term) :-
|
|||||||
type_error(Expectation, Term, Goal-Arg) :-
|
type_error(Expectation, Term, Goal-Arg) :-
|
||||||
throw(error(type_error(Expectation, Term), type_error(Goal, Arg, Expectation, Term))).
|
throw(error(type_error(Expectation, Term), type_error(Goal, Arg, Expectation, Term))).
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
foldl/4
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
foldl(Goal_3, Ls, A0, A) :-
|
|
||||||
foldl_(Ls, Goal_3, A0, A).
|
|
||||||
|
|
||||||
foldl_([], _, A, A).
|
|
||||||
foldl_([L|Ls], G_3, A0, A) :-
|
|
||||||
call(G_3, L, A0, A1),
|
|
||||||
foldl_(Ls, G_3, A1, A).
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
foldl/5
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
foldl(Goal_4, Xs, Ys, A0, A) :-
|
|
||||||
foldl_(Xs, Ys, Goal_4, A0, A).
|
|
||||||
|
|
||||||
foldl_([], [], _, A, A).
|
|
||||||
foldl_([X|Xs], [Y|Ys], G_4, A0, A) :-
|
|
||||||
call(G_4, X, Y, A0, A1),
|
|
||||||
foldl_(Xs, Ys, G_4, A1, A).
|
|
||||||
|
|
||||||
|
|
||||||
partition(Pred, Ls0, As, Bs) :-
|
partition(Pred, Ls0, As, Bs) :-
|
||||||
include(Pred, Ls0, As),
|
include(Pred, Ls0, As),
|
||||||
exclude(Pred, Ls0, Bs).
|
exclude(Pred, Ls0, Bs).
|
||||||
|
|
||||||
sum_list(Ls, S) :-
|
|
||||||
foldl(sum_, Ls, 0, S).
|
|
||||||
|
|
||||||
sum_(L, S0, S) :- S is S0 + L.
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
Pairs.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
pairs_keys_values([], [], []).
|
|
||||||
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
|
|
||||||
pairs_keys_values(ABs, As, Bs).
|
|
||||||
|
|
||||||
pairs_keys(Ps, Ks) :- pairs_keys_values(Ps, Ks, _).
|
|
||||||
|
|
||||||
pairs_values(Ps, Vs) :- pairs_keys_values(Ps, _, Vs).
|
|
||||||
|
|
||||||
map_list_to_pairs(Pred, Ls, Ps) :-
|
|
||||||
map_list_to_pairs2(Ls, Pred, Ps).
|
|
||||||
|
|
||||||
map_list_to_pairs2([], _, []).
|
|
||||||
map_list_to_pairs2([H|T0], Pred, [K-H|T]) :-
|
|
||||||
call(Pred, H, K),
|
|
||||||
map_list_to_pairs2(T0, Pred, T).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
goal_expansion(get_attr(Var, Module, Value), (var(Var),get_atts(Var, Access))) :-
|
goal_expansion(get_attr(Var, Module, Value), (var(Var),get_atts(Var, Access))) :-
|
||||||
Access =.. [Module,Value].
|
Access =.. [Module,Value].
|
||||||
|
|
||||||
@@ -728,10 +674,6 @@ existential(V, BDD, Node) :-
|
|||||||
Counter network for card(Is,Fs).
|
Counter network for card(Is,Fs).
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
same_length([], []).
|
|
||||||
same_length([_|As], [_|Bs]) :-
|
|
||||||
same_length(As, Bs).
|
|
||||||
|
|
||||||
counter_network(Cs, Fs, Node) :-
|
counter_network(Cs, Fs, Node) :-
|
||||||
same_length([_|Fs], Indicators),
|
same_length([_|Fs], Indicators),
|
||||||
fill_indicators(Indicators, 0, Cs),
|
fill_indicators(Indicators, 0, Cs),
|
||||||
|
|||||||
7625
src/prolog/lib/clpz.pl
Normal file
7625
src/prolog/lib/clpz.pl
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
:- module(cont, [reset/3, shift/1]).
|
:- module(cont, [reset/3, shift/1]).
|
||||||
|
|
||||||
reset(Goal, Ball, Cont) :-
|
reset(Goal, Ball, Cont) :-
|
||||||
@@ -7,14 +6,14 @@ reset(Goal, Ball, Cont) :-
|
|||||||
'$bind_from_register'(Cont, 3),
|
'$bind_from_register'(Cont, 3),
|
||||||
'$bind_from_register'(Ball, 4).
|
'$bind_from_register'(Ball, 4).
|
||||||
|
|
||||||
shift(Term) :-
|
shift(Ball) :-
|
||||||
'$nextEP'(first, E, P),
|
'$nextEP'(first, E, P),
|
||||||
get_chunks(E, P, L),
|
get_chunks(E, P, L),
|
||||||
( L == [] ->
|
( L == [] ->
|
||||||
Cont = none
|
Cont = none
|
||||||
; Cont = cont(call_continuation(L))
|
; Cont = cont(call_continuation(L))
|
||||||
),
|
),
|
||||||
'$write_cont_and_term'(_, _, Cont, Term),
|
'$write_cont_and_term'(_, _, Cont, Ball),
|
||||||
'$unwind_environments'.
|
'$unwind_environments'.
|
||||||
|
|
||||||
get_chunks(E, P, L) :-
|
get_chunks(E, P, L) :-
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
% :- op(1105, xfy, ('|')).
|
:- module(dcgs, [op(1200, xfx, -->),
|
||||||
|
op(1105, xfy, '|'),
|
||||||
:- module(dcgs, [op(1200, xfx, -->), phrase/2, phrase/3]).
|
phrase/2,
|
||||||
|
phrase/3]).
|
||||||
|
|
||||||
|
:- use_module(library(error)).
|
||||||
:- use_module(library(lists), [append/3]).
|
:- use_module(library(lists), [append/3]).
|
||||||
|
|
||||||
user:term_expansion(Term0, Term) :-
|
user:term_expansion(Term0, Term) :-
|
||||||
@@ -31,8 +33,8 @@ phrase_((A -> B ; C), S0, S) :-
|
|||||||
).
|
).
|
||||||
phrase_((A ; B), S0, S) :-
|
phrase_((A ; B), S0, S) :-
|
||||||
( phrase(A, S0, S) ; phrase(B, S0, S) ).
|
( phrase(A, S0, S) ; phrase(B, S0, S) ).
|
||||||
%% phrase_((A | B), S0, S) :-
|
phrase_((A | B), S0, S) :-
|
||||||
%% ( phrase(A, S0, S) ; phrase(B, S0, S) ).
|
( phrase(A, S0, S) ; phrase(B, S0, S) ).
|
||||||
phrase_({G}, S0, S) :-
|
phrase_({G}, S0, S) :-
|
||||||
( call(G), S0 = S ).
|
( call(G), S0 = S ).
|
||||||
phrase_(call(G), S0, S) :-
|
phrase_(call(G), S0, S) :-
|
||||||
@@ -95,7 +97,7 @@ dcg_constr([]). % 7.14.1
|
|||||||
dcg_constr([_|_]). % 7.14.2 - terminal sequence
|
dcg_constr([_|_]). % 7.14.2 - terminal sequence
|
||||||
dcg_constr(( _, _ )). % 7.14.3 - concatenation
|
dcg_constr(( _, _ )). % 7.14.3 - concatenation
|
||||||
dcg_constr(( _ ; _ )). % 7.14.4 - alternative
|
dcg_constr(( _ ; _ )). % 7.14.4 - alternative
|
||||||
%% dcg_constr(( _'|'_ )). % 7.14.6 - alternative
|
dcg_constr(( _'|'_ )). % 7.14.6 - alternative
|
||||||
dcg_constr({_}). % 7.14.7
|
dcg_constr({_}). % 7.14.7
|
||||||
dcg_constr(call(_)). % 7.14.8
|
dcg_constr(call(_)). % 7.14.8
|
||||||
dcg_constr(phrase(_)). % 7.14.9
|
dcg_constr(phrase(_)). % 7.14.9
|
||||||
@@ -107,6 +109,7 @@ dcg_constr((_->_)). % 7.14.12 - if-then (existence implementation dep.)
|
|||||||
% the construct to be expanded.
|
% the construct to be expanded.
|
||||||
dcg_cbody([], S0, S, S0 = S).
|
dcg_cbody([], S0, S, S0 = S).
|
||||||
dcg_cbody([T|Ts], S0, S, Goal) :-
|
dcg_cbody([T|Ts], S0, S, Goal) :-
|
||||||
|
must_be(list, [T|Ts]),
|
||||||
dcg_terminals([T|Ts], S0, S, Goal).
|
dcg_terminals([T|Ts], S0, S, Goal).
|
||||||
dcg_cbody(( GRFirst, GRSecond ), S0, S, ( First, Second )) :-
|
dcg_cbody(( GRFirst, GRSecond ), S0, S, ( First, Second )) :-
|
||||||
dcg_body(GRFirst, S0, S1, First),
|
dcg_body(GRFirst, S0, S1, First),
|
||||||
@@ -119,9 +122,9 @@ dcg_cbody(( GRCond ; GRElse ), S0, S, ( Cond ; Else )) :-
|
|||||||
subsumes_term(( _GRIf -> _GRThen ), GRCond),
|
subsumes_term(( _GRIf -> _GRThen ), GRCond),
|
||||||
dcg_cbody(GRCond, S0, S, Cond),
|
dcg_cbody(GRCond, S0, S, Cond),
|
||||||
dcg_body(GRElse, S0, S, Else).
|
dcg_body(GRElse, S0, S, Else).
|
||||||
%% dcg_cbody(( GREither '|' GROr ), S0, S, ( Either ; Or )) :-
|
dcg_cbody(( GREither '|' GROr ), S0, S, ( Either ; Or )) :-
|
||||||
%% dcg_body(GREither, S0, S, Either),
|
dcg_body(GREither, S0, S, Either),
|
||||||
%% dcg_body(GROr, S0, S, Or).
|
dcg_body(GROr, S0, S, Or).
|
||||||
dcg_cbody({Goal}, S0, S, ( Goal, S0 = S )).
|
dcg_cbody({Goal}, S0, S, ( Goal, S0 = S )).
|
||||||
dcg_cbody(call(Cont), S0, S, call(Cont, 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), S0, S, phrase(Body, S0, S)).
|
||||||
|
|||||||
481
src/prolog/lib/format.pl
Normal file
481
src/prolog/lib/format.pl
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Written March 2020 by Markus Triska (triska@metalevel.at)
|
||||||
|
Part of Scryer Prolog.
|
||||||
|
|
||||||
|
This library provides the nonterminal format_//2 to describe
|
||||||
|
formatted strings. format/2 is provided for impure output.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
======
|
||||||
|
|
||||||
|
phrase(format_(FormatString, Arguments), Ls)
|
||||||
|
|
||||||
|
format_//2 describes a list of characters Ls that are formatted
|
||||||
|
according to FormatString. FormatString is a string (i.e.,
|
||||||
|
a list of characters) that specifies the layout of Ls.
|
||||||
|
The characters in FormatString are used literally, except
|
||||||
|
for the following tokens with special meaning:
|
||||||
|
|
||||||
|
~w use the next available argument from Arguments here
|
||||||
|
~q use the next argument here, formatted as by writeq/1
|
||||||
|
~a use the next argument here, which must be an atom
|
||||||
|
~s use the next argument here, which must be a string
|
||||||
|
~d use the next argument here, which must be an integer
|
||||||
|
~f use the next argument here, a floating point number
|
||||||
|
~Nf where N is an integer: format the float argument
|
||||||
|
using N digits after the decimal point
|
||||||
|
~Nd like ~d, placing the last N digits after a decimal point;
|
||||||
|
if N is 0 or omitted, no decimal point is used.
|
||||||
|
~ND like ~Nd, separating digits to the left of the decimal point
|
||||||
|
in groups of three, using the character "," (comma)
|
||||||
|
~N| where N is an integer: place a tab stop at text column N
|
||||||
|
~N+ where N is an integer: place a tab stop N characters
|
||||||
|
after the previous tab stop (or start of line)
|
||||||
|
~t distribute spaces evenly between the two closest tab stops
|
||||||
|
~`Ct like ~t, use character C instead of spaces to fill the space
|
||||||
|
~n newline
|
||||||
|
~Nn N newlines
|
||||||
|
~i ignore the next argument
|
||||||
|
~~ the literal ~
|
||||||
|
|
||||||
|
Instead of ~N, you can write ~* to use the next argument from Arguments
|
||||||
|
as the numeric argument.
|
||||||
|
|
||||||
|
The predicate format/2 is like format_//2, except that it outputs
|
||||||
|
the text on the terminal instead of describing it declaratively.
|
||||||
|
|
||||||
|
If at all possible, format_//2 should be used, to stress pure parts
|
||||||
|
that enable easy testing etc. If necessary, you can emit the list Ls
|
||||||
|
with maplist(write, Ls).
|
||||||
|
|
||||||
|
The entire library only works if the Prolog flag double_quotes
|
||||||
|
is set to chars, the default value in Scryer Prolog. This should
|
||||||
|
also stay that way, to encourage a sensible environment.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
?- phrase(format_("~s~n~`.t~w!~12|", ["hello",there]), Cs).
|
||||||
|
%@ Cs = [h,e,l,l,o,'\n','.','.','.','.','.','.',t,h,e,r,e,!]
|
||||||
|
%@ ; false.
|
||||||
|
|
||||||
|
I place this code in the public domain. Use it in any way you want.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
:- module(format, [format_//2,
|
||||||
|
format/2,
|
||||||
|
portray_clause/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
:- use_module(library(dcgs)).
|
||||||
|
:- use_module(library(lists)).
|
||||||
|
:- use_module(library(error)).
|
||||||
|
:- use_module(library(charsio)).
|
||||||
|
|
||||||
|
format_(Fs, Args) -->
|
||||||
|
{ must_be(list, Fs),
|
||||||
|
must_be(list, Args),
|
||||||
|
phrase(cells(Fs,Args,0,[]), Cells) },
|
||||||
|
format_cells(Cells).
|
||||||
|
|
||||||
|
format_cells([]) --> [].
|
||||||
|
format_cells([Cell|Cells]) -->
|
||||||
|
format_cell(Cell),
|
||||||
|
format_cells(Cells).
|
||||||
|
|
||||||
|
format_cell(newline) --> "\n".
|
||||||
|
format_cell(cell(From,To,Es)) -->
|
||||||
|
% distribute the space between the glue elements
|
||||||
|
{ phrase(elements_gluevars(Es, 0, Length), Vs),
|
||||||
|
( Vs = [] -> true
|
||||||
|
; Space is To - From - Length,
|
||||||
|
( Space =< 0 -> maplist(=(0), Vs)
|
||||||
|
; length(Vs, NumGlue),
|
||||||
|
Distr is Space // NumGlue,
|
||||||
|
Delta is Space - Distr*NumGlue,
|
||||||
|
( Delta =:= 0 ->
|
||||||
|
maplist(=(Distr), Vs)
|
||||||
|
; BigGlue is Distr + Delta,
|
||||||
|
reverse(Vs, [BigGlue|Rest]),
|
||||||
|
maplist(=(Distr), Rest)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) },
|
||||||
|
format_elements(Es).
|
||||||
|
|
||||||
|
format_elements([]) --> [].
|
||||||
|
format_elements([E|Es]) -->
|
||||||
|
format_element(E),
|
||||||
|
format_elements(Es).
|
||||||
|
|
||||||
|
format_element(chars(Cs)) --> list(Cs).
|
||||||
|
format_element(glue(Fill,Num)) -->
|
||||||
|
{ length(Ls, Num),
|
||||||
|
maplist(=(Fill), Ls) },
|
||||||
|
list(Ls).
|
||||||
|
|
||||||
|
list([]) --> [].
|
||||||
|
list([L|Ls]) --> [L], list(Ls).
|
||||||
|
|
||||||
|
elements_gluevars([], N, N) --> [].
|
||||||
|
elements_gluevars([E|Es], N0, N) -->
|
||||||
|
element_gluevar(E, N0, N1),
|
||||||
|
elements_gluevars(Es, N1, N).
|
||||||
|
|
||||||
|
element_gluevar(chars(Cs), N0, N) -->
|
||||||
|
{ length(Cs, L),
|
||||||
|
N is N0 + L }.
|
||||||
|
element_gluevar(glue(_,V), N, N) --> [V].
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Our key datastructure is a list of cells and newlines.
|
||||||
|
A cell has the shape from_to(From,To,Elements), where
|
||||||
|
From and To denote the positions of surrounding tab stops.
|
||||||
|
|
||||||
|
Elements is a list of elements that occur in a cell,
|
||||||
|
namely terms of the form chars(Cs) and glue(Char, Var).
|
||||||
|
"glue" elements (TeX terminology) are evenly stretched
|
||||||
|
to fill the remaining whitespace in the cell. For each
|
||||||
|
glue element, the character Char is used for filling,
|
||||||
|
and Var is a free variable that is used when the
|
||||||
|
available space is distributed.
|
||||||
|
|
||||||
|
newline is used if ~n occurs in a format string.
|
||||||
|
It is is used because a newline character does not
|
||||||
|
consume whitespace in the sense of format strings.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
cells([], Args, Tab, Es) -->
|
||||||
|
( { Args == [] } -> cell(Tab, Tab, Es)
|
||||||
|
; { domain_error(no_remaining_arguments, Args) }
|
||||||
|
).
|
||||||
|
cells([~,~|Fs], Args, Tab, Es) --> !,
|
||||||
|
cells(Fs, Args, Tab, [chars("~")|Es]).
|
||||||
|
cells([~,w|Fs], [Arg|Args], Tab, Es) --> !,
|
||||||
|
{ write_term_to_chars(Arg, [], Chars) },
|
||||||
|
cells(Fs, Args, Tab, [chars(Chars)|Es]).
|
||||||
|
cells([~,q|Fs], [Arg|Args], Tab, Es) --> !,
|
||||||
|
{ write_term_to_chars(Arg, [quoted(true)], Chars) },
|
||||||
|
cells(Fs, Args, Tab, [chars(Chars)|Es]).
|
||||||
|
cells([~,a|Fs], [Arg|Args], Tab, Es) --> !,
|
||||||
|
{ atom_chars(Arg, Chars) },
|
||||||
|
cells(Fs, Args, Tab, [chars(Chars)|Es]).
|
||||||
|
cells([~|Fs0], Args0, Tab, Es) -->
|
||||||
|
{ numeric_argument(Fs0, Num, [d|Fs], Args0, [Arg|Args]) },
|
||||||
|
!,
|
||||||
|
{ number_chars(Arg, Cs0) },
|
||||||
|
( { Num =:= 0 } -> { Cs = Cs0 }
|
||||||
|
; { length(Cs0, L),
|
||||||
|
( L =< Num ->
|
||||||
|
Delta is Num - L,
|
||||||
|
length(Zs, Delta),
|
||||||
|
maplist(=('0'), Zs),
|
||||||
|
phrase(("0.",list(Zs),list(Cs0)), Cs)
|
||||||
|
; BeforeComma is L - Num,
|
||||||
|
length(Bs, BeforeComma),
|
||||||
|
append(Bs, Ds, Cs0),
|
||||||
|
phrase((list(Bs),".",list(Ds)), Cs)
|
||||||
|
) }
|
||||||
|
),
|
||||||
|
cells(Fs, Args, Tab, [chars(Cs)|Es]).
|
||||||
|
cells([~|Fs0], Args0, Tab, Es) -->
|
||||||
|
{ numeric_argument(Fs0, Num, ['D'|Fs], Args0, [Arg|Args]) },
|
||||||
|
!,
|
||||||
|
{ number_chars(Num, NCs),
|
||||||
|
phrase(("~",list(NCs),"d"), FStr),
|
||||||
|
phrase(format_(FStr, [Arg]), Cs0),
|
||||||
|
phrase(upto_what(Bs0, .), Cs0, Ds),
|
||||||
|
reverse(Bs0, Bs1),
|
||||||
|
phrase(groups_of_three(Bs1), Bs2),
|
||||||
|
reverse(Bs2, Bs),
|
||||||
|
append(Bs, Ds, Cs) },
|
||||||
|
cells(Fs, Args, Tab, [chars(Cs)|Es]).
|
||||||
|
cells([~,i|Fs], [_|Args], Tab, Es) --> !,
|
||||||
|
cells(Fs, Args, Tab, Es).
|
||||||
|
cells([~,n|Fs], Args, Tab, Es) --> !,
|
||||||
|
cell(Tab, Tab, Es),
|
||||||
|
n_newlines(1),
|
||||||
|
cells(Fs, Args, 0, []).
|
||||||
|
cells([~|Fs0], Args0, Tab, Es) -->
|
||||||
|
{ numeric_argument(Fs0, Num, [n|Fs], Args0, Args) },
|
||||||
|
!,
|
||||||
|
cell(Tab, Tab, Es),
|
||||||
|
n_newlines(Num),
|
||||||
|
cells(Fs, Args, 0, []).
|
||||||
|
cells([~,s|Fs], [Arg|Args], Tab, Es) --> !,
|
||||||
|
cells(Fs, Args, Tab, [chars(Arg)|Es]).
|
||||||
|
cells([~,f|Fs], [Arg|Args], Tab, Es) --> !,
|
||||||
|
{ number_chars(Arg, Chars) },
|
||||||
|
cells(Fs, Args, Tab, [chars(Chars)|Es]).
|
||||||
|
cells([~|Fs0], Args0, Tab, Es) -->
|
||||||
|
{ numeric_argument(Fs0, Num, [f|Fs], Args0, [Arg|Args]) },
|
||||||
|
!,
|
||||||
|
{ number_chars(Arg, Cs0),
|
||||||
|
phrase(upto_what(Bs, .), Cs0, Cs),
|
||||||
|
( Num =:= 0 -> Chars = Bs
|
||||||
|
; ( Cs = ['.'|Rest] ->
|
||||||
|
length(Rest, L),
|
||||||
|
( Num < L ->
|
||||||
|
length(Ds, Num),
|
||||||
|
append(Ds, _, Rest)
|
||||||
|
; Num =:= L ->
|
||||||
|
Ds = Rest
|
||||||
|
; Num > L,
|
||||||
|
Delta is Num - L,
|
||||||
|
% we should look into the float with
|
||||||
|
% greater accuracy here, and use the
|
||||||
|
% actual digits instead of 0.
|
||||||
|
length(Zs, Delta),
|
||||||
|
maplist(=('0'), Zs),
|
||||||
|
append(Rest, Zs, Ds)
|
||||||
|
)
|
||||||
|
; length(Ds, Num),
|
||||||
|
maplist(=('0'), Ds)
|
||||||
|
),
|
||||||
|
append(Bs, ['.'|Ds], Chars)
|
||||||
|
) },
|
||||||
|
cells(Fs, Args, Tab, [chars(Chars)|Es]).
|
||||||
|
cells([~,'`',Char,t|Fs], Args, Tab, Es) --> !,
|
||||||
|
cells(Fs, Args, Tab, [glue(Char,_)|Es]).
|
||||||
|
cells([~,t|Fs], Args, Tab, Es) --> !,
|
||||||
|
cells(Fs, Args, Tab, [glue(' ',_)|Es]).
|
||||||
|
cells([~|Fs0], Args0, Tab, Es) -->
|
||||||
|
{ numeric_argument(Fs0, Num, ['|'|Fs], Args0, Args) },
|
||||||
|
!,
|
||||||
|
cell(Tab, Num, Es),
|
||||||
|
cells(Fs, Args, Num, []).
|
||||||
|
cells([~|Fs0], Args0, Tab0, Es) -->
|
||||||
|
{ numeric_argument(Fs0, Num, [+|Fs], Args0, Args) },
|
||||||
|
!,
|
||||||
|
{ Tab is Tab0 + Num },
|
||||||
|
cell(Tab0, Tab, Es),
|
||||||
|
cells(Fs, Args, Tab, []).
|
||||||
|
cells([~,C|_], _, _, _) -->
|
||||||
|
{ atom_chars(A, [~,C]),
|
||||||
|
domain_error(format_string, A) }.
|
||||||
|
cells(Fs0, Args, Tab, Es) -->
|
||||||
|
{ phrase(upto_what(Fs1, ~), Fs0, Fs),
|
||||||
|
Fs1 = [_|_] },
|
||||||
|
cells(Fs, Args, Tab, [chars(Fs1)|Es]).
|
||||||
|
|
||||||
|
domain_error(Type, Term) :-
|
||||||
|
throw(error(domain_error(Type, Term), _)).
|
||||||
|
|
||||||
|
n_newlines(0) --> !.
|
||||||
|
n_newlines(1) --> !, [newline].
|
||||||
|
n_newlines(N0) --> { N0 > 1, N is N0 - 1 }, [newline], n_newlines(N).
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
?- 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 = [].
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
upto_what([], W), [W] --> [W], !.
|
||||||
|
upto_what([C|Cs], W) --> [C], !, upto_what(Cs, W).
|
||||||
|
upto_what([], _) --> [].
|
||||||
|
|
||||||
|
groups_of_three([A,B,C,D|Rs]) --> !, [A,B,C], ",", groups_of_three([D|Rs]).
|
||||||
|
groups_of_three(Ls) --> list(Ls).
|
||||||
|
|
||||||
|
cell(From, To, Es0) -->
|
||||||
|
( { Es0 == [] } -> []
|
||||||
|
; { reverse(Es0, Es) },
|
||||||
|
[cell(From,To,Es)]
|
||||||
|
).
|
||||||
|
|
||||||
|
%?- numeric_argument("2f", Num, ['f'|Fs], Args0, Args).
|
||||||
|
|
||||||
|
%?- numeric_argument("100b", Num, Rs, Args0, Args).
|
||||||
|
|
||||||
|
numeric_argument(Ds, Num, Rest, Args0, Args) :-
|
||||||
|
( Ds = [*|Rest] ->
|
||||||
|
Args0 = [Num|Args]
|
||||||
|
; numeric_argument_(Ds, [], Ns, Rest),
|
||||||
|
foldl(pow10, Ns, 0-0, Num-_),
|
||||||
|
Args0 = Args
|
||||||
|
).
|
||||||
|
|
||||||
|
numeric_argument_([D|Ds], Ns0, Ns, Rest) :-
|
||||||
|
( member(D, "0123456789") ->
|
||||||
|
number_chars(N, [D]),
|
||||||
|
numeric_argument_(Ds, [N|Ns0], Ns, Rest)
|
||||||
|
; Ns = Ns0,
|
||||||
|
Rest = [D|Ds]
|
||||||
|
).
|
||||||
|
|
||||||
|
|
||||||
|
pow10(D, N0-Pow0, N-Pow) :-
|
||||||
|
N is N0 + D*10^Pow0,
|
||||||
|
Pow is Pow0 + 1.
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Impure I/O, implemented as a small wrapper over format_//2.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
format(Fs, Args) :-
|
||||||
|
phrase(format_(Fs, Args), Cs),
|
||||||
|
maplist(write, Cs).
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
?- phrase(cells("hello", [], 0, []), Cs).
|
||||||
|
|
||||||
|
?- phrase(cells("hello~10|", [], 0, []), Cs).
|
||||||
|
?- phrase(cells("~ta~t~10|", [], 0, []), Cs).
|
||||||
|
|
||||||
|
?- phrase(format_("~`at~50|", []), Ls).
|
||||||
|
|
||||||
|
?- phrase(cells("~`at~50|", [], 0, []), Cs),
|
||||||
|
phrase(format_cells(Cs), Ls).
|
||||||
|
?- phrase(cells("~ta~t~tb~tc~21|", [], 0, []), Cs).
|
||||||
|
Cs = [cell(0,21,[glue(' ',_38),chars([a]),glue(' ',_62),glue(' ',_67),chars([b]),glue(' ',_91),chars([c])])].
|
||||||
|
?- phrase(cells("~ta~t~4|", [], 0, []), Cs).
|
||||||
|
Cs = [cell(0,4,[glue(' ',_38),chars([a]),glue(' ',_62)])].
|
||||||
|
|
||||||
|
?- phrase(format_cell(cell(0,1,[glue(a,_94)])), Ls).
|
||||||
|
|
||||||
|
?- phrase(format_cell(cell(0,50,[chars("hello")])), Ls).
|
||||||
|
|
||||||
|
?- phrase(format_("~`at~50|~n", []), Ls).
|
||||||
|
?- phrase(format_("hello~n~tthere~6|", []), Ls).
|
||||||
|
|
||||||
|
?- format("~ta~t~4|", []).
|
||||||
|
a true
|
||||||
|
; false.
|
||||||
|
|
||||||
|
?- format("~ta~tb~tc~10|", []).
|
||||||
|
a b ctrue
|
||||||
|
; false.
|
||||||
|
|
||||||
|
?- format("~tabc~3|", []).
|
||||||
|
|
||||||
|
?- format("~ta~t~4|", []).
|
||||||
|
|
||||||
|
?- format("~ta~t~tb~tc~20|", []).
|
||||||
|
a b ctrue
|
||||||
|
; false.
|
||||||
|
|
||||||
|
?- format("~2f~n", [3]).
|
||||||
|
3.00
|
||||||
|
true
|
||||||
|
|
||||||
|
?- format("~20f", [0.1]).
|
||||||
|
0.10000000000000000000true % this should use higher accuracy!
|
||||||
|
; false.
|
||||||
|
|
||||||
|
?- X is atan(2), format("~7f~n", [X]).
|
||||||
|
1.1071487
|
||||||
|
X = 1.1071487177940906
|
||||||
|
|
||||||
|
?- format("~`at~50|~n", []).
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
true
|
||||||
|
|
||||||
|
?- format("~t~N", []).
|
||||||
|
|
||||||
|
?- format("~q", [.]).
|
||||||
|
'.'true
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
We also provide a rudimentary version of portray_clause/1.
|
||||||
|
|
||||||
|
In the eventual library organization, portray_clause/1
|
||||||
|
and related predicates (such as listing/1) may be placed
|
||||||
|
in their own dedicated library.
|
||||||
|
|
||||||
|
portray_clause/1 is useful for printing solutions in such a way
|
||||||
|
that they can be read back with read/1.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
portray_clause(Term) :-
|
||||||
|
phrase(portray_clause_(Term), Ls),
|
||||||
|
maplist(write, Ls).
|
||||||
|
|
||||||
|
portray_clause_(Term) -->
|
||||||
|
portray_(Term), ".\n".
|
||||||
|
|
||||||
|
literal(Lit) --> format_("~q", [Lit]).
|
||||||
|
|
||||||
|
portray_(Var) --> { var(Var) }, !, literal(Var).
|
||||||
|
portray_((Head :- Body)) --> !,
|
||||||
|
literal(Head), " :-\n",
|
||||||
|
body_(Body, 0, 8).
|
||||||
|
portray_((Head --> Body)) --> !,
|
||||||
|
literal(Head), " -->\n",
|
||||||
|
body_(Body, 0, 8).
|
||||||
|
portray_(Any) --> literal(Any).
|
||||||
|
|
||||||
|
|
||||||
|
body_(Var, C, I) --> { var(Var) }, !,
|
||||||
|
indent_to(C, I),
|
||||||
|
literal(Var).
|
||||||
|
body_((A,B), C, I) --> !,
|
||||||
|
body_(A, C, I), ",\n",
|
||||||
|
body_(B, 0, I).
|
||||||
|
body_((A ; Else), C, I) --> % ( If -> Then ; Else )
|
||||||
|
{ nonvar(A), A = (If -> Then) },
|
||||||
|
!,
|
||||||
|
indent_to(C, I),
|
||||||
|
"( ",
|
||||||
|
{ C1 is I + 3 },
|
||||||
|
body_(If, C1, C1), " ->\n",
|
||||||
|
body_(Then, 0, C1), "\n",
|
||||||
|
else_branch(Else, C1, I).
|
||||||
|
body_((A;B), C, I) --> !,
|
||||||
|
indent_to(C, I),
|
||||||
|
"( ",
|
||||||
|
{ C1 is I + 3 },
|
||||||
|
body_(A, C1, C1), "\n",
|
||||||
|
else_branch(B, C1, I).
|
||||||
|
body_(Goal, C, I) -->
|
||||||
|
indent_to(C, I), literal(Goal).
|
||||||
|
|
||||||
|
|
||||||
|
else_branch(Else, C, I) -->
|
||||||
|
indent_to(0, I),
|
||||||
|
";", " ", % (see #336)
|
||||||
|
body_(Else, C, C), "\n",
|
||||||
|
indent_to(0, I),
|
||||||
|
")".
|
||||||
|
|
||||||
|
indent_to(CurrentColumn, Indent) -->
|
||||||
|
{ Delta is Indent - CurrentColumn },
|
||||||
|
format_("~t~*|", [Delta]).
|
||||||
|
|
||||||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
?- portray_clause(a), nl.
|
||||||
|
a.
|
||||||
|
|
||||||
|
?- nl, portray_clause((a :- b)), nl.
|
||||||
|
a :-
|
||||||
|
b.
|
||||||
|
|
||||||
|
?- nl, portray_clause((a :- b, c, d)), nl.
|
||||||
|
a :-
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
d.
|
||||||
|
|
||||||
|
|
||||||
|
?- nl, portray_clause([a,b,c,d]), nl.
|
||||||
|
"abcd".
|
||||||
|
|
||||||
|
?- nl, portray_clause(X).
|
||||||
|
?- nl, portray_clause((f(X) :- X)).
|
||||||
|
|
||||||
|
?- nl, portray_clause((h :- ( a -> b; c))).
|
||||||
|
|
||||||
|
?- nl, portray_clause((h :- ( (a -> x ; y) -> b; c))).
|
||||||
|
|
||||||
|
?- nl, portray_clause((h(X) :- ( (a(X) ; y(A,B)) -> b; c))).
|
||||||
|
|
||||||
|
?- nl, portray_clause((h :- (a,d;b,c) ; (b,e;d))).
|
||||||
|
|
||||||
|
?- nl, portray_clause((a :- b ; c ; d)).
|
||||||
|
|
||||||
|
?- nl, portray_clause((h :- L = '.')).
|
||||||
|
|
||||||
|
?- nl, portray_clause(-->(a, (b, {t}, d))).
|
||||||
|
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
:- use_module(library(si)).
|
:- use_module(library(si)).
|
||||||
|
|
||||||
gensym_key(Base, BaseKey) :-
|
gensym_key(Base, BaseKey) :-
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
%% for builtins that are not part of the ISO standard.
|
%% for builtins that are not part of the ISO standard.
|
||||||
%% must be loaded at the REPL with
|
%% must be loaded at the REPL with
|
||||||
|
|
||||||
%% ?- use_module(library(non_iso)).
|
%% ?- use_module(library(iso_ext)).
|
||||||
|
|
||||||
:- module(non_iso, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
|
:- module(iso_ext, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
|
||||||
call_with_inference_limit/3, forall/2, maybe/0,
|
call_with_inference_limit/3, forall/2, maybe/0,
|
||||||
partial_string/1, partial_string/3,
|
partial_string/1, partial_string/3,
|
||||||
partial_string_tail/2, set_random/1,
|
partial_string_tail/2, set_random/1,
|
||||||
@@ -157,13 +157,15 @@ set_random(Seed) :-
|
|||||||
; throw(error(instantiation_error, set_random/1))
|
; throw(error(instantiation_error, set_random/1))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
partial_string(String, L, L0) :-
|
partial_string(String, L, L0) :-
|
||||||
( String == [] -> throw(error(type_error(list, []), partial_string/3))
|
( String == [] ->
|
||||||
|
L = L0
|
||||||
; catch(atom_chars(Atom, String),
|
; catch(atom_chars(Atom, String),
|
||||||
error(E, _),
|
error(E, _),
|
||||||
throw(error(E, partial_string/3)))
|
throw(error(E, partial_string/3))),
|
||||||
),
|
'$create_partial_string'(Atom, L, L0)
|
||||||
'$create_partial_string'(Atom, L, L0).
|
).
|
||||||
|
|
||||||
partial_string(String) :-
|
partial_string(String) :-
|
||||||
'$is_partial_string'(String).
|
'$is_partial_string'(String).
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
:- module(lists, [member/2, select/3, append/3, foldl/4, foldl/5,
|
:- module(lists, [member/2, select/3, append/2, append/3, foldl/4, foldl/5,
|
||||||
memberchk/2, reverse/2, length/2, maplist/2,
|
memberchk/2, reverse/2, length/2, maplist/2,
|
||||||
maplist/3, maplist/4, maplist/5, maplist/6,
|
maplist/3, maplist/4, maplist/5, maplist/6,
|
||||||
maplist/7, maplist/8, maplist/9, same_length/2,
|
maplist/7, maplist/8, maplist/9, same_length/2,
|
||||||
sumlist/2]).
|
sum_list/2, transpose/2]).
|
||||||
|
|
||||||
|
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
@@ -44,6 +44,12 @@ select(X, [X|Xs], Xs).
|
|||||||
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
|
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
|
||||||
|
|
||||||
|
|
||||||
|
append([], []).
|
||||||
|
append([L0|Ls0], Ls) :-
|
||||||
|
append(L0, Rest, Ls),
|
||||||
|
append(Ls0, Rest).
|
||||||
|
|
||||||
|
|
||||||
append([], R, R).
|
append([], R, R).
|
||||||
append([X|L], R, [X|S]) :- append(L, R, S).
|
append([X|L], R, [X|S]) :- append(L, R, S).
|
||||||
|
|
||||||
@@ -102,14 +108,10 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7
|
|||||||
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s).
|
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s).
|
||||||
|
|
||||||
|
|
||||||
sumlist_([], S, S).
|
sum_list(Ls, S) :-
|
||||||
sumlist_([N|Ns], S, S0) :-
|
foldl(sum_, Ls, 0, S).
|
||||||
S1 is S0 + N,
|
|
||||||
sumlist_(Ns, S, S1).
|
|
||||||
|
|
||||||
sumlist(Ns, S) :-
|
sum_(L, S0, S) :- S is S0 + L.
|
||||||
must_be(list, Ns),
|
|
||||||
sumlist_(Ns, S, 0).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -134,3 +136,16 @@ foldl_([], [], _, A, A).
|
|||||||
foldl_([X|Xs], [Y|Ys], G_4, A0, A) :-
|
foldl_([X|Xs], [Y|Ys], G_4, A0, A) :-
|
||||||
call(G_4, X, Y, A0, A1),
|
call(G_4, X, Y, A0, A1),
|
||||||
foldl_(Xs, Ys, G_4, A1, A).
|
foldl_(Xs, Ys, G_4, A1, A).
|
||||||
|
|
||||||
|
transpose(Ls, Ts) :-
|
||||||
|
lists_transpose(Ls, Ts).
|
||||||
|
|
||||||
|
lists_transpose([], []).
|
||||||
|
lists_transpose([L|Ls], Ts) :-
|
||||||
|
maplist(same_length(L), Ls),
|
||||||
|
foldl(transpose_, L, Ts, [L|Ls], _).
|
||||||
|
|
||||||
|
transpose_(_, Fs, Lists0, Lists) :-
|
||||||
|
maplist(list_first_rest, Lists0, Fs, Lists).
|
||||||
|
|
||||||
|
list_first_rest([L|Ls], L, Ls).
|
||||||
|
|||||||
21
src/prolog/lib/pairs.pl
Normal file
21
src/prolog/lib/pairs.pl
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
:- module(pairs, [pairs_keys_values/3,
|
||||||
|
pairs_keys/2,
|
||||||
|
pairs_values/2,
|
||||||
|
map_list_to_pairs/3]).
|
||||||
|
|
||||||
|
|
||||||
|
pairs_keys_values([], [], []).
|
||||||
|
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
|
||||||
|
pairs_keys_values(ABs, As, Bs).
|
||||||
|
|
||||||
|
pairs_keys(Ps, Ks) :- pairs_keys_values(Ps, Ks, _).
|
||||||
|
|
||||||
|
pairs_values(Ps, Vs) :- pairs_keys_values(Ps, _, Vs).
|
||||||
|
|
||||||
|
map_list_to_pairs(Pred, Ls, Ps) :-
|
||||||
|
map_list_to_pairs2(Ls, Pred, Ps).
|
||||||
|
|
||||||
|
map_list_to_pairs2([], _, []).
|
||||||
|
map_list_to_pairs2([H|T0], Pred, [K-H|T]) :-
|
||||||
|
call(Pred, H, K),
|
||||||
|
map_list_to_pairs2(T0, Pred, T).
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
:- use_module(library(cont)).
|
:- use_module(library(cont)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
%:- use_module(library(debug)).
|
%:- use_module(library(debug)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
%% :- meta_predicate
|
%% :- meta_predicate
|
||||||
%% start_tabling(+, 0).
|
%% start_tabling(+, 0).
|
||||||
|
|||||||
@@ -208,4 +208,3 @@ dll_get_reverse_contents_(List, Contents) :-
|
|||||||
dll_get_pointer_to_previous(List, Prev),
|
dll_get_pointer_to_previous(List, Prev),
|
||||||
dll_get_reverse_contents_(Prev, Rest)
|
dll_get_reverse_contents_(Prev, Rest)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
]).
|
]).
|
||||||
|
|
||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
:- attribute table_global_worklist/1.
|
:- attribute table_global_worklist/1.
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(gensym)).
|
:- use_module(library(gensym)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
:- attribute table_status/1, newly_created_table_identifiers/1.
|
:- attribute table_status/1, newly_created_table_identifiers/1.
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
:- use_module(library(terms)).
|
:- use_module(library(terms)).
|
||||||
|
|
||||||
:- use_module(trie).
|
:- use_module(trie).
|
||||||
|
|||||||
1211
src/prolog/machine/arithmetic_ops.rs
Normal file
1211
src/prolog/machine/arithmetic_ops.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
|||||||
driver(Vars, Values) :-
|
driver(Vars, Values) :-
|
||||||
iterate(Vars, Values, ListOfListsOfGoalLists),
|
iterate(Vars, Values, ListOfListsOfGoalLists),
|
||||||
'$clear_attr_var_bindings',
|
|
||||||
!,
|
!,
|
||||||
call_goals(ListOfListsOfGoalLists),
|
call_goals(ListOfListsOfGoalLists),
|
||||||
'$return_from_verify_attr'.
|
'$return_from_verify_attr'.
|
||||||
@@ -17,13 +16,6 @@ gather_modules([Attr|Attrs], [Module|Modules]) :-
|
|||||||
'$module_of'(Module, Attr), % write the owning module of Attr to Module.
|
'$module_of'(Module, Attr), % write the owning module of Attr to Module.
|
||||||
gather_modules(Attrs, Modules).
|
gather_modules(Attrs, Modules).
|
||||||
|
|
||||||
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
|
|
||||||
catch(Module:verify_attributes(Var, Value, Goals),
|
|
||||||
error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
|
|
||||||
Goals = []),
|
|
||||||
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
|
||||||
verify_attrs([], _, _, []).
|
|
||||||
|
|
||||||
call_verify_attributes(Attrs, _, _, []) :-
|
call_verify_attributes(Attrs, _, _, []) :-
|
||||||
var(Attrs), !.
|
var(Attrs), !.
|
||||||
call_verify_attributes([], _, _, []).
|
call_verify_attributes([], _, _, []).
|
||||||
@@ -32,6 +24,13 @@ call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
|
|||||||
sort(Modules0, Modules),
|
sort(Modules0, Modules),
|
||||||
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
|
|
||||||
|
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
|
||||||
|
catch(Module:verify_attributes(Var, Value, Goals),
|
||||||
|
error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
|
||||||
|
Goals = []),
|
||||||
|
verify_attrs(Modules, Var, Value, ListOfGoalLists).
|
||||||
|
verify_attrs([], _, _, []).
|
||||||
|
|
||||||
call_goals([ListOfGoalLists | ListsCubed]) :-
|
call_goals([ListOfGoalLists | ListsCubed]) :-
|
||||||
call_goals_0(ListOfGoalLists),
|
call_goals_0(ListOfGoalLists),
|
||||||
call_goals(ListsCubed).
|
call_goals(ListsCubed).
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::prolog::machine::*;
|
use crate::prolog::machine::*;
|
||||||
|
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||||
@@ -18,7 +19,8 @@ pub(super) struct AttrVarInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AttrVarInitializer {
|
impl AttrVarInitializer {
|
||||||
pub(super) fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
|
pub(super)
|
||||||
|
fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
|
||||||
AttrVarInitializer {
|
AttrVarInitializer {
|
||||||
attribute_goals: vec![],
|
attribute_goals: vec![],
|
||||||
attr_var_queue: vec![],
|
attr_var_queue: vec![],
|
||||||
@@ -31,21 +33,24 @@ impl AttrVarInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn reset(&mut self) {
|
pub(super)
|
||||||
|
fn reset(&mut self) {
|
||||||
self.attribute_goals.clear();
|
self.attribute_goals.clear();
|
||||||
self.attr_var_queue.clear();
|
self.attr_var_queue.clear();
|
||||||
self.bindings.clear();
|
self.bindings.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
|
pub(super)
|
||||||
|
fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
|
||||||
self.attr_var_queue.truncate(queue_b);
|
self.attr_var_queue.truncate(queue_b);
|
||||||
self.bindings.truncate(bindings_b);
|
self.bindings.truncate(bindings_b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
|
pub(super)
|
||||||
|
fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
|
||||||
if self.attr_var_init.bindings.is_empty() {
|
if self.attr_var_init.bindings.is_empty() {
|
||||||
self.attr_var_init.instigating_p = self.p.local();
|
self.attr_var_init.instigating_p = self.p.local();
|
||||||
|
|
||||||
@@ -66,18 +71,17 @@ impl MachineState {
|
|||||||
.attr_var_init
|
.attr_var_init
|
||||||
.bindings
|
.bindings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(ref h, _)| Addr::AttrVar(*h));
|
.map(|(ref h, _)| HeapCellValue::Addr(Addr::AttrVar(*h)));
|
||||||
|
|
||||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||||
|
|
||||||
let iter = self
|
let iter = self
|
||||||
.attr_var_init
|
.attr_var_init
|
||||||
.bindings
|
.bindings
|
||||||
.iter()
|
.drain(0 ..)
|
||||||
.map(|(_, ref addr)| addr.clone());
|
.map(|(_, addr)| HeapCellValue::Addr(addr));
|
||||||
|
|
||||||
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||||
|
|
||||||
(var_list_addr, value_list_addr)
|
(var_list_addr, value_list_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +96,8 @@ impl MachineState {
|
|||||||
self[temp_v!(2)] = value_list_addr;
|
self[temp_v!(2)] = value_list_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
|
pub(super)
|
||||||
|
fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
|
||||||
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
|
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
|
.filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
|
||||||
@@ -101,13 +106,16 @@ impl MachineState {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
attr_vars.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
|
attr_vars.sort_unstable_by(|a1, a2| {
|
||||||
|
self.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
|
||||||
|
});
|
||||||
|
|
||||||
self.term_dedup(&mut attr_vars);
|
self.term_dedup(&mut attr_vars);
|
||||||
attr_vars.into_iter()
|
attr_vars.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
|
pub(super)
|
||||||
|
fn verify_attr_interrupt(&mut self, p: usize) {
|
||||||
self.allocate(self.num_of_args + 2);
|
self.allocate(self.num_of_args + 2);
|
||||||
|
|
||||||
let e = self.e;
|
let e = self.e;
|
||||||
@@ -118,9 +126,9 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
||||||
Addr::Con(Constant::CutPoint(self.b0));
|
Addr::CutPoint(self.b0);
|
||||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
|
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
|
||||||
Addr::Con(Constant::Usize(self.num_of_args));
|
Addr::Usize(self.num_of_args);
|
||||||
|
|
||||||
self.verify_attributes();
|
self.verify_attributes();
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use ref_thread_local::RefThreadLocal;
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@@ -60,9 +59,9 @@ fn fix_filename(
|
|||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_module<R: Read>(
|
fn load_module(
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
stream: ParsingStream<R>,
|
stream: Stream,
|
||||||
suppress_warnings: bool,
|
suppress_warnings: bool,
|
||||||
listing_src: &ListingSource,
|
listing_src: &ListingSource,
|
||||||
) -> Result<ClauseName, SessionError> {
|
) -> Result<ClauseName, SessionError> {
|
||||||
@@ -78,7 +77,11 @@ fn load_module<R: Read>(
|
|||||||
listing_src.clone(),
|
listing_src.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let results = compiler.gather_items(wam, stream, &mut indices);
|
let results = compiler.gather_items(
|
||||||
|
wam,
|
||||||
|
&mut parsing_stream(stream),
|
||||||
|
&mut indices,
|
||||||
|
);
|
||||||
|
|
||||||
let module_name = if let Some(ref module) = &compiler.module {
|
let module_name = if let Some(ref module) = &compiler.module {
|
||||||
module.module_decl.name.clone()
|
module.module_decl.name.clone()
|
||||||
@@ -114,14 +117,14 @@ fn load_module_from_file(
|
|||||||
let mut path_buf = fix_filename(wam.indices.atom_tbl.clone(), path_buf)?;
|
let mut path_buf = fix_filename(wam.indices.atom_tbl.clone(), path_buf)?;
|
||||||
let filename = clause_name!(path_buf.to_string_lossy().to_string(), wam.indices.atom_tbl);
|
let filename = clause_name!(path_buf.to_string_lossy().to_string(), wam.indices.atom_tbl);
|
||||||
|
|
||||||
let file_handle = File::open(&path_buf).or_else(|_| {
|
let file_handle = Stream::from(File::open(&path_buf).or_else(|_| {
|
||||||
Err(SessionError::InvalidFileName(filename.clone()))
|
Err(SessionError::InvalidFileName(filename.clone()))
|
||||||
})?;
|
})?);
|
||||||
|
|
||||||
path_buf.pop();
|
path_buf.pop();
|
||||||
|
|
||||||
let listing_src = ListingSource::from_file_and_path(filename, path_buf);
|
let listing_src = ListingSource::from_file_and_path(filename, path_buf);
|
||||||
load_module(wam, parsing_stream(file_handle), suppress_warnings, &listing_src)
|
load_module(wam, file_handle, suppress_warnings, &listing_src)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
|
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
|
||||||
@@ -320,10 +323,11 @@ fn setup_module_expansions(wam: &mut Machine, module: &Module) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn compile_into_module<R: Read>(
|
pub(super)
|
||||||
|
fn compile_into_module(
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
module_name: ClauseName,
|
module_name: ClauseName,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
) -> EvalSession {
|
) -> EvalSession {
|
||||||
let mut indices = default_index_store!(wam.atom_tbl_of(&name));
|
let mut indices = default_index_store!(wam.atom_tbl_of(&name));
|
||||||
@@ -333,7 +337,11 @@ pub(super) fn compile_into_module<R: Read>(
|
|||||||
indices.op_dir = module.op_dir.clone();
|
indices.op_dir = module.op_dir.clone();
|
||||||
indices.atom_tbl = module.atom_tbl.clone();
|
indices.atom_tbl = module.atom_tbl.clone();
|
||||||
|
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo, true, module.listing_src.clone());
|
let mut compiler = ListingCompiler::new(
|
||||||
|
&wam.code_repo,
|
||||||
|
true,
|
||||||
|
module.listing_src.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
match compile_into_module_impl(wam, &mut compiler, module, src, indices) {
|
match compile_into_module_impl(wam, &mut compiler, module, src, indices) {
|
||||||
Ok(()) => EvalSession::EntrySuccess,
|
Ok(()) => EvalSession::EntrySuccess,
|
||||||
@@ -348,11 +356,11 @@ pub(super) fn compile_into_module<R: Read>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_into_module_impl<R: Read>(
|
fn compile_into_module_impl(
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
compiler: &mut ListingCompiler,
|
compiler: &mut ListingCompiler,
|
||||||
module: Module,
|
module: Module,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
mut indices: IndexStore,
|
mut indices: IndexStore,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
setup_module_expansions(wam, &module);
|
setup_module_expansions(wam, &module);
|
||||||
@@ -363,7 +371,11 @@ fn compile_into_module_impl<R: Read>(
|
|||||||
wam.code_repo.compile_hook(CompileTimeHook::TermExpansion)?;
|
wam.code_repo.compile_hook(CompileTimeHook::TermExpansion)?;
|
||||||
wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion)?;
|
wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion)?;
|
||||||
|
|
||||||
let mut results = compiler.gather_items(wam, src, &mut indices)?;
|
let mut results = compiler.gather_items(
|
||||||
|
wam,
|
||||||
|
&mut parsing_stream(src),
|
||||||
|
&mut indices,
|
||||||
|
)?;
|
||||||
|
|
||||||
compiler.adapt_in_situ_code(
|
compiler.adapt_in_situ_code(
|
||||||
results.worker_results,
|
results.worker_results,
|
||||||
@@ -392,7 +404,6 @@ fn compile_into_module_impl<R: Read>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
wam.code_repo.code.extend(results.in_situ_code.into_iter());
|
wam.code_repo.code.extend(results.in_situ_code.into_iter());
|
||||||
|
|
||||||
clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
|
clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
|
||||||
|
|
||||||
Ok(compiler.drop_expansions(&mut wam.code_repo))
|
Ok(compiler.drop_expansions(&mut wam.code_repo))
|
||||||
@@ -548,8 +559,8 @@ fn add_module(
|
|||||||
term_dir: TermDir,
|
term_dir: TermDir,
|
||||||
) {
|
) {
|
||||||
module.code_dir.extend(indices.code_dir);
|
module.code_dir.extend(indices.code_dir);
|
||||||
module.op_dir.extend(indices.op_dir.into_iter());
|
module.op_dir.extend(indices.op_dir);
|
||||||
module.term_dir.extend(term_dir.into_iter());
|
module.term_dir.extend(term_dir);
|
||||||
|
|
||||||
wam.add_in_situ_module_dir(indices.module_dir);
|
wam.add_in_situ_module_dir(indices.module_dir);
|
||||||
wam.add_module(module);
|
wam.add_module(module);
|
||||||
@@ -568,7 +579,7 @@ fn add_non_module_code(
|
|||||||
clause_code_generator.generate_clause_code(&dynamic_clause_map, wam)?;
|
clause_code_generator.generate_clause_code(&dynamic_clause_map, wam)?;
|
||||||
|
|
||||||
add_toplevel(wam, indices, term_dir);
|
add_toplevel(wam, indices, term_dir);
|
||||||
wam.code_repo.code.extend(code.into_iter());
|
wam.code_repo.code.extend(code);
|
||||||
clause_code_generator.add_clause_code(wam, dynamic_clause_map);
|
clause_code_generator.add_clause_code(wam, dynamic_clause_map);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -591,12 +602,18 @@ fn load_library(
|
|||||||
|
|
||||||
load_module(
|
load_module(
|
||||||
wam,
|
wam,
|
||||||
parsing_stream(code.as_bytes()),
|
Stream::from(*code),
|
||||||
suppress_warnings,
|
suppress_warnings,
|
||||||
&listing_src,
|
&listing_src,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => Err(SessionError::ModuleNotFound)
|
None => {
|
||||||
|
let err = ExistenceError::SourceSink(ModuleSource::Library(
|
||||||
|
name.clone()
|
||||||
|
));
|
||||||
|
|
||||||
|
Err(SessionError::ExistenceError(err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,7 +699,11 @@ impl ListingCompiler {
|
|||||||
|
|
||||||
Ok(wam_indices.insert_module(submodule))
|
Ok(wam_indices.insert_module(submodule))
|
||||||
} else {
|
} else {
|
||||||
Err(SessionError::ModuleNotFound)
|
let err = ExistenceError::SourceSink(ModuleSource::File(
|
||||||
|
module_name,
|
||||||
|
));
|
||||||
|
|
||||||
|
Err(SessionError::ExistenceError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,7 +737,11 @@ impl ListingCompiler {
|
|||||||
|
|
||||||
Ok(wam_indices.insert_module(submodule))
|
Ok(wam_indices.insert_module(submodule))
|
||||||
} else {
|
} else {
|
||||||
Err(SessionError::ModuleNotFound)
|
let err = ExistenceError::SourceSink(ModuleSource::File(
|
||||||
|
module_name
|
||||||
|
));
|
||||||
|
|
||||||
|
Err(SessionError::ExistenceError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,6 +993,10 @@ impl ListingCompiler {
|
|||||||
Declaration::Op(op_decl) => {
|
Declaration::Op(op_decl) => {
|
||||||
self.submit_op(wam, indices, &op_decl)
|
self.submit_op(wam, indices, &op_decl)
|
||||||
}
|
}
|
||||||
|
Declaration::SetPrologFlag(dbl_quotes) => {
|
||||||
|
wam.machine_st.flags.double_quotes = dbl_quotes;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Declaration::UseModule(ModuleSource::Library(name)) => {
|
Declaration::UseModule(ModuleSource::Library(name)) => {
|
||||||
let name = if !wam.indices.modules.contains_key(&name) {
|
let name = if !wam.indices.modules.contains_key(&name) {
|
||||||
load_library(wam, name, true)?
|
load_library(wam, name, true)?
|
||||||
@@ -1018,10 +1047,10 @@ impl ListingCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_multifile_decl<R: Read>(
|
fn setup_multifile_decl(
|
||||||
&self,
|
&self,
|
||||||
indicator: MultiFileIndicator,
|
indicator: MultiFileIndicator,
|
||||||
worker: &mut TopLevelBatchWorker<R>,
|
worker: &mut TopLevelBatchWorker,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
match indicator {
|
match indicator {
|
||||||
MultiFileIndicator::LocalScoped(name, arity) => {
|
MultiFileIndicator::LocalScoped(name, arity) => {
|
||||||
@@ -1042,7 +1071,11 @@ impl ListingCompiler {
|
|||||||
insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs);
|
insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(SessionError::ModuleNotFound);
|
let err = ExistenceError::SourceSink(ModuleSource::File(
|
||||||
|
module_name,
|
||||||
|
));
|
||||||
|
|
||||||
|
return Err(SessionError::ExistenceError(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1051,10 +1084,10 @@ impl ListingCompiler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_and_commit_decl<R: Read>(
|
fn process_and_commit_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
decl: Declaration,
|
decl: Declaration,
|
||||||
worker: &mut TopLevelBatchWorker<R>,
|
worker: &mut TopLevelBatchWorker,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
@@ -1101,15 +1134,15 @@ impl ListingCompiler {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn gather_items<R: Read>(
|
pub(crate) fn gather_items(
|
||||||
&mut self,
|
&mut self,
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
mut src: ParsingStream<R>,
|
src: &mut ParsingStream<Stream>,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
) -> Result<GatherResult, SessionError> {
|
) -> Result<GatherResult, SessionError> {
|
||||||
let flags = wam.machine_flags();
|
let flags = wam.machine_flags();
|
||||||
let atom_tbl = indices.atom_tbl.clone();
|
let atom_tbl = indices.atom_tbl.clone();
|
||||||
let mut worker = TopLevelBatchWorker::new(&mut src, atom_tbl.clone(), flags, wam);
|
let mut worker = TopLevelBatchWorker::new(src, atom_tbl.clone(), flags, wam);
|
||||||
|
|
||||||
let mut toplevel_results = vec![];
|
let mut toplevel_results = vec![];
|
||||||
let mut toplevel_indices = default_index_store!(atom_tbl.clone());
|
let mut toplevel_indices = default_index_store!(atom_tbl.clone());
|
||||||
@@ -1302,28 +1335,32 @@ fn compile_work_impl(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_work<R: Read>(
|
fn compile_work(
|
||||||
compiler: &mut ListingCompiler,
|
compiler: &mut ListingCompiler,
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
mut indices: IndexStore,
|
mut indices: IndexStore,
|
||||||
) -> EvalSession {
|
) -> EvalSession {
|
||||||
|
let src = &mut parsing_stream(src);
|
||||||
let results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
|
let results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
|
||||||
|
|
||||||
try_eval_session!(compile_work_impl(compiler, wam, indices, results));
|
try_eval_session!(compile_work_impl(compiler, wam, indices, results));
|
||||||
|
|
||||||
EvalSession::EntrySuccess
|
EvalSession::EntrySuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a truncated version of compile_user_module, used for
|
/* This is a truncated version of compile_user_module, used for
|
||||||
compiling code composing special forms, ie. the code that calls
|
compiling code composing special forms, ie. the code that calls
|
||||||
M:verify_attributes on attributed variables. */
|
M:verify_attributes on attributed variables. */
|
||||||
pub fn compile_special_form<R: Read>(
|
pub fn compile_special_form(
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
listing_src: ListingSource,
|
listing_src: ListingSource,
|
||||||
) -> Result<usize, SessionError> {
|
) -> Result<usize, SessionError> {
|
||||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||||
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
||||||
|
|
||||||
|
let src = &mut parsing_stream(src);
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo, true, listing_src);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, true, listing_src);
|
||||||
let mut results = compiler.gather_items(wam, src, &mut indices)?;
|
let mut results = compiler.gather_items(wam, src, &mut indices)?;
|
||||||
|
|
||||||
@@ -1348,9 +1385,9 @@ pub fn compile_special_form<R: Read>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compile_listing<R: Read>(
|
pub fn compile_listing(
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
indices: IndexStore,
|
indices: IndexStore,
|
||||||
suppress_warnings: bool,
|
suppress_warnings: bool,
|
||||||
listing_src: ListingSource,
|
listing_src: ListingSource,
|
||||||
@@ -1373,20 +1410,24 @@ pub(super) fn setup_indices(
|
|||||||
module: ClauseName,
|
module: ClauseName,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
if let Some(module) = wam.indices.take_module(module) {
|
if let Some(module) = wam.indices.take_module(module.clone()) {
|
||||||
let flags = wam.machine_flags();
|
let flags = wam.machine_flags();
|
||||||
let result = indices.use_module(&mut wam.code_repo, flags, &module);
|
let result = indices.use_module(&mut wam.code_repo, flags, &module);
|
||||||
|
|
||||||
wam.indices.insert_module(module);
|
wam.indices.insert_module(module);
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
Err(SessionError::ModuleNotFound)
|
let err = ExistenceError::SourceSink(ModuleSource::Library(
|
||||||
|
module
|
||||||
|
));
|
||||||
|
|
||||||
|
Err(SessionError::ExistenceError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_user_module<R: Read>(
|
pub fn compile_user_module(
|
||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
suppress_warnings: bool,
|
suppress_warnings: bool,
|
||||||
listing_src: ListingSource,
|
listing_src: ListingSource,
|
||||||
) -> EvalSession {
|
) -> EvalSession {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::stack::*;
|
use crate::prolog::machine::stack::*;
|
||||||
|
use crate::prolog::machine::streams::*;
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
use std::ops::IndexMut;
|
use std::ops::IndexMut;
|
||||||
|
|
||||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||||
@@ -11,12 +13,13 @@ pub enum AttrVarPolicy {
|
|||||||
StripAttributes
|
StripAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
pub(crate)
|
||||||
fn threshold(&self) -> usize;
|
trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||||
fn push(&mut self, val: HeapCellValue);
|
|
||||||
fn store(&self, val: Addr) -> Addr;
|
|
||||||
fn deref(&self, val: Addr) -> Addr;
|
fn deref(&self, val: Addr) -> Addr;
|
||||||
|
fn push(&mut self, val: HeapCellValue);
|
||||||
fn stack(&mut self) -> &mut Stack;
|
fn stack(&mut self) -> &mut Stack;
|
||||||
|
fn store(&self, val: Addr) -> Addr;
|
||||||
|
fn threshold(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
@@ -30,13 +33,13 @@ struct CopyTermState<T: CopierTarget> {
|
|||||||
scan: usize,
|
scan: usize,
|
||||||
old_h: usize,
|
old_h: usize,
|
||||||
target: T,
|
target: T,
|
||||||
attr_var_policy: AttrVarPolicy
|
attr_var_policy: AttrVarPolicy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: CopierTarget> CopyTermState<T> {
|
impl<T: CopierTarget> CopyTermState<T> {
|
||||||
fn new(target: T, attr_var_policy: AttrVarPolicy) -> Self {
|
fn new(target: T, attr_var_policy: AttrVarPolicy) -> Self {
|
||||||
CopyTermState {
|
CopyTermState {
|
||||||
trail: vec![],
|
trail: Trail::new(),
|
||||||
scan: 0,
|
scan: 0,
|
||||||
old_h: target.threshold(),
|
old_h: target.threshold(),
|
||||||
target,
|
target,
|
||||||
@@ -50,152 +53,99 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
&mut self.target[scan]
|
&mut self.target[scan]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copied_list(&mut self, addr: usize) -> bool {
|
fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
|
||||||
match &self.target[addr] {
|
let trail_item = mem::replace(
|
||||||
HeapCellValue::Addr(Addr::Lis(addr)) | HeapCellValue::Addr(Addr::HeapCell(addr)) => {
|
&mut self.target[addr],
|
||||||
if *addr >= self.old_h {
|
HeapCellValue::Addr(Addr::Lis(threshold)),
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(*addr));
|
);
|
||||||
self.scan += 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
|
|
||||||
false
|
self.trail.push((
|
||||||
}
|
Ref::HeapCell(addr),
|
||||||
|
trail_item,
|
||||||
fn copied_partial_string(&mut self, addr: usize) -> bool {
|
));
|
||||||
if let HeapCellValue::PartialString(ref pstr) = &self.target[addr] {
|
|
||||||
if let Addr::PStrLocation(h, n) = pstr.tail_addr() {
|
|
||||||
if *h >= self.old_h {
|
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(*h, *n));
|
|
||||||
self.scan += 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_list(&mut self, addr: usize) {
|
fn copy_list(&mut self, addr: usize) {
|
||||||
if self.copied_list(addr) {
|
for offset in 0 .. 2 {
|
||||||
|
if let Addr::Lis(h) = self.target[addr + offset].as_addr(addr + offset) {
|
||||||
|
if h >= self.old_h {
|
||||||
|
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h));
|
||||||
|
self.scan += 1;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let threshold = self.target.threshold();
|
let threshold = self.target.threshold();
|
||||||
|
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
|
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
|
||||||
|
|
||||||
let ra = self.target[addr].as_addr(threshold);
|
for i in 0 .. 2 {
|
||||||
let rd = self.target.store(self.target.deref(ra.clone()));
|
let hcv = self.target[addr + i].context_free_clone();
|
||||||
|
|
||||||
self.target.push(HeapCellValue::Addr(ra.clone()));
|
|
||||||
|
|
||||||
let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
|
|
||||||
|
|
||||||
self.target.push(hcv);
|
self.target.push(hcv);
|
||||||
|
|
||||||
match rd.clone() {
|
|
||||||
Addr::AttrVar(h) | Addr::HeapCell(h) | Addr::PStrTail(h, _)
|
|
||||||
if h >= self.old_h => {
|
|
||||||
self.target[threshold] = HeapCellValue::Addr(rd)
|
|
||||||
}
|
}
|
||||||
var @ Addr::AttrVar(_)
|
|
||||||
| var @ Addr::HeapCell(..)
|
|
||||||
| var @ Addr::StackCell(..)
|
|
||||||
| var @ Addr::PStrTail(..) => {
|
|
||||||
if ra == rd {
|
|
||||||
self.reinstantiate_var(var, threshold);
|
|
||||||
|
|
||||||
if let AttrVarPolicy::StripAttributes = self.attr_var_policy {
|
let cdr = self.target.store(self.target.deref(Addr::HeapCell(addr + 1)));
|
||||||
self.trail.push((Ref::HeapCell(addr), HeapCellValue::Addr(ra)));
|
|
||||||
self.target[addr] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
if !cdr.is_ref() {
|
||||||
}
|
self.trail_list_cell(addr + 1, threshold);
|
||||||
} else {
|
} else {
|
||||||
self.target[threshold] = HeapCellValue::Addr(ra);
|
let car = self.target.store(self.target.deref(Addr::HeapCell(addr)));
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.trail.push((
|
|
||||||
Ref::HeapCell(addr),
|
|
||||||
HeapCellValue::Addr(self.target[addr].as_addr(addr)),
|
|
||||||
));
|
|
||||||
|
|
||||||
self.target[addr] = HeapCellValue::Addr(Addr::Lis(threshold))
|
if !car.is_ref() {
|
||||||
|
self.trail_list_cell(addr, threshold);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn copy_partial_string(&mut self, addr: usize, n: usize) {
|
fn copy_partial_string(&mut self, addr: usize, n: usize) {
|
||||||
let threshold = self.target.threshold();
|
if let &HeapCellValue::Addr(Addr::PStrLocation(h, _)) = &self.target[addr] {
|
||||||
|
if h >= self.old_h {
|
||||||
|
*self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(h, n));
|
||||||
|
self.scan += 1;
|
||||||
|
|
||||||
let tail_addr =
|
|
||||||
match &self.target[addr] {
|
|
||||||
HeapCellValue::PartialString(ref pstr) => {
|
|
||||||
self.trail.push((
|
|
||||||
Ref::PStrTail(addr, 0),
|
|
||||||
HeapCellValue::Addr(pstr.tail.clone()),
|
|
||||||
));
|
|
||||||
|
|
||||||
self.target.store(self.target.deref(pstr.tail.clone()))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let pstr =
|
|
||||||
match &mut self.target[addr] {
|
|
||||||
HeapCellValue::PartialString(ref mut pstr) => {
|
|
||||||
let mut new_pstr = pstr.clone_from_offset(n);
|
|
||||||
|
|
||||||
if let Addr::PStrTail(h, n) = &tail_addr {
|
|
||||||
new_pstr.tail = if *h == addr {
|
|
||||||
Addr::PStrTail(threshold, *n)
|
|
||||||
} else {
|
|
||||||
Addr::HeapCell(threshold + 1)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
new_pstr.tail = Addr::HeapCell(threshold + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pstr.tail = Addr::PStrLocation(threshold, 0);
|
|
||||||
new_pstr
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match tail_addr {
|
|
||||||
Addr::PStrTail(h, _) if h == addr => {
|
|
||||||
self.target.push(HeapCellValue::PartialString(pstr));
|
|
||||||
}
|
|
||||||
addr => {
|
|
||||||
self.target.push(HeapCellValue::PartialString(pstr));
|
|
||||||
self.target.push(HeapCellValue::Addr(addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copy_partial_string_from(&mut self, addr: usize, n: usize) {
|
|
||||||
if self.copied_partial_string(addr) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let threshold = self.target.threshold();
|
let threshold = self.target.threshold();
|
||||||
|
|
||||||
self.target[self.scan] =
|
*self.value_at_scan() =
|
||||||
HeapCellValue::Addr(Addr::PStrLocation(threshold, n));
|
HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
|
||||||
|
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
|
|
||||||
self.copy_partial_string(addr, n);
|
let (pstr, has_tail) =
|
||||||
|
match &self.target[addr] {
|
||||||
|
&HeapCellValue::PartialString(ref pstr, has_tail) => {
|
||||||
|
(pstr.clone_from_offset(n), has_tail)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.target.push(HeapCellValue::PartialString(pstr, has_tail));
|
||||||
|
|
||||||
|
let replacement = HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
|
||||||
|
|
||||||
|
let trail_item = mem::replace(
|
||||||
|
&mut self.target[addr],
|
||||||
|
replacement,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.trail.push((
|
||||||
|
Ref::HeapCell(addr),
|
||||||
|
trail_item,
|
||||||
|
));
|
||||||
|
|
||||||
|
if has_tail {
|
||||||
|
let tail_addr = self.target[addr + 1].as_addr(addr + 1);
|
||||||
|
self.target.push(HeapCellValue::Addr(tail_addr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reinstantiate_var(&mut self, addr: Addr, frontier: usize) {
|
fn reinstantiate_var(&mut self, addr: Addr, frontier: usize) {
|
||||||
@@ -203,6 +153,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
Addr::HeapCell(h) => {
|
Addr::HeapCell(h) => {
|
||||||
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
||||||
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
||||||
|
|
||||||
self.trail.push((
|
self.trail.push((
|
||||||
Ref::HeapCell(h),
|
Ref::HeapCell(h),
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h)),
|
HeapCellValue::Addr(Addr::HeapCell(h)),
|
||||||
@@ -211,27 +162,12 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
Addr::StackCell(fr, sc) => {
|
Addr::StackCell(fr, sc) => {
|
||||||
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
|
||||||
self.target.stack().index_and_frame_mut(fr)[sc] = Addr::HeapCell(frontier);
|
self.target.stack().index_and_frame_mut(fr)[sc] = Addr::HeapCell(frontier);
|
||||||
|
|
||||||
self.trail.push((
|
self.trail.push((
|
||||||
Ref::StackCell(fr, sc),
|
Ref::StackCell(fr, sc),
|
||||||
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
|
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Addr::PStrTail(h, n) => {
|
|
||||||
match &mut self.target[h] {
|
|
||||||
HeapCellValue::PartialString(ref mut pstr) => {
|
|
||||||
pstr.tail = Addr::PStrTail(frontier, n);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.target[frontier] = HeapCellValue::Addr(Addr::PStrTail(frontier, n));
|
|
||||||
self.trail.push((
|
|
||||||
Ref::PStrTail(h, n),
|
|
||||||
HeapCellValue::Addr(Addr::PStrTail(h, n))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Addr::AttrVar(h) => {
|
Addr::AttrVar(h) => {
|
||||||
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||||
self.target.threshold()
|
self.target.threshold()
|
||||||
@@ -241,6 +177,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
|
|
||||||
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||||
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||||
|
|
||||||
self.trail.push((
|
self.trail.push((
|
||||||
Ref::AttrVar(h),
|
Ref::AttrVar(h),
|
||||||
HeapCellValue::Addr(Addr::AttrVar(h)),
|
HeapCellValue::Addr(Addr::AttrVar(h)),
|
||||||
@@ -249,18 +186,20 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||||
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
||||||
|
|
||||||
let list_val = self.target[h + 1].clone();
|
let list_val = self.target[h + 1].context_free_clone();
|
||||||
self.target.push(list_val);
|
self.target.push(list_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_var(&mut self, addr: Addr) {
|
fn copy_var(&mut self, addr: Addr) {
|
||||||
let rd = self.target.store(self.target.deref(addr.clone()));
|
let rd = self.target.store(self.target.deref(addr));
|
||||||
|
|
||||||
match rd.clone() {
|
match rd {
|
||||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
@@ -275,30 +214,54 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn copy_stream(&mut self, addr: usize) {
|
||||||
|
let threshold = self.target.threshold();
|
||||||
|
|
||||||
|
let trail_item = mem::replace(
|
||||||
|
&mut self.target[addr],
|
||||||
|
HeapCellValue::Addr(Addr::Stream(threshold)),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.trail.push((
|
||||||
|
Ref::HeapCell(addr),
|
||||||
|
trail_item,
|
||||||
|
));
|
||||||
|
|
||||||
|
self.target.push(HeapCellValue::Stream(Stream::null_stream()));
|
||||||
|
|
||||||
|
self.scan += 1;
|
||||||
|
}
|
||||||
|
|
||||||
fn copy_structure(&mut self, addr: usize) {
|
fn copy_structure(&mut self, addr: usize) {
|
||||||
match self.target[addr].clone() {
|
match self.target[addr].context_free_clone() {
|
||||||
HeapCellValue::NamedStr(arity, name, fixity) => {
|
HeapCellValue::NamedStr(arity, name, fixity) => {
|
||||||
let threshold = self.target.threshold();
|
let threshold = self.target.threshold();
|
||||||
|
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
|
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
|
||||||
self.target[addr] = HeapCellValue::Addr(Addr::Str(threshold));
|
|
||||||
|
let trail_item = mem::replace(
|
||||||
|
&mut self.target[addr],
|
||||||
|
HeapCellValue::Addr(Addr::Str(threshold)),
|
||||||
|
);
|
||||||
|
|
||||||
self.trail.push((
|
self.trail.push((
|
||||||
Ref::HeapCell(addr),
|
Ref::HeapCell(addr),
|
||||||
HeapCellValue::NamedStr(arity, name.clone(), fixity.clone()),
|
trail_item,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
|
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
|
||||||
|
|
||||||
for i in 0..arity {
|
for i in 0..arity {
|
||||||
let hcv = self.target[addr + 1 + i].clone();
|
let hcv = self.target[addr + 1 + i].context_free_clone();
|
||||||
self.target.push(hcv);
|
self.target.push(hcv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Str(addr)) => {
|
HeapCellValue::Addr(Addr::Str(addr)) => {
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
|
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
@@ -310,32 +273,43 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
|
|
||||||
while self.scan < self.target.threshold() {
|
while self.scan < self.target.threshold() {
|
||||||
match self.value_at_scan() {
|
match self.value_at_scan() {
|
||||||
HeapCellValue::NamedStr(..) => {
|
&mut HeapCellValue::Addr(addr) => {
|
||||||
|
match addr {
|
||||||
|
Addr::Con(h) => {
|
||||||
|
let addr = self.target[h].as_addr(h);
|
||||||
|
|
||||||
|
if addr == Addr::Con(h) {
|
||||||
|
*self.value_at_scan() = self.target[h].context_free_clone();
|
||||||
|
} else {
|
||||||
|
*self.value_at_scan() = HeapCellValue::Addr(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Lis(h) if h >= self.old_h => {
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(ref addr) => {
|
Addr::Lis(h) => {
|
||||||
match addr.clone() {
|
self.copy_list(h);
|
||||||
Addr::Lis(addr) => {
|
|
||||||
self.copy_list(addr);
|
|
||||||
}
|
}
|
||||||
addr @ Addr::AttrVar(_)
|
addr @ Addr::AttrVar(_) |
|
||||||
| addr @ Addr::HeapCell(_)
|
addr @ Addr::HeapCell(_) |
|
||||||
| addr @ Addr::StackCell(..)
|
addr @ Addr::StackCell(..) => {
|
||||||
| addr @ Addr::PStrTail(..) => {
|
|
||||||
self.copy_var(addr);
|
self.copy_var(addr);
|
||||||
}
|
}
|
||||||
Addr::Str(addr) => {
|
Addr::Str(addr) => {
|
||||||
self.copy_structure(addr);
|
self.copy_structure(addr);
|
||||||
}
|
}
|
||||||
Addr::PStrLocation(addr, n) => {
|
Addr::PStrLocation(addr, n) => {
|
||||||
self.copy_partial_string_from(addr, n);
|
self.copy_partial_string(addr, n);
|
||||||
}
|
}
|
||||||
Addr::Con(_) | Addr::DBRef(_) => {
|
Addr::Stream(h) => {
|
||||||
|
self.copy_stream(h);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::PartialString(_) => {
|
_ => {
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,10 +323,6 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
match r {
|
match r {
|
||||||
Ref::AttrVar(h) | Ref::HeapCell(h) =>
|
Ref::AttrVar(h) | Ref::HeapCell(h) =>
|
||||||
self.target[h] = value,
|
self.target[h] = value,
|
||||||
Ref::PStrTail(h, _) =>
|
|
||||||
if let HeapCellValue::PartialString(ref mut pstr) = &mut self.target[h] {
|
|
||||||
pstr.tail = value.as_addr(0);
|
|
||||||
},
|
|
||||||
Ref::StackCell(fr, sc) =>
|
Ref::StackCell(fr, sc) =>
|
||||||
self.target.stack().index_and_frame_mut(fr)[sc] = value.as_addr(0),
|
self.target.stack().index_and_frame_mut(fr)[sc] = value.as_addr(0),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::heap_print::*;
|
use crate::prolog::heap_print::*;
|
||||||
|
use crate::prolog::machine::*;
|
||||||
use crate::prolog::machine::compile::*;
|
use crate::prolog::machine::compile::*;
|
||||||
use crate::prolog::machine::machine_errors::*;
|
use crate::prolog::machine::machine_errors::*;
|
||||||
use crate::prolog::machine::*;
|
use crate::prolog::machine::streams::*;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
|
pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
|
||||||
@@ -15,9 +16,9 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_into_machine<R: Read>(
|
fn compile_into_machine(
|
||||||
&mut self,
|
&mut self,
|
||||||
src: ParsingStream<R>,
|
src: Stream,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
) -> EvalSession {
|
) -> EvalSession {
|
||||||
@@ -42,13 +43,35 @@ impl Machine {
|
|||||||
let arity = self.machine_st[arity].clone();
|
let arity = self.machine_st[arity].clone();
|
||||||
|
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
Addr::Con(h) =>
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.machine_st.heap[h] {
|
||||||
|
name.clone()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
||||||
Addr::Con(Constant::Integer(arity)) => arity.to_usize().unwrap(),
|
Addr::Con(h) => {
|
||||||
_ => unreachable!(),
|
match &self.machine_st.heap[h] {
|
||||||
|
HeapCellValue::Integer(ref arity) => {
|
||||||
|
arity.to_usize().unwrap()
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
||||||
|
usize::try_from(*arity).unwrap()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Usize(n) => {
|
||||||
|
n
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(name, arity)
|
(name, arity)
|
||||||
@@ -102,7 +125,9 @@ impl Machine {
|
|||||||
let module_addr = self.machine_st[module].clone();
|
let module_addr = self.machine_st[module].clone();
|
||||||
|
|
||||||
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get_mut(&module) {
|
Addr::Con(h) =>
|
||||||
|
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
||||||
|
match self.indices.modules.get_mut(module) {
|
||||||
Some(ref mut module) => {
|
Some(ref mut module) => {
|
||||||
module.code_dir.remove(&(name.clone(), arity));
|
module.code_dir.remove(&(name.clone(), arity));
|
||||||
module.module_decl.name.clone()
|
module.module_decl.name.clone()
|
||||||
@@ -111,6 +136,9 @@ impl Machine {
|
|||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@@ -130,7 +158,12 @@ impl Machine {
|
|||||||
) {
|
) {
|
||||||
let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
|
let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
|
||||||
|
|
||||||
let result = self.compile_into_machine(parsing_stream(pred_str.as_bytes()), name, arity);
|
let result = self.compile_into_machine(
|
||||||
|
Stream::from(pred_str),
|
||||||
|
name,
|
||||||
|
arity,
|
||||||
|
);
|
||||||
|
|
||||||
self.machine_st = machine_st;
|
self.machine_st = machine_st;
|
||||||
|
|
||||||
if let EvalSession::Error(err) = result {
|
if let EvalSession::Error(err) = result {
|
||||||
@@ -158,20 +191,33 @@ impl Machine {
|
|||||||
place.push_to_queue(&mut addrs, added_clause);
|
place.push_to_queue(&mut addrs, added_clause);
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => {
|
||||||
|
return self.machine_st.throw_exception(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, place.predicate_name());
|
self.handle_eval_result_from_dynamic_compile(
|
||||||
|
pred_str,
|
||||||
|
name,
|
||||||
|
arity,
|
||||||
|
place.predicate_name(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
|
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
|
||||||
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get(&module) {
|
Addr::Con(h) =>
|
||||||
|
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
||||||
|
match self.indices.modules.get(module) {
|
||||||
Some(ref module) => module.atom_tbl.clone(),
|
Some(ref module) => module.atom_tbl.clone(),
|
||||||
None => {
|
None => {
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@@ -200,7 +246,18 @@ impl Machine {
|
|||||||
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
let index = self.machine_st[temp_v!(3)].clone();
|
||||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
Addr::Con(h) =>
|
||||||
|
match &self.machine_st.heap[h] {
|
||||||
|
HeapCellValue::Integer(ref arity) => {
|
||||||
|
arity.to_usize().unwrap()
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
||||||
|
usize::try_from(*arity).unwrap()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -220,7 +277,9 @@ impl Machine {
|
|||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => {
|
||||||
|
return self.machine_st.throw_exception(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
self.handle_eval_result_from_dynamic_compile(
|
||||||
@@ -235,8 +294,22 @@ impl Machine {
|
|||||||
fn retract_from_dynamic_predicate(&mut self) {
|
fn retract_from_dynamic_predicate(&mut self) {
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
let index = self.machine_st[temp_v!(3)].clone();
|
||||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
Addr::Con(h) => {
|
||||||
_ => unreachable!(),
|
match &self.machine_st.heap[h] {
|
||||||
|
HeapCellValue::Integer(ref arity) => {
|
||||||
|
arity.to_usize().unwrap()
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
||||||
|
usize::try_from(*arity).unwrap()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||||
@@ -253,7 +326,9 @@ impl Machine {
|
|||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => {
|
||||||
|
return self.machine_st.throw_exception(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
self.handle_eval_result_from_dynamic_compile(
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::Constant;
|
||||||
|
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::partial_string::*;
|
use crate::prolog::machine::partial_string::*;
|
||||||
use crate::prolog::machine::raw_block::*;
|
use crate::prolog::machine::raw_block::*;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@@ -39,12 +40,12 @@ impl<T: RawBlockTraits> Drop for HeapTemplate<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
struct HeapIntoIterator<T: RawBlockTraits> {
|
struct HeapIntoIter<T: RawBlockTraits> {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buf: RawBlock<T>,
|
buf: RawBlock<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Drop for HeapIntoIterator<T> {
|
impl<T: RawBlockTraits> Drop for HeapIntoIter<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let mut heap =
|
let mut heap =
|
||||||
HeapTemplate { buf: self.buf.take(), _marker: PhantomData };
|
HeapTemplate { buf: self.buf.take(), _marker: PhantomData };
|
||||||
@@ -54,7 +55,7 @@ impl<T: RawBlockTraits> Drop for HeapIntoIterator<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Iterator for HeapIntoIterator<T> {
|
impl<T: RawBlockTraits> Iterator for HeapIntoIter<T> {
|
||||||
type Item = HeapCellValue;
|
type Item = HeapCellValue;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@@ -72,19 +73,19 @@ impl<T: RawBlockTraits> Iterator for HeapIntoIterator<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
struct HeapIterator<'a, T: RawBlockTraits> {
|
struct HeapIter<'a, T: RawBlockTraits> {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buf: &'a RawBlock<T>,
|
buf: &'a RawBlock<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: RawBlockTraits> HeapIterator<'a, T> {
|
impl<'a, T: RawBlockTraits> HeapIter<'a, T> {
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn new(buf: &'a RawBlock<T>, offset: usize) -> Self {
|
fn new(buf: &'a RawBlock<T>, offset: usize) -> Self {
|
||||||
HeapIterator { buf, offset }
|
HeapIter { buf, offset }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> {
|
impl<'a, T: RawBlockTraits> Iterator for HeapIter<'a, T> {
|
||||||
type Item = &'a HeapCellValue;
|
type Item = &'a HeapCellValue;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@@ -101,20 +102,28 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
struct HeapIteratorMut<'a, T: RawBlockTraits> {
|
fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: usize) {
|
||||||
|
for (index, term) in heap.enumerate() {
|
||||||
|
println!("{} : {}", h + index, term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
struct HeapIterMut<'a, T: RawBlockTraits> {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buf: &'a mut RawBlock<T>,
|
buf: &'a mut RawBlock<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: RawBlockTraits> HeapIteratorMut<'a, T> {
|
impl<'a, T: RawBlockTraits> HeapIterMut<'a, T> {
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn new(buf: &'a mut RawBlock<T>, offset: usize) -> Self {
|
fn new(buf: &'a mut RawBlock<T>, offset: usize) -> Self {
|
||||||
HeapIteratorMut { buf, offset }
|
HeapIterMut { buf, offset }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: RawBlockTraits> Iterator for HeapIteratorMut<'a, T> {
|
impl<'a, T: RawBlockTraits> Iterator for HeapIterMut<'a, T> {
|
||||||
type Item = &'a mut HeapCellValue;
|
type Item = &'a mut HeapCellValue;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@@ -140,17 +149,183 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn push(&mut self, val: HeapCellValue) {
|
fn clone(&self, h: usize) -> HeapCellValue {
|
||||||
unsafe {
|
match &self[h] {
|
||||||
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
&HeapCellValue::Addr(addr) => {
|
||||||
ptr::write(self.buf.top as *mut _, val);
|
HeapCellValue::Addr(addr)
|
||||||
self.buf.top = new_top;
|
}
|
||||||
|
&HeapCellValue::Atom(ref name, ref op) => {
|
||||||
|
HeapCellValue::Atom(name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::DBRef(ref db_ref) => {
|
||||||
|
HeapCellValue::DBRef(db_ref.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
HeapCellValue::Integer(n.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::PartialString(..) => {
|
||||||
|
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(_) => {
|
||||||
|
HeapCellValue::Addr(Addr::Stream(h))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn allocate_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
fn put_complete_string(&mut self, s: &str) -> Addr {
|
||||||
|
let addr = self.allocate_pstr(s);
|
||||||
|
self.pop();
|
||||||
|
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
match &mut self[h - 1] {
|
||||||
|
&mut HeapCellValue::PartialString(_, ref mut has_tail) => {
|
||||||
|
*has_tail = false;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn put_constant(&mut self, c: Constant) -> Addr {
|
||||||
|
match c {
|
||||||
|
Constant::Atom(name, op) => {
|
||||||
|
Addr::Con(self.push(HeapCellValue::Atom(name, op)))
|
||||||
|
}
|
||||||
|
Constant::Char(c) => {
|
||||||
|
Addr::Char(c)
|
||||||
|
}
|
||||||
|
Constant::CharCode(c) => {
|
||||||
|
Addr::CharCode(c)
|
||||||
|
}
|
||||||
|
Constant::EmptyList => {
|
||||||
|
Addr::EmptyList
|
||||||
|
}
|
||||||
|
Constant::Fixnum(n) => {
|
||||||
|
Addr::Fixnum(n)
|
||||||
|
}
|
||||||
|
Constant::Integer(n) => {
|
||||||
|
Addr::Con(self.push(HeapCellValue::Integer(n)))
|
||||||
|
}
|
||||||
|
Constant::Rational(r) => {
|
||||||
|
Addr::Con(self.push(HeapCellValue::Rational(r)))
|
||||||
|
}
|
||||||
|
Constant::Float(f) => {
|
||||||
|
Addr::Float(f)
|
||||||
|
}
|
||||||
|
Constant::String(s) => {
|
||||||
|
if s.is_empty() {
|
||||||
|
Addr::EmptyList
|
||||||
|
} else {
|
||||||
|
self.put_complete_string(&s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constant::Usize(n) => {
|
||||||
|
Addr::Usize(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn pop(&mut self) {
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
if h > 0 {
|
||||||
|
self.truncate(h - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn push(&mut self, val: HeapCellValue) -> usize {
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
||||||
|
ptr::write(self.buf.top as *mut _, val);
|
||||||
|
self.buf.top = new_top;
|
||||||
|
}
|
||||||
|
|
||||||
|
h
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn atom_at(&self, h: usize) -> bool {
|
||||||
|
if let HeapCellValue::Atom(..) = &self[h] {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr {
|
||||||
|
match non_heap_value {
|
||||||
|
HeapCellValue::Addr(addr) => {
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::Atom(..)
|
||||||
|
| val @ HeapCellValue::Integer(_)
|
||||||
|
| val @ HeapCellValue::DBRef(_)
|
||||||
|
| val @ HeapCellValue::Rational(_) => {
|
||||||
|
Addr::Con(self.push(val))
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::NamedStr(..) => {
|
||||||
|
Addr::Str(self.push(val))
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::Stream(..) => {
|
||||||
|
Addr::Stream(self.push(val))
|
||||||
|
}
|
||||||
|
HeapCellValue::PartialString(pstr, has_tail) => {
|
||||||
|
let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
|
||||||
|
|
||||||
|
if has_tail {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr::Con(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn allocate_pstr(&mut self, src: &str) -> Addr {
|
||||||
|
self.write_pstr(src)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
self.push(HeapCellValue::PartialString(
|
||||||
|
PartialString::empty(),
|
||||||
|
true,
|
||||||
|
));
|
||||||
|
|
||||||
|
self.push(HeapCellValue::Addr(
|
||||||
|
Addr::HeapCell(h + 1)
|
||||||
|
));
|
||||||
|
|
||||||
|
Addr::PStrLocation(h, 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
||||||
let orig_h = self.h();
|
let orig_h = self.h();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -158,17 +333,8 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
return if orig_h == self.h() {
|
return if orig_h == self.h() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let prev_h = self.h() - 1;
|
let tail_h = self.h() - 1;
|
||||||
|
self[tail_h] = HeapCellValue::Addr(Addr::HeapCell(tail_h));
|
||||||
match &mut self[prev_h] {
|
|
||||||
HeapCellValue::PartialString(ref mut pstr) => {
|
|
||||||
let s = pstr.block_as_str();
|
|
||||||
pstr.tail = Addr::PStrTail(prev_h, s.len());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Addr::PStrLocation(orig_h, 0))
|
Some(Addr::PStrLocation(orig_h, 0))
|
||||||
};
|
};
|
||||||
@@ -176,8 +342,8 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
|
|
||||||
let h = self.h();
|
let h = self.h();
|
||||||
|
|
||||||
let (mut pstr, rest_src) =
|
let (pstr, rest_src) =
|
||||||
match PartialString::new(src, h) {
|
match PartialString::new(src) {
|
||||||
Some(tuple) => {
|
Some(tuple) => {
|
||||||
tuple
|
tuple
|
||||||
}
|
}
|
||||||
@@ -188,44 +354,19 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
} else if orig_h == h {
|
} else if orig_h == h {
|
||||||
return None;
|
return None;
|
||||||
} else {
|
} else {
|
||||||
let prev_h = h - 1;
|
self[h - 1] = HeapCellValue::Addr(Addr::HeapCell(h - 1));
|
||||||
|
|
||||||
match &mut self[prev_h] {
|
|
||||||
HeapCellValue::PartialString(ref mut pstr) => {
|
|
||||||
let s = pstr.block_as_str();
|
|
||||||
pstr.tail = Addr::PStrTail(prev_h, s.len());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(Addr::PStrLocation(orig_h, 0));
|
return Some(Addr::PStrLocation(orig_h, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_top = unsafe {
|
self.push(HeapCellValue::PartialString(pstr, true));
|
||||||
self.buf.new_block(mem::size_of::<HeapCellValue>())
|
|
||||||
};
|
|
||||||
|
|
||||||
if rest_src != "" {
|
if rest_src != "" {
|
||||||
pstr.tail = Addr::PStrLocation(h+1, 0);
|
self.push(HeapCellValue::Addr(Addr::PStrLocation(h + 2, 0)));
|
||||||
src = rest_src;
|
src = rest_src;
|
||||||
} else {
|
} else {
|
||||||
pstr.tail = Addr::PStrTail(h, src.len());
|
self.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
|
||||||
}
|
|
||||||
|
|
||||||
unsafe{
|
|
||||||
ptr::write(
|
|
||||||
self.buf.top as *mut _,
|
|
||||||
HeapCellValue::PartialString(pstr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.buf.top = new_top;
|
|
||||||
|
|
||||||
if rest_src == "" {
|
|
||||||
return Some(Addr::PStrLocation(orig_h, 0));
|
return Some(Addr::PStrLocation(orig_h, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,35 +420,39 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn to_list<Iter: Iterator<Item = Addr>>(&mut self, values: Iter) -> usize {
|
fn to_list<Iter, SrcT>(&mut self, values: Iter) -> usize
|
||||||
|
where Iter: Iterator<Item = SrcT>,
|
||||||
|
SrcT: Into<HeapCellValue>
|
||||||
|
{
|
||||||
let head_addr = self.h();
|
let head_addr = self.h();
|
||||||
|
let mut h = head_addr;
|
||||||
|
|
||||||
for value in values {
|
for value in values.map(|v| v.into()) {
|
||||||
let h = self.h();
|
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
self.push(HeapCellValue::Addr(value));
|
self.push(value);
|
||||||
|
|
||||||
|
h += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
|
||||||
head_addr
|
head_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create an iterator starting from the passed offset. */
|
/* Create an iterator starting from the passed offset. */
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn iter_from<'a>(&'a self, offset: usize) -> HeapIterator<'a, T> {
|
fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> {
|
||||||
HeapIterator::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
|
HeapIter::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIteratorMut<'a, T> {
|
fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> {
|
||||||
HeapIteratorMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
|
HeapIterMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn into_iter(mut self) -> HeapIntoIterator<T> {
|
fn into_iter(mut self) -> HeapIntoIter<T> {
|
||||||
HeapIntoIterator { buf: self.buf.take(), offset: 0 }
|
HeapIntoIter { buf: self.buf.take(), offset: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
@@ -320,8 +465,9 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
pub(crate)
|
pub(crate)
|
||||||
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
||||||
let extract_integer = |s: usize| -> Option<usize> {
|
let extract_integer = |s: usize| -> Option<usize> {
|
||||||
match self[s].as_addr(s) {
|
match &self[s] {
|
||||||
Addr::Con(Constant::Integer(n)) => n.to_usize(),
|
&HeapCellValue::Addr(Addr::Fixnum(n)) => usize::try_from(n).ok(),
|
||||||
|
&HeapCellValue::Integer(ref n) => n.to_usize(),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -361,6 +507,19 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub
|
||||||
|
fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
||||||
|
match addr {
|
||||||
|
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) => {
|
||||||
|
RefOrOwned::Borrowed(&self[h])
|
||||||
|
}
|
||||||
|
addr => {
|
||||||
|
RefOrOwned::Owned(HeapCellValue::Addr(*addr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::forms::PredicateKey;
|
use crate::prolog::forms::{ModuleSource, Number, PredicateKey};
|
||||||
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
@@ -21,34 +22,103 @@ pub(super) struct MachineError {
|
|||||||
from: ErrorProvenance,
|
from: ErrorProvenance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineError {
|
pub(super)
|
||||||
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
trait TypeError {
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
fn type_error(self, h: usize, valid_type: ValidType) -> MachineError;
|
||||||
functor!(
|
|
||||||
"/",
|
|
||||||
2,
|
|
||||||
[name, heap_integer!(Integer::from(arity))],
|
|
||||||
SharedOpDesc::new(400, YFX)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
impl TypeError for Addr {
|
||||||
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
|
fn type_error(self, _: usize, valid_type: ValidType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"type_error",
|
||||||
|
[atom(valid_type.as_str()), addr(self)]
|
||||||
|
);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
from: ErrorProvenance::Received,
|
from: ErrorProvenance::Received
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
|
impl TypeError for MachineStub {
|
||||||
|
fn type_error(self, h: usize, valid_type: ValidType) -> MachineError {
|
||||||
let stub = functor!(
|
let stub = functor!(
|
||||||
"type_error",
|
"type_error",
|
||||||
2,
|
[atom(valid_type.as_str()), aux(h, 0)],
|
||||||
[
|
[self]
|
||||||
heap_atom!(valid_type.as_str()),
|
);
|
||||||
HeapCellValue::Addr(culprit)
|
|
||||||
]
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeError for Number {
|
||||||
|
fn type_error(self, _h: usize, valid_type: ValidType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"type_error",
|
||||||
|
[atom(valid_type.as_str()), number(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
trait PermissionError {
|
||||||
|
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PermissionError for Addr {
|
||||||
|
fn permission_error(self, _: usize, index_str: &'static str, perm: Permission) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"permission_error",
|
||||||
|
[atom(perm.as_str()), atom(index_str), addr(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PermissionError for MachineStub {
|
||||||
|
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"permission_error",
|
||||||
|
[atom(perm.as_str()), atom(index_str), aux(h, 0)],
|
||||||
|
[self]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
trait DomainError {
|
||||||
|
fn domain_error(self, error: DomainErrorType) -> MachineError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainError for Addr {
|
||||||
|
fn domain_error(self, error: DomainErrorType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"domain_error",
|
||||||
|
[atom(error.as_str()), addr(self)]
|
||||||
);
|
);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
@@ -57,55 +127,74 @@ impl MachineError {
|
|||||||
from: ErrorProvenance::Received,
|
from: ErrorProvenance::Received,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn module_resolution_error(
|
impl DomainError for Number {
|
||||||
|
fn domain_error(self, error: DomainErrorType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"domain_error",
|
||||||
|
[atom(error.as_str()), number(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MachineError {
|
||||||
|
pub(super)
|
||||||
|
fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
||||||
|
functor!(
|
||||||
|
"/",
|
||||||
|
SharedOpDesc::new(400, YFX),
|
||||||
|
[clause_name(name), integer(arity)]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn evaluation_error(eval_error: EvalError) -> Self {
|
||||||
|
let stub = functor!("evaluation_error", [atom(eval_error.as_str())]);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn type_error<T: TypeError>(h: usize, valid_type: ValidType, culprit: T) -> Self {
|
||||||
|
culprit.type_error(h, valid_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn module_resolution_error(
|
||||||
h: usize,
|
h: usize,
|
||||||
mod_name: ClauseName,
|
mod_name: ClauseName,
|
||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name, None)));
|
let res_stub = functor!(
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
|
||||||
|
|
||||||
let mut stub = functor!(
|
|
||||||
"evaluation_error",
|
|
||||||
1,
|
|
||||||
[HeapCellValue::Addr(Addr::HeapCell(h + 2))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut functor!(
|
|
||||||
"/",
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
|
|
||||||
heap_integer!(Integer::from(arity))
|
|
||||||
],
|
|
||||||
SharedOpDesc::new(400, YFX)
|
|
||||||
));
|
|
||||||
|
|
||||||
stub.append(&mut functor!(
|
|
||||||
":",
|
":",
|
||||||
2,
|
SharedOpDesc::new(600, XFY),
|
||||||
[mod_name, name],
|
[clause_name(mod_name), clause_name(name)]
|
||||||
SharedOpDesc::new(600, XFY)
|
);
|
||||||
));
|
|
||||||
|
let ind_stub = functor!(
|
||||||
MachineError {
|
"/",
|
||||||
stub,
|
SharedOpDesc::new(400, YFX),
|
||||||
location: None,
|
[aux(h + 2, 0), integer(arity)],
|
||||||
from: ErrorProvenance::Constructed,
|
[res_stub]
|
||||||
}
|
);
|
||||||
}
|
|
||||||
|
let stub = functor!(
|
||||||
pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self {
|
"evaluation_error",
|
||||||
match err {
|
[aux(h, 0)],
|
||||||
ExistenceError::Procedure(name, arity) => {
|
[ind_stub]
|
||||||
let mut stub = functor!(
|
|
||||||
"existence_error",
|
|
||||||
2,
|
|
||||||
[heap_atom!("procedure"), heap_str!(3 + h)]
|
|
||||||
);
|
);
|
||||||
stub.append(&mut Self::functor_stub(name, arity));
|
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -113,57 +202,34 @@ impl MachineError {
|
|||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Constructed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExistenceError::Module(name) => {
|
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
|
||||||
let stub = functor!("existence_error", 2, [heap_atom!("module"), name]);
|
|
||||||
|
|
||||||
MachineError {
|
pub(super)
|
||||||
stub,
|
fn existence_error(h: usize, err: ExistenceError) -> Self {
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Constructed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn session_error(h: usize, err: SessionError) -> Self {
|
|
||||||
match err {
|
match err {
|
||||||
SessionError::ParserError(err) => Self::syntax_error(h, err),
|
ExistenceError::Module(name) => {
|
||||||
SessionError::CannotOverwriteBuiltIn(pred_str)
|
let stub = functor!(
|
||||||
| SessionError::CannotOverwriteImport(pred_str) => {
|
"existence_error",
|
||||||
Self::permission_error(PermissionError::Modify, "private_procedure", pred_str)
|
[atom("source_sink"), clause_name(name)]
|
||||||
}
|
);
|
||||||
SessionError::InvalidFileName(filename) => {
|
|
||||||
Self::existence_error(h, ExistenceError::Module(filename))
|
|
||||||
}
|
|
||||||
SessionError::ModuleDoesNotContainExport(..) => Self::permission_error(
|
|
||||||
PermissionError::Access,
|
|
||||||
"private_procedure",
|
|
||||||
clause_name!("module_does_not_contain_claimed_export"),
|
|
||||||
),
|
|
||||||
SessionError::ModuleNotFound => Self::permission_error(
|
|
||||||
PermissionError::Access,
|
|
||||||
"private_procedure",
|
|
||||||
clause_name!("module_does_not_exist"),
|
|
||||||
),
|
|
||||||
SessionError::OpIsInfixAndPostFix(op) => {
|
|
||||||
Self::permission_error(PermissionError::Create, "operator", op)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn permission_error(
|
MachineError {
|
||||||
err: PermissionError,
|
stub,
|
||||||
index_str: &'static str,
|
location: None,
|
||||||
pred_str: ClauseName,
|
from: ErrorProvenance::Received,
|
||||||
) -> Self {
|
}
|
||||||
let pred_str = HeapCellValue::Addr(Addr::Con(Constant::Atom(pred_str, None)));
|
}
|
||||||
|
ExistenceError::Procedure(name, arity) => {
|
||||||
|
let culprit = functor!(
|
||||||
|
"/",
|
||||||
|
SharedOpDesc::new(400, YFX),
|
||||||
|
[clause_name(name), integer(arity)]
|
||||||
|
);
|
||||||
|
|
||||||
let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), pred_str];
|
let stub = functor!(
|
||||||
let mut stub = functor!("permission_error", 3);
|
"existence_error",
|
||||||
|
[atom("procedure"), aux(h, 0)],
|
||||||
stub.extend(err.into_iter());
|
[culprit]
|
||||||
|
);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -171,46 +237,168 @@ impl MachineError {
|
|||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Constructed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExistenceError::SourceSink(source) => {
|
||||||
|
let source_stub = source.as_functor_stub();
|
||||||
|
|
||||||
|
let stub = functor!(
|
||||||
|
"existence_error",
|
||||||
|
[atom("source_sink"), aux(h, 0)],
|
||||||
|
[source_stub]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExistenceError::Stream(culprit) => {
|
||||||
|
let stub = functor!(
|
||||||
|
"existence_error",
|
||||||
|
[atom("stream"), addr(culprit)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn permission_error<T: PermissionError>(
|
||||||
|
h: usize,
|
||||||
|
err: Permission,
|
||||||
|
index_str: &'static str,
|
||||||
|
culprit: T,
|
||||||
|
) -> Self {
|
||||||
|
culprit.permission_error(
|
||||||
|
h,
|
||||||
|
index_str,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
ArithmeticError::UninstantiatedVar => Self::instantiation_error(),
|
ArithmeticError::UninstantiatedVar => {
|
||||||
|
Self::instantiation_error()
|
||||||
|
}
|
||||||
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
||||||
let name = HeapCellValue::Addr(Addr::Con(name));
|
|
||||||
let culprit = functor!(
|
let culprit = functor!(
|
||||||
"/",
|
"/",
|
||||||
2,
|
SharedOpDesc::new(400, YFX),
|
||||||
[name, heap_integer!(Integer::from(arity))],
|
[constant(h, &name), integer(arity)]
|
||||||
SharedOpDesc::new(400, YFX)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub;
|
Self::type_error(h, ValidType::Evaluable, culprit)
|
||||||
stub.extend(culprit.into_iter());
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn domain_error<T: DomainError>(error: DomainErrorType, culprit: T) -> Self {
|
||||||
|
culprit.domain_error(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn instantiation_error() -> Self {
|
||||||
|
let stub = functor!("instantiation_error");
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Received,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn uninstantiation_error(culprit: Addr) -> Self {
|
||||||
|
let stub = functor!(
|
||||||
|
"uninstantiation_error",
|
||||||
|
[addr(culprit)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn session_error(h: usize, err: SessionError) -> Self {
|
||||||
|
match err {
|
||||||
|
SessionError::CannotOverwriteBuiltIn(pred_str) |
|
||||||
|
SessionError::CannotOverwriteImport(pred_str) => {
|
||||||
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Modify,
|
||||||
|
"private_procedure",
|
||||||
|
functor!(clause_name(pred_str)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SessionError::ExistenceError(err) => {
|
||||||
|
Self::existence_error(h, err)
|
||||||
|
}
|
||||||
|
SessionError::InvalidFileName(filename) => {
|
||||||
|
Self::existence_error(h, ExistenceError::Module(filename))
|
||||||
|
}
|
||||||
|
SessionError::ModuleDoesNotContainExport(..) => {
|
||||||
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Access,
|
||||||
|
"private_procedure",
|
||||||
|
functor!("module_does_not_contain_claimed_export"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SessionError::NamelessEntry => {
|
||||||
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Create,
|
||||||
|
"static_procedure",
|
||||||
|
functor!("nameless_procedure")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SessionError::OpIsInfixAndPostFix(op) => {
|
||||||
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Create,
|
||||||
|
"operator",
|
||||||
|
functor!(clause_name(op)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SessionError::ParserError(err) => {
|
||||||
|
Self::syntax_error(h, err)
|
||||||
|
}
|
||||||
|
SessionError::QueryCannotBeDefinedAsFact => {
|
||||||
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Create,
|
||||||
|
"static_procedure",
|
||||||
|
functor!("query_cannot_be_defined_as_fact")
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn syntax_error(h: usize, err: ParserError) -> Self {
|
pub(super)
|
||||||
|
fn syntax_error(h: usize, err: ParserError) -> Self {
|
||||||
if let ParserError::Arithmetic(err) = err {
|
if let ParserError::Arithmetic(err) = err {
|
||||||
return Self::arithmetic_error(h, err);
|
return Self::arithmetic_error(h, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let location = err.line_and_col_num();
|
let location = err.line_and_col_num();
|
||||||
let err = vec![heap_atom!(err.as_str())];
|
let stub = functor!(err.as_str());
|
||||||
|
|
||||||
let mut stub = if err.len() == 1 {
|
let stub = functor!(
|
||||||
functor!("syntax_error", 1)
|
"syntax_error",
|
||||||
} else {
|
[aux(h, 0)],
|
||||||
functor!("syntax_error", 1, [heap_str!(h + 2)])
|
[stub]
|
||||||
};
|
);
|
||||||
|
|
||||||
stub.extend(err.into_iter());
|
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -219,30 +407,10 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self {
|
pub(super)
|
||||||
let stub = functor!(
|
fn representation_error(flag: RepFlag) -> Self {
|
||||||
"domain_error",
|
let stub = functor!("representation_error", [atom(flag.as_str())]);
|
||||||
2,
|
|
||||||
[heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]
|
|
||||||
);
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Received,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn instantiation_error() -> Self {
|
|
||||||
let stub = functor!("instantiation_error");
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Received,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn representation_error(flag: RepFlag) -> Self {
|
|
||||||
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
@@ -268,18 +436,22 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum PermissionError {
|
pub enum Permission {
|
||||||
Access,
|
Access,
|
||||||
Create,
|
Create,
|
||||||
|
InputStream,
|
||||||
Modify,
|
Modify,
|
||||||
|
OutputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PermissionError {
|
impl Permission {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
PermissionError::Access => "access",
|
Permission::Access => "access",
|
||||||
PermissionError::Create => "create",
|
Permission::Create => "create",
|
||||||
PermissionError::Modify => "modify",
|
Permission::InputStream => "input",
|
||||||
|
Permission::Modify => "modify",
|
||||||
|
Permission::OutputStream => "output",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,14 +503,18 @@ impl ValidType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum DomainError {
|
pub enum DomainErrorType {
|
||||||
NotLessThanZero,
|
NotLessThanZero,
|
||||||
|
Stream,
|
||||||
|
StreamOrAlias,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DomainError {
|
impl DomainErrorType {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
DomainError::NotLessThanZero => "not_less_than_zero",
|
DomainErrorType::NotLessThanZero => "not_less_than_zero",
|
||||||
|
DomainErrorType::Stream => "stream",
|
||||||
|
DomainErrorType::StreamOrAlias => "stream_or_alias",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,21 +564,20 @@ impl EvalError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// used by '$skip_max_list'.
|
// used by '$skip_max_list'.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub(super) enum CycleSearchResult {
|
pub(super) enum CycleSearchResult {
|
||||||
EmptyList,
|
EmptyList,
|
||||||
NotList,
|
NotList,
|
||||||
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
||||||
ProperList(usize), // the list length.
|
ProperList(usize), // the list length.
|
||||||
CompleteString(usize, Rc<String>), // the string length (in bytes), the string.
|
|
||||||
UntouchedString(usize, Rc<String>), // the cut off, past which is the untouched string.
|
|
||||||
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
|
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
|
||||||
PStrTail(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
|
|
||||||
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
// see 8.4.3 of Draft Technical Corrigendum 2.
|
// see 8.4.3 of Draft Technical Corrigendum 2.
|
||||||
pub(super) fn check_sort_errors(&self) -> CallResult {
|
pub(super)
|
||||||
|
fn check_sort_errors(&self) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||||
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
@@ -412,14 +587,14 @@ impl MachineState {
|
|||||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||||
}
|
}
|
||||||
CycleSearchResult::NotList => {
|
CycleSearchResult::NotList => {
|
||||||
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
return Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.detect_cycles(sorted.clone()) {
|
match self.detect_cycles(sorted.clone()) {
|
||||||
CycleSearchResult::NotList if !sorted.is_ref() => {
|
CycleSearchResult::NotList if !sorted.is_ref() => {
|
||||||
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub))
|
Err(self.error_form(MachineError::type_error(0, ValidType::List, sorted), stub))
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
@@ -430,7 +605,7 @@ impl MachineState {
|
|||||||
|
|
||||||
match self.detect_cycles(list.clone()) {
|
match self.detect_cycles(list.clone()) {
|
||||||
CycleSearchResult::NotList if !list.is_ref() => {
|
CycleSearchResult::NotList if !list.is_ref() => {
|
||||||
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut addr = list;
|
let mut addr = list;
|
||||||
@@ -439,18 +614,23 @@ impl MachineState {
|
|||||||
let mut new_l = l;
|
let mut new_l = l;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.heap[new_l].clone() {
|
match self.heap.clone(new_l) {
|
||||||
HeapCellValue::Addr(Addr::Str(l)) => new_l = l,
|
HeapCellValue::Addr(Addr::Str(l)) => {
|
||||||
HeapCellValue::NamedStr(2, ref name, Some(_))
|
new_l = l;
|
||||||
if name.as_str() == "-" =>
|
}
|
||||||
{
|
HeapCellValue::NamedStr(2, ref name, Some(_))
|
||||||
break
|
if name.as_str() == "-" => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell(_)) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::StackCell(..)) => {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::HeapCell(_)) => break,
|
|
||||||
HeapCellValue::Addr(Addr::StackCell(..)) => break,
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(self.error_form(
|
return Err(self.error_form(
|
||||||
MachineError::type_error(ValidType::Pair, Addr::HeapCell(l)),
|
MachineError::type_error(0, ValidType::Pair, Addr::HeapCell(l)),
|
||||||
stub,
|
stub,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -466,8 +646,10 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// see 8.4.4 of Draft Technical Corrigendum 2.
|
// see 8.4.4 of Draft Technical Corrigendum 2.
|
||||||
pub(super) fn check_keysort_errors(&self) -> CallResult {
|
pub(super)
|
||||||
|
fn check_keysort_errors(&self) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
||||||
|
|
||||||
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
|
|
||||||
@@ -476,7 +658,7 @@ impl MachineState {
|
|||||||
Err(self.error_form(MachineError::instantiation_error(), stub))
|
Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||||
}
|
}
|
||||||
CycleSearchResult::NotList => {
|
CycleSearchResult::NotList => {
|
||||||
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub))
|
Err(self.error_form(MachineError::type_error(0, ValidType::List, pairs), stub))
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}?;
|
}?;
|
||||||
@@ -484,7 +666,8 @@ impl MachineState {
|
|||||||
self.check_for_list_pairs(sorted)
|
self.check_for_list_pairs(sorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
|
pub(super)
|
||||||
|
fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
|
||||||
let location = err.location;
|
let location = err.location;
|
||||||
let err_len = err.len();
|
let err_len = err.len();
|
||||||
|
|
||||||
@@ -500,21 +683,17 @@ impl MachineState {
|
|||||||
if let Some((line_num, _)) = location {
|
if let Some((line_num, _)) = location {
|
||||||
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
|
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
|
||||||
|
|
||||||
stub.extend(
|
stub.push(HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc));
|
||||||
vec![
|
stub.push(HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)));
|
||||||
HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
|
stub.push(HeapCellValue::Integer(Rc::new(Integer::from(line_num))));
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
|
|
||||||
heap_integer!(Integer::from(line_num)),
|
|
||||||
]
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stub.extend(src.into_iter());
|
stub.extend(src.into_iter());
|
||||||
stub
|
stub
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
pub(super)
|
||||||
|
fn throw_exception(&mut self, err: MachineStub) {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
self.ball.boundary = 0;
|
self.ball.boundary = 0;
|
||||||
@@ -532,16 +711,19 @@ impl MachineState {
|
|||||||
pub enum ExistenceError {
|
pub enum ExistenceError {
|
||||||
Module(ClauseName),
|
Module(ClauseName),
|
||||||
Procedure(ClauseName, usize),
|
Procedure(ClauseName, usize),
|
||||||
|
SourceSink(ModuleSource),
|
||||||
|
Stream(Addr),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SessionError {
|
pub enum SessionError {
|
||||||
CannotOverwriteBuiltIn(ClauseName),
|
CannotOverwriteBuiltIn(ClauseName),
|
||||||
CannotOverwriteImport(ClauseName),
|
CannotOverwriteImport(ClauseName),
|
||||||
|
ExistenceError(ExistenceError),
|
||||||
InvalidFileName(ClauseName),
|
InvalidFileName(ClauseName),
|
||||||
ModuleDoesNotContainExport(ClauseName, PredicateKey),
|
ModuleDoesNotContainExport(ClauseName, PredicateKey),
|
||||||
ModuleNotFound,
|
|
||||||
NamelessEntry,
|
NamelessEntry,
|
||||||
OpIsInfixAndPostFix(ClauseName),
|
OpIsInfixAndPostFix(ClauseName),
|
||||||
|
QueryCannotBeDefinedAsFact,
|
||||||
ParserError(ParserError),
|
ParserError(ParserError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,4 +748,5 @@ impl From<ParserError> for EvalSession {
|
|||||||
fn from(err: ParserError) -> Self {
|
fn from(err: ParserError) -> Self {
|
||||||
EvalSession::from(SessionError::ParserError(err))
|
EvalSession::from(SessionError::ParserError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,20 @@ use crate::prolog::forms::*;
|
|||||||
use crate::prolog::machine::code_repo::CodeRepo;
|
use crate::prolog::machine::code_repo::CodeRepo;
|
||||||
use crate::prolog::machine::Ball;
|
use crate::prolog::machine::Ball;
|
||||||
use crate::prolog::machine::heap::*;
|
use crate::prolog::machine::heap::*;
|
||||||
|
use crate::prolog::machine::machine_state::*;
|
||||||
use crate::prolog::machine::partial_string::*;
|
use crate::prolog::machine::partial_string::*;
|
||||||
use crate::prolog::machine::raw_block::RawBlockTraits;
|
use crate::prolog::machine::raw_block::RawBlockTraits;
|
||||||
|
use crate::prolog::machine::streams::Stream;
|
||||||
use crate::prolog::instructions::*;
|
use crate::prolog::instructions::*;
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::ordered_float::OrderedFloat;
|
||||||
|
use crate::prolog::rug::{Integer, Rational};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::{BTreeMap, VecDeque};
|
use std::collections::{BTreeMap, VecDeque};
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -38,25 +42,40 @@ pub enum DBRef {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
// 7.2
|
||||||
pub enum Addr {
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
AttrVar(usize),
|
pub enum TermOrderCategory {
|
||||||
Con(Constant),
|
Variable,
|
||||||
DBRef(DBRef),
|
FloatingPoint,
|
||||||
Lis(usize),
|
Integer,
|
||||||
HeapCell(usize),
|
Atom,
|
||||||
StackCell(usize, usize),
|
Compound,
|
||||||
Str(usize),
|
|
||||||
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
|
||||||
PStrTail(usize, usize), // location of pstr in heap, offset into string in bytes.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Addr {
|
||||||
|
AttrVar(usize),
|
||||||
|
Char(char),
|
||||||
|
CharCode(u32),
|
||||||
|
Con(usize),
|
||||||
|
CutPoint(usize),
|
||||||
|
EmptyList,
|
||||||
|
Fixnum(isize),
|
||||||
|
Float(OrderedFloat<f64>),
|
||||||
|
Lis(usize),
|
||||||
|
HeapCell(usize),
|
||||||
|
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
||||||
|
StackCell(usize, usize),
|
||||||
|
Str(usize),
|
||||||
|
Stream(usize),
|
||||||
|
Usize(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Hash, Eq, PartialEq, PartialOrd)]
|
||||||
pub enum Ref {
|
pub enum Ref {
|
||||||
AttrVar(usize),
|
AttrVar(usize),
|
||||||
HeapCell(usize),
|
HeapCell(usize),
|
||||||
StackCell(usize, usize),
|
StackCell(usize, usize),
|
||||||
PStrTail(usize, usize),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ref {
|
impl Ref {
|
||||||
@@ -65,7 +84,28 @@ impl Ref {
|
|||||||
Ref::AttrVar(h) => Addr::AttrVar(h),
|
Ref::AttrVar(h) => Addr::AttrVar(h),
|
||||||
Ref::HeapCell(h) => Addr::HeapCell(h),
|
Ref::HeapCell(h) => Addr::HeapCell(h),
|
||||||
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
|
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
|
||||||
Ref::PStrTail(h, n) => Addr::PStrTail(h, n),
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Ref {
|
||||||
|
fn cmp(&self, other: &Ref) -> Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Ref::AttrVar(h1), Ref::AttrVar(h2))
|
||||||
|
| (Ref::HeapCell(h1), Ref::HeapCell(h2))
|
||||||
|
| (Ref::HeapCell(h1), Ref::AttrVar(h2))
|
||||||
|
| (Ref::AttrVar(h1), Ref::HeapCell(h2)) => {
|
||||||
|
h1.cmp(&h2)
|
||||||
|
}
|
||||||
|
(Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) => {
|
||||||
|
fr1.cmp(&fr2).then_with(|| sc1.cmp(&sc2))
|
||||||
|
}
|
||||||
|
(Ref::StackCell(..), _) => {
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
(_, Ref::StackCell(..)) => {
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +122,7 @@ impl PartialOrd<Ref> for Addr {
|
|||||||
match self {
|
match self {
|
||||||
&Addr::StackCell(fr, sc) => {
|
&Addr::StackCell(fr, sc) => {
|
||||||
match *r {
|
match *r {
|
||||||
Ref::AttrVar(_) | Ref::HeapCell(_) | Ref::PStrTail(..) => {
|
Ref::AttrVar(_) | Ref::HeapCell(_) => {
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
}
|
}
|
||||||
Ref::StackCell(fr1, sc1) => {
|
Ref::StackCell(fr1, sc1) => {
|
||||||
@@ -104,22 +144,6 @@ impl PartialOrd<Ref> for Addr {
|
|||||||
Ref::AttrVar(h1) | Ref::HeapCell(h1) => {
|
Ref::AttrVar(h1) | Ref::HeapCell(h1) => {
|
||||||
h.partial_cmp(h1)
|
h.partial_cmp(h1)
|
||||||
}
|
}
|
||||||
Ref::PStrTail(h1, _) => {
|
|
||||||
h.partial_cmp(h1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&Addr::PStrTail(h, n) => {
|
|
||||||
match r {
|
|
||||||
Ref::StackCell(..) => {
|
|
||||||
Some(Ordering::Less)
|
|
||||||
}
|
|
||||||
Ref::AttrVar(h1) | Ref::HeapCell(h1) => {
|
|
||||||
h.partial_cmp(h1)
|
|
||||||
}
|
|
||||||
Ref::PStrTail(h1, n1) => {
|
|
||||||
Some(h.cmp(h1).then_with(|| n.cmp(n1)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -130,9 +154,24 @@ impl PartialOrd<Ref> for Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Addr {
|
impl Addr {
|
||||||
|
#[inline]
|
||||||
|
pub fn is_heap_bound(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList |
|
||||||
|
Addr::CutPoint(_) | Addr::Usize(_) | Addr::Fixnum(_) |
|
||||||
|
Addr::Float(_) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn is_ref(&self) -> bool {
|
pub fn is_ref(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) | Addr::PStrTail(..) => {
|
Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -141,16 +180,115 @@ impl Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn as_var(&self) -> Option<Ref> {
|
pub fn as_var(&self) -> Option<Ref> {
|
||||||
match self {
|
match self {
|
||||||
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
|
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
|
||||||
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
|
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
|
||||||
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
|
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
|
||||||
&Addr::PStrTail(h, n) => Some(Ref::PStrTail(h, n)),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
|
||||||
|
match Number::try_from((*self, heap)) {
|
||||||
|
Ok(Number::Integer(_)) | Ok(Number::Fixnum(_)) | Ok(Number::Rational(_)) => {
|
||||||
|
Some(TermOrderCategory::Integer)
|
||||||
|
}
|
||||||
|
Ok(Number::Float(_)) => {
|
||||||
|
Some(TermOrderCategory::FloatingPoint)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
match self {
|
||||||
|
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
|
||||||
|
Some(TermOrderCategory::Variable)
|
||||||
|
}
|
||||||
|
Addr::Float(_) => {
|
||||||
|
Some(TermOrderCategory::FloatingPoint)
|
||||||
|
}
|
||||||
|
&Addr::Con(h) => {
|
||||||
|
match &heap[h] {
|
||||||
|
HeapCellValue::Atom(..) => {
|
||||||
|
Some(TermOrderCategory::Atom)
|
||||||
|
}
|
||||||
|
HeapCellValue::DBRef(_) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Char(_) | Addr::EmptyList => {
|
||||||
|
Some(TermOrderCategory::Atom)
|
||||||
|
}
|
||||||
|
Addr::CharCode(_) | Addr::Fixnum(_) | Addr::Usize(_) => {
|
||||||
|
Some(TermOrderCategory::Integer)
|
||||||
|
}
|
||||||
|
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||||
|
Some(TermOrderCategory::Compound)
|
||||||
|
}
|
||||||
|
Addr::CutPoint(_) | Addr::Stream(_) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_constant(&self, machine_st: &MachineState) -> Option<Constant> {
|
||||||
|
match self {
|
||||||
|
&Addr::Char(c) => {
|
||||||
|
Some(Constant::Char(c))
|
||||||
|
}
|
||||||
|
&Addr::CharCode(c) => {
|
||||||
|
Some(Constant::CharCode(c))
|
||||||
|
}
|
||||||
|
&Addr::Con(h) => {
|
||||||
|
match &machine_st.heap[h] {
|
||||||
|
&HeapCellValue::Atom(ref name, ref op) => {
|
||||||
|
Some(Constant::Atom(name.clone(), op.clone()))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
Some(Constant::Integer(n.clone()))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref n) => {
|
||||||
|
Some(Constant::Rational(n.clone()))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Addr::EmptyList => {
|
||||||
|
Some(Constant::EmptyList)
|
||||||
|
}
|
||||||
|
&Addr::Fixnum(n) => {
|
||||||
|
Some(Constant::Fixnum(n))
|
||||||
|
}
|
||||||
|
&Addr::Float(f) => {
|
||||||
|
Some(Constant::Float(f))
|
||||||
|
}
|
||||||
|
&Addr::PStrLocation(h, n) => {
|
||||||
|
let mut heap_pstr_iter =
|
||||||
|
machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||||
|
|
||||||
|
let buf = heap_pstr_iter.to_string();
|
||||||
|
let end_addr = heap_pstr_iter.focus();
|
||||||
|
|
||||||
|
if end_addr == Addr::EmptyList {
|
||||||
|
Some(Constant::String(Rc::new(buf)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_protected(&self, e: usize) -> bool {
|
pub fn is_protected(&self, e: usize) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Addr::StackCell(addr, _) if addr >= e => false,
|
&Addr::StackCell(addr, _) if addr >= e => false,
|
||||||
@@ -164,12 +302,13 @@ impl Add<usize> for Addr {
|
|||||||
|
|
||||||
fn add(self, rhs: usize) -> Self::Output {
|
fn add(self, rhs: usize) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
|
Addr::Stream(h) => Addr::Stream(h + rhs),
|
||||||
|
Addr::Con(h) => Addr::Con(h + rhs),
|
||||||
Addr::Lis(a) => Addr::Lis(a + rhs),
|
Addr::Lis(a) => Addr::Lis(a + rhs),
|
||||||
Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
|
Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
|
||||||
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
|
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
|
||||||
Addr::Str(s) => Addr::Str(s + rhs),
|
Addr::Str(s) => Addr::Str(s + rhs),
|
||||||
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs, n),
|
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs, n),
|
||||||
Addr::PStrTail(h, n) => Addr::PStrTail(h + rhs, n),
|
|
||||||
_ => self,
|
_ => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,11 +320,12 @@ impl Sub<i64> for Addr {
|
|||||||
fn sub(self, rhs: i64) -> Self::Output {
|
fn sub(self, rhs: i64) -> Self::Output {
|
||||||
if rhs < 0 {
|
if rhs < 0 {
|
||||||
match self {
|
match self {
|
||||||
|
Addr::Stream(h) => Addr::Stream(h + rhs.abs() as usize),
|
||||||
|
Addr::Con(h) => Addr::Con(h + rhs.abs() as usize),
|
||||||
Addr::Lis(a) => Addr::Lis(a + rhs.abs() as usize),
|
Addr::Lis(a) => Addr::Lis(a + rhs.abs() as usize),
|
||||||
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
|
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
|
||||||
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
|
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
|
||||||
Addr::Str(s) => Addr::Str(s + rhs.abs() as usize),
|
Addr::Str(s) => Addr::Str(s + rhs.abs() as usize),
|
||||||
Addr::PStrTail(h, n) => Addr::PStrTail(h + rhs.abs() as usize, n),
|
|
||||||
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs.abs() as usize, n),
|
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs.abs() as usize, n),
|
||||||
_ => self,
|
_ => self,
|
||||||
}
|
}
|
||||||
@@ -200,11 +340,12 @@ impl Sub<usize> for Addr {
|
|||||||
|
|
||||||
fn sub(self, rhs: usize) -> Self::Output {
|
fn sub(self, rhs: usize) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
|
Addr::Stream(h) => Addr::Stream(h - rhs),
|
||||||
|
Addr::Con(h) => Addr::Con(h - rhs),
|
||||||
Addr::Lis(a) => Addr::Lis(a - rhs),
|
Addr::Lis(a) => Addr::Lis(a - rhs),
|
||||||
Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
|
Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
|
||||||
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
|
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
|
||||||
Addr::Str(s) => Addr::Str(s - rhs),
|
Addr::Str(s) => Addr::Str(s - rhs),
|
||||||
Addr::PStrTail(h, n) => Addr::PStrTail(h - rhs, n),
|
|
||||||
Addr::PStrLocation(h, n) => Addr::PStrLocation(h - rhs, n),
|
Addr::PStrLocation(h, n) => Addr::PStrLocation(h - rhs, n),
|
||||||
_ => self,
|
_ => self,
|
||||||
}
|
}
|
||||||
@@ -230,29 +371,78 @@ impl From<Ref> for TrailRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
pub enum HeapCellValue {
|
pub enum HeapCellValue {
|
||||||
Addr(Addr),
|
Addr(Addr),
|
||||||
|
Atom(ClauseName, Option<SharedOpDesc>),
|
||||||
|
DBRef(DBRef),
|
||||||
|
Integer(Rc<Integer>),
|
||||||
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
||||||
PartialString(PartialString),
|
Rational(Rc<Rational>),
|
||||||
|
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
|
||||||
|
Stream(Stream),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeapCellValue {
|
impl HeapCellValue {
|
||||||
|
#[inline]
|
||||||
pub fn as_addr(&self, focus: usize) -> Addr {
|
pub fn as_addr(&self, focus: usize) -> Addr {
|
||||||
match self {
|
match self {
|
||||||
HeapCellValue::Addr(ref a) => {
|
HeapCellValue::Addr(ref a) => {
|
||||||
a.clone()
|
*a
|
||||||
|
}
|
||||||
|
HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) |
|
||||||
|
HeapCellValue::Rational(..) => {
|
||||||
|
Addr::Con(focus)
|
||||||
}
|
}
|
||||||
HeapCellValue::NamedStr(_, _, _) => {
|
HeapCellValue::NamedStr(_, _, _) => {
|
||||||
Addr::Str(focus)
|
Addr::Str(focus)
|
||||||
}
|
}
|
||||||
HeapCellValue::PartialString(_) => {
|
HeapCellValue::PartialString(..) => {
|
||||||
Addr::PStrLocation(focus, 0)
|
Addr::PStrLocation(focus, 0)
|
||||||
}
|
}
|
||||||
|
HeapCellValue::Stream(_) => {
|
||||||
|
Addr::Stream(focus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn context_free_clone(&self) -> HeapCellValue {
|
||||||
|
match self {
|
||||||
|
&HeapCellValue::Addr(addr) => {
|
||||||
|
HeapCellValue::Addr(addr)
|
||||||
|
}
|
||||||
|
&HeapCellValue::Atom(ref name, ref op) => {
|
||||||
|
HeapCellValue::Atom(name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::DBRef(ref db_ref) => {
|
||||||
|
HeapCellValue::DBRef(db_ref.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
HeapCellValue::Integer(n.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::PartialString(ref pstr, has_tail) => {
|
||||||
|
HeapCellValue::PartialString(pstr.clone(), has_tail)
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(_) => {
|
||||||
|
HeapCellValue::Stream(Stream::null_stream())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Addr> for HeapCellValue {
|
||||||
|
#[inline]
|
||||||
|
fn from(value: Addr) -> HeapCellValue {
|
||||||
|
HeapCellValue::Addr(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum IndexPtr {
|
pub enum IndexPtr {
|
||||||
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||||
@@ -428,37 +618,31 @@ impl LocalCodePtr {
|
|||||||
LocalCodePtr::DirEntry(p) => {
|
LocalCodePtr::DirEntry(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"dir_entry",
|
"dir_entry",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::InSituDirEntry(p) => {
|
LocalCodePtr::InSituDirEntry(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"in_situ_dir_entry",
|
"in_situ_dir_entry",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"top_level",
|
"top_level",
|
||||||
2,
|
[integer(*chunk_num), integer(*offset)]
|
||||||
[heap_integer!(Integer::from(*chunk_num)),
|
|
||||||
heap_integer!(Integer::from(*offset))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::UserGoalExpansion(p) => {
|
LocalCodePtr::UserGoalExpansion(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"user_goal_expansion",
|
"user_goal_expansion",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::UserTermExpansion(p) => {
|
LocalCodePtr::UserTermExpansion(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"user_term_expansion",
|
"user_term_expansion",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,8 +654,12 @@ impl LocalCodePtr {
|
|||||||
impl PartialOrd<CodePtr> for CodePtr {
|
impl PartialOrd<CodePtr> for CodePtr {
|
||||||
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
|
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => {
|
||||||
_ => Some(Ordering::Greater),
|
l1.partial_cmp(l2)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,8 +674,12 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
|||||||
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
||||||
p1.partial_cmp(p2)
|
p1.partial_cmp(p2)
|
||||||
}
|
}
|
||||||
(_, &LocalCodePtr::TopLevel(_, _)) => Some(Ordering::Less),
|
(_, &LocalCodePtr::TopLevel(_, _)) => {
|
||||||
_ => Some(Ordering::Greater),
|
Some(Ordering::Less)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,17 +805,19 @@ impl ModuleStub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
|
pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
|
||||||
|
pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
|
||||||
|
|
||||||
pub struct IndexStore {
|
pub struct IndexStore {
|
||||||
pub(super) atom_tbl: TabledData<Atom>,
|
pub(super) atom_tbl: TabledData<Atom>,
|
||||||
pub(super) code_dir: CodeDir,
|
pub(super) code_dir: CodeDir,
|
||||||
pub(super) module_dir: ModuleDir,
|
|
||||||
pub(super) dynamic_code_dir: DynamicCodeDir,
|
pub(super) dynamic_code_dir: DynamicCodeDir,
|
||||||
pub(super) global_variables: GlobalVarDir,
|
pub(super) global_variables: GlobalVarDir,
|
||||||
pub(super) in_situ_code_dir: InSituCodeDir,
|
pub(super) in_situ_code_dir: InSituCodeDir,
|
||||||
pub(super) in_situ_module_dir: ModuleStubDir,
|
pub(super) in_situ_module_dir: ModuleStubDir,
|
||||||
|
pub(super) module_dir: ModuleDir,
|
||||||
pub(super) modules: ModuleDir,
|
pub(super) modules: ModuleDir,
|
||||||
pub(super) op_dir: OpDir,
|
pub(super) op_dir: OpDir,
|
||||||
|
pub(super) stream_aliases: StreamAliasDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexStore {
|
impl IndexStore {
|
||||||
@@ -710,6 +904,7 @@ impl IndexStore {
|
|||||||
in_situ_module_dir: ModuleStubDir::new(),
|
in_situ_module_dir: ModuleStubDir::new(),
|
||||||
op_dir: default_op_dir(),
|
op_dir: default_op_dir(),
|
||||||
modules: ModuleDir::new(),
|
modules: ModuleDir::new(),
|
||||||
|
stream_aliases: StreamAliasDir::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,13 +935,13 @@ impl IndexStore {
|
|||||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||||
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
||||||
|
|
||||||
let non_iso = clause_name!("non_iso");
|
let iso_ext = clause_name!("iso_ext");
|
||||||
|
|
||||||
let r_w_h = self
|
let r_w_h = self
|
||||||
.get_internal(r_w_h, 0, non_iso.clone())
|
.get_internal(r_w_h, 0, iso_ext.clone())
|
||||||
.and_then(|item| item.local());
|
.and_then(|item| item.local());
|
||||||
let r_wo_h = self
|
let r_wo_h = self
|
||||||
.get_internal(r_wo_h, 1, non_iso)
|
.get_internal(r_wo_h, 1, iso_ext)
|
||||||
.and_then(|item| item.local());
|
.and_then(|item| item.local());
|
||||||
|
|
||||||
if let Some(r_w_h) = r_w_h {
|
if let Some(r_w_h) = r_w_h {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
use prolog_parser::tabled_rc::*;
|
||||||
|
|
||||||
use crate::prolog::clause_types::*;
|
use crate::prolog::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
|
use crate::prolog::heap_print::*;
|
||||||
use crate::prolog::machine::attributed_variables::*;
|
use crate::prolog::machine::attributed_variables::*;
|
||||||
use crate::prolog::machine::copier::*;
|
use crate::prolog::machine::copier::*;
|
||||||
use crate::prolog::machine::heap::*;
|
use crate::prolog::machine::heap::*;
|
||||||
@@ -9,16 +11,191 @@ use crate::prolog::machine::machine_errors::*;
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::modules::*;
|
use crate::prolog::machine::modules::*;
|
||||||
use crate::prolog::machine::stack::*;
|
use crate::prolog::machine::stack::*;
|
||||||
use crate::prolog::read::PrologStream;
|
use crate::prolog::machine::streams::*;
|
||||||
|
use crate::prolog::read::readline;
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
|
|
||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
|
|
||||||
|
use indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::io::{stdout, Write};
|
use std::convert::TryFrom;
|
||||||
|
use std::io::Write;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
pub(crate) struct HeapPStrIter<'a> {
|
||||||
|
focus: Addr,
|
||||||
|
machine_st: &'a MachineState,
|
||||||
|
seen: IndexSet<Addr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HeapPStrIter<'a> {
|
||||||
|
#[inline]
|
||||||
|
fn new(machine_st: &'a MachineState, focus: Addr) -> Self {
|
||||||
|
HeapPStrIter {
|
||||||
|
focus,
|
||||||
|
machine_st,
|
||||||
|
seen: IndexSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn focus(&'a self) -> Addr {
|
||||||
|
self.machine_st.store(self.machine_st.deref(self.focus))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn to_string(&mut self) -> String {
|
||||||
|
let mut buf = String::new();
|
||||||
|
|
||||||
|
while let Some(iteratee) = self.next() {
|
||||||
|
match iteratee {
|
||||||
|
PStrIteratee::Char(c) => {
|
||||||
|
buf.push(c);
|
||||||
|
}
|
||||||
|
PStrIteratee::PStrSegment(h, n) => {
|
||||||
|
match &self.machine_st.heap[h] {
|
||||||
|
HeapCellValue::PartialString(ref pstr, _) => {
|
||||||
|
buf += pstr.as_str_from(n);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub(crate) enum PStrIteratee {
|
||||||
|
Char(char),
|
||||||
|
PStrSegment(usize, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for HeapPStrIter<'a> {
|
||||||
|
type Item = PStrIteratee;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let addr = self.machine_st.store(self.machine_st.deref(self.focus));
|
||||||
|
|
||||||
|
if !self.seen.contains(&addr) {
|
||||||
|
self.seen.insert(addr);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match addr {
|
||||||
|
Addr::PStrLocation(h, n) => {
|
||||||
|
if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
|
||||||
|
self.focus = if has_tail {
|
||||||
|
Addr::HeapCell(h + 1)
|
||||||
|
} else {
|
||||||
|
Addr::EmptyList
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(PStrIteratee::PStrSegment(h, n));
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Lis(l) => {
|
||||||
|
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
|
||||||
|
|
||||||
|
let opt_c = match addr {
|
||||||
|
Addr::Con(h) if self.machine_st.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref atom, _) = &self.machine_st.heap[h] {
|
||||||
|
if atom.is_char() {
|
||||||
|
Some(atom.as_str().chars().next().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Char(c) => {
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(c) = opt_c {
|
||||||
|
self.focus = Addr::HeapCell(l + 1);
|
||||||
|
return Some(PStrIteratee::Char(c));
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::EmptyList => {
|
||||||
|
self.focus = Addr::EmptyList;
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn compare_pstr_to_string<'a>(
|
||||||
|
heap_pstr_iter: &mut HeapPStrIter<'a>,
|
||||||
|
s: &String,
|
||||||
|
) -> Option<usize> {
|
||||||
|
let mut s_offset = 0;
|
||||||
|
|
||||||
|
while let Some(iteratee) = heap_pstr_iter.next() {
|
||||||
|
match iteratee {
|
||||||
|
PStrIteratee::Char(c1) => {
|
||||||
|
if let Some(c2) = s[s_offset ..].chars().next() {
|
||||||
|
if c1 != c2 {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
s_offset += c1.len_utf8();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PStrIteratee::PStrSegment(h, n) => {
|
||||||
|
match heap_pstr_iter.machine_st.heap[h] {
|
||||||
|
HeapCellValue::PartialString(ref pstr, _) => {
|
||||||
|
let t = pstr.as_str_from(n);
|
||||||
|
|
||||||
|
if s[s_offset ..].starts_with(t) {
|
||||||
|
s_offset += t.len();
|
||||||
|
} else if t.starts_with(&s[s_offset ..]) {
|
||||||
|
heap_pstr_iter.focus =
|
||||||
|
Addr::PStrLocation(h, n + s[s_offset ..].len());
|
||||||
|
|
||||||
|
s_offset += s[s_offset ..].len();
|
||||||
|
return Some(s_offset);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(s_offset)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Ball {
|
pub struct Ball {
|
||||||
pub(super) boundary: usize,
|
pub(super) boundary: usize,
|
||||||
pub(super) stub: Heap,
|
pub(super) stub: Heap,
|
||||||
@@ -57,13 +234,12 @@ impl Ball {
|
|||||||
|
|
||||||
for heap_value in self.stub.iter_from(0) {
|
for heap_value in self.stub.iter_from(0) {
|
||||||
stub.push(match heap_value {
|
stub.push(match heap_value {
|
||||||
HeapCellValue::Addr(ref addr) => HeapCellValue::Addr(addr.clone() - diff),
|
&HeapCellValue::Addr(addr) => {
|
||||||
HeapCellValue::PartialString(ref pstr) => {
|
HeapCellValue::Addr(addr - diff)
|
||||||
let mut new_pstr = pstr.clone();
|
}
|
||||||
new_pstr.tail = pstr.tail.clone() - diff;
|
heap_value => {
|
||||||
HeapCellValue::PartialString(new_pstr)
|
heap_value.context_free_clone()
|
||||||
}
|
}
|
||||||
heap_value => heap_value.clone(),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,14 +361,18 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
|||||||
let index = h - self.heap_boundary;
|
let index = h - self.heap_boundary;
|
||||||
self.stub[index].as_addr(h)
|
self.stub[index].as_addr(h)
|
||||||
}
|
}
|
||||||
Addr::StackCell(fr, sc) => self.stack.index_and_frame(fr)[sc].clone(),
|
Addr::StackCell(fr, sc) => {
|
||||||
addr => addr,
|
self.stack.index_and_frame(fr)[sc]
|
||||||
|
}
|
||||||
|
addr => {
|
||||||
|
addr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deref(&self, mut addr: Addr) -> Addr {
|
fn deref(&self, mut addr: Addr) -> Addr {
|
||||||
loop {
|
loop {
|
||||||
let value = self.store(addr.clone());
|
let value = self.store(addr);
|
||||||
|
|
||||||
if value.is_ref() && value != addr {
|
if value.is_ref() && value != addr {
|
||||||
addr = value;
|
addr = value;
|
||||||
@@ -225,9 +405,12 @@ impl Index<RegType> for MachineState {
|
|||||||
impl IndexMut<RegType> for MachineState {
|
impl IndexMut<RegType> for MachineState {
|
||||||
fn index_mut(&mut self, reg: RegType) -> &mut Self::Output {
|
fn index_mut(&mut self, reg: RegType) -> &mut Self::Output {
|
||||||
match reg {
|
match reg {
|
||||||
RegType::Temp(temp) => &mut self.registers[temp],
|
RegType::Temp(temp) => {
|
||||||
|
&mut self.registers[temp]
|
||||||
|
}
|
||||||
RegType::Perm(perm) => {
|
RegType::Perm(perm) => {
|
||||||
let e = self.e;
|
let e = self.e;
|
||||||
|
|
||||||
&mut self.stack.index_and_frame_mut(e)[perm]
|
&mut self.stack.index_and_frame_mut(e)[perm]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,8 +425,49 @@ pub(super) enum MachineMode {
|
|||||||
Write,
|
Write,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(super) enum HeapPtr {
|
||||||
|
HeapCell(usize),
|
||||||
|
PStrChar(usize, usize),
|
||||||
|
PStrLocation(usize, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeapPtr {
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn read(&self, heap: &Heap) -> Addr {
|
||||||
|
match self {
|
||||||
|
&HeapPtr::HeapCell(h) => {
|
||||||
|
Addr::HeapCell(h)
|
||||||
|
}
|
||||||
|
&HeapPtr::PStrChar(h, n) => {
|
||||||
|
if let &HeapCellValue::PartialString(ref pstr, has_tail) = &heap[h] {
|
||||||
|
if let Some(c) = pstr.range_from(n ..).next() {
|
||||||
|
Addr::Char(c)
|
||||||
|
} else if has_tail {
|
||||||
|
Addr::HeapCell(h + 1)
|
||||||
|
} else {
|
||||||
|
Addr::EmptyList
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapPtr::PStrLocation(h, n) => {
|
||||||
|
Addr::PStrLocation(h, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HeapPtr {
|
||||||
|
fn default() -> Self {
|
||||||
|
HeapPtr::HeapCell(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MachineState {
|
pub struct MachineState {
|
||||||
pub(super) s: usize,
|
pub(super) s: HeapPtr,
|
||||||
pub(super) p: CodePtr,
|
pub(super) p: CodePtr,
|
||||||
pub(super) b: usize,
|
pub(super) b: usize,
|
||||||
pub(super) b0: usize,
|
pub(super) b0: usize,
|
||||||
@@ -270,37 +494,208 @@ pub struct MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
|
pub(crate)
|
||||||
|
fn read_term(
|
||||||
|
&mut self,
|
||||||
|
current_input_stream: &mut Stream,
|
||||||
|
indices: &mut IndexStore,
|
||||||
|
) -> CallResult {
|
||||||
|
match self.read(
|
||||||
|
&mut parsing_stream(current_input_stream.clone()),
|
||||||
|
indices.atom_tbl.clone(),
|
||||||
|
&indices.op_dir,
|
||||||
|
) {
|
||||||
|
Ok(term_write_result) => {
|
||||||
|
let a1 = self[temp_v!(1)];
|
||||||
|
self.unify(Addr::HeapCell(term_write_result.heap_loc), a1);
|
||||||
|
|
||||||
|
if self.fail {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut list_of_var_eqs = vec![];
|
||||||
|
|
||||||
|
for (var, binding) in term_write_result.var_dict.into_iter().rev() {
|
||||||
|
let var_atom = clause_name!(var.to_string(), indices.atom_tbl);
|
||||||
|
|
||||||
|
let h = self.heap.h();
|
||||||
|
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
||||||
|
|
||||||
|
self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec));
|
||||||
|
self.heap.push(HeapCellValue::Atom(var_atom, None));
|
||||||
|
self.heap.push(HeapCellValue::Addr(binding));
|
||||||
|
|
||||||
|
list_of_var_eqs.push(Addr::Str(h));
|
||||||
|
}
|
||||||
|
|
||||||
|
let a2 = self[temp_v!(2)];
|
||||||
|
let list_offset =
|
||||||
|
Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
|
||||||
|
|
||||||
|
Ok(self.unify(list_offset, a2))
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
if let ParserError::UnexpectedEOF = err {
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the input stream after an input failure.
|
||||||
|
*current_input_stream = readline::input_stream();
|
||||||
|
|
||||||
|
let h = self.heap.h();
|
||||||
|
let syntax_error = MachineError::syntax_error(h, err);
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("read_term"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(syntax_error, stub))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn write_term<'a>(
|
||||||
|
&'a self,
|
||||||
|
op_dir: &'a OpDir,
|
||||||
|
) -> Result<Option<HCPrinter<'a, PrinterOutputter>>, MachineStub>
|
||||||
|
{
|
||||||
|
let ignore_ops = self.store(self.deref(self[temp_v!(2)]));
|
||||||
|
let numbervars = self.store(self.deref(self[temp_v!(3)]));
|
||||||
|
let quoted = self.store(self.deref(self[temp_v!(4)]));
|
||||||
|
let max_depth = self.store(self.deref(self[temp_v!(6)]));
|
||||||
|
|
||||||
|
let mut printer = HCPrinter::new(&self, op_dir, PrinterOutputter::new());
|
||||||
|
|
||||||
|
if let &Addr::Con(h) = &ignore_ops {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
printer.ignore_ops = name.as_str() == "true";
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let &Addr::Con(h) = &numbervars {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
printer.numbervars = name.as_str() == "true";
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let &Addr::Con(h) = "ed {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
printer.quoted = name.as_str() == "true";
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match Number::try_from((max_depth, &self.heap)) {
|
||||||
|
Ok(Number::Fixnum(n)) => {
|
||||||
|
if let Ok(n) = usize::try_from(n) {
|
||||||
|
printer.max_depth = n;
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Number::Integer(n)) => {
|
||||||
|
if let Some(n) = n.to_usize() {
|
||||||
|
printer.max_depth = n;
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
|
||||||
|
|
||||||
|
match self.try_from_list(temp_v!(5), stub) {
|
||||||
|
Ok(addrs) => {
|
||||||
|
let mut var_names: IndexMap<Addr, String> = IndexMap::new();
|
||||||
|
|
||||||
|
for addr in addrs {
|
||||||
|
match addr {
|
||||||
|
Addr::Str(s) => match &self.heap[s] {
|
||||||
|
&HeapCellValue::NamedStr(2, ref name, _)
|
||||||
|
if name.as_str() == "=" =>
|
||||||
|
{
|
||||||
|
let atom = self.heap[s + 1].as_addr(s + 1);
|
||||||
|
let var = self.heap[s + 2].as_addr(s + 2);
|
||||||
|
|
||||||
|
let atom = match self.store(self.deref(atom)) {
|
||||||
|
Addr::Con(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
|
||||||
|
atom.to_string()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Char(c) => c.to_string(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let var = self.store(self.deref(var));
|
||||||
|
|
||||||
|
if var_names.contains_key(&var) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var_names.insert(var, atom);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printer.var_names = var_names;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(printer))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
|
||||||
|
HeapPStrIter::new(self, focus)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError> {
|
fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError> {
|
||||||
let mut chars = String::new();
|
let mut chars = String::new();
|
||||||
let mut iter = addrs.iter();
|
let mut iter = addrs.iter();
|
||||||
|
|
||||||
while let Some(addr) = iter.next() {
|
while let Some(addr) = iter.next() {
|
||||||
match addr {
|
let addr = self.store(self.deref(*addr));
|
||||||
&Addr::Con(Constant::String(n, ref s))
|
|
||||||
if self.flags.double_quotes.is_chars() => {
|
|
||||||
if s.len() < n {
|
|
||||||
chars += &s[n ..];
|
|
||||||
}
|
|
||||||
|
|
||||||
if iter.next().is_some() {
|
match addr {
|
||||||
return Err(MachineError::type_error(ValidType::Character, addr.clone()));
|
Addr::Char(c) => {
|
||||||
}
|
|
||||||
}
|
|
||||||
&Addr::Con(Constant::Char(c)) => {
|
|
||||||
chars.push(c);
|
chars.push(c);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
&Addr::Con(Constant::Atom(ref name, _))
|
Addr::Con(h) => {
|
||||||
if name.as_str().len() == 1 => {
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
if name.is_char() {
|
||||||
chars += name.as_str();
|
chars += name.as_str();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let h = self.heap.h();
|
||||||
|
|
||||||
return Err(
|
return Err(
|
||||||
MachineError::type_error(ValidType::Character, addr.clone())
|
MachineError::type_error(h, ValidType::Character, addr)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(chars)
|
Ok(chars)
|
||||||
}
|
}
|
||||||
@@ -384,15 +779,15 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<usize>
|
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<LocalCodePtr>
|
||||||
{
|
{
|
||||||
match indices.in_situ_code_dir.get(&(name.clone(), arity)) {
|
match indices.in_situ_code_dir.get(&(name.clone(), arity)) {
|
||||||
Some(p) => Some(*p),
|
Some(p) => Some(LocalCodePtr::InSituDirEntry(*p)),
|
||||||
None =>
|
None =>
|
||||||
match indices.code_dir.get(&(name, arity)) {
|
match indices.code_dir.get(&(name, arity)) {
|
||||||
Some(ref idx) => {
|
Some(ref idx) => {
|
||||||
if let IndexPtr::Index(p) = idx.0.borrow().0 {
|
if let IndexPtr::Index(p) = idx.0.borrow().0 {
|
||||||
Some(p)
|
Some(LocalCodePtr::DirEntry(p))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -411,12 +806,12 @@ fn try_in_situ(
|
|||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
||||||
if last_call {
|
if last_call {
|
||||||
machine_st.execute_at_index(arity, LocalCodePtr::DirEntry(p));
|
machine_st.execute_at_index(arity, p);
|
||||||
} else {
|
} else {
|
||||||
machine_st.call_at_index(arity, LocalCodePtr::DirEntry(p));
|
machine_st.call_at_index(arity, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.p = in_situ_dir_entry!(p);
|
machine_st.p = CodePtr::Local(p);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||||
@@ -435,7 +830,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1 .. n + 1 {
|
||||||
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
|
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
machine_st.num_of_args = n;
|
||||||
@@ -474,7 +869,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1 .. n + 1 {
|
||||||
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
|
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
machine_st.num_of_args = n;
|
||||||
@@ -510,7 +905,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1 .. n + 1 {
|
||||||
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
|
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
machine_st.num_of_args = n;
|
||||||
@@ -536,8 +931,8 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
attr_var_init_bindings_b,
|
attr_var_init_bindings_b,
|
||||||
);
|
);
|
||||||
|
|
||||||
machine_st.stack.truncate(machine_st.b);
|
|
||||||
machine_st.b = machine_st.stack.index_or_frame(b).prelude.b;
|
machine_st.b = machine_st.stack.index_or_frame(b).prelude.b;
|
||||||
|
machine_st.stack.truncate(b);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h();
|
machine_st.hb = machine_st.heap.h();
|
||||||
machine_st.p += offset;
|
machine_st.p += offset;
|
||||||
@@ -550,7 +945,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1 .. n + 1 {
|
||||||
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
|
machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.num_of_args = n;
|
machine_st.num_of_args = n;
|
||||||
@@ -576,8 +971,8 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
attr_var_init_bindings_b,
|
attr_var_init_bindings_b,
|
||||||
);
|
);
|
||||||
|
|
||||||
machine_st.stack.truncate(machine_st.b);
|
|
||||||
machine_st.b = machine_st.stack.index_or_frame(b).prelude.b;
|
machine_st.b = machine_st.stack.index_or_frame(b).prelude.b;
|
||||||
|
machine_st.stack.truncate(b);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h();
|
machine_st.hb = machine_st.heap.h();
|
||||||
machine_st.p += 1;
|
machine_st.p += 1;
|
||||||
@@ -667,11 +1062,12 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
ct: &BuiltInClauseType,
|
ct: &BuiltInClauseType,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
parsing_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
match ct {
|
match ct {
|
||||||
&BuiltInClauseType::AcyclicTerm => {
|
&BuiltInClauseType::AcyclicTerm => {
|
||||||
let addr = machine_st[temp_v!(1)].clone();
|
let addr = machine_st[temp_v!(1)];
|
||||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
machine_st.fail = machine_st.is_cyclic_term(addr);
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
@@ -680,48 +1076,50 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Compare => {
|
&BuiltInClauseType::Compare => {
|
||||||
let a1 = machine_st[temp_v!(1)].clone();
|
let a1 = machine_st[temp_v!(1)];
|
||||||
let a2 = machine_st[temp_v!(2)].clone();
|
let a2 = machine_st[temp_v!(2)];
|
||||||
let a3 = machine_st[temp_v!(3)].clone();
|
let a3 = machine_st[temp_v!(3)];
|
||||||
|
|
||||||
let c = match machine_st.compare_term_test(&a2, &a3) {
|
let atom = match machine_st.compare_term_test(&a2, &a3) {
|
||||||
Ordering::Greater => {
|
Some(Ordering::Greater) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
||||||
Addr::Con(Constant::Atom(clause_name!(">"), spec))
|
HeapCellValue::Atom(clause_name!(">"), spec)
|
||||||
}
|
}
|
||||||
Ordering::Equal => {
|
Some(Ordering::Equal) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
||||||
Addr::Con(Constant::Atom(clause_name!("="), spec))
|
HeapCellValue::Atom(clause_name!("="), spec)
|
||||||
}
|
}
|
||||||
Ordering::Less => {
|
None | Some(Ordering::Less) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
||||||
Addr::Con(Constant::Atom(clause_name!("<"), spec))
|
HeapCellValue::Atom(clause_name!("<"), spec)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
machine_st.unify(a1, c);
|
let h = machine_st.heap.h();
|
||||||
|
|
||||||
|
machine_st.heap.push(atom);
|
||||||
|
machine_st.unify(a1, Addr::Con(h));
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::CompareTerm(qt) => {
|
&BuiltInClauseType::CompareTerm(qt) => {
|
||||||
machine_st.compare_term(qt);
|
machine_st.compare_term(qt);
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::CyclicTerm => {
|
|
||||||
let addr = machine_st[temp_v!(1)].clone();
|
|
||||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
|
||||||
}
|
|
||||||
&BuiltInClauseType::Nl => {
|
&BuiltInClauseType::Nl => {
|
||||||
let mut stdout = stdout();
|
write!(current_output_stream, "\n").unwrap();
|
||||||
|
current_output_stream.flush().unwrap();
|
||||||
|
|
||||||
write!(stdout, "\n").unwrap();
|
|
||||||
stdout.flush().unwrap();
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Read => {
|
&BuiltInClauseType::Read => {
|
||||||
match machine_st.read(parsing_stream, indices.atom_tbl.clone(), &indices.op_dir) {
|
match machine_st.read(
|
||||||
|
&mut parsing_stream(current_input_stream.clone()),
|
||||||
|
indices.atom_tbl.clone(),
|
||||||
|
&indices.op_dir,
|
||||||
|
) {
|
||||||
Ok(offset) => {
|
Ok(offset) => {
|
||||||
let addr = machine_st[temp_v!(1)].clone();
|
let addr = machine_st[temp_v!(1)];
|
||||||
machine_st.unify(addr, Addr::HeapCell(offset.heap_loc));
|
machine_st.unify(addr, Addr::HeapCell(offset.heap_loc));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -741,8 +1139,8 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Eq => {
|
&BuiltInClauseType::Eq => {
|
||||||
let a1 = machine_st[temp_v!(1)].clone();
|
let a1 = machine_st[temp_v!(1)];
|
||||||
let a2 = machine_st[temp_v!(2)].clone();
|
let a2 = machine_st[temp_v!(2)];
|
||||||
|
|
||||||
machine_st.fail = machine_st.eq_test(a1, a2);
|
machine_st.fail = machine_st.eq_test(a1, a2);
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
@@ -756,10 +1154,11 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::NotEq => {
|
&BuiltInClauseType::NotEq => {
|
||||||
let a1 = machine_st[temp_v!(1)].clone();
|
let a1 = machine_st[temp_v!(1)];
|
||||||
let a2 = machine_st[temp_v!(2)].clone();
|
let a2 = machine_st[temp_v!(2)];
|
||||||
|
|
||||||
machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
|
machine_st.fail =
|
||||||
|
if let Some(Ordering::Equal) = machine_st.compare_term_test(&a1, &a2) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -773,12 +1172,15 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||||
let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
|
let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
|
||||||
|
|
||||||
list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2));
|
list.sort_unstable_by(|a1, a2| {
|
||||||
|
machine_st.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
|
||||||
|
});
|
||||||
|
|
||||||
machine_st.term_dedup(&mut list);
|
machine_st.term_dedup(&mut list);
|
||||||
|
|
||||||
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
|
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
|
||||||
|
|
||||||
let r2 = machine_st[temp_v!(2)].clone();
|
let r2 = machine_st[temp_v!(2)];
|
||||||
machine_st.unify(r2, heap_addr);
|
machine_st.unify(r2, heap_addr);
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
@@ -795,21 +1197,25 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
key_pairs.push((key, val.clone()));
|
key_pairs.push((key, val.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
key_pairs.sort_by(|a1, a2| machine_st.compare_term_test(&a1.0, &a2.0));
|
key_pairs.sort_by(|a1, a2| {
|
||||||
|
machine_st.compare_term_test(&a1.0, &a2.0).unwrap_or(Ordering::Less)
|
||||||
|
});
|
||||||
|
|
||||||
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
||||||
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
|
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
|
||||||
|
|
||||||
let r2 = machine_st[temp_v!(2)].clone();
|
let r2 = machine_st[temp_v!(2)];
|
||||||
machine_st.unify(r2, heap_addr);
|
machine_st.unify(r2, heap_addr);
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Is(r, ref at) => {
|
&BuiltInClauseType::Is(r, ref at) => {
|
||||||
let a1 = machine_st[r].clone();
|
let a1 = machine_st[r];
|
||||||
let a2 = machine_st.get_number(at)?;
|
let n2 = machine_st.get_number(at)?;
|
||||||
|
|
||||||
|
let n2 = machine_st.heap.put_constant(n2.into());
|
||||||
|
machine_st.unify(a1, n2);
|
||||||
|
|
||||||
machine_st.unify(a1, Addr::Con(a2.to_constant()));
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -842,13 +1248,20 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
parsing_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||||
match ClauseType::from(name.clone(), arity, None) {
|
match ClauseType::from(name.clone(), arity, None) {
|
||||||
ClauseType::BuiltIn(built_in) => {
|
ClauseType::BuiltIn(built_in) => {
|
||||||
machine_st.setup_built_in_call(built_in.clone());
|
machine_st.setup_built_in_call(built_in.clone());
|
||||||
self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
|
self.call_builtin(
|
||||||
|
machine_st,
|
||||||
|
&built_in,
|
||||||
|
indices,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
ClauseType::CallN => {
|
ClauseType::CallN => {
|
||||||
machine_st.handle_internal_call_n(arity);
|
machine_st.handle_internal_call_n(arity);
|
||||||
@@ -876,11 +1289,13 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClauseType::Hook(_) | ClauseType::System(_) => {
|
ClauseType::Hook(_) | ClauseType::System(_) => {
|
||||||
let name = Addr::Con(Constant::Atom(name, None));
|
let name = functor!(clause_name(name));
|
||||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||||
|
|
||||||
return Err(machine_st
|
return Err(machine_st.error_form(
|
||||||
.error_form(MachineError::type_error(ValidType::Callable, name), stub));
|
MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name),
|
||||||
|
stub,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -928,10 +1343,17 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
ct: &BuiltInClauseType,
|
ct: &BuiltInClauseType,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
parsing_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
self.prev_policy
|
self.prev_policy.call_builtin(
|
||||||
.call_builtin(machine_st, ct, indices, parsing_stream)?;
|
machine_st,
|
||||||
|
ct,
|
||||||
|
indices,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream
|
||||||
|
)?;
|
||||||
|
|
||||||
self.increment(machine_st)
|
self.increment(machine_st)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -940,10 +1362,17 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
machine_st: &mut MachineState,
|
machine_st: &mut MachineState,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
parsing_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
self.prev_policy
|
self.prev_policy.call_n(
|
||||||
.call_n(machine_st, arity, indices, parsing_stream)?;
|
machine_st,
|
||||||
|
arity,
|
||||||
|
indices,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
)?;
|
||||||
|
|
||||||
self.increment(machine_st)
|
self.increment(machine_st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -962,7 +1391,8 @@ pub(crate) struct CWILCallPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CWILCallPolicy {
|
impl CWILCallPolicy {
|
||||||
pub(crate) fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
pub(crate)
|
||||||
|
fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
||||||
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||||
mem::swap(&mut prev_policy, policy);
|
mem::swap(&mut prev_policy, policy);
|
||||||
|
|
||||||
@@ -972,6 +1402,7 @@ impl CWILCallPolicy {
|
|||||||
limits: vec![],
|
limits: vec![],
|
||||||
inference_limit_exceeded: false,
|
inference_limit_exceeded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
*policy = Box::new(new_policy);
|
*policy = Box::new(new_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,10 +1414,10 @@ impl CWILCallPolicy {
|
|||||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
if let Some(&(ref limit, bp)) = self.limits.last() {
|
||||||
if self.count == *limit {
|
if self.count == *limit {
|
||||||
self.inference_limit_exceeded = true;
|
self.inference_limit_exceeded = true;
|
||||||
|
|
||||||
return Err(functor!(
|
return Err(functor!(
|
||||||
"inference_limit_exceeded",
|
"inference_limit_exceeded",
|
||||||
1,
|
[addr(Addr::Usize(bp))]
|
||||||
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]
|
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
@@ -996,7 +1427,8 @@ impl CWILCallPolicy {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
|
pub(crate)
|
||||||
|
fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
|
||||||
limit += &self.count;
|
limit += &self.count;
|
||||||
|
|
||||||
match self.limits.last().cloned() {
|
match self.limits.last().cloned() {
|
||||||
@@ -1007,7 +1439,8 @@ impl CWILCallPolicy {
|
|||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
pub(crate)
|
||||||
|
fn remove_limit(&mut self, b: usize) -> &Integer {
|
||||||
if let Some((_, bp)) = self.limits.last().cloned() {
|
if let Some((_, bp)) = self.limits.last().cloned() {
|
||||||
if bp == b {
|
if bp == b {
|
||||||
self.limits.pop();
|
self.limits.pop();
|
||||||
@@ -1017,11 +1450,13 @@ impl CWILCallPolicy {
|
|||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_empty(&self) -> bool {
|
pub(crate)
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
self.limits.is_empty()
|
self.limits.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
pub(crate)
|
||||||
|
fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
||||||
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||||
mem::swap(&mut self.prev_policy, &mut new_inner);
|
mem::swap(&mut self.prev_policy, &mut new_inner);
|
||||||
new_inner
|
new_inner
|
||||||
@@ -1030,16 +1465,16 @@ impl CWILCallPolicy {
|
|||||||
|
|
||||||
pub(crate) trait CutPolicy: Any {
|
pub(crate) trait CutPolicy: Any {
|
||||||
// returns true iff we fail or cut redirected the MachineState's p itself
|
// returns true iff we fail or cut redirected the MachineState's p itself
|
||||||
fn cut(&mut self, _: &mut MachineState, _: RegType) -> bool;
|
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
downcast!(dyn CutPolicy);
|
downcast!(dyn CutPolicy);
|
||||||
|
|
||||||
fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
|
fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool {
|
||||||
let b = machine_st.b;
|
let b = machine_st.b;
|
||||||
|
|
||||||
match addr {
|
match addr {
|
||||||
Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
|
&Addr::CutPoint(b0) | &Addr::Usize(b0) => {
|
||||||
if b > b0 {
|
if b > b0 {
|
||||||
machine_st.b = b0;
|
machine_st.b = b0;
|
||||||
machine_st.tidy_trail();
|
machine_st.tidy_trail();
|
||||||
@@ -1057,14 +1492,14 @@ fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
|
|||||||
pub(crate) struct DefaultCutPolicy {}
|
pub(crate) struct DefaultCutPolicy {}
|
||||||
|
|
||||||
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
|
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
|
||||||
let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
|
let addr = machine_st.store(machine_st.deref(machine_st[r]));
|
||||||
cut_body(machine_st, addr);
|
cut_body(machine_st, &addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CutPolicy for DefaultCutPolicy {
|
impl CutPolicy for DefaultCutPolicy {
|
||||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
||||||
let addr = machine_st[r].clone();
|
let addr = machine_st[r];
|
||||||
cut_body(machine_st, addr)
|
cut_body(machine_st, &addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1102,7 +1537,7 @@ impl SCCCutPolicy {
|
|||||||
let (idx, arity) = if machine_st.block < prev_block {
|
let (idx, arity) = if machine_st.block < prev_block {
|
||||||
(dir_entry!(self.r_c_w_h), 0)
|
(dir_entry!(self.r_c_w_h), 0)
|
||||||
} else {
|
} else {
|
||||||
machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
|
machine_st[temp_v!(1)] = Addr::Usize(b_cutoff);
|
||||||
(dir_entry!(self.r_c_wo_h), 1)
|
(dir_entry!(self.r_c_wo_h), 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1124,8 +1559,8 @@ impl CutPolicy for SCCCutPolicy {
|
|||||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
||||||
let b = machine_st.b;
|
let b = machine_st.b;
|
||||||
|
|
||||||
match machine_st[r].clone() {
|
match machine_st[r] {
|
||||||
Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
|
Addr::Usize(b0) | Addr::CutPoint(b0) => {
|
||||||
if b > b0 {
|
if b > b0 {
|
||||||
machine_st.b = b0;
|
machine_st.b = b0;
|
||||||
machine_st.tidy_trail();
|
machine_st.tidy_trail();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -19,12 +19,15 @@ pub mod machine_errors;
|
|||||||
pub mod machine_indices;
|
pub mod machine_indices;
|
||||||
pub(super) mod machine_state;
|
pub(super) mod machine_state;
|
||||||
pub mod modules;
|
pub mod modules;
|
||||||
mod partial_string;
|
pub mod partial_string;
|
||||||
mod raw_block;
|
mod raw_block;
|
||||||
mod stack;
|
mod stack;
|
||||||
|
pub(crate) mod streams;
|
||||||
pub(super) mod term_expansion;
|
pub(super) mod term_expansion;
|
||||||
pub mod toplevel;
|
pub mod toplevel;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod arithmetic_ops;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod machine_state_impl;
|
mod machine_state_impl;
|
||||||
mod system_calls;
|
mod system_calls;
|
||||||
@@ -36,14 +39,14 @@ use crate::prolog::machine::machine_errors::*;
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
use crate::prolog::machine::modules::*;
|
use crate::prolog::machine::modules::*;
|
||||||
|
use crate::prolog::machine::streams::*;
|
||||||
use crate::prolog::machine::toplevel::*;
|
use crate::prolog::machine::toplevel::*;
|
||||||
use crate::prolog::read::PrologStream;
|
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -76,7 +79,8 @@ pub struct Machine {
|
|||||||
pub(super) indices: IndexStore,
|
pub(super) indices: IndexStore,
|
||||||
pub(super) code_repo: CodeRepo,
|
pub(super) code_repo: CodeRepo,
|
||||||
pub(super) toplevel_idx: usize,
|
pub(super) toplevel_idx: usize,
|
||||||
pub(super) prolog_stream: ParsingStream<Box<dyn Read>>,
|
pub(super) current_input_stream: Stream,
|
||||||
|
pub(super) current_output_stream: Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<LocalCodePtr> for CodeRepo {
|
impl Index<LocalCodePtr> for CodeRepo {
|
||||||
@@ -149,8 +153,16 @@ impl SubModuleUser for IndexStore {
|
|||||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
|
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
|
||||||
if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) {
|
if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) {
|
||||||
if !code_idx.is_undefined() {
|
if !code_idx.is_undefined() {
|
||||||
|
match (name.as_str(), arity) {
|
||||||
|
("term_expansion", 2) => {
|
||||||
|
}
|
||||||
|
("goal_expansion", 2) => {
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
println!("Warning: overwriting {}/{}", &name, arity);
|
println!("Warning: overwriting {}/{}", &name, arity);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let (p, module_name) = idx.0.borrow().clone();
|
let (p, module_name) = idx.0.borrow().clone();
|
||||||
set_code_index!(code_idx, p, module_name);
|
set_code_index!(code_idx, p, module_name);
|
||||||
@@ -193,7 +205,11 @@ impl SubModuleUser for IndexStore {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_dir() -> std::path::PathBuf {
|
fn current_dir() -> std::path::PathBuf {
|
||||||
let mut path_buf = std::path::PathBuf::from(file!());
|
let mut path_buf = std::path::PathBuf::from(PROJECT_DIR);
|
||||||
|
|
||||||
|
// file!() always produces a path relative to PROJECT_DIR.
|
||||||
|
path_buf = path_buf.join(std::path::PathBuf::from(file!()));
|
||||||
|
|
||||||
path_buf.pop();
|
path_buf.pop();
|
||||||
path_buf
|
path_buf
|
||||||
}
|
}
|
||||||
@@ -212,7 +228,11 @@ impl Machine {
|
|||||||
current_dir.clone(),
|
current_dir.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
match compile_special_form(self, parsing_stream(VERIFY_ATTRS.as_bytes()), verify_attrs_src)
|
match compile_special_form(
|
||||||
|
self,
|
||||||
|
Stream::from(VERIFY_ATTRS),
|
||||||
|
verify_attrs_src,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Ok(p) => {
|
Ok(p) => {
|
||||||
self.machine_st.attr_var_init.verify_attrs_loc = p;
|
self.machine_st.attr_var_init.verify_attrs_loc = p;
|
||||||
@@ -226,7 +246,11 @@ impl Machine {
|
|||||||
current_dir,
|
current_dir,
|
||||||
);
|
);
|
||||||
|
|
||||||
match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes()), project_attrs_src)
|
match compile_special_form(
|
||||||
|
self,
|
||||||
|
Stream::from(PROJECT_ATTRS),
|
||||||
|
project_attrs_src,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Ok(p) => {
|
Ok(p) => {
|
||||||
self.machine_st.attr_var_init.project_attrs_loc = p;
|
self.machine_st.attr_var_init.project_attrs_loc = p;
|
||||||
@@ -250,7 +274,7 @@ impl Machine {
|
|||||||
|
|
||||||
compile_user_module(
|
compile_user_module(
|
||||||
self,
|
self,
|
||||||
parsing_stream(TOPLEVEL.as_bytes()),
|
Stream::from(TOPLEVEL),
|
||||||
true,
|
true,
|
||||||
top_lvl_src,
|
top_lvl_src,
|
||||||
);
|
);
|
||||||
@@ -264,7 +288,11 @@ impl Machine {
|
|||||||
|
|
||||||
Ok(self.indices.insert_module(module))
|
Ok(self.indices.insert_module(module))
|
||||||
} else {
|
} else {
|
||||||
Err(SessionError::ModuleNotFound)
|
let err = ExistenceError::SourceSink(ModuleSource::File(
|
||||||
|
clause_name!("$toplevel"),
|
||||||
|
));
|
||||||
|
|
||||||
|
Err(SessionError::ExistenceError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +306,7 @@ impl Machine {
|
|||||||
|
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
let file_src = match File::open(&path) {
|
let file_src = match File::open(&path) {
|
||||||
Ok(file_handle) => parsing_stream(file_handle),
|
Ok(file_handle) => Stream::from(file_handle),
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -293,7 +321,7 @@ impl Machine {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.prolog_stream = readline::input_stream();
|
self.current_input_stream = readline::input_stream();
|
||||||
self.policies.cut_policy = Box::new(DefaultCutPolicy {});
|
self.policies.cut_policy = Box::new(DefaultCutPolicy {});
|
||||||
self.machine_st.reset();
|
self.machine_st.reset();
|
||||||
}
|
}
|
||||||
@@ -319,8 +347,8 @@ impl Machine {
|
|||||||
// the first of these is the path to the scryer-prolog executable, so skip
|
// the first of these is the path to the scryer-prolog executable, so skip
|
||||||
// it.
|
// it.
|
||||||
for filename in env::args().skip(1) {
|
for filename in env::args().skip(1) {
|
||||||
let atom = atom!(filename, self.indices.atom_tbl);
|
let atom = clause_name!(filename, self.indices.atom_tbl);
|
||||||
filename_atoms.push(Addr::Con(atom));
|
filename_atoms.push(HeapCellValue::Atom(atom, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
let list_addr =
|
let list_addr =
|
||||||
@@ -332,7 +360,7 @@ impl Machine {
|
|||||||
self.run_query();
|
self.run_query();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(prolog_stream: PrologStream) -> Self
|
pub fn new(current_input_stream: Stream, current_output_stream: Stream) -> Self
|
||||||
{
|
{
|
||||||
let mut wam = Machine {
|
let mut wam = Machine {
|
||||||
machine_st: MachineState::new(),
|
machine_st: MachineState::new(),
|
||||||
@@ -341,7 +369,8 @@ impl Machine {
|
|||||||
indices: IndexStore::new(),
|
indices: IndexStore::new(),
|
||||||
code_repo: CodeRepo::new(),
|
code_repo: CodeRepo::new(),
|
||||||
toplevel_idx: 0,
|
toplevel_idx: 0,
|
||||||
prolog_stream,
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
let atom_tbl = wam.indices.atom_tbl.clone();
|
let atom_tbl = wam.indices.atom_tbl.clone();
|
||||||
@@ -354,7 +383,7 @@ impl Machine {
|
|||||||
|
|
||||||
compile_listing(
|
compile_listing(
|
||||||
&mut wam,
|
&mut wam,
|
||||||
parsing_stream(BUILTINS.as_bytes()),
|
Stream::from(BUILTINS),
|
||||||
default_index_store!(atom_tbl.clone()),
|
default_index_store!(atom_tbl.clone()),
|
||||||
true,
|
true,
|
||||||
ListingSource::from_file_and_path(
|
ListingSource::from_file_and_path(
|
||||||
@@ -365,25 +394,36 @@ impl Machine {
|
|||||||
|
|
||||||
wam.compile_special_forms();
|
wam.compile_special_forms();
|
||||||
|
|
||||||
compile_user_module(&mut wam, parsing_stream(ERROR.as_bytes()), true,
|
compile_user_module(&mut wam,
|
||||||
|
Stream::from(ERROR),
|
||||||
|
true,
|
||||||
ListingSource::from_file_and_path(
|
ListingSource::from_file_and_path(
|
||||||
clause_name!("error"),
|
clause_name!("error"),
|
||||||
lib_path.clone(),
|
lib_path.clone(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
compile_user_module(&mut wam, parsing_stream(LISTS.as_bytes()), true,
|
|
||||||
|
compile_user_module(&mut wam,
|
||||||
|
Stream::from(LISTS),
|
||||||
|
true,
|
||||||
ListingSource::from_file_and_path(
|
ListingSource::from_file_and_path(
|
||||||
clause_name!("lists"),
|
clause_name!("lists"),
|
||||||
lib_path.clone(),
|
lib_path.clone(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
compile_user_module(&mut wam, parsing_stream(NON_ISO.as_bytes()), true,
|
|
||||||
|
compile_user_module(&mut wam,
|
||||||
|
Stream::from(ISO_EXT),
|
||||||
|
true,
|
||||||
ListingSource::from_file_and_path(
|
ListingSource::from_file_and_path(
|
||||||
clause_name!("non_iso"),
|
clause_name!("iso_ext"),
|
||||||
lib_path.clone(),
|
lib_path.clone(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
compile_user_module(&mut wam, parsing_stream(SI.as_bytes()), true,
|
|
||||||
|
compile_user_module(&mut wam,
|
||||||
|
Stream::from(SI),
|
||||||
|
true,
|
||||||
ListingSource::from_file_and_path(
|
ListingSource::from_file_and_path(
|
||||||
clause_name!("si"),
|
clause_name!("si"),
|
||||||
lib_path.clone(),
|
lib_path.clone(),
|
||||||
@@ -514,15 +554,17 @@ impl Machine {
|
|||||||
HeapCellValue::NamedStr(arity, ref name, _)
|
HeapCellValue::NamedStr(arity, ref name, _)
|
||||||
if *arity == 2 && name.as_str() == "/" => {
|
if *arity == 2 && name.as_str() == "/" => {
|
||||||
let name = match &self.machine_st.heap[s+1] {
|
let name = match &self.machine_st.heap[s+1] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
&HeapCellValue::Atom(ref name, _) =>
|
||||||
name.clone(),
|
name.clone(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let arity = match &self.machine_st.heap[s+2] {
|
let arity = match &self.machine_st.heap[s+2] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
|
&HeapCellValue::Integer(ref arity) =>
|
||||||
arity.to_usize().unwrap(),
|
arity.to_usize().unwrap(),
|
||||||
|
&HeapCellValue::Addr(Addr::Fixnum(n)) =>
|
||||||
|
usize::try_from(n).unwrap(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
@@ -532,22 +574,24 @@ impl Machine {
|
|||||||
HeapCellValue::NamedStr(arity, ref name, _)
|
HeapCellValue::NamedStr(arity, ref name, _)
|
||||||
if *arity == 3 && name.as_str() == "op" => {
|
if *arity == 3 && name.as_str() == "op" => {
|
||||||
let name = match &self.machine_st.heap[s+3] {
|
let name = match &self.machine_st.heap[s+3] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
&HeapCellValue::Atom(ref name, _) =>
|
||||||
name.clone(),
|
name.clone(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let spec = match &self.machine_st.heap[s+2] {
|
let spec = match &self.machine_st.heap[s+2] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
&HeapCellValue::Atom(ref name, _) =>
|
||||||
name.clone(),
|
name.clone(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let prec = match &self.machine_st.heap[s+1] {
|
let prec = match &self.machine_st.heap[s+1] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
|
&HeapCellValue::Integer(ref arity) =>
|
||||||
arity.to_usize().unwrap(),
|
arity.to_usize().unwrap(),
|
||||||
|
&HeapCellValue::Addr(Addr::Fixnum(n)) =>
|
||||||
|
usize::try_from(n).unwrap(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
@@ -577,9 +621,13 @@ impl Machine {
|
|||||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||||
|
|
||||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
|
let name = {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||||
_ => unreachable!()
|
|
||||||
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
|
HeapCellValue::Atom(name, _) => name.clone(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let load_result = match to_src(name) {
|
let load_result = match to_src(name) {
|
||||||
@@ -620,9 +668,13 @@ impl Machine {
|
|||||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||||
|
|
||||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
|
let name = {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||||
_ => unreachable!()
|
|
||||||
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
|
HeapCellValue::Atom(name, _) => name.clone(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let exports = match self.extract_module_export_list() {
|
let exports = match self.extract_module_export_list() {
|
||||||
@@ -699,7 +751,7 @@ impl Machine {
|
|||||||
snapshot.e = self.machine_st.e;
|
snapshot.e = self.machine_st.e;
|
||||||
snapshot.b = self.machine_st.b;
|
snapshot.b = self.machine_st.b;
|
||||||
snapshot.b0 = self.machine_st.b0;
|
snapshot.b0 = self.machine_st.b0;
|
||||||
snapshot.s = self.machine_st.s;
|
snapshot.s = self.machine_st.s.clone();
|
||||||
snapshot.tr = self.machine_st.tr;
|
snapshot.tr = self.machine_st.tr;
|
||||||
snapshot.num_of_args = self.machine_st.num_of_args;
|
snapshot.num_of_args = self.machine_st.num_of_args;
|
||||||
|
|
||||||
@@ -751,12 +803,16 @@ impl Machine {
|
|||||||
&mut self.indices,
|
&mut self.indices,
|
||||||
&mut self.policies,
|
&mut self.policies,
|
||||||
&mut self.code_repo,
|
&mut self.code_repo,
|
||||||
&mut self.prolog_stream,
|
&mut self.current_input_stream,
|
||||||
|
&mut self.current_output_stream,
|
||||||
);
|
);
|
||||||
|
|
||||||
match self.machine_st.p {
|
match self.machine_st.p {
|
||||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {}
|
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {
|
||||||
CodePtr::REPL(code_ptr, p) => self.handle_toplevel_command(code_ptr, p),
|
}
|
||||||
|
CodePtr::REPL(code_ptr, p) => {
|
||||||
|
self.handle_toplevel_command(code_ptr, p)
|
||||||
|
}
|
||||||
CodePtr::DynamicTransaction(trans_type, p) => {
|
CodePtr::DynamicTransaction(trans_type, p) => {
|
||||||
// self.code_repo.cached_query is about to be overwritten by the term expander,
|
// self.code_repo.cached_query is about to be overwritten by the term expander,
|
||||||
// so hold onto it locally and restore it after the compiler has finished.
|
// so hold onto it locally and restore it after the compiler has finished.
|
||||||
@@ -784,29 +840,37 @@ impl MachineState {
|
|||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
policies: &mut MachinePolicies,
|
policies: &mut MachinePolicies,
|
||||||
code_repo: &CodeRepo,
|
code_repo: &CodeRepo,
|
||||||
prolog_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) {
|
) {
|
||||||
match instr {
|
match instr {
|
||||||
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
|
&Line::Arithmetic(ref arith_instr) => {
|
||||||
|
self.execute_arith_instr(arith_instr)
|
||||||
|
}
|
||||||
&Line::Choice(ref choice_instr) => {
|
&Line::Choice(ref choice_instr) => {
|
||||||
self.execute_choice_instr(choice_instr, &mut policies.call_policy)
|
self.execute_choice_instr(choice_instr, &mut policies.call_policy)
|
||||||
}
|
}
|
||||||
&Line::Cut(ref cut_instr) => {
|
&Line::Cut(ref cut_instr) => {
|
||||||
self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
|
self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
|
||||||
}
|
}
|
||||||
&Line::Control(ref control_instr) => self.execute_ctrl_instr(
|
&Line::Control(ref control_instr) => {
|
||||||
|
self.execute_ctrl_instr(
|
||||||
indices,
|
indices,
|
||||||
code_repo,
|
code_repo,
|
||||||
&mut policies.call_policy,
|
&mut policies.call_policy,
|
||||||
&mut policies.cut_policy,
|
&mut policies.cut_policy,
|
||||||
prolog_stream,
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
control_instr,
|
control_instr,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
&Line::Fact(ref fact_instr) => {
|
&Line::Fact(ref fact_instr) => {
|
||||||
self.execute_fact_instr(&fact_instr);
|
self.execute_fact_instr(&fact_instr);
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
}
|
}
|
||||||
&Line::Indexing(ref indexing_instr) => self.execute_indexing_instr(&indexing_instr),
|
&Line::Indexing(ref indexing_instr) => {
|
||||||
|
self.execute_indexing_instr(&indexing_instr)
|
||||||
|
}
|
||||||
&Line::IndexedChoice(ref choice_instr) => {
|
&Line::IndexedChoice(ref choice_instr) => {
|
||||||
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
|
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
|
||||||
}
|
}
|
||||||
@@ -822,14 +886,22 @@ impl MachineState {
|
|||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
policies: &mut MachinePolicies,
|
policies: &mut MachinePolicies,
|
||||||
code_repo: &CodeRepo,
|
code_repo: &CodeRepo,
|
||||||
prolog_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) {
|
) {
|
||||||
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
||||||
Some(instr) => instr,
|
Some(instr) => instr,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
|
self.dispatch_instr(
|
||||||
|
instr.as_ref(),
|
||||||
|
indices,
|
||||||
|
policies,
|
||||||
|
code_repo,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn backtrack(&mut self) {
|
fn backtrack(&mut self) {
|
||||||
@@ -880,7 +952,8 @@ impl MachineState {
|
|||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
policies: &mut MachinePolicies,
|
policies: &mut MachinePolicies,
|
||||||
code_repo: &mut CodeRepo,
|
code_repo: &mut CodeRepo,
|
||||||
prolog_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
loop {
|
loop {
|
||||||
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
||||||
@@ -896,7 +969,14 @@ impl MachineState {
|
|||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
|
self.dispatch_instr(
|
||||||
|
instr.as_ref(),
|
||||||
|
indices,
|
||||||
|
policies,
|
||||||
|
code_repo,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail {
|
||||||
self.backtrack();
|
self.backtrack();
|
||||||
@@ -920,10 +1000,17 @@ impl MachineState {
|
|||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
policies: &mut MachinePolicies,
|
policies: &mut MachinePolicies,
|
||||||
code_repo: &mut CodeRepo,
|
code_repo: &mut CodeRepo,
|
||||||
prolog_stream: &mut PrologStream,
|
current_input_stream: &mut Stream,
|
||||||
|
current_output_stream: &mut Stream,
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
self.execute_instr(indices, policies, code_repo, prolog_stream);
|
self.execute_instr(
|
||||||
|
indices,
|
||||||
|
policies,
|
||||||
|
code_repo,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail {
|
||||||
self.backtrack();
|
self.backtrack();
|
||||||
@@ -939,7 +1026,13 @@ impl MachineState {
|
|||||||
if !instigating_instr.as_ref().is_head_instr() {
|
if !instigating_instr.as_ref().is_head_instr() {
|
||||||
let cp = self.p.local();
|
let cp = self.p.local();
|
||||||
self.run_verify_attr_interrupt(cp);
|
self.run_verify_attr_interrupt(cp);
|
||||||
} else if !self.verify_attr_stepper(indices, policies, code_repo, prolog_stream) {
|
} else if !self.verify_attr_stepper(
|
||||||
|
indices,
|
||||||
|
policies,
|
||||||
|
code_repo,
|
||||||
|
current_input_stream,
|
||||||
|
current_output_stream,
|
||||||
|
) {
|
||||||
if self.fail {
|
if self.fail {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use core::marker::PhantomData;
|
||||||
use crate::prolog::machine::raw_block::*;
|
|
||||||
|
|
||||||
|
use std::alloc;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::ops::RangeFrom;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
pub(crate) struct PartialStringTraits {}
|
|
||||||
|
|
||||||
impl RawBlockTraits for PartialStringTraits {
|
|
||||||
#[inline]
|
|
||||||
fn init_size() -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn align() -> usize {
|
|
||||||
mem::align_of::<char>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PartialString {
|
pub struct PartialString {
|
||||||
pub(super) buf: RawBlock<PartialStringTraits>,
|
buf: *const u8,
|
||||||
pub(super) tail: Addr,
|
len: usize,
|
||||||
|
_marker: PhantomData<[u8]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PartialString {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(self.len, mem::align_of::<u8>());
|
||||||
|
alloc::dealloc(self.buf as *mut u8, layout);
|
||||||
|
|
||||||
|
self.buf = ptr::null();
|
||||||
|
self.len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for PartialString {
|
impl Clone for PartialString {
|
||||||
@@ -32,17 +32,10 @@ impl Clone for PartialString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for PartialString {
|
fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
|
||||||
#[inline]
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self as *const _ == other as *const _
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scan_for_terminator(src: &str) -> usize {
|
|
||||||
let mut terminator_idx = 0;
|
let mut terminator_idx = 0;
|
||||||
|
|
||||||
for c in src.chars() {
|
for c in iter {
|
||||||
if c == '\u{0}' {
|
if c == '\u{0}' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -53,12 +46,61 @@ fn scan_for_terminator(src: &str) -> usize {
|
|||||||
terminator_idx
|
terminator_idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PStrIter {
|
||||||
|
buf: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PStrIter {
|
||||||
|
#[inline]
|
||||||
|
fn from(buf: *const u8, idx: usize) -> Self {
|
||||||
|
PStrIter {
|
||||||
|
buf: (buf as usize + idx) as *const _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PStrIter {
|
||||||
|
type Item = char;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
unsafe {
|
||||||
|
let mut byte_count = 0;
|
||||||
|
|
||||||
|
for n in 0 .. mem::size_of::<char>() {
|
||||||
|
let b = ptr::read((self.buf as usize + n) as *const u8);
|
||||||
|
|
||||||
|
if b == 0u8 {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
byte_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if byte_count == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let slice = slice::from_raw_parts(self.buf, byte_count);
|
||||||
|
let s = str::from_utf8(slice).unwrap();
|
||||||
|
|
||||||
|
if let Some(c) = s.chars().next() {
|
||||||
|
self.buf = self.buf.offset(c.len_utf8() as isize);
|
||||||
|
Some(c)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialString {
|
impl PartialString {
|
||||||
|
#[inline]
|
||||||
pub(super)
|
pub(super)
|
||||||
fn new(src: &str, h: usize) -> Option<(Self, &str)> {
|
fn new(src: &str) -> Option<(Self, &str)> {
|
||||||
let pstr = PartialString {
|
let pstr = PartialString {
|
||||||
buf: RawBlock::with_capacity(src.len() + '\u{0}'.len_utf8()),
|
buf: ptr::null_mut(),
|
||||||
tail: Addr::PStrTail(h, 0),
|
len: 0,
|
||||||
|
_marker: PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -66,22 +108,51 @@ impl PartialString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn empty() -> Self {
|
||||||
|
let mut pstr = PartialString {
|
||||||
|
buf: ptr::null(),
|
||||||
|
len: 0,
|
||||||
|
_marker: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(
|
||||||
|
'\u{0}'.len_utf8(),
|
||||||
|
mem::align_of::<u8>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
pstr.buf = alloc::alloc(layout) as *const _;
|
||||||
|
pstr.len = '\u{0}'.len_utf8();
|
||||||
|
|
||||||
|
pstr.write_terminator_at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pstr
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
|
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
|
||||||
let terminator_idx = scan_for_terminator(src);
|
let terminator_idx = scan_for_terminator(src.chars());
|
||||||
|
|
||||||
if terminator_idx == 0 {
|
if terminator_idx == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_top = self.buf.new_block(terminator_idx + '\u{0}'.len_utf8());
|
let layout = alloc::Layout::from_size_align_unchecked(
|
||||||
|
terminator_idx + '\u{0}'.len_utf8(),
|
||||||
|
mem::align_of::<u8>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.buf = alloc::alloc(layout) as *const _;
|
||||||
|
self.len = terminator_idx + '\u{0}'.len_utf8();
|
||||||
|
|
||||||
ptr::copy(
|
ptr::copy(
|
||||||
src.as_ptr(),
|
src.as_ptr(),
|
||||||
self.buf.top as *mut _,
|
self.buf as *mut _,
|
||||||
terminator_idx,
|
terminator_idx,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
|
|
||||||
self.write_terminator_at(terminator_idx);
|
self.write_terminator_at(terminator_idx);
|
||||||
|
|
||||||
Some(if terminator_idx != src.len() {
|
Some(if terminator_idx != src.len() {
|
||||||
@@ -91,30 +162,38 @@ impl PartialString {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ordinarily cloning of heap cell values is done in copy_term,
|
|
||||||
* so we rely on it to set the tail correctly. here it's set to PStrTail(0, 0),
|
|
||||||
* because we don't know its heap location. */
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn clone_from_offset(&self, n: usize) -> Self {
|
fn clone_from_offset(&self, n: usize) -> Self {
|
||||||
|
let len =
|
||||||
|
if self.len - '\u{0}'.len_utf8() > n {
|
||||||
|
self.len - n - '\u{0}'.len_utf8()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let mut pstr = PartialString {
|
let mut pstr = PartialString {
|
||||||
buf: RawBlock::with_capacity(self.len() + '\u{0}'.len_utf8()),
|
buf: ptr::null_mut(),
|
||||||
tail: Addr::PStrTail(0, 0),
|
len: len + '\u{0}'.len_utf8(),
|
||||||
|
_marker: PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let len = if self.len() > n { self.len() - n } else { 0 };
|
let layout = alloc::Layout::from_size_align_unchecked(
|
||||||
let new_top = pstr.buf.new_block(len + '\u{0}'.len_utf8());
|
len + '\u{0}'.len_utf8(),
|
||||||
|
mem::align_of::<u8>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
pstr.buf = alloc::alloc(layout);
|
||||||
|
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
ptr::copy(
|
ptr::copy(
|
||||||
(self.buf.base as usize + n) as *mut u8,
|
(self.buf as usize + n) as *const u8,
|
||||||
pstr.buf.base as *mut _,
|
pstr.buf as *mut _,
|
||||||
len,
|
len,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pstr.write_terminator_at(len);
|
pstr.write_terminator_at(len);
|
||||||
pstr.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pstr
|
pstr
|
||||||
@@ -125,37 +204,35 @@ impl PartialString {
|
|||||||
fn write_terminator_at(&mut self, index: usize) {
|
fn write_terminator_at(&mut self, index: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::write(
|
ptr::write(
|
||||||
(self.buf.base as usize + index) as *mut u8,
|
(self.buf as usize + index) as *mut u8,
|
||||||
0u8,
|
0u8,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
|
||||||
fn block_as_str(&self) -> &str {
|
PStrIter::from(self.buf, index.start)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn at_end(&self, end_n: usize) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let slice = slice::from_raw_parts(self.buf.base, self.len());
|
ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
|
||||||
str::from_utf8(slice).unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub fn as_str_from(&self, n: usize) -> &str {
|
||||||
fn tail_addr(&self) -> &Addr {
|
unsafe {
|
||||||
&self.tail
|
let slice = slice::from_raw_parts(
|
||||||
}
|
self.buf,
|
||||||
|
self.len - '\u{0}'.len_utf8(),
|
||||||
|
);
|
||||||
|
|
||||||
#[inline]
|
let s = str::from_utf8(slice).unwrap();
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.buf.top as usize - self.buf.base as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
&s[n ..]
|
||||||
pub fn truncate(&mut self, len: usize) {
|
|
||||||
if (len + self.buf.base as usize) < self.buf.top as usize {
|
|
||||||
self.buf.top = (len + self.buf.base as usize) as *const _;
|
|
||||||
self.write_terminator_at(len);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,20 +36,6 @@ impl<T: RawBlockTraits> RawBlock<T> {
|
|||||||
block
|
block
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
|
||||||
fn with_capacity(cap: usize) -> Self {
|
|
||||||
let mut block = RawBlock { size: 0,
|
|
||||||
base: ptr::null(),
|
|
||||||
top: ptr::null(),
|
|
||||||
_marker: PhantomData };
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
block.init_at_size(cap);
|
|
||||||
}
|
|
||||||
|
|
||||||
block
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn init_at_size(&mut self, cap: usize) {
|
unsafe fn init_at_size(&mut self, cap: usize) {
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
|
let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
|
||||||
|
|
||||||
@@ -86,7 +72,6 @@ impl<T: RawBlockTraits> RawBlock<T> {
|
|||||||
mem::replace(self, Self::empty_block())
|
mem::replace(self, Self::empty_block())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn free_space(&self) -> usize {
|
fn free_space(&self) -> usize {
|
||||||
debug_assert!(self.top >= self.base,
|
debug_assert!(self.top >= self.base,
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ impl Drop for Stack {
|
|||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct FramePrelude {
|
pub struct FramePrelude {
|
||||||
is_or_frame: u8,
|
|
||||||
pub num_cells: usize,
|
pub num_cells: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +61,6 @@ pub struct AndFramePrelude {
|
|||||||
|
|
||||||
pub struct AndFrame {
|
pub struct AndFrame {
|
||||||
pub prelude: AndFramePrelude,
|
pub prelude: AndFramePrelude,
|
||||||
_marker: PhantomData<Addr>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AndFrame {
|
impl AndFrame {
|
||||||
@@ -101,24 +99,6 @@ impl IndexMut<usize> for AndFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AndFrame {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let prelude_offset = prelude_size::<AndFramePrelude>();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
|
|
||||||
let ptr = ptr as usize + prelude_offset;
|
|
||||||
|
|
||||||
for idx in 0 .. self.prelude.univ_prelude.num_cells {
|
|
||||||
let index_offset = idx * mem::size_of::<Addr>();
|
|
||||||
let ptr = (ptr + index_offset) as *mut Addr;
|
|
||||||
|
|
||||||
ptr::drop_in_place(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct OrFramePrelude {
|
pub struct OrFramePrelude {
|
||||||
pub univ_prelude: FramePrelude,
|
pub univ_prelude: FramePrelude,
|
||||||
pub e: usize,
|
pub e: usize,
|
||||||
@@ -135,7 +115,6 @@ pub struct OrFramePrelude {
|
|||||||
|
|
||||||
pub struct OrFrame {
|
pub struct OrFrame {
|
||||||
pub prelude: OrFramePrelude,
|
pub prelude: OrFramePrelude,
|
||||||
_marker: PhantomData<Addr>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for OrFrame {
|
impl Index<usize> for OrFrame {
|
||||||
@@ -170,24 +149,6 @@ impl IndexMut<usize> for OrFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for OrFrame {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let prelude_offset = prelude_size::<OrFramePrelude>();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
|
|
||||||
let ptr = ptr as usize + prelude_offset;
|
|
||||||
|
|
||||||
for idx in 0 .. self.prelude.univ_prelude.num_cells {
|
|
||||||
let index_offset = idx * mem::size_of::<Addr>();
|
|
||||||
let ptr = (ptr + index_offset) as *mut Addr;
|
|
||||||
|
|
||||||
ptr::drop_in_place(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OrFrame {
|
impl OrFrame {
|
||||||
pub fn size_of(num_cells: usize) -> usize {
|
pub fn size_of(num_cells: usize) -> usize {
|
||||||
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
|
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
|
||||||
@@ -211,8 +172,6 @@ impl Stack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let and_frame = &mut *(self.buf.top as *mut AndFrame);
|
let and_frame = &mut *(self.buf.top as *mut AndFrame);
|
||||||
|
|
||||||
and_frame.prelude.univ_prelude.is_or_frame = 0;
|
|
||||||
and_frame.prelude.univ_prelude.num_cells = num_cells;
|
and_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||||
|
|
||||||
let e = self.buf.top as usize - self.buf.base as usize;
|
let e = self.buf.top as usize - self.buf.base as usize;
|
||||||
@@ -234,8 +193,6 @@ impl Stack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let or_frame = &mut *(self.buf.top as *mut OrFrame);
|
let or_frame = &mut *(self.buf.top as *mut OrFrame);
|
||||||
|
|
||||||
or_frame.prelude.univ_prelude.is_or_frame = 1;
|
|
||||||
or_frame.prelude.univ_prelude.num_cells = num_cells;
|
or_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||||
|
|
||||||
let b = self.buf.top as usize - self.buf.base as usize;
|
let b = self.buf.top as usize - self.buf.base as usize;
|
||||||
@@ -281,6 +238,7 @@ impl Stack {
|
|||||||
Stack { buf: self.buf.take(), _marker: PhantomData }
|
Stack { buf: self.buf.take(), _marker: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn truncate(&mut self, b: usize) {
|
pub fn truncate(&mut self, b: usize) {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
self.inner_truncate(mem::align_of::<Addr>());
|
self.inner_truncate(mem::align_of::<Addr>());
|
||||||
@@ -289,42 +247,14 @@ impl Stack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn inner_truncate(&mut self, b: usize) {
|
fn inner_truncate(&mut self, b: usize) {
|
||||||
let mut b = b + self.buf.base as usize;
|
let base = b + self.buf.base as usize;
|
||||||
let base = b;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
while b as *const _ < self.buf.top {
|
|
||||||
let univ_prelude = ptr::read(b as *const FramePrelude);
|
|
||||||
|
|
||||||
let offset = if univ_prelude.is_or_frame == 0 {
|
|
||||||
let frame_ptr = b as *mut AndFrame;
|
|
||||||
let frame = &mut *frame_ptr;
|
|
||||||
let size_of_frame = AndFrame::size_of(frame.prelude.univ_prelude.num_cells);
|
|
||||||
|
|
||||||
ptr::drop_in_place(frame_ptr);
|
|
||||||
|
|
||||||
b + size_of_frame
|
|
||||||
} else {
|
|
||||||
debug_assert!(univ_prelude.is_or_frame == 1);
|
|
||||||
|
|
||||||
let frame_ptr = b as *mut OrFrame;
|
|
||||||
let frame = &mut *frame_ptr;
|
|
||||||
let size_of_frame = OrFrame::size_of(frame.prelude.univ_prelude.num_cells);
|
|
||||||
|
|
||||||
ptr::drop_in_place(frame_ptr);
|
|
||||||
|
|
||||||
b + size_of_frame
|
|
||||||
};
|
|
||||||
|
|
||||||
b = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if base < self.buf.top as usize {
|
if base < self.buf.top as usize {
|
||||||
self.buf.top = base as *const _;
|
self.buf.top = base as *const _;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn drop_in_place(&mut self) {
|
pub fn drop_in_place(&mut self) {
|
||||||
self.truncate(mem::align_of::<Addr>());
|
self.truncate(mem::align_of::<Addr>());
|
||||||
|
|||||||
356
src/prolog/machine/streams.rs
Normal file
356
src/prolog/machine/streams.rs
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
use crate::prolog_parser::ast::*;
|
||||||
|
|
||||||
|
use crate::prolog::read::readline::*;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{stdin, stdout, Cursor, ErrorKind, Read, Write};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::net::TcpStream;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum StreamType {
|
||||||
|
Binary,
|
||||||
|
Text,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum EOFAction {
|
||||||
|
EOFCode,
|
||||||
|
Error,
|
||||||
|
Reset,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all these streams are closed automatically when the instance is
|
||||||
|
* dropped. */
|
||||||
|
pub enum StreamInstance {
|
||||||
|
Bytes(Cursor<Vec<u8>>),
|
||||||
|
DynReadSource(Box<dyn Read>),
|
||||||
|
File(File),
|
||||||
|
Null,
|
||||||
|
ReadlineStream(ReadlineStream),
|
||||||
|
Stdin,
|
||||||
|
Stdout,
|
||||||
|
TcpStream(TcpStream),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct WrappedStreamInstance(Rc<RefCell<StreamInstance>>);
|
||||||
|
|
||||||
|
impl WrappedStreamInstance {
|
||||||
|
#[inline]
|
||||||
|
fn new(stream_inst: StreamInstance) -> Self {
|
||||||
|
WrappedStreamInstance(Rc::new(RefCell::new(stream_inst)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for WrappedStreamInstance {
|
||||||
|
#[inline]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
Rc::ptr_eq(&self.0, &other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for WrappedStreamInstance {}
|
||||||
|
|
||||||
|
impl Hash for WrappedStreamInstance {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
let rc = &self.0;
|
||||||
|
let ptr = Rc::into_raw(rc.clone());
|
||||||
|
|
||||||
|
state.write_usize(ptr as usize);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// necessary to avoid memory leak.
|
||||||
|
let _ = Rc::from_raw(ptr);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum StreamError {
|
||||||
|
ReadFromOutputStream,
|
||||||
|
WriteToInputStream,
|
||||||
|
FlushToInputStream,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for StreamError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
StreamError::ReadFromOutputStream => {
|
||||||
|
write!(f, "attempted to read from a write-only stream")
|
||||||
|
}
|
||||||
|
StreamError::WriteToInputStream => {
|
||||||
|
write!(f, "attempted to write to a read-only stream")
|
||||||
|
}
|
||||||
|
StreamError::FlushToInputStream => {
|
||||||
|
write!(f, "attempted to flush a read-only stream")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for StreamError {}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct StreamOptions {
|
||||||
|
pub stream_type: StreamType,
|
||||||
|
pub reposition: bool,
|
||||||
|
pub alias: Option<ClauseName>,
|
||||||
|
pub eof_action: EOFAction,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StreamOptions {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
StreamOptions {
|
||||||
|
stream_type: StreamType::Text,
|
||||||
|
reposition: false,
|
||||||
|
alias: None,
|
||||||
|
eof_action: EOFAction::EOFCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Stream {
|
||||||
|
pub options: StreamOptions,
|
||||||
|
stream_inst: WrappedStreamInstance,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for Stream {
|
||||||
|
fn from(string: String) -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::Bytes(Cursor::new(string.into_bytes()))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ReadlineStream> for Stream {
|
||||||
|
fn from(rl_stream: ReadlineStream) -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::ReadlineStream(rl_stream)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&'static str> for Stream {
|
||||||
|
fn from(src: &'static str) -> Stream {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::DynReadSource(Box::new(src.as_bytes()))
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<File> for Stream {
|
||||||
|
fn from(file: File) -> Stream {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::File(file)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stream {
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn as_ptr(&self) -> *const RefCell<StreamInstance> {
|
||||||
|
let rc = self.stream_inst.0.clone();
|
||||||
|
let ptr = Rc::into_raw(rc);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// must be done to avoid memory leak.
|
||||||
|
let _ = Rc::from_raw(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn stdout() -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::Stdout
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn stdin() -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::Stdin
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn null_stream() -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(), // TODO: null_options?
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::Null
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn is_stdout(&self) -> bool {
|
||||||
|
match *self.stream_inst.0.borrow() {
|
||||||
|
StreamInstance::Stdout => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn is_stdin(&self) -> bool {
|
||||||
|
match *self.stream_inst.0.borrow() {
|
||||||
|
StreamInstance::Stdin | StreamInstance::ReadlineStream(_) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn is_input_stream(&self) -> bool {
|
||||||
|
match *self.stream_inst.0.borrow() {
|
||||||
|
StreamInstance::Stdin
|
||||||
|
| StreamInstance::TcpStream(_)
|
||||||
|
| StreamInstance::Bytes(_)
|
||||||
|
| StreamInstance::ReadlineStream(_)
|
||||||
|
| StreamInstance::DynReadSource(_)
|
||||||
|
| StreamInstance::File(_) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn is_output_stream(&self) -> bool {
|
||||||
|
match *self.stream_inst.0.borrow() {
|
||||||
|
StreamInstance::Stdout
|
||||||
|
| StreamInstance::TcpStream(_)
|
||||||
|
| StreamInstance::Bytes(_)
|
||||||
|
| StreamInstance::File(_) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for Stream {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
match *self.stream_inst.0.borrow_mut() {
|
||||||
|
StreamInstance::File(ref mut file) => {
|
||||||
|
file.read(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::TcpStream(ref mut tcp_stream) => {
|
||||||
|
tcp_stream.read(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::ReadlineStream(ref mut rl_stream) => {
|
||||||
|
rl_stream.read(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::DynReadSource(ref mut src) => {
|
||||||
|
src.read(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::Bytes(ref mut cursor) => {
|
||||||
|
cursor.read(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::Stdin => {
|
||||||
|
stdin().read(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::Stdout | StreamInstance::Null => {
|
||||||
|
Err(std::io::Error::new(
|
||||||
|
ErrorKind::PermissionDenied,
|
||||||
|
StreamError::ReadFromOutputStream,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for Stream {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
|
match *self.stream_inst.0.borrow_mut() {
|
||||||
|
StreamInstance::File(ref mut file) => {
|
||||||
|
file.write(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::TcpStream(ref mut tcp_stream) => {
|
||||||
|
tcp_stream.write(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::Bytes(ref mut cursor) => {
|
||||||
|
cursor.write(buf)
|
||||||
|
}
|
||||||
|
StreamInstance::Stdout => {
|
||||||
|
stdout().write(buf)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(std::io::Error::new(
|
||||||
|
ErrorKind::PermissionDenied,
|
||||||
|
StreamError::WriteToInputStream,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
|
match *self.stream_inst.0.borrow_mut() {
|
||||||
|
StreamInstance::File(ref mut file) => {
|
||||||
|
file.flush()
|
||||||
|
}
|
||||||
|
StreamInstance::TcpStream(ref mut tcp_stream) => {
|
||||||
|
tcp_stream.flush()
|
||||||
|
}
|
||||||
|
StreamInstance::Bytes(ref mut cursor) => {
|
||||||
|
cursor.flush()
|
||||||
|
}
|
||||||
|
StreamInstance::Stdout => {
|
||||||
|
stdout().flush()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(std::io::Error::new(
|
||||||
|
ErrorKind::PermissionDenied,
|
||||||
|
StreamError::FlushToInputStream,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: write a Seek instance.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -8,35 +8,9 @@ use crate::prolog::rug::Integer;
|
|||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::Read;
|
|
||||||
use std::iter::Rev;
|
use std::iter::Rev;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)> {
|
|
||||||
if let &mut Term::Clause(_, ref name, ref mut subterms, _) = term {
|
|
||||||
if name.as_str() == s && subterms.len() == 2 {
|
|
||||||
let snd = *subterms.pop().unwrap();
|
|
||||||
let fst = *subterms.pop().unwrap();
|
|
||||||
|
|
||||||
return Some((fst, snd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term> {
|
|
||||||
let mut terms = vec![];
|
|
||||||
|
|
||||||
while let Some((fst, snd)) = unfold_by_str_once(&mut term, s) {
|
|
||||||
terms.push(fst);
|
|
||||||
term = snd;
|
|
||||||
}
|
|
||||||
|
|
||||||
terms.push(term);
|
|
||||||
terms
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
||||||
where
|
where
|
||||||
I: DoubleEndedIterator<Item = Term>,
|
I: DoubleEndedIterator<Item = Term>,
|
||||||
@@ -53,7 +27,11 @@ where
|
|||||||
term
|
term
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_from_list(head: Box<Term>, tail: Box<Term>) -> Result<Rev<IntoIter<Term>>, ParserError> {
|
fn extract_from_list(
|
||||||
|
head: Box<Term>,
|
||||||
|
tail: Box<Term>,
|
||||||
|
) -> Result<Rev<IntoIter<Term>>, ParserError>
|
||||||
|
{
|
||||||
let mut terms = vec![*head];
|
let mut terms = vec![*head];
|
||||||
let mut tail = *tail;
|
let mut tail = *tail;
|
||||||
|
|
||||||
@@ -69,10 +47,10 @@ fn extract_from_list(head: Box<Term>, tail: Box<Term>) -> Result<Rev<IntoIter<Te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TermStream<'a, R: Read> {
|
pub struct TermStream<'a> {
|
||||||
stack: Vec<Term>,
|
stack: Vec<Term>,
|
||||||
pub(crate) wam: &'a mut Machine,
|
pub(crate) wam: &'a mut Machine,
|
||||||
parser: Parser<'a, R>,
|
parser: Parser<'a, Stream>,
|
||||||
pub(crate) flags: MachineFlags,
|
pub(crate) flags: MachineFlags,
|
||||||
term_expansion_lens: (usize, usize),
|
term_expansion_lens: (usize, usize),
|
||||||
goal_expansion_lens: (usize, usize),
|
goal_expansion_lens: (usize, usize),
|
||||||
@@ -100,7 +78,7 @@ impl ExpansionAdditionResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: Read> Drop for TermStream<'a, R> {
|
impl<'a> Drop for TermStream<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.wam.indices.in_situ_code_dir.clear();
|
self.wam.indices.in_situ_code_dir.clear();
|
||||||
self.wam.indices.in_situ_module_dir.clear();
|
self.wam.indices.in_situ_module_dir.clear();
|
||||||
@@ -110,9 +88,9 @@ impl<'a, R: Read> Drop for TermStream<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: Read> TermStream<'a, R> {
|
impl<'a> TermStream<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
src: &'a mut ParsingStream<R>,
|
src: &'a mut ParsingStream<Stream>,
|
||||||
atom_tbl: TabledData<Atom>,
|
atom_tbl: TabledData<Atom>,
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
wam: &'a mut Machine,
|
wam: &'a mut Machine,
|
||||||
@@ -326,7 +304,8 @@ impl<'a, R: Read> TermStream<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub(super) fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
|
pub(super)
|
||||||
|
fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
|
||||||
let output = PrinterOutputter::new();
|
let output = PrinterOutputter::new();
|
||||||
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
|
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
|
||||||
let mut max_var_length = 0;
|
let mut max_var_length = 0;
|
||||||
@@ -337,12 +316,16 @@ impl MachineState {
|
|||||||
|
|
||||||
printer.quoted = true;
|
printer.quoted = true;
|
||||||
printer.numbervars = true;
|
printer.numbervars = true;
|
||||||
// the purpose of the offset is to avoid clashes with variable names that might
|
|
||||||
// occur after the addresses in the expanded term are substituted with the variable
|
// the purpose of the offset is to avoid clashes with variable
|
||||||
// names in the pre-expansion term. This formula ensures that all generated "numbervars"-
|
// names that might occur after the addresses in the expanded
|
||||||
// style variable names will be longer than the keys of the var_dict, and therefore
|
// term are substituted with the variable names in the
|
||||||
// not equal to any of them.
|
// pre-expansion term. This formula ensures that all generated
|
||||||
|
// "numbervars"- style variable names will be longer than the
|
||||||
|
// keys of the var_dict, and therefore not equal to any of
|
||||||
|
// them.
|
||||||
printer.numbervars_offset = Integer::from(10).pow(max_var_length as u32) * 26;
|
printer.numbervars_offset = Integer::from(10).pow(max_var_length as u32) * 26;
|
||||||
|
printer.print_strings_as_strs = true;
|
||||||
printer.drop_toplevel_spec();
|
printer.drop_toplevel_spec();
|
||||||
|
|
||||||
printer.see_all_locs();
|
printer.see_all_locs();
|
||||||
@@ -354,8 +337,8 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset the machine, but keep the heap contents as they were.
|
// reset the machine, but keep the heap contents as they were.
|
||||||
// this prevents clashes between underscored variable names
|
// this prevents clashes between underscored variable names in the
|
||||||
// in the same query.
|
// same query.
|
||||||
fn reset_with_heap_preservation(&mut self) {
|
fn reset_with_heap_preservation(&mut self) {
|
||||||
let heap = self.heap.take();
|
let heap = self.heap.take();
|
||||||
self.reset();
|
self.reset();
|
||||||
@@ -379,13 +362,16 @@ impl MachineState {
|
|||||||
wam.code_repo.cached_query = code;
|
wam.code_repo.cached_query = code;
|
||||||
|
|
||||||
self.cp = LocalCodePtr::TopLevel(0, 0);
|
self.cp = LocalCodePtr::TopLevel(0, 0);
|
||||||
|
|
||||||
self.at_end_of_expansion = false;
|
self.at_end_of_expansion = false;
|
||||||
|
self.flags.double_quotes = DoubleQuotes::Chars;
|
||||||
|
|
||||||
self.query_stepper(
|
self.query_stepper(
|
||||||
&mut wam.indices,
|
&mut wam.indices,
|
||||||
&mut wam.policies,
|
&mut wam.policies,
|
||||||
&mut wam.code_repo,
|
&mut wam.code_repo,
|
||||||
&mut readline::input_stream(),
|
&mut readline::input_stream(),
|
||||||
|
&mut Stream::stdout(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.fail || self.at_end_of_expansion {
|
if self.fail || self.at_end_of_expansion {
|
||||||
@@ -398,6 +384,7 @@ impl MachineState {
|
|||||||
let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
|
let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
|
||||||
|
|
||||||
self.reset_with_heap_preservation();
|
self.reset_with_heap_preservation();
|
||||||
|
|
||||||
Some(output.result())
|
Some(output.result())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use indexmap::{IndexMap, IndexSet};
|
|||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::Read;
|
use std::convert::TryFrom;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -30,15 +30,15 @@ fn op_dir<'a, 'b: 'a>(from: &'b IndexSource<'a, IndexStore>) -> RefOrOwned<'a, O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CompositeIndices<'a, 'b, 'c, R: Read> {
|
struct CompositeIndices<'a, 'b, 'c> {
|
||||||
term_stream: &'b mut TermStream<'a, R>,
|
term_stream: &'b mut TermStream<'a>,
|
||||||
index_src: IndexSource<'c, IndexStore>,
|
index_src: IndexSource<'c, IndexStore>,
|
||||||
static_code_dir: Option<IndexSource<'c, CodeDir>>
|
static_code_dir: Option<IndexSource<'c, CodeDir>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, R: Read> CompositeIndices<'a, 'b, 'c, R> {
|
impl<'a, 'b, 'c> CompositeIndices<'a, 'b, 'c> {
|
||||||
fn new(
|
fn new(
|
||||||
term_stream: &'b mut TermStream<'a, R>,
|
term_stream: &'b mut TermStream<'a>,
|
||||||
index_src: IndexSource<'c, IndexStore>,
|
index_src: IndexSource<'c, IndexStore>,
|
||||||
static_code_dir: Option<IndexSource<'c, CodeDir>>,
|
static_code_dir: Option<IndexSource<'c, CodeDir>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -212,8 +212,8 @@ fn setup_op_decl(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let prec = match *terms.pop().unwrap() {
|
let prec = match *terms.pop().unwrap() {
|
||||||
Term::Constant(_, Constant::Integer(bi)) => match bi.to_usize() {
|
Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
|
||||||
Some(n) if n <= 1200 => n,
|
Ok(n) if n <= 1200 => n,
|
||||||
_ => return Err(ParserError::InconsistentEntry),
|
_ => return Err(ParserError::InconsistentEntry),
|
||||||
},
|
},
|
||||||
_ => return Err(ParserError::InconsistentEntry),
|
_ => return Err(ParserError::InconsistentEntry),
|
||||||
@@ -225,16 +225,21 @@ fn setup_op_decl(
|
|||||||
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserError>
|
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserError>
|
||||||
{
|
{
|
||||||
match term {
|
match term {
|
||||||
Term::Clause(_, ref name, ref mut terms, Some(_))
|
Term::Clause(_, ref slash, ref mut terms, Some(_))
|
||||||
if name.as_str() == "/" && terms.len() == 2 =>
|
if (slash.as_str() == "/" || slash.as_str() == "//") && terms.len() == 2 =>
|
||||||
{
|
{
|
||||||
let arity = *terms.pop().unwrap();
|
let arity = *terms.pop().unwrap();
|
||||||
let name = *terms.pop().unwrap();
|
let name = *terms.pop().unwrap();
|
||||||
|
|
||||||
let arity = arity
|
let arity = arity
|
||||||
.to_constant()
|
.to_constant()
|
||||||
.and_then(|c| c.to_integer())
|
.and_then(|c| {
|
||||||
.and_then(|n| n.to_usize())
|
match c {
|
||||||
|
Constant::Integer(n) => n.to_usize(),
|
||||||
|
Constant::Fixnum(n) => usize::try_from(n).ok(),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
.ok_or(ParserError::InvalidModuleExport)?;
|
.ok_or(ParserError::InvalidModuleExport)?;
|
||||||
|
|
||||||
let name = name
|
let name = name
|
||||||
@@ -242,7 +247,11 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
|
|||||||
.and_then(|c| c.to_atom())
|
.and_then(|c| c.to_atom())
|
||||||
.ok_or(ParserError::InvalidModuleExport)?;
|
.ok_or(ParserError::InvalidModuleExport)?;
|
||||||
|
|
||||||
|
if slash.as_str() == "/" {
|
||||||
Ok((name, arity))
|
Ok((name, arity))
|
||||||
|
} else {
|
||||||
|
Ok((name, arity + 2))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ParserError::InvalidModuleExport),
|
_ => Err(ParserError::InvalidModuleExport),
|
||||||
}
|
}
|
||||||
@@ -339,6 +348,32 @@ fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, Pars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, ParserError> {
|
||||||
|
let dbl_quotes = *terms.pop().unwrap();
|
||||||
|
|
||||||
|
match terms[0].as_ref() {
|
||||||
|
Term::Constant(_, Constant::Atom(ref name, _))
|
||||||
|
if name.as_str() == "double_quotes" => {
|
||||||
|
match dbl_quotes {
|
||||||
|
Term::Constant(_, Constant::Atom(name, _)) => {
|
||||||
|
match name.as_str() {
|
||||||
|
"atom" => Ok(DoubleQuotes::Atom),
|
||||||
|
"chars" => Ok(DoubleQuotes::Chars),
|
||||||
|
"codes" => Ok(DoubleQuotes::Codes),
|
||||||
|
_ => Err(ParserError::InvalidDoubleQuotesDecl),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Err(ParserError::InvalidDoubleQuotesDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
Err(ParserError::InvalidDoubleQuotesDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type UseModuleExport = (ModuleSource, Vec<ModuleExport>);
|
type UseModuleExport = (ModuleSource, Vec<ModuleExport>);
|
||||||
|
|
||||||
fn setup_qualified_import(
|
fn setup_qualified_import(
|
||||||
@@ -551,8 +586,8 @@ fn draw_from_term_dir_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_from_term_dir<R: Read>(
|
fn draw_from_term_dir(
|
||||||
indices: &CompositeIndices<R>,
|
indices: &CompositeIndices,
|
||||||
intra_module_term_dirs: &mut IndexMap<ClauseName, TermDirQuantum>,
|
intra_module_term_dirs: &mut IndexMap<ClauseName, TermDirQuantum>,
|
||||||
top_level_term_dirs: &mut TermDirQuantum,
|
top_level_term_dirs: &mut TermDirQuantum,
|
||||||
key: &PredicateKey,
|
key: &PredicateKey,
|
||||||
@@ -589,8 +624,8 @@ fn draw_from_term_dir<R: Read>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_declaration<'a, 'b, 'c, R: Read>(
|
fn setup_declaration<'a, 'b, 'c>(
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
mut terms: Vec<Box<Term>>,
|
mut terms: Vec<Box<Term>>,
|
||||||
line_num: usize,
|
line_num: usize,
|
||||||
@@ -620,18 +655,23 @@ fn setup_declaration<'a, 'b, 'c, R: Read>(
|
|||||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||||
Ok(Declaration::NonCountedBacktracking(name, arity))
|
Ok(Declaration::NonCountedBacktracking(name, arity))
|
||||||
}
|
}
|
||||||
|
("set_prolog_flag", 2) => {
|
||||||
|
Ok(Declaration::SetPrologFlag(setup_double_quotes(terms)?))
|
||||||
|
}
|
||||||
("multifile", 1) => {
|
("multifile", 1) => {
|
||||||
let mut term = *terms.pop().unwrap();
|
let mut term = *terms.pop().unwrap();
|
||||||
|
|
||||||
match setup_predicate_indicator(&mut term) {
|
match setup_predicate_indicator(&mut term) {
|
||||||
Ok((name, arity)) =>
|
Ok((name, arity)) => {
|
||||||
Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity))),
|
Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity)))
|
||||||
_ =>
|
}
|
||||||
|
_ => {
|
||||||
setup_scoped_predicate_indicator(&mut term)
|
setup_scoped_predicate_indicator(&mut term)
|
||||||
.map(|key| {
|
.map(|key| {
|
||||||
Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key))
|
Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
("use_module", 1) => {
|
("use_module", 1) => {
|
||||||
Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
|
Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
|
||||||
@@ -644,7 +684,9 @@ fn setup_declaration<'a, 'b, 'c, R: Read>(
|
|||||||
Err(ParserError::InconsistentEntry)
|
Err(ParserError::InconsistentEntry)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => Err(ParserError::InconsistentEntry),
|
_ => {
|
||||||
|
Err(ParserError::InconsistentEntry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -767,9 +809,9 @@ impl RelationWorker {
|
|||||||
self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
|
self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_query_term<'a, 'b, 'c, R: Read>(
|
fn to_query_term<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
term: Term,
|
term: Term,
|
||||||
) -> Result<QueryTerm, ParserError> {
|
) -> Result<QueryTerm, ParserError> {
|
||||||
match term {
|
match term {
|
||||||
@@ -843,9 +885,9 @@ impl RelationWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_query_term<'a, 'b, 'c, R: Read>(
|
fn pre_query_term<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
term: Term,
|
term: Term,
|
||||||
) -> Result<QueryTerm, ParserError> {
|
) -> Result<QueryTerm, ParserError> {
|
||||||
match term {
|
match term {
|
||||||
@@ -864,9 +906,9 @@ impl RelationWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_query<'a, 'b, 'c, R: Read>(
|
fn setup_query<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
terms: Vec<Box<Term>>,
|
terms: Vec<Box<Term>>,
|
||||||
blocks_cuts: bool,
|
blocks_cuts: bool,
|
||||||
) -> Result<Vec<QueryTerm>, ParserError> {
|
) -> Result<Vec<QueryTerm>, ParserError> {
|
||||||
@@ -917,10 +959,10 @@ impl RelationWorker {
|
|||||||
Ok(query_terms)
|
Ok(query_terms)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_hook<'a, 'b, 'c, R: Read>(
|
fn setup_hook<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
hook: CompileTimeHook,
|
hook: CompileTimeHook,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
term: Term,
|
term: Term,
|
||||||
) -> Result<CompileTimeHookCompileInfo, ParserError> {
|
) -> Result<CompileTimeHookCompileInfo, ParserError> {
|
||||||
match flatten_hook(term) {
|
match flatten_hook(term) {
|
||||||
@@ -941,9 +983,9 @@ impl RelationWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_rule<'a, 'b, 'c, R: Read>(
|
fn setup_rule<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
mut terms: Vec<Box<Term>>,
|
mut terms: Vec<Box<Term>>,
|
||||||
blocks_cuts: bool,
|
blocks_cuts: bool,
|
||||||
assume_dyn: bool,
|
assume_dyn: bool,
|
||||||
@@ -974,9 +1016,9 @@ impl RelationWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_term_to_query<'a, 'b, 'c, R: Read>(
|
fn try_term_to_query<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
terms: Vec<Box<Term>>,
|
terms: Vec<Box<Term>>,
|
||||||
blocks_cuts: bool,
|
blocks_cuts: bool,
|
||||||
) -> Result<TopLevel, ParserError> {
|
) -> Result<TopLevel, ParserError> {
|
||||||
@@ -987,10 +1029,10 @@ impl RelationWorker {
|
|||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compact_module_scoped_head<'a, 'b, 'c, R: Read>(
|
fn compact_module_scoped_head<'a, 'b, 'c>(
|
||||||
&self,
|
&self,
|
||||||
term: &mut Term,
|
term: &mut Term,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
) {
|
) {
|
||||||
let inner_term = match term {
|
let inner_term = match term {
|
||||||
Term::Clause(_, ref name, ref mut inner_terms, _)
|
Term::Clause(_, ref name, ref mut inner_terms, _)
|
||||||
@@ -1015,9 +1057,9 @@ impl RelationWorker {
|
|||||||
*term = inner_term;
|
*term = inner_term;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_term_to_tl<'a, 'b, 'c, R: Read>(
|
fn try_term_to_tl<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
term: Term,
|
term: Term,
|
||||||
blocks_cuts: bool,
|
blocks_cuts: bool,
|
||||||
) -> Result<TopLevel, ParserError> {
|
) -> Result<TopLevel, ParserError> {
|
||||||
@@ -1051,19 +1093,20 @@ impl RelationWorker {
|
|||||||
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
|
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
term =>
|
term => {
|
||||||
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num)),
|
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_terms_to_tls<'a, 'b, 'c, I, R>(
|
fn try_terms_to_tls<'a, 'b, 'c, I>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
terms: I,
|
terms: I,
|
||||||
blocks_cuts: bool,
|
blocks_cuts: bool,
|
||||||
) -> Result<VecDeque<TopLevel>, ParserError>
|
) -> Result<VecDeque<TopLevel>, ParserError>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Term>, R: Read
|
I: IntoIterator<Item = Term>
|
||||||
{
|
{
|
||||||
let mut results = VecDeque::new();
|
let mut results = VecDeque::new();
|
||||||
|
|
||||||
@@ -1074,9 +1117,9 @@ impl RelationWorker {
|
|||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_queue<'a, 'b, 'c, R: Read>(
|
fn parse_queue<'a, 'b, 'c>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indices: &mut CompositeIndices<'a, 'b, 'c, R>,
|
indices: &mut CompositeIndices<'a, 'b, 'c>,
|
||||||
) -> Result<VecDeque<TopLevel>, ParserError> {
|
) -> Result<VecDeque<TopLevel>, ParserError> {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
|
|
||||||
@@ -1090,8 +1133,7 @@ impl RelationWorker {
|
|||||||
|
|
||||||
fn absorb(&mut self, other: RelationWorker) {
|
fn absorb(&mut self, other: RelationWorker) {
|
||||||
self.queue.extend(other.queue.into_iter());
|
self.queue.extend(other.queue.into_iter());
|
||||||
self.dynamic_clauses
|
self.dynamic_clauses.extend(other.dynamic_clauses.into_iter());
|
||||||
.extend(other.dynamic_clauses.into_iter());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,8 +1141,8 @@ pub type DynamicClause = Vec<(Term, Term)>;
|
|||||||
|
|
||||||
pub type DynamicClauseMap = IndexMap<(ClauseName, usize), DynamicClause>;
|
pub type DynamicClauseMap = IndexMap<(ClauseName, usize), DynamicClause>;
|
||||||
|
|
||||||
pub struct TopLevelBatchWorker<'a, R: Read> {
|
pub struct TopLevelBatchWorker<'a> {
|
||||||
pub(crate) term_stream: TermStream<'a, R>,
|
pub(crate) term_stream: TermStream<'a>,
|
||||||
rel_worker: RelationWorker,
|
rel_worker: RelationWorker,
|
||||||
pub(crate) results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
pub(crate) results: Vec<(Predicate, VecDeque<TopLevel>)>,
|
||||||
pub(crate) dynamic_clause_map: DynamicClauseMap,
|
pub(crate) dynamic_clause_map: DynamicClauseMap,
|
||||||
@@ -1110,14 +1152,14 @@ pub struct TopLevelBatchWorker<'a, R: Read> {
|
|||||||
pub(crate) non_counted_bt_preds: IndexSet<PredicateKey>,
|
pub(crate) non_counted_bt_preds: IndexSet<PredicateKey>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
impl<'a> TopLevelBatchWorker<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
inner: &'a mut ParsingStream<R>,
|
stream: &'a mut ParsingStream<Stream>,
|
||||||
atom_tbl: TabledData<Atom>,
|
atom_tbl: TabledData<Atom>,
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
wam: &'a mut Machine,
|
wam: &'a mut Machine,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let term_stream = TermStream::new(inner, atom_tbl, flags, wam);
|
let term_stream = TermStream::new(stream, atom_tbl, flags, wam);
|
||||||
|
|
||||||
let line_num = term_stream.line_num();
|
let line_num = term_stream.line_num();
|
||||||
let col_num = term_stream.col_num();
|
let col_num = term_stream.col_num();
|
||||||
@@ -1248,7 +1290,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
TopLevel::Declaration(decl) =>
|
TopLevel::Declaration(decl) =>
|
||||||
return Ok(Some(decl)),
|
return Ok(Some(decl)),
|
||||||
TopLevel::Query(_) =>
|
TopLevel::Query(_) =>
|
||||||
return Err(SessionError::NamelessEntry),
|
return Err(SessionError::QueryCannotBeDefinedAsFact),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,52 +4,183 @@ macro_rules! interm {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! heap_str {
|
/* A simple macro to count the arguments in a variadic list
|
||||||
($s:expr) => {
|
* of token trees.
|
||||||
HeapCellValue::Addr(Addr::Str($s))
|
*/
|
||||||
};
|
macro_rules! count_tt {
|
||||||
}
|
() => { 0 };
|
||||||
|
($odd:tt $($a:tt $b:tt)*) => { (count_tt!($($a)*) << 1) | 1 };
|
||||||
macro_rules! heap_integer {
|
($($a:tt $even:tt)*) => { count_tt!($($a)*) << 1 };
|
||||||
($i:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::Integer($i)))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! heap_cell {
|
|
||||||
($i:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::HeapCell($i))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! heap_con {
|
|
||||||
($i:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con($i))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! heap_atom {
|
|
||||||
($name:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con(atom!($name)))
|
|
||||||
};
|
|
||||||
($name:expr, $tbl:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! functor {
|
macro_rules! functor {
|
||||||
|
($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
|
||||||
|
{
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
let aux_lens = [$($aux.len()),*];
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
|
||||||
|
|
||||||
|
$(
|
||||||
|
result.extend($aux.into_iter());
|
||||||
|
)*
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||||
|
{
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
|
||||||
|
{
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
let aux_lens = [$($aux.len()),*];
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
|
||||||
|
|
||||||
|
$(
|
||||||
|
result.extend($aux.into_iter());
|
||||||
|
)*
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||||
|
{
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, $fixity:expr) => (
|
||||||
|
vec![ HeapCellValue::Atom(clause_name!($name), Some($fixity)) ]
|
||||||
|
);
|
||||||
|
(clause_name($name:expr)) => (
|
||||||
|
vec![ HeapCellValue::Atom($name, None) ]
|
||||||
|
);
|
||||||
($name:expr) => (
|
($name:expr) => (
|
||||||
vec![ heap_atom!($name) ]
|
vec![ HeapCellValue::Atom(clause_name!($name), None) ]
|
||||||
);
|
);
|
||||||
($name:expr, $len:expr) => (
|
}
|
||||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None) ]
|
|
||||||
|
macro_rules! functor_term {
|
||||||
|
(aux(0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + 1))
|
||||||
|
});
|
||||||
|
(aux($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
let len: usize = $aux_lens[0 .. $e].iter().sum();
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + 1 + len))
|
||||||
|
});
|
||||||
|
(aux($h:expr, 0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1))
|
||||||
|
});
|
||||||
|
(aux($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
let len: usize = $aux_lens[0 .. $e].iter().sum();
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1 + len))
|
||||||
|
});
|
||||||
|
(addr($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
|
HeapCellValue::Addr($e)
|
||||||
);
|
);
|
||||||
($name:expr, $len:expr, [$($args:expr),*]) => (
|
(constant($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
|
from_constant!($e, $h, $arity, $aux_lens, $addendum)
|
||||||
);
|
);
|
||||||
($name:expr, $len:expr, [$($args:expr),*], $fix: expr) => (
|
(constant($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), Some($fix)), $($args),* ]
|
from_constant!($e, 0, $arity, $aux_lens, $addendum)
|
||||||
);
|
);
|
||||||
|
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
|
$e.into()
|
||||||
|
);
|
||||||
|
(integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
|
HeapCellValue::Integer(Rc::new(Integer::from($e)))
|
||||||
|
);
|
||||||
|
(clause_name($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
|
HeapCellValue::Atom($e, None)
|
||||||
|
);
|
||||||
|
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
|
HeapCellValue::Atom(clause_name!($e), None)
|
||||||
|
);
|
||||||
|
(string($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
|
||||||
|
let len: usize = $aux_lens.iter().sum();
|
||||||
|
let h = len + $arity + 1 + $addendum.h() + $h;
|
||||||
|
|
||||||
|
$addendum.put_complete_string(&$e);
|
||||||
|
|
||||||
|
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||||
|
});
|
||||||
|
(boolean($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
|
||||||
|
if $e {
|
||||||
|
functor_term!(atom("true"), $arity, $aux_lens, $addendum)
|
||||||
|
} else {
|
||||||
|
functor_term!(atom("false"), $arity, $aux_lens, $addendum)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($e:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
|
$e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! from_constant {
|
||||||
|
($e:expr, $over_h:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
match $e {
|
||||||
|
&Constant::Atom(ref name, ref op) => {
|
||||||
|
HeapCellValue::Atom(name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&Constant::Char(c) => {
|
||||||
|
HeapCellValue::Addr(Addr::Char(c))
|
||||||
|
}
|
||||||
|
&Constant::CharCode(c) => {
|
||||||
|
HeapCellValue::Addr(Addr::CharCode(c))
|
||||||
|
}
|
||||||
|
&Constant::Fixnum(n) => {
|
||||||
|
HeapCellValue::Addr(Addr::Fixnum(n))
|
||||||
|
}
|
||||||
|
&Constant::Integer(ref n) => {
|
||||||
|
HeapCellValue::Integer(n.clone())
|
||||||
|
}
|
||||||
|
&Constant::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
|
&Constant::Float(f) => {
|
||||||
|
HeapCellValue::Addr(Addr::Float(f))
|
||||||
|
}
|
||||||
|
&Constant::String(ref s) => {
|
||||||
|
let len: usize = $aux_lens.iter().sum();
|
||||||
|
let h = len + $arity + 1 + $addendum.h() + $over_h;
|
||||||
|
|
||||||
|
$addendum.put_complete_string(&s);
|
||||||
|
|
||||||
|
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||||
|
}
|
||||||
|
&Constant::Usize(u) => {
|
||||||
|
HeapCellValue::Addr(Addr::Usize(u))
|
||||||
|
}
|
||||||
|
&Constant::EmptyList => {
|
||||||
|
HeapCellValue::Addr(Addr::EmptyList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! is_atom {
|
macro_rules! is_atom {
|
||||||
@@ -94,12 +225,6 @@ macro_rules! is_nonvar {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! is_string {
|
|
||||||
($r:expr) => {
|
|
||||||
call_clause!(ClauseType::Inlined(InlinedClauseType::IsString($r)), 1, 0)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! is_var {
|
macro_rules! is_var {
|
||||||
($r:expr) => {
|
($r:expr) => {
|
||||||
call_clause!(ClauseType::Inlined(InlinedClauseType::IsVar($r)), 1, 0)
|
call_clause!(ClauseType::Inlined(InlinedClauseType::IsVar($r)), 1, 0)
|
||||||
@@ -211,12 +336,6 @@ macro_rules! dir_entry {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! in_situ_dir_entry {
|
|
||||||
($idx:expr) => {
|
|
||||||
CodePtr::Local(LocalCodePtr::InSituDirEntry($idx))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! set_code_index {
|
macro_rules! set_code_index {
|
||||||
($idx:expr, $ip:expr, $mod_name:expr) => {{
|
($idx:expr, $ip:expr, $mod_name:expr) => {{
|
||||||
let mut idx = $idx.0.borrow_mut();
|
let mut idx = $idx.0.borrow_mut();
|
||||||
@@ -238,6 +357,7 @@ macro_rules! index_store {
|
|||||||
in_situ_module_dir: ModuleStubDir::new(),
|
in_situ_module_dir: ModuleStubDir::new(),
|
||||||
op_dir: $op_dir,
|
op_dir: $op_dir,
|
||||||
modules: $modules,
|
modules: $modules,
|
||||||
|
stream_aliases: StreamAliasDir::new(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,27 +6,16 @@ use crate::prolog::forms::*;
|
|||||||
use crate::prolog::iterators::*;
|
use crate::prolog::iterators::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::MachineState;
|
use crate::prolog::machine::machine_state::MachineState;
|
||||||
|
use crate::prolog::machine::streams::Stream;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||||
|
|
||||||
impl<'a> TermRef<'a> {
|
pub type PrologStream = ParsingStream<Stream>;
|
||||||
fn as_addr(&self, h: usize) -> Addr {
|
|
||||||
match self {
|
|
||||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h),
|
|
||||||
&TermRef::Cons(..) => Addr::HeapCell(h),
|
|
||||||
&TermRef::Constant(_, _, c) => Addr::Con(c.clone()),
|
|
||||||
&TermRef::Clause(..) => Addr::Str(h),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type PrologStream = ParsingStream<Box<dyn Read>>;
|
|
||||||
|
|
||||||
pub mod readline {
|
pub mod readline {
|
||||||
use prolog_parser::ast::*;
|
use crate::prolog::machine::streams::Stream;
|
||||||
use crate::prolog::rustyline::error::ReadlineError;
|
use crate::prolog::rustyline::error::ReadlineError;
|
||||||
use crate::prolog::rustyline::{Cmd, Editor, KeyPress};
|
use crate::prolog::rustyline::{Cmd, Editor, KeyPress};
|
||||||
use std::io::{Cursor, Read};
|
use std::io::{Cursor, Read};
|
||||||
@@ -52,10 +41,10 @@ pub mod readline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ReadlineStream {
|
impl ReadlineStream {
|
||||||
fn input_stream(pending_input: String) -> Self {
|
pub fn input_stream(pending_input: String) -> Stream {
|
||||||
let mut rl = Editor::<()>::new();
|
let mut rl = Editor::<()>::new();
|
||||||
rl.bind_sequence(KeyPress::Tab, Cmd::Insert(1, "\t".to_string()));
|
rl.bind_sequence(KeyPress::Tab, Cmd::Insert(1, "\t".to_string()));
|
||||||
ReadlineStream { rl, pending_input: Cursor::new(pending_input) }
|
Stream::from(ReadlineStream { rl, pending_input: Cursor::new(pending_input) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_readline(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
fn call_readline(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
@@ -93,15 +82,14 @@ pub mod readline {
|
|||||||
result => {
|
result => {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn input_stream() -> crate::PrologStream {
|
pub fn input_stream() -> Stream {
|
||||||
let reader: Box<dyn Read> = Box::new(ReadlineStream::input_stream(String::from("")));
|
let input_stream = ReadlineStream::input_stream(String::from(""));
|
||||||
parsing_stream(reader)
|
Stream::from(input_stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,24 +107,17 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_stub_addr(machine_st: &mut MachineState) {
|
#[inline]
|
||||||
let h = machine_st.heap.h();
|
pub(crate)
|
||||||
machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
|
||||||
|
let term_writer = TermWriter::new(machine_st);
|
||||||
|
term_writer.write_term_to_heap(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modify_head_of_queue(
|
struct TermWriter<'a> {
|
||||||
machine_st: &mut MachineState,
|
machine_st: &'a mut MachineState,
|
||||||
queue: &mut SubtermDeque,
|
queue: SubtermDeque,
|
||||||
term: TermRef,
|
var_dict: HeapVarDict,
|
||||||
h: usize,
|
|
||||||
) {
|
|
||||||
if let Some((arity, site_h)) = queue.pop_front() {
|
|
||||||
machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h));
|
|
||||||
|
|
||||||
if arity > 1 {
|
|
||||||
queue.push_front((arity - 1, site_h + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TermWriteResult {
|
pub struct TermWriteResult {
|
||||||
@@ -144,76 +125,135 @@ pub struct TermWriteResult {
|
|||||||
pub(crate) var_dict: HeapVarDict,
|
pub(crate) var_dict: HeapVarDict,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
|
impl<'a> TermWriter<'a> {
|
||||||
let heap_loc = machine_st.heap.h();
|
#[inline]
|
||||||
|
fn new(machine_st: &'a mut MachineState) -> Self {
|
||||||
|
TermWriter {
|
||||||
|
machine_st,
|
||||||
|
queue: SubtermDeque::new(),
|
||||||
|
var_dict: HeapVarDict::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut queue = SubtermDeque::new();
|
#[inline]
|
||||||
let mut var_dict = HeapVarDict::new();
|
fn modify_head_of_queue(&mut self, term: &TermRef<'a>, h: usize) {
|
||||||
|
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||||
|
self.machine_st.heap[site_h] =
|
||||||
|
HeapCellValue::Addr(self.term_as_addr(term, h));
|
||||||
|
|
||||||
|
if arity > 1 {
|
||||||
|
self.queue.push_front((arity - 1, site_h + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn push_stub_addr(&mut self) {
|
||||||
|
let h = self.machine_st.heap.h();
|
||||||
|
self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn term_as_addr(&mut self, term: &TermRef<'a>, h: usize) -> Addr {
|
||||||
|
match term {
|
||||||
|
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
|
||||||
|
Addr::HeapCell(h)
|
||||||
|
}
|
||||||
|
&TermRef::Cons(..) => {
|
||||||
|
Addr::HeapCell(h)
|
||||||
|
}
|
||||||
|
&TermRef::Constant(_, _, c) => {
|
||||||
|
self.machine_st.heap.put_constant(c.clone())
|
||||||
|
}
|
||||||
|
&TermRef::Clause(..) => {
|
||||||
|
Addr::Str(h)
|
||||||
|
}
|
||||||
|
&TermRef::PartialString(..) => {
|
||||||
|
Addr::PStrLocation(h, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_term_to_heap(mut self, term: &'a Term) -> TermWriteResult {
|
||||||
|
let heap_loc = self.machine_st.heap.h();
|
||||||
|
|
||||||
for term in breadth_first_iter(term, true) {
|
for term in breadth_first_iter(term, true) {
|
||||||
let h = machine_st.heap.h();
|
let h = self.machine_st.heap.h();
|
||||||
|
|
||||||
match &term {
|
match &term {
|
||||||
&TermRef::Cons(lvl, ..) => {
|
&TermRef::Cons(lvl, ..) => {
|
||||||
queue.push_back((2, h + 1));
|
self.queue.push_back((2, h + 1));
|
||||||
machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
self.machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
|
|
||||||
push_stub_addr(machine_st);
|
self.push_stub_addr();
|
||||||
push_stub_addr(machine_st);
|
self.push_stub_addr();
|
||||||
|
|
||||||
if let Level::Root = lvl {
|
if let Level::Root = lvl {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&TermRef::Clause(lvl, _, ref ct, subterms) => {
|
&TermRef::Clause(lvl, _, ref ct, subterms) => {
|
||||||
queue.push_back((subterms.len(), h + 1));
|
self.queue.push_back((subterms.len(), h + 1));
|
||||||
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
|
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
|
||||||
|
|
||||||
machine_st.heap.push(named);
|
self.machine_st.heap.push(named);
|
||||||
|
|
||||||
for _ in 0..subterms.len() {
|
for _ in 0..subterms.len() {
|
||||||
push_stub_addr(machine_st);
|
self.push_stub_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Level::Root = lvl {
|
if let Level::Root = lvl {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
|
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) |
|
||||||
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
|
|
||||||
}
|
|
||||||
&TermRef::Var(Level::Root, ..) => {
|
&TermRef::Var(Level::Root, ..) => {
|
||||||
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
|
let addr = self.term_as_addr(&term, h);
|
||||||
|
self.machine_st.heap.push(HeapCellValue::Addr(addr));
|
||||||
}
|
}
|
||||||
&TermRef::AnonVar(_) => {
|
&TermRef::AnonVar(_) => {
|
||||||
if let Some((arity, site_h)) = queue.pop_front() {
|
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||||
if arity > 1 {
|
if arity > 1 {
|
||||||
queue.push_front((arity - 1, site_h + 1));
|
self.queue.push_front((arity - 1, site_h + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
&TermRef::PartialString(lvl, _, ref pstr, tail) => {
|
||||||
|
if tail.is_some() {
|
||||||
|
self.machine_st.heap.allocate_pstr(&pstr);
|
||||||
|
} else {
|
||||||
|
self.machine_st.heap.put_complete_string(&pstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Level::Root = lvl {
|
||||||
|
} else if tail.is_some() {
|
||||||
|
let h = self.machine_st.heap.h();
|
||||||
|
self.queue.push_back((1, h - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
&TermRef::Var(_, _, ref var) => {
|
&TermRef::Var(_, _, ref var) => {
|
||||||
if let Some((arity, site_h)) = queue.pop_front() {
|
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||||
if let Some(addr) = var_dict.get(var).cloned() {
|
if let Some(addr) = self.var_dict.get(var).cloned() {
|
||||||
machine_st.heap[site_h] = HeapCellValue::Addr(addr);
|
self.machine_st.heap[site_h] = HeapCellValue::Addr(addr);
|
||||||
} else {
|
} else {
|
||||||
var_dict.insert(var.clone(), Addr::HeapCell(site_h));
|
self.var_dict.insert(var.clone(), Addr::HeapCell(site_h));
|
||||||
}
|
}
|
||||||
|
|
||||||
if arity > 1 {
|
if arity > 1 {
|
||||||
queue.push_front((arity - 1, site_h + 1));
|
self.queue.push_front((arity - 1, site_h + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
modify_head_of_queue(machine_st, &mut queue, term, h);
|
self.modify_head_of_queue(&term, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
TermWriteResult { heap_loc, var_dict }
|
TermWriteResult { heap_loc, var_dict: self.var_dict }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ pub trait CompilationTarget<'a> {
|
|||||||
fn to_void(_: usize) -> Self;
|
fn to_void(_: usize) -> Self;
|
||||||
fn is_void_instr(&self) -> bool;
|
fn is_void_instr(&self) -> bool;
|
||||||
|
|
||||||
|
fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self;
|
||||||
|
|
||||||
fn incr_void_instr(&mut self);
|
fn incr_void_instr(&mut self);
|
||||||
|
|
||||||
fn constant_subterm(_: Constant) -> Self;
|
fn constant_subterm(_: Constant) -> Self;
|
||||||
@@ -62,6 +64,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self {
|
||||||
|
FactInstruction::GetPartialString(lvl, string, r, has_tail)
|
||||||
|
}
|
||||||
|
|
||||||
fn incr_void_instr(&mut self) {
|
fn incr_void_instr(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
&mut FactInstruction::UnifyVoid(ref mut incr) => *incr += 1,
|
&mut FactInstruction::UnifyVoid(ref mut incr) => *incr += 1,
|
||||||
@@ -117,6 +123,10 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
|
|||||||
QueryInstruction::PutList(lvl, reg)
|
QueryInstruction::PutList(lvl, reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self {
|
||||||
|
QueryInstruction::PutPartialString(lvl, string, r, has_tail)
|
||||||
|
}
|
||||||
|
|
||||||
fn to_void(subterms: usize) -> Self {
|
fn to_void(subterms: usize) -> Self {
|
||||||
QueryInstruction::SetVoid(subterms)
|
QueryInstruction::SetVoid(subterms)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,26 +24,30 @@
|
|||||||
% make '$compile_batch', a system routine, callable.
|
% make '$compile_batch', a system routine, callable.
|
||||||
'$$compile_batch' :- '$compile_batch'.
|
'$$compile_batch' :- '$compile_batch'.
|
||||||
|
|
||||||
'$instruction_match'([Item], []) :-
|
'$instruction_match'(Term, VarList) :-
|
||||||
( atom(Item) -> !,
|
( var(Term) ->
|
||||||
|
throw(error(instantiation_error, repl/0))
|
||||||
|
;
|
||||||
|
Term = [Item] -> !,
|
||||||
|
( atom(Item) ->
|
||||||
( Item == user ->
|
( Item == user ->
|
||||||
catch('$$compile_batch', E, '$print_exception_with_check'(E))
|
catch('$$compile_batch', E, '$print_exception_with_check'(E))
|
||||||
; consult(Item)
|
; consult(Item)
|
||||||
)
|
)
|
||||||
; !,
|
;
|
||||||
catch(throw(error(type_error(atom, Item), repl/0)),
|
catch(throw(error(type_error(atom, Item), repl/0)),
|
||||||
E,
|
E,
|
||||||
'$print_exception_with_check'(E))
|
'$print_exception_with_check'(E))
|
||||||
|
)
|
||||||
|
;
|
||||||
|
'$submit_query_and_print_results'(Term, VarList)
|
||||||
).
|
).
|
||||||
'$instruction_match'(Term, VarList) :-
|
|
||||||
'$submit_query_and_print_results'(Term, VarList),
|
|
||||||
!.
|
|
||||||
|
|
||||||
'$submit_query_and_print_results'(Term0, VarList) :-
|
'$submit_query_and_print_results'(Term0, VarList) :-
|
||||||
( expand_goals(Term0, Term) -> true
|
( expand_goals(Term0, Term) -> true
|
||||||
; Term0 = Term
|
; Term0 = Term
|
||||||
),
|
),
|
||||||
( '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList),
|
( '$get_b_value'(B), write(' '), call(Term), '$write_eqs_and_read_input'(B, VarList),
|
||||||
!
|
!
|
||||||
% clear attribute goal lists, which may be populated by
|
% clear attribute goal lists, which may be populated by
|
||||||
% copy_term/3 prior to failure.
|
% copy_term/3 prior to failure.
|
||||||
@@ -57,34 +61,78 @@
|
|||||||
_,
|
_,
|
||||||
false),
|
false),
|
||||||
( EqPrec < FPrec -> true
|
( EqPrec < FPrec -> true
|
||||||
|
; '$quoted_token'(F) -> true
|
||||||
; EqPrec == FPrec,
|
; EqPrec == FPrec,
|
||||||
memberchk(EqSpec, [fx,xfx,yfx])
|
memberchk(EqSpec, [fx,xfx,yfx])
|
||||||
).
|
).
|
||||||
|
|
||||||
'$write_goal'(G, VarList) :-
|
'$fabricate_var_name'(VarName, N) :-
|
||||||
|
char_code('A', AC),
|
||||||
|
LN is N mod 26 + AC,
|
||||||
|
char_code(LC, LN),
|
||||||
|
NN is N // 26,
|
||||||
|
( NN =:= 0 ->
|
||||||
|
atom_chars(VarName, ['_', LC])
|
||||||
|
; number_chars(NN, NNChars),
|
||||||
|
atom_chars(VarName, ['_', LC | NNChars])
|
||||||
|
).
|
||||||
|
|
||||||
|
'$var_list_contains_name'([VarName = _ | VarList], VarName0) :-
|
||||||
|
( VarName == VarName0 -> true
|
||||||
|
; '$var_list_contains_name'(VarList, VarName0)
|
||||||
|
).
|
||||||
|
|
||||||
|
'$var_list_contains_variable'([_ = Var | VarList], Var0) :-
|
||||||
|
( Var == Var0 -> true
|
||||||
|
; '$var_list_contains_variable'(VarList, Var0)
|
||||||
|
).
|
||||||
|
|
||||||
|
'$make_new_var_name'(V, VarName, N, N1, VarList) :-
|
||||||
|
'$fabricate_var_name'(VarName0, N),
|
||||||
|
( '$var_list_contains_name'(VarList, VarName0) ->
|
||||||
|
N0 is N + 1,
|
||||||
|
'$make_new_var_name'(V, VarName, N0, N1, VarList)
|
||||||
|
; VarName = VarName0,
|
||||||
|
N1 is N + 1
|
||||||
|
).
|
||||||
|
|
||||||
|
'$extend_var_list'(Value, VarList, NewVarList) :-
|
||||||
|
term_variables(Value, Vars),
|
||||||
|
'$extend_var_list_'(Vars, 0, VarList, NewVarList).
|
||||||
|
|
||||||
|
'$extend_var_list_'([], N, VarList, VarList).
|
||||||
|
'$extend_var_list_'([V|Vs], N, VarList, NewVarList) :-
|
||||||
|
( '$var_list_contains_variable'(VarList, V) ->
|
||||||
|
'$extend_var_list_'(Vs, N, VarList, NewVarList)
|
||||||
|
; '$make_new_var_name'(V, VarName, N, N1, VarList),
|
||||||
|
NewVarList = [VarName = V | NewVarList0],
|
||||||
|
'$extend_var_list_'(Vs, N1, VarList, NewVarList0)
|
||||||
|
).
|
||||||
|
|
||||||
|
'$write_goal'(G, VarList, MaxDepth) :-
|
||||||
( G = (Var = Value) ->
|
( G = (Var = Value) ->
|
||||||
write(Var),
|
write(Var),
|
||||||
write(' = '),
|
write(' = '),
|
||||||
( '$needs_bracketing'(Value, (=)) ->
|
( '$needs_bracketing'(Value, (=)) ->
|
||||||
write('('),
|
write('('),
|
||||||
write_term(Value, [quoted(true), variable_names(VarList)]),
|
write_term(Value, [quoted(true), variable_names(VarList), max_depth(MaxDepth)]),
|
||||||
write(')')
|
write(')')
|
||||||
; write_term(Value, [quoted(true), variable_names(VarList)])
|
; write_term(Value, [quoted(true), variable_names(VarList), max_depth(MaxDepth)])
|
||||||
)
|
)
|
||||||
; G == [] ->
|
; G == [] ->
|
||||||
write('true')
|
write('true')
|
||||||
; write_term(G, [quoted(true), variable_names(VarList)])
|
; write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth)])
|
||||||
).
|
).
|
||||||
|
|
||||||
'$write_last_goal'(G, VarList) :-
|
'$write_last_goal'(G, VarList, MaxDepth) :-
|
||||||
( G = (Var = Value) ->
|
( G = (Var = Value) ->
|
||||||
write(Var),
|
write(Var),
|
||||||
write(' = '),
|
write(' = '),
|
||||||
( '$needs_bracketing'(Value, (=)) ->
|
( '$needs_bracketing'(Value, (=)) ->
|
||||||
write('('),
|
write('('),
|
||||||
write_term(Value, [quoted(true), variable_names(VarList)]),
|
write_term(Value, [quoted(true), variable_names(VarList), max_depth(MaxDepth)]),
|
||||||
write(')')
|
write(')')
|
||||||
; write_term(Value, [quoted(true), variable_names(VarList)]),
|
; write_term(Value, [quoted(true), variable_names(VarList), max_depth(MaxDepth)]),
|
||||||
( '$trailing_period_is_ambiguous'(Value) ->
|
( '$trailing_period_is_ambiguous'(Value) ->
|
||||||
write(' ')
|
write(' ')
|
||||||
; true
|
; true
|
||||||
@@ -92,16 +140,16 @@
|
|||||||
)
|
)
|
||||||
; G == [] ->
|
; G == [] ->
|
||||||
write('true')
|
write('true')
|
||||||
; write_term(G, [quoted(true), variable_names(VarList)])
|
; write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth)])
|
||||||
).
|
).
|
||||||
|
|
||||||
'$write_eq'((G1, G2), VarList) :-
|
'$write_eq'((G1, G2), VarList, MaxDepth) :-
|
||||||
!,
|
!,
|
||||||
'$write_goal'(G1, VarList),
|
'$write_goal'(G1, VarList, MaxDepth),
|
||||||
write(', '),
|
write(', '),
|
||||||
'$write_eq'(G2, VarList).
|
'$write_eq'(G2, VarList, MaxDepth).
|
||||||
'$write_eq'(G, VarList) :-
|
'$write_eq'(G, VarList, MaxDepth) :-
|
||||||
'$write_last_goal'(G, VarList).
|
'$write_last_goal'(G, VarList, MaxDepth).
|
||||||
|
|
||||||
'$graphic_token_char'(C) :-
|
'$graphic_token_char'(C) :-
|
||||||
memberchk(C, ['#', '$', '&', '*', '+', '-', '.', ('/'), ':',
|
memberchk(C, ['#', '$', '&', '*', '+', '-', '.', ('/'), ':',
|
||||||
@@ -118,27 +166,52 @@
|
|||||||
'$graphic_token_char'(Char).
|
'$graphic_token_char'(Char).
|
||||||
|
|
||||||
'$write_eqs_and_read_input'(B, VarList) :-
|
'$write_eqs_and_read_input'(B, VarList) :-
|
||||||
sort(VarList, SortedVarList),
|
'$extend_var_list'(VarList, VarList, NewVarList),
|
||||||
|
sort(NewVarList, SortedVarList),
|
||||||
'$get_b_value'(B0),
|
'$get_b_value'(B0),
|
||||||
'$gather_goals'(SortedVarList, VarList, Goals),
|
'$gather_goals'(SortedVarList, SortedVarList, Goals),
|
||||||
( B0 == B ->
|
( B0 == B ->
|
||||||
( Goals == [] ->
|
( Goals == [] ->
|
||||||
write('true.'), nl
|
write('true.'), nl
|
||||||
; thread_goals(Goals, ThreadedGoals, (',')),
|
; thread_goals(Goals, ThreadedGoals, (',')),
|
||||||
'$write_eq'(ThreadedGoals, VarList),
|
'$write_eq'(ThreadedGoals, NewVarList, 20),
|
||||||
write('.'),
|
write('.'),
|
||||||
nl
|
nl
|
||||||
)
|
)
|
||||||
; thread_goals(Goals, ThreadedGoals, (',')),
|
; thread_goals(Goals, ThreadedGoals, (',')),
|
||||||
'$write_eq'(ThreadedGoals, VarList),
|
'$write_eq'(ThreadedGoals, NewVarList, 20),
|
||||||
'$raw_input_read_char'(C),
|
'$read_input'(ThreadedGoals, NewVarList)
|
||||||
( C == (';'), !,
|
|
||||||
write(' ;'), nl, false
|
|
||||||
; C == ('.'), !,
|
|
||||||
write(' ...'), nl
|
|
||||||
)
|
|
||||||
).
|
).
|
||||||
|
|
||||||
|
'$read_input'(ThreadedGoals, NewVarList) :-
|
||||||
|
'$raw_input_read_char'(C),
|
||||||
|
( C == w ->
|
||||||
|
nl,
|
||||||
|
write(' '),
|
||||||
|
'$write_eq'(ThreadedGoals, NewVarList, 0),
|
||||||
|
'$read_input'(ThreadedGoals, NewVarList)
|
||||||
|
; C == p ->
|
||||||
|
nl,
|
||||||
|
write(' '),
|
||||||
|
'$write_eq'(ThreadedGoals, NewVarList, 20),
|
||||||
|
'$read_input'(ThreadedGoals, NewVarList)
|
||||||
|
; C == (';') ->
|
||||||
|
nl, write('; '), false
|
||||||
|
; C == h ->
|
||||||
|
'$help_message',
|
||||||
|
'$read_input'(ThreadedGoals, NewVarList)
|
||||||
|
; C == '.',
|
||||||
|
nl, write('; ...'), nl
|
||||||
|
).
|
||||||
|
|
||||||
|
'$help_message' :-
|
||||||
|
nl, nl,
|
||||||
|
write('SPACE, "n" or ";": next solution, if any\n'),
|
||||||
|
write('".": stop enumeration\n'),
|
||||||
|
write('"h": display this help message\n'),
|
||||||
|
write('"w": write terms without depth limit\n'),
|
||||||
|
write('"p": print terms with depth limit\n\n').
|
||||||
|
|
||||||
'$gather_query_vars'([_ = Var | Vars], QueryVars) :-
|
'$gather_query_vars'([_ = Var | Vars], QueryVars) :-
|
||||||
( var(Var) ->
|
( var(Var) ->
|
||||||
QueryVars = [Var | QueryVars1],
|
QueryVars = [Var | QueryVars1],
|
||||||
@@ -153,10 +226,8 @@
|
|||||||
).
|
).
|
||||||
|
|
||||||
'$gather_goals'([], VarList, Goals) :-
|
'$gather_goals'([], VarList, Goals) :-
|
||||||
'$get_attr_var_queue_beyond'(0, AttrVars),
|
|
||||||
'$gather_query_vars'(VarList, QueryVars),
|
'$gather_query_vars'(VarList, QueryVars),
|
||||||
'$call_attribute_goals'(QueryVars, AttrVars),
|
copy_term(QueryVars, QueryVars, Goals).
|
||||||
'$fetch_attribute_goals'(Goals).
|
|
||||||
'$gather_goals'([Var = Value | Pairs], VarList, Goals) :-
|
'$gather_goals'([Var = Value | Pairs], VarList, Goals) :-
|
||||||
( ( nonvar(Value)
|
( ( nonvar(Value)
|
||||||
; '$is_a_different_variable'(Pairs, Value)
|
; '$is_a_different_variable'(Pairs, Value)
|
||||||
@@ -167,7 +238,7 @@
|
|||||||
).
|
).
|
||||||
|
|
||||||
'$print_exception'(E) :-
|
'$print_exception'(E) :-
|
||||||
write_term('caught: ', [quoted(false)]),
|
write_term('caught: ', [quoted(false), max_depth(20)]),
|
||||||
writeq(E),
|
writeq(E),
|
||||||
nl.
|
nl.
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,13 @@ impl fmt::Display for FactInstruction {
|
|||||||
&FactInstruction::GetConstant(lvl, ref constant, ref r) => {
|
&FactInstruction::GetConstant(lvl, ref constant, ref r) => {
|
||||||
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num())
|
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num())
|
||||||
}
|
}
|
||||||
&FactInstruction::GetList(lvl, ref r) => write!(f, "get_list {}{}", lvl, r.reg_num()),
|
&FactInstruction::GetList(lvl, ref r) => {
|
||||||
|
write!(f, "get_list {}{}", lvl, r.reg_num())
|
||||||
|
}
|
||||||
|
&FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => {
|
||||||
|
write!(f, "get_partial_string({}, {}, {}, {})",
|
||||||
|
lvl, s, r, has_tail)
|
||||||
|
}
|
||||||
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
|
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
|
||||||
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
|
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
|
||||||
}
|
}
|
||||||
@@ -86,7 +92,13 @@ impl fmt::Display for QueryInstruction {
|
|||||||
&QueryInstruction::PutConstant(lvl, ref constant, ref r) => {
|
&QueryInstruction::PutConstant(lvl, ref constant, ref r) => {
|
||||||
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num())
|
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num())
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutList(lvl, ref r) => write!(f, "put_list {}{}", lvl, r.reg_num()),
|
&QueryInstruction::PutList(lvl, ref r) => {
|
||||||
|
write!(f, "put_list {}{}", lvl, r.reg_num())
|
||||||
|
}
|
||||||
|
&QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => {
|
||||||
|
write!(f, "put_partial_string({}, {}, {}, {})",
|
||||||
|
lvl, s, r, has_tail)
|
||||||
|
}
|
||||||
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) => {
|
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) => {
|
||||||
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r)
|
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r)
|
||||||
}
|
}
|
||||||
@@ -143,6 +155,10 @@ impl fmt::Display for HeapCellValue {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
|
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
|
||||||
|
&HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
|
||||||
|
&HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
|
||||||
|
&HeapCellValue::Integer(ref n) => write!(f, "{}", n),
|
||||||
|
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
|
||||||
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
||||||
f,
|
f,
|
||||||
"{}/{} (op, priority: {}, spec: {})",
|
"{}/{} (op, priority: {}, spec: {})",
|
||||||
@@ -154,8 +170,16 @@ impl fmt::Display for HeapCellValue {
|
|||||||
&HeapCellValue::NamedStr(arity, ref name, None) => {
|
&HeapCellValue::NamedStr(arity, ref name, None) => {
|
||||||
write!(f, "{}/{}", name.as_str(), arity)
|
write!(f, "{}/{}", name.as_str(), arity)
|
||||||
}
|
}
|
||||||
&HeapCellValue::PartialString(ref pstr) => {
|
&HeapCellValue::PartialString(ref pstr, has_tail) => {
|
||||||
write!(f, "pstr ( buf: {}, tail: {} )", pstr.block_as_str(), pstr.tail_addr())
|
write!(
|
||||||
|
f,
|
||||||
|
"pstr ( buf: \"{}\", has_tail({}) )",
|
||||||
|
pstr.as_str_from(0),
|
||||||
|
has_tail,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(ref stream) => {
|
||||||
|
write!(f, "$stream({})", stream.as_ptr() as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,15 +199,21 @@ impl fmt::Display for DBRef {
|
|||||||
impl fmt::Display for Addr {
|
impl fmt::Display for Addr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
&Addr::Char(c) => write!(f, "Addr::Char({})", c),
|
||||||
|
&Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c),
|
||||||
|
&Addr::EmptyList => write!(f, "Addr::EmptyList"),
|
||||||
|
&Addr::Fixnum(n) => write!(f, "Addr::Fixnum({})", n),
|
||||||
|
&Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
|
||||||
|
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
|
||||||
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
||||||
&Addr::DBRef(ref db_ref) => write!(f, "Addr::DBRef({})", db_ref),
|
|
||||||
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
||||||
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
||||||
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
||||||
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
||||||
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
||||||
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
||||||
&Addr::PStrTail(h, n) => write!(f, "Addr::PStrTail({}, {})", h, n),
|
&Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
|
||||||
|
&Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,14 +289,18 @@ impl fmt::Display for IndexingInstruction {
|
|||||||
impl fmt::Display for SessionError {
|
impl fmt::Display for SessionError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&SessionError::CannotOverwriteBuiltIn(ref msg) => write!(f, "cannot overwrite {}", msg),
|
&SessionError::ExistenceError(ref err) => {
|
||||||
|
write!(f, "{}", err)
|
||||||
|
}
|
||||||
|
&SessionError::CannotOverwriteBuiltIn(ref msg) => {
|
||||||
|
write!(f, "cannot overwrite {}", msg)
|
||||||
|
}
|
||||||
&SessionError::CannotOverwriteImport(ref msg) => {
|
&SessionError::CannotOverwriteImport(ref msg) => {
|
||||||
write!(f, "cannot overwrite import {}", msg)
|
write!(f, "cannot overwrite import {}", msg)
|
||||||
}
|
}
|
||||||
&SessionError::InvalidFileName(ref filename) => {
|
&SessionError::InvalidFileName(ref filename) => {
|
||||||
write!(f, "filename {} is invalid", filename)
|
write!(f, "filename {} is invalid", filename)
|
||||||
}
|
}
|
||||||
&SessionError::ModuleNotFound => write!(f, "module not found."),
|
|
||||||
&SessionError::ModuleDoesNotContainExport(ref module, ref key) => {
|
&SessionError::ModuleDoesNotContainExport(ref module, ref key) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
@@ -282,7 +316,44 @@ impl fmt::Display for SessionError {
|
|||||||
&SessionError::NamelessEntry => {
|
&SessionError::NamelessEntry => {
|
||||||
write!(f, "the predicate head is not an atom or clause.")
|
write!(f, "the predicate head is not an atom or clause.")
|
||||||
}
|
}
|
||||||
&SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()),
|
&SessionError::ParserError(ref e) => {
|
||||||
|
write!(f, "syntax_error({})", e.as_str())
|
||||||
|
}
|
||||||
|
&SessionError::QueryCannotBeDefinedAsFact => {
|
||||||
|
write!(f, "queries cannot be defined as facts.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ExistenceError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
&ExistenceError::Module(ref module_name) => {
|
||||||
|
write!(f, "the module {} does not exist", module_name)
|
||||||
|
}
|
||||||
|
&ExistenceError::Procedure(ref name, arity) => {
|
||||||
|
write!(f, "the procedure {}/{} does not exist", name, arity)
|
||||||
|
}
|
||||||
|
&ExistenceError::SourceSink(ref module_source) => {
|
||||||
|
write!(f, "the source/sink {} does not exist", module_source)
|
||||||
|
}
|
||||||
|
&ExistenceError::Stream(ref addr) => {
|
||||||
|
write!(f, "the stream at {} does not exist", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ModuleSource {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
&ModuleSource::File(ref file) => {
|
||||||
|
write!(f, "at the file {}", file)
|
||||||
|
}
|
||||||
|
&ModuleSource::Library(ref library) => {
|
||||||
|
write!(f, "at library({})", library)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,6 +376,7 @@ impl fmt::Display for Line {
|
|||||||
impl fmt::Display for Number {
|
impl fmt::Display for Number {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
&Number::Fixnum(n) => write!(f, "{}", n),
|
||||||
&Number::Float(fl) => write!(f, "{}", fl),
|
&Number::Float(fl) => write!(f, "{}", fl),
|
||||||
&Number::Integer(ref bi) => write!(f, "{}", bi),
|
&Number::Integer(ref bi) => write!(f, "{}", bi),
|
||||||
&Number::Rational(ref r) => write!(f, "{}", r),
|
&Number::Rational(ref r) => write!(f, "{}", r),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
:- module(tests_on_builtins, []).
|
:- module(tests_on_builtins, []).
|
||||||
|
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
test_queries_on_builtins :-
|
test_queries_on_builtins :-
|
||||||
\+ atom(_),
|
\+ atom(_),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
:- module(tests_on_call_with_inference_limit, []).
|
:- module(tests_on_call_with_inference_limit, []).
|
||||||
|
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
:- dynamic(f/1).
|
:- dynamic(f/1).
|
||||||
:- dynamic(g/1).
|
:- dynamic(g/1).
|
||||||
|
|||||||
@@ -62,4 +62,3 @@ cleanup :- abolish(p/3),
|
|||||||
abolish(h/1).
|
abolish(h/1).
|
||||||
|
|
||||||
:- initialization(test_queries_on_rules).
|
:- initialization(test_queries_on_rules).
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
:- module(test_on_setup_call_cleanup, []).
|
:- module(test_on_setup_call_cleanup, []).
|
||||||
|
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(iso_ext)).
|
||||||
|
|
||||||
test_queries_on_setup_call_cleanup :-
|
test_queries_on_setup_call_cleanup :-
|
||||||
\+ setup_call_cleanup(false, _, _),
|
\+ setup_call_cleanup(false, _, _),
|
||||||
|
|||||||
Reference in New Issue
Block a user