# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-[[package]]
-name = "arc-swap"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62"
-
-[[package]]
-name = "arrayref"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
-
[[package]]
name = "arrayvec"
version = "0.4.12"
"nodrop",
]
-[[package]]
-name = "arrayvec"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
-
[[package]]
name = "autocfg"
version = "0.1.7"
[[package]]
name = "autocfg"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "az"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41a6b78289a33e09b00818ca8c90ab17c5dabb6e74f4b29a6de679c0e0886ade"
-
-[[package]]
-name = "base64"
-version = "0.11.0"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
+checksum = "e9bcd47d94aa4eb8c076b50fc61a75020789394ffb9bd74a180b3379130f6569"
[[package]]
name = "base64"
[[package]]
name = "bit-vec"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "bitflags"
"opaque-debug",
]
-[[package]]
-name = "blake2b_simd"
-version = "0.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
-dependencies = [
- "arrayref",
- "arrayvec 0.5.1",
- "constant_time_eq",
-]
-
[[package]]
name = "block-buffer"
version = "0.7.3"
[[package]]
name = "bumpalo"
-version = "3.2.1"
+version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187"
+checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
[[package]]
name = "byte-tools"
[[package]]
name = "byteorder"
-version = "1.3.4"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
+checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
[[package]]
name = "cc"
-version = "1.0.52"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
+checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
[[package]]
name = "chrono"
-version = "0.4.11"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
+ "libc",
"num-integer",
- "num-traits 0.2.11",
+ "num-traits 0.2.14",
"time",
+ "winapi 0.3.9",
]
[[package]]
"bitflags",
]
-[[package]]
-name = "constant_time_eq"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
-
[[package]]
name = "core-foundation"
-version = "0.7.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
+checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
dependencies = [
"core-foundation-sys",
"libc",
[[package]]
name = "core-foundation-sys"
-version = "0.7.0"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
+checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
name = "cpu-time"
checksum = "e9e393a7668fe1fad3075085b86c781883000b4ede868f43627b34a87c8b7ded"
dependencies = [
"libc",
- "winapi 0.3.8",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
-dependencies = [
- "autocfg 1.0.0",
- "cfg-if 0.1.10",
- "lazy_static",
+ "winapi 0.3.9",
]
[[package]]
"mio",
"parking_lot",
"signal-hook",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
name = "crossterm_winapi"
-version = "0.6.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "057b7146d02fb50175fd7dbe5158f6097f33d02831f43b4ee8ae4ddf67b68f5c"
+checksum = "c2265c3f8e080075d9b6417aa72293fc71662f34b4af2612d8d1b074d29510db"
dependencies = [
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
"generic-array",
]
-[[package]]
-name = "dirs"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff"
-dependencies = [
- "dirs-sys",
-]
-
[[package]]
name = "dirs-next"
version = "2.0.0"
"dirs-sys-next",
]
-[[package]]
-name = "dirs-sys"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
-dependencies = [
- "libc",
- "redox_users",
- "winapi 0.3.8",
-]
-
[[package]]
name = "dirs-sys-next"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99de365f605554ae33f115102a02057d4fc18b01f3284d6870be0938743cfe7d"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
[[package]]
name = "getrandom"
-version = "0.1.14"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
"libc",
"wasi",
]
checksum = "34a97a52fdee1870a34fa6e4b77570cba531b27d1838874fef4429a791a3d657"
dependencies = [
"proc-macro-hack",
- "proc-macro2 1.0.10",
- "quote 1.0.3",
- "syn 1.0.18",
+ "proc-macro2 1.0.24",
+ "quote 1.0.8",
+ "syn 1.0.60",
]
[[package]]
name = "gmp-mpfr-sys"
-version = "1.2.2"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63d7f805cf9df081683d463f62864bda8b8e3ce7162a8e11cd0c49f27b8ce89b"
+checksum = "a57fdb339d49833021b1fded600ed240ae907e33909d5511a61dff884df7f16e"
dependencies = [
"libc",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
+[[package]]
+name = "hashbrown"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+
[[package]]
name = "hostname"
version = "0.3.1"
dependencies = [
"libc",
"match_cfg",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
[[package]]
name = "indexmap"
-version = "1.3.2"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
+checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
dependencies = [
- "autocfg 1.0.0",
+ "autocfg 1.0.1",
+ "hashbrown",
]
[[package]]
[[package]]
name = "itoa"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
-version = "0.3.39"
+version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7"
+checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
dependencies = [
"wasm-bindgen",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14"
dependencies = [
- "arrayvec 0.4.12",
+ "arrayvec",
"cfg-if 0.1.10",
"rustc_version",
"ryu",
[[package]]
name = "libc"
-version = "0.2.81"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
+checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
[[package]]
name = "libsodium-sys"
[[package]]
name = "log"
-version = "0.4.8"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+[[package]]
+name = "mach"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "markup5ever"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
-[[package]]
-name = "maybe-uninit"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
-
[[package]]
name = "memchr"
-version = "2.3.3"
+version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "mio"
-version = "0.6.21"
+version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
+checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
dependencies = [
"cfg-if 0.1.10",
"fuchsia-zircon",
[[package]]
name = "miow"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
dependencies = [
"kernel32-sys",
"net2",
[[package]]
name = "native-tls"
-version = "0.2.4"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d"
+checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
dependencies = [
"lazy_static",
"libc",
[[package]]
name = "net2"
-version = "0.2.33"
+version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
+checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
dependencies = [
"cfg-if 0.1.10",
"libc",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
- "autocfg 1.0.0",
+ "autocfg 1.0.1",
"num-integer",
- "num-traits 0.2.11",
+ "num-traits 0.2.14",
]
[[package]]
name = "num-integer"
-version = "0.1.42"
+version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
- "autocfg 1.0.0",
- "num-traits 0.2.11",
+ "autocfg 1.0.1",
+ "num-traits 0.2.14",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
- "autocfg 1.0.0",
+ "autocfg 1.0.1",
"num-bigint",
"num-integer",
- "num-traits 0.2.11",
+ "num-traits 0.2.14",
]
[[package]]
"num-bigint",
"num-integer",
"num-rational",
- "num-traits 0.2.11",
+ "num-traits 0.2.14",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
- "num-traits 0.2.11",
+ "num-traits 0.2.14",
]
[[package]]
name = "num-traits"
-version = "0.2.11"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
- "autocfg 1.0.0",
+ "autocfg 1.0.1",
]
[[package]]
name = "once_cell"
-version = "1.3.1"
+version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
+checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "opaque-debug"
[[package]]
name = "openssl"
-version = "0.10.29"
+version = "0.10.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd"
+checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70"
dependencies = [
"bitflags",
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
"foreign-types",
"lazy_static",
"libc",
[[package]]
name = "openssl-src"
-version = "111.9.0+1.1.1g"
+version = "111.13.0+1.1.1i"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2dbe10ddd1eb335aba3780eb2eaa13e1b7b441d2562fd962398740927f39ec4"
+checksum = "045e4dc48af57aad93d665885789b43222ae26f4886494da12d1ed58d309dcb6"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
-version = "0.9.58"
+version = "0.9.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
+checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6"
dependencies = [
- "autocfg 1.0.0",
+ "autocfg 1.0.1",
"cc",
"libc",
"openssl-src",
"cfg-if 0.1.10",
"cloudabi",
"libc",
- "redox_syscall",
- "smallvec 1.4.0",
- "winapi 0.3.8",
+ "redox_syscall 0.1.57",
+ "smallvec",
+ "winapi 0.3.9",
]
[[package]]
[[package]]
name = "pkg-config"
-version = "0.3.17"
+version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
+checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
-version = "0.2.8"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "precomputed-hash"
[[package]]
name = "proc-macro-hack"
-version = "0.5.15"
+version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
[[package]]
name = "proc-macro2"
-version = "1.0.10"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
- "unicode-xid 0.2.0",
+ "unicode-xid 0.2.1",
]
[[package]]
name = "prolog_parser"
version = "0.8.68"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520bf98dcd386ef320ef11239415c9a11856d3b28fab0d8dc0b61b0d7e65ffe5"
dependencies = [
"lexical",
"num-rug-adapter",
[[package]]
name = "quote"
-version = "1.0.3"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
+checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
dependencies = [
- "proc-macro2 1.0.10",
+ "proc-macro2 1.0.24",
]
[[package]]
"rand_os",
"rand_pcg",
"rand_xorshift",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
name = "rand"
-version = "0.7.3"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
- "getrandom",
"libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc 0.2.0",
+ "rand_chacha 0.3.0",
+ "rand_core 0.6.1",
+ "rand_hc 0.3.0",
]
[[package]]
[[package]]
name = "rand_chacha"
-version = "0.2.2"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"ppv-lite86",
- "rand_core 0.5.1",
+ "rand_core 0.6.1",
]
[[package]]
[[package]]
name = "rand_core"
-version = "0.5.1"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
- "rand_core 0.5.1",
+ "rand_core 0.6.1",
]
[[package]]
dependencies = [
"libc",
"rand_core 0.4.2",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
"libc",
"rand_core 0.4.2",
"rdrand",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
[[package]]
name = "redox_syscall"
-version = "0.1.56"
+version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
+checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
+dependencies = [
+ "bitflags",
+]
[[package]]
name = "redox_users"
-version = "0.3.4"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
+checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
dependencies = [
"getrandom",
- "redox_syscall",
- "rust-argon2",
+ "redox_syscall 0.2.4",
]
[[package]]
[[package]]
name = "remove_dir_all"
-version = "0.5.2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
name = "ring"
-version = "0.16.13"
+version = "0.16.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196"
+checksum = "024a1e66fea74c66c66624ee5622a7ff0e4b73a13b4f5c326ddb50c708944226"
dependencies = [
"cc",
"libc",
"spin",
"untrusted",
"web-sys",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
[[package]]
name = "rug"
-version = "1.8.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72315b6d9cb7d886fb99724330c47ceb29e923df657c31da3849fe88c0ded710"
+checksum = "e538d00da450a8e48aac7e6322e67b2dc86ec71a1feeac0e3954c4f07f01bc45"
dependencies = [
"az",
"gmp-mpfr-sys",
"libc",
]
-[[package]]
-name = "rust-argon2"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
-dependencies = [
- "base64 0.11.0",
- "blake2b_simd",
- "constant_time_eq",
- "crossbeam-utils",
-]
-
[[package]]
name = "rustc_version"
version = "0.2.3"
[[package]]
name = "rustyline"
-version = "7.0.0"
+version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a5f54deba50e65ee4cf786dbc37e8b3c63bdccccbcf9d3a8a9fd0c1bb7e1984"
+checksum = "8227301bfc717136f0ecbd3d064ba8199e44497a0bdd46bb01ede4387cfd2cec"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
- "dirs",
+ "dirs-next",
"fs2",
"libc",
"log",
"unicode-segmentation",
"unicode-width",
"utf8parse",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
name = "ryu"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "schannel"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
name = "scryer-prolog"
version = "0.8.127"
dependencies = [
- "base64 0.12.3",
+ "base64",
"blake2",
"chrono",
"cpu-time",
"rustyline",
"select",
"sha3",
+ "slice-deque",
"sodiumoxide",
"unicode_reader",
]
[[package]]
name = "security-framework"
-version = "0.4.4"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
+checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
dependencies = [
"bitflags",
"core-foundation",
[[package]]
name = "security-framework-sys"
-version = "0.4.3"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405"
+checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
dependencies = [
"core-foundation-sys",
"libc",
[[package]]
name = "serde"
-version = "1.0.114"
+version = "1.0.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
+checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
[[package]]
name = "serde_derive"
-version = "1.0.113"
+version = "1.0.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93c5eaa17d0954cb481cdcfffe9d84fcfa7a1a9f2349271e678677be4c26ae31"
+checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
dependencies = [
- "proc-macro2 1.0.10",
- "quote 1.0.3",
- "syn 1.0.18",
+ "proc-macro2 1.0.24",
+ "quote 1.0.8",
+ "syn 1.0.60",
]
[[package]]
name = "serde_json"
-version = "1.0.55"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226"
+checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
dependencies = [
"itoa",
"ryu",
[[package]]
name = "signal-hook"
-version = "0.1.13"
+version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10b9f3a1686a29f53cfd91ee5e3db3c12313ec02d33765f02c1a9645a1811e2c"
+checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
dependencies = [
"libc",
"mio",
[[package]]
name = "signal-hook-registry"
-version = "1.2.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
+checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
dependencies = [
- "arc-swap",
"libc",
]
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
-name = "smallvec"
-version = "0.6.13"
+name = "slice-deque"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
+checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25"
dependencies = [
- "maybe-uninit",
+ "libc",
+ "mach",
+ "winapi 0.3.9",
]
[[package]]
name = "smallvec"
-version = "1.4.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
+checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "sodiumoxide"
dependencies = [
"phf_generator",
"phf_shared",
- "proc-macro2 1.0.10",
- "quote 1.0.3",
+ "proc-macro2 1.0.24",
+ "quote 1.0.8",
"string_cache_shared",
]
[[package]]
name = "syn"
-version = "1.0.18"
+version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
+checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
dependencies = [
- "proc-macro2 1.0.10",
- "quote 1.0.3",
- "unicode-xid 0.2.0",
+ "proc-macro2 1.0.24",
+ "quote 1.0.8",
+ "unicode-xid 0.2.1",
]
[[package]]
name = "tempfile"
-version = "3.1.0"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
"libc",
- "rand 0.7.3",
- "redox_syscall",
+ "rand 0.8.3",
+ "redox_syscall 0.2.4",
"remove_dir_all",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
name = "tendril"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
+checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33"
dependencies = [
"futf",
"mac",
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
"libc",
- "winapi 0.3.8",
+ "winapi 0.3.9",
]
[[package]]
[[package]]
name = "unicode-segmentation"
-version = "1.6.0"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
[[package]]
name = "unicode-width"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
+checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
[[package]]
name = "unicode-xid"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "unicode_reader"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f886d405a2be65db804cb1088f969dbd99528a9eec9bcf941584b17de4cd3034"
+checksum = "5b639121690b27acd92c97ed2b52c5e5e8d3d39482e943b4559695cef62f771a"
dependencies = [
- "smallvec 0.6.13",
+ "smallvec",
"unicode-segmentation",
]
[[package]]
name = "vcpkg"
-version = "0.2.9"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c"
+checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "void"
[[package]]
name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
+version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
-version = "0.2.62"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551"
+checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.62"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94"
+checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
dependencies = [
"bumpalo",
"lazy_static",
"log",
- "proc-macro2 1.0.10",
- "quote 1.0.3",
- "syn 1.0.18",
+ "proc-macro2 1.0.24",
+ "quote 1.0.8",
+ "syn 1.0.60",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.62"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776"
+checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
dependencies = [
- "quote 1.0.3",
+ "quote 1.0.8",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.62"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
+checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
dependencies = [
- "proc-macro2 1.0.10",
- "quote 1.0.3",
- "syn 1.0.18",
+ "proc-macro2 1.0.24",
+ "quote 1.0.8",
+ "syn 1.0.60",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.62"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad"
+checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
[[package]]
name = "web-sys"
-version = "0.3.39"
+version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642"
+checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
dependencies = [
"js-sys",
"wasm-bindgen",
[[package]]
name = "winapi"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
[[package]]
name = "xmlparser"
-version = "0.13.2"
+version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52613e655f6f11f63c0fe7d1c3b5ef69e44d96df9b65dab296b441ed0e1125f5"
+checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8"
nix = "0.15.0"
num-rug-adapter = { optional = true, version = "0.1.4" }
ordered-float = "0.5.0"
-prolog_parser = { version = "0.8.68", default-features = false }
+prolog_parser = { version = "0.8.63", path = "../prolog_parser", default-features = false }
ref_thread_local = "0.0.0"
rug = { version = "1.4.0", optional = true }
rustyline = "7.0.0"
roxmltree = "0.11.0"
base64 = "0.12.3"
sodiumoxide = "0.2.6"
+slice-deque = "0.3.0"
\ No newline at end of file
Ok(entries) => entries,
Err(_) => return,
};
+
for entry in entries.filter_map(Result::ok).map(|e| e.path()) {
if entry.is_dir() {
if let Some(file_name) = entry.file_name() {
let contain =
String::from_utf8(fs::read(&entry).unwrap()).unwrap();
let name = entry.file_stem().unwrap().to_str().unwrap();
+
let line = format!(
" m.insert(\"{}\",\n{:?});\n",
prefix.to_owned() + name,
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SystemClauseType {
- AbolishClause,
- AbolishModuleClause,
- AssertDynamicPredicateToBack,
- AssertDynamicPredicateToFront,
- AtEndOfExpansion,
+ // AbolishClause,
+ // AbolishModuleClause,
+ // AssertDynamicPredicateToBack,
+ // AssertDynamicPredicateToFront,
+ // AtEndOfExpansion,
AtomChars,
AtomCodes,
AtomLength,
DynamicModuleResolution(usize),
EnqueueAttributeGoal,
EnqueueAttributedVar,
- ExpandGoal,
- ExpandTerm,
+// ExpandGoal,
+// ExpandTerm,
FetchGlobalVar,
FetchGlobalVarWithOffset,
FirstStream,
GetAttrVarQueueDelimiter,
GetAttrVarQueueBeyond,
GetBValue,
- GetClause,
+// GetClause,
GetContinuationChunk,
- GetModuleClause,
+// GetModuleClause,
GetNextDBRef,
GetNextOpDBRef,
IsPartialString,
LookupDBRef,
LookupOpDBRef,
Halt,
- ModuleHeadIsDynamic,
+// ModuleHeadIsDynamic,
GetLiftedHeapFromOffset,
GetLiftedHeapFromOffsetDiff,
GetSCCCleaner,
InstallSCCCleaner,
InstallInferenceCounter,
LiftedHeapLength,
- ModuleAssertDynamicPredicateToFront,
- ModuleAssertDynamicPredicateToBack,
+ LoadLibraryAsStream,
+ // ModuleAssertDynamicPredicateToFront,
+ // ModuleAssertDynamicPredicateToBack,
ModuleExists,
- ModuleOf,
- ModuleRetractClause,
+ // ModuleRetractClause,
NextEP,
NoSuchPredicate,
NumberToChars,
ResetContinuationMarker,
ResetGlobalVarAtKey,
ResetGlobalVarAtOffset,
- RetractClause,
+ // RetractClause,
RestoreCutPolicy,
SetCutPoint(RegType),
SetInput,
impl SystemClauseType {
pub fn name(&self) -> ClauseName {
match self {
- &SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
- &SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
- &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
- &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
- &SystemClauseType::AtEndOfExpansion => clause_name!("$at_end_of_expansion"),
+ // &SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
+ // &SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
+ // &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
+ // &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
+ // &SystemClauseType::AtEndOfExpansion => clause_name!("$at_end_of_expansion"),
&SystemClauseType::AtomChars => clause_name!("$atom_chars"),
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
&SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
&SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
&SystemClauseType::FileTime => clause_name!("$file_time"),
- &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
- &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
- &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
- clause_name!("$use_qualified_module")
- }
- &SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile) => {
- clause_name!("$use_module_from_file")
- }
- &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
- clause_name!("$use_qualified_module_from_file")
- }
+ &SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) =>
+ clause_name!("$add_dynamic_predicate"),
+ &SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) =>
+ clause_name!("$add_goal_expansion_clause"),
+ &SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause) =>
+ clause_name!("$add_term_expansion_clause"),
+ &SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable) =>
+ clause_name!("$clause_to_evacuable"),
+ &SystemClauseType::REPL(REPLCodePtr::ConcludeLoad) =>
+ clause_name!("$conclude_load"),
+ &SystemClauseType::REPL(REPLCodePtr::DeclareModule) =>
+ clause_name!("$declare_module"),
+ &SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary) =>
+ clause_name!("$load_compiled_library"),
+ &SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload) =>
+ clause_name!("$push_load_state_payload"),
+ &SystemClauseType::REPL(REPLCodePtr::UserAsserta) =>
+ clause_name!("$asserta"),
+ &SystemClauseType::REPL(REPLCodePtr::UserAssertz) =>
+ clause_name!("$assertz"),
+ &SystemClauseType::REPL(REPLCodePtr::UserRetract) =>
+ clause_name!("$retract_clause"),
+ &SystemClauseType::REPL(REPLCodePtr::UseModule) =>
+ clause_name!("$use_module"),
+ &SystemClauseType::REPL(REPLCodePtr::PushLoadContext) =>
+ clause_name!("$push_load_context"),
+ &SystemClauseType::REPL(REPLCodePtr::PopLoadContext) =>
+ clause_name!("$pop_load_context"),
+ &SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload) =>
+ clause_name!("$pop_load_state_payload"),
+ &SystemClauseType::REPL(REPLCodePtr::LoadContextSource) =>
+ clause_name!("$prolog_lc_source"),
+ &SystemClauseType::REPL(REPLCodePtr::LoadContextFile) =>
+ clause_name!("$prolog_lc_file"),
+ &SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory) =>
+ clause_name!("$prolog_lc_dir"),
+ &SystemClauseType::REPL(REPLCodePtr::LoadContextModule) =>
+ clause_name!("$prolog_lc_module"),
+ &SystemClauseType::REPL(REPLCodePtr::LoadContextStream) =>
+ clause_name!("$prolog_lc_stream"),
+ &SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty) =>
+ clause_name!("$cpp_meta_predicate_property"),
+ &SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates) =>
+ clause_name!("$compile_pending_predicates"),
&SystemClauseType::Close => clause_name!("$close"),
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
&SystemClauseType::DynamicModuleResolution(_) => clause_name!("$module_call"),
&SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"),
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
- &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
- &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
- &SystemClauseType::FetchGlobalVarWithOffset => {
- clause_name!("$fetch_global_var_with_offset")
- }
+ &SystemClauseType::FetchGlobalVarWithOffset =>
+ clause_name!("$fetch_global_var_with_offset"),
&SystemClauseType::FirstStream => clause_name!("$first_stream"),
&SystemClauseType::FlushOutput => clause_name!("$flush_output"),
&SystemClauseType::GetByte => clause_name!("$get_byte"),
clause_name!("$get_lh_from_offset_diff")
}
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
- &SystemClauseType::GetClause => clause_name!("$get_clause"),
+// &SystemClauseType::GetClause => clause_name!("$get_clause"),
&SystemClauseType::GetNextDBRef => clause_name!("$get_next_db_ref"),
&SystemClauseType::GetNextOpDBRef => clause_name!("$get_next_op_db_ref"),
&SystemClauseType::LookupDBRef => clause_name!("$lookup_db_ref"),
&SystemClauseType::LookupOpDBRef => clause_name!("$lookup_op_db_ref"),
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
- &SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
+// &SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
&SystemClauseType::Halt => clause_name!("$halt"),
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
&SystemClauseType::Maybe => clause_name!("maybe"),
&SystemClauseType::CpuNow => clause_name!("$cpu_now"),
&SystemClauseType::CurrentTime => clause_name!("$current_time"),
- &SystemClauseType::ModuleAssertDynamicPredicateToFront => {
- clause_name!("$module_asserta")
- }
- &SystemClauseType::ModuleAssertDynamicPredicateToBack => {
- clause_name!("$module_assertz")
- }
- &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
+ // &SystemClauseType::ModuleAssertDynamicPredicateToFront => {
+ // clause_name!("$module_asserta")
+ // }
+ // &SystemClauseType::ModuleAssertDynamicPredicateToBack => {
+ // clause_name!("$module_assertz")
+ // }
+// &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
&SystemClauseType::ModuleExists => clause_name!("$module_exists"),
- &SystemClauseType::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NextStream => clause_name!("$next_stream"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
&SystemClauseType::GetCutPoint => clause_name!("$get_cp"),
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
- &SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
+ // &SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
&SystemClauseType::NextEP => clause_name!("$nextEP"),
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_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::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
- &SystemClauseType::RetractClause => clause_name!("$retract_clause"),
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
&SystemClauseType::ResetContinuationMarker => clause_name!("$reset_cont_marker"),
&SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"),
&SystemClauseType::SetEnv => clause_name!("$setenv"),
&SystemClauseType::UnsetEnv => clause_name!("$unsetenv"),
&SystemClauseType::CharsBase64 => clause_name!("$chars_base64"),
+ &SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"),
}
}
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
- ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
- ("$at_end_of_expansion", 0) => Some(SystemClauseType::AtEndOfExpansion),
+ // ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
+ ("$add_dynamic_predicate", 3) =>
+ Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate)),
+ ("$add_goal_expansion_clause", 4) =>
+ Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause)),
+ ("$add_term_expansion_clause", 3) =>
+ Some(SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause)),
+ // ("$at_end_of_expansion", 0) => Some(SystemClauseType::AtEndOfExpansion),
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
- ("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
+ // ("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
("$bind_from_register", 2) => Some(SystemClauseType::BindFromRegister),
- ("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
- ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
- ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
- ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
+ // ("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
+ // ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
("$char_code", 2) => Some(SystemClauseType::CharCode),
("$char_type", 2) => Some(SystemClauseType::CharType),
("$copy_term_without_attr_vars", 2) => Some(SystemClauseType::CopyTermWithoutAttrVars),
("$create_partial_string", 3) => Some(SystemClauseType::CreatePartialString),
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
- ("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
("$close", 2) => Some(SystemClauseType::Close),
("$current_hostname", 1) => Some(SystemClauseType::CurrentHostname),
("$peek_char", 2) => Some(SystemClauseType::PeekChar),
("$peek_code", 2) => Some(SystemClauseType::PeekCode),
("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
- ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
- ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
+// ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
+// ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_byte", 2) => Some(SystemClauseType::GetByte),
}
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
- ("$get_clause", 2) => Some(SystemClauseType::GetClause),
- ("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
+// ("$get_clause", 2) => Some(SystemClauseType::GetClause),
+// ("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
("$halt", 1) => Some(SystemClauseType::Halt),
- ("$head_is_dynamic", 1) => Some(SystemClauseType::HeadIsDynamic),
+ ("$head_is_dynamic", 2) => Some(SystemClauseType::HeadIsDynamic),
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
("$cpu_now", 1) => Some(SystemClauseType::CpuNow),
("$current_time", 1) => Some(SystemClauseType::CurrentTime),
("$module_exists", 1) => Some(SystemClauseType::ModuleExists),
- ("$module_of", 2) => Some(SystemClauseType::ModuleOf),
- ("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
- ("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
- ("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
+ // ("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
+ // ("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
+ ("$no_such_predicate", 2) => Some(SystemClauseType::NoSuchPredicate),
("$number_to_chars", 2) => Some(SystemClauseType::NumberToChars),
("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
("$op", 3) => Some(SystemClauseType::OpDeclaration),
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset),
- ("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
+ // ("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
("$set_ball", 1) => Some(SystemClauseType::SetBall),
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory),
("$path_canonical", 2) => Some(SystemClauseType::PathCanonical),
("$file_time", 3) => Some(SystemClauseType::FileTime),
- ("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
- ("$use_module_from_file", 1) =>
- Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),
- ("$use_qualified_module", 2) =>
- Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule)),
- ("$use_qualified_module_from_file", 2) =>
- Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
+ ("$clause_to_evacuable", 3) => Some(SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable)),
+ ("$conclude_load", 1) => Some(SystemClauseType::REPL(REPLCodePtr::ConcludeLoad)),
+ ("$use_module", 3) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
+ ("$declare_module", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DeclareModule)),
+ ("$load_compiled_library", 2) => Some(SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary)),
+ ("$push_load_state_payload", 1) => Some(SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload)),
+ ("$asserta", 4) => Some(SystemClauseType::REPL(REPLCodePtr::UserAsserta)),
+ ("$assertz", 4) => Some(SystemClauseType::REPL(REPLCodePtr::UserAssertz)),
+ ("$retract_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::UserRetract)),
("$variant", 2) => Some(SystemClauseType::Variant),
- ("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
+ ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions),
("$write_term", 7) => Some(SystemClauseType::WriteTerm),
("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars),
("$scryer_prolog_version", 1) => Some(SystemClauseType::ScryerPrologVersion),
("$setenv", 2) => Some(SystemClauseType::SetEnv),
("$unsetenv", 1) => Some(SystemClauseType::UnsetEnv),
("$chars_base64", 4) => Some(SystemClauseType::CharsBase64),
+ ("$load_library_as_stream", 3) => Some(SystemClauseType::LoadLibraryAsStream),
+ ("$push_load_context", 2) => Some(SystemClauseType::REPL(REPLCodePtr::PushLoadContext)),
+ ("$pop_load_state_payload", 1) => Some(SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload)),
+ ("$pop_load_context", 0) => Some(SystemClauseType::REPL(REPLCodePtr::PopLoadContext)),
+ ("$prolog_lc_source", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextSource)),
+ ("$prolog_lc_file", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextFile)),
+ ("$prolog_lc_dir", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory)),
+ ("$prolog_lc_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextModule)),
+ ("$prolog_lc_stream", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextStream)),
+ ("$cpp_meta_predicate_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)),
+ ("$compile_pending_predicates", 1) => Some(SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates)),
_ => None,
}
}
pub enum ClauseType {
BuiltIn(BuiltInClauseType),
CallN,
- Hook(CompileTimeHook),
Inlined(InlinedClauseType),
Named(ClauseName, usize, CodeIndex), // name, arity, index.
Op(ClauseName, SharedOpDesc, CodeIndex),
match self {
&ClauseType::BuiltIn(ref built_in) => built_in.name(),
&ClauseType::CallN => clause_name!("call"),
- &ClauseType::Hook(ref hook) => hook.name(),
&ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
&ClauseType::Op(ref name, ..) => name.clone(),
&ClauseType::Named(ref name, ..) => name.clone(),
/// Code generation to WAM-like instructions.
use crate::prolog_parser::ast::*;
+use crate::prolog_parser::tabled_rc::TabledData;
use crate::allocator::*;
use crate::arithmetic::*;
use crate::indexing::*;
use crate::instructions::*;
use crate::iterators::*;
-use crate::machine::machine_indices::*;
use crate::targets::*;
+use crate::machine::machine_errors::*;
+
use crate::indexmap::{IndexMap, IndexSet};
use std::cell::Cell;
+use std::collections::VecDeque;
use std::rc::Rc;
-use std::vec::Vec;
-#[derive(Debug)]
-pub struct CodeGenerator<TermMarker> {
- marker: TermMarker,
- pub var_count: IndexMap<Rc<Var>, usize>,
- non_counted_bt: bool,
+#[inline]
+pub fn trust_me(non_counted_bt: bool) -> ChoiceInstruction {
+ if non_counted_bt {
+ ChoiceInstruction::DefaultTrustMe(0)
+ } else {
+ ChoiceInstruction::TrustMe(0)
+ }
+}
+
+#[inline]
+pub fn retry_me_else(offset: usize, non_counted_bt: bool) -> ChoiceInstruction {
+ if non_counted_bt {
+ ChoiceInstruction::DefaultRetryMeElse(offset)
+ } else {
+ ChoiceInstruction::RetryMeElse(offset)
+ }
}
#[derive(Debug)]
}
}
+#[derive(Clone, Copy, Debug)]
+pub struct CodeGenSettings {
+ pub is_extensible: bool,
+ pub non_counted_bt: bool,
+}
+
+impl CodeGenSettings {
+ #[inline]
+ pub fn new(is_extensible: bool, non_counted_bt: bool) -> Self {
+ CodeGenSettings {
+ is_extensible,
+ non_counted_bt,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct CodeGenerator<TermMarker> {
+ atom_tbl: TabledData<Atom>,
+ marker: TermMarker,
+ pub var_count: IndexMap<Rc<Var>, usize>,
+ non_counted_bt: bool,
+ is_extensible: bool,
+ pub skeleton: PredicateSkeleton,
+ pub jmp_by_locs: Vec<usize>,
+ global_jmp_by_locs_offset: usize,
+}
+
impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
- pub fn new(non_counted_bt: bool) -> Self {
+ pub fn new(atom_tbl: TabledData<Atom>, settings: CodeGenSettings) -> Self {
CodeGenerator {
+ atom_tbl,
marker: Allocator::new(),
var_count: IndexMap::new(),
- non_counted_bt,
+ non_counted_bt: settings.non_counted_bt,
+ is_extensible: settings.is_extensible,
+ skeleton: PredicateSkeleton::new(),
+ jmp_by_locs: vec![],
+ global_jmp_by_locs_offset: 0,
}
}
- pub fn take_vars(self) -> AllocVarDict {
- self.marker.take_bindings()
- }
-
fn update_var_count<Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
for term in iter {
if let TermRef::Var(_, _, var) = term {
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
}
- fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) {
+ fn add_conditional_call(&mut self, code: &mut Code, qt: &QueryTerm, pvs: usize) {
match qt {
- &QueryTerm::Jump(ref vars) => code.push(jmp_call!(vars.len(), 0, pvs)),
+ &QueryTerm::Jump(ref vars) => {
+ self.jmp_by_locs.push(code.len());
+ code.push(jmp_call!(vars.len(), 0, pvs));
+ }
&QueryTerm::Clause(_, ref ct, ref terms, true) => {
- code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs))
+ code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs));
}
&QueryTerm::Clause(_, ref ct, ref terms, false) => {
- code.push(call_clause!(ct.clone(), terms.len(), pvs))
+ code.push(call_clause!(ct.clone(), terms.len(), pvs));
+ }
+ _ => {
}
- _ => {}
}
}
match code.last_mut() {
Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
&mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
- *last_call = true
+ *last_call = true;
}
&mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => {
- *last_call = true
+ *last_call = true;
+ }
+ &mut ControlInstruction::Proceed => {
+ }
+ _ => {
+ dealloc_index += 1;
}
- &mut ControlInstruction::Proceed => {}
- _ => dealloc_index += 1,
},
- Some(&mut Line::Cut(CutInstruction::Cut(_))) => dealloc_index += 1,
- _ => {}
+ Some(&mut Line::Cut(CutInstruction::Cut(_))) => {
+ dealloc_index += 1;
+ }
+ _ => {
+ }
};
dealloc_index
terms: &'a Vec<Box<Term>>,
term_loc: GenContext,
code: &mut Code,
- ) -> Result<(), ParserError> {
+ ) -> Result<(), CompilationError> {
match ct {
&InlinedClauseType::CompareNumber(cmp, ..) => {
self.marker.reset_arg(2);
code: &mut Code,
term_loc: GenContext,
use_default_call_policy: bool,
- ) -> Result<(), ParserError> {
+ ) -> Result<(), CompilationError> {
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
code.append(&mut acode);
conjunct_info: &ConjunctInfo<'a>,
code: &mut Code,
is_exposed: bool,
- ) -> Result<(), ParserError> {
+ ) -> Result<(), CompilationError> {
for (chunk_num, _, terms) in iter.rule_body_iter() {
for (i, term) in terms.iter().enumerate() {
let term_loc = if i + 1 < terms.len() {
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
self.compile_get_level_and_unify(code, cell, var.clone(), term_loc)
}
- &QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
- &QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
- Line::Cut(CutInstruction::NeckCut)
- } else {
- Line::Cut(CutInstruction::Cut(perm_v!(1)))
- }),
+ &QueryTerm::UnblockedCut(ref cell) => {
+ self.compile_unblocked_cut(code, cell)
+ }
+ &QueryTerm::BlockedCut => {
+ code.push(if chunk_num == 0 {
+ Line::Cut(CutInstruction::NeckCut)
+ } else {
+ Line::Cut(CutInstruction::Cut(perm_v!(1)))
+ })
+ }
&QueryTerm::Clause(
_,
ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
ref terms,
use_default_call_policy,
- ) => self.compile_is_call(terms, code, term_loc, use_default_call_policy)?,
+ ) => {
+ self.compile_is_call(terms, code, term_loc, use_default_call_policy)?
+ }
&QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
self.compile_inlined(ct, terms, term_loc, code)?
}
}
}
- fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) {
+ fn compile_cleanup(&mut self, code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) {
// add a proceed to bookend any trailing cuts.
match toc {
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
let dealloc_index = Self::lco(code);
if conjunct_info.allocates() {
+ let offset = self.global_jmp_by_locs_offset;
+
+ if let Some(jmp_by_offset) = self.jmp_by_locs[offset ..].last_mut() {
+ if *jmp_by_offset == dealloc_index {
+ *jmp_by_offset += 1;
+ }
+ }
+
code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
}
}
- pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, ParserError> {
+ pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, CompilationError> {
let iter = ChunkedIterator::from_rule(rule);
let conjunct_info = self.collect_var_data(iter);
ref clauses,
} = rule;
- let mut code = Vec::new();
+ let mut code = Code::new();
self.marker.reset_at_head(args);
self.compile_seq_prelude(&conjunct_info, &mut code);
self.compile_seq(iter, &conjunct_info, &mut code, false)?;
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)
}
}
}
- Self::add_conditional_call(code, term, num_perm_vars_left);
+ self.add_conditional_call(code, term, num_perm_vars_left);
}
- pub fn compile_query(&mut self, query: &'a Vec<QueryTerm>) -> Result<Code, ParserError> {
+/*
+ pub fn compile_query(&mut self, query: &'a Vec<QueryTerm>) -> Result<Code, CompilationError> {
let iter = ChunkedIterator::from_term_sequence(query);
let conjunct_info = self.collect_var_data(iter);
Ok(code)
}
+*/
+
+ #[inline]
+ fn increment_jmp_by_locs_by(&mut self, incr: usize) {
+ let offset = self.global_jmp_by_locs_offset;
+
+ for loc in &mut self.jmp_by_locs[offset ..] {
+ *loc += incr;
+ }
+ }
/// Returns the index of the first instantiated argument.
fn first_instantiated_index(clauses: &[PredicateClause]) -> Option<usize> {
subseqs
}
- fn trust_me(&self) -> ChoiceInstruction {
- if self.non_counted_bt {
- ChoiceInstruction::DefaultTrustMe
- } else {
- ChoiceInstruction::TrustMe
- }
- }
-
- fn retry_me_else(&self, offset: usize) -> ChoiceInstruction {
- if self.non_counted_bt {
- ChoiceInstruction::DefaultRetryMeElse(offset)
- } else {
- ChoiceInstruction::RetryMeElse(offset)
- }
- }
-
fn compile_pred_subseq<'b: 'a>(
&mut self,
clauses: &'b [PredicateClause],
optimal_index: usize,
- ) -> Result<Code, ParserError> {
- let mut code_body = Vec::new();
- let mut code_offsets = CodeOffsets::new();
+ ) -> Result<Code, CompilationError> {
+ let mut code = VecDeque::new();
+ let mut code_offsets = CodeOffsets::new(self.atom_tbl.clone(), optimal_index + 1);
+ let mut skip_stub_try_me_else = false;
- let num_clauses = clauses.len();
+ let jmp_by_locs_len = self.jmp_by_locs.len();
for (i, clause) in clauses.iter().enumerate() {
self.marker.reset();
- let mut clause_code = match *clause {
- PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
- PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
+ let mut clause_index_info = ClauseIndexInfo::new(code.len());
+ self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
+
+ let clause_code = match clause {
+ &PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
+ &PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
};
- if num_clauses > 1 {
+ if clauses.len() > 1 {
let choice = match i {
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
- _ if i == num_clauses - 1 => self.trust_me(),
- _ => self.retry_me_else(clause_code.len() + 1),
+ _ if i == clauses.len() - 1 => trust_me(self.non_counted_bt),
+ _ => retry_me_else(clause_code.len() + 1, self.non_counted_bt),
};
- code_body.push(Line::Choice(choice));
+ code.push_back(Line::Choice(choice));
+ } else if self.is_extensible {
+ /*
+ generate stub choice instructions for extensible
+ predicates. if predicates are added to either the
+ inner or outer thread of choice instructions,
+ these stubs will be used, and surrounding indexing
+ instructions modified accordingly.
+
+ until then, the v offset of SwitchOnTerm will skip
+ over them.
+ */
+
+ code.push_front(Line::Choice(ChoiceInstruction::TryMeElse(0)));
+ skip_stub_try_me_else = true;
}
let arg = match clause.args() {
},
None => None,
};
+
if let Some(arg) = arg {
- let index = code_body.len();
- code_offsets.index_term(arg, index);
+ let index = code.len();
+ code_offsets.index_term(arg, index, &mut clause_index_info);
+ }
+
+ if !skip_stub_try_me_else {
+ self.increment_jmp_by_locs_by(code.len());
}
- code_body.append(&mut clause_code);
+ self.skeleton.clauses.push_back(clause_index_info);
+ code.extend(clause_code.into_iter());
}
- let mut code = Vec::new();
- code_offsets.add_indices(&mut code, code_body, optimal_index + 1);
+ let index_code = code_offsets.compute_indices(skip_stub_try_me_else);
+ self.global_jmp_by_locs_offset = jmp_by_locs_len;
- Ok(code)
+ if !index_code.is_empty() {
+ code.push_front(Line::IndexingCode(index_code));
+
+ if skip_stub_try_me_else {
+ // skip the TryMeElse(0) also.
+ self.increment_jmp_by_locs_by(2);
+ } else {
+ self.increment_jmp_by_locs_by(1);
+ }
+ } else if skip_stub_try_me_else {
+ // remove the TryMeElse(0).
+ code.pop_front();
+ }
+
+ Ok(Vec::from(code))
}
pub fn compile_predicate<'b: 'a>(
&mut self,
clauses: &'b Vec<PredicateClause>,
- ) -> Result<Code, ParserError> {
- let mut code = Vec::new();
+ ) -> Result<Code, CompilationError> {
+ let mut code = Code::new();
+
let optimal_index = match Self::first_instantiated_index(&clauses) {
Some(index) => index,
None => 0, // Default to first argument indexing.
};
+
let split_pred = Self::split_predicate(&clauses, optimal_index);
let multi_seq = split_pred.len() > 1;
for (l, r) in split_pred {
- let mut code_segment =
- self.compile_pred_subseq(&clauses[l..r], optimal_index)?;
+ let skel_lower_bound = self.skeleton.clauses.len();
+ let code_segment = self.compile_pred_subseq(&clauses[l .. r], optimal_index)?;
+ let clause_start_offset = code.len();
if multi_seq {
let choice = match l {
0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1),
- _ if r == clauses.len() => self.trust_me(),
- _ => self.retry_me_else(code_segment.len() + 1),
+ _ if r == clauses.len() => trust_me(self.non_counted_bt),
+ _ => retry_me_else(code_segment.len() + 1, self.non_counted_bt),
};
code.push(Line::Choice(choice));
+ } else if self.is_extensible {
+ code.push(Line::Choice(ChoiceInstruction::TryMeElse(0)));
}
- code.append(&mut code_segment);
+ if self.is_extensible {
+ let segment_is_indexed = to_indexing_line(&code_segment[0]).is_some();
+
+ for clause_index_info in self.skeleton.clauses[skel_lower_bound ..].iter_mut() {
+ clause_index_info.clause_start +=
+ clause_start_offset + 2 * (segment_is_indexed as usize);
+ clause_index_info.opt_arg_index_key +=
+ clause_start_offset + 1;
+ }
+ }
+
+ self.increment_jmp_by_locs_by(code.len());
+ self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
+
+ code.extend(code_segment.into_iter());
}
Ok(code)
use crate::prolog_parser::ast::*;
use crate::prolog_parser::parser::OpDesc;
-use crate::prolog_parser::tabled_rc::*;
use crate::clause_types::*;
use crate::machine::machine_errors::*;
use crate::ordered_float::OrderedFloat;
use crate::rug::{Integer, Rational};
-use crate::indexmap::IndexMap;
+use crate::indexmap::{IndexMap, IndexSet};
+
+use slice_deque::*;
use std::cell::Cell;
-use std::collections::VecDeque;
+use std::ops::AddAssign;
use std::path::PathBuf;
use std::rc::Rc;
pub type PredicateKey = (ClauseName, usize); // name, arity.
+pub type Predicate = Vec<PredicateClause>;
+
// vars of predicate, toplevel offset. Vec<Term> is always a vector
// of vars (we get their adjoining cells this way).
pub type JumpStub = Vec<Term>;
#[derive(Debug, Clone)]
pub enum TopLevel {
Declaration(Declaration),
- Fact(Term, usize, usize), // Term, line_num, col_num
+ Fact(Term), // Term, line_num, col_num
Predicate(Predicate),
Query(Vec<QueryTerm>),
- Rule(Rule, usize, usize), // Rule, line_num, col_num
+ Rule(Rule), // Rule, line_num, col_num
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum AppendOrPrepend {
+ Append,
+ Prepend
}
-impl TopLevel {
- pub fn is_end_of_file_atom(&self) -> bool {
+impl AppendOrPrepend {
+ #[inline]
+ pub fn is_append(self) -> bool {
match self {
- &TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _)), ..) => {
- return name.as_str() == "end_of_file"
- }
- _ => false,
+ AppendOrPrepend::Append => true,
+ AppendOrPrepend::Prepend => false,
}
}
}
pub clauses: Vec<QueryTerm>,
}
-#[derive(Debug, Clone)]
-pub struct Predicate(pub Vec<PredicateClause>);
-
-impl Predicate {
- #[inline]
- pub fn new() -> Self {
- Predicate(vec![])
- }
-
- #[inline]
- pub fn clauses(self) -> Vec<PredicateClause> {
- self.0
- }
-
- #[inline]
- pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> {
- self.0
- .first()
- .and_then(|clause| clause.name().map(|name| (name, clause.arity())))
- }
-}
-
-#[derive(Debug, Clone)]
+#[derive(Clone, Debug, Hash)]
pub enum ListingSource {
+ DynamicallyGenerated,
File(ClauseName, PathBuf), // filename, path
User,
}
pub fn from_file_and_path(filename: ClauseName, path_buf: PathBuf) -> Self {
ListingSource::File(filename, path_buf)
}
-
- pub fn name(&self) -> ClauseName {
- match self {
- ListingSource::File(ref filename, _) => filename.clone(),
- ListingSource::User => clause_name!("[user]")
- }
- }
-
- pub fn path(&self) -> PathBuf {
- match self {
- ListingSource::File(_, ref path) => path.clone(),
- ListingSource::User => std::env::current_dir().unwrap(),
- }
- }
-}
-
-fn resolved_term_and_module(term: &Term) -> Option<(ClauseName, ClauseName)>
-{
- match term {
- Term::Clause(_, ref name, ref terms, _) => {
- if name.as_str() == ":" && terms.len() == 2 {
- let module_name = match terms[0].as_ref() {
- &Term::Constant(_, Constant::Atom(ref module_name, _)) => {
- module_name.clone()
- }
- _ => {
- return Some((name.owning_module(), name.clone()));
- }
- };
-
- match terms[1].as_ref() {
- Term::Clause(_, ref name, ..)
- | Term::Constant(_, Constant::Atom(ref name, ..)) => {
- return Some((module_name, name.clone()));
- }
- _ => {
- }
- }
-
- Some((name.owning_module(), name.clone()))
- } else {
- Some((name.owning_module(), name.clone()))
- }
- }
- Term::Constant(_, Constant::Atom(ref name, _)) => {
- Some((name.owning_module(), name.clone()))
- }
- _ => {
- None
- }
- }
}
-fn resolved_term_arity(term: &Term) -> usize
-{
- match term {
- Term::Clause(_, ref name, ref terms, _) => {
- if name.as_str() == ":" && terms.len() == 2 {
- match terms[0].as_ref() {
- &Term::Constant(_, Constant::Atom(..)) => {
- }
- _ => {
- return 2;
- }
- }
-
- match terms[1].as_ref() {
- Term::Clause(_, _, ref terms, _) => {
- terms.len()
- }
- Term::Constant(_, Constant::Atom(..)) => {
- 0
- }
- _ => {
- 2
- }
- }
- } else {
- terms.len()
- }
- }
- _ => {
- 0
- }
- }
-}
-
-pub trait ClauseConsistency {
+pub trait ClauseInfo {
fn is_consistent(&self, clauses: &Vec<PredicateClause>) -> bool {
match clauses.first() {
- Some(ref cl) => {
- self.name_and_module() == cl.name_and_module() && self.arity() == cl.arity()
+ Some(cl) => {
+ self.name() == cl.name() && self.arity() == cl.arity()
}
None => {
true
}
}
- fn name_and_module(&self) -> Option<(ClauseName, ClauseName)>;
+ fn name(&self) -> Option<ClauseName>;
fn arity(&self) -> usize;
}
-/* Of course '$current_module$' isn't the name of the current
- * module. It'll do if no module is explicitly specified through
- * (:)/2.
- */
-impl ClauseConsistency for Term {
- fn name_and_module(&self) -> Option<(ClauseName, ClauseName)>
- {
+impl ClauseInfo for Term {
+ fn name(&self) -> Option<ClauseName> {
match self {
- Term::Clause(_, ref name, ref terms, _) =>
+ Term::Clause(_, ref name, ref terms, _) => {
match name.as_str() {
":-" => {
match terms.len() {
1 => None, // a declaration.
- 2 => resolved_term_and_module(&terms[0]),
- _ => Some((name.owning_module(), clause_name!(":-"))),
+ 2 => terms[0].name(),
+ _ => Some(clause_name!(":-")),
}
}
_ => {
- resolved_term_and_module(self)
+ Some(name.clone())
}
- },
+ }
+ }
Term::Constant(_, Constant::Atom(ref name, _)) => {
- Some((name.owning_module(), name.clone()))
+ Some(name.clone())
}
_ => {
None
":-" => {
match terms.len() {
1 => 0,
- 2 => resolved_term_arity(&terms[0]),
+ 2 => terms[0].arity(),
_ => terms.len(),
}
}
_ => {
- resolved_term_arity(self)
+ terms.len()
}
},
_ => {
}
}
-impl ClauseConsistency for Rule {
- fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
- Some((self.head.0.owning_module(), self.head.0.clone()))
+impl ClauseInfo for Rule {
+ fn name(&self) -> Option<ClauseName> {
+ Some(self.head.0.clone())
}
fn arity(&self) -> usize {
}
}
-impl ClauseConsistency for PredicateClause {
- fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
+impl ClauseInfo for PredicateClause {
+ fn name(&self) -> Option<ClauseName> {
match self {
&PredicateClause::Fact(ref term, ..) => {
- term.name_and_module()
- .map(|(_, name)| (name.owning_module(), name))
+ term.name()
}
&PredicateClause::Rule(ref rule, ..) => {
- rule.name_and_module()
+ rule.name()
}
}
}
}
}
-impl ClauseConsistency for Predicate {
- fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
- self.0.first().and_then(|clause| clause.name_and_module())
- }
-
- fn arity(&self) -> usize {
- self.0.first().map(|clause| clause.arity()).unwrap_or(0)
- }
-}
-
-pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
+// pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
#[derive(Debug, Clone)]
pub enum PredicateClause {
- Fact(Term, usize, usize), // Term, line number, column number.
- Rule(Rule, usize, usize), // Term, line number, column number.
+ Fact(Term),
+ Rule(Rule),
}
impl PredicateClause {
}
}
-pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator.
+// pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator.
+/*
#[derive(Debug, Clone)]
pub enum MultiFileIndicator {
LocalScoped(ClauseName, usize), // name, arity
ModuleScoped(ScopedPredicateKey),
}
+*/
+
+#[derive(Clone, Copy, Hash, Debug)]
+pub enum MetaSpec {
+ Minus,
+ Plus,
+ Either,
+ RequiresExpansion,
+ RequiresExpansionWithArgument(usize),
+}
#[derive(Debug, Clone)]
pub enum Declaration {
- Dynamic(ClauseName, usize), // name, arity
- EndOfFile,
- Hook(CompileTimeHook, PredicateClause, VecDeque<TopLevel>),
- ModuleInitialization(Vec<QueryTerm>, VecDeque<TopLevel>), // goal
+ Dynamic(ClauseName, usize),
+ MetaPredicate(ClauseName, ClauseName, Vec<MetaSpec>), // module name, name, meta-specs
Module(ModuleDecl),
- MultiFile(MultiFileIndicator),
NonCountedBacktracking(ClauseName, usize), // name, arity
Op(OpDecl),
- SetPrologFlag(DoubleQuotes),
UseModule(ModuleSource),
- UseQualifiedModule(ModuleSource, Vec<ModuleExport>),
+ UseQualifiedModule(ModuleSource, IndexSet<ModuleExport>),
}
-impl Declaration {
- #[inline]
- pub fn is_module_decl(&self) -> bool {
- if let &Declaration::Module(_) = self {
- true
- } else {
- false
- }
- }
-
- #[inline]
- pub fn is_end_of_file(&self) -> bool {
- if let &Declaration::EndOfFile = self {
- true
- } else {
- false
- }
- }
+#[derive(Debug, Clone, Eq, Hash, PartialEq, Ord, PartialOrd)]
+pub struct OpDecl {
+ pub prec: usize,
+ pub spec: Specifier,
+ pub name: ClauseName
}
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
-
impl OpDecl {
#[inline]
- pub fn name(&self) -> ClauseName {
- self.2.clone()
+ pub fn new(prec: usize, spec: Specifier, name: ClauseName) -> Self {
+ Self { prec, spec, name }
}
#[inline]
- pub fn remove(&self, op_dir: &mut OpDir) {
- self.insert_into_op_dir(clause_name!(""), op_dir, 0);
+ pub fn remove(&mut self, op_dir: &mut OpDir) {
+ let prec = self.prec;
+ self.prec = 0;
+
+ self.insert_into_op_dir(op_dir);
+ self.prec = prec;
}
#[inline]
pub fn fixity(&self) -> Fixity {
- match self.1 {
+ match self.spec {
XFY | XFX | YFX => Fixity::In,
XF | YF => Fixity::Post,
FX | FY => Fixity::Pre,
}
}
- pub fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) {
- let (spec, name) = (self.1, self.2.clone());
-
- let fixity = self.fixity();
+ pub fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<(usize, Specifier)> {
+ let key = (self.name.clone(), self.fixity());
- match op_dir.get(&(name.clone(), fixity)) {
+ match op_dir.get(&key) {
Some(cell) => {
- cell.shared_op_desc().set(prec, spec);
- return;
+ return Some(cell.shared_op_desc().replace((self.prec, self.spec)));
+ }
+ None => {
}
- None => {}
}
- op_dir.insert((name, fixity), OpDirValue::new(spec, prec, module));
+ op_dir.insert(key, OpDirValue::new(self.spec, self.prec))
+ .map(|op_dir_value| op_dir_value.shared_op_desc().get())
}
pub fn submit(
&self,
- module: ClauseName,
existing_desc: Option<OpDesc>,
op_dir: &mut OpDir,
) -> Result<(), SessionError> {
- let (prec, spec, name) = (self.0, self.1, self.2.clone());
+ let (spec, name) = (self.spec, self.name.clone());
if is_infix!(spec) {
if let Some(desc) = existing_desc {
}
}
- Ok(self.insert_into_op_dir(module, op_dir, prec))
+ self.insert_into_op_dir(op_dir);
+ Ok(())
}
}
match arity {
2 => op_dir
.get(&(name, Fixity::In))
- .and_then(|OpDirValue(spec, _)| {
+ .and_then(|OpDirValue(spec)| {
if spec.prec() > 0 {
Some(spec.clone())
} else {
}
}),
1 => {
- if let Some(OpDirValue(spec, _)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
+ if let Some(OpDirValue(spec)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
if spec.prec() > 0 {
return Some(spec.clone());
}
}
op_dir
- .get(&(name, Fixity::Post))
- .and_then(|OpDirValue(spec, _)| {
+ .get(&(name.clone(), Fixity::Post))
+ .and_then(|OpDirValue(spec)| {
if spec.prec() > 0 {
Some(spec.clone())
} else {
pub type ModuleDir = IndexMap<ClauseName, Module>;
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum ModuleExport {
OpDecl(OpDecl),
PredicateKey(PredicateKey),
#[derive(Debug)]
pub struct Module {
- pub atom_tbl: TabledData<Atom>,
pub module_decl: ModuleDecl,
pub code_dir: CodeDir,
pub op_dir: OpDir,
- pub term_dir: TermDir, // this contains multifile predicates.
- pub term_expansions: (Predicate, VecDeque<TopLevel>),
- pub goal_expansions: (Predicate, VecDeque<TopLevel>),
- pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope.
- pub user_goal_expansions: (Predicate, VecDeque<TopLevel>), // same for goal_expansions.
- pub local_term_expansions: (Predicate, VecDeque<TopLevel>), // expansions local to the module.
- pub local_goal_expansions: (Predicate, VecDeque<TopLevel>),
- pub inserted_expansions: bool, // has the module been successfully inserted into toplevel??
+ pub meta_predicates: MetaPredicateDir,
+ pub extensible_predicates: IndexMap<PredicateKey, PredicateSkeleton>,
pub is_impromptu_module: bool,
pub listing_src: ListingSource,
- }
+ pub clause_assert_margin: usize,
+}
+
+// Module's and related types are defined in forms.
+impl Module {
+ pub fn new(module_decl: ModuleDecl, listing_src: ListingSource) -> Self {
+ Module {
+ module_decl,
+ code_dir: CodeDir::new(),
+ op_dir: default_op_dir(),
+ meta_predicates: MetaPredicateDir::new(),
+ is_impromptu_module: false,
+ extensible_predicates: IndexMap::new(),
+ listing_src,
+ clause_assert_margin: 0,
+ }
+ }
+}
+
#[derive(Debug, Clone)]
pub enum Number {
}
}
}
+
+#[derive(Debug, Clone)]
+pub enum OptArgIndexKey {
+ Constant(usize, usize, Constant, Vec<Constant>), // index, IndexingCode location, opt arg, alternatives
+ List(usize, usize), // index, IndexingCode location
+ None,
+ Structure(usize, usize, ClauseName, usize), // index, IndexingCode location, name, arity
+}
+
+impl OptArgIndexKey {
+ #[inline]
+ pub fn take(&mut self) -> OptArgIndexKey {
+ std::mem::replace(self, OptArgIndexKey::None)
+ }
+
+ #[inline]
+ pub fn arg_num(&self) -> usize {
+ match &self {
+ OptArgIndexKey::Constant(arg_num, ..) |
+ OptArgIndexKey::Structure(arg_num, ..) |
+ OptArgIndexKey::List(arg_num, _) => {
+ // these are always at least 1.
+ *arg_num
+ }
+ OptArgIndexKey::None => {
+ 0
+ }
+ }
+ }
+
+ #[inline]
+ pub fn is_some(&self) -> bool {
+ self.switch_on_term_loc().is_some()
+ }
+
+ #[inline]
+ pub fn switch_on_term_loc(&self) -> Option<usize> {
+ match &self {
+ OptArgIndexKey::Constant(_, loc, ..) |
+ OptArgIndexKey::Structure(_, loc, ..) |
+ OptArgIndexKey::List(_, loc) => {
+ Some(*loc)
+ }
+ OptArgIndexKey::None => {
+ None
+ }
+ }
+ }
+
+ #[inline]
+ pub fn set_switch_on_term_loc(&mut self, value: usize) {
+ match self {
+ OptArgIndexKey::Constant(_, ref mut loc, ..) |
+ OptArgIndexKey::Structure(_, ref mut loc, ..) |
+ OptArgIndexKey::List(_, ref mut loc) => {
+ *loc = value;
+ }
+ OptArgIndexKey::None => {
+ }
+ }
+ }
+}
+
+impl AddAssign<usize> for OptArgIndexKey {
+ #[inline]
+ fn add_assign(&mut self, n: usize) {
+ match self {
+ OptArgIndexKey::Constant(_, ref mut o, ..) |
+ OptArgIndexKey::List(_, ref mut o) |
+ OptArgIndexKey::Structure(_, ref mut o, ..) => {
+ *o += n;
+ }
+ OptArgIndexKey::None => {
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct ClauseIndexInfo {
+ pub clause_start: usize,
+ pub opt_arg_index_key: OptArgIndexKey,
+}
+
+impl ClauseIndexInfo {
+ #[inline]
+ pub fn new(clause_start: usize) -> Self {
+ Self {
+ clause_start,
+ opt_arg_index_key: OptArgIndexKey::None,
+ // index_locs: vec![],
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct PredicateSkeleton {
+ pub is_discontiguous: bool,
+ pub is_dynamic: bool,
+ pub is_multifile: bool,
+ pub clauses: SliceDeque<ClauseIndexInfo>,
+ pub clause_clause_locs: SliceDeque<usize>,
+}
+
+impl PredicateSkeleton {
+ #[inline]
+ pub fn new() -> Self {
+ PredicateSkeleton {
+ is_discontiguous: false,
+ is_dynamic: false,
+ is_multifile: false,
+ clauses: sdeq![],
+ clause_clause_locs: sdeq![],
+ }
+ }
+
+ /*
+ #[inline]
+ pub fn set_discontiguous(self, is_discontiguous: bool) -> Self {
+ PredicateSkeleton {
+ is_discontiguous,
+ is_dynamic: self.is_dynamic,
+ is_multifile: self.is_multifile,
+ clauses: self.clauses,
+ }
+ }
+ */
+
+ #[inline]
+ pub fn set_dynamic(self, is_dynamic: bool) -> Self {
+ PredicateSkeleton {
+ is_discontiguous: self.is_discontiguous,
+ is_dynamic,
+ is_multifile: self.is_multifile,
+ clauses: self.clauses,
+ clause_clause_locs: self.clause_clause_locs,
+ }
+ }
+
+ /*
+ #[inline]
+ pub fn set_multifile(self, is_multifile: bool) -> Self {
+ PredicateSkeleton {
+ is_discontiguous: self.is_discontiguous,
+ is_dynamic: self.is_dynamic,
+ is_multifile,
+ clauses: self.clauses,
+ }
+ }
+ */
+}
| HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
Addr::Con(h)
}
+ HeapCellValue::LoadStatePayload(_) => {
+ Addr::LoadStatePayload(h)
+ }
HeapCellValue::Stream(_) => {
Addr::Stream(h)
}
- &HeapCellValue::TcpListener(_) => {
+ HeapCellValue::TcpListener(_) => {
Addr::TcpListener(h)
}
}
}
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
match &self.machine_st.heap[h] {
- &HeapCellValue::PartialString(ref pstr, _) => {
+ &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)));
- }
+ */
+ // self.parent_stack.push((2, Addr::PStrLocation(h, next_n)));
+ // }
+
+ self.parent_stack.push((2, Addr::PStrLocation(h, n)));
}
_ => {
unreachable!()
}
}
+/*
fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict {
machine_st
.heap_locs
})
.collect()
}
+*/
fn non_quoted_graphic_token<Iter: Iterator<Item = char>>(mut iter: Iter, c: char) -> bool {
if c == '/' {
max_depth: 0,
}
}
-
+/*
pub fn from_heap_locs(
machine_st: &'a MachineState,
op_dir: &'a OpDir,
printer
}
-
+*/
+/*
pub fn drop_toplevel_spec(&mut self) {
self.toplevel_spec = None;
}
-
+*/
+/*
#[inline]
pub fn see_all_locs(&mut self) {
for key in self.heap_locs.keys().cloned() {
self.printed_vars.insert(key);
}
}
+*/
#[inline]
fn ambiguity_check(&self, atom: &str) -> bool {
fn print_rational(&mut self, r: &Rational, add_brackets: bool) {
match self.op_dir.get(&(clause_name!("rdiv"), Fixity::In)) {
- Some(OpDirValue(ref spec, _)) => {
+ Some(OpDirValue(ref spec)) => {
if add_brackets {
self.state_stack.push(TokenOrRedirect::Close);
}
use crate::prolog_parser::ast::*;
use crate::prolog_parser::tabled_rc::*;
+use crate::forms::*;
use crate::instructions::*;
-use crate::rug::Integer;
use crate::indexmap::IndexMap;
+use crate::rug::Integer;
+
+use slice_deque::{sdeq, SliceDeque};
-use std::collections::VecDeque;
use std::convert::TryFrom;
use std::hash::Hash;
+use std::iter::once;
use std::rc::Rc;
#[derive(Debug, Clone, Copy)]
-enum IntIndex {
- External(usize),
+pub enum IndexingCodePtr {
+ External(usize), // the index points past the indexing instruction prelude.
Fail,
- Internal(usize),
+ Internal(usize), // the index points into the indexing instruction prelude.
}
-#[derive(Debug)]
-pub struct CodeOffsets {
- atom_tbl: TabledData<Atom>,
- pub constants: IndexMap<Constant, ThirdLevelIndex>,
- pub lists: ThirdLevelIndex,
- pub structures: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
+impl IndexingCodePtr {
+ #[inline]
+ fn is_internal(self) -> bool {
+ if let IndexingCodePtr::Internal(_) = self {
+ true
+ } else {
+ false
+ }
+ }
}
-impl CodeOffsets {
- pub fn new() -> Self {
- CodeOffsets {
- atom_tbl: TabledData::new(Rc::new("_index".to_string())),
- constants: IndexMap::new(),
- lists: Vec::new(),
- structures: IndexMap::new(),
+#[derive(Debug, Clone, Copy)]
+enum OptArgIndexKeyType {
+ Structure,
+ Constant,
+ List,
+}
+
+impl OptArgIndexKey {
+ #[inline]
+ fn has_key_type(&self, key_type: OptArgIndexKeyType) -> bool {
+ match (self, key_type) {
+ (OptArgIndexKey::Constant(..), OptArgIndexKeyType::Constant) |
+ (OptArgIndexKey::Structure(..), OptArgIndexKeyType::Structure) |
+ (OptArgIndexKey::List(..), OptArgIndexKeyType::List) => {
+ true
+ }
+ _ => {
+ false
+ }
}
}
+}
- fn cap_choice_seq_with_trust(prelude: &mut ThirdLevelIndex) {
- prelude.last_mut().map(|instr| {
- match instr {
- &mut IndexedChoiceInstruction::Retry(i) => {
- *instr = IndexedChoiceInstruction::Trust(i)
- }
- _ => {}
- };
- });
+#[inline]
+fn search_skeleton_for_first_key_type(
+ skeleton: &[ClauseIndexInfo],
+ key_type: OptArgIndexKeyType,
+ append_or_prepend: AppendOrPrepend,
+) -> Option<&OptArgIndexKey> {
+ if append_or_prepend.is_append() {
+ for clause_index_info in skeleton.iter().rev() {
+ if clause_index_info.opt_arg_index_key.has_key_type(key_type) {
+ return Some(&clause_index_info.opt_arg_index_key);
+ }
+ }
+ } else {
+ for clause_index_info in skeleton.iter() {
+ if clause_index_info.opt_arg_index_key.has_key_type(key_type) {
+ return Some(&clause_index_info.opt_arg_index_key);
+ }
+ }
+ }
+
+ None
+}
+
+struct IndexingCodeMergingPtr<'a> {
+ skeleton: &'a mut [ClauseIndexInfo],
+ // merged_clause_index: usize,
+ indexing_code: &'a mut Vec<IndexingLine>,
+ offset: usize,
+ append_or_prepend: AppendOrPrepend,
+}
+
+impl<'a> IndexingCodeMergingPtr<'a> {
+ #[inline]
+ fn new(
+ skeleton: &'a mut [ClauseIndexInfo],
+ indexing_code: &'a mut Vec<IndexingLine>,
+ append_or_prepend: AppendOrPrepend,
+ ) -> Self {
+ Self { skeleton, indexing_code, offset: 0, append_or_prepend }
}
- fn add_index(is_first_index: bool, index: usize) -> IndexedChoiceInstruction {
- if is_first_index {
- IndexedChoiceInstruction::Try(index)
+ fn internalize_constant(&mut self, constant_ptr: IndexingCodePtr) {
+ let constant_key =
+ search_skeleton_for_first_key_type(
+ self.skeleton,
+ OptArgIndexKeyType::Constant,
+ self.append_or_prepend,
+ );
+
+ let mut constants = IndexMap::new();
+
+ match constant_key {
+ Some(OptArgIndexKey::Constant(_, _, ref constant, _)) => {
+ constants.insert(constant.clone(), constant_ptr);
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+
+ if let IndexingCodePtr::Internal(_) = constant_ptr {
+ self.indexing_code.push(IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(constants)
+ ));
+
+ let last_index = self.indexing_code.len() - 1;
+ self.indexing_code.swap(self.offset, last_index);
} else {
- IndexedChoiceInstruction::Retry(index)
+ self.offset = self.indexing_code.len();
+
+ self.indexing_code.push(IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(constants)
+ ));
}
}
- fn intercept_overlapping_constant(&mut self, constant: &Constant, index: usize) {
- match constant {
- &Constant::Atom(ref name, ref op) if name.is_char() => {
- let c = name.as_str().chars().next().unwrap();
- let code = self.constants
- .entry(Constant::Char(c))
- .or_insert(vec![]);
+ fn add_indexed_choice_for_constant(&mut self, external: usize, constant: Constant, index: usize)
+ {
+ let third_level_index =
+ if self.append_or_prepend.is_append() {
+ sdeq![
+ IndexedChoiceInstruction::Try(external),
+ IndexedChoiceInstruction::Trust(index)
+ ]
+ } else {
+ sdeq![
+ IndexedChoiceInstruction::Try(index),
+ IndexedChoiceInstruction::Trust(external)
+ ]
+ };
- code.push(Self::add_index(code.is_empty(), index));
+ let indexing_code_len = self.indexing_code.len();
+ self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index));
- if op.is_some() {
- let code = self.constants
- .entry(Constant::Atom(name.clone(), None))
- .or_insert(vec![]);
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(ref mut constants)
+ ) => {
+ constants.insert(constant, IndexingCodePtr::Internal(indexing_code_len - self.offset));
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
- code.push(Self::add_index(false, index));
+ fn extend_indexed_choice(&mut self, index: usize) {
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::IndexedChoice(ref mut indexed_choice_instrs)
+ if self.append_or_prepend.is_append() => {
+ uncap_choice_seq_with_trust(indexed_choice_instrs);
+ indexed_choice_instrs.push_back(IndexedChoiceInstruction::Trust(index));
}
+ IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => {
+ uncap_choice_seq_with_try(indexed_choice_instrs);
+ indexed_choice_instrs.push_front(IndexedChoiceInstruction::Try(index));
}
- &Constant::Atom(ref name, Some(_)) => {
- let code = self.constants
- .entry(Constant::Atom(name.clone(), None))
- .or_insert(vec![]);
-
- code.push(Self::add_index(code.is_empty(), index));
+ _ => {
+ unreachable!()
}
- &Constant::Char(c) => {
- let atom = clause_name!(c.to_string(), self.atom_tbl.clone());
+ }
+ }
- let code = self.constants
- .entry(Constant::Atom(atom, None))
- .or_insert(vec![]);
+ fn index_overlapping_constant(
+ &mut self,
+ orig_constant: &Constant,
+ overlapping_constant: Constant,
+ index: usize,
+ ) {
+ loop {
+ let indexing_code_len = self.indexing_code.len();
- 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![]);
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)
+ ) => {
+ match *c {
+ IndexingCodePtr::Fail => {
+ *c = IndexingCodePtr::External(index);
+ break;
+ }
+ IndexingCodePtr::External(_) => {
+ let mut constants = IndexMap::new();
+ constants.insert(orig_constant.clone(), *c);
- code.push(Self::add_index(code.is_empty(), index));
+ *c = IndexingCodePtr::Internal(indexing_code_len);
- if n >= 0 {
- if let Ok(n) = usize::try_from(n) {
- let code = self.constants
- .entry(Constant::Usize(n))
- .or_insert(vec![]);
+ self.indexing_code.push(IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(constants)
+ ));
- code.push(Self::add_index(code.is_empty(), index));
+ self.offset = indexing_code_len;
+ }
+ IndexingCodePtr::Internal(o) => {
+ self.offset += o;
+ }
}
}
- }
- &Constant::Integer(ref n) => {
- if let Some(n) = n.to_isize() {
- let code = self.constants
- .entry(Constant::Fixnum(n))
- .or_insert(vec![]);
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(constants)
+ ) => {
+ match constants.get(&overlapping_constant).cloned() {
+ None | Some(IndexingCodePtr::Fail) => {
+ constants.insert(overlapping_constant, IndexingCodePtr::External(index));
+ }
+ Some(IndexingCodePtr::External(o)) => {
+ self.add_indexed_choice_for_constant(o, overlapping_constant, index);
+ }
+ Some(IndexingCodePtr::Internal(o)) => {
+ self.offset += o;
+ self.extend_indexed_choice(index);
+ }
+ }
- code.push(Self::add_index(code.is_empty(), index));
+ break;
+ }
+ IndexingLine::IndexedChoice(_) => {
+ self.internalize_constant(
+ IndexingCodePtr::Internal(indexing_code_len - self.offset),
+ );
+ }
+ _ => {
+ unreachable!()
}
+ }
+ }
+ }
- if let Some(n) = n.to_usize() {
- let code = self.constants
- .entry(Constant::Usize(n))
- .or_insert(vec![]);
+ fn index_constant(&mut self, constant: Constant, index: usize) {
+ loop {
+ let indexing_code_len = self.indexing_code.len();
+
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)
+ ) => {
+ match *c {
+ IndexingCodePtr::Fail => {
+ *c = IndexingCodePtr::External(index);
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ *c = IndexingCodePtr::Internal(indexing_code_len - self.offset);
+ self.internalize_constant(IndexingCodePtr::External(o));
+ }
+ IndexingCodePtr::Internal(o) => {
+ self.offset += o;
+ }
+ }
+ }
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(constants)
+ ) => {
+ match constants.get(&constant).cloned() {
+ None | Some(IndexingCodePtr::Fail) => {
+ constants.insert(constant, IndexingCodePtr::External(index));
+ }
+ Some(IndexingCodePtr::External(o)) => {
+ self.add_indexed_choice_for_constant(o, constant, index);
+ }
+ Some(IndexingCodePtr::Internal(o)) => {
+ self.offset += o;
+ self.extend_indexed_choice(index);
+ }
+ }
- code.push(Self::add_index(code.is_empty(), index));
+ break;
+ }
+ IndexingLine::IndexedChoice(_) => {
+ self.internalize_constant(
+ IndexingCodePtr::Internal(indexing_code_len - self.offset),
+ );
+ }
+ _ => {
+ unreachable!()
}
}
- &Constant::Usize(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));
+ fn internalize_structure(&mut self, structure_ptr: IndexingCodePtr) {
+ let structure_key =
+ search_skeleton_for_first_key_type(
+ self.skeleton,
+ OptArgIndexKeyType::Structure,
+ self.append_or_prepend,
+ );
- if let Ok(n) = isize::try_from(n) {
- let code = self.constants
- .entry(Constant::Fixnum(n))
- .or_insert(vec![]);
+ let mut structures = IndexMap::new();
- code.push(Self::add_index(code.is_empty(), index));
- }
+ match structure_key {
+ Some(OptArgIndexKey::Structure(_, _, ref name, ref arity)) => {
+ structures.insert((name.clone(), *arity), structure_ptr);
}
_ => {
+ unreachable!()
}
}
+
+ if let IndexingCodePtr::Internal(_) = structure_ptr {
+ self.indexing_code.push(IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(structures)
+ ));
+
+ let last_index = self.indexing_code.len() - 1;
+ self.indexing_code.swap(self.offset, last_index);
+ } else {
+ self.offset = self.indexing_code.len();
+
+ self.indexing_code.push(IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(structures)
+ ));
+ }
}
- pub fn index_term(&mut self, optimal_arg: &Term, index: usize) {
- match optimal_arg {
- &Term::Clause(_, ref name, ref terms, _) => {
- let code = self
- .structures
- .entry((name.clone(), terms.len()))
- .or_insert(Vec::new());
+ fn add_indexed_choice_for_structure(&mut self, external: usize, key: PredicateKey, index: usize)
+ {
+ let third_level_index =
+ if self.append_or_prepend.is_append() {
+ sdeq![
+ IndexedChoiceInstruction::Try(external),
+ IndexedChoiceInstruction::Trust(index)
+ ]
+ } else {
+ sdeq![
+ IndexedChoiceInstruction::Try(index),
+ IndexedChoiceInstruction::Trust(external)
+ ]
+ };
+
+ let indexing_code_len = self.indexing_code.len();
+ self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index));
- let is_initial_index = code.is_empty();
- code.push(Self::add_index(is_initial_index, index));
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(ref mut structures)
+ ) => {
+ structures.insert(key, IndexingCodePtr::Internal(indexing_code_len - self.offset));
}
- &Term::Cons(..) | &Term::Constant(_, Constant::String(_)) => {
- let is_initial_index = self.lists.is_empty();
- self.lists.push(Self::add_index(is_initial_index, index));
+ _ => {
+ unreachable!()
}
- &Term::Constant(_, ref constant) => {
- self.intercept_overlapping_constant(constant, index);
+ }
+ }
+
+ fn index_structure(&mut self, key: PredicateKey, index: usize) {
+ loop {
+ let indexing_code_len = self.indexing_code.len();
+
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s)
+ ) => {
+ match *s {
+ IndexingCodePtr::Fail => {
+ *s = IndexingCodePtr::External(index);
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ *s = IndexingCodePtr::Internal(indexing_code_len - self.offset);
+ self.internalize_structure(IndexingCodePtr::External(o));
+ }
+ IndexingCodePtr::Internal(o) => {
+ self.offset += o;
+ }
+ }
+ }
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(structures)
+ ) => {
+ match structures.get(&key).cloned() {
+ None | Some(IndexingCodePtr::Fail) => {
+ structures.insert(key, IndexingCodePtr::External(index));
+ }
+ Some(IndexingCodePtr::External(o)) => {
+ self.add_indexed_choice_for_structure(o, key, index);
+ }
+ Some(IndexingCodePtr::Internal(o)) => {
+ self.offset += o;
+ self.extend_indexed_choice(index);
+ }
+ }
+
+ break;
+ }
+ IndexingLine::IndexedChoice(_) => {
+ // replace this value, at self.offset, with
+ // SwitchOnStructures, and swap this IndexedChoice
+ // vector to the end of self.indexing_code.
+ self.internalize_structure(
+ IndexingCodePtr::Internal(indexing_code_len - self.offset),
+ );
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+
+ fn index_list(&mut self, index: usize) {
+ let indexing_code_len = self.indexing_code.len();
+
+ match &mut self.indexing_code[self.offset] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)
+ ) => {
+ match *l {
+ IndexingCodePtr::Fail => {
+ *l = IndexingCodePtr::External(index);
+ }
+ IndexingCodePtr::External(o) => {
+ *l = IndexingCodePtr::Internal(indexing_code_len - self.offset);
- let code = self.constants
- .entry(constant.clone())
- .or_insert(vec![]);
+ let third_level_index =
+ if self.append_or_prepend.is_append() {
+ sdeq![
+ IndexedChoiceInstruction::Try(o),
+ IndexedChoiceInstruction::Trust(index)
+ ]
+ } else {
+ sdeq![
+ IndexedChoiceInstruction::Try(index),
+ IndexedChoiceInstruction::Trust(o)
+ ]
+ };
- let is_initial_index = code.is_empty();
- code.push(Self::add_index(is_initial_index, index));
+ self.indexing_code.push(
+ IndexingLine::IndexedChoice(third_level_index),
+ );
+ }
+ IndexingCodePtr::Internal(o) => {
+ self.offset += o;
+ self.extend_indexed_choice(index);
+ }
+ }
}
_ => {
+ unreachable!()
+ }
+ }
+ }
+}
+
+pub fn merge_clause_index(
+ target_indexing_code: &mut Vec<IndexingLine>,
+ skeleton: &mut [ClauseIndexInfo], // the clause to be merged is the last element in the skeleton.
+ new_clause_loc: usize, // the absolute location of the new clause in the code vector.
+ append_or_prepend: AppendOrPrepend,
+) {
+ let opt_arg_index_key =
+ match append_or_prepend {
+ AppendOrPrepend::Append => {
+ skeleton.last_mut().unwrap().opt_arg_index_key.take()
+ }
+ AppendOrPrepend::Prepend => {
+ skeleton.first_mut().unwrap().opt_arg_index_key.take()
}
};
+
+ let mut merging_ptr = IndexingCodeMergingPtr::new(
+ skeleton,
+ target_indexing_code,
+ append_or_prepend,
+ );
+
+ match &opt_arg_index_key {
+ OptArgIndexKey::Constant(_, index_loc, ref constant, ref overlapping_constants) => {
+ let offset = new_clause_loc - index_loc + 1;
+ merging_ptr.index_constant(constant.clone(), offset);
+
+ for overlapping_constant in overlapping_constants {
+ merging_ptr.index_overlapping_constant(
+ constant, overlapping_constant.clone(), offset,
+ );
+ }
+ }
+ OptArgIndexKey::Structure(_, index_loc, ref name, ref arity) => {
+ merging_ptr.index_structure((name.clone(), *arity), new_clause_loc - index_loc + 1);
+ }
+ OptArgIndexKey::List(_, index_loc) => {
+ merging_ptr.index_list(new_clause_loc - index_loc + 1);
+ }
+ OptArgIndexKey::None => {
+ unreachable!()
+ }
}
- fn second_level_index<Index>(
- indices: IndexMap<Index, ThirdLevelIndex>,
- prelude: &mut CodeDeque,
- ) -> IndexMap<Index, IntIndex>
- where
- Index: Eq + Hash,
- {
- let mut index_locs = IndexMap::new();
+ match append_or_prepend {
+ AppendOrPrepend::Append => {
+ skeleton.last_mut().unwrap().opt_arg_index_key = opt_arg_index_key;
+ }
+ AppendOrPrepend::Prepend => {
+ skeleton.first_mut().unwrap().opt_arg_index_key = opt_arg_index_key;
+ }
+ }
+}
- for (key, mut code) in indices.into_iter() {
- if code.len() > 1 {
- index_locs.insert(key, IntIndex::Internal(prelude.len()));
- Self::cap_choice_seq_with_trust(&mut code);
- prelude.extend(code.into_iter().map(|code| Line::from(code)));
- } else {
- code.first().map(|i| {
- index_locs.insert(key, IntIndex::External(i.offset()));
- });
+#[inline]
+fn remove_instruction_with_offset(
+ code: &mut SliceDeque<IndexedChoiceInstruction>,
+ offset: usize,
+) {
+ for (index, line) in code.iter().enumerate() {
+ if offset == line.offset() {
+ code.remove(index);
+ cap_choice_seq(code);
+ return;
+ }
+ }
+}
+
+pub fn remove_constant_indices(
+ constant: &Constant,
+ overlapping_constants: &[Constant],
+ indexing_code: &mut Vec<IndexingLine>,
+ offset: usize,
+) {
+ let mut index = 0;
+ let iter = once(constant).chain(overlapping_constants.iter());
+
+ match &mut indexing_code[index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)
+ ) => {
+ match *c {
+ IndexingCodePtr::External(_) => {
+ *c = IndexingCodePtr::Fail;
+ return;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
+ IndexingCodePtr::Fail => {
+ return;
+ }
}
}
+ _ => {
+ unreachable!()
+ }
+ }
- index_locs
+ let mut constants_index = 0;
+
+ for constant in iter { // (constant, index_loc) in iter.zip(index_locs.iter()) {
+ loop {
+ match &mut indexing_code[index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(ref mut constants)
+ ) => {
+ constants_index = index;
+
+ match constants.get(constant).cloned() {
+ Some(IndexingCodePtr::External(_)) => {
+ constants.remove(constant);
+ break;
+ }
+ Some(IndexingCodePtr::Internal(o)) => {
+ index += o;
+ }
+ Some(IndexingCodePtr::Fail) | None => {
+ unreachable!()
+ }
+ }
+ }
+ IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => {
+ remove_instruction_with_offset(indexed_choice_instrs, offset);
+
+ if indexed_choice_instrs.len() == 1 {
+ let ext = IndexingCodePtr::External(
+ indexed_choice_instrs.pop_back().unwrap().offset()
+ );
+
+ match &mut indexing_code[constants_index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)
+ ) => {
+ *c = ext;
+ }
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(ref mut constants)
+ ) => {
+ constants.insert(constant.clone(), ext);
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+
+ break;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
}
- fn no_indices(&self) -> bool {
- let no_constants = self.constants.is_empty();
- let no_structures = self.structures.is_empty();
- let no_lists = self.lists.is_empty();
+ match &indexing_code[constants_index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnConstant(ref constants)
+ ) if constants.is_empty() => {
+ match &mut indexing_code[0] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)
+ ) => {
+ *c = IndexingCodePtr::Fail;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ _ => {
+ }
+ }
+}
- no_constants && no_structures && no_lists
+pub fn remove_structure_index(
+ name: &ClauseName,
+ arity: usize,
+ indexing_code: &mut Vec<IndexingLine>,
+ offset: usize,
+) {
+ let mut index = 0;
+
+ match &mut indexing_code[index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s)
+ ) => {
+ match *s {
+ IndexingCodePtr::External(_) => {
+ *s = IndexingCodePtr::Fail;
+ return;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
+ IndexingCodePtr::Fail => {
+ return;
+ }
+ }
+ }
+ _ => {
+ unreachable!()
+ }
}
- fn flatten_index<Index>(index: IndexMap<Index, IntIndex>, len: usize) -> IndexMap<Index, usize>
- where
- Index: Eq + Hash,
- {
- let mut flattened_index = IndexMap::new();
+ let mut structures_index = 0;
+
+ loop {
+ match &mut indexing_code[index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(ref mut structures)
+ ) => {
+ structures_index = index;
- for (key, int_index) in index.into_iter() {
- match int_index {
- IntIndex::External(offset) => {
- flattened_index.insert(key, offset + len + 1);
+ match structures.get(&(name.clone(), arity)).cloned() {
+ Some(IndexingCodePtr::External(_)) => {
+ structures.remove(&(name.clone(), arity));
+ break;
+ }
+ Some(IndexingCodePtr::Internal(o)) => {
+ index += o;
+ }
+ Some(IndexingCodePtr::Fail) | None => {
+ return;
+ }
}
- IntIndex::Internal(offset) => {
- flattened_index.insert(key, offset + 1);
+ }
+ IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => {
+ remove_instruction_with_offset(indexed_choice_instrs, offset);
+
+ if indexed_choice_instrs.len() == 1 {
+ let ext = IndexingCodePtr::External(
+ indexed_choice_instrs.pop_back().unwrap().offset()
+ );
+
+ match &mut indexing_code[structures_index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s)
+ ) => {
+ *s = ext;
+ }
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(ref mut structures)
+ ) => {
+ structures.insert((name.clone(), arity), ext);
+ }
+ _ => {
+ unreachable!()
+ }
+ }
}
- _ => {}
- };
+
+ break;
+ }
+ _ => {
+ unreachable!()
+ }
}
+ }
- flattened_index
+ match &indexing_code[structures_index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnStructure(ref structures)
+ ) if structures.is_empty() => {
+ match &mut indexing_code[0] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s)
+ ) => {
+ *s = IndexingCodePtr::Fail;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ _ => {
+ }
}
+}
- fn adjust_internal_index(index: IntIndex) -> IntIndex {
- match index {
- IntIndex::Internal(o) => IntIndex::Internal(o + 1),
- IntIndex::External(o) => IntIndex::External(o),
- _ => IntIndex::Fail,
+pub fn remove_list_index(
+ indexing_code: &mut Vec<IndexingLine>,
+ offset: usize,
+) {
+ let mut index = 0;
+
+ match &mut indexing_code[index] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)
+ ) => {
+ match *l {
+ IndexingCodePtr::External(_) => {
+ *l = IndexingCodePtr::Fail;
+ return;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
+ IndexingCodePtr::Fail => {
+ return;
+ }
+ }
+ }
+ _ => {
+ unreachable!()
}
}
- fn switch_on_constant(
- con_ind: IndexMap<Constant, ThirdLevelIndex>,
- prelude: &mut CodeDeque,
- optimal_index: usize,
- ) -> IntIndex {
- let con_ind = Self::second_level_index(con_ind, prelude);
+ match &mut indexing_code[index] {
+ IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => {
+ remove_instruction_with_offset(indexed_choice_instrs, offset);
- if con_ind.len() > 1 {
- let index = Self::flatten_index(con_ind, prelude.len());
- let instr = IndexingInstruction::SwitchOnConstant(
- optimal_index,
- index.len(),
- index
- );
+ if indexed_choice_instrs.len() == 1 {
+ let ext = IndexingCodePtr::External(
+ indexed_choice_instrs.pop_back().unwrap().offset()
+ );
- prelude.push_front(Line::from(instr));
+ match &mut indexing_code[0] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)
+ ) => {
+ *l = ext;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+}
- IntIndex::Internal(1)
- } else {
- con_ind
- .values()
- .next()
- .map(|index| Self::adjust_internal_index(*index))
- .unwrap_or(IntIndex::Fail)
- }
- }
-
- fn switch_on_structure(
- str_ind: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
- prelude: &mut CodeDeque,
- optimal_index: usize,
- ) -> IntIndex {
- let str_ind = Self::second_level_index(str_ind, prelude);
-
- if str_ind.len() > 1 {
- let index = Self::flatten_index(str_ind, prelude.len());
- let instr = IndexingInstruction::SwitchOnStructure(
- optimal_index,
- index.len(),
- index
+pub fn remove_index(
+ //skeleton: &[ClauseIndexInfo],
+ opt_arg_index_key: &OptArgIndexKey,
+ indexing_code: &mut Vec<IndexingLine>,
+ clause_loc: usize,
+) {
+ match opt_arg_index_key {
+ OptArgIndexKey::Constant(_, _, ref constant, ref overlapping_constants) => {
+ remove_constant_indices(
+ constant,
+ overlapping_constants,
+ indexing_code,
+ clause_loc,
+ //&skeleton[index].index_locs,
+ );
+ }
+ OptArgIndexKey::Structure(_, _, ref name, ref arity) => {
+ remove_structure_index(
+ name,
+ *arity,
+ indexing_code,
+ clause_loc,
+ //&skeleton[index].index_locs,
+ );
+ }
+ OptArgIndexKey::List(..) => {
+ remove_list_index(
+ indexing_code,
+ clause_loc,
+ //&skeleton[index].index_locs,
);
+ }
+ OptArgIndexKey::None => {
+ unreachable!()
+ }
+ }
+}
- prelude.push_front(Line::from(instr));
+fn second_level_index<IndexKey: Eq + Hash>(
+ indices: IndexMap<IndexKey, SliceDeque<IndexedChoiceInstruction>>,
+ prelude: &mut SliceDeque<IndexingLine>,
+) -> IndexMap<IndexKey, IndexingCodePtr>
+{
+ let mut index_locs = IndexMap::new();
- IntIndex::Internal(1)
+ for (key, mut code) in indices.into_iter() {
+ if code.len() > 1 {
+ index_locs.insert(key, IndexingCodePtr::Internal(prelude.len() + 1));
+ cap_choice_seq_with_trust(&mut code);
+ prelude.push_back(IndexingLine::from(code));
} else {
- str_ind
- .values()
- .next()
- .map(|index| Self::adjust_internal_index(*index))
- .unwrap_or(IntIndex::Fail)
+ code.first().map(|i| {
+ index_locs.insert(key, IndexingCodePtr::External(i.offset()));
+ });
}
}
- fn switch_on_list(mut lists: ThirdLevelIndex, prelude: &mut CodeDeque) -> IntIndex {
- if lists.len() > 1 {
- Self::cap_choice_seq_with_trust(&mut lists);
- prelude.extend(lists.into_iter().map(|i| Line::from(i)));
- IntIndex::Internal(0)
- } else {
- lists
- .first()
- .map(|i| IntIndex::External(i.offset()))
- .unwrap_or(IntIndex::Fail)
- }
+ index_locs
+}
+
+fn switch_on<IndexKey: Eq + Hash>(
+ instr_fn: impl Fn(IndexMap<IndexKey, IndexingCodePtr>) -> IndexingInstruction,
+ index: IndexMap<IndexKey, SliceDeque<IndexedChoiceInstruction>>,
+ prelude: &mut SliceDeque<IndexingLine>,
+) -> IndexingCodePtr {
+ let index = second_level_index(index, prelude);
+
+ if index.len() > 1 {
+ let instr = instr_fn(index);
+ prelude.push_front(IndexingLine::from(instr));
+
+ IndexingCodePtr::Internal(1)
+ } else {
+ index.into_iter()
+ .next()
+ .map(|(_, v)| v)
+ .unwrap_or(IndexingCodePtr::Fail)
+ }
+}
+
+fn switch_on_list(
+ mut lists: SliceDeque<IndexedChoiceInstruction>,
+ prelude: &mut SliceDeque<IndexingLine>,
+) -> IndexingCodePtr {
+ if lists.len() > 1 {
+ cap_choice_seq_with_trust(&mut lists);
+ prelude.push_back(IndexingLine::from(lists));
+ IndexingCodePtr::Internal(1)
+ } else {
+ lists.first()
+ .map(|i| IndexingCodePtr::External(i.offset()))
+ .unwrap_or(IndexingCodePtr::Fail)
}
+}
+
+#[inline]
+fn cap_choice_seq(prelude: &mut [IndexedChoiceInstruction]) {
+ prelude.first_mut().map(|instr| {
+ *instr = IndexedChoiceInstruction::Try(instr.offset());
+ });
+
+ cap_choice_seq_with_trust(prelude);
+}
- fn switch_on_str_offset_from(
- str_loc: IntIndex,
- prelude_len: usize,
- con_loc: IntIndex,
- ) -> usize {
- match str_loc {
- IntIndex::External(o) => o + prelude_len + 1,
- IntIndex::Fail => 0,
- IntIndex::Internal(_) => match con_loc {
- IntIndex::Internal(_) => 2,
- _ => 1,
- },
+#[inline]
+fn cap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
+ prelude.last_mut().map(|instr| {
+ if let IndexedChoiceInstruction::Retry(i) = instr {
+ *instr = IndexedChoiceInstruction::Trust(*i);
}
+ });
+}
+
+#[inline]
+fn uncap_choice_seq_with_trust(prelude: &mut [IndexedChoiceInstruction]) {
+ prelude.last_mut().map(|instr| {
+ if let IndexedChoiceInstruction::Trust(i) = instr {
+ *instr = IndexedChoiceInstruction::Retry(*i);
+ }
+ });
+}
+
+#[inline]
+fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) {
+ prelude.first_mut().map(|instr| {
+ if let IndexedChoiceInstruction::Try(i) = instr {
+ *instr = IndexedChoiceInstruction::Retry(*i);
+ }
+ });
+}
+
+fn compute_index(is_first_index: bool, index: usize) -> IndexedChoiceInstruction {
+ // in either case, increment index to skip the IndexingLine vector.
+ if is_first_index {
+ IndexedChoiceInstruction::Try(index + 1)
+ } else {
+ IndexedChoiceInstruction::Retry(index + 1)
}
+}
+
+pub fn constant_key_alternatives(constant: &Constant, atom_tbl: TabledData<Atom>) -> Vec<Constant> {
+ let mut constants = vec![];
- fn switch_on_con_offset_from(con_loc: IntIndex, prelude_len: usize) -> usize {
- match con_loc {
- IntIndex::External(offset) => offset + prelude_len + 1,
- IntIndex::Fail => 0,
- IntIndex::Internal(offset) => offset,
+ match constant {
+ Constant::Atom(ref name, ref op) => {
+ if name.is_char() {
+ let c = name.as_str().chars().next().unwrap();
+ constants.push(Constant::Char(c));
+ }
+
+ if op.is_some() {
+ constants.push(Constant::Atom(name.clone(), None));
+ }
+ }
+ Constant::Char(c) => {
+ let atom = clause_name!(c.to_string(), atom_tbl);
+ constants.push(Constant::Atom(atom, None));
+ }
+ Constant::Fixnum(ref n) => {
+ constants.push(Constant::Integer(Rc::new(Integer::from(*n))));
+
+ if *n >= 0 {
+ if let Ok(n) = usize::try_from(*n) {
+ constants.push(Constant::Usize(n));
+ }
+ }
+ }
+ Constant::Integer(ref n) => {
+ if let Some(n) = n.to_isize() {
+ constants.push(Constant::Fixnum(n));
+ }
+
+ if let Some(n) = n.to_usize() {
+ constants.push(Constant::Usize(n));
+ }
+ }
+ Constant::Usize(n) => {
+ constants.push(Constant::Integer(Rc::new(Integer::from(*n))));
+
+ if let Ok(n) = isize::try_from(*n) {
+ constants.push(Constant::Fixnum(n));
+ }
+ }
+ _ => {
}
}
- fn switch_on_lst_offset_from(
- lst_loc: IntIndex,
- prelude_len: usize,
- ) -> usize {
- match lst_loc {
- IntIndex::External(o) => o + prelude_len + 1,
- IntIndex::Fail => 0,
- IntIndex::Internal(_) => 1, // this internal is always 0.
+ constants
+}
+
+#[derive(Debug)]
+pub struct CodeOffsets {
+ atom_tbl: TabledData<Atom>,
+ pub constants: IndexMap<Constant, SliceDeque<IndexedChoiceInstruction>>,
+ pub lists: SliceDeque<IndexedChoiceInstruction>,
+ pub structures: IndexMap<(ClauseName, usize), SliceDeque<IndexedChoiceInstruction>>,
+ optimal_index: usize,
+}
+
+impl CodeOffsets {
+ pub fn new(atom_tbl: TabledData<Atom>, optimal_index: usize) -> Self {
+ CodeOffsets {
+ atom_tbl,
+ constants: IndexMap::new(),
+ lists: sdeq![],
+ structures: IndexMap::new(),
+ optimal_index
}
}
- pub fn add_indices(self, code: &mut Code, mut code_body: Code, optimal_index: usize) {
- if self.no_indices() {
- *code = code_body;
- return;
+ fn index_list(&mut self, index: usize) {
+ let is_initial_index = self.lists.is_empty();
+ self.lists.push_back(compute_index(is_initial_index, index));
+ }
+
+ fn index_constant(&mut self, constant: &Constant, index: usize) -> Vec<Constant> {
+ let overlapping_constants =
+ constant_key_alternatives(constant, self.atom_tbl.clone());
+
+ let code = self.constants
+ .entry(constant.clone())
+ .or_insert(sdeq![]);
+
+ let is_initial_index = code.is_empty();
+
+ code.push_back(compute_index(is_initial_index, index));
+
+ for constant in &overlapping_constants {
+ let code = self.constants
+ .entry(constant.clone())
+ .or_insert(sdeq![]);
+
+ let is_initial_index = code.is_empty();
+ let index = compute_index(is_initial_index, index);
+
+ code.push_back(index);
}
- let mut prelude = VecDeque::new();
+ overlapping_constants
+ }
- let lst_loc = Self::switch_on_list(self.lists, &mut prelude);
- let str_loc =
- Self::switch_on_structure(self.structures, &mut prelude, optimal_index);
- let con_loc =
- Self::switch_on_constant(self.constants, &mut prelude, optimal_index);
+ fn index_structure(&mut self, name: &ClauseName, arity: usize, index: usize) -> usize {
+ let code = self
+ .structures
+ .entry((name.clone(), arity))
+ .or_insert(sdeq![]);
- let prelude_length = prelude.len();
+ let code_len = code.len();
+ let is_initial_index = code.is_empty();
- for (index, line) in prelude.iter_mut().enumerate() {
- match line {
- &mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i)) |
- &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i)) |
- &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => {
- *i += prelude_length - index;
- }
- _ => {
- }
+ code.push_back(compute_index(is_initial_index, index));
+ code_len
+ }
+
+ pub fn index_term(
+ &mut self,
+ optimal_arg: &Term,
+ index: usize,
+ clause_index_info: &mut ClauseIndexInfo,
+ ) {
+ match optimal_arg {
+ &Term::Clause(_, ref name, ref terms, _) => {
+ clause_index_info.opt_arg_index_key =
+ OptArgIndexKey::Structure(self.optimal_index, 0, name.clone(), terms.len());
+
+ self.index_structure(name, terms.len(), index);
+ }
+ &Term::Cons(..) | &Term::Constant(_, Constant::String(_)) => {
+ clause_index_info.opt_arg_index_key =
+ OptArgIndexKey::List(self.optimal_index, 0);
+
+ self.index_list(index);
}
+ &Term::Constant(_, ref constant) => {
+ let overlapping_constants =
+ self.index_constant(constant, index);
+
+ clause_index_info.opt_arg_index_key =
+ OptArgIndexKey::Constant(
+ self.optimal_index,
+ 0,
+ constant.clone(),
+ overlapping_constants,
+ );
+ }
+ _ => {
+ }
+ }
+ }
+
+ pub fn no_indices(&self) -> bool {
+ let no_constants = self.constants.is_empty();
+ let no_structures = self.structures.is_empty();
+ let no_lists = self.lists.is_empty();
+
+ no_constants && no_structures && no_lists
+ }
+
+ pub fn compute_indices(self, skip_stub_try_me_else: bool) -> Vec<IndexingLine> {
+ if self.no_indices() {
+ return vec![];
}
- 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 lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len());
+ let mut prelude = sdeq![];
+
+ let mut lst_loc = switch_on_list(self.lists, &mut prelude);
- let switch_instr = IndexingInstruction::SwitchOnTerm(
- optimal_index,
- prelude.len() + 1,
- con_loc,
- lst_loc,
- str_loc
+ let mut str_loc = switch_on(
+ IndexingInstruction::SwitchOnStructure,
+ self.structures,
+ &mut prelude,
);
- prelude.push_front(Line::from(switch_instr));
+ let con_loc = switch_on(
+ IndexingInstruction::SwitchOnConstant,
+ self.constants,
+ &mut prelude,
+ );
+
+ match &mut str_loc {
+ IndexingCodePtr::Internal(ref mut i) => {
+ *i += con_loc.is_internal() as usize;
+ }
+ _ => {
+ }
+ };
+
+ match &mut lst_loc {
+ IndexingCodePtr::Internal(ref mut i) => {
+ *i += con_loc.is_internal() as usize;
+ *i += str_loc.is_internal() as usize;
+ }
+ _ => {
+ }
+ };
+
+ let var_offset = 1 + skip_stub_try_me_else as usize;
+
+ prelude.push_front(IndexingLine::from(
+ IndexingInstruction::SwitchOnTerm(self.optimal_index, var_offset, con_loc, lst_loc, str_loc)
+ ));
- *code = Vec::from(prelude);
- code.append(&mut code_body);
+ prelude.into_iter().collect()
}
}
use crate::clause_types::*;
use crate::forms::*;
+use crate::indexing::IndexingCodePtr;
use crate::machine::heap::*;
use crate::machine::machine_errors::MachineStub;
use crate::machine::machine_indices::*;
use crate::indexmap::IndexMap;
-use std::collections::VecDeque;
+use slice_deque::SliceDeque;
+
use std::rc::Rc;
fn reg_type_into_functor(r: RegType) -> MachineStub {
#[derive(Debug)]
pub enum ChoiceInstruction {
DefaultRetryMeElse(usize),
- DefaultTrustMe,
+ DefaultTrustMe(usize),
RetryMeElse(usize),
- TrustMe,
+ TrustMe(usize),
TryMeElse(usize),
}
&ChoiceInstruction::RetryMeElse(offset) => {
functor!("retry_me_else", [integer(offset)])
}
- &ChoiceInstruction::TrustMe => {
- functor!("trust_me")
+ &ChoiceInstruction::TrustMe(offset) => {
+ functor!("trust_me", [integer(offset)])
}
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
functor!("default_retry_me_else", [integer(offset)])
}
- &ChoiceInstruction::DefaultTrustMe => {
- functor!("default_trust_me")
+ &ChoiceInstruction::DefaultTrustMe(offset) => {
+ functor!("default_trust_me", [integer(offset)])
}
}
}
}
}
-#[derive(Debug)]
+#[derive(Clone, Copy, Debug)]
pub enum IndexedChoiceInstruction {
Retry(usize),
Trust(usize),
Try(usize),
}
-impl From<IndexedChoiceInstruction> for Line {
- fn from(i: IndexedChoiceInstruction) -> Self {
- Line::IndexedChoice(i)
- }
-}
-
impl IndexedChoiceInstruction {
pub fn offset(&self) -> usize {
match self {
}
/// A `Line` is an instruction (cf. page 98 of wambook).
+#[derive(Debug)]
+pub enum IndexingLine {
+ Indexing(IndexingInstruction),
+ IndexedChoice(SliceDeque<IndexedChoiceInstruction>),
+}
+
+impl From<IndexingInstruction> for IndexingLine {
+ #[inline]
+ fn from(instr: IndexingInstruction) -> Self {
+ IndexingLine::Indexing(instr)
+ }
+}
+
+impl From<SliceDeque<IndexedChoiceInstruction>> for IndexingLine {
+ #[inline]
+ fn from(instrs: SliceDeque<IndexedChoiceInstruction>) -> Self {
+ IndexingLine::IndexedChoice(instrs)
+ }
+}
+
#[derive(Debug)]
pub enum Line {
Arithmetic(ArithmeticInstruction),
Control(ControlInstruction),
Cut(CutInstruction),
Fact(FactInstruction),
- Indexing(IndexingInstruction),
+ IndexingCode(Vec<IndexingLine>),
IndexedChoice(IndexedChoiceInstruction),
Query(QueryInstruction),
}
impl Line {
+ #[inline]
pub fn is_head_instr(&self) -> bool {
match self {
&Line::Cut(_) => true,
}
}
- pub fn to_functor(&self, h: usize) -> MachineStub {
+ pub fn enqueue_functors(&self, mut h: usize, functors: &mut Vec<MachineStub>) {
match self {
- &Line::Arithmetic(ref arith_instr) => arith_instr.to_functor(h),
- &Line::Choice(ref choice_instr) => choice_instr.to_functor(),
- &Line::Control(ref control_instr) => control_instr.to_functor(),
- &Line::Cut(ref cut_instr) => cut_instr.to_functor(h),
- &Line::Fact(ref fact_instr) => fact_instr.to_functor(h),
- &Line::Indexing(ref indexing_instr) => indexing_instr.to_functor(),
- &Line::IndexedChoice(ref indexed_choice_instr) => indexed_choice_instr.to_functor(),
- &Line::Query(ref query_instr) => query_instr.to_functor(h),
+ &Line::Arithmetic(ref arith_instr) =>
+ functors.push(arith_instr.to_functor(h)),
+ &Line::Choice(ref choice_instr) =>
+ functors.push(choice_instr.to_functor()),
+ &Line::Control(ref control_instr) =>
+ functors.push(control_instr.to_functor()),
+ &Line::Cut(ref cut_instr) =>
+ functors.push(cut_instr.to_functor(h)),
+ &Line::Fact(ref fact_instr) =>
+ functors.push(fact_instr.to_functor(h)),
+ &Line::IndexingCode(ref indexing_instrs) => {
+ for indexing_instr in indexing_instrs {
+ match indexing_instr {
+ IndexingLine::Indexing(indexing_instr) => {
+ let section = indexing_instr.to_functor(h);
+ h += section.len();
+ functors.push(section);
+ }
+ IndexingLine::IndexedChoice(indexed_choice_instrs) => {
+ for indexed_choice_instr in indexed_choice_instrs {
+ let section = indexed_choice_instr.to_functor();
+ h += section.len();
+ functors.push(section);
+ }
+ }
+ }
+ }
+ }
+ &Line::IndexedChoice(ref indexed_choice_instr) =>
+ functors.push(indexed_choice_instr.to_functor()),
+ &Line::Query(ref query_instr) =>
+ functors.push(query_instr.to_functor(h)),
+ }
+ }
+}
+
+#[inline]
+pub fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec<IndexingLine>> {
+ match line {
+ Line::IndexingCode(ref mut indexing_code) => {
+ Some(indexing_code)
+ }
+ _ => {
+ None
+ }
+ }
+}
+
+#[inline]
+pub fn to_indexing_line(line: &Line) -> Option<&Vec<IndexingLine>> {
+ match line {
+ Line::IndexingCode(ref indexing_code) => {
+ Some(indexing_code)
+ }
+ _ => {
+ None
}
}
}
CallClause(ClauseType, usize, usize, bool, bool),
Deallocate,
JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
+ RevJmpBy(usize), // notice the lack of context change as in
+ // JmpBy. RevJmpBy is used only to patch extensible
+ // predicates together.
Proceed,
}
&ControlInstruction::JmpBy(_, offset, ..) => {
functor!("jmp_by", [integer(offset)])
}
+ &ControlInstruction::RevJmpBy(offset) => {
+ functor!("rev_jmp_by", [integer(offset)])
+ }
&ControlInstruction::Proceed => {
functor!("proceed")
}
#[derive(Debug)]
pub enum IndexingInstruction {
// The first index is the optimal argument being indexed.
- SwitchOnTerm(usize, usize, usize, usize, usize),
- SwitchOnConstant(usize, usize, IndexMap<Constant, usize>),
- SwitchOnStructure(usize, usize, IndexMap<(ClauseName, usize), usize>),
-}
-
-impl From<IndexingInstruction> for Line {
- fn from(i: IndexingInstruction) -> Self {
- Line::Indexing(i)
- }
+ SwitchOnTerm(usize, usize, IndexingCodePtr, IndexingCodePtr, IndexingCodePtr),
+ SwitchOnConstant(IndexMap<Constant, IndexingCodePtr>),
+ SwitchOnStructure(IndexMap<(ClauseName, usize), IndexingCodePtr>),
}
impl IndexingInstruction {
- pub fn to_functor(&self) -> MachineStub {
+ pub fn to_functor(&self, mut h: usize) -> MachineStub {
match self {
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
functor!(
"switch_on_term",
[integer(arg),
integer(vars),
- integer(constants),
- integer(lists),
- integer(structures)]
+ indexing_code_ptr(h, constants),
+ indexing_code_ptr(h, lists),
+ indexing_code_ptr(h, structures)]
)
}
- &IndexingInstruction::SwitchOnConstant(arg, constants, _) => {
+ &IndexingInstruction::SwitchOnConstant(ref constants) => {
+ let mut key_value_list_stub = vec![];
+ let orig_h = h;
+
+ h += 2; // skip the 2-cell "switch_on_constant" functor.
+
+ for (c, ptr) in constants.iter() {
+ let key_value_pair = functor!(
+ ":",
+ SharedOpDesc::new(600, XFY),
+ [constant(c),
+ indexing_code_ptr(h + 3, *ptr)]
+ );
+
+ key_value_list_stub.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
+ key_value_list_stub.push(HeapCellValue::Addr(Addr::Str(h + 3)));
+ key_value_list_stub.push(HeapCellValue::Addr(
+ Addr::HeapCell(h + 3 + key_value_pair.len())
+ ));
+
+ h += key_value_pair.len() + 3;
+ key_value_list_stub.extend(key_value_pair.into_iter());
+ }
+
+ key_value_list_stub.push(HeapCellValue::Addr(Addr::EmptyList));
+
functor!(
"switch_on_constant",
- [integer(arg), integer(constants)]
+ [aux(orig_h, 0)],
+ [key_value_list_stub]
)
}
- &IndexingInstruction::SwitchOnStructure(arg, structures, _) => {
+ &IndexingInstruction::SwitchOnStructure(ref structures) => {
+ let mut key_value_list_stub = vec![];
+ let orig_h = h;
+
+ h += 2; // skip the 2-cell "switch_on_constant" functor.
+
+ for ((name, arity), ptr) in structures.iter() {
+ let predicate_indicator_stub = functor!(
+ "/",
+ SharedOpDesc::new(400, YFX),
+ [clause_name(name.clone()),
+ integer(*arity)]
+ );
+
+ let key_value_pair = functor!(
+ ":",
+ SharedOpDesc::new(600, XFY),
+ [aux(h + 3, 0),
+ indexing_code_ptr(h + 3, *ptr)],
+ [predicate_indicator_stub]
+ );
+
+ key_value_list_stub.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
+ key_value_list_stub.push(HeapCellValue::Addr(Addr::Str(h + 3)));
+ key_value_list_stub.push(HeapCellValue::Addr(
+ Addr::HeapCell(h + 3 + key_value_pair.len())
+ ));
+
+ h += key_value_pair.len() + 3;
+ key_value_list_stub.extend(key_value_pair.into_iter());
+ }
+
+ key_value_list_stub.push(HeapCellValue::Addr(Addr::EmptyList));
+
functor!(
"switch_on_structure",
- [integer(arg), integer(structures)]
+ [aux(orig_h, 0)],
+ [key_value_list_stub]
)
}
}
pub type CompiledFact = Vec<FactInstruction>;
-pub type ThirdLevelIndex = Vec<IndexedChoiceInstruction>;
-
pub type Code = Vec<Line>;
-
-pub type CodeDeque = VecDeque<Line>;
}
}))
}
-
+/*
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self {
ChunkedIterator {
chunk_num: 0,
cut_var_in_head: false,
}
}
-
+*/
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
-:- module(atts, [op(1199, fx, attribute), call_residue_vars/2,
+:- module(atts, [op(1199, fx, attribute),
+ call_residue_vars/2,
term_attributed_variables/2,
'$absent_attr'/2, '$copy_attr_list'/2, '$get_attr'/2,
'$put_attr'/2, '$absent_from_list'/2,
).
'$default_attr_list'([PG | PGs], Module, AttrVar) -->
- ( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)]
- ; { true }
- ),
+ [Module:put_atts(AttrVar, PG)],
'$default_attr_list'(PGs, Module, AttrVar).
'$default_attr_list'([], _, _) --> [].
'$del_attr_step'(Ls1, V, Attr) :-
( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
- ; true ).
+ ; true
+ ).
%% assumptions: Ls0 is a list, Ls1 is its tail;
%% the head of Ls0 can be ignored.
; Ls1 = [Att | Ls2] ->
( Att \= Attr -> '$del_attr_buried'(Ls1, Ls2, V, Attr)
; '$enqueue_attr_var'(V),
- '$del_attr_non_head'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
- '$del_attr_step'(Ls1, V, Attr)
+ '$del_attr_non_head'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
+ '$del_attr_step'(Ls1, V, Attr)
)
).
nonvar(Term0),
Term0 = (:- attribute Atts),
nonvar(Atts),
- phrase(expand_terms(Atts), Terms).
+ loader:prolog_load_context(module, Module),
+ phrase(expand_terms(Atts, Module), Terms).
-expand_terms(Atts) -->
+expand_terms(Atts, Module) -->
put_attrs_var_check,
- put_attrs(Atts),
+ put_attrs(Atts, Module),
get_attrs_var_check,
- get_attrs(Atts).
+ get_attrs(Atts, Module).
put_attrs_var_check -->
- { numbervars([Var, Attr], 0, _) },
[(put_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), put_atts/2))),
(put_atts(Var, Attr) :- var(Attr), throw(error(instantiation_error, put_atts/2)))].
get_attrs_var_check -->
- { numbervars([Var, Ls, Attr], 0, _) },
[(get_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), get_atts/2))),
(get_atts(Var, Attr) :- var(Attr), !, '$get_attr_list'(Var, Ls), nonvar(Ls),
'$copy_attr_list'(Ls, Attr))].
-put_attrs(Name/Arity) -->
- put_attr(Name, Arity),
- { numbervars([Var, Attr], 0, _) },
+put_attrs(Name/Arity, Module) -->
+ put_attr(Name, Arity, Module),
[(put_atts(Var, Attr) :- lists:maplist(put_atts(Var), Attr), !)].
-put_attrs((Name/Arity, Atts)) -->
+put_attrs((Name/Arity, Atts), Module) -->
{ nonvar(Atts) },
- put_attr(Name, Arity),
- put_attrs(Atts).
+ put_attr(Name, Arity, Module),
+ put_attrs(Atts, Module).
-get_attrs(Name/Arity) -->
- get_attr(Name, Arity).
-get_attrs((Name/Arity, Atts)) -->
+get_attrs(Name/Arity, Module) -->
+ get_attr(Name, Arity, Module).
+get_attrs((Name/Arity, Atts), Module) -->
{ nonvar(Atts) },
- get_attr(Name, Arity),
- get_attrs(Atts).
-
-put_attr(Name, Arity) -->
- { functor(Attr, Name, Arity),
- numbervars(Attr, 0, Arity),
- V = '$VAR'(Arity) },
- [(put_atts(V, +Attr) :- !, functor(Attr, Head, Arity),
- functor(AttrForm, Head, Arity),
- '$get_attr_list'(V, Ls),
- '$del_attr'(Ls, V, AttrForm),
- '$put_attr'(V, Attr)),
- (put_atts(V, Attr) :- !, functor(Attr, Head, Arity),
- functor(AttrForm, Head, Arity),
- '$get_attr_list'(V, Ls),
- '$del_attr'(Ls, V, AttrForm),
- '$put_attr'(V, Attr)),
- (put_atts(V, -Attr) :- !, functor(Attr, _, _),
- '$get_attr_list'(V, Ls),
- '$del_attr'(Ls, V, Attr))].
-
-get_attr(Name, Arity) -->
- { functor(Attr, Name, Arity),
- numbervars(Attr, 0, Arity),
- V = '$VAR'(Arity) },
- [(get_atts(V, +Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Attr)),
- (get_atts(V, Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Attr)),
- (get_atts(V, -Attr) :- !, functor(Attr, _, _), '$absent_attr'(V, Attr))].
+ get_attr(Name, Arity, Module),
+ get_attrs(Atts, Module).
+
+put_attr(Name, Arity, Module) -->
+ { functor(Attr, Name, Arity) },
+ [(put_atts(V, +Attr) :-
+ !,
+ functor(Attr, Head, Arity),
+ functor(AttrForm, Head, Arity),
+ '$get_attr_list'(V, Ls),
+ '$del_attr'(Ls, V, Module:AttrForm),
+ '$put_attr'(V, Module:Attr)),
+ (put_atts(V, Attr) :-
+ !,
+ functor(Attr, Head, Arity),
+ functor(AttrForm, Head, Arity),
+ '$get_attr_list'(V, Ls),
+ '$del_attr'(Ls, V, Module:AttrForm),
+ '$put_attr'(V, Module:Attr)),
+ (put_atts(V, -Attr) :-
+ !,
+ functor(Attr, _, _),
+ '$get_attr_list'(V, Ls),
+ '$del_attr'(Ls, V, Module:Attr))].
+
+get_attr(Name, Arity, Module) -->
+ { functor(Attr, Name, Arity) },
+ [(get_atts(V, +Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Module:Attr)),
+ (get_atts(V, Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Module:Attr)),
+ (get_atts(V, -Attr) :- !, functor(Attr, _, _), '$absent_attr'(V, Module:Attr))].
user:goal_expansion(Term, M:put_atts(Var, Attr)) :-
nonvar(Term),
-:- op(400, yfx, /).
-
-% module resolution operator.
-:- op(600, xfy, :).
-
-user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
- '$expand_op_list'([Op | OtherOps], Pred, Spec, OpResults).
-
-'$expand_op_list'([], _, _, []).
-'$expand_op_list'([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResults]) :-
- '$expand_op_list'(OtherOps, Pred, Spec, OtherResults).
-
-/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
- and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
- instructions are unchanged. */
-:- op(700, fx, non_counted_backtracking).
-
-% arithmetic operators.
-:- op(700, xfx, is).
-:- op(500, yfx, [+, -]).
-:- op(400, yfx, *).
-:- op(200, xfy, [**, ^]).
-:- op(500, yfx, [/\, \/, xor]).
-:- op(400, yfx, [div, //, rdiv, <<, >>, mod, rem]).
-:- op(200, fy, [+, -, \]).
-
-:- op(1200, xfx, -->).
-
-% arithmetic comparison operators.
-:- op(700, xfx, [>, <, =\=, =:=, >=, =<]).
-
-% term comparison.
-:- op(700, xfx, [==, \==, @=<, @>=, @<, @>]).
-
-% conditional operators.
-:- op(1050, xfy, ->).
-:- op(1100, xfy, ;).
-
-% control.
-:- op(700, xfx, [=, =.., \=]).
-:- op(900, fy, \+).
-
:- module(builtins, [(=)/2, (\=)/2, (\+)/1, (',')/2, (->)/2, (;)/2,
(=..)/2, (:)/2, (:)/3, (:)/4, (:)/5, (:)/6,
(:)/7, (:)/8, (:)/9, (:)/10, (:)/11, (:)/12,
clause/2, close/1, close/2, current_input/1,
current_output/1, current_op/3,
current_predicate/1, current_prolog_flag/2,
- expand_goal/2, expand_term/2, fail/0, false/0,
- findall/3, findall/4, flush_output/0,
- flush_output/1, get_byte/1, get_byte/2,
- get_char/1, get_char/2, get_code/1, get_code/2,
- halt/0, halt/1, max_arity/1, number_chars/2,
- number_codes/2, once/1, op/3, open/3, open/4,
- peek_byte/1, peek_byte/2, peek_char/1,
- peek_char/2, peek_code/1, peek_code/2,
- put_byte/1, put_byte/2, put_code/1, put_code/2,
- put_char/1, put_char/2, read_term/2, read_term/3,
- repeat/0, retract/1, set_prolog_flag/2,
- set_input/1, set_stream_position/2, set_output/1,
- setof/3, stream_property/2, sub_atom/5,
- subsumes_term/2, term_variables/2, throw/1,
- true/0, unify_with_occurs_check/2, write/1,
+ fail/0, false/0, findall/3, findall/4,
+ flush_output/0, flush_output/1, get_byte/1,
+ get_byte/2, get_char/1, get_char/2, get_code/1,
+ get_code/2, halt/0, halt/1, max_arity/1,
+ number_chars/2, number_codes/2, once/1, op/3,
+ open/3, open/4, peek_byte/1, peek_byte/2,
+ peek_char/1, peek_char/2, peek_code/1,
+ peek_code/2, put_byte/1, put_byte/2, put_code/1,
+ put_code/2, put_char/1, put_char/2, read_term/2,
+ read_term/3, repeat/0, retract/1,
+ set_prolog_flag/2, set_input/1,
+ set_stream_position/2, set_output/1, setof/3,
+ stream_property/2, sub_atom/5, subsumes_term/2,
+ term_variables/2, throw/1, true/0,
+ unify_with_occurs_check/2, write/1,
write_canonical/1, write_term/2, write_term/3,
writeq/1]).
false :- '$fail'.
-% dynamic module resolution.
-
Module : Predicate :-
- ( atom(Module) -> '$module_call'(Module, Predicate)
- ; throw(error(type_error(atom, Module), (:)/2))
+ ( atom(Module) ->
+ '$module_call'(Module, Predicate)
+ ;
+ throw(error(type_error(atom, Module), (:)/2))
).
+
+% dynamic module resolution.
+
:(Module, Predicate, A1) :-
( atom(Module) -> '$module_call'(A1, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
; throw(error(type_error(atom, Module), (:)/2))
).
-
% flags.
current_prolog_flag(Flag, false) :- Flag == bounded, !.
set_prolog_flag(integer_rounding_function, down) :- !. % 7.11.1.4
set_prolog_flag(integer_rounding_function, Value) :-
throw(error(domain_error(flag_value, integer_rounding_function + Value),
- set_prolog_flag/2)). % 8.17.1.3 e
+ set_prolog_flag/2)). % 8.17.1.3 e
set_prolog_flag(double_quotes, chars) :-
!, '$set_double_quotes'(chars). % 7.11.2.5, list of one-char atoms.
set_prolog_flag(double_quotes, atom) :-
!, '$set_double_quotes'(codes).
set_prolog_flag(double_quotes, Value) :-
throw(error(domain_error(flag_value, double_quotes + Value),
- set_prolog_flag/2)). % 8.17.1.3 e
+ set_prolog_flag/2)). % 8.17.1.3 e
set_prolog_flag(Flag, _) :-
atom(Flag),
throw(error(domain_error(prolog_flag, Flag), set_prolog_flag/2)). % 8.17.1.3 d
fail :- '$fail'.
+:- meta_predicate \+(:).
+
\+ G :- call(G), !, false.
\+ _.
_ \= _.
+:- meta_predicate once(:).
+
once(G) :- call(G), !.
repeat :- repeat.
+
+:- meta_predicate ','(:, :).
+
+:- meta_predicate ','(:, +, +).
+
+:- meta_predicate ;(:, :).
+
+:- meta_predicate ;(:, :, +).
+
+:- meta_predicate ->(:, :).
+
+:- meta_predicate ->(:, :, +).
+
+
','(G1, G2) :-
'$get_b_value'(B),
( '$call_with_default_policy'(var(G1)) ->
univ_errors(Term, List, N) :-
'$skip_max_list'(N, -1, List, R),
( var(R) ->
- ( var(Term), throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 a)
- ; true
- )
+ ( var(Term),
+ throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 a)
+ ; true
+ )
; R \== [] ->
throw(error(type_error(list, List), (=..)/2)) % 8.5.3.3 b)
; List = [H|T] ->
- ( var(H), var(Term), % R == [] => List is a proper list.
+ ( var(H),
+ var(Term), % R == [] => List is a proper list.
throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 c)
- ; T \== [], nonvar(H), \+ atom(H),
+ ; T \== [],
+ nonvar(H),
+ \+ atom(H),
throw(error(type_error(atom, H), (=..)/2)) % 8.5.3.3 d)
- ; compound(H), T == [],
+ ; compound(H),
+ T == [],
throw(error(type_error(atomic, H), (=..)/2)) % 8.5.3.3 e)
- ; var(Term), max_arity(M), N - 1 > M,
+ ; var(Term),
+ max_arity(M),
+ N - 1 > M,
throw(error(representation_error(max_arity), (=..)/2)) % 8.5.3.3 g)
; true
)
; true
).
-Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
- '$call_with_default_policy'(univ_worker(Term, List, N)).
+Term =.. List :-
+ '$call_with_default_policy'(univ_errors(Term, List, N)),
+ '$call_with_default_policy'(univ_worker(Term, List, N)).
:- non_counted_backtracking univ_worker/3.
univ_worker(Term, List, _) :-
- atomic(Term), !, '$call_with_default_policy'(List = [Term]).
+ atomic(Term),
+ !,
+ '$call_with_default_policy'(List = [Term]).
univ_worker(Term, [Name|Args], N) :-
var(Term), !,
'$call_with_default_policy'(Arity is N-1),
:- non_counted_backtracking get_args/4.
get_args(Args, _, _, 0) :-
- !, '$call_with_default_policy'(Args = []).
+ !,
+ '$call_with_default_policy'(Args = []).
get_args([Arg], Func, N, N) :-
- !, '$call_with_default_policy'(arg(N, Func, Arg)).
+ !,
+ '$call_with_default_policy'(arg(N, Func, Arg)).
get_args([Arg|Args], Func, I0, N) :-
'$call_with_default_policy'(arg(I0, Func, Arg)),
'$call_with_default_policy'(I1 is I0 + 1),
'$call_with_default_policy'(get_args(Args, Func, I1, N)).
+
+:- meta_predicate parse_options_list(?, :, ?, ?, ?).
+
+parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
+ '$skip_max_list'(_, -1, Options, Tail),
+ ( Tail == [] ->
+ true
+ ; var(Tail) ->
+ throw(error(instantiation_error, Stub)) % 8.11.5.3c)
+ ; Tail \== [] ->
+ throw(error(type_error(list, Options), Stub)) % 8.11.5.3e)
+ ),
+ ( lists:maplist(nonvar, Options),
+ catch(lists:maplist(Selector, Options, OptionPairs0),
+ error(E, _),
+ builtins:throw(error(E, Stub))) ->
+ lists:append(DefaultPairs, OptionPairs0, OptionPairs1),
+ keysort(OptionPairs1, OptionPairs),
+ select_rightmost_options(OptionPairs, OptionValues)
+ ;
+ throw(error(instantiation_error, Stub)) % 8.11.5.3c)
+ ).
+
+
parse_write_options(Options, OptionValues, Stub) :-
DefaultOptions = [ignore_ops-false, max_depth-0, numbervars-false,
quoted-false, variable_names-[]],
- parse_options_list(Options, parse_write_options_, DefaultOptions, OptionValues, Stub).
+ parse_options_list(Options, builtins:parse_write_options_, DefaultOptions, OptionValues, Stub).
parse_write_options_(ignore_ops(IgnoreOps), ignore_ops-IgnoreOps) :-
- ( nonvar(IgnoreOps), lists:member(IgnoreOps, [true, false])
+ ( nonvar(IgnoreOps),
+ lists:member(IgnoreOps, [true, false])
;
throw(error(domain_error(write_option, ignore_ops(IgnoreOps)), _))
).
parse_write_options_(quoted(Quoted), quoted-Quoted) :-
- ( nonvar(Quoted), lists:member(Quoted, [true, false])
+ ( nonvar(Quoted),
+ lists:member(Quoted, [true, false])
;
throw(error(domain_error(write_option, quoted(Quoted)), _))
).
parse_write_options_(numbervars(NumberVars), numbervars-NumberVars) :-
- ( nonvar(NumberVars), lists:member(NumberVars, [true, false])
+ ( nonvar(NumberVars),
+ lists:member(NumberVars, [true, false])
;
throw(error(domain_error(write_option, numbervars(NumberVars)), _))
).
parse_write_options_(variable_names(VNNames), variable_names-VNNames) :-
must_be_var_names_list(VNNames).
parse_write_options_(max_depth(MaxDepth), max_depth-MaxDepth) :-
- ( integer(MaxDepth), MaxDepth >= 0
+ ( integer(MaxDepth),
+ MaxDepth >= 0
;
throw(error(domain_error(write_option, max_depth(MaxDepth)), _))
).
must_be_var_names_list(VarNames) :-
'$skip_max_list'(_, -1, VarNames, Tail),
- ( Tail == [] -> must_be_var_names_list_(VarNames, VarNames)
- ; var(Tail) -> throw(error(instantiation_error, write_term/2))
+ ( Tail == [] ->
+ must_be_var_names_list_(VarNames, VarNames)
+ ; var(Tail) ->
+ throw(error(instantiation_error, write_term/2))
; throw(error(domain_error(write_option, variable_names(VarNames)), write_term/2))
).
must_be_var_names_list_([VarName | VarNames], List) :-
( nonvar(VarName) ->
( VarName = (Atom = _) ->
- ( atom(Atom) -> must_be_var_names_list_(VarNames, List)
- ; var(Atom) -> throw(error(instantiation_error, write_term/2))
+ ( atom(Atom) ->
+ must_be_var_names_list_(VarNames, List)
+ ; var(Atom) ->
+ throw(error(instantiation_error, write_term/2))
; throw(error(domain_error(write_option, variable_names(List)), write_term/2))
)
; throw(error(domain_error(write_option, variable_names(List)), write_term/2))
select_rightmost_options([], []).
-parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
- '$skip_max_list'(_, -1, Options, Tail),
- ( Tail == [] ->
- true
- ; var(Tail) ->
- throw(error(instantiation_error, Stub)) % 8.11.5.3c)
- ; Tail \== [] ->
- throw(error(type_error(list, Options), Stub)) % 8.11.5.3e)
- ),
- ( lists:maplist(nonvar, Options),
- catch(lists:maplist(Selector, Options, OptionPairs0),
- error(E, _),
- throw(error(E, Stub))) ->
- lists:append(DefaultPairs, OptionPairs0, OptionPairs1),
- keysort(OptionPairs1, OptionPairs),
- select_rightmost_options(OptionPairs, OptionValues)
- ;
- throw(error(instantiation_error, Stub)) % 8.11.5.3c)
- ).
-
-
parse_read_term_options(Options, OptionValues, Stub) :-
DefaultOptions = [singletons-_, variables-_, variable_names-_],
- parse_options_list(Options, parse_read_term_options_, DefaultOptions, OptionValues, Stub).
+ parse_options_list(Options, builtins:parse_read_term_options_, DefaultOptions, OptionValues, Stub).
parse_read_term_options_(singletons(Vars), singletons-Vars).
read_term(Stream, Term, Options).
-% expand_goal.
-
-expand_goal(Term0, Term) :- '$expand_goal'(Term0, Term).
-
-% expand_term.
-
-expand_term(Term0, Term) :- '$expand_term'(Term0, Term).
-
% term_variables.
% ensures List is either a variable or a list.
-can_be_list(List, _) :- var(List), !.
-can_be_list(List, _) :- '$skip_max_list'(_, -1, List, Tail), ( var(Tail) -> true ; Tail == []), !.
-can_be_list(List, PI) :- throw(error(type_error(list, List), PI)).
+can_be_list(List, _) :-
+ var(List),
+ !.
+can_be_list(List, _) :-
+ '$skip_max_list'(_, -1, List, Tail),
+ ( var(Tail) ->
+ true
+ ; Tail == []
+ ),
+ !.
+can_be_list(List, PI) :-
+ throw(error(type_error(list, List), PI)).
term_variables(Term, Vars) :-
can_be_list(Vars, term_variables/2),
% exceptions.
-catch(G,C,R) :- '$get_current_block'(Bb), '$call_with_default_policy'(catch(G,C,R,Bb)).
+:- meta_predicate catch(:, ?, :).
+
+catch(G,C,R) :-
+ '$get_current_block'(Bb),
+ '$call_with_default_policy'(catch(G,C,R,Bb)).
+
+
+:- meta_predicate catch(:, ?, :, +).
:- non_counted_backtracking catch/4.
catch(G,C,R,Bb) :-
'$get_ball'(Ball),
'$call_with_default_policy'(handle_ball(Ball, C, R)).
+
:- non_counted_backtracking end_block/2.
-end_block(Bb, NBb) :- '$clean_up_block'(NBb), '$reset_block'(Bb).
-end_block(Bb, NBb) :- '$reset_block'(NBb), '$fail'.
+end_block(Bb, NBb) :-
+ '$clean_up_block'(NBb),
+ '$reset_block'(Bb).
+end_block(Bb, NBb) :-
+ '$reset_block'(NBb),
+ '$fail'.
+
+:- meta_predicate handle_ball(?, ?, :).
:- non_counted_backtracking handle_ball/3.
-handle_ball(C, C, R) :- !, '$erase_ball', call(R).
-handle_ball(_, _, _) :- '$unwind_stack'.
+handle_ball(C, C, R) :-
+ !,
+ '$erase_ball',
+ call(R).
+handle_ball(_, _, _) :-
+ '$unwind_stack'.
throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'.
+
+% :- meta_predicate '$iterate_find_all'(?, :, ?, ?).
+
:- non_counted_backtracking '$iterate_find_all'/4.
'$iterate_find_all'(Template, Goal, _, LhOffset) :-
call(Goal),
'$truncate_if_no_lh_growth'(LhOffset),
'$get_lh_from_offset'(LhOffset, Solutions).
+
truncate_lh_to(LhLength) :- '$truncate_lh_to'(LhLength).
+
+:- meta_predicate findall(?, :, ?).
+
findall(Template, Goal, Solutions) :-
error:can_be(list, Solutions),
'$lh_length'(LhLength),
- '$call_with_default_policy'(catch('$iterate_find_all'(Template, Goal, Solutions, LhLength),
- Error,
- ( truncate_lh_to(LhLength), throw(Error) ))).
+ '$call_with_default_policy'(
+ catch(builtins:'$iterate_find_all'(Template, Goal, Solutions, LhLength),
+ Error,
+ ( builtins:truncate_lh_to(LhLength), builtins:throw(Error) ))
+ ).
+
+
+% :- meta_predicate '$iterate_find_all_diff'(?, :, ?, ?, ?).
:- non_counted_backtracking '$iterate_find_all_diff'/5.
'$iterate_find_all_diff'(Template, Goal, _, _, LhOffset) :-
'$get_lh_from_offset_diff'(LhOffset, Solutions0, Solutions1).
+% :- meta_predicate findall(?, :, ?, ?).
+
findall(Template, Goal, Solutions0, Solutions1) :-
error:can_be(list, Solutions0),
error:can_be(list, Solutions1),
'$lh_length'(LhLength),
- '$call_with_default_policy'(catch('$iterate_find_all_diff'(Template, Goal, Solutions0,
- Solutions1, LhLength),
- Error,
- ( truncate_lh_to(LhLength), throw(Error) ))).
+ '$call_with_default_policy'(catch(builtins:'$iterate_find_all_diff'(Template, Goal, Solutions0,
+ Solutions1, LhLength),
+ Error,
+ ( builtins:truncate_lh_to(LhLength), builtins:throw(Error) ))).
set_difference([X|Xs], [Y|Ys], Zs) :-
X == Y, !, set_difference(Xs, [Y|Ys], Zs).
set_difference(Xs, [], Xs).
group_by_variant([V2-S2 | Pairs], V1-S1, [S2 | Solutions], Pairs0) :-
- iso_ext: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_variants([V-S|Pairs], [V-Solution|Solutions]) :-
; Xs = [], FinalTerm = Term
).
+
+% :- meta_predicate findall_with_existential(?, :, ?, ?, ?).
+
findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) :-
- ( nonvar(Goal), Goal = _ ^ _ ->
+ ( nonvar(Goal),
+ Goal = _ ^ _ ->
rightmost_power(Goal, Goal1, ExistentialVars0),
term_variables(ExistentialVars0, ExistentialVars),
sort(Witnesses0, Witnesses1),
findall(Witnesses-Template, Goal, PairedSolutions)
).
+
+:- meta_predicate bagof(?, :, ?).
+
bagof(Template, Goal, Solution) :-
error:can_be(list, Solution),
term_variables(Template, TemplateVars0),
iterate_variants_and_sort([_|GroupSolutions], Ws, Solution) :-
iterate_variants_and_sort(GroupSolutions, Ws, Solution).
+
+:- meta_predicate setof(?, :, ?).
+
setof(Template, Goal, Solution) :-
error:can_be(list, Solution),
term_variables(Template, TemplateVars0),
'$clause_body_is_valid'(B) :-
( var(B) -> true
- ; functor(B, Name, _) -> ( atom(Name), Name \== '.' -> true
- ; throw(error(type_error(callable, B), clause/2))
- )
+ ; functor(B, Name, _) ->
+ ( atom(Name), Name \== '.' -> true
+ ; throw(error(type_error(callable, B), clause/2))
+ )
; throw(error(type_error(callable, B), clause/2))
).
'$module_clause'(H, B, Module) :-
( var(H) -> throw(error(instantiation_error, clause/2))
- ; functor(H, Name, Arity) -> ( Name == '.' -> throw(error(type_error(callable, H), clause/2))
- ; '$module_head_is_dynamic'(H, Module) ->
- '$clause_body_is_valid'(B),
- '$get_module_clause'(H, B, Module)
- ; throw(error(permission_error(access, private_procedure, Name/Arity),
- clause/2))
- )
+ ; functor(H, Name, Arity) ->
+ ( Name == '.' ->
+ throw(error(type_error(callable, H), clause/2))
+ ; '$head_is_dynamic'(Module, H) ->
+ '$clause_body_is_valid'(B),
+ Module:'$clause'(H, B) %%TODO: how do we show this exists?
+ ; throw(error(permission_error(access, private_procedure, Name/Arity),
+ clause/2))
+ )
; throw(error(type_error(callable, H), clause/2))
).
+
+:- dynamic('$clause'/2).
+
clause(H, B) :-
- ( var(H) -> throw(error(instantiation_error, clause/2))
+ ( var(H) ->
+ throw(error(instantiation_error, clause/2))
; functor(H, Name, Arity) ->
- ( Name == '.' -> throw(error(type_error(callable, H), clause/2))
- ; Name == (:), Arity =:= 2 ->
+ ( Name == '.' ->
+ throw(error(type_error(callable, H), clause/2))
+ ; Name == (:),
+ Arity =:= 2 ->
arg(1, H, Module),
arg(2, H, F),
'$module_clause'(F, B, Module)
- %% '$no_such_predicate' fails if H is not callable.
- ; '$no_such_predicate'(H) -> '$fail'
- ; '$head_is_dynamic'(H) -> '$clause_body_is_valid'(B),
- '$get_clause'(H, B)
+ ; '$no_such_predicate'(user, H) -> %% '$no_such_predicate' fails if
+ %% H is not callable.
+ '$fail'
+ ; '$head_is_dynamic'(user, H) ->
+ '$clause_body_is_valid'(B),
+ '$clause'(H, B)
; throw(error(permission_error(access, private_procedure, Name/Arity),
clause/2))
)
call_module_asserta(Head, Body, Name, Arity, Module) :-
'$clause_body_is_valid'(Body),
functor(VarHead, Name, Arity),
- findall((VarHead :- VarBody), clause(Module:VarHead, VarBody), Clauses),
+ findall((VarHead :- VarBody), builtins:clause(Module:VarHead, VarBody), Clauses),
'$module_asserta'((Head :- Body), Clauses, Name, Arity, Module).
call_asserta(Head, Body, Name, Arity) :-
'$clause_body_is_valid'(Body),
functor(VarHead, Name, Arity),
- findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
- '$asserta'((Head :- Body), Clauses, Name, Arity).
+ '$asserta'(Head, Body, Name, Arity).
module_asserta_clause(Head, Body, Module) :-
( var(Head) -> throw(error(instantiation_error, asserta/1))
- ; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( '$module_head_is_dynamic'(Head, Module) -> call_module_asserta(Head, Body, Name, Arity, Module)
+ ; functor(Head, Name, Arity),
+ atom(Name),
+ Name \== '.' ->
+ ( '$module_head_is_dynamic'(Head, Module) ->
+ call_module_asserta(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
)
; throw(error(type_error(callable, Head), asserta/1))
asserta_clause(Head, Body) :-
( var(Head) -> throw(error(instantiation_error, asserta/1))
- ; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( Name == (:), Arity =:= 2 ->
- arg(1, Head, Module),
- arg(2, Head, F),
- module_asserta_clause(F, Body, Module)
- ; '$no_such_predicate'(Head) -> call_asserta(Head, Body, Name, Arity)
- ; '$head_is_dynamic'(Head) -> call_asserta(Head, Body, Name, Arity)
+ ; functor(Head, Name, Arity),
+ atom(Name),
+ Name \== '.' ->
+ ( Name == (:),
+ Arity =:= 2 ->
+ arg(1, Head, Module),
+ arg(2, Head, F),
+ module_asserta_clause(F, Body, Module)
+ ; '$no_such_predicate'(user, Head) ->
+ call_asserta(Head, Body, Name, Arity)
+ ; '$head_is_dynamic'(user, Head) ->
+ call_asserta(Head, Body, Name, Arity)
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
)
; throw(error(type_error(callable, Head), asserta/1))
).
asserta(Clause) :-
- ( Clause \= (_ :- _) -> Head = Clause, Body = true, asserta_clause(Head, Body)
- ; Clause = (Head :- Body) -> asserta_clause(Head, Body)
+ ( Clause \= (_ :- _) ->
+ Head = Clause,
+ Body = true, asserta_clause(Head, Body)
+ ; Clause = (Head :- Body) ->
+ asserta_clause(Head, Body)
).
+% NOT MODIFIED.
call_module_assertz(Head, Body, Name, Arity, Module) :-
'$clause_body_is_valid'(Body),
functor(VarHead, Name, Arity),
- findall((VarHead :- VarBody), clause(Module:VarHead, VarBody), Clauses),
+ findall((VarHead :- VarBody), builtins:clause(Module:VarHead, VarBody), Clauses),
'$module_assertz'((Head :- Body), Clauses, Name, Arity, Module).
-call_assertz(Head, Body, Name, Arity) :-
- '$clause_body_is_valid'(Body),
- functor(VarHead, Name, Arity),
- findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
- '$assertz'((Head :- Body), Clauses, Name, Arity).
-
module_assertz_clause(Head, Body, Module) :-
- ( var(Head) -> throw(error(instantiation_error, assertz/1))
- ; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( '$module_head_is_dynamic'(Head, Module) -> call_module_assertz(Head, Body, Name, Arity, Module)
+ ( var(Head) ->
+ throw(error(instantiation_error, assertz/1))
+ ; functor(Head, Name, Arity),
+ atom(Name),
+ Name \== '.' ->
+ ( '$head_is_dynamic'(Module, Head) ->
+ call_module_assertz(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
)
; throw(error(type_error(callable, Head), assertz/1))
).
+% MODIFIED.
+call_assertz(Head, Body, Name, Arity) :-
+ '$clause_body_is_valid'(Body),
+ functor(VarHead, Name, Arity),
+ '$assertz'(Head, Body, Name, Arity).
+
assertz_clause(Head, Body) :-
- ( var(Head) -> throw(error(instantiation_error, assertz/1))
- ; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( Name == (:), Arity =:= 2 ->
- arg(1, Head, Module),
- arg(2, Head, F),
- module_assertz_clause(F, Body, Module)
- ; '$no_such_predicate'(Head) ->
- call_assertz(Head, Body, Name, Arity)
- ; '$head_is_dynamic'(Head) ->
- call_assertz(Head, Body, Name, Arity)
+ ( var(Head) ->
+ throw(error(instantiation_error, assertz/1))
+ ; functor(Head, Name, Arity),
+ atom(Name),
+ Name \== '.' ->
+ ( Name == (:),
+ Arity =:= 2 ->
+ arg(1, Head, Module),
+ arg(2, Head, F),
+ module_assertz_clause(F, Body, Module)
+ ; '$no_such_predicate'(user, Head) ->
+ call_assertz(Head, Body, Name, Arity)
+ ; '$head_is_dynamic'(user, Head) ->
+ call_assertz(Head, Body, Name, Arity)
; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
)
; throw(error(type_error(callable, Head), assertz/1))
).
assertz(Clause) :-
- ( Clause \= (_ :- _) -> Head = Clause, Body = true, assertz_clause(Head, Body)
- ; Clause = (Head :- Body) -> assertz_clause(Head, Body)
- ).
-
-first_match_index([Clause0 | Clauses], Clause1, N0, N) :-
- ( Clause0 \= Clause1 ->
- N1 is N0 + 1,
- first_match_index(Clauses, Clause1, N1, N)
- ; N0 = N, Clause0 = Clause1
+ ( Clause \= (_ :- _) ->
+ Head = Clause,
+ Body = true,
+ assertz_clause(Head, Body)
+ ; Clause = (Head :- Body) ->
+ assertz_clause(Head, Body)
).
-retract_clauses([Clause | Clauses0], Head, Body, Name, Arity) :-
- functor(VarHead, Name, Arity),
- findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses1),
- first_match_index(Clauses1, (Head :- Body), 0, N),
- ( Clauses0 == [] -> !
- ; true
- ),
- '$retract_clause'(Name, Arity, N, Clauses1).
-retract_clauses([_ | Clauses0], Head, Body, Name, Arity) :-
- retract_clauses(Clauses0, Head, Body, Name, Arity).
-
-call_retract(Head, Body, Name, Arity) :-
- findall((Head :- Body), clause(Head, Body), Clauses),
- retract_clauses(Clauses, Head, Body, Name, Arity).
module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :-
functor(VarHead, Name, Arity),
- findall((VarHead :- VarBody), clause(Module:VarHead, VarBody), Clauses1),
+ findall((VarHead :- VarBody), builtins:clause(Module:VarHead, VarBody), Clauses1),
first_match_index(Clauses1, (Head :- Body), 0, N),
( Clauses0 == [] -> !
; true
),
'$module_retract_clause'(Name, Arity, N, Clauses1, Module).
+
module_retract_clauses([_|Clauses0], Head, Body, Name, Arity, Module) :-
module_retract_clauses(Clauses0, Head, Body, Name, Arity, Module).
call_module_retract(Head, Body, Name, Arity, Module) :-
- findall((Head :- Body), clause(Module:Head, Body), Clauses),
+ findall((Head :- Body), builtins:clause(Module:Head, Body), Clauses),
module_retract_clauses(Clauses, Head, Body, Name, Arity, Module).
retract_module_clause(Head, Body, Module) :-
- ( var(Head) -> throw(error(instantiation_error, retract/1))
- ; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
+ ( var(Head) ->
+ throw(error(instantiation_error, retract/1))
+ ; functor(Head, Name, Arity),
+ atom(Name),
+ Name \== '.' ->
( '$module_head_is_dynamic'(Head, Module) ->
- call_module_retract(Head, Body, Name, Arity, Module)
+ call_module_retract(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
)
; throw(error(type_error(callable, Head), retract/1))
).
+
+first_match_index([Clause0 | Clauses], Clause1, N0, N) :-
+ ( Clause0 \= Clause1 ->
+ N1 is N0 + 1,
+ first_match_index(Clauses, Clause1, N1, N)
+ ; N0 = N,
+ Clause0 = Clause1
+ ).
+
+retract_clauses([Clause | Clauses0], Head, Body, Name, Arity) :-
+ functor(VarHead, Name, Arity),
+ findall((VarHead :- VarBody), builtins:'$clause'(VarHead, VarBody), Clauses1),
+ first_match_index(Clauses1, (Head :- Body), 0, N),
+ ( Clauses0 == [] -> !
+ ; true
+ ),
+ '$retract_clause'(Name, Arity, N).
+
+retract_clauses([_ | Clauses0], Head, Body, Name, Arity) :-
+ retract_clauses(Clauses0, Head, Body, Name, Arity).
+
+call_retract(Head, Body, Name, Arity) :-
+ findall((Head :- Body), builtins:'$clause'(Head, Body), Clauses),
+ retract_clauses(Clauses, Head, Body, Name, Arity).
+
retract_clause(Head, Body) :-
- ( var(Head) -> throw(error(instantiation_error, retract/1))
- ; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( Name == (:), Arity =:= 2 ->
- arg(1, Head, Module),
- arg(2, Head, F),
- retract_module_clause(F, Body, Module)
- ; '$head_is_dynamic'(Head) -> call_retract(Head, Body, Name, Arity)
- ; '$no_such_predicate'(Head) -> '$fail'
+ ( var(Head) ->
+ throw(error(instantiation_error, retract/1))
+ ; functor(Head, Name, Arity),
+ atom(Name),
+ Name \== '.' ->
+ ( Name == (:),
+ Arity =:= 2 ->
+ arg(1, Head, Module),
+ arg(2, Head, F),
+ retract_module_clause(F, Body, Module)
+ ; '$head_is_dynamic'(user, Head) ->
+ call_retract(Head, Body, Name, Arity)
+ ; '$no_such_predicate'(user, Head) ->
+ '$fail'
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
)
; throw(error(type_error(callable, Head), retract/1))
).
retract(Clause) :-
- ( Clause \= (_ :- _) -> Head = Clause, Body = true, retract_clause(Head, Body)
- ; Clause = (Head :- Body) -> retract_clause(Head, Body)
+ ( Clause \= (_ :- _) ->
+ Head = Clause,
+ Body = true,
+ retract_clause(Head, Body)
+ ; Clause = (Head :- Body) ->
+ retract_clause(Head, Body)
).
+
module_abolish(Pred, Module) :-
- ( var(Pred) -> throw(error(instantiation_error), abolish/1)
+ ( var(Pred) ->
+ throw(error(instantiation_error), abolish/1)
; Pred = Name/Arity ->
- ( var(Name) -> throw(error(instantiation_error, abolish/1))
+ ( var(Name) ->
+ throw(error(instantiation_error, abolish/1))
; integer(Arity) ->
- ( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1))
- ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
- ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1))
- ; functor(Head, Name, Arity) ->
- ( '$module_head_is_dynamic'(Head, Module) ->
- '$abolish_module_clause'(Name, Arity, Module)
- ; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
- )
- )
+ ( \+ atom(Name) ->
+ throw(error(type_error(atom, Name), abolish/1))
+ ; Arity < 0 ->
+ throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
+ ; max_arity(N), Arity > N ->
+ throw(error(representation_error(max_arity), abolish/1))
+ ; functor(Head, Name, Arity) ->
+ ( '$module_head_is_dynamic'(Head, Module) ->
+ '$abolish_module_clause'(Name, Arity, Module)
+ ; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
+ )
+ )
; throw(error(type_error(integer, Arity), abolish/1))
)
; throw(error(type_error(predicate_indicator, Module:Pred), abolish/1))
).
abolish(Pred) :-
- ( var(Pred) -> throw(error(instantiation_error), abolish/1)
- ; Pred = Module:InnerPred -> module_abolish(InnerPred, Module)
+ ( var(Pred) ->
+ throw(error(instantiation_error), abolish/1)
+ ; Pred = Module:InnerPred ->
+ module_abolish(InnerPred, Module)
; Pred = Name/Arity ->
- ( var(Name) -> throw(error(instantiation_error, abolish/1))
- ; var(Arity) -> throw(error(instantiation_error, abolish/1))
+ ( var(Name) ->
+ throw(error(instantiation_error, abolish/1))
+ ; var(Arity) ->
+ throw(error(instantiation_error, abolish/1))
; integer(Arity) ->
- ( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1))
- ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
- ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1))
- ; functor(Head, Name, Arity) ->
- ( '$no_such_predicate'(Head) -> true
- ; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)
- ; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
- )
- )
+ ( \+ atom(Name) ->
+ throw(error(type_error(atom, Name), abolish/1))
+ ; Arity < 0 ->
+ throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
+ ; max_arity(N), Arity > N ->
+ throw(error(representation_error(max_arity), abolish/1))
+ ; functor(Head, Name, Arity) ->
+ ( '$no_such_predicate'(Head) -> true
+ ; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)
+ ; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
+ )
+ )
; throw(error(type_error(integer, Arity), abolish/1))
)
; throw(error(type_error(predicate_indicator, Pred), abolish/1))
'$get_next_db_ref'(Ref, NextRef),
'$iterate_db_refs'(NextRef, Name/Arity).
+
current_predicate(Pred) :-
( nonvar(Pred), Pred \= _ / _
-> throw(error(type_error(predicate_indicator, Pred), current_predicate/1))
can_be_op_specifier(Spec) :- op_specifier(Spec).
current_op(Priority, Spec, Op) :-
- ( can_be_op_priority(Priority), can_be_op_specifier(Spec), error:can_be(atom, Op)
- -> '$get_next_op_db_ref'(Ref, _),
+ ( can_be_op_priority(Priority),
+ can_be_op_specifier(Spec),
+ error:can_be(atom, Op) ->
+ '$get_next_op_db_ref'(Ref, _),
'$iterate_op_db_refs'(Ref, Priority, Spec, Op)
).
throw(error(domain_error(operator_priority, Priority))) % 8.14.3.3 h)
; true
).
+
op_priority(Priority) :-
throw(error(type_error(integer, Priority), op/3)). % 8.14.3.3 d)
-op_specifier(OpSpec) :- atom(OpSpec),
+op_specifier(OpSpec) :-
+ atom(OpSpec),
( lists:member(OpSpec, [yfx, xfy, xfx, yf, fy, xf, fx]), !
; throw(error(domain_error(operator_specifier, OpSpec), op/3)) % 8.14.3.3 i)
).
-op_specifier(OpSpec) :- throw(error(type_error(atom, OpSpec), op/3)).
-valid_op(Op) :- atom(Op),
- ( Op == (',') -> throw(error(permission_error(modify, operator, (',')), op/3)) % 8.14.3.3 j), k).
- ; Op == {} -> throw(error(permission_error(create, operator, {}), op/3))
- ; Op == [] -> throw(error(permission_error(create, operator, []), op/3))
+op_specifier(OpSpec) :-
+ throw(error(type_error(atom, OpSpec), op/3)).
+
+valid_op(Op) :-
+ atom(Op),
+ ( Op == (',') ->
+ throw(error(permission_error(modify, operator, (',')), op/3)) % 8.14.3.3 j), k).
+ ; Op == {} ->
+ throw(error(permission_error(create, operator, {}), op/3))
+ ; Op == [] ->
+ throw(error(permission_error(create, operator, []), op/3))
; true
).
-op_(Priority, OpSpec, Op) :- '$op'(Priority, OpSpec, Op).
+op_(Priority, OpSpec, Op) :-
+ '$op'(Priority, OpSpec, Op).
op(Priority, OpSpec, Op) :-
- ( var(Priority) -> throw(error(instantiation_error, op/3)) % 8.14.3.3 a)
- ; var(OpSpec) -> throw(error(instantiation_error, op/3)) % 8.14.3.3 b)
- ; var(Op) -> throw(error(instantiation_error, op/3)) % 8.14.3.3 c)
- ; Op == '|' -> ( op_priority(Priority), op_specifier(OpSpec),
- lists:member(OpSpec, [xfx, xfy, yfx]), ( Priority >= 1001 ; Priority == 0 )
- -> '$op'(Priority, OpSpec, Op)
- ; throw(error(permission_error(create, operator, (|)), op/3))) % www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing#72
+ ( var(Priority) ->
+ throw(error(instantiation_error, op/3)) % 8.14.3.3 a)
+ ; var(OpSpec) ->
+ throw(error(instantiation_error, op/3)) % 8.14.3.3 b)
+ ; var(Op) ->
+ throw(error(instantiation_error, op/3)) % 8.14.3.3 c)
+ ; Op == '|' ->
+ ( op_priority(Priority),
+ op_specifier(OpSpec),
+ lists:member(OpSpec, [xfx, xfy, yfx]),
+ ( Priority >= 1001 ; Priority == 0 )
+ -> '$op'(Priority, OpSpec, Op)
+ ; throw(error(permission_error(create, operator, (|)), op/3))) % www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing#72
; valid_op(Op), op_priority(Priority), op_specifier(OpSpec) ->
'$op'(Priority, OpSpec, Op)
; list_of_op_atoms(Op), op_priority(Priority), op_specifier(OpSpec) ->
- lists:maplist(op_(Priority, OpSpec), Op), !
+ lists:maplist(op_(Priority, OpSpec), Op),
+ !
; throw(error(type_error(list, Op), op/3)) % 8.14.3.3 f)
).
).
atom_length(Atom, Length) :-
- ( var(Atom) -> throw(error(instantiation_error, atom_length/2)) % 8.16.1.3 a)
- ; atom(Atom) -> ( var(Length) -> '$atom_length'(Atom, Length)
- ; integer(Length), Length >= 0 -> '$atom_length'(Atom, Length)
- ; integer(Length) -> throw(error(domain_error(not_less_than_zero, Length), atom_length/2))
- % 8.16.1.3 d)
- ; throw(error(type_error(integer, Length), atom_length/2)) % 8.16.1.3 c)
- )
+ ( var(Atom) ->
+ throw(error(instantiation_error, atom_length/2)) % 8.16.1.3 a)
+ ; atom(Atom) ->
+ ( var(Length) ->
+ '$atom_length'(Atom, Length)
+ ; integer(Length), Length >= 0 ->
+ '$atom_length'(Atom, Length)
+ ; integer(Length) ->
+ throw(error(domain_error(not_less_than_zero, Length), atom_length/2))
+ % 8.16.1.3 d)
+ ; throw(error(type_error(integer, Length), atom_length/2)) % 8.16.1.3 c)
+ )
; throw(error(type_error(atom, Atom), atom_length/2)) % 8.16.1.3 b)
).
atom_chars(Atom, List) :-
'$skip_max_list'(_, -1, List, Tail),
- ( ( Tail == [] ; var(Tail) ) -> true
+ ( ( Tail == [] ; var(Tail) ) ->
+ true
; throw(error(type_error(list, List), atom_chars/2))
),
( var(Atom) ->
- ( var(Tail) -> throw(error(instantiation_error, atom_chars/2))
- ; ground(List) -> '$atom_chars'(Atom, List)
+ ( var(Tail) ->
+ throw(error(instantiation_error, atom_chars/2))
+ ; ground(List) ->
+ '$atom_chars'(Atom, List)
; throw(error(instantiation_error, atom_chars/2))
)
- ; atom(Atom) -> '$atom_chars'(Atom, List)
+ ; atom(Atom) ->
+ '$atom_chars'(Atom, List)
; throw(error(type_error(atom, Atom), atom_chars/2))
).
atom_codes(Atom, List) :-
'$skip_max_list'(_, -1, List, Tail),
- ( ( Tail == [] ; var(Tail) ) -> true
+ ( ( Tail == [] ; var(Tail) ) ->
+ true
; throw(error(type_error(list, List), atom_codes/2))
),
( var(Atom) ->
- ( var(Tail) -> throw(error(instantiation_error, atom_codes/2))
- ; ground(List), Tail == [] -> '$atom_codes'(Atom, List)
+ ( var(Tail) ->
+ throw(error(instantiation_error, atom_codes/2))
+ ; ground(List), Tail == [] ->
+ '$atom_codes'(Atom, List)
; throw(error(instantiation_error, atom_codes/2))
)
- ; atom(Atom) -> '$atom_codes'(Atom, List)
+ ; atom(Atom) ->
+ '$atom_codes'(Atom, List)
; throw(error(type_error(atom, Atom), atom_codes/2))
).
error:can_be(atom, Atom_2),
error:can_be(atom, Atom_12),
( var(Atom_1) ->
- ( var(Atom_12) -> throw(error(instantiation_error, atom_concat/3))
+ ( var(Atom_12) ->
+ throw(error(instantiation_error, atom_concat/3))
; atom_chars(Atom_12, Atom_12_Chars),
- lists:append(BeforeChars, AfterChars, Atom_12_Chars),
- atom_chars(Atom_1, BeforeChars),
- atom_chars(Atom_2, AfterChars)
+ lists:append(BeforeChars, AfterChars, Atom_12_Chars),
+ atom_chars(Atom_1, BeforeChars),
+ atom_chars(Atom_2, AfterChars)
)
; var(Atom_2) ->
( var(Atom_12) -> throw(error(instantiation_error, atom_concat/3))
; atom_chars(Atom_1, Atom_1_Chars),
- atom_chars(Atom_12, Atom_12_Chars),
- lists:append(Atom_1_Chars, Atom_2_Chars, Atom_12_Chars),
- atom_chars(Atom_2, Atom_2_Chars)
+ atom_chars(Atom_12, Atom_12_Chars),
+ lists:append(Atom_1_Chars, Atom_2_Chars, Atom_12_Chars),
+ atom_chars(Atom_2, Atom_2_Chars)
)
; atom_chars(Atom_1, Atom_1_Chars),
atom_chars(Atom_2, Atom_2_Chars),
error:can_be(integer, Before),
error:can_be(integer, Length),
error:can_be(integer, After),
- ( integer(Before), Before < 0 -> throw(error(domain_error(not_less_than_zero, Before), sub_atom/5))
- ; integer(Length), Length < 0 -> throw(error(domain_error(not_less_than_zero, Length), sub_atom/5))
- ; integer(After), After < 0 -> throw(error(domain_error(not_less_than_zero, After), sub_atom/5))
+ ( integer(Before), Before < 0 ->
+ throw(error(domain_error(not_less_than_zero, Before), sub_atom/5))
+ ; integer(Length), Length < 0 ->
+ throw(error(domain_error(not_less_than_zero, Length), sub_atom/5))
+ ; integer(After), After < 0 ->
+ throw(error(domain_error(not_less_than_zero, After), sub_atom/5))
; atom_chars(Atom, AtomChars),
lists:append(BeforeChars, LengthAndAfterChars, AtomChars),
lists:append(LengthChars, AfterChars, LengthAndAfterChars),
char_code(Char, Code) :-
( var(Char) ->
- ( var(Code) -> throw(error(instantiation_error, char_code/2))
- ; integer(Code) -> '$char_code'(Char, Code)
+ ( var(Code) ->
+ throw(error(instantiation_error, char_code/2))
+ ; integer(Code) ->
+ '$char_code'(Char, Code)
; throw(error(type_error(integer, Code), char_code/2))
)
- ; atom_length(Char, 1) -> '$char_code'(Char, Code)
+ ; atom_length(Char, 1) ->
+ '$char_code'(Char, Code)
; throw(error(type_error(character, Char), char_code/2))
).
),
!.
must_be_number(N, PI) :-
- ( nonvar(N) -> throw(error(type_error(number, N), PI))
+ ( nonvar(N) ->
+ throw(error(type_error(number, N), PI))
; throw(error(instantiation_error, PI))
).
parse_stream_options(Options, OptionValues, Stub) :-
DefaultOptions = [alias-[], eof_action-eof_code, reposition-false, type-text],
- parse_options_list(Options, parse_stream_options_, DefaultOptions, OptionValues, Stub).
+ parse_options_list(Options, builtins:parse_stream_options_, DefaultOptions, OptionValues, Stub).
parse_stream_options_(type(Type), type-Type) :-
parse_close_options(Options, OptionValues, Stub) :-
DefaultOptions = [force-false],
- parse_options_list(Options, parse_close_options_, DefaultOptions, OptionValues, Stub).
+ parse_options_list(Options, builtins:parse_close_options_, DefaultOptions, OptionValues, Stub).
parse_close_options_(force(Force), force-Force) :-
( nonvar(Force), lists:member(Force, [true, false]), !
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- module(clpb, [op(300, fy, ~),
- op(500, yfx, #),
- sat/1,
+ op(500, yfx, #),
+ sat/1,
taut/2,
labeling/1,
sat_count/2,
:- use_module(library(error)).
:- use_module(library(lists), [append/3]).
+:- use_module(library(loader), [strip_module/3]).
+
+:- meta_predicate phrase(2, ?).
+
+:- meta_predicate phrase(2, ?, ?).
phrase(GRBody, S0) :-
phrase(GRBody, S0, []).
+
phrase(GRBody, S0, S) :-
( var(GRBody) -> throw(error(instantiation_error, phrase/3))
- ; dcg_constr(GRBody) -> phrase_(GRBody, S0, S)
+ ; strip_module(GRBody, _, GRBody0),
+ dcg_constr(GRBody0) ->
+ phrase_(GRBody0, S0, S)
; functor(GRBody, _, _) -> call(GRBody, S0, S)
; throw(error(type_error(callable, GRBody), phrase/3))
).
:- use_module(library(error)).
+
wam_instructions(Clause, Listing) :-
( nonvar(Clause) ->
- Clause = Name / Arity,
- must_be(atom, Name),
- must_be(integer, Arity),
- ( Arity >= 0 -> '$wam_instructions'(Name, Arity, Listing)
- ; throw(error(domain_error(not_less_than_zero, Arity), wam_instructions/2))
+ ( Clause = Name / Arity ->
+ fetch_instructions(user, Name, Arity, Listing)
+ ; Clause = Module : (Name / Arity) ->
+ fetch_instructions(Module, Name, Arity, Listing)
)
; throw(error(instantiation_error, wam_instructions/2))
).
+
+
+fetch_instructions(Module, Name, Arity, Listing) :-
+ must_be(atom, Module),
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ ( Arity >= 0 ->
+ '$wam_instructions'(Module, Name, Arity, Listing)
+ ; throw(error(domain_error(not_less_than_zero, Arity), wam_instructions/2))
+ ).
put_dif_att(Var, X, Y) :-
( get_atts(Var, +dif(Z)) ->
- sort([X \== Y | Z], NewZ),
- put_atts(Var, +dif(NewZ))
+ sort([X \== Y | Z], NewZ),
+ put_atts(Var, +dif(NewZ))
; put_atts(Var, +dif([X \== Y]))
).
append_goals([], _).
append_goals([Var|Vars], Goals) :-
( get_atts(Var, +dif(VarGoals)) ->
- append(Goals, VarGoals, NewGoals0),
- sort(NewGoals0, NewGoals)
+ append(Goals, VarGoals, NewGoals0),
+ sort(NewGoals0, NewGoals)
; NewGoals = Goals
),
put_atts(Var, +dif(NewGoals)),
verify_attributes(Var, Value, Goals) :-
( get_atts(Var, +dif(Goals)) ->
- term_variables(Value, ValueVars),
- append_goals(ValueVars, Goals)
+ term_variables(Value, ValueVars),
+ append_goals(ValueVars, Goals)
; Goals = []
).
gather_dif_goals([]) --> [].
gather_dif_goals([(X \== Y) | Goals]) -->
( { X \= Y } -> []
- ; [dif(X, Y)]
+ ; [dif:dif(X, Y)]
),
gather_dif_goals(Goals).
).
must_be_(integer, Term) :- check_(integer, integer, Term).
must_be_(atom, Term) :- check_(atom, atom, Term).
-must_be_(character, T) :- check_(character, character, T).
-must_be_(list, Term) :- check_(ilist, list, Term).
-must_be_(type, Term) :- check_(type, type, Term).
-must_be_(boolean, Term) :- check_(boolean, boolean, Term).
+must_be_(character, T) :- check_(error:character, character, T).
+must_be_(list, Term) :- check_(error:ilist, list, Term).
+must_be_(type, Term) :- check_(error:type, type, Term).
+must_be_(boolean, Term) :- check_(error:boolean, boolean, Term).
check_(Pred, Type, Term) :-
( var(Term) -> instantiation_error(must_be/2)
bb_b_put(Key, NewValue) :-
( '$bb_get_with_offset'(Key, OldValue, OldOffset) ->
- call_cleanup((store_global_var_with_offset(Key, NewValue) ; false),
+ call_cleanup((iso_ext:store_global_var_with_offset(Key, NewValue) ; false),
reset_global_var_at_offset(Key, OldValue, OldOffset))
- ; call_cleanup((store_global_var_with_offset(Key, NewValue) ; false),
+ ; call_cleanup((iso_ext:store_global_var_with_offset(Key, NewValue) ; false),
reset_global_var_at_key(Key))
).
bb_get(Key, Value) :- atom(Key), !, '$fetch_global_var'(Key, Value).
bb_get(Key, _) :- throw(error(type_error(atom, Key), bb_get/2)).
+
+:- meta_predicate call_cleanup(:, :).
+
call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
% setup_call_cleanup.
+:- meta_predicate setup_call_cleanup(:, :, :).
+
setup_call_cleanup(S, G, C) :-
'$get_b_value'(B),
call(S),
'$remove_call_policy_check'(B),
'$call_with_default_policy'(throw(E)).
+:- meta_predicate call_with_inference_limit(:, ?, ?).
+
call_with_inference_limit(G, L, R) :-
'$get_current_block'(Bb),
'$get_b_value'(B),
:- module(lists, [member/2, select/3, append/2, append/3, foldl/4, foldl/5,
- memberchk/2, reverse/2, length/2, maplist/2,
- maplist/3, maplist/4, maplist/5, maplist/6,
- maplist/7, maplist/8, maplist/9, same_length/2, nth0/3,
- sum_list/2, transpose/2, list_to_set/2, list_max/2, list_min/2]).
+ memberchk/2, reverse/2, length/2, maplist/2,
+ maplist/3, maplist/4, maplist/5, maplist/6,
+ maplist/7, maplist/8, maplist/9, same_length/2, nth0/3,
+ sum_list/2, transpose/2, list_to_set/2, list_max/2, list_min/2]).
:- use_module(library(error)).
+:- meta_predicate maplist(1, ?).
+:- meta_predicate maplist(2, ?, ?).
+:- meta_predicate maplist(3, ?, ?, ?).
+:- meta_predicate maplist(4, ?, ?, ?, ?).
+:- meta_predicate maplist(5, ?, ?, ?, ?, ?).
+:- meta_predicate maplist(6, ?, ?, ?, ?, ?, ?).
+:- meta_predicate maplist(7, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate maplist(8, ?, ?, ?, ?, ?, ?, ?, ?).
+
+:- meta_predicate foldl(3, ?, ?, ?).
+:- meta_predicate foldl(4, ?, ?, ?, ?).
+
+
length(Xs, N) :-
- var(N), !,
+ var(N),
+ !,
'$skip_max_list'(M, -1, Xs, Xs0),
( Xs0 == [] -> N = M
; var(Xs0) -> length_addendum(Xs0, N, M)).
reverse([_|Xs], [Y1|Ys], YsPreludeRev, Xss) :-
reverse(Xs, Ys, [Y1|YsPreludeRev], Xss).
-
maplist(_, []).
maplist(Cont1, [E1|E1s]) :-
call(Cont1, E1),
call(Cont, E1, E2, E3, E4),
maplist(Cont, E1s, E2s, E3s, E4s).
+
maplist(_, [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
call(Cont, E1, E2, E3, E4, E5),
maplist(Cont, E1s, E2s, E3s, E4s, E5s).
+
maplist(_, [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
call(Cont, E1, E2, E3, E4, E5, E6),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
+
maplist(_, [], [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
call(Cont, E1, E2, E3, E4, E5, E6, E7),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
+
maplist(_, [], [], [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
call(Cont, E1, E2, E3, E4, E5, E6, E7, E8),
sum_list(Ls, S) :-
foldl(sum_, Ls, 0, S).
-sum_(L, S0, S) :- S is S0 + L.
+sum_(L, S0, S) :- is(S, +(S0, L)).
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),
--- /dev/null
+:- op(400, yfx, /).
+
+% module resolution operator.
+:- op(600, xfy, :).
+
+:- op(1199, fx, meta_predicate).
+
+/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
+ and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
+ instructions are unchanged. */
+:- op(700, fx, non_counted_backtracking).
+
+% arithmetic operators.
+:- op(700, xfx, is).
+:- op(500, yfx, +).
+:- op(500, yfx, -).
+:- op(400, yfx, *).
+:- op(200, xfy, **).
+:- op(200, xfy, ^).
+:- op(500, yfx, /\).
+:- op(500, yfx, \/).
+:- op(500, yfx, xor).
+:- op(400, yfx, div).
+:- op(400, yfx, //).
+:- op(400, yfx, rdiv).
+:- op(400, yfx, <<).
+:- op(400, yfx, >>).
+:- op(400, yfx, mod).
+:- op(400, yfx, rem).
+:- op(200, fy, +).
+:- op(200, fy, -).
+:- op(200, fy, \).
+
+% arithmetic comparison operators.
+:- op(700, xfx, >).
+:- op(700, xfx, <).
+:- op(700, xfx, =\=).
+:- op(700, xfx, =:=).
+:- op(700, xfx, >=).
+:- op(700, xfx, =<).
+
+% term comparison.
+:- op(700, xfx, ==).
+:- op(700, xfx, \==).
+:- op(700, xfx, @=<).
+:- op(700, xfx, @>=).
+:- op(700, xfx, @<).
+:- op(700, xfx, @>).
+
+% conditional operators.
+:- op(1050, xfy, ->).
+:- op(1100, xfy, ;).
+
+% control.
+:- op(700, xfx, =).
+:- op(700, xfx, =..).
+:- op(700, xfx, \=).
+:- op(900, fy, \+).
+
+:- op(1200, xfx, -->).
+
+% meta_predicate declarations for call/{0, 64}.
+:- meta_predicate call(:).
+:- meta_predicate call(:, ?).
+:- meta_predicate call(:, ?, ?).
+:- meta_predicate call(:, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
+:- meta_predicate call(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?).
map_list_to_pairs/3]).
+:- meta_predicate map_list_to_pairs(:, ?, ?).
+
pairs_keys_values([], [], []).
pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :-
pairs_keys_values(ABs, As, Bs).
atom_concat(Name, ' tabled', WrapName),
Head =.. [Name|Args],
WrappedHead =.. [WrapName|Args],
- '$module_of'(Module, Name) %prolog_load_context(module, Module)
+ prolog_load_context(module, Module)
},
[ ( Head :-
start_tabling(Module:Head, WrappedHead)
user:term_expansion(Term0, Clauses) :-
- nonvar(Term0),
+ nonvar(Term0),
Term0 = (:- table Preds),
phrase(wrappers(Preds), Clauses).
user:term_expansion(Clause, NewClause) :-
- nonvar(Clause),
- '$module_of'(Module, Clause),
+ nonvar(Clause),
+ prolog_load_context(module, Module),
rename(Clause, NewClause, Module).
% '$cpu_now' can be replaced by statistics/2 once that is implemented.
+:- meta_predicate time(:).
+
time(Goal) :-
'$cpu_now'(T0),
setup_call_cleanup(true,
--- /dev/null
+
+:- module(loader, [consult/1,
+ expand_goal/3,
+ expand_term/2,
+ file_load/2,
+ load/1,
+ predicate_property/2,
+ prolog_load_context/2,
+ strip_module/3,
+ use_module/1,
+ use_module/2
+ ]).
+
+
+:- use_module(library(error)).
+:- use_module(library(lists)).
+:- use_module(library(pairs)).
+
+
+create_file_load_context(Stream, Path, Evacuable) :-
+ '$push_load_context'(Stream, Path),
+ '$push_load_state_payload'(Evacuable).
+
+create_load_context(Stream, Evacuable) :-
+ '$push_load_context'(Stream, ''),
+ '$push_load_state_payload'(Evacuable).
+
+unload_evacuable(Evacuable) :-
+ '$pop_load_state_payload'(Evacuable),
+ '$pop_load_context'.
+
+
+file_load(Stream, Path) :-
+ file_load(Stream, Path, _).
+
+file_load(Stream, Path, Evacuable) :-
+ create_file_load_context(Stream, Path, Evacuable),
+ catch(loader:load_loop(Stream, Evacuable),
+ E,
+ (loader:unload_evacuable(Evacuable), throw(E))),
+ '$pop_load_context'.
+
+
+load(Stream) :-
+ create_load_context(Stream, Evacuable),
+ catch(loader:load_loop(Stream, Evacuable),
+ E,
+ (loader:unload_evacuable(Evacuable), throw(E))),
+ '$pop_load_context'.
+
+load_loop(Stream, Evacuable) :-
+ read_term(Stream, Term, [variable_names(VNs), singletons(Singletons)]),
+ ( Term == end_of_file ->
+ close(Stream),
+ '$conclude_load'(Evacuable)
+ ; var(Term) ->
+ instantiation_error(load/1)
+ ; expand_terms_and_goals(Term, Terms),
+ !,
+ ( var(Terms) ->
+ instantiation_error(load/1)
+ ; Terms = [_|_] ->
+ compile_dispatch_or_clause_on_list(Terms, Evacuable, VNs)
+ ; compile_dispatch_or_clause(Terms, Evacuable, VNs)
+ ),
+ load_loop(Stream, Evacuable)
+ ).
+
+
+inner_meta_specs((:), HeadArg, InnerHeadArgs, InnerMetaSpecs) :-
+ !,
+ predicate_property(HeadArg, meta_predicate(InnerMetaSpecs)),
+ HeadArg =.. [_ | InnerHeadArgs].
+
+inner_meta_specs(N, HeadArg, InnerHeadArgs, InnerMetaSpecs) :-
+ integer(N),
+ N >= 0,
+ HeadArg =.. [Functor | InnerHeadArgs],
+ length(InnerHeadArgs1, N),
+ append(InnerHeadArgs, InnerHeadArgs1, InnerHeadArgs0),
+ CompleteHeadArg =.. [Functor | InnerHeadArgs0],
+ predicate_property(CompleteHeadArg, meta_predicate(InnerMetaSpecs)).
+
+
+module_expanded_head_variables_([], _, HeadVars, HeadVars).
+module_expanded_head_variables_([HeadArg | HeadArgs], [MetaSpec | MetaSpecs], HeadVars, HeadVars0) :-
+ ( ( MetaSpec == (:)
+ ; integer(MetaSpec),
+ MetaSpec >= 0
+ ) ->
+ ( var(HeadArg) ->
+ HeadVars = [HeadArg-HeadArg | HeadVars1],
+ module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars1, HeadVars0)
+ ; inner_meta_specs(MetaSpec, HeadArg, InnerHeadArgs, InnerMetaSpecs) ->
+ module_expanded_head_variables_(InnerHeadArgs, InnerMetaSpecs, HeadVars, HeadVars1),
+ module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars1, HeadVars0)
+ ; module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, HeadVars0)
+ )
+ ; module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, HeadVars0)
+ ).
+
+module_expanded_head_variables(Head, MetaSpecs, HeadVars) :-
+ ( var(Head) ->
+ instantiation_error(load/1)
+ ; predicate_property(Head, meta_predicate(MetaSpecs)),
+ Head =.. [_ | HeadArgs] ->
+ module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, [])
+ ; HeadVars = []
+ ).
+
+
+expand_terms_and_goals(Term, Terms) :-
+ expand_term(Term, Terms0),
+ ( var(Terms0) ->
+ instantiation_error(load/1)
+ ; Terms0 = (Head1 :- Body0) ->
+ ( var(Head1) ->
+ instantiation_error(load/1)
+ ; prolog_load_context(module, Target),
+ module_expanded_head_variables(Head1, MetaSpecs, HeadVars),
+ expand_goal(Body0, Target, Body1, HeadVars)
+ ),
+ Terms = (Head1 :- Body1)
+ ; Terms = Terms0
+ ).
+
+
+expand_term(UnexpandedTerm, ExpandedTerm) :-
+ user:term_expansion(UnexpandedTerm, ExpandedTerm).
+
+
+compile_dispatch_or_clause_on_list([], Evacuable, VNs).
+compile_dispatch_or_clause_on_list([Term | Terms], Evacuable, VNs) :-
+ compile_dispatch_or_clause(Term, Evacuable, VNs),
+ compile_dispatch_or_clause_on_list(Terms, Evacuable, VNs).
+
+
+compile_dispatch_or_clause(Term, Evacuable, VNs) :-
+ ( var(Term) ->
+ instantiation_error(load/1)
+ ; compile_dispatch(Term, Evacuable, VNs) ->
+ true
+ ;
+ compile_clause(Term, Evacuable, VNs)
+ ).
+
+
+compile_dispatch((:- Declaration), Evacuable, _VNs) :-
+ ( var(Declaration) ->
+ instantiation_error(load/1)
+ ;
+ compile_declaration(Declaration, Evacuable)
+ ).
+compile_dispatch(term_expansion(Term, Terms), Evacuable, VNs) :-
+ '$add_term_expansion_clause'('$term_expansion'(Term, Terms), Evacuable, VNs).
+compile_dispatch((term_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
+ '$add_term_expansion_clause'(('$term_expansion'(Term, Terms) :- Body), Evacuable, VNs).
+compile_dispatch(user:term_expansion(Term, Terms), Evacuable, VNs) :-
+ '$add_term_expansion_clause'('$term_expansion'(Term, Terms), Evacuable, VNs).
+compile_dispatch((user:term_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
+ '$add_term_expansion_clause'(('$term_expansion'(Term, Terms) :- Body), Evacuable, VNs).
+compile_dispatch(goal_expansion(Term, Terms), Evacuable, VNs) :-
+ prolog_load_context(module, Target),
+ '$add_goal_expansion_clause'(Target, goal_expansion(Term, Terms), Evacuable, VNs).
+compile_dispatch((goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
+ prolog_load_context(module, Target),
+ '$add_goal_expansion_clause'(Target, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs).
+compile_dispatch(Target:goal_expansion(Term, Terms), Evacuable, VNs) :-
+ '$add_goal_expansion_clause'(Target, goal_expansion(Term, Terms), Evacuable, VNs).
+compile_dispatch((Target:goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :-
+ '$add_goal_expansion_clause'(Target, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs).
+
+
+compile_declaration(use_module(Module), Evacuable) :-
+ use_module(Module, [], Evacuable).
+compile_declaration(use_module(Module, Exports), Evacuable) :-
+ ( Exports == [] ->
+ '$remove_module_exports'(Module, Evacuable) % TODO: implement this.
+ ;
+ use_module(Module, Exports, Evacuable)
+ ).
+compile_declaration(module(Module, Exports), Evacuable) :-
+ ( atom(Module) ->
+ '$declare_module'(Module, Exports, Evacuable)
+ ;
+ type_error(atom, Module, load/1)
+ ).
+compile_declaration(dynamic(Name/Arity), Evacuable) :-
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ '$add_dynamic_predicate'(Name, Arity, Evacuable).
+compile_declaration(initialization(Goal), Evacuable) :-
+ prolog_load_context(module, Module),
+ '$compile_pending_predicates'(Evacuable),
+ expand_goal(call(Goal), Module, call(ExpandedGoal)),
+ call(ExpandedGoal).
+
+
+compile_clause(Clause, Evacuable, VNs) :-
+ '$clause_to_evacuable'(Clause, Evacuable, VNs).
+
+
+prolog_load_context(source, Source) :-
+ %% The absolute path name of the file being compiled. During
+ %% loading of a PO file, the corresponding source file name is
+ %% returned.
+ '$prolog_lc_source'(Source).
+prolog_load_context(file, File) :-
+ %% Outside included files (see Include Declarations) this is the
+ %% same as the source key. In included files this is the absolute
+ %% path name of the file being included.
+ '$prolog_lc_file'(File).
+prolog_load_context(directory, Dir) :-
+ %% The absolute path name of the directory of the file being
+ %% compiled/loaded. In included files this is the directory of the
+ %% file being included.
+ '$prolog_lc_dir'(Dir).
+prolog_load_context(module, Module) :-
+ %% The source module (see ref-mod-mne). This is useful for example
+ %% if you are defining clauses for user:term_expansion/6 and need
+ %% to access the source module at compile time.
+ '$prolog_lc_module'(Module).
+prolog_load_context(stream, Stream) :-
+ %% The stream being compiled or loaded from.
+ '$prolog_lc_stream'(Stream).
+prolog_load_context(term_position, TermPosition) :-
+ %% TermPosition represents the stream position of the last term read.
+ '$prolog_lc_stream'(Stream),
+ stream_property(Stream, position(TermPosition)).
+
+
+consult(Item) :-
+ ( atom(Item) -> use_module(Item)
+ ; type_error(atom, Item, consult/1)
+ ).
+
+
+use_module(Module) :-
+ '$push_load_state_payload'(Evacuable),
+ use_module(Module, [], Evacuable).
+
+use_module(Module, Exports) :-
+ '$push_load_state_payload'(Evacuable),
+ ( Exports == [] ->
+ '$remove_module_exports'(Module, Evacuable)
+ ;
+ use_module(Module, Exports, Evacuable)
+ ).
+
+
+%% If use_module is invoked in an existing load context, use its
+%% directory. Otherwise, use the relative path of Path.
+load_context_path(Module, Path) :-
+ ( prolog_load_context(directory, CurrentDir) ->
+ atom_concat(CurrentDir, Path, Module)
+ ;
+ Module = Path
+ ).
+
+use_module(Module, Exports, Evacuable) :-
+ ( var(Module) ->
+ instantiation_error(load/1)
+ ; Module = library(Library) ->
+ ( atom(Library) ->
+ ( '$load_compiled_library'(Library, Evacuable) -> %% TODO: What about Exports?
+ true
+ ;
+ '$load_library_as_stream'(Library, Stream, Path),
+ file_load(Stream, Path, Subevacuable),
+ '$use_module'(Evacuable, Subevacuable, Exports)
+ )
+ ; var(Library) ->
+ instantiation_error(load/1)
+ ;
+ type_error(atom, Library, load/1)
+ )
+ ; atom(Module) ->
+ load_context_path(Module, Path),
+ open(Path, read, Stream),
+ file_load(Stream, Path, Subevacuable),
+ '$use_module'(Evacuable, Subevacuable, Exports)
+ ;
+ type_error(atom, Library, load/1)
+ ).
+
+
+
+check_predicate_property(meta_predicate, Name, Arity, MetaPredicateTerm) :-
+ must_be(atom, Name),
+ must_be(integer, Arity),
+ '$cpp_meta_predicate_property'(Name, Arity, MetaPredicateTerm).
+
+
+predicate_property(Callable, Property) :-
+ ( var(Callable) ->
+ instantiation_error(load/1)
+ ; functor(Callable, Name, Arity),
+ ( var(Property) ->
+ true
+ ; functor(Property, PropertyType, _)
+ ),
+ check_predicate_property(PropertyType, Name, Arity, Property)
+ ).
+
+
+strip_module_(M0, G0, M1, G1) :-
+ ( nonvar(G0),
+ G0 = (MG1:G2) ->
+ strip_module_(MG1, G2, M1, G1)
+ ; M0 = M1,
+ G0 = G1
+ ).
+
+strip_module(Goal, M, G) :-
+ strip_module_(_, Goal, M, G).
+
+
+
+expand_subgoal(UnexpandedGoals, MS, Module, ExpandedGoals, HeadVars) :-
+ ( var(UnexpandedGoals) ->
+ UnexpandedGoals = ExpandedGoals
+ ; user:goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
+ ( Module \== user ->
+ user:goal_expansion(UnexpandedGoals1, user, Goals)
+ ; Goals = UnexpandedGoals1
+ ),
+ ( inner_meta_specs(MS, Goals, _, MetaSpecs) ->
+ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars)
+ ; Goals = ExpandedGoals
+ )
+ ; UnexpandedGoals = ExpandedGoals
+ ).
+
+
+expand_module_name(ESG0, M, ESG) :-
+ ( var(ESG0) ->
+ ESG = M:ESG0
+ ; ESG0 = _:ESG1 ->
+ ESG = ESG0
+ ; ESG = M:ESG0
+ ).
+
+
+expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars) :-
+ ( ( MS == (:)
+ ; integer(MS),
+ MS >= 0
+ ) ->
+ ( var(SG),
+ pairs:same_key(SG, HeadVars, [_|_], _) ->
+ expand_subgoal(SG, MS, M, ESG, HeadVars)
+ ; expand_subgoal(SG, MS, M, ESG0, HeadVars),
+ expand_module_name(ESG0, M, ESG)
+ ),
+ expand_meta_predicate_subgoals(SGs, MSs, M, ESGs, HeadVars)
+ ; ESG = SG,
+ expand_meta_predicate_subgoals(SGs, MSs, M, ESGs, HeadVars)
+ ).
+
+expand_meta_predicate_subgoals([], _, _, [], _).
+
+
+expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :-
+ Goals =.. [GoalFunctor | SubGoals],
+ ( GoalFunctor == (:) ->
+ false
+ ; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars),
+ ExpandedGoals =.. [GoalFunctor | ExpandedGoalList]
+ ).
+
+
+expand_goal(UnexpandedGoals, Module, ExpandedGoals) :-
+ expand_goal(UnexpandedGoals, Module, ExpandedGoals, []),
+ !.
+
+expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :-
+ ( var(UnexpandedGoals) ->
+ UnexpandedGoals = ExpandedGoals
+ ; user:goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
+ ( Module \== user ->
+ user:goal_expansion(UnexpandedGoals1, user, Goals)
+ ; Goals = UnexpandedGoals1
+ ),
+ ( Goals = (Goal0, Goals0) ->
+ ( expand_goal(Goal0, Module, Goal1, HeadVars) ->
+ expand_goal(Goals0, Module, Goals1, HeadVars),
+ thread_goals(Goal1, ExpandedGoals, Goals1, (','))
+ ; expand_goal(Goals0, Module, Goals1, HeadVars),
+ ExpandedGoals = (Goal0, Goals1)
+ )
+ ; Goals = (Goals0 -> Goals1) ->
+ expand_goal(Goals0, Module, ExpandedGoals0, HeadVars),
+ expand_goal(Goals1, Module, ExpandedGoals1, HeadVars),
+ ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1)
+ ; Goals = (Goals0 ; Goals1) ->
+ expand_goal(Goals0, Module, ExpandedGoals0, HeadVars),
+ expand_goal(Goals1, Module, ExpandedGoals1, HeadVars),
+ ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
+ ; Goals = (\+ Goals0) ->
+ expand_goal(Goals0, Module, Goals1, HeadVars),
+ ExpandedGoals = (\+ Goals1)
+ ; predicate_property(Goals, meta_predicate(MetaSpecs)) ->
+ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars)
+ ; thread_goals(Goals, ExpandedGoals, (','))
+ ; Goals = ExpandedGoals
+ )
+ ).
+
+thread_goals(Goals0, Goals1, Functor) :-
+ ( var(Goals0) ->
+ Goals0 = Goals1
+ ; ( Goals0 = [G | Gs] ->
+ ( Gs = [] ->
+ Goals1 = G
+ ; Goals1 =.. [Functor, G, Goals2],
+ thread_goals(Gs, Goals2, Functor)
+ )
+ ; Goals1 = Goals0
+ )
+ ).
+
+thread_goals(Goals0, Goals1, Hole, Functor) :-
+ ( var(Goals0) ->
+ Goals0 = Goals1
+ ; ( Goals0 = [G | Gs] ->
+ ( Gs == [] ->
+ Goals1 =.. [Functor, G, Hole]
+ ; Goals1 =.. [Functor, G, Goals2],
+ thread_goals(Gs, Goals2, Hole, Functor)
+ )
+ ; Goals1 =.. [Functor, Goals0, Hole]
+ )
+ ).
iterate(VarBindings, ValueBindings, ListsCubed).
iterate([], [], []).
+/*
gather_modules(Attrs, []) :- var(Attrs), !.
gather_modules([Attr|Attrs], [Module|Modules]) :-
'$module_of'(Module, Attr), % write the owning module of Attr to Module.
gather_modules(Attrs, Modules).
+*/
+
+gather_modules(Attrs, []) :- var(Attrs), !.
+gather_modules([Module:_|Attrs], [Module|Modules]) :-
+ gather_modules(Attrs, Modules).
call_verify_attributes(Attrs, _, _, []) :-
var(Attrs), !.
call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
gather_modules([Attr|Attrs], Modules0),
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([], _, _, []).
+/*
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_0(ListOfGoalLists),
use std::cmp::Ordering;
use std::vec::IntoIter;
-pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
-pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
-
pub(super) type Bindings = Vec<(usize, Addr)>;
#[derive(Debug)]
self.stack.index_and_frame_mut(e).prelude.interrupt_cp = self.attr_var_init.cp;
for i in 1 .. self.num_of_args + 1 {
- self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)].clone();
+ self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)];
}
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
use crate::clause_types::*;
-use crate::codegen::*;
-use crate::debray_allocator::*;
-use crate::forms::*;
use crate::instructions::*;
-use crate::machine::compile::*;
-use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
-use crate::indexmap::IndexSet;
-
-use std::collections::VecDeque;
-use std::mem;
-
#[derive(Debug)]
pub struct CodeRepo {
- pub(super) cached_query: Code,
- pub(super) goal_expanders: Code,
- pub(super) term_expanders: Code,
pub(super) code: Code,
- pub(super) in_situ_code: Code,
- pub(super) term_dir: TermDir,
}
impl CodeRepo {
#[inline]
- pub(super) fn new() -> Self {
+ pub(super)
+ fn new() -> Self {
CodeRepo {
- cached_query: vec![],
- goal_expanders: Code::new(),
- term_expanders: Code::new(),
code: Code::new(),
- in_situ_code: Code::new(),
- term_dir: TermDir::new(),
}
}
#[inline]
- pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
- self.term_dir
- .get(&key)
- .map(|entry| ((entry.0).0.len(), entry.1.len()))
- .unwrap_or((0, 0))
- }
-
- #[inline]
- pub fn truncate_terms(
- &mut self,
- key: PredicateKey,
- len: usize,
- queue_len: usize,
- ) -> (Predicate, VecDeque<TopLevel>) {
- self.term_dir
- .get_mut(&key)
- .map(|entry| {
- let terms =
- if len < (entry.0).0.len() {
- (entry.0).0.drain(len ..).collect()
- } else {
- vec![]
- };
-
- let queue =
- if queue_len < entry.1.len() {
- entry.1.drain(queue_len ..).collect()
- } else {
- VecDeque::new()
- };
-
- (Predicate(terms), queue)
- })
- .unwrap_or((Predicate::new(), VecDeque::new()))
- }
-
- pub(crate)
- fn add_in_situ_result(
- &mut self,
- result: &CompiledResult,
- in_situ_code_dir: &mut InSituCodeDir,
- in_situ_module_dir: &mut ModuleStubDir,
- non_counted_bt_preds: &IndexSet<PredicateKey>,
- ) -> Result<(), SessionError> {
- let (ref decl, ref queue) = result;
- let (name, arity) = decl
- .0
- .first()
- .and_then(|cl| {
- let arity = cl.arity();
- cl.name().map(|name| (name, arity))
- })
- .ok_or(SessionError::NamelessEntry)?;
-
- let non_counted_bt = non_counted_bt_preds.contains(&(name.clone(), arity));
- let module_name = name.owning_module();
-
- let p = self.in_situ_code.len();
-
- match in_situ_module_dir.get_mut(&module_name) {
- Some(ref mut module_stub) if name.has_table(&module_stub.atom_tbl) => {
- module_stub.in_situ_code_dir.insert((name, arity), p);
+ pub(super)
+ fn lookup_local_instr<'a>(
+ &'a self,
+ p: LocalCodePtr,
+ ) -> RefOrOwned<'a, Line> {
+ match p {
+ LocalCodePtr::Halt => {
+ unreachable!()
}
- _ => {
- in_situ_code_dir.insert((name, arity), p);
+ LocalCodePtr::DirEntry(p) => {
+ RefOrOwned::Borrowed(&self.code[p as usize])
+ }
+ LocalCodePtr::IndexingBuf(p, o, i) => {
+ match &self.code[p] {
+ &Line::IndexingCode(ref indexing_lines) => {
+ match &indexing_lines[o] {
+ &IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
+ RefOrOwned::Owned(Line::IndexedChoice(indexed_choice_instrs[i]))
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
}
}
-
- let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
- let mut decl_code = cg.compile_predicate(&decl.0)?;
-
- compile_appendix(&mut decl_code, queue, non_counted_bt)?;
-
- Ok(self.in_situ_code.extend(decl_code.into_iter()))
- }
-
- #[inline]
- pub(super)
- fn size_of_cached_query(&self) -> usize {
- self.cached_query.len()
- }
-
- #[inline]
- pub(super)
- fn take_in_situ_code(&mut self) -> Code {
- mem::replace(&mut self.in_situ_code, Code::new())
}
pub(super)
p: &CodePtr,
) -> Option<RefOrOwned<'a, Line>> {
match p {
- &CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => {
- if p < self.goal_expanders.len() {
- Some(RefOrOwned::Borrowed(&self.goal_expanders[p]))
- } else {
- None
- }
+ &CodePtr::Local(local) => {
+ return Some(self.lookup_local_instr(local));
}
- &CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => {
- if p < self.term_expanders.len() {
- Some(RefOrOwned::Borrowed(&self.term_expanders[p]))
- } else {
- None
- }
+ &CodePtr::REPL(..) => {
+ None
}
- &CodePtr::Local(LocalCodePtr::TopLevel(_, p)) => {
- if p < self.cached_query.len() {
- Some(RefOrOwned::Borrowed(&self.cached_query[p]))
- } else {
- None
- }
- }
- &CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) => {
- Some(RefOrOwned::Borrowed(&self.in_situ_code[p]))
- }
- &CodePtr::Local(LocalCodePtr::DirEntry(p)) => Some(RefOrOwned::Borrowed(&self.code[p])),
- &CodePtr::REPL(..) => None,
&CodePtr::BuiltInClause(ref built_in, _) => {
let call_clause = call_clause!(
ClauseType::BuiltIn(built_in.clone()),
0,
last_call
);
+
Some(RefOrOwned::Owned(call_clause))
}
&CodePtr::CallN(arity, _, last_call) => {
- let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
+ let call_clause = call_clause!(
+ ClauseType::CallN,
+ arity,
+ 0,
+ last_call
+ );
+
Some(RefOrOwned::Owned(call_clause))
}
- &CodePtr::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])),
- &CodePtr::DynamicTransaction(..) => None,
+ &CodePtr::VerifyAttrInterrupt(p) => {
+ Some(RefOrOwned::Borrowed(&self.code[p]))
+ }
+/*
+ &CodePtr::DynamicTransaction(..) => {
+ None
+ }
+*/
}
}
}
use crate::instructions::*;
-use std::collections::VecDeque;
+use indexmap::IndexSet;
-fn scan_for_trust_me(
- code: &Code,
- jmp_offsets: &mut VecDeque<usize>,
- before_idx: usize,
- after_idx: &mut usize,
-) {
- // record the location of the line after the TrustMe capping the
- // choice instruction sequence to after_idx.
- loop {
- match &code[*after_idx] {
- &Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) |
- &Line::Choice(ChoiceInstruction::RetryMeElse(offset)) |
- &Line::IndexedChoice(IndexedChoiceInstruction::Retry(offset)) => {
- *after_idx += offset;
- }
- &Line::Choice(ChoiceInstruction::DefaultTrustMe) |
- &Line::Choice(ChoiceInstruction::TrustMe) |
- &Line::IndexedChoice(IndexedChoiceInstruction::Trust(..)) => {
- break;
- }
- _ => {
- *after_idx += 1;
- }
+fn capture_offset(line: &Line, index: usize, stack: &mut Vec<usize>) -> bool {
+ match line {
+ &Line::Choice(ChoiceInstruction::TryMeElse(offset)) if offset > 0 => {
+ stack.push(index + offset);
}
- }
-
- // search the code in the range for JmpBy instructions and record their
- // offsets for future scanning.
- for (idx, instr) in code[before_idx .. *after_idx].iter().enumerate() {
- match instr {
- &Line::Control(ControlInstruction::JmpBy(_, offset, ..)) => {
- jmp_offsets.push_back(before_idx + idx + offset)
- }
- _ => {
+ &Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) |
+ &Line::Choice(ChoiceInstruction::RetryMeElse(offset)) if offset > 0 => {
+ stack.push(index + offset);
+ }
+ &Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
+ stack.push(index + offset);
+ }
+ &Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
+ stack.push(index + offset);
+ return true;
+ }
+ &Line::Control(ControlInstruction::Proceed) |
+ &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) => {
+ return true;
+ }
+ &Line::Control(ControlInstruction::RevJmpBy(offset)) => {
+ if offset > 0 {
+ stack.push(index - offset);
+ } else {
+ return true;
}
}
- }
-
- *after_idx += 1;
-}
-
-fn capture_next_range(code: &Code, queue: &mut VecDeque<usize>, last_idx: &mut usize) {
- loop {
- match &code[*last_idx] {
- &Line::Choice(ChoiceInstruction::TryMeElse(offset)) |
- &Line::IndexedChoice(IndexedChoiceInstruction::Try(offset)) => {
- let before_idx = *last_idx;
- *last_idx += offset;
+ _ => {
+ }
+ };
- scan_for_trust_me(code, queue, before_idx, last_idx);
- }
- &Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
- queue.push_back(*last_idx + offset);
- *last_idx += 1;
- }
- &Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
- queue.push_back(*last_idx + offset);
- break;
- }
- &Line::Control(ControlInstruction::Proceed) |
- &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) =>
- break,
- _ =>
- *last_idx += 1,
- };
- }
+ false
}
/* This function walks the code of a single predicate, supposed to
*/
pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line))
{
- let mut queue = VecDeque::from(vec![p]);
+ let mut stack = vec![p];
+ let mut visited_indices = IndexSet::new();
- while let Some(first_idx) = queue.pop_front() {
- let mut last_idx = first_idx;
-
- capture_next_range(code, &mut queue, &mut last_idx);
+ while let Some(first_index) = stack.pop() {
+ if visited_indices.contains(&first_index) {
+ continue;
+ } else {
+ visited_indices.insert(first_index);
+ }
- for instr in &code[first_idx .. last_idx + 1] {
+ for (index, instr) in code[first_index ..].iter().enumerate() {
walker(instr);
+
+ if capture_offset(instr, first_index + index, &mut stack) {
+ break;
+ }
}
}
}
/* A function for code walking that might result in modification to
* the code. Otherwise identical to walk_code.
*/
+/*
pub fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line))
{
let mut queue = VecDeque::from(vec![p]);
}
}
}
+*/
-use crate::prolog_parser::ast::*;
-use crate::prolog_parser::parser::get_desc;
-use crate::prolog_parser::tabled_rc::TabledData;
-
use crate::codegen::*;
use crate::debray_allocator::*;
-use crate::forms::*;
-use crate::instructions::*;
-use crate::iterators::*;
-use crate::machine::code_walker::*;
-use crate::machine::machine_errors::*;
-use crate::machine::machine_indices::*;
-use crate::machine::term_expansion::ExpansionAdditionResult;
-use crate::machine::toplevel::*;
+use crate::indexing::{merge_clause_index, remove_index};
+use crate::machine::load_state::set_code_index;
+use crate::machine::loader::*;
+use crate::machine::load_state::LoadState;
use crate::machine::*;
+use crate::machine::term_stream::*;
-use crate::indexmap::{IndexMap, IndexSet};
-
-use crate::ref_thread_local::RefThreadLocal;
+use slice_deque::sdeq;
use std::cell::Cell;
use std::collections::VecDeque;
-use std::fs::File;
-use std::mem;
-use std::path::PathBuf;
-
-#[allow(dead_code)]
-pub fn print_code(code: &Code) {
- for clause in code {
- match clause {
- &Line::Arithmetic(ref arith) => println!("{}", arith),
- &Line::Fact(ref fact_instr) => println!("{}", fact_instr),
- &Line::Cut(ref cut) => println!("{}", cut),
- &Line::Choice(ref choice) => println!("{}", choice),
- &Line::Control(ref control) => println!("{}", control),
- &Line::IndexedChoice(ref choice) => println!("{}", choice),
- &Line::Indexing(ref indexing) => println!("{}", indexing),
- &Line::Query(ref query_instr) => println!("{}", query_instr),
- }
- }
-}
-
-fn fix_filename(
- atom_tbl: TabledData<Atom>,
- mut path: PathBuf,
-) -> Result<PathBuf, SessionError>
-{
- if !path.is_file() {
- if path.extension().is_none() {
- path.set_extension("pl");
- }
-
- if !path.is_file() {
- let filename = clause_name!(path.to_string_lossy().to_string(), atom_tbl);
- return Err(SessionError::InvalidFileName(filename));
- }
- }
-
- Ok(path)
-}
-
-fn load_module(
- wam: &mut Machine,
- stream: Stream,
- suppress_warnings: bool,
- listing_src: &ListingSource,
-) -> Result<ClauseName, SessionError> {
- // follow the operation of compile_user_module, but before
- // compiling, check that a module is declared in the file. if not,
- // throw an exception.
- let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
- setup_indices(wam, clause_name!("builtins"), &mut indices)?;
-
- let mut compiler = ListingCompiler::new(
- &wam.code_repo,
- suppress_warnings,
- listing_src.clone(),
- );
-
- let mut stream = parsing_stream(stream)?;
-
- let results = compiler.gather_items(
- wam,
- &mut stream,
- &mut indices,
- );
-
- let module_name = if let Some(ref module) = &compiler.module {
- module.module_decl.name.clone()
- } else {
- // this impromptu definition (namely, its exports) will be filled out later.
- let module_decl = ModuleDecl { name: listing_src.name(), exports: vec![] };
-
- let mut module = Module::new(module_decl, wam.indices.atom_tbl.clone(), listing_src.clone());
- let module_name = module.module_decl.name.clone();
-
- module.is_impromptu_module = true;
+use std::ops::Range;
- compiler.module = Some(module);
- module_name
- };
-
- results.and_then(|results| compile_work_impl(&mut compiler, wam, indices, results))
- .or_else(|e| {
- wam.indices.take_module(module_name.clone());
- compiler.print_error(&e);
- Err(e)
- })?;
-
- Ok(module_name)
+struct StandaloneCompileResult {
+ clause_code: Code,
+ standalone_skeleton: PredicateSkeleton,
}
pub(super)
-fn load_module_from_file(
+fn bootstrapping_compile(
+ stream: Stream,
wam: &mut Machine,
- path_buf: PathBuf,
- suppress_warnings: bool,
-) -> Result<ClauseName, SessionError> {
- 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 file_handle = Stream::from_file_as_input(filename.clone(), File::open(&path_buf).or_else(|_| {
- Err(SessionError::InvalidFileName(filename.clone()))
- })?);
+ listing_src: ListingSource,
+) -> Result<(), SessionError> {
+ let stream = &mut parsing_stream(stream)?;
+ let term_stream =
+ BootstrappingTermStream::from_prolog_stream(
+ stream,
+ wam.machine_st.atom_tbl.clone(),
+ wam.machine_st.flags,
+ listing_src,
+ );
- path_buf.pop();
+ let loader = Loader::new(term_stream, wam);
+ loader.load()?;
- let listing_src = ListingSource::from_file_and_path(filename, path_buf);
- load_module(wam, file_handle, suppress_warnings, &listing_src)
+ Ok(())
}
-pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
-
// throw errors if declaration or query found.
+pub(super)
fn compile_relation(
cg: &mut CodeGenerator<DebrayAllocator>,
tl: &TopLevel
-) -> Result<Code, ParserError> {
+) -> Result<Code, CompilationError> {
match tl {
- &TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(ParserError::ExpectedRel),
- &TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses.0),
- &TopLevel::Fact(ref fact, ..) => Ok(cg.compile_fact(fact)),
- &TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
+ &TopLevel::Declaration(_) | &TopLevel::Query(_) =>
+ Err(CompilationError::ExpectedRel),
+ &TopLevel::Predicate(ref clauses) =>
+ cg.compile_predicate(&clauses),
+ &TopLevel::Fact(ref fact, ..) =>
+ Ok(cg.compile_fact(fact)),
+ &TopLevel::Rule(ref rule, ..) =>
+ cg.compile_rule(rule),
}
}
-fn issue_singleton_warnings(
- src_name: ClauseName,
- terms_and_locs: Vec<(Term, usize, usize)>,
-) {
- for (term, line_num, _col_num) in terms_and_locs {
- let mut singletons = vec![];
- let mut var_count = IndexMap::new();
-
- for subterm in breadth_first_iter(&term, true) {
- if let TermRef::Var(_, _, var) = subterm {
- let entry = var_count.entry(var).or_insert(0);
- *entry += 1;
- }
- }
+pub(super)
+fn compile_appendix(
+ code: &mut Code,
+ queue: &VecDeque<TopLevel>,
+ jmp_by_locs: Vec<usize>,
+ non_counted_bt: bool,
+ atom_tbl: TabledData<Atom>,
+) -> Result<(), CompilationError> {
+ let mut jmp_by_locs = VecDeque::from(jmp_by_locs);
+
+ for tl in queue.iter() {
+ let code_len = code.len();
+ let jmp_by_offset = jmp_by_locs.pop_front().unwrap();
- for (var, count) in var_count {
- if count == 1 && !var.starts_with("_") && var.as_str() != "!" {
- singletons.push(var);
+ match &mut code[jmp_by_offset] {
+ &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => {
+ *offset = code_len - jmp_by_offset;
+ }
+ _ => {
+ unreachable!()
}
}
- if let Some(last_var) = singletons.pop() {
- print!("Warning: {}:{}: Singleton variables: [",
- src_name, line_num);
+ // false because the inner predicate is a one-off, hence not extensible.
+ let settings = CodeGenSettings::new(false, non_counted_bt);
- for var in singletons {
- print!("{}, ", var);
- }
+ let mut cg = CodeGenerator::<DebrayAllocator>::new(atom_tbl.clone(), settings);
+ let decl_code = compile_relation(&mut cg, tl)?;
- println!("{}]", last_var);
- }
+ jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len()));
+ code.extend(decl_code.into_iter());
}
+
+ Ok(())
}
-// set first jmp_by_call or jmp_by_index instruction to code.len() -
-// idx, where idx is the place it occurs. It only does this to the
-// *first* uninitialized jmp index it encounters, then returns.
-fn set_first_index(code: &mut Code) {
- let code_len = code.len();
-
- for (idx, line) in code.iter_mut().enumerate() {
- match line {
- &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..))
- if *offset == 0 =>
- {
- *offset = code_len - idx;
- debug_assert!(*offset > 0);
-
- break;
- }
- _ => {}
- };
+fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize {
+ if target_pos == 0 {
+ return 0;
}
-}
-pub fn compile_appendix(
- code: &mut Code,
- queue: &VecDeque<TopLevel>,
- non_counted_bt: bool,
-) -> Result<(), ParserError> {
- for tl in queue.iter() {
- set_first_index(code);
- let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
- let decl_code = compile_relation(&mut cg, tl)?;
- code.extend(decl_code.into_iter());
+ let arg_num = skeleton.clauses[target_pos - 1].opt_arg_index_key.arg_num();
+
+ if arg_num == 0 {
+ return target_pos - 1;
}
- Ok(())
+ for index in (0 .. target_pos - 1).rev() {
+ let current_arg_num = skeleton.clauses[index].opt_arg_index_key.arg_num();
+
+ if current_arg_num == 0 || current_arg_num != arg_num {
+ return index + 1;
+ }
+ }
+
+ 0
}
-fn append_trivial_goal(name: &ClauseName, pred: &mut Predicate)
-{
- let var = Box::new(Term::Var(Cell::default(), Rc::new(String::from("X"))));
- let body = QueryTerm::Clause(
- Cell::default(),
- ClauseType::from(clause_name!("$at_end_of_expansion"), 0, None),
- vec![],
- false
- );
+fn compile_standalone_clause(
+ clause: PredicateClause,
+ queue: VecDeque<TopLevel>,
+ settings: CodeGenSettings,
+ atom_tbl: TabledData<Atom>,
+) -> Result<StandaloneCompileResult, SessionError> {
+ let mut cg = CodeGenerator::<DebrayAllocator>::new(atom_tbl.clone(), settings);
+ let mut clause_code = cg.compile_predicate(&vec![clause])?;
+
+ compile_appendix(
+ &mut clause_code,
+ &queue,
+ cg.jmp_by_locs,
+ settings.non_counted_bt,
+ atom_tbl,
+ )?;
+
+ Ok(StandaloneCompileResult {
+ clause_code,
+ standalone_skeleton: cg.skeleton,
+ })
+}
- let rule = Rule {
- head: (name.clone(), vec![var.clone(), var], body),
- clauses: vec![]
- };
+fn derelictize_try_me_else(
+ code: &mut Code,
+ index: usize,
+ retraction_info: &mut RetractionInfo,
+) -> Option<usize> {
+ match &mut code[index] {
+ Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ None
+ }
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut offset)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(index, *offset),
+ );
- pred.0.push(PredicateClause::Rule(rule, 0, 0));
+ Some(mem::replace(offset, 0))
+ }
+ _ => {
+ unreachable!()
+ }
+ }
}
-impl CodeRepo {
- pub fn compile_hook(
- &mut self,
- hook: CompileTimeHook,
- ) -> Result<(), ParserError> {
- let key = (hook.name(), hook.arity());
+fn merge_indices(
+ code: &mut Code,
+ target_index_loc: usize,
+ index_range: Range<usize>,
+ skeleton: &mut [ClauseIndexInfo],
+ retraction_info: &mut RetractionInfo,
+) {
+ for clause_index in index_range {
+ if let Some(index_loc) = skeleton[clause_index].opt_arg_index_key.switch_on_term_loc() {
+ let clause_loc =
+ find_inner_choice_instr(code, skeleton[clause_index].clause_start, index_loc);
- match self.term_dir.get_mut(&key) {
- Some(ref mut preds) => {
- append_trivial_goal(&key.0, &mut preds.0);
+ let target_indexing_line =
+ to_indexing_line_mut(&mut code[target_index_loc]).unwrap();
- let mut cg = CodeGenerator::<DebrayAllocator>::new(false);
- let mut code = cg.compile_predicate(&(preds.0).0)?;
+ skeleton[clause_index].opt_arg_index_key.set_switch_on_term_loc(target_index_loc);
- compile_appendix(&mut code, &preds.1, false)?;
+ merge_clause_index(
+ target_indexing_line,
+ &mut skeleton[0 .. clause_index + 1],
+ clause_loc,
+ AppendOrPrepend::Append,
+ );
- (preds.0).0.pop();
+ retraction_info.push_record(
+ RetractionRecord::AddedIndex(
+ skeleton[clause_index].opt_arg_index_key.clone(),
+ clause_loc,
+ ),
+ );
+ } else {
+ break;
+ }
+ }
+}
- Ok(match hook {
- CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
- self.term_expanders = code
- }
- CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
- self.goal_expanders = code
- }
- })
+fn find_inner_choice_instr(
+ code: &Code,
+ mut index: usize,
+ index_loc: usize,
+) -> usize {
+ loop {
+ match &code[index] {
+ Line::Choice(ChoiceInstruction::TryMeElse(o)) |
+ Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ if *o > 0 {
+ return index;
+ } else {
+ index = index_loc;
+ }
+ }
+ Line::Choice(ChoiceInstruction::TrustMe(_)) => {
+ return index;
}
- None => Ok(match hook {
- CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
- if self.term_expanders.is_empty() {
- let mut preds = Predicate::new();
- append_trivial_goal(&key.0, &mut preds);
-
- let mut cg = CodeGenerator::<DebrayAllocator>::new(false);
- self.term_expanders = cg.compile_predicate(&preds.0)?;
+ Line::IndexingCode(indexing_code) => {
+ match &indexing_code[0] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, v, ..)
+ ) => {
+ index += v;
}
- }
- CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
- if self.goal_expanders.is_empty() {
- let mut preds = Predicate::new();
- append_trivial_goal(&key.0, &mut preds);
-
- let mut cg = CodeGenerator::<DebrayAllocator>::new(false);
- self.goal_expanders = cg.compile_predicate(&preds.0)?;
+ _ => {
+ unreachable!();
}
}
- })
+ }
+ Line::Control(ControlInstruction::RevJmpBy(offset)) => {
+ index -= offset;
+ }
+ _ => {
+ /* Here we land at the line after a TryMeElse(0),
+ * which happens iff a single clause belongs to the
+ * indexed subsequence. So, end the search by pointing
+ * to the original derelict TryMeElse.
+ */
+ return index - 1;
+ }
}
}
}
-fn compile_query(
- terms: Vec<QueryTerm>,
- queue: VecDeque<TopLevel>,
-) -> Result<(Code, AllocVarDict), ParserError> {
- // count backtracking inferences.
- let mut cg = CodeGenerator::<DebrayAllocator>::new(false);
- let mut code = cg.compile_query(&terms)?;
-
- compile_appendix(&mut code, &queue, false)?;
- Ok((code, cg.take_vars()))
-}
-
-fn add_hooks_to_mockup(
- code_repo: &mut CodeRepo,
- hook: CompileTimeHook,
- expansions: (Predicate, VecDeque<TopLevel>),
+fn remove_index_from_subsequence(
+ code: &mut Code,
+ opt_arg_index_key: &OptArgIndexKey,
+ clause_start: usize,
+ retraction_info: &mut RetractionInfo,
) {
- let key = (hook.name(), hook.arity());
- let preds = code_repo
- .term_dir
- .entry(key.clone())
- .or_insert((Predicate::new(), VecDeque::from(vec![])));
-
- (preds.0).0.extend((expansions.0).0.into_iter());
- preds.1.extend(expansions.1.into_iter());
-}
+ if let Some(index_loc) = opt_arg_index_key.switch_on_term_loc() {
+ let clause_start = find_inner_choice_instr(code, clause_start, index_loc);
-fn setup_module_expansions(wam: &mut Machine, module: &Module) {
- let term_expansions = module.term_expansions.clone();
- let goal_expansions = module.goal_expansions.clone();
+ let target_indexing_line =
+ to_indexing_line_mut(&mut code[index_loc]).unwrap();
- add_hooks_to_mockup(
- &mut wam.code_repo,
- CompileTimeHook::TermExpansion,
- term_expansions,
- );
+ let offset = clause_start - index_loc + 1;
- add_hooks_to_mockup(
- &mut wam.code_repo,
- CompileTimeHook::GoalExpansion,
- goal_expansions,
- );
+ remove_index(opt_arg_index_key, target_indexing_line, offset);
+
+ // TODO: this isn't sufficiently precise. The removed offset could
+ // appear anywhere inside an Internal record.
+ retraction_info.push_record(
+ RetractionRecord::RemovedIndex(
+ index_loc,
+ opt_arg_index_key.clone(),
+ offset,
+ ),
+ );
+ }
}
-pub(super)
-fn compile_into_module(
- wam: &mut Machine,
- module_name: ClauseName,
- src: Stream,
- name: ClauseName,
-) -> EvalSession {
- let mut indices = default_index_store!(wam.atom_tbl_of(&name));
- let module = wam.indices.take_module(module_name.clone()).unwrap();
-
- indices.code_dir = module.code_dir.clone();
- indices.op_dir = module.op_dir.clone();
- indices.atom_tbl = module.atom_tbl.clone();
-
- let mut compiler = ListingCompiler::new(
- &wam.code_repo,
- true,
- module.listing_src.clone(),
+fn merge_indexed_subsequences(
+ code: &mut Code,
+ skeleton: &mut PredicateSkeleton,
+ lower_upper_bound: usize,
+ upper_lower_bound: usize,
+ retraction_info: &mut RetractionInfo,
+) -> Option<IndexPtr> {
+ // patch the inner-threaded choice instructions to link the
+ // two sequences, patch lower_bound's outer-threaded choice
+ // instruction to TrustMe (or RetryMeElse), and derelict-ize
+ // target_pos + 1's inner TryMeElse.
+
+ let inner_trust_me_loc =
+ skeleton.clauses[upper_lower_bound - 2].clause_start;
+
+ let inner_try_me_else_loc = find_inner_choice_instr(
+ code,
+ skeleton.clauses[upper_lower_bound].clause_start,
+ skeleton.clauses[upper_lower_bound].opt_arg_index_key
+ .switch_on_term_loc().unwrap(),
);
- match compile_into_module_impl(wam, &mut compiler, module, src, indices) {
- Ok(()) => {
- EvalSession::EntrySuccess
+ match &mut code[inner_try_me_else_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(
+ skeleton.clauses[upper_lower_bound].clause_start,
+ *o,
+ ),
+ );
+
+ match *o {
+ 0 => {
+ code[inner_try_me_else_loc] =
+ Line::Choice(ChoiceInstruction::TrustMe(0));
+ }
+ o => {
+ match &code[inner_try_me_else_loc + o] {
+ Line::Control(ControlInstruction::RevJmpBy(0)) => {
+ code[inner_try_me_else_loc] =
+ Line::Choice(ChoiceInstruction::TrustMe(o));
+ }
+ _ => {
+ code[inner_try_me_else_loc] =
+ Line::Choice(ChoiceInstruction::RetryMeElse(o));
+ }
+ }
+ }
+ }
}
- Err(e) => {
- compiler.drop_expansions(&mut wam.code_repo);
- EvalSession::from(e)
+ _ => {
}
}
-}
-fn compile_into_module_impl(
- wam: &mut Machine,
- compiler: &mut ListingCompiler,
- module: Module,
- src: Stream,
- mut indices: IndexStore,
-) -> Result<(), SessionError> {
- setup_module_expansions(wam, &module);
+ thread_choice_instr_at_to(
+ code,
+ inner_trust_me_loc,
+ inner_try_me_else_loc,
+ retraction_info,
+ );
- let module_name = module.module_decl.name.clone();
- // compiler.module = Some(module); This trips the goal expansion up. Should be possible to 'merge' modules.
- // A much better strategy!
- wam.indices.insert_module(module);
+ let mut end_of_upper_lower_bound = None;
- wam.code_repo.compile_hook(CompileTimeHook::TermExpansion)?;
- wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion)?;
+ for index in upper_lower_bound .. skeleton.clauses.len() {
+ if !skeleton.clauses[index].opt_arg_index_key.is_some() {
+ end_of_upper_lower_bound = Some(index);
+ break;
+ }
+ }
- let mut results = compiler.gather_items(
- wam,
- &mut parsing_stream(src)?,
- &mut indices,
- )?;
+ let outer_threaded_choice_instr_loc =
+ skeleton.clauses[lower_upper_bound].clause_start - 2;
- compiler.adapt_in_situ_code(
- results.worker_results,
- wam,
- &mut indices.code_dir,
- &mut indices.module_dir,
- &mut results.in_situ_code,
- &results.in_situ_code_dir,
- &results.in_situ_module_dir,
- )?;
+ match end_of_upper_lower_bound {
+ Some(outer_threaded_clause_index) => {
+ thread_choice_instr_at_to(
+ code,
+ outer_threaded_choice_instr_loc,
+ skeleton.clauses[outer_threaded_clause_index].clause_start,
+ retraction_info,
+ );
+ }
+ None => {
+ match &mut code[outer_threaded_choice_instr_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(inner_trust_me_loc, *o),
+ );
- let mut clause_code_generator = ClauseCodeGenerator::new(
- results.in_situ_code.len(),
- module_name.clone()
- );
+ *o = 0;
- clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?;
+ return Some(IndexPtr::Index(outer_threaded_choice_instr_loc + 1));
+ }
+ _ => {
+ }
+ }
+ }
+ }
- let top_level_term_dir = results.top_level_term_dirs.consolidate();
- let module = wam.indices.take_module(module_name).unwrap();
+ None
+}
- add_module(
- wam,
- module,
- indices,
- top_level_term_dir,
+fn delete_from_dynamic_skeleton(
+ compilation_target: CompilationTarget,
+ key: PredicateKey,
+ skeleton: &mut PredicateSkeleton,
+ target_pos: usize,
+ retraction_info: &mut RetractionInfo,
+) -> usize {
+ let clause_clause_loc = skeleton.clause_clause_locs.remove(target_pos);
+ let clause_index_info = skeleton.clauses.remove(target_pos);
+
+ retraction_info.push_record(
+ RetractionRecord::RemovedDynamicSkeletonClause(
+ compilation_target,
+ key,
+ target_pos,
+ clause_index_info,
+ clause_clause_loc,
+ ),
);
- wam.code_repo.code.extend(results.in_situ_code.into_iter());
- clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
-
- Ok(compiler.drop_expansions(&mut wam.code_repo))
+ clause_clause_loc
}
-#[derive(Debug)]
-pub struct GatherResult {
- dynamic_clause_map: DynamicClauseMap,
- pub(crate) worker_results: Vec<PredicateCompileQueue>,
- toplevel_results: Vec<PredicateCompileQueue>,
- toplevel_indices: IndexStore,
- addition_results: ExpansionAdditionResult,
- top_level_terms: Vec<(Term, usize, usize)>,
- top_level_term_dirs: TermDirQuantum,
- module_term_dirs: TermDirQuantum,
- in_situ_code_dir: InSituCodeDir,
- in_situ_code: Code,
- in_situ_module_dir: ModuleStubDir,
-}
+fn blunt_leading_choice_instr(
+ code: &mut Code,
+ mut instr_loc: usize,
+ retraction_info: &mut RetractionInfo,
+) -> usize {
+ loop {
+ match &mut code[instr_loc] {
+ Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedRetryMeElse(instr_loc, *o),
+ );
-#[derive(Debug)]
-pub struct ClauseCodeGenerator {
- len_offset: usize,
- code: Code,
- module_name: ClauseName,
- pi_to_loc: IndexMap<PredicateKey, usize>,
-}
+ code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(*o));
+
+ return instr_loc;
+ }
+ Line::Choice(ChoiceInstruction::TrustMe(offset)) => {
+ retraction_info.push_record(
+ RetractionRecord::AppendedTrustMe(instr_loc, *offset, false),
+ );
-impl ClauseCodeGenerator {
- #[inline]
- fn new(len_offset: usize, module_name: ClauseName) -> Self {
- ClauseCodeGenerator {
- len_offset,
- code: vec![],
- module_name,
- pi_to_loc: IndexMap::new(),
+ code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(0));
+ return instr_loc + 1;
+ }
+ Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ return instr_loc + 1;
+ }
+ Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
+ instr_loc += *o;
+ }
+ Line::Control(ControlInstruction::RevJmpBy(o)) => {
+ instr_loc -= *o;
+ }
+ _ => {
+ unreachable!()
+ }
}
}
+}
- // compiles the latest version of clause/2.
- fn generate_clause_code(
- &mut self,
- dynamic_clause_map: &DynamicClauseMap,
- wam: &Machine,
- ) -> Result<(), SessionError> {
- for ((name, arity), heads_and_tails) in dynamic_clause_map {
- if heads_and_tails.is_empty() {
- continue;
- }
+fn set_switch_var_offset_to_choice_instr_(
+ code: &mut Code,
+ index_loc: usize,
+ offset: usize,
+ retraction_info: &mut RetractionInfo,
+) {
+ let target_indexing_line =
+ to_indexing_line_mut(&mut code[index_loc]).unwrap();
- let predicate = Predicate(
- heads_and_tails
- .iter()
- .map(|(head, tail)| {
- let clause = Term::Clause(
- Cell::default(),
- clause_name!("clause"),
- vec![Box::new(head.clone()), Box::new(tail.clone())],
- None,
- );
+ let v =
+ match &mut target_indexing_line[0] {
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => {
+ *v
+ }
+ _ => {
+ unreachable!();
+ }
+ };
- PredicateClause::Fact(clause, 0, 0)
- })
- .collect(),
+ match &code[index_loc + v] {
+ Line::Choice(ChoiceInstruction::TryMeElse(_)) => {
+ }
+ _ => {
+ set_switch_var_offset(
+ code,
+ index_loc,
+ offset,
+ retraction_info,
);
-
- let p = self.code.len() + wam.code_repo.code.len() + self.len_offset;
- let mut cg = CodeGenerator::<DebrayAllocator>::new(false);
-
- let mut decl_code = compile_relation(
- &mut cg,
- &TopLevel::Predicate(predicate),
- )?;
-
- compile_appendix(&mut decl_code, &VecDeque::new(), false)?;
-
- self.pi_to_loc.insert((name.clone(), *arity), p);
- self.code.extend(decl_code.into_iter());
}
-
- Ok(())
}
+}
- fn add_clause_code(self, wam: &mut Machine, dynamic_code_dir: DynamicClauseMap)
- {
- wam.code_repo.code.extend(self.code.into_iter());
+#[inline]
+fn set_switch_var_offset(
+ code: &mut Code,
+ index_loc: usize,
+ offset: usize,
+ retraction_info: &mut RetractionInfo,
+) {
+ let target_indexing_line =
+ to_indexing_line_mut(&mut code[index_loc]).unwrap();
- if self.module_name.as_str() == "user" {
- for ((name, arity), _) in &dynamic_code_dir {
- wam.indices.code_dir.entry((name.clone(), *arity))
- .or_insert(CodeIndex::dynamic_undefined(clause_name!("user")));
+ let old_v =
+ match &mut target_indexing_line[0] {
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => {
+ mem::replace(v, offset)
}
- }
+ _ => {
+ unreachable!()
+ }
+ };
- for ((name, arity), _) in dynamic_code_dir {
- wam.indices.dynamic_code_dir.insert((name.owning_module(), name, arity),
- DynamicPredicateInfo::default());
- }
+ retraction_info.push_record(
+ RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v),
+ );
+}
- for ((name, arity), p) in self.pi_to_loc {
- let entry = wam
- .indices
- .dynamic_code_dir
- .entry((name.owning_module(), name, arity))
- .or_insert(DynamicPredicateInfo::default());
+fn internalize_choice_instr_at(
+ code: &mut Code,
+ instr_loc: usize,
+ retraction_info: &mut RetractionInfo,
+) {
+ match &mut code[instr_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(instr_loc, 0),
+ );
- entry.clauses_subsection_p = p;
+ code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
}
- }
-}
+ Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
+ let o = *o;
-fn insert_or_refresh_term_dir_quantum(
- term_dir: &TermDir,
- key: PredicateKey,
- term_dirs: &mut TermDirQuantum
-) {
- match term_dir.get(&key) {
- Some((ref preds, ref queue)) => {
- let entry = TermDirQuantumEntry::from(preds, queue);
- term_dirs.insert_or_refresh(key, entry);
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(instr_loc, o),
+ );
+
+ match &mut code[instr_loc + o] {
+ Line::Control(ControlInstruction::RevJmpBy(p))
+ if *p == 0 => {
+ code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(o));
+ }
+ _ => {
+ code[instr_loc] = Line::Choice(ChoiceInstruction::RetryMeElse(o));
+ }
+ }
}
- None => {
- let entry = TermDirQuantumEntry::from(&Predicate::new(), &VecDeque::new());
- term_dirs.insert_or_refresh(key, entry);
+ _ => {
+ unreachable!();
}
}
}
-#[derive(Debug)]
-pub struct ListingCompiler {
- module: Option<Module>,
- user_term_dir: TermDir,
- orig_term_expansion_lens: (usize, usize),
- orig_goal_expansion_lens: (usize, usize),
- initialization_goals: (Vec<QueryTerm>, VecDeque<TopLevel>),
- suppress_warnings: bool,
- listing_src: ListingSource, // a file? a module?
-}
-
-fn add_toplevel(
- wam: &mut Machine,
- indices: IndexStore,
- term_dir: TermDir,
+fn thread_choice_instr_at_to(
+ code: &mut Code,
+ mut instr_loc: usize,
+ target_loc: usize,
+ retraction_info: &mut RetractionInfo,
) {
- wam.add_batched_code_dir(indices.code_dir);
- wam.add_batched_ops(indices.op_dir);
- wam.add_in_situ_module_dir(indices.module_dir);
+ loop {
+ match &mut code[instr_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) |
+ Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o))
+ if target_loc >= instr_loc => {
+ retraction_info.push_record(
+ RetractionRecord::ReplacedChoiceOffset(instr_loc, *o),
+ );
- wam.code_repo.term_dir.extend(term_dir.into_iter());
-}
+ *o = target_loc - instr_loc;
+ return;
+ }
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) |
+ Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) => {
+ instr_loc += *o;
+ }
+ Line::Control(ControlInstruction::RevJmpBy(ref mut o))
+ if instr_loc >= target_loc => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedRevJmpBy(instr_loc, *o),
+ );
-#[inline]
-fn add_module(
- wam: &mut Machine,
- mut module: Module,
- indices: IndexStore,
- term_dir: TermDir,
-) {
- module.code_dir.extend(indices.code_dir);
- module.op_dir.extend(indices.op_dir);
- module.term_dir.extend(term_dir);
+ *o = instr_loc - target_loc;
+ return;
+ }
+ Line::Choice(ChoiceInstruction::TrustMe(ref mut o))
+ if target_loc >= instr_loc => {
+ retraction_info.push_record(
+ RetractionRecord::AppendedTrustMe(instr_loc, *o, false),
+ //choice_instr.is_default()),
+ );
+
+ code[instr_loc] =
+ Line::Choice(ChoiceInstruction::RetryMeElse(target_loc - instr_loc));
- wam.add_in_situ_module_dir(indices.module_dir);
- wam.add_module(module);
+ return;
+ }
+ Line::Choice(ChoiceInstruction::TrustMe(o))
+ if *o > 0 => {
+ instr_loc += *o;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
}
-fn add_non_module_code(
- wam: &mut Machine,
- dynamic_clause_map: DynamicClauseMap,
- code: Code,
- indices: IndexStore,
- term_dir: TermDir,
-) -> Result<(), SessionError> {
- wam.check_toplevel_code(&indices)?;
+fn remove_non_leading_clause(
+ code: &mut Code,
+ preceding_choice_instr_loc: usize,
+ non_indexed_choice_instr_loc: usize,
+ retraction_info: &mut RetractionInfo,
+) -> Option<IndexPtr> {
+ match &mut code[non_indexed_choice_instr_loc] {
+ Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) => {
+ let o = *o;
+
+ thread_choice_instr_at_to(
+ code,
+ preceding_choice_instr_loc,
+ non_indexed_choice_instr_loc + o,
+ retraction_info,
+ );
- let mut clause_code_generator = ClauseCodeGenerator::new(code.len(), clause_name!("user"));
- clause_code_generator.generate_clause_code(&dynamic_clause_map, wam)?;
+ None
+ }
+ Line::Choice(ChoiceInstruction::TrustMe(_)) => {
+ match &mut code[preceding_choice_instr_loc] {
+ Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedRetryMeElse(
+ preceding_choice_instr_loc,
+ *o,
+ ),
+ );
- add_toplevel(wam, indices, term_dir);
- wam.code_repo.code.extend(code);
- clause_code_generator.add_clause_code(wam, dynamic_clause_map);
+ code[preceding_choice_instr_loc] =
+ Line::Choice(ChoiceInstruction::TrustMe(0));
- Ok(())
-}
+ None
+ }
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(
+ preceding_choice_instr_loc,
+ *o,
+ )
+ );
-pub(super)
-fn load_library(
- wam: &mut Machine,
- name: ClauseName,
- suppress_warnings: bool,
-) -> Result<ClauseName, SessionError> {
- match LIBRARIES.borrow().get(name.as_str()) {
- Some(code) => {
- let listing_src = ListingSource::User;
-
- load_module(
- wam,
- Stream::from(*code),
- suppress_warnings,
- &listing_src,
- )
- }
- None => {
- let err = ExistenceError::ModuleSource(ModuleSource::Library(
- name.clone()
- ));
+ *o = 0;
- Err(SessionError::ExistenceError(err))
+ Some(IndexPtr::Index(preceding_choice_instr_loc + 1))
+ }
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ _ => {
+ unreachable!();
}
}
}
-impl ListingCompiler {
- #[inline]
- pub fn new(
- code_repo: &CodeRepo,
- suppress_warnings: bool,
- listing_src: ListingSource,
- ) -> Self {
- ListingCompiler {
- module: None,
- user_term_dir: TermDir::new(),
- orig_term_expansion_lens: code_repo
- .term_dir_entry_len((clause_name!("term_expansion"), 2)),
- orig_goal_expansion_lens: code_repo
- .term_dir_entry_len((clause_name!("goal_expansion"), 2)),
- initialization_goals: (vec![], VecDeque::from(vec![])),
- suppress_warnings,
- listing_src
- }
- }
+fn finalize_retract(
+ key: PredicateKey,
+ compilation_target: CompilationTarget,
+ skeleton: &mut PredicateSkeleton,
+ code_index: CodeIndex,
+ target_pos: usize,
+ index_ptr_opt: Option<IndexPtr>,
+ retraction_info: &mut RetractionInfo,
+) -> usize {
+ let clause_clause_loc =
+ delete_from_dynamic_skeleton(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton,
+ target_pos,
+ retraction_info,
+ );
- /* Replace calls to self with a localized index cell, not
- * available to the global CodeIndex. This is done to implement
- * logical update semantics for dynamic database updates.
- */
- fn localize_self_calls(&mut self, key: PredicateKey, code: &mut Code, p: usize, target_p: usize)
- {
- let (name, arity) = key;
-
- let self_idx = CodeIndex::default();
- set_code_index!(self_idx, IndexPtr::Index(target_p), self.get_module_name());
-
- walk_code_mut(code, p, |instr|
- match instr {
- Line::Control(ControlInstruction::CallClause(ref mut ct, ..)) => {
- match ct {
- ClauseType::Named(ref ct_name, ct_arity, ref mut idx)
- if ct_name == &name && arity == *ct_arity =>
- {
- *idx = self_idx.clone();
- }
- ClauseType::Op(ref op_name, ref shared_op_desc, ref mut idx)
- if op_name == &name && shared_op_desc.arity() == arity =>
- {
- *idx = self_idx.clone();
- }
- _ => {}
- }
- }
- _ => {}
- },
+ if let Some(index_ptr) = index_ptr_opt {
+ set_code_index(
+ retraction_info,
+ &compilation_target,
+ key,
+ &code_index,
+ index_ptr,
);
}
- fn use_module(
- &mut self,
- submodule: ClauseName,
- code_repo: &mut CodeRepo,
- flags: MachineFlags,
- wam_indices: &mut IndexStore,
- indices: &mut IndexStore,
- ) -> Result<(), SessionError> {
- let module_name = self.get_module_name();
+ clause_clause_loc
+}
- if let Some(mut submodule) = wam_indices.take_module(submodule) {
- unwind_protect!(
- indices.use_module(code_repo, flags, &submodule),
- wam_indices.insert_module(submodule)
- );
+fn remove_leading_unindexed_clause(
+ code: &mut Code,
+ non_indexed_choice_instr_loc: usize,
+ retraction_info: &mut RetractionInfo,
+) -> Option<IndexPtr> {
+ match &mut code[non_indexed_choice_instr_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ if *o > 0 {
+ retraction_info.push_record(
+ RetractionRecord::ModifiedTryMeElse(
+ non_indexed_choice_instr_loc,
+ *o,
+ )
+ );
- if let Some(ref mut module) = &mut self.module {
- module.remove_module(module_name, &submodule);
- unwind_protect!(
- module.use_module(code_repo, flags, &submodule),
- wam_indices.insert_module(submodule)
+ let o = mem::replace(o, 0);
+
+ let index_ptr = blunt_leading_choice_instr(
+ code,
+ non_indexed_choice_instr_loc + o,
+ retraction_info,
);
+
+ Some(IndexPtr::Index(index_ptr))
} else {
- submodule.inserted_expansions = true;
- wam_indices.remove_module(clause_name!("user"), &submodule);
+ Some(IndexPtr::DynamicUndefined)
}
-
- Ok(wam_indices.insert_module(submodule))
- } else {
- let err = ExistenceError::ModuleSource(ModuleSource::File(
- module_name,
- ));
-
- Err(SessionError::ExistenceError(err))
+ }
+ _ => {
+ unreachable!();
}
}
+}
- fn use_qualified_module(
- &mut self,
- submodule: ClauseName,
- code_repo: &mut CodeRepo,
- flags: MachineFlags,
- exports: &Vec<ModuleExport>,
- wam_indices: &mut IndexStore,
- indices: &mut IndexStore,
- ) -> Result<(), SessionError> {
- let module_name = self.get_module_name();
+fn prepend_compiled_clause(
+ code: &mut Code,
+ compilation_target: CompilationTarget,
+ key: PredicateKey,
+ mut clause_code: Code,
+ skeleton: &mut PredicateSkeleton,
+ retraction_info: &mut RetractionInfo,
+) -> usize {
+ let clause_loc = code.len();
+ let mut prepend_queue = sdeq![];
+
+ let target_arg_num = skeleton.clauses[0].opt_arg_index_key.arg_num();
+ let head_arg_num = skeleton.clauses[1].opt_arg_index_key.arg_num();
+
+ if skeleton.clauses[0].opt_arg_index_key.switch_on_term_loc().is_some() {
+ match skeleton.clauses[1].opt_arg_index_key.switch_on_term_loc() {
+ Some(index_loc) if target_arg_num == head_arg_num => {
+ prepend_queue.extend(clause_code.drain(3 ..));
+
+ skeleton.clauses[0].opt_arg_index_key += index_loc - 1;
+ skeleton.clauses[0].clause_start = clause_loc + 2;
+
+ retraction_info.push_record(
+ RetractionRecord::AddedIndex(
+ skeleton.clauses[0].opt_arg_index_key.clone(),
+ skeleton.clauses[0].clause_start,
+ ),
+ );
- if let Some(mut submodule) = wam_indices.take_module(submodule) {
- unwind_protect!(
- indices.use_qualified_module(code_repo, flags, &submodule, exports),
- wam_indices.insert_module(submodule)
- );
+ let outer_thread_choice_loc = skeleton.clauses[1].clause_start - 2;
- if let &mut Some(ref mut module) = &mut self.module {
- module.remove_module(module_name, &submodule);
- unwind_protect!(
- module.use_qualified_module(code_repo, flags, &submodule, exports),
- wam_indices.insert_module(submodule)
+ retraction_info.push_record(
+ RetractionRecord::SkeletonClauseStartReplaced(
+ compilation_target,
+ key.clone(),
+ 1,
+ skeleton.clauses[1].clause_start,
+ ),
);
- } else {
- submodule.inserted_expansions = true;
- wam_indices.remove_module(clause_name!("user"), &submodule);
- }
- Ok(wam_indices.insert_module(submodule))
- } else {
- let err = ExistenceError::ModuleSource(ModuleSource::File(
- module_name
- ));
+ skeleton.clauses[1].clause_start =
+ find_inner_choice_instr(
+ code,
+ skeleton.clauses[1].clause_start,
+ index_loc,
+ );
- Err(SessionError::ExistenceError(err))
- }
- }
+ let inner_thread_rev_offset =
+ 3 + prepend_queue.len() + clause_loc - skeleton.clauses[1].clause_start;
- #[inline]
- fn get_module_name(&self) -> ClauseName {
- self.module
- .as_ref()
- .map(|module| module.module_decl.name.clone())
- .unwrap_or(ClauseName::BuiltIn("user"))
- }
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)),
+ );
- fn generate_init_goal_code(
- &mut self,
- ) -> Result<Code, SessionError> {
- let query_terms = mem::replace(&mut self.initialization_goals.0, vec![]);
- let queue = mem::replace(&mut self.initialization_goals.1, VecDeque::new());
+ prepend_queue.push_front(
+ Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())),
+ );
- compile_query(query_terms, queue)
- .map(|(code, _)| code)
- .map_err(SessionError::from)
- }
+ // prepend_queue is now:
+ // | TryMeElse N_2
+ // | (clause_code)
+ // +N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1)
- fn set_code_index(
- &mut self,
- wam: &Machine,
- key: PredicateKey,
- in_situ_code: &mut Code,
- code_dir: &mut CodeDir,
- in_situ_code_dir: &InSituCodeDir,
- decl: PredicateCompileQueue,
- ) -> Result<(), SessionError> {
- let p = wam.code_repo.code.len();
+ prepend_queue.push_front(
+ Line::Control(ControlInstruction::RevJmpBy(
+ 1 + clause_loc - index_loc
+ )),
+ );
- let idx = code_dir
- .entry(key.clone())
- .or_insert(CodeIndex::default());
+ let outer_thread_choice_offset = // outer_thread_choice_loc WAS index_loc - 1..
+ match derelictize_try_me_else(code, outer_thread_choice_loc, retraction_info) {
+ Some(next_subseq_offset) => {
+ // skeleton.clauses[1] has a non-stub TryMeElse.
- Ok(match in_situ_code_dir.get(&key) {
- Some(in_situ_p) => {
- set_code_index!(idx, IndexPtr::Index(p + *in_situ_p), self.get_module_name());
- self.localize_self_calls(key, in_situ_code, *in_situ_p, p + *in_situ_p);
- }
- None => {
- let (decl, queue) = decl;
+ let outer_thread_rev_offset =
+ prepend_queue.len() + 1 + clause_loc - outer_thread_choice_loc -
+ next_subseq_offset;
- let mut cg = CodeGenerator::<DebrayAllocator>::new(false);
- let mut decl_code = cg.compile_predicate(&decl.0)?;
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(outer_thread_rev_offset))
+ );
- compile_appendix(&mut decl_code, &queue, false)?;
+ prepend_queue.len()
+ }
+ None => {
+ // This case occurs when the clauses of
+ // the host predicate, up to and including
+ // the prepending of this clause, are
+ // indexed.
+
+ // The outer TryMeElse / RevJmpBy pushed
+ // in this case are stub instructions
+ // awaiting the addition of unindexed
+ // clauses.
+
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(0)),
+ );
+
+ 0
+ }
+ };
+
+ prepend_queue.push_front(
+ Line::Choice(ChoiceInstruction::TryMeElse(outer_thread_choice_offset)),
+ );
+
+ // prepend_queue is now:
+ // | TryMeElse N_3
+ // | RevJmpBy (SwitchOnTerm at index_loc)
+ // | TryMeElse N_2
+ // | (clause_code)
+ // N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1)
+ // N_3 | RevJmpBy (TryMeElse(N_1) at index_loc - 1 or TrustMe if N_1 == 0)
+
+ let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
+
+ merge_clause_index(
+ target_indexing_line,
+ &mut skeleton.clauses,
+ clause_loc + 2, // == skeleton.clauses[0].clause_start
+ AppendOrPrepend::Prepend,
+ );
+
+ set_switch_var_offset(
+ code,
+ index_loc,
+ clause_loc - index_loc + 2,
+ retraction_info,
+ );
- let in_situ_p = in_situ_code.len();
+ internalize_choice_instr_at(code, skeleton.clauses[1].clause_start, retraction_info);
- in_situ_code.extend(decl_code.into_iter());
+ code.extend(prepend_queue.into_iter());
- set_code_index!(idx, IndexPtr::Index(p + in_situ_p), self.get_module_name());
- self.localize_self_calls(key, in_situ_code, in_situ_p, p + in_situ_p);
+ clause_loc + (outer_thread_choice_offset == 0) as usize
}
- })
- }
+ _ => {
+ prepend_queue.extend(clause_code.drain(1 ..));
- fn adapt_in_situ_code(
- &mut self,
- decls: Vec<PredicateCompileQueue>,
- wam: &Machine,
- code_dir: &mut CodeDir,
- module_dir: &mut ModuleDir,
- in_situ_code: &mut Code,
- in_situ_code_dir: &InSituCodeDir,
- in_situ_module_dir: &ModuleStubDir,
- ) -> Result<(), SessionError> {
- for decl in decls {
- let key = decl.0
- .predicate_indicator()
- .ok_or(SessionError::NamelessEntry)?;
-
- let (name, _arity) = key.clone();
- let module_name = name.owning_module();
-
- match in_situ_module_dir.get(&module_name) {
- Some(ref module_stub) if name.has_table(&module_stub.atom_tbl) => {
- let module =
- module_dir.entry(module_name.clone())
- .or_insert_with(|| {
- let module_decl = ModuleDecl {
- name: module_name.clone(),
- exports: vec![]
- };
-
- Module::new(
- module_decl,
- module_stub.atom_tbl.clone(),
- self.listing_src.clone(),
- )
- });
-
- self.set_code_index(
- wam,
- key,
- in_situ_code,
- &mut module.code_dir,
- &module_stub.in_situ_code_dir,
- decl,
- )?;
- }
- _ => {
- self.set_code_index(
- wam,
- key,
- in_situ_code,
- code_dir,
- in_situ_code_dir,
- decl,
- )?;
+ skeleton.clauses[0].opt_arg_index_key += clause_loc;
+ skeleton.clauses[0].clause_start = clause_loc + 2;
+
+ let old_clause_start = skeleton.clauses[1].clause_start;
+
+ let inner_thread_rev_offset =
+ 2 + prepend_queue.len() + clause_loc - old_clause_start;
+
+ // this is a stub for chaining inner-threaded choice
+ // instructions.
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(0))
+ );
+
+ let prepend_queue_len = prepend_queue.len();
+
+ match &mut prepend_queue[1] {
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o))
+ if *o == 0 => {
+ *o = prepend_queue_len - 2;
+ }
+ _ => {
+ unreachable!();
+ }
}
- }
- }
- Ok(())
- }
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)),
+ );
- fn add_term_dir_terms(
- &mut self,
- hook: CompileTimeHook,
- code_repo: &mut CodeRepo,
- key: PredicateKey,
- clause: PredicateClause,
- queue: VecDeque<TopLevel>,
- ) -> (usize, usize) {
- let preds = code_repo
- .term_dir
- .entry(key.clone())
- .or_insert((Predicate::new(), VecDeque::from(vec![])));
-
- let (mut len, mut queue_len) = ((preds.0).0.len(), preds.1.len());
-
- if self.module.is_some() && hook.has_module_scope() {
- let module_preds = self
- .user_term_dir
- .entry(key.clone())
- .or_insert((Predicate::new(), VecDeque::from(vec![])));
-
- if let Some(ref mut module) = &mut self.module {
- module.add_expansion_record(hook, clause.clone(), queue.clone());
- module.add_local_expansion(hook, clause.clone(), queue.clone());
+ prepend_queue.push_front(
+ Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())),
+ );
+
+ // prepend_queue is now:
+ // | TryMeElse(N_2)
+ // | SwitchOnTerm 2, ...
+ // | TryMeElse(0)
+ // | (clause_code)
+ // +N_2 | RevJmpBy (RetryMeElse(M_1))
+
+ internalize_choice_instr_at(code, old_clause_start, retraction_info);
+
+ code.extend(prepend_queue.into_iter());
+
+ clause_loc // + (outer_thread_choice_offset == 0 as usize)
}
+ }
+ } else {
+ match skeleton.clauses[1].opt_arg_index_key.switch_on_term_loc() {
+ Some(_) => {
+ prepend_queue.extend(clause_code.drain(1 ..));
- (module_preds.0).0.push(clause);
- module_preds.1.extend(queue.into_iter());
+ let old_clause_start = skeleton.clauses[1].clause_start - 2;
- (preds.0).0.extend((module_preds.0).0.iter().cloned());
- preds.1.extend(module_preds.1.iter().cloned());
- } else {
- let module_preds = self
- .user_term_dir
- .entry(key.clone())
- .or_insert((Predicate::new(), VecDeque::from(vec![])));
+ let inner_thread_rev_offset =
+ 1 + prepend_queue.len() + clause_loc - old_clause_start;
- len += 1;
- queue_len += queue.len();
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)),
+ );
- (preds.0).0.push(clause);
- preds.1.extend(queue.into_iter());
+ prepend_queue.push_front(
+ Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())),
+ );
- (preds.0).0.extend((module_preds.0).0.iter().cloned());
- preds.1.extend(module_preds.1.iter().cloned());
- }
+ // prepend_queue is now:
+ // | TryMeElse(N_2)
+ // | (clause_code)
+ // +N_2 | RevJmpBy (RetryMeElse(M_1))
- (len, queue_len)
- }
+ internalize_choice_instr_at(code, old_clause_start, retraction_info);
- fn submit_op(
- &mut self,
- wam: &Machine,
- indices: &mut IndexStore,
- op_decl: &OpDecl,
- ) -> Result<(), SessionError> {
- let spec = get_desc(
- op_decl.name(),
- composite_op!(
- self.module.is_some(),
- &wam.indices.op_dir,
- &mut indices.op_dir
- ),
- );
+ code.extend(prepend_queue.into_iter());
- op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
- }
+ // skeleton.clauses[0].opt_arg_index_key += clause_loc;
+ skeleton.clauses[0].clause_start = clause_loc;
- fn process_decl(
- &mut self,
- decl: Declaration,
- wam: &mut Machine,
- indices: &mut IndexStore,
- flags: MachineFlags,
- non_counted_bt_preds: &mut IndexSet<PredicateKey>,
- ) -> Result<(), SessionError> {
- match decl {
- Declaration::Dynamic(..) => {
- Ok(())
- }
- Declaration::EndOfFile => {
- Ok(())
+ clause_loc // + (outer_thread_choice_offset == 0 as usize)
}
- Declaration::Hook(hook, clause, queue) => {
- let key = (hook.name(), hook.arity());
- let (len, queue_len) =
- self.add_term_dir_terms(hook, &mut wam.code_repo, key.clone(), clause, queue);
+ None => {
+ prepend_queue.extend(clause_code.drain(1 ..));
- let result = wam
- .code_repo
- .compile_hook(hook)
- .map_err(SessionError::from);
+ let old_clause_start = skeleton.clauses[1].clause_start;
- wam.code_repo.truncate_terms(key, len, queue_len);
+ let inner_thread_rev_offset =
+ 1 + prepend_queue.len() + clause_loc - old_clause_start;
- result
- }
- Declaration::Module(module_decl) => {
- if self.module.is_none() {
- let module_name = module_decl.name.clone();
- let atom_tbl = TabledData::new(module_name.to_rc());
-
- for export in module_decl.exports.iter() {
- if let ModuleExport::OpDecl(ref op_decl) = export {
- self.submit_op(wam, indices, op_decl)?;
- }
- }
+ prepend_queue.push_back(
+ Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)),
+ );
- let listing_src = self.listing_src.clone();
+ prepend_queue.push_front(
+ Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())),
+ );
- Ok(self.module = Some(Module::new(module_decl, atom_tbl, listing_src)))
- } else {
- Err(SessionError::from(ParserError::InvalidModuleDecl))
- }
- }
- Declaration::ModuleInitialization(query_terms, queue) => {
- self.initialization_goals.0.extend(query_terms.into_iter());
- self.initialization_goals.1.extend(queue.into_iter());
-
- Ok(())
- }
- Declaration::MultiFile(..) => {
- Ok(())
- }
- Declaration::NonCountedBacktracking(name, arity) => {
- non_counted_bt_preds.insert((name, arity));
- Ok(())
- }
- Declaration::Op(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)) => {
- let name = if !wam.indices.modules.contains_key(&name) {
- load_library(wam, name, true)?
- } else {
- name
- };
+ // prepend_queue is now:
+ // | TryMeElse(N_2)
+ // | (clause_code)
+ // +N_2 | RevJmpBy (RetryMeElse(M_1))
- self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
- }
- Declaration::UseModule(ModuleSource::File(filename)) => {
- let mut path_buf = self.listing_src.path();
- path_buf.push(filename.as_str());
+ internalize_choice_instr_at(code, old_clause_start, retraction_info);
- let name = load_module_from_file(wam, path_buf, true)?;
- self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
- }
- Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => {
- let name = if !wam.indices.modules.contains_key(&name) {
- load_library(wam, name, true)?
- } else {
- name
- };
-
- self.use_qualified_module(
- name,
- &mut wam.code_repo,
- flags,
- &exports,
- &mut wam.indices,
- indices
- )
- }
- Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
- let mut path_buf = self.listing_src.path();
- path_buf.push(filename.as_str());
-
- let name = load_module_from_file(wam, path_buf, true)?;
-
- self.use_qualified_module(
- name,
- &mut wam.code_repo,
- flags,
- &exports,
- &mut wam.indices,
- indices,
- )
+ code.extend(prepend_queue.into_iter());
+
+ // skeleton.clauses[0].opt_arg_index_key += clause_loc;
+ skeleton.clauses[0].clause_start = clause_loc;
+
+ clause_loc // + (outer_thread_choice_offset == 0 as usize)
}
}
}
+}
- fn setup_multifile_decl(
- &self,
- indicator: MultiFileIndicator,
- worker: &mut TopLevelBatchWorker,
- ) -> Result<(), SessionError> {
- match indicator {
- MultiFileIndicator::LocalScoped(name, arity) => {
- let term_dir = &worker.term_stream.wam.code_repo.term_dir;
- let key = (name, arity);
- let term_dirs = &mut worker.term_dirs;
+fn append_compiled_clause(
+ code: &mut Code,
+ mut clause_code: Code,
+ skeleton: &mut PredicateSkeleton,
+ retraction_info: &mut RetractionInfo,
+) -> Option<usize> {
+ let clause_loc = code.len();
+ let target_pos = skeleton.clauses.len() - 1;
+ let lower_bound = lower_bound_of_target_clause(skeleton, target_pos);
+
+ code.push(Line::Choice(ChoiceInstruction::TrustMe(0)));
+ skeleton.clauses[target_pos].clause_start = clause_loc;
+
+ let mut code_ptr_opt = None;
+
+ let lower_bound_arg_num = skeleton.clauses[lower_bound].opt_arg_index_key.arg_num();
+ let target_arg_num = skeleton.clauses[target_pos].opt_arg_index_key.arg_num();
+
+ let threaded_choice_instr_loc =
+ match skeleton.clauses[lower_bound].opt_arg_index_key.switch_on_term_loc() {
+ Some(index_loc) if lower_bound_arg_num == target_arg_num => {
+ code.extend(clause_code.drain(3 ..)); // skip the indexing code
+
+ // set skeleton[target_pos].opt_arg_index_key to
+ // index_loc. its original value is always 1.
+ skeleton.clauses[target_pos].opt_arg_index_key += index_loc - 1;
+
+ retraction_info.push_record(
+ RetractionRecord::AddedIndex(
+ skeleton.clauses[target_pos].opt_arg_index_key.clone(),
+ skeleton.clauses[target_pos].clause_start,
+ ),
+ );
+
+ let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
+
+ merge_clause_index(
+ target_indexing_line,
+ &mut skeleton.clauses[lower_bound ..],
+ clause_loc,
+ AppendOrPrepend::Append,
+ );
+
+ if lower_bound + 1 == target_pos {
+ set_switch_var_offset(code, index_loc, 1, retraction_info);
+ }
- insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs);
+ skeleton.clauses[target_pos - 1].clause_start
}
- MultiFileIndicator::ModuleScoped((module_name, key)) => {
- match worker.term_stream.wam.indices.modules.get(&module_name) {
- Some(ref module) => {
- let term_dir = &module.term_dir;
- let term_dirs = worker.intra_module_term_dirs
- .entry(module_name)
- .or_insert(TermDirQuantum::new());
-
- insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs);
+ _ => {
+ skeleton.clauses[target_pos].opt_arg_index_key += clause_loc;
+ code.extend(clause_code.drain(1 ..));
+
+ match skeleton.clauses[lower_bound].opt_arg_index_key.switch_on_term_loc() {
+ Some(_) => {
+ if lower_bound == 0 {
+ code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start - 2);
+ }
+
+ skeleton.clauses[lower_bound].clause_start - 2
}
- None => {
- let err = ExistenceError::ModuleSource(ModuleSource::File(
- module_name,
- ));
+ _ => {
+ if lower_bound == 0 {
+ code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start);
+ }
- return Err(SessionError::ExistenceError(err));
+ skeleton.clauses[lower_bound].clause_start
}
}
}
};
- Ok(())
+ thread_choice_instr_at_to(code, threaded_choice_instr_loc, clause_loc, retraction_info);
+
+ code_ptr_opt
+}
+
+#[inline]
+fn mergeable_indexed_subsequences(
+ lower_bound: usize,
+ target_pos: usize,
+ skeleton: &PredicateSkeleton,
+) -> bool {
+ let lower_bound_arg_num = skeleton.clauses[lower_bound].opt_arg_index_key.arg_num();
+
+ if target_pos + 1 < skeleton.clauses.len() {
+ let succ_arg_num = skeleton.clauses[target_pos + 1].opt_arg_index_key.arg_num();
+ let target_arg_num = skeleton.clauses[target_pos].opt_arg_index_key.arg_num();
+
+ return target_arg_num != succ_arg_num && lower_bound_arg_num == succ_arg_num;
}
- fn process_and_commit_decl(
+ false
+}
+
+impl<'a> LoadState<'a> {
+ fn compile(
&mut self,
- decl: Declaration,
- worker: &mut TopLevelBatchWorker,
- indices: &mut IndexStore,
- flags: MachineFlags,
- ) -> Result<(), SessionError> {
- let mut update_expansion_lengths = false;
-
- match &decl {
- &Declaration::Dynamic(ref name, arity) => {
- worker
- .dynamic_clause_map
- .entry((name.clone(), arity))
- .or_insert(vec![]);
-
- indices.code_dir
- .entry((name.clone(), arity))
- .or_insert(CodeIndex::dynamic_undefined(self.get_module_name()));
- }
- &Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker
- .term_stream
- .incr_expansion_lens(hook.user_scope(), 1, queue.len()),
- &Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() => {
- worker.term_stream.incr_expansion_lens(hook, 1, queue.len())
+ key: PredicateKey,
+ predicates: &Vec<PredicateClause>,
+ queue: &VecDeque<TopLevel>,
+ settings: CodeGenSettings,
+ ) -> Result<IndexPtr, SessionError> {
+ let code_index = self.get_or_insert_code_index(key.clone());
+ let code_len = self.wam.code_repo.code.len();
+ let mut code_ptr = code_len;
+
+ let mut cg = CodeGenerator::<DebrayAllocator>::new(
+ self.wam.machine_st.atom_tbl.clone(),
+ settings,
+ );
+
+ let mut code = cg.compile_predicate(predicates)?;
+
+ compile_appendix(
+ &mut code,
+ queue,
+ cg.jmp_by_locs,
+ settings.non_counted_bt,
+ self.wam.machine_st.atom_tbl.clone(),
+ )?;
+
+ if settings.is_extensible {
+ for clause_index_info in cg.skeleton.clauses.iter_mut() {
+ clause_index_info.clause_start += code_len;
+ clause_index_info.opt_arg_index_key += code_len;
}
- &Declaration::MultiFile(ref indicator) => {
- self.setup_multifile_decl(indicator.clone(), worker)?;
+
+ match &mut code[0] {
+ Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ code_ptr += 1;
+ }
+ _ => {
+ }
}
- &Declaration::UseModule(_) | &Declaration::UseQualifiedModule(..) => {
- update_expansion_lengths = true
+
+ match self.wam.indices.get_predicate_skeleton(
+ &self.compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ self.retraction_info.push_record(
+ RetractionRecord::SkeletonClauseTruncateBack(
+ self.compilation_target.clone(),
+ key.clone(),
+ skeleton.clauses.len(),
+ ),
+ );
+
+ skeleton.clauses.extend(cg.skeleton.clauses.into_iter());
+ }
+ None => {
+ self.add_extensible_predicate(key.clone(), cg.skeleton);
+ }
}
- _ => {}
- };
+ }
- let result = self.process_decl(
- decl,
- &mut worker.term_stream.wam,
- indices,
- flags,
- &mut worker.non_counted_bt_preds,
+ set_code_index(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ key,
+ &code_index,
+ IndexPtr::Index(code_ptr),
);
- if update_expansion_lengths {
- worker.term_stream.update_expansion_lens();
- }
+ self.wam.code_repo.code.extend(code.into_iter());
+ Ok(code_index.get())
+ }
- result
+ fn record_incremental_compile(&mut self, key: PredicateKey, append_or_prepend: AppendOrPrepend)
+ {
+ self.retraction_info.push_record(
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ match append_or_prepend {
+ AppendOrPrepend::Append => {
+ RetractionRecord::AppendedUserExtensiblePredicate(
+ key,
+ )
+ }
+ AppendOrPrepend::Prepend => {
+ RetractionRecord::PrependedUserExtensiblePredicate(
+ key,
+ )
+ }
+ }
+ }
+ CompilationTarget::Module(ref module_name) => {
+ match append_or_prepend {
+ AppendOrPrepend::Append => {
+ RetractionRecord::AppendedModuleExtensiblePredicate(
+ module_name.clone(), key,
+ )
+ }
+ AppendOrPrepend::Prepend => {
+ RetractionRecord::PrependedModuleExtensiblePredicate(
+ module_name.clone(), key,
+ )
+ }
+ }
+ }
+ }
+ );
}
- pub(crate)
- fn gather_items(
+ pub(super)
+ fn incremental_compile_clause(
&mut self,
- wam: &mut Machine,
- src: &mut ParsingStream<Stream>,
- indices: &mut IndexStore,
- ) -> Result<GatherResult, SessionError> {
- let flags = wam.machine_flags();
- let atom_tbl = indices.atom_tbl.clone();
- let mut worker = TopLevelBatchWorker::new(src, atom_tbl.clone(), flags, wam);
-
- let mut toplevel_results = vec![];
- let mut toplevel_indices = default_index_store!(atom_tbl.clone());
+ key: PredicateKey,
+ clause: PredicateClause,
+ queue: VecDeque<TopLevel>,
+ non_counted_bt: bool,
+ append_or_prepend: AppendOrPrepend,
+ ) -> Result<IndexPtr, SessionError> {
+ self.record_incremental_compile(key.clone(), append_or_prepend);
+
+ let skeleton =
+ match self.wam.indices.get_predicate_skeleton(
+ &self.compilation_target,
+ &key,
+ ) {
+ Some(skeleton) if !skeleton.clauses.is_empty() => {
+ skeleton
+ }
+ _ => {
+ // true because this predicate is extensible.
+ let settings = CodeGenSettings::new(true, non_counted_bt);
+ return self.compile(key, &vec![clause], &queue, settings);
+ }
+ };
- let mut top_level_term_dirs = TermDirQuantum::new();
+ let settings = CodeGenSettings::new(true, non_counted_bt);
+ let atom_tbl = self.wam.machine_st.atom_tbl.clone();
- while let Some(decl) = worker.consume(indices)? {
- if decl.is_module_decl() {
- toplevel_indices.copy_and_swap(indices);
- mem::swap(&mut worker.results, &mut toplevel_results);
- worker.in_module = true;
+ let StandaloneCompileResult { clause_code, mut standalone_skeleton } =
+ compile_standalone_clause(clause, queue, settings, atom_tbl)?;
- self.process_and_commit_decl(decl, &mut worker, indices, flags)?;
+ match append_or_prepend {
+ AppendOrPrepend::Append => {
+ skeleton.clauses.push_back(standalone_skeleton.clauses.pop_back().unwrap());
- if let Some(ref module) = &self.module {
- worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
+ self.retraction_info.push_record(
+ RetractionRecord::SkeletonClausePopBack(
+ self.compilation_target.clone(),
+ key.clone(),
+ ),
+ );
- top_level_term_dirs = mem::replace(
- &mut worker.term_dirs,
- TermDirQuantum::new(),
+ let result =
+ append_compiled_clause(
+ &mut self.wam.code_repo.code,
+ clause_code,
+ skeleton,
+ &mut self.retraction_info,
);
- }
- } else if decl.is_end_of_file() {
- break;
- } else {
- self.process_and_commit_decl(decl, &mut worker, indices, flags)?;
- }
- }
- let addition_results = worker.term_stream.rollback_expansion_code()?;
+ let code_index = self.get_or_insert_code_index(key.clone());
- let module_term_dirs = if self.module.is_some() {
- worker.term_dirs
- } else {
- top_level_term_dirs = worker.term_dirs;
- TermDirQuantum::new()
- };
+ if let Some(new_code_index) = result {
+ set_code_index(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ key,
+ &code_index,
+ IndexPtr::Index(new_code_index),
+ );
+ }
- Ok(GatherResult {
- worker_results: worker.results,
- dynamic_clause_map: worker.dynamic_clause_map,
- toplevel_results,
- toplevel_indices,
- addition_results,
- top_level_terms: worker.term_stream.top_level_terms(),
- top_level_term_dirs,
- module_term_dirs,
- in_situ_code_dir: worker.term_stream.wam.indices.take_in_situ_code_dir(),
- in_situ_code: worker.term_stream.wam.code_repo.take_in_situ_code(),
- in_situ_module_dir: worker.term_stream.wam.indices.take_in_situ_module_dir(),
- })
- }
+ Ok(code_index.get())
+ }
+ AppendOrPrepend::Prepend => {
+ skeleton.clauses.push_front(standalone_skeleton.clauses.pop_back().unwrap());
+
+ self.retraction_info.push_record(
+ RetractionRecord::SkeletonClausePopFront(
+ self.compilation_target.clone(),
+ key.clone(),
+ ),
+ );
- fn drop_expansions(&self, code_repo: &mut CodeRepo) {
- let (te_len, te_queue_len) = self.orig_term_expansion_lens;
- let (ge_len, ge_queue_len) = self.orig_goal_expansion_lens;
+ let threaded_choice_instr_loc =
+ prepend_compiled_clause(
+ &mut self.wam.code_repo.code,
+ self.compilation_target.clone(),
+ key.clone(),
+ clause_code,
+ skeleton,
+ &mut self.retraction_info,
+ );
- code_repo.truncate_terms((clause_name!("term_expansion"), 2), te_len, te_queue_len);
- code_repo.truncate_terms((clause_name!("goal_expansion"), 2), ge_len, ge_queue_len);
+ let code_index = self.get_or_insert_code_index(key.clone());
- discard_result!(code_repo.compile_hook(CompileTimeHook::UserGoalExpansion));
- discard_result!(code_repo.compile_hook(CompileTimeHook::UserTermExpansion));
- }
+ set_code_index(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ key,
+ &code_index,
+ IndexPtr::Index(threaded_choice_instr_loc),
+ );
- fn print_error(&self, e: &SessionError) {
- if let &SessionError::ParserError(ref e) = e {
- if let Some((line_num, _col_num)) = e.line_and_col_num() {
- println!("{}:{}: {}", self.listing_src.name(), line_num, e.as_str());
+ Ok(IndexPtr::Index(threaded_choice_instr_loc))
}
}
}
-}
-fn compile_work_impl(
- compiler: &mut ListingCompiler,
- wam: &mut Machine,
- mut indices: IndexStore,
- mut results: GatherResult,
-) -> Result<(), SessionError> {
- if let Some(ref mut module) = &mut compiler.module {
- // compile the module-level goal and term expansions and store
- // their locations to the module's code_dir.
- let mut decls = module.take_local_expansions();
+ pub(super)
+ fn retract_clause(&mut self, key: PredicateKey, target_pos: usize) -> usize {
+ let code_index = self.get_or_insert_code_index(key.clone());
+
+ let skeleton =
+ match self.wam.indices.get_predicate_skeleton(
+ &self.compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton
+ }
+ None => {
+ unreachable!();
+ }
+ };
+
+ let code = &mut self.wam.code_repo.code;
+ let lower_bound = lower_bound_of_target_clause(skeleton, target_pos);
+ let lower_bound_is_unindexed = !skeleton.clauses[lower_bound].opt_arg_index_key.is_some();
+
+ if target_pos == 0 || (lower_bound + 1 == target_pos && lower_bound_is_unindexed) {
+ // the clause preceding target_pos, if there is one, is of key type
+ // OptArgIndexKey::None.
+ match skeleton.clauses[target_pos].opt_arg_index_key.switch_on_term_loc() {
+ Some(index_loc) => {
+ let inner_clause_start = find_inner_choice_instr(
+ code,
+ skeleton.clauses[target_pos].clause_start,
+ index_loc,
+ );
- if !decls.is_empty() {
- append_trivial_goal(&clause_name!("term_expansion"), &mut decls[0].0);
- append_trivial_goal(&clause_name!("goal_expansion"), &mut decls[1].0);
+ remove_index_from_subsequence(
+ code,
+ &skeleton.clauses[target_pos].opt_arg_index_key,
+ inner_clause_start,
+ &mut self.retraction_info,
+ );
- results.worker_results.extend(decls.into_iter());
+ match derelictize_try_me_else(
+ code,
+ inner_clause_start,
+ &mut self.retraction_info,
+ ) {
+ Some(offset) => {
+ let instr_loc = find_inner_choice_instr(
+ code,
+ inner_clause_start + offset,
+ index_loc,
+ );
+
+ let clause_loc = blunt_leading_choice_instr(
+ code,
+ instr_loc,
+ &mut self.retraction_info,
+ );
+
+ set_switch_var_offset(
+ code,
+ index_loc,
+ clause_loc - index_loc,
+ &mut self.retraction_info,
+ );
+
+ self.retraction_info.push_record(
+ RetractionRecord::SkeletonClauseStartReplaced(
+ self.compilation_target.clone(),
+ key.clone(),
+ target_pos + 1,
+ skeleton.clauses[target_pos + 1].clause_start,
+ ),
+ );
+
+ skeleton.clauses[target_pos + 1].clause_start =
+ skeleton.clauses[target_pos].clause_start;
+
+ return delete_from_dynamic_skeleton(
+ self.compilation_target.clone(),
+ key,
+ skeleton,
+ target_pos,
+ &mut self.retraction_info,
+ );
+ }
+ None => {
+ let index_ptr_opt =
+ if target_pos > 0 {
+ let preceding_choice_instr_loc =
+ skeleton.clauses[target_pos - 1].clause_start;
+
+ remove_non_leading_clause(
+ code,
+ preceding_choice_instr_loc,
+ skeleton.clauses[target_pos].clause_start - 2,
+ &mut self.retraction_info,
+ )
+ } else {
+ remove_leading_unindexed_clause(
+ code,
+ skeleton.clauses[target_pos].clause_start - 2,
+ &mut self.retraction_info,
+ )
+ };
+
+ return finalize_retract(
+ key,
+ self.compilation_target.clone(),
+ skeleton,
+ code_index,
+ target_pos,
+ index_ptr_opt,
+ &mut self.retraction_info,
+ );
+ }
+ }
+ }
+ None => {
+ }
+ }
}
- }
-
- let top_level_term_dir = results.top_level_term_dirs.consolidate();
- let module_term_dir = results.module_term_dirs.consolidate();
-
- let mut code = results.in_situ_code;
-
- let in_situ_code_dir = results.in_situ_code_dir;
- let in_situ_module_dir = results.in_situ_module_dir;
- compiler.adapt_in_situ_code(
- results.worker_results,
- wam,
- &mut indices.code_dir,
- &mut indices.module_dir,
- &mut code,
- &in_situ_code_dir,
- &in_situ_module_dir,
- )?;
+ let index_ptr_opt =
+ match skeleton.clauses[lower_bound].opt_arg_index_key.switch_on_term_loc() {
+ Some(target_indexing_loc)
+ if mergeable_indexed_subsequences(lower_bound, target_pos, skeleton) =>
+ {
+ let result;
+
+ match skeleton.clauses[target_pos + 1].opt_arg_index_key.switch_on_term_loc() {
+ Some(later_indexing_loc) if later_indexing_loc < target_indexing_loc => {
+ let target_indexing_line = mem::replace(
+ &mut code[target_indexing_loc],
+ Line::Control(ControlInstruction::RevJmpBy(
+ target_indexing_loc - later_indexing_loc
+ )),
+ );
+
+ match target_indexing_line {
+ Line::IndexingCode(indexing_code) => {
+ self.retraction_info.push_record(
+ RetractionRecord::ReplacedIndexingLine(
+ target_indexing_loc,
+ indexing_code,
+ ),
+ );
+ }
+ _ => {
+ }
+ }
+
+ set_switch_var_offset(
+ code,
+ later_indexing_loc,
+ target_indexing_loc - later_indexing_loc + 1,
+ &mut self.retraction_info,
+ );
+
+ result = merge_indexed_subsequences(
+ code,
+ skeleton,
+ lower_bound,
+ target_pos + 1,
+ &mut self.retraction_info,
+ );
+
+ merge_indices(
+ code,
+ later_indexing_loc,
+ 0 .. target_pos - lower_bound,
+ &mut skeleton.clauses[lower_bound ..],
+ &mut self.retraction_info,
+ );
+ }
+ _ => {
+ set_switch_var_offset_to_choice_instr_(
+ code,
+ target_indexing_loc,
+ 1,
+ &mut self.retraction_info,
+ );
+
+ result = merge_indexed_subsequences(
+ code,
+ skeleton,
+ lower_bound,
+ target_pos + 1,
+ &mut self.retraction_info,
+ );
+
+ merge_indices(
+ code,
+ target_indexing_loc,
+ target_pos + 1 - lower_bound .. skeleton.clauses.len() - lower_bound,
+ &mut skeleton.clauses[lower_bound ..],
+ &mut self.retraction_info,
+ );
+ }
+ };
- compiler.adapt_in_situ_code(
- results.toplevel_results,
- wam,
- &mut results.toplevel_indices.code_dir,
- &mut indices.module_dir,
- &mut code,
- &in_situ_code_dir,
- &in_situ_module_dir,
- )?;
+ result
+ }
+ _ => {
+ if target_pos > 0 {
+ remove_index_from_subsequence(
+ code,
+ &skeleton.clauses[target_pos].opt_arg_index_key,
+ skeleton.clauses[target_pos].clause_start,
+ &mut self.retraction_info,
+ );
- if let Some(ref mut module) = &mut compiler.module {
- if !module.is_impromptu_module {
- module.user_term_expansions = results.addition_results.take_term_expansions();
- module.user_goal_expansions = results.addition_results.take_goal_expansions();
- }
+ match skeleton.clauses[target_pos].opt_arg_index_key.switch_on_term_loc() {
+ Some(index_loc) => {
+ let preceding_choice_instr_loc = find_inner_choice_instr(
+ code,
+ skeleton.clauses[target_pos - 1].clause_start,
+ index_loc,
+ );
+
+ remove_non_leading_clause(
+ code,
+ preceding_choice_instr_loc,
+ skeleton.clauses[target_pos].clause_start,
+ &mut self.retraction_info,
+ );
+
+ match &mut code[preceding_choice_instr_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ set_switch_var_offset(
+ code,
+ index_loc,
+ preceding_choice_instr_loc + 1 - index_loc,
+ &mut self.retraction_info,
+ );
+ }
+ _ => {
+ }
+ }
+
+ None
+ }
+ None => {
+ let preceding_choice_instr_loc =
+ if skeleton.clauses[lower_bound].opt_arg_index_key.is_some() {
+ skeleton.clauses[lower_bound].clause_start - 2
+ } else {
+ skeleton.clauses[lower_bound].clause_start
+ };
+
+ remove_non_leading_clause(
+ code,
+ preceding_choice_instr_loc,
+ skeleton.clauses[target_pos].clause_start,
+ &mut self.retraction_info,
+ )
+ }
+ }
+ } else {
+ remove_leading_unindexed_clause(
+ code,
+ skeleton.clauses[target_pos].clause_start,
+ &mut self.retraction_info,
+ )
+ }
+ }
+ };
+
+ finalize_retract(
+ key,
+ self.compilation_target.clone(),
+ skeleton,
+ code_index,
+ target_pos,
+ index_ptr_opt,
+ &mut self.retraction_info,
+ )
}
+}
- wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion)?;
- wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion)?;
-
- if let Some(mut module) = compiler.module.take() {
- if module.is_impromptu_module {
- module.module_decl.exports = indices.code_dir.keys().cloned()
- .filter(|(name, _)| name.owning_module().as_str() != "builtins")
- .map(ModuleExport::PredicateKey)
- .collect();
-
- module.module_decl.exports.extend(
- indices.op_dir.iter()
- .map(|((name, _), OpDirValue (shared_op_desc, _))|
- ModuleExport::OpDecl(OpDecl(
- shared_op_desc.prec(),
- shared_op_desc.assoc(),
- name.clone(),
- ))
+impl<'a, TS: TermStream> Loader<'a, TS> {
+ pub(super)
+ fn compile_clause_clauses<ClauseIter: Iterator<Item=(Term, Term)>>(
+ &mut self,
+ key: PredicateKey,
+ clause_clauses: ClauseIter,
+ append_or_prepend: AppendOrPrepend,
+ ) -> Result<(), SessionError> {
+ let clause_predicates =
+ clause_clauses.map(|(head, body)| {
+ PredicateClause::Fact(
+ Term::Clause(
+ Cell::default(),
+ clause_name!("$clause"),
+ vec![Box::new(head), Box::new(body)],
+ None,
)
- );
- }
+ )
+ });
- let mut clause_code_generator =
- ClauseCodeGenerator::new(code.len(), module.module_decl.name.clone());
+ let compilation_target = mem::replace(
+ &mut self.load_state.compilation_target,
+ CompilationTarget::Module(clause_name!("builtins")),
+ );
- wam.check_toplevel_code(&results.toplevel_indices)?;
- clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?;
+ let mut clause_clause_locs = sdeq![];
- if let Some(ref module) = wam.indices.modules.swap_remove(&module.module_decl.name) {
- wam.indices.remove_module(clause_name!("user"), module);
- }
+ for clause_predicate in clause_predicates {
+ clause_clause_locs.push_back(self.load_state.wam.code_repo.code.len());
- if module.is_impromptu_module {
- add_module(wam, module, indices, module_term_dir);
+ let result = self.load_state.incremental_compile_clause(
+ (clause_name!("$clause"), 2),
+ clause_predicate,
+ VecDeque::new(),
+ false, // non_counted_bt is false.
+ append_or_prepend,
+ );
- let module = wam.indices.take_module(compiler.listing_src.name()).unwrap();
+ if let Err(e) = result {
+ self.load_state.compilation_target = compilation_target;
+ return Err(e);
+ }
+ }
- wam.indices.use_module(&mut wam.code_repo, wam.machine_st.flags, &module)?;
- wam.indices.insert_module(module);
- } else {
- add_module(wam, module, indices, module_term_dir);
+ match self.load_state.wam.indices.get_predicate_skeleton(
+ &self.load_state.compilation_target,
+ &(clause_name!("$clause"), 2),
+ ) {
+ Some(skeleton) if append_or_prepend.is_append() => {
+ skeleton.clause_clause_locs.extend_from_slice(&clause_clause_locs[0 ..]);
+ }
+ Some(skeleton) => {
+ for loc in clause_clause_locs.iter() {
+ skeleton.clause_clause_locs.push_front(*loc);
+ }
+ }
+ None => {
+ unreachable!();
+ }
}
- add_toplevel(wam, results.toplevel_indices, top_level_term_dir);
- wam.code_repo.code.extend(code.into_iter());
+ match self.load_state.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) if append_or_prepend.is_append() => {
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::SkeletonClauseClausesTruncateBack(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton.clause_clause_locs.len(),
+ ),
+ );
- clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
- } else {
- add_non_module_code(
- wam,
- results.dynamic_clause_map,
- code,
- indices,
- top_level_term_dir,
- )?;
- }
+ skeleton.clause_clause_locs.append(
+ &mut clause_clause_locs
+ );
+ }
+ Some(skeleton) => {
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::SkeletonClauseClausesTruncateFront(
+ compilation_target.clone(),
+ key.clone(),
+ skeleton.clause_clause_locs.len(),
+ ),
+ );
- let init_goal_code = compiler.generate_init_goal_code()?;
+ for loc in clause_clause_locs.iter() {
+ skeleton.clause_clause_locs.push_front(*loc);
+ }
- if init_goal_code.len() > 0 {
- if !wam.run_init_code(init_goal_code) {
- println!("Warning: initialization goal for {} failed",
- compiler.listing_src.name());
+ self.load_state.increment_clause_assert_margin(
+ clause_clause_locs.len()
+ );
+ }
+ None => {
+ unreachable!();
+ }
}
- }
- if !compiler.suppress_warnings {
- issue_singleton_warnings(
- compiler.listing_src.name(),
- results.top_level_terms,
- );
+ self.load_state.compilation_target = compilation_target;
+ Ok(())
}
- Ok(())
-}
-
-fn compile_work(
- compiler: &mut ListingCompiler,
- wam: &mut Machine,
- src: Stream,
- mut indices: IndexStore,
-) -> EvalSession {
- let mut stream = try_eval_session!(parsing_stream(src));
- let src = &mut stream;
- let results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
-
- try_eval_session!(compile_work_impl(compiler, wam, indices, results));
-
- EvalSession::EntrySuccess
-}
-
-/* This is a truncated version of compile_user_module, used for
-compiling code composing special forms, ie. the code that calls
-M:verify_attributes on attributed variables. */
-pub fn compile_special_form(
- wam: &mut Machine,
- src: Stream,
- listing_src: ListingSource,
-) -> Result<usize, SessionError> {
- let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
- setup_indices(wam, clause_name!("builtins"), &mut indices)?;
-
- let mut src = parsing_stream(src)?;
- let mut compiler = ListingCompiler::new(&wam.code_repo, true, listing_src);
- let mut results = compiler.gather_items(wam, &mut src, &mut indices)?;
-
- compiler.adapt_in_situ_code(
- results.worker_results,
- wam,
- &mut indices.code_dir,
- &mut indices.module_dir,
- &mut results.in_situ_code,
- &results.in_situ_code_dir,
- &results.in_situ_module_dir,
- )?;
-
- let p = wam.code_repo.code.len();
- let top_level_term_dir = results.top_level_term_dirs.consolidate();
-
- add_toplevel(wam, indices, top_level_term_dir);
+ pub(super)
+ fn compile_and_submit(&mut self) -> Result<(), SessionError> {
+ let queue = self.preprocessor.parse_queue(&mut self.load_state)?;
- wam.code_repo.code.extend(results.in_situ_code.into_iter());
+ let key = self.predicates
+ .first()
+ .and_then(|cl| {
+ let arity = cl.arity();
+ cl.name().map(|name| (name, arity))
+ })
+ .ok_or(SessionError::NamelessEntry)?;
- Ok(p)
-}
+ let (is_dynamic, is_extensible) = self.load_state.wam.indices
+ .get_predicate_skeleton(&self.load_state.compilation_target, &key)
+ .map(|skeleton| (skeleton.is_dynamic, true))
+ .unwrap_or((false, false));
-#[inline]
-pub fn compile_listing(
- wam: &mut Machine,
- src: Stream,
- indices: IndexStore,
- suppress_warnings: bool,
- listing_src: ListingSource,
-) -> EvalSession {
- let mut compiler = ListingCompiler::new(&wam.code_repo, suppress_warnings, listing_src);
+ let non_counted_bt = self.non_counted_bt_preds.contains(&key);
+ let settings = CodeGenSettings::new(is_extensible, non_counted_bt);
- match compile_work(&mut compiler, wam, src, indices) {
- EvalSession::Error(e) => {
- compiler.drop_expansions(&mut wam.code_repo);
- compiler.print_error(&e);
+ self.load_state.compile(key.clone(), &self.predicates, &queue, settings)?;
- EvalSession::Error(e)
+ if is_dynamic {
+ let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter();
+ self.compile_clause_clauses(key, iter, AppendOrPrepend::Append)?;
}
- result => result,
- }
-}
-
-pub(super) fn setup_indices(
- wam: &mut Machine,
- module: ClauseName,
- indices: &mut IndexStore,
-) -> Result<(), SessionError> {
- if let Some(module) = wam.indices.take_module(module.clone()) {
- let flags = wam.machine_flags();
- let result = indices.use_module(&mut wam.code_repo, flags, &module);
-
- wam.indices.insert_module(module);
- result
- } else {
- let err = ExistenceError::ModuleSource(ModuleSource::Library(
- module
- ));
- Err(SessionError::ExistenceError(err))
+ Ok(self.predicates.clear())
}
}
-
-pub fn compile_user_module(
- wam: &mut Machine,
- src: Stream,
- suppress_warnings: bool,
- listing_src: ListingSource,
-) -> EvalSession {
- let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
- try_eval_session!(setup_indices(wam, clause_name!("builtins"), &mut indices));
- compile_listing(wam, src, indices, suppress_warnings, listing_src)
-}
+++ /dev/null
-use crate::prolog_parser::ast::*;
-
-use crate::heap_print::*;
-use crate::machine::*;
-use crate::machine::compile::*;
-use crate::machine::machine_errors::*;
-use crate::machine::streams::*;
-
-use std::convert::TryFrom;
-
-impl Machine {
- pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
- match name {
- &ClauseName::User(ref rc) => rc.table.clone(),
- _ => self.indices.atom_tbl(),
- }
- }
-
- fn compile_into_machine(
- &mut self,
- src: Stream,
- name: ClauseName,
- arity: usize,
- ) -> EvalSession {
- match name.owning_module().as_str() {
- "user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() {
- Some(idx) => {
- let module = idx.0.borrow().1.clone();
-
- match module.as_str() {
- "user" => compile_user_module(self, src, true, ListingSource::User),
- _ => compile_into_module(self, module, src, name)
- }
- }
- None => compile_user_module(self, src, true, ListingSource::User),
- },
- _ => compile_into_module(self, name.owning_module(), src, name),
- }
- }
-
- fn get_predicate_key(&self, name: RegType, arity: RegType) -> PredicateKey {
- let name = self.machine_st[name].clone();
- let arity = self.machine_st[arity].clone();
-
- let name = match self.machine_st.store(self.machine_st.deref(name)) {
- Addr::Con(h) =>
- if let HeapCellValue::Atom(ref name, _) = &self.machine_st.heap[h] {
- name.clone()
- } else {
- unreachable!()
- },
- _ => unreachable!(),
- };
-
- let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
- 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!()
- }
- }
- }
- Addr::Fixnum(arity) => {
- usize::try_from(arity).unwrap()
- }
- Addr::Usize(n) => {
- n
- }
- _ => {
- unreachable!()
- }
- };
-
- (name, arity)
- }
-
- fn print_new_dynamic_clause(
- &self,
- addrs: VecDeque<Addr>,
- name: ClauseName,
- arity: usize,
- ) -> String {
- let mut output = PrinterOutputter::new();
- output.append(format!(":- dynamic({}/{}). ", name.as_str(), arity).as_str());
-
- for addr in addrs {
- let mut printer = HCPrinter::new(&self.machine_st, &self.indices.op_dir, output);
- printer.quoted = true;
-
- output = printer.print(addr);
- output.append(". ");
- }
-
- output.result()
- }
-
- fn make_undefined(&mut self, name: ClauseName, arity: usize) {
- let module_name = name.owning_module();
-
- match self.indices.modules.get(&module_name) {
- Some(ref module) => {
- if let Some(idx) = module.code_dir.get(&(name.clone(), arity)) {
- set_code_index!(idx, IndexPtr::DynamicUndefined, module_name);
- }
- }
- None => {
- }
- }
-
- if let Some(idx) = self.indices.code_dir.get(&(name, arity)) {
- set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
- }
- }
-
- fn make_undefined_in_module(&mut self, module_name: ClauseName, name: ClauseName, arity: usize) {
- if let Some(idx) = self.indices.code_dir.get(&(name, arity)) {
- if idx.module_name() == module_name {
- set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
- }
- }
- }
-
- fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
- let (name, arity) = self.get_predicate_key(name, arity);
-
- self.make_undefined(name.clone(), arity);
-
- self.indices.remove_code_index((name.clone(), arity));
- self.indices.remove_clause_subsection(name.owning_module(), name, arity);
- }
-
- fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) {
- let (name, arity) = self.get_predicate_key(name, arity);
- let module_addr = self.machine_st[module].clone();
-
- let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
- 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) => {
- module.code_dir.remove(&(name.clone(), arity));
- module.module_decl.name.clone()
- }
- _ => {
- self.machine_st.fail = true;
- return;
- }
- }
- } else {
- unreachable!()
- },
- _ => unreachable!(),
- };
-
- self.make_undefined_in_module(module_name.clone(), name.clone(), arity);
-
- self.indices.remove_code_index((name.clone(), arity));
- self.indices.remove_clause_subsection(module_name, name, arity);
- }
-
- fn handle_eval_result_from_dynamic_compile(
- &mut self,
- pred_str: String,
- name: ClauseName,
- arity: usize,
- src: ClauseName,
- ) {
- let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
-
- let result = self.compile_into_machine(
- Stream::from(pred_str),
- name,
- arity,
- );
-
- self.machine_st = machine_st;
-
- if let EvalSession::Error(err) = result {
- let h = self.machine_st.heap.h();
- let stub = MachineError::functor_stub(src, 1);
- let err = MachineError::session_error(h, err);
- let err = self.machine_st.error_form(err, stub);
-
- self.machine_st.throw_exception(err);
- }
- }
-
- fn recompile_dynamic_predicate_impl(
- &mut self,
- place: DynamicAssertPlace,
- name: ClauseName,
- arity: usize,
- ) {
- let stub = MachineError::functor_stub(place.predicate_name(), 1);
- let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
- Ok(addrs) => {
- let mut addrs = VecDeque::from(addrs);
- let added_clause = self.machine_st[temp_v!(1)].clone();
-
- place.push_to_queue(&mut addrs, added_clause);
- self.print_new_dynamic_clause(addrs, name.clone(), arity)
- }
- Err(err) => {
- return self.machine_st.throw_exception(err);
- }
- };
-
- 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 {
- let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
- 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(),
- None => {
- self.machine_st.fail = true;
- return false;
- }
- }
- } else {
- self.machine_st.fail = true;
- return false;
- },
- _ => unreachable!(),
- };
-
- if let &mut ClauseName::User(ref mut rc) = name {
- rc.table = atom_tbl;
- }
-
- true
- }
-
- fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace) {
- let (mut name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
- let module_addr = self.machine_st[temp_v!(5)].clone();
-
- if self.set_module_atom_tbl(module_addr, &mut name) {
- self.recompile_dynamic_predicate_impl(place, name, arity);
- }
- }
-
- fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace) {
- let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
- self.recompile_dynamic_predicate_impl(place, name, arity);
- }
-
- fn retract_from_dynamic_predicate_in_module(&mut self) {
- let index = self.machine_st[temp_v!(3)].clone();
- let index = match self.machine_st.store(self.machine_st.deref(index)) {
- 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!()
- }
- }
- Addr::Fixnum(arity) => {
- usize::try_from(arity).unwrap()
- }
- _ => {
- unreachable!()
- }
- };
-
- let (mut name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
- let module_addr = self.machine_st[temp_v!(5)].clone();
-
- if self.set_module_atom_tbl(module_addr, &mut name) {
- let stub = MachineError::functor_stub(clause_name!("retract"), 1);
- let pred_str = match self.machine_st.try_from_list(temp_v!(4), stub) {
- Ok(addrs) => {
- let mut addrs = VecDeque::from(addrs);
- addrs.remove(index);
-
- if addrs.is_empty() {
- self.make_undefined(name.clone(), arity);
- }
-
- self.print_new_dynamic_clause(addrs, name.clone(), arity)
- }
- Err(err) => {
- return self.machine_st.throw_exception(err);
- }
- };
-
- self.handle_eval_result_from_dynamic_compile(
- pred_str,
- name,
- arity,
- clause_name!("retract"),
- );
- }
- }
-
- fn retract_from_dynamic_predicate(&mut self) {
- let index = self.machine_st[temp_v!(3)].clone();
- let index = match self.machine_st.store(self.machine_st.deref(index)) {
- 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!()
- }
- }
- }
- Addr::Usize(n) => {
- n
- }
- Addr::Fixnum(n) => {
- usize::try_from(n).unwrap()
- }
- _ => {
- unreachable!()
- }
- };
-
- let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
-
- let stub = MachineError::functor_stub(clause_name!("retract"), 1);
- let pred_str = match self.machine_st.try_from_list(temp_v!(4), stub) {
- Ok(addrs) => {
- let mut addrs = VecDeque::from(addrs);
- addrs.remove(index);
-
- if addrs.is_empty() {
- self.make_undefined(name.clone(), arity);
- }
-
- self.print_new_dynamic_clause(addrs, name.clone(), arity)
- }
- Err(err) => {
- return self.machine_st.throw_exception(err);
- }
- };
-
- self.handle_eval_result_from_dynamic_compile(
- pred_str,
- name,
- arity,
- clause_name!("retract"),
- );
- }
-
- pub(super) fn dynamic_transaction(
- &mut self,
- trans_type: DynamicTransactionType,
- p: LocalCodePtr,
- ) {
- match trans_type {
- DynamicTransactionType::Abolish => {
- self.abolish_dynamic_clause(temp_v!(1), temp_v!(2))
- }
- DynamicTransactionType::Assert(place) => {
- self.recompile_dynamic_predicate(place)
- }
- DynamicTransactionType::ModuleAbolish => {
- self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3))
- }
- DynamicTransactionType::ModuleAssert(place) => {
- self.recompile_dynamic_predicate_in_module(place)
- }
- DynamicTransactionType::ModuleRetract => {
- self.retract_from_dynamic_predicate_in_module()
- }
- DynamicTransactionType::Retract => {
- self.retract_from_dynamic_predicate()
- }
- }
-
- self.machine_st.p = CodePtr::Local(p);
- }
-}
&HeapCellValue::Integer(ref n) => {
HeapCellValue::Integer(n.clone())
}
+ &HeapCellValue::LoadStatePayload(_) => {
+ HeapCellValue::Addr(Addr::LoadStatePayload(h))
+ }
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
}
val @ HeapCellValue::Rational(_) => {
Addr::Con(self.push(val))
}
+ val @ HeapCellValue::LoadStatePayload(_) => {
+ Addr::LoadStatePayload(self.push(val))
+ }
val @ HeapCellValue::NamedStr(..) => {
Addr::Str(self.push(val))
}
}
}
- #[inline]
- pub(crate)
- fn take(&mut self) -> Self {
- HeapTemplate {
- buf: self.buf.take(),
- _marker: PhantomData,
- }
- }
-
#[inline]
pub(crate)
fn truncate(&mut self, h: usize) {
("dir_entry", 1) => {
extract_integer(s+1).map(LocalCodePtr::DirEntry)
}
- ("in_situ_dir_entry", 1) => {
- extract_integer(s+1).map(LocalCodePtr::InSituDirEntry)
- }
+ /*
("top_level", 2) => {
if let Some(chunk_num) = extract_integer(s+1) {
if let Some(p) = extract_integer(s+2) {
None
}
- ("user_goal_expansion", 1) => {
- extract_integer(s+1).map(LocalCodePtr::UserGoalExpansion)
- }
- ("user_term_expansion", 1) => {
- extract_integer(s+1).map(LocalCodePtr::UserTermExpansion)
+ */
+ _ => {
+ None
}
- _ => None
}
}
_ => unreachable!()
}
#[inline]
- pub
- fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
+ pub fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
match addr {
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => {
RefOrOwned::Borrowed(&self[h])
--- /dev/null
+use crate::machine::*;
+use crate::machine::machine_indices::*;
+use crate::machine::term_stream::*;
+
+use indexmap::IndexSet;
+
+use crate::ref_thread_local::RefThreadLocal;
+
+type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>;
+
+/*
+ * We will want to borrow these fields from Loader separately, without
+ * restricting access to other fields by borrowing them mutably.
+ */
+pub(super) struct LoadState<'a> {
+ pub(super) compilation_target: CompilationTarget,
+ pub(super) module_op_exports: ModuleOpExports,
+ pub(super) retraction_info: RetractionInfo,
+ pub(super) wam: &'a mut Machine,
+}
+
+pub(super)
+fn set_code_index(
+ retraction_info: &mut RetractionInfo,
+ compilation_target: &CompilationTarget,
+ key: PredicateKey,
+ code_index: &CodeIndex,
+ code_ptr: IndexPtr,
+) {
+ let record =
+ match compilation_target {
+ CompilationTarget::User => {
+ if IndexPtr::Undefined == code_index.get() {
+ code_index.set(code_ptr);
+ RetractionRecord::AddedUserPredicate(key)
+ } else {
+ // TODO: emit warning about overwriting previous record
+ let replaced = code_index.replace(code_ptr);
+ RetractionRecord::ReplacedUserPredicate(key, replaced)
+ }
+ }
+ CompilationTarget::Module(ref module_name) => {
+ if IndexPtr::Undefined == code_index.get() {
+ code_index.set(code_ptr);
+ RetractionRecord::AddedModulePredicate(module_name.clone(), key)
+ } else {
+ // TODO: emit warning about overwriting previous record
+ let replaced = code_index.replace(code_ptr);
+ RetractionRecord::ReplacedModulePredicate(module_name.clone(), key, replaced)
+ }
+ }
+ };
+
+ retraction_info.push_record(record);
+}
+
+fn add_op_decl_as_module_export(
+ module_op_dir: &mut OpDir,
+ compilation_target: &CompilationTarget,
+ retraction_info: &mut RetractionInfo,
+ wam_op_dir: &mut OpDir,
+ module_op_exports: &mut ModuleOpExports,
+ op_decl: &OpDecl,
+) {
+ /*
+ insert the operator at top-level so it can
+ inform the parser. it will be retracted
+ from the user-level op_dir when the load
+ succeeds.
+ */
+
+ match op_decl.insert_into_op_dir(wam_op_dir) {
+ Some((prec, spec)) => {
+ retraction_info.push_record(
+ RetractionRecord::ReplacedUserOp(op_decl.clone(), prec, spec)
+ );
+
+ module_op_exports.push((op_decl.clone(), Some((prec, spec))));
+ }
+ None => {
+ retraction_info.push_record(
+ RetractionRecord::AddedUserOp(op_decl.clone())
+ );
+
+ module_op_exports.push((op_decl.clone(), None));
+ }
+ }
+
+ add_op_decl(retraction_info, compilation_target, module_op_dir, op_decl);
+}
+
+pub(super)
+fn add_op_decl(
+ retraction_info: &mut RetractionInfo,
+ compilation_target: &CompilationTarget,
+ op_dir: &mut OpDir,
+ op_decl: &OpDecl,
+) {
+ match op_decl.insert_into_op_dir(op_dir) {
+ Some((prec, spec)) => {
+ match &compilation_target {
+ CompilationTarget::User => {
+ retraction_info.push_record(
+ RetractionRecord::ReplacedUserOp(op_decl.clone(), prec, spec),
+ );
+ }
+ CompilationTarget::Module(ref module_name) => {
+ retraction_info.push_record(
+ RetractionRecord::ReplacedModuleOp(
+ module_name.clone(), op_decl.clone(), prec, spec,
+ ),
+ );
+ }
+ }
+ }
+ None => {
+ match &compilation_target {
+ CompilationTarget::User => {
+ retraction_info.push_record(
+ RetractionRecord::AddedUserOp(op_decl.clone()),
+ );
+ }
+ CompilationTarget::Module(ref module_name) => {
+ retraction_info.push_record(
+ RetractionRecord::AddedModuleOp(module_name.clone(), op_decl.clone()),
+ );
+ }
+ }
+ }
+ }
+}
+
+pub(super)
+fn import_module_exports(
+ retraction_info: &mut RetractionInfo,
+ compilation_target: &CompilationTarget,
+ imported_module: &Module,
+ code_dir: &mut CodeDir,
+ op_dir: &mut OpDir,
+ meta_predicates: &mut MetaPredicateDir,
+) {
+ for export in imported_module.module_decl.exports.iter() {
+ match export {
+ ModuleExport::PredicateKey((ref name, arity)) => {
+ let key = (name.clone(), *arity);
+
+ if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
+ meta_predicates.insert(key.clone(), meta_specs.clone());
+ }
+
+ if let Some(src_code_index) = imported_module.code_dir.get(&key) {
+ let target_code_index = code_dir
+ .entry(key.clone())
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone();
+
+ set_code_index(
+ retraction_info,
+ compilation_target,
+ key,
+ &target_code_index,
+ src_code_index.get(),
+ );
+ } else {
+ unreachable!()
+ }
+ }
+ ModuleExport::OpDecl(ref op_decl) => {
+ add_op_decl(
+ retraction_info,
+ compilation_target,
+ op_dir,
+ op_decl,
+ );
+ }
+ }
+ }
+}
+
+fn import_module_exports_into_module(
+ retraction_info: &mut RetractionInfo,
+ compilation_target: &CompilationTarget,
+ imported_module: &Module,
+ code_dir: &mut CodeDir,
+ op_dir: &mut OpDir,
+ meta_predicates: &mut MetaPredicateDir,
+ wam_op_dir: &mut OpDir,
+ module_op_exports: &mut ModuleOpExports
+) {
+ for export in imported_module.module_decl.exports.iter() {
+ match export {
+ ModuleExport::PredicateKey((ref name, arity)) => {
+ let key = (name.clone(), *arity);
+
+ if let Some(meta_specs) = imported_module.meta_predicates.get(&key) {
+ meta_predicates.insert(key.clone(), meta_specs.clone());
+ }
+
+ if let Some(src_code_index) = imported_module.code_dir.get(&key) {
+ let target_code_index = code_dir
+ .entry(key.clone())
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone();
+
+ set_code_index(
+ retraction_info,
+ compilation_target,
+ key,
+ &target_code_index,
+ src_code_index.get(),
+ );
+ } else {
+ unreachable!()
+ }
+ }
+ ModuleExport::OpDecl(ref op_decl) => {
+ add_op_decl_as_module_export(
+ op_dir,
+ compilation_target,
+ retraction_info,
+ wam_op_dir,
+ module_op_exports,
+ op_decl,
+ );
+ }
+ }
+ }
+}
+
+
+fn import_qualified_module_exports(
+ retraction_info: &mut RetractionInfo,
+ compilation_target: &CompilationTarget,
+ imported_module: &Module,
+ exports: &IndexSet<ModuleExport>,
+ code_dir: &mut CodeDir,
+ op_dir: &mut OpDir,
+) {
+ for export in imported_module.module_decl.exports.iter() {
+ if !exports.contains(export) {
+ continue;
+ }
+
+ match export {
+ ModuleExport::PredicateKey((ref name, arity)) => {
+ let key = (name.clone(), *arity);
+
+ if let Some(src_code_index) = imported_module.code_dir.get(&key) {
+ let target_code_index = code_dir
+ .entry(key.clone())
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone();
+
+ set_code_index(
+ retraction_info,
+ compilation_target,
+ key,
+ &target_code_index,
+ src_code_index.get(),
+ );
+ } else {
+ unreachable!()
+ }
+ }
+ ModuleExport::OpDecl(ref op_decl) => {
+ add_op_decl(
+ retraction_info,
+ compilation_target,
+ op_dir,
+ op_decl,
+ );
+ }
+ }
+ }
+}
+
+fn import_qualified_module_exports_into_module(
+ retraction_info: &mut RetractionInfo,
+ compilation_target: &CompilationTarget,
+ imported_module: &Module,
+ exports: &IndexSet<ModuleExport>,
+ code_dir: &mut CodeDir,
+ op_dir: &mut OpDir,
+ wam_op_dir: &mut OpDir,
+ module_op_exports: &mut ModuleOpExports,
+) {
+ for export in imported_module.module_decl.exports.iter() {
+ if !exports.contains(export) {
+ continue;
+ }
+
+ match export {
+ ModuleExport::PredicateKey((ref name, arity)) => {
+ let key = (name.clone(), *arity);
+
+ if let Some(src_code_index) = imported_module.code_dir.get(&key) {
+ let target_code_index = code_dir
+ .entry(key.clone())
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone();
+
+ set_code_index(
+ retraction_info,
+ compilation_target,
+ key,
+ &target_code_index,
+ src_code_index.get(),
+ );
+ } else {
+ unreachable!()
+ }
+ }
+ ModuleExport::OpDecl(ref op_decl) => {
+ add_op_decl_as_module_export(
+ op_dir,
+ compilation_target,
+ retraction_info,
+ wam_op_dir,
+ module_op_exports,
+ op_decl,
+ );
+ }
+ }
+ }
+}
+
+impl<'a> LoadState<'a> {
+ #[inline]
+ pub(super)
+ fn increment_clause_assert_margin(&mut self, incr: usize) {
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ }
+ CompilationTarget::Module(ref module_name) => {
+ self.retraction_info.push_record(
+ RetractionRecord::IncreasedClauseAssertMargin(
+ module_name.clone(),
+ incr,
+ ),
+ );
+
+ self.wam.indices.modules.get_mut(module_name)
+ .map(|module| module.clause_assert_margin += incr);
+ }
+ }
+ }
+
+ #[inline]
+ pub(super)
+ fn remove_module_op_exports(&mut self) {
+ for (mut op_decl, record) in self.module_op_exports.drain(0 ..) {
+ op_decl.remove(&mut self.wam.indices.op_dir);
+
+ if let Some((prec, spec)) = record {
+ op_decl.prec = prec;
+ op_decl.spec = spec;
+ op_decl.insert_into_op_dir(&mut self.wam.indices.op_dir);
+ }
+ }
+ }
+
+ fn get_or_insert_local_code_index(
+ &mut self,
+ module_name: ClauseName,
+ key: PredicateKey,
+ ) -> CodeIndex {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.code_dir
+ .entry(key)
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone()
+ }
+ None => {
+ let mut module = Module::new(
+ ModuleDecl { name: module_name.clone(), exports: vec![] },
+ ListingSource::DynamicallyGenerated,
+ );
+
+ let code_index = module.code_dir
+ .entry(key)
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone();
+
+ self.retraction_info.push_record(
+ RetractionRecord::AddedModule(module_name.clone()),
+ );
+
+ self.wam.indices.modules.insert(module_name, module);
+ code_index
+ }
+ }
+ }
+
+ pub(super)
+ fn get_or_insert_code_index(&mut self, key: PredicateKey) -> CodeIndex {
+ match self.compilation_target.clone() {
+ CompilationTarget::User => {
+ self.wam.indices.code_dir
+ .entry(key)
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone()
+ }
+ CompilationTarget::Module(module_name) => {
+ self.get_or_insert_local_code_index(module_name, key)
+ }
+ }
+ }
+
+ pub(super)
+ fn get_or_insert_qualified_code_index(
+ &mut self,
+ module_name: ClauseName,
+ key: PredicateKey,
+ ) -> CodeIndex {
+ if module_name.as_str() == "user" {
+ return self.wam.indices.code_dir
+ .entry(key)
+ .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined))
+ .clone();
+ } else {
+ self.get_or_insert_local_code_index(module_name, key)
+ }
+ }
+
+ #[inline]
+ pub(super)
+ fn add_extensible_predicate(&mut self, key: PredicateKey, skeleton: PredicateSkeleton) {
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ self.wam.indices.extensible_predicates.insert(key.clone(), skeleton);
+
+ self.retraction_info.push_record(
+ RetractionRecord::AddedUserExtensiblePredicate(key),
+ );
+ }
+ CompilationTarget::Module(ref module_name) => {
+ if let Some(module) = self.wam.indices.modules.get_mut(module_name) {
+ module.extensible_predicates.insert(key.clone(), skeleton);
+
+ self.retraction_info.push_record(
+ RetractionRecord::AddedModuleExtensiblePredicate(module_name.clone(), key),
+ );
+ } else {
+ unreachable!()
+ }
+ }
+ }
+ }
+
+ pub(super)
+ fn add_op_decl(&mut self, op_decl: &OpDecl) {
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ add_op_decl(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ &mut self.wam.indices.op_dir,
+ op_decl,
+ );
+ }
+ CompilationTarget::Module(ref module_name) => {
+ match self.wam.indices.modules.get_mut(module_name) {
+ Some(ref mut module) => {
+ add_op_decl_as_module_export(
+ &mut module.op_dir,
+ &self.compilation_target,
+ &mut self.retraction_info,
+ &mut self.wam.indices.op_dir,
+ &mut self.module_op_exports,
+ op_decl,
+ );
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+ }
+
+ pub(super)
+ fn get_clause_type(
+ &mut self,
+ name: ClauseName,
+ arity: usize,
+ fixity: Option<SharedOpDesc>,
+ ) -> ClauseType {
+ match ClauseType::from(name, arity, fixity) {
+ ClauseType::Named(name, arity, _) => {
+ let idx = self.get_or_insert_code_index((name.clone(), arity));
+ ClauseType::Named(name, arity, idx)
+ }
+ ClauseType::Op(name, fixity, _) => {
+ let idx = self.get_or_insert_code_index((name.clone(), arity));
+ ClauseType::Op(name, fixity, idx)
+ }
+ ct => {
+ ct
+ }
+ }
+ }
+
+ pub(super)
+ fn get_qualified_clause_type(
+ &mut self,
+ module_name: ClauseName,
+ name: ClauseName,
+ arity: usize,
+ fixity: Option<SharedOpDesc>,
+ ) -> ClauseType {
+ match ClauseType::from(name, arity, fixity) {
+ ClauseType::Named(name, arity, _) => {
+ let key = (name.clone(), arity);
+ let idx = self.get_or_insert_qualified_code_index(module_name, key);
+
+ ClauseType::Named(name, arity, idx)
+ }
+ ClauseType::Op(name, fixity, _) => {
+ let key = (name.clone(), arity);
+ let idx = self.get_or_insert_qualified_code_index(module_name, key);
+
+ ClauseType::Op(name, fixity, idx)
+ }
+ ct => {
+ ct
+ }
+ }
+ }
+
+ #[inline]
+ pub(super)
+ fn module_name(&self) -> ClauseName {
+ match self.compilation_target {
+ CompilationTarget::User => {
+ clause_name!("user")
+ }
+ CompilationTarget::Module(ref module_name) => {
+ module_name.clone()
+ }
+ }
+ }
+
+ pub(super)
+ fn add_meta_predicate_record(
+ &mut self,
+ module_name: ClauseName,
+ name: ClauseName,
+ meta_specs: Vec<MetaSpec>,
+ ) {
+ let arity = meta_specs.len();
+ let key = (name, arity);
+
+ match module_name.as_str() {
+ "user" => {
+ match self.wam.indices.meta_predicates.insert(key.clone(), meta_specs) {
+ Some(old_meta_specs) => {
+ self.retraction_info.push_record(
+ RetractionRecord::ReplacedMetaPredicate(
+ module_name.clone(), key.0, old_meta_specs,
+ ),
+ );
+ }
+ None => {
+ self.retraction_info.push_record(
+ RetractionRecord::AddedMetaPredicate(
+ module_name.clone(), key,
+ )
+ );
+ }
+ }
+ }
+ _ => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ match module.meta_predicates.insert(key.clone(), meta_specs) {
+ Some(old_meta_specs) => {
+ self.retraction_info.push_record(
+ RetractionRecord::ReplacedMetaPredicate(
+ module_name.clone(), key.0, old_meta_specs,
+ ),
+ );
+ }
+ None => {
+ self.retraction_info.push_record(
+ RetractionRecord::AddedMetaPredicate(
+ module_name.clone(), key,
+ )
+ );
+ }
+ }
+ }
+ None => {
+ let module_decl = ModuleDecl {
+ name: module_name.clone(),
+ exports: vec![],
+ };
+
+ let listing_src = ListingSource::DynamicallyGenerated;
+ let mut module = Module::new(module_decl, listing_src);
+
+ module.meta_predicates.insert(key.clone(), meta_specs);
+
+ self.retraction_info.push_record(
+ RetractionRecord::AddedMetaPredicate(
+ module_name.clone(), key,
+ )
+ );
+
+ self.retraction_info.push_record(
+ RetractionRecord::AddedModule(module_name.clone()),
+ );
+
+ self.wam.indices.modules.insert(module_name, module);
+ }
+ }
+ }
+ }
+ }
+
+ fn import_builtins_in_module(
+ &mut self,
+ code_dir: &mut CodeDir,
+ op_dir: &mut OpDir,
+ meta_predicates: &mut MetaPredicateDir,
+ ) {
+ if let Some(builtins) = self.wam.indices.modules.get(&clause_name!("builtins")) {
+ import_module_exports(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ builtins,
+ code_dir,
+ op_dir,
+ meta_predicates,
+ );
+ }
+ }
+
+ pub(crate)
+ fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
+ let module_name = module_decl.name.clone();
+
+ let mut module =
+ match self.wam.indices.modules.remove(&module_name) {
+ Some(mut module) => {
+ let old_module_decl = mem::replace(&mut module.module_decl, module_decl);
+
+ self.retraction_info.push_record(
+ RetractionRecord::ReplacedModule(
+ old_module_decl, listing_src.clone(),
+ ),
+ );
+
+ module.listing_src = listing_src;
+ module
+ }
+ None => {
+ self.retraction_info.push_record(
+ RetractionRecord::AddedModule(module_name.clone()),
+ );
+
+ Module::new(module_decl, listing_src)
+ }
+ };
+
+ self.import_builtins_in_module(
+ &mut module.code_dir,
+ &mut module.op_dir,
+ &mut module.meta_predicates,
+ );
+
+ for export in &module.module_decl.exports {
+ if let ModuleExport::OpDecl(ref op_decl) = export {
+ add_op_decl_as_module_export(
+ &mut module.op_dir,
+ &self.compilation_target, // this is a Module.
+ &mut self.retraction_info,
+ &mut self.wam.indices.op_dir,
+ &mut self.module_op_exports,
+ op_decl,
+ );
+ }
+ }
+
+ if let Some(load_context) = self.wam.load_contexts.last_mut() {
+ load_context.module = module_name.clone();
+ }
+
+ self.wam.indices.modules.insert(module_name, module);
+ }
+
+ pub(super)
+ fn import_module(&mut self, module_name: ClauseName) -> Result<(), SessionError> {
+ if let Some(module) = self.wam.indices.modules.remove(&module_name) {
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ import_module_exports(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ &module,
+ &mut self.wam.indices.code_dir,
+ &mut self.wam.indices.op_dir,
+ &mut self.wam.indices.meta_predicates,
+ );
+ }
+ CompilationTarget::Module(ref defining_module_name) => {
+ match self.wam.indices.modules.get_mut(defining_module_name) {
+ Some(ref mut target_module) => {
+ import_module_exports_into_module(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ &module,
+ &mut target_module.code_dir,
+ &mut target_module.op_dir,
+ &mut target_module.meta_predicates,
+ &mut self.wam.indices.op_dir,
+ &mut self.module_op_exports,
+ );
+ }
+ None => {
+ // we find ourselves here because we're trying to import
+ // a module into itself as it is being defined.
+ self.wam.indices.modules.insert(module_name.clone(), module);
+ return Err(SessionError::ModuleCannotImportSelf(module_name));
+ }
+ }
+ }
+ }
+
+ self.wam.indices.modules.insert(module_name, module);
+ Ok(())
+ } else {
+ Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
+ }
+ }
+
+ fn import_qualified_module(
+ &mut self,
+ module_name: ClauseName,
+ exports: IndexSet<ModuleExport>,
+ ) -> Result<(), SessionError> {
+ if let Some(module) = self.wam.indices.modules.remove(&module_name) {
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ import_qualified_module_exports(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ &module,
+ &exports,
+ &mut self.wam.indices.code_dir,
+ &mut self.wam.indices.op_dir,
+ );
+ }
+ CompilationTarget::Module(ref defining_module_name) => {
+ match self.wam.indices.modules.get_mut(defining_module_name) {
+ Some(ref mut target_module) => {
+ import_qualified_module_exports_into_module(
+ &mut self.retraction_info,
+ &self.compilation_target,
+ &module,
+ &exports,
+ &mut target_module.code_dir,
+ &mut target_module.op_dir,
+ &mut self.wam.indices.op_dir,
+ &mut self.module_op_exports,
+ );
+ }
+ None => {
+ // we find ourselves here because we're trying to import
+ // a module into itself as it is being defined.
+ self.wam.indices.modules.insert(module_name.clone(), module);
+ return Err(SessionError::ModuleCannotImportSelf(module_name));
+ }
+ }
+ }
+ }
+
+ self.wam.indices.modules.insert(module_name, module);
+ Ok(())
+ } else {
+ Err(SessionError::ExistenceError(ExistenceError::Module(module_name)))
+ }
+ }
+
+ pub(crate)
+ fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> {
+ let (stream, listing_src) =
+ match module_src {
+ ModuleSource::File(filename) => {
+ let mut path_buf = PathBuf::from(filename.as_str());
+ path_buf.set_extension("pl");
+ let file = File::open(&path_buf)?;
+
+ (Stream::from_file_as_input(filename.clone(), file),
+ ListingSource::File(filename, path_buf))
+ }
+ ModuleSource::Library(library) => {
+ match LIBRARIES.borrow().get(library.as_str()) {
+ Some(code) => {
+ if let Some(ref module) = self.wam.indices.modules.get(&library) {
+ if let ListingSource::DynamicallyGenerated = &module.listing_src {
+ (Stream::from(*code), ListingSource::User)
+ } else {
+ return self.import_module(library);
+ }
+ } else {
+ (Stream::from(*code), ListingSource::User)
+ }
+ }
+ None => {
+ return self.import_module(library);
+ }
+ }
+ }
+ };
+
+ let compilation_target = {
+ let stream = &mut parsing_stream(stream)?;
+
+ let ts = BootstrappingTermStream::from_prolog_stream(
+ stream,
+ self.wam.machine_st.atom_tbl.clone(),
+ self.wam.machine_st.flags,
+ listing_src,
+ );
+
+ let subloader = Loader::new(ts, self.wam);
+ subloader.load()?
+ };
+
+ match compilation_target {
+ CompilationTarget::User => {
+ // nothing to do.
+ Ok(())
+ }
+ CompilationTarget::Module(module_name) => {
+ self.import_module(module_name)
+ }
+ }
+ }
+
+ pub(crate)
+ fn use_qualified_module(
+ &mut self,
+ module_src: ModuleSource,
+ exports: IndexSet<ModuleExport>,
+ ) -> Result<(), SessionError> {
+ let (stream, listing_src) =
+ match module_src {
+ ModuleSource::File(filename) => {
+ let mut path_buf = PathBuf::from(filename.as_str());
+ path_buf.set_extension("pl");
+ let file = File::open(&path_buf)?;
+
+ (Stream::from_file_as_input(filename.clone(), file),
+ ListingSource::File(filename, path_buf))
+ }
+ ModuleSource::Library(library) => {
+ match LIBRARIES.borrow().get(library.as_str()) {
+ Some(code) => {
+ if self.wam.indices.modules.contains_key(&library) {
+ return self.import_qualified_module(library, exports);
+ } else {
+ (Stream::from(*code), ListingSource::User)
+ }
+ }
+ None => {
+ return self.import_qualified_module(library, exports);
+ }
+ }
+ }
+ };
+
+ let compilation_target = {
+ let stream = &mut parsing_stream(stream)?;
+
+ let ts = BootstrappingTermStream::from_prolog_stream(
+ stream,
+ self.wam.machine_st.atom_tbl.clone(),
+ self.wam.machine_st.flags,
+ listing_src,
+ );
+
+ let subloader = Loader::new(ts, self.wam);
+ subloader.load()?
+ };
+
+ match compilation_target {
+ CompilationTarget::User => {
+ // nothing to do.
+ Ok(())
+ }
+ CompilationTarget::Module(module_name) => {
+ self.import_qualified_module(module_name, exports)
+ }
+ }
+ }
+
+ #[inline]
+ pub(super)
+ fn composite_op_dir(&self) -> CompositeOpDir {
+ match &self.compilation_target {
+ CompilationTarget::User => {
+ CompositeOpDir::new(&self.wam.indices.op_dir, None)
+ }
+ CompilationTarget::Module(ref module_name) => {
+ match self.wam.indices.modules.get(module_name) {
+ Some(ref module) => {
+ CompositeOpDir::new(&self.wam.indices.op_dir, Some(&module.op_dir))
+ }
+ None => {
+ unreachable!()
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+use prolog_parser::ast::*;
+
+use crate::forms::*;
+use crate::indexing::*;
+use crate::machine::*;
+use crate::machine::load_state::*;
+use crate::machine::machine_indices::*;
+use crate::machine::preprocessor::*;
+
+use indexmap::IndexSet;
+
+use std::cell::Cell;
+use std::convert::TryFrom;
+use std::rc::Rc;
+
+/*
+ * The loader compiles Prolog terms read from a TermStream instance,
+ * which may be incremental or monolithic. The monolithic term stream
+ * reads from a file. It's used only to bootstrap Scryer at
+ * start-up. Once Scryer is bootstrapped, all compilation and loading
+ * work is divided between loader.pl and loader.rs.
+ *
+ * loader.pl does a few high-level things more easily handled from
+ * Prolog that are not supported (or needed) during bootstrapping:
+ * term and goal expansion, loading modules from different streams,
+ * verifying certain kinds of declarations, perhaps (in the future?)
+ * compiling inline disjunctions.
+ *
+ * Since the loader can operate incrementally, it uses an intermittent
+ * structure to rebuild the loader between
+ * invocations. TopLevelBatchWorker needs access to a &'a mut Machine
+ * for as long as it lives, and we can't have copies of &'a mut
+ * Machine distributed among multiple owners.
+ *
+ * When loading a module, we modify the records of the WAM with the
+ * location of new predicates, with new meta-predicate information,
+ * new term and goal expansions, new dynamic clauses, etc. Should the
+ * loader fail later, all changes must be rolled back, restoring the
+ * WAM to its prior state. Retraction records describe individual changes
+ * made by the loader, and they may be used later.
+ */
+
+#[derive(Debug)]
+pub(crate) enum RetractionRecord {
+ AddedMetaPredicate(ClauseName, PredicateKey),
+ ReplacedMetaPredicate(ClauseName, ClauseName, Vec<MetaSpec>),
+ AddedModule(ClauseName),
+ ReplacedModule(ModuleDecl, ListingSource),
+ AddedModuleDynamicPredicate(ClauseName, PredicateKey),
+ AddedModuleExtensiblePredicate(ClauseName, PredicateKey),
+ AppendedModuleExtensiblePredicate(ClauseName, PredicateKey),
+ PrependedModuleExtensiblePredicate(ClauseName, PredicateKey),
+ AddedModuleOp(ClauseName, OpDecl),
+ ReplacedModuleOp(ClauseName, OpDecl, usize, Specifier),
+ AddedModulePredicate(ClauseName, PredicateKey),
+ ReplacedModulePredicate(ClauseName, PredicateKey, IndexPtr),
+ AddedUserDynamicPredicate(PredicateKey),
+ AddedUserOp(OpDecl),
+ ReplacedUserOp(OpDecl, usize, Specifier),
+ AddedUserExtensiblePredicate(PredicateKey),
+ AppendedUserExtensiblePredicate(PredicateKey),
+ PrependedUserExtensiblePredicate(PredicateKey),
+ AddedUserPredicate(PredicateKey),
+ ReplacedUserPredicate(PredicateKey, IndexPtr),
+ AddedIndex(OptArgIndexKey, usize), //, Vec<usize>),
+ RemovedIndex(usize, OptArgIndexKey, usize),
+ ReplacedChoiceOffset(usize, usize),
+ AppendedTrustMe(usize, usize, bool),
+ ReplacedSwitchOnTermVarIndex(usize, usize),
+ ModifiedTryMeElse(usize, usize),
+ ModifiedRetryMeElse(usize, usize),
+ ModifiedRevJmpBy(usize, usize),
+ IncreasedClauseAssertMargin(ClauseName, usize),
+ SkeletonClauseClausesTruncateBack(CompilationTarget, PredicateKey, usize),
+ SkeletonClauseClausesTruncateFront(CompilationTarget, PredicateKey, usize),
+ SkeletonClausePopBack(CompilationTarget, PredicateKey),
+ SkeletonClausePopFront(CompilationTarget, PredicateKey),
+ SkeletonClauseTruncateBack(CompilationTarget, PredicateKey, usize),
+ SkeletonClauseStartReplaced(CompilationTarget, PredicateKey, usize, usize),
+ RemovedDynamicSkeletonClause(CompilationTarget, PredicateKey, usize, ClauseIndexInfo, usize),
+ ReplacedIndexingLine(usize, Vec<IndexingLine>),
+}
+
+/*
+ * Retractions to be performed on rollback are represented by
+ * individual records, and the original extent of the code vector of
+ * the IndexStore, of which there are several (one per module). The
+ * "extent" of a code vector is its length prior to an attempted
+ * module load. The only code vector of the WAM's IndexStore, "code",
+ * is shared by all modules, including the default "user" module.
+ */
+
+pub(super) struct RetractionInfo {
+ orig_code_extent: usize,
+ records: Vec<RetractionRecord>,
+}
+
+impl RetractionInfo {
+ #[inline]
+ pub(super)
+ fn new(orig_code_extent: usize) -> Self {
+ Self {
+ orig_code_extent,
+ records: vec![], //BTreeMap::new(),
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn push_record(&mut self, record: RetractionRecord) {
+ self.records.push(record);
+ }
+
+ #[inline]
+ pub(crate)
+ fn reset(&mut self, code_len: usize) -> Self {
+ let orig_code_extent = self.orig_code_extent;
+ self.orig_code_extent = code_len;
+
+ Self {
+ orig_code_extent,
+ records: mem::replace(&mut self.records, vec![]), //BTreeMap::new()),
+ }
+ }
+}
+
+impl<'a> Drop for LoadState<'a> {
+ fn drop(&mut self) {
+ while let Some(record) = self.retraction_info.records.pop() {
+ match record {
+ RetractionRecord::AddedMetaPredicate(target_module_name, key) => {
+ match target_module_name.as_str() {
+ "user" => {
+ self.wam.indices.meta_predicates.remove(&key);
+ }
+ _ => {
+ match self.wam.indices.modules.get_mut(&target_module_name) {
+ Some(ref mut module) => {
+ module.meta_predicates.remove(&key);
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+ }
+ RetractionRecord::ReplacedMetaPredicate(target_module_name, name, meta_specs) => {
+ match target_module_name.as_str() {
+ "user" => {
+ self.wam.indices.meta_predicates.insert(
+ (name, meta_specs.len()),
+ meta_specs,
+ );
+ }
+ _ => {
+ match self.wam.indices.modules.get_mut(&target_module_name) {
+ Some(ref mut module) => {
+ module.meta_predicates.insert(
+ (name, meta_specs.len()),
+ meta_specs,
+ );
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+ }
+ RetractionRecord::AddedModule(module_name) => {
+ self.wam.indices.modules.remove(&module_name);
+ }
+ RetractionRecord::ReplacedModule(module_decl, listing_src) => {
+ match self.wam.indices.modules.get_mut(&module_decl.name) {
+ Some(ref mut module) => {
+ module.module_decl = module_decl;
+ module.listing_src = listing_src;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ RetractionRecord::AddedModuleDynamicPredicate(module_name, key) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.extensible_predicates.get_mut(&key)
+ .map(|skeleton| {
+ skeleton.is_dynamic = false;
+ });
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::AddedModuleExtensiblePredicate(module_name, key) => {
+ self.wam.indices.remove_predicate_skeleton(
+ &CompilationTarget::Module(module_name),
+ &key,
+ );
+ }
+ RetractionRecord::AppendedModuleExtensiblePredicate(module_name, key) => {
+ self.wam.indices.get_predicate_skeleton(
+ &CompilationTarget::Module(module_name),
+ &key,
+ ).map(|skeleton| {
+ skeleton.clauses.pop_back();
+ });
+ }
+ RetractionRecord::PrependedModuleExtensiblePredicate(module_name, key) => {
+ self.wam.indices.get_predicate_skeleton(
+ &CompilationTarget::Module(module_name),
+ &key,
+ ).map(|skeleton| {
+ skeleton.clauses.pop_front();
+ });
+ }
+ RetractionRecord::AddedModuleOp(module_name, mut op_decl) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ op_decl.remove(&mut module.op_dir);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::ReplacedModuleOp(module_name, mut op_decl, prec, spec) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ op_decl.prec = prec;
+ op_decl.spec = spec;
+ op_decl.insert_into_op_dir(&mut module.op_dir);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::AddedModulePredicate(module_name, key) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.code_dir.remove(&key);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::ReplacedModulePredicate(module_name, key, old_code_idx) => {
+ match self.wam.indices.modules.get_mut(&module_name) {
+ Some(ref mut module) => {
+ module.code_dir
+ .get_mut(&key)
+ .map(|code_idx| code_idx.replace(old_code_idx));
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::AddedUserDynamicPredicate(key) => {
+ self.wam.indices.extensible_predicates.get_mut(&key)
+ .map(|skeleton| {
+ skeleton.is_dynamic = false;
+ });
+ }
+ RetractionRecord::AddedUserExtensiblePredicate(key) => {
+ self.wam.indices.remove_predicate_skeleton(
+ &CompilationTarget::User,
+ &key,
+ );
+ }
+ RetractionRecord::AppendedUserExtensiblePredicate(key) => {
+ self.wam.indices.get_predicate_skeleton(
+ &CompilationTarget::User,
+ &key,
+ ).map(|skeleton| {
+ skeleton.clauses.pop_back();
+ });
+ }
+ RetractionRecord::PrependedUserExtensiblePredicate(key) => {
+ self.wam.indices.get_predicate_skeleton(
+ &CompilationTarget::User,
+ &key,
+ ).map(|skeleton| {
+ skeleton.clauses.pop_front();
+ });
+ }
+ RetractionRecord::AddedUserOp(mut op_decl) => {
+ op_decl.remove(&mut self.wam.indices.op_dir);
+ }
+ RetractionRecord::ReplacedUserOp(mut op_decl, prec, spec) => {
+ op_decl.prec = prec;
+ op_decl.spec = spec;
+ op_decl.insert_into_op_dir(&mut self.wam.indices.op_dir);
+ }
+ RetractionRecord::AddedUserPredicate(key) => {
+ self.wam.indices.code_dir.remove(&key);
+ }
+ RetractionRecord::ReplacedUserPredicate(key, old_code_idx) => {
+ self.wam.indices.code_dir
+ .get_mut(&key)
+ .map(|code_idx| code_idx.replace(old_code_idx));
+ }
+ RetractionRecord::AddedIndex(index_key, clause_loc) => { // WAS: inner_index_locs) => {
+ if let Some(index_loc) = index_key.switch_on_term_loc() {
+ let indexing_code =
+ match &mut self.wam.code_repo.code[index_loc] {
+ Line::IndexingCode(indexing_code) => {
+ indexing_code
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ match index_key {
+ OptArgIndexKey::Constant(_, index_loc, constant, overlapping_constants) => {
+ remove_constant_indices(
+ &constant,
+ &overlapping_constants,
+ indexing_code,
+ clause_loc - index_loc, // WAS: &inner_index_locs,
+ );
+ }
+ OptArgIndexKey::Structure(_, index_loc, name, arity) => {
+ remove_structure_index(
+ &name,
+ arity,
+ indexing_code,
+ clause_loc - index_loc, // WAS: &inner_index_locs,
+ );
+ }
+ OptArgIndexKey::List(_, index_loc) => {
+ remove_list_index(
+ indexing_code,
+ clause_loc - index_loc, // WAS: &inner_index_locs,
+ );
+ }
+ OptArgIndexKey::None => {
+ unreachable!();
+ }
+ }
+ }
+ }
+ RetractionRecord::RemovedIndex(_index_loc, _index_key, _clause_loc) => {
+ // TODO: this needs to be fixed! RemovedIndex doesn't provide
+ // enough information to restore the index. Correct that, then
+ // write the retraction logic of this arm.
+ }
+ RetractionRecord::ReplacedChoiceOffset(instr_loc, offset) => {
+ match &mut self.wam.code_repo.code[instr_loc] {
+ Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) |
+ Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) |
+ Line::Choice(ChoiceInstruction::DefaultRetryMeElse(ref mut o)) => {
+ *o = offset;
+ }
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ RetractionRecord::AppendedTrustMe(instr_loc, offset, is_default) => {
+ match &mut self.wam.code_repo.code[instr_loc] {
+ Line::Choice(ref mut choice_instr) => {
+ *choice_instr = if is_default {
+ ChoiceInstruction::DefaultTrustMe(offset)
+ } else {
+ ChoiceInstruction::TrustMe(offset)
+ };
+ }
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v) => {
+ match &mut self.wam.code_repo.code[index_loc] {
+ Line::IndexingCode(ref mut indexing_code) => {
+ match &mut indexing_code[0] {
+ IndexingLine::Indexing(
+ IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)
+ ) => {
+ *v = old_v;
+ }
+ _ => {
+ }
+ }
+ }
+ _ => {
+ }
+ }
+ }
+ RetractionRecord::ModifiedTryMeElse(instr_loc, o) => {
+ self.wam.code_repo.code[instr_loc] =
+ Line::Choice(ChoiceInstruction::TryMeElse(o));
+ }
+ RetractionRecord::ModifiedRetryMeElse(instr_loc, o) => {
+ self.wam.code_repo.code[instr_loc] =
+ Line::Choice(ChoiceInstruction::RetryMeElse(o));
+ }
+ RetractionRecord::ModifiedRevJmpBy(instr_loc, o) => {
+ self.wam.code_repo.code[instr_loc] =
+ Line::Control(ControlInstruction::RevJmpBy(o));
+ }
+ RetractionRecord::IncreasedClauseAssertMargin(module_name, incr) => {
+ if let Some(module) = self.wam.indices.modules.get_mut(&module_name) {
+ module.clause_assert_margin -= incr;
+ }
+ }
+ RetractionRecord::SkeletonClauseClausesTruncateFront(compilation_target, key, len) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clause_clause_locs.truncate_front(len);
+ }
+ None => {
+ }
+ }
+
+ let compilation_target =
+ match compilation_target {
+ CompilationTarget::User => {
+ CompilationTarget::Module(clause_name!("builtins"))
+ }
+ _ => {
+ compilation_target
+ }
+ };
+
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &(clause_name!("$clause"), 2),
+ ) {
+ Some(skeleton) => {
+ skeleton.clause_clause_locs.truncate_front(len);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::SkeletonClauseClausesTruncateBack(compilation_target, key, len) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clause_clause_locs.truncate_back(len);
+ }
+ None => {
+ }
+ }
+
+ let compilation_target =
+ match compilation_target {
+ CompilationTarget::User => {
+ CompilationTarget::Module(clause_name!("builtins"))
+ }
+ _ => {
+ compilation_target
+ }
+ };
+
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &(clause_name!("$clause"), 2),
+ ) {
+ Some(skeleton) => {
+ skeleton.clause_clause_locs.truncate_back(len);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::SkeletonClausePopBack(compilation_target, key) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clauses.pop_back();
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::SkeletonClausePopFront(compilation_target, key) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clauses.pop_front();
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::SkeletonClauseTruncateBack(compilation_target, key, len) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clauses.truncate_back(len);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::SkeletonClauseStartReplaced(
+ compilation_target,
+ key,
+ target_pos,
+ clause_start,
+ ) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clauses[target_pos].clause_start = clause_start;
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::RemovedDynamicSkeletonClause(
+ compilation_target,
+ key,
+ target_pos,
+ clause_index_info,
+ clause_clause_loc,
+ ) => {
+ match self.wam.indices.get_predicate_skeleton(
+ &compilation_target,
+ &key,
+ ) {
+ Some(skeleton) => {
+ skeleton.clause_clause_locs.insert(target_pos, clause_clause_loc);
+ skeleton.clauses.insert(target_pos, clause_index_info);
+ }
+ None => {
+ }
+ }
+ }
+ RetractionRecord::ReplacedIndexingLine(index_loc, indexing_code) => {
+ self.wam.code_repo.code[index_loc] = Line::IndexingCode(indexing_code);
+ }
+ }
+ }
+ // TODO: necessary? unnecessary?
+ // self.wam.code_repo.code.truncate(self.retraction_info.orig_code_extent);
+ }
+}
+
+#[derive(Debug, Clone)]
+pub enum CompilationTarget {
+ Module(ClauseName),
+ User,
+}
+
+impl Default for CompilationTarget {
+ #[inline]
+ fn default() -> Self {
+ CompilationTarget::User
+ }
+}
+
+impl CompilationTarget {
+ #[inline]
+ pub(super)
+ fn take(&mut self) -> CompilationTarget {
+ mem::replace(self, CompilationTarget::User)
+ }
+}
+
+pub(crate) struct Loader<'a, TermStream> {
+ pub(super) load_state: LoadState<'a>,
+ pub(super) predicates: Vec<PredicateClause>,
+ pub(super) clause_clauses: Vec<(Term, Term)>,
+ term_stream: TermStream,
+ pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
+ pub(super) preprocessor: Preprocessor,
+}
+
+impl<'a, TS: TermStream> Loader<'a, TS> {
+ #[inline]
+ pub(super)
+ fn new(term_stream: TS, wam: &'a mut Machine) -> Self {
+ let flags = wam.machine_st.flags;
+ let load_state = LoadState {
+ compilation_target: CompilationTarget::User,
+ module_op_exports: vec![],
+ retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
+ wam,
+ };
+
+ Self {
+ load_state,
+ term_stream,
+ non_counted_bt_preds: IndexSet::new(),
+ preprocessor: Preprocessor::new(flags),
+ predicates: vec![],
+ clause_clauses: vec![],
+ }
+ }
+
+ pub(crate)
+ fn load(mut self) -> Result<TS::Evacuable, SessionError> {
+ while let Some(decl) = self.dequeue_terms()? {
+ self.load_decl(decl)?;
+ }
+
+ TS::evacuate(self)
+ }
+
+ fn dequeue_terms(&mut self) -> Result<Option<Declaration>, SessionError> {
+ while !self.term_stream.eof()? {
+ let term = self.term_stream.next(&self.load_state.composite_op_dir())?;
+
+ // if is_consistent is false, self.predicates is not empty.
+ if !term.is_consistent(&self.predicates) {
+ self.compile_and_submit()?;
+ }
+
+ let tl = self.preprocessor.try_term_to_tl(
+ &mut self.load_state,
+ term,
+ CutContext::BlocksCuts,
+ )?;
+
+ match tl {
+ TopLevel::Fact(fact) =>
+ self.predicates.push(PredicateClause::Fact(fact)),
+ TopLevel::Rule(rule) =>
+ self.predicates.push(PredicateClause::Rule(rule)),
+ TopLevel::Predicate(pred) =>
+ self.predicates.extend(pred),
+ TopLevel::Declaration(decl) =>
+ return Ok(Some(decl)),
+ TopLevel::Query(_) =>
+ return Err(SessionError::QueryCannotBeDefinedAsFact),
+ }
+ }
+
+ Ok(None)
+ }
+
+ pub(super)
+ fn load_decl(&mut self, decl: Declaration) -> Result<(), SessionError> {
+ match decl {
+ Declaration::Dynamic(name, arity) => {
+ self.add_dynamic_predicate(name, arity);
+ }
+ Declaration::MetaPredicate(module_name, name, meta_specs) => {
+ self.load_state.add_meta_predicate_record(
+ module_name,
+ name,
+ meta_specs,
+ );
+ }
+ Declaration::Module(module_decl) => {
+ self.load_state.compilation_target =
+ CompilationTarget::Module(module_decl.name.clone());
+
+ self.load_state.add_module(
+ module_decl,
+ self.term_stream.listing_src().clone(),
+ );
+ }
+ Declaration::NonCountedBacktracking(name, arity) => {
+ self.non_counted_bt_preds.insert((name, arity));
+ }
+ Declaration::Op(op_decl) => {
+ self.load_state.add_op_decl(&op_decl);
+ }
+ Declaration::UseModule(module_src) => {
+ self.load_state.use_module(module_src)?;
+ }
+ Declaration::UseQualifiedModule(module_src, exports) => {
+ self.load_state.use_qualified_module(module_src, exports)?;
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(super)
+ fn read_term_from_heap(&self, heap_term_loc: RegType) -> Result<Term, SessionError> {
+ let machine_st = &self.load_state.wam.machine_st;
+ let term_addr = machine_st[heap_term_loc];
+
+ if machine_st.is_cyclic_term(term_addr) {
+ return Err(SessionError::from(CompilationError::CannotParseCyclicTerm));
+ }
+
+ let mut term_stack = vec![];
+
+ for addr in machine_st.post_order_iter(term_addr) {
+ match machine_st.heap.index_addr(&addr).as_ref() {
+ HeapCellValue::Addr(Addr::Lis(_)) |
+ HeapCellValue::Addr(Addr::PStrLocation(..)) => {
+ let tail = term_stack.pop().unwrap();
+ let head = term_stack.pop().unwrap();
+
+ term_stack.push(Term::Cons(
+ Cell::default(),
+ Box::new(head),
+ Box::new(tail),
+ ));
+ }
+ HeapCellValue::Addr(addr) => {
+ if let Some(r) = addr.as_var() {
+ let offset_string =
+ match r {
+ Ref::HeapCell(h) | Ref::AttrVar(h) =>
+ format!("_{}", h),
+ Ref::StackCell(fr, sc) =>
+ format!("_s_{}_{}", fr, sc),
+ };
+
+ term_stack.push(Term::Var(
+ Cell::default(),
+ Rc::new(offset_string),
+ ));
+ } else {
+ match addr.as_constant_index(machine_st) {
+ Some(constant) => {
+ term_stack.push(Term::Constant(Cell::default(), constant));
+ }
+ None => {
+ return Err(SessionError::from(CompilationError::UnreadableTerm));
+ }
+ }
+ }
+ }
+ HeapCellValue::Atom(ref name, ref shared_op_desc) => {
+ term_stack.push(Term::Constant(
+ Cell::default(),
+ Constant::Atom(name.clone(), shared_op_desc.clone()),
+ ));
+ }
+ HeapCellValue::Integer(ref integer) => {
+ term_stack.push(Term::Constant(
+ Cell::default(),
+ Constant::Integer(integer.clone()),
+ ));
+ }
+ HeapCellValue::NamedStr(arity, ref name, ref shared_op_desc) => {
+ let subterms = term_stack.drain(term_stack.len() - arity ..)
+ .map(Box::new)
+ .collect();
+
+ term_stack.push(Term::Clause(
+ Cell::default(),
+ name.clone(),
+ subterms,
+ shared_op_desc.clone(),
+ ));
+ }
+ HeapCellValue::PartialString(..) => {
+ let string = machine_st.heap_pstr_iter(addr).to_string();
+ term_stack.push(Term::Constant(
+ Cell::default(),
+ Constant::String(Rc::new(string)),
+ ));
+ }
+ HeapCellValue::Rational(ref rational) => {
+ term_stack.push(Term::Constant(
+ Cell::default(),
+ Constant::Rational(rational.clone()),
+ ));
+ }
+ _ => {
+ return Err(SessionError::from(CompilationError::UnreadableTerm));
+ }
+ }
+ }
+
+ debug_assert!(term_stack.len() == 1);
+ Ok(term_stack.pop().unwrap())
+ }
+
+ fn extract_module_export_list_from_heap(
+ &self,
+ r: RegType,
+ ) -> Result<IndexSet<ModuleExport>, SessionError> {
+ let export_list = self.read_term_from_heap(r)?;
+ let atom_tbl = self.load_state.wam.machine_st.atom_tbl.clone();
+ let export_list = setup_module_export_list(export_list, atom_tbl)?;
+
+ Ok(export_list.into_iter().collect())
+ }
+
+ fn add_clause_clause(&mut self, term: Term) -> Result<(), CompilationError> {
+ match term {
+ Term::Clause(_, turnstile, mut terms, _)
+ if turnstile.as_str() == ":-" && terms.len() == 2 => {
+ let body = *terms.pop().unwrap();
+ let head = *terms.pop().unwrap();
+
+ self.clause_clauses.push((head, body));
+ }
+ head @ Term::Constant(_, Constant::Atom(..)) |
+ head @ Term::Clause(..) => {
+ let body = Term::Constant(
+ Cell::default(),
+ Constant::Atom(clause_name!("true"), None),
+ );
+
+ self.clause_clauses.push((head, body));
+ }
+ _ => {
+ return Err(CompilationError::InadmissibleFact);
+ }
+ }
+
+ Ok(())
+ }
+
+ fn add_dynamic_predicate(&mut self, name: ClauseName, arity: usize) {
+ let key = (name, arity);
+
+ match &self.load_state.compilation_target {
+ CompilationTarget::User => {
+ match self.load_state.wam.indices.extensible_predicates.get_mut(&key) {
+ Some(ref mut skeleton) => {
+ if !skeleton.is_dynamic {
+ skeleton.is_dynamic = true;
+
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::AddedUserDynamicPredicate(key.clone())
+ );
+ }
+ }
+ None => {
+ self.load_state.wam.indices.extensible_predicates.insert(
+ key.clone(),
+ PredicateSkeleton::new().set_dynamic(true),
+ );
+
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::AddedUserExtensiblePredicate(key.clone())
+ );
+ }
+ }
+ }
+ CompilationTarget::Module(ref module_name) => {
+ match self.load_state.wam.indices.modules.get_mut(module_name) {
+ Some(ref mut module) => {
+ match module.extensible_predicates.get_mut(&key) {
+ Some(ref mut skeleton) => {
+ if !skeleton.is_dynamic {
+ skeleton.is_dynamic = true;
+
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::AddedModuleDynamicPredicate(
+ module_name.clone(),
+ key.clone(),
+ ),
+ );
+ }
+ }
+ None => {
+ module.extensible_predicates.insert(
+ key.clone(),
+ PredicateSkeleton::new().set_dynamic(true),
+ );
+
+ self.load_state.retraction_info.push_record(
+ RetractionRecord::AddedModuleExtensiblePredicate(
+ module_name.clone(),
+ key.clone(),
+ ),
+ );
+ }
+ }
+ }
+ None => {
+ unreachable!();
+ }
+ }
+ }
+ }
+
+ let code_index = self.load_state.get_or_insert_code_index(key.clone());
+
+ set_code_index(
+ &mut self.load_state.retraction_info,
+ &self.load_state.compilation_target,
+ key,
+ &code_index,
+ IndexPtr::DynamicUndefined,
+ );
+ }
+}
+
+impl Machine {
+ pub(crate)
+ fn use_module(&mut self) {
+ let subevacuable_addr =
+ self.machine_st.store(self.machine_st.deref(self.machine_st[temp_v!(2)]));
+
+ let module_src =
+ ModuleSource::Library(
+ match subevacuable_addr {
+ Addr::LoadStatePayload(payload) => {
+ match &self.machine_st.heap[payload] {
+ HeapCellValue::LoadStatePayload(payload) => {
+ match &payload.compilation_target {
+ CompilationTarget::Module(ref module_name) => {
+ module_name.clone()
+ }
+ CompilationTarget::User => {
+ return;
+ }
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ );
+
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(1));
+
+ let use_module = || {
+ let export_list = loader.extract_module_export_list_from_heap(temp_v!(3))?;
+
+ if export_list.is_empty() {
+ loader.load_state.use_module(module_src)?;
+ } else {
+ loader.load_state.use_qualified_module(module_src, export_list)?;
+ }
+
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = use_module();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn load_compiled_library(&mut self) {
+ let library = atom_from!(
+ self.machine_st,
+ self.machine_st.store(self.machine_st.deref(
+ self.machine_st[temp_v!(1)]
+ ))
+ );
+
+ if let Some(module) = self.indices.modules.get(&library) {
+ if let ListingSource::DynamicallyGenerated = module.listing_src {
+ self.machine_st.fail = true;
+ return;
+ }
+
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2));
+
+ let import_module = || {
+ loader.load_state.import_module(library)?;
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = import_module();
+ self.restore_load_state_payload(result, evacuable_h);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ pub(crate)
+ fn declare_module(&mut self) {
+ let module_name = atom_from!(
+ self.machine_st,
+ self.machine_st.store(self.machine_st.deref(
+ self.machine_st[temp_v!(1)]
+ ))
+ );
+
+ // let export_list = self.machine_st.extract_module_export_list(temp_v!(2));
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3));
+
+ let declare_module = || {
+ // let export_list = export_list?;
+ let exports = loader.extract_module_export_list_from_heap(temp_v!(2))?;
+
+ let module_decl = ModuleDecl {
+ name: module_name,
+ exports: exports.into_iter().collect(),
+ };
+
+ loader.load_decl(Declaration::Module(module_decl))?;
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = declare_module();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn add_dynamic_predicate(&mut self) {
+ let predicate_name = atom_from!(
+ self.machine_st,
+ self.machine_st.store(self.machine_st.deref(
+ self.machine_st[temp_v!(1)]
+ ))
+ );
+
+ let arity =
+ self.machine_st.store(self.machine_st.deref(self.machine_st[temp_v!(2)]));
+
+ let arity =
+ match Number::try_from((arity, &self.machine_st.heap)) {
+ Ok(Number::Integer(n)) if &*n >= &0 && &*n <= &MAX_ARITY =>
+ Ok(n.to_usize().unwrap()),
+ Ok(Number::Fixnum(n)) if n >= 0 && n <= MAX_ARITY as isize =>
+ Ok(usize::try_from(n).unwrap()),
+ _ =>
+ Err(SessionError::from(CompilationError::InvalidRuleHead))
+ };
+
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3));
+
+ let add_dynamic_predicate = || {
+ loader.add_dynamic_predicate(predicate_name, arity?);
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = add_dynamic_predicate();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn add_term_expansion_clause(&mut self) {
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2));
+
+ let add_clause = || {
+ let term = loader.read_term_from_heap(temp_v!(1))?;
+
+ loader.incremental_compile_clause(
+ (clause_name!("$term_expansion"), 2),
+ term,
+ CompilationTarget::User,
+ false,
+ AppendOrPrepend::Append,
+ )?;
+
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = add_clause();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn add_goal_expansion_clause(&mut self) {
+ let target_module_name = atom_from!(
+ self.machine_st,
+ self.machine_st.store(self.machine_st.deref(
+ self.machine_st[temp_v!(1)]
+ ))
+ );
+
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3));
+
+ let compilation_target =
+ match target_module_name.as_str() {
+ "user" => CompilationTarget::User,
+ _ => CompilationTarget::Module(target_module_name),
+ };
+
+ let add_clause = || {
+ let term = loader.read_term_from_heap(temp_v!(2))?;
+
+ loader.incremental_compile_clause(
+ (clause_name!("goal_expansion"), 2),
+ term,
+ compilation_target,
+ false, // backtracking inferences are counted by call_with_inference_limit.
+ AppendOrPrepend::Append,
+ )?;
+
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = add_clause();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn loader_from_heap_evacuable(&mut self, r: RegType) -> (Loader<LiveTermStream>, usize) {
+ let (load_state_payload, evacuable_h) =
+ match self.machine_st.store(self.machine_st.deref(self.machine_st[r])) {
+ Addr::LoadStatePayload(h) => {
+ ( mem::replace(
+ &mut self.machine_st.heap[h],
+ HeapCellValue::Addr(Addr::EmptyList),
+ ),
+ h,
+ )
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ match load_state_payload {
+ HeapCellValue::LoadStatePayload(payload) => {
+ (Loader::from_load_state_payload(self, payload), evacuable_h)
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn push_load_state_payload(&mut self) {
+ let payload = LoadStatePayload::new(self);
+ let addr = Addr::LoadStatePayload(
+ self.machine_st.heap.push(HeapCellValue::LoadStatePayload(payload))
+ );
+
+ self.machine_st.bind(self.machine_st[temp_v!(1)].as_var().unwrap(), addr);
+ }
+
+ #[inline]
+ pub(crate)
+ fn pop_load_state_payload(&mut self) {
+ let load_state_payload =
+ match self.machine_st.store(self.machine_st.deref(self.machine_st[temp_v!(1)])) {
+ Addr::LoadStatePayload(h) => {
+ mem::replace(
+ &mut self.machine_st.heap[h],
+ HeapCellValue::Addr(Addr::EmptyList),
+ )
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ match load_state_payload {
+ HeapCellValue::LoadStatePayload(payload) => {
+ Loader::from_load_state_payload(self, payload);
+ }
+ _ => {
+ // unlike in loader_from_heap_evacuable,
+ // pop_load_state_payload is allowed to fail to find a
+ // LoadStatePayload in the heap, as a Rust-side
+ // top-level command may have failed to write the
+ // load state payload back to the heap.
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn pop_load_context(&mut self) {
+ self.load_contexts.pop();
+ }
+
+ pub(crate)
+ fn push_load_context(&mut self) {
+ let stream =
+ try_or_fail!(
+ self.machine_st,
+ self.machine_st.get_stream_or_alias(
+ self.machine_st[temp_v!(1)],
+ &self.indices,
+ "$push_load_context",
+ 2,
+ )
+ );
+
+ let path =
+ atom_from!(
+ self.machine_st,
+ self.machine_st.store(self.machine_st.deref(
+ self.machine_st[temp_v!(2)]
+ ))
+ );
+
+ self.load_contexts.push(LoadContext::new(path.as_str(), stream));
+ }
+
+ pub(crate)
+ fn restore_load_state_payload(
+ &mut self,
+ result: Result<LoadStatePayload, SessionError>,
+ evacuable_h: usize,
+ ) {
+ match result {
+ Ok(payload) => {
+ self.machine_st.heap[evacuable_h] = HeapCellValue::LoadStatePayload(
+ payload
+ );
+ }
+ Err(e) => {
+ self.throw_session_error(e, (clause_name!("load"), 1));
+ }
+ }
+ }
+
+ pub(crate)
+ fn clause_to_evacuable(&mut self) {
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2));
+
+ let enqueue_term = || {
+ let term = loader.read_term_from_heap(temp_v!(1))?;
+
+ if let Some(predicate_name) = ClauseInfo::name(&term) {
+ let arity = ClauseInfo::arity(&term);
+
+ let is_dynamic =
+ loader.load_state.wam.indices.get_predicate_skeleton(
+ &loader.load_state.compilation_target,
+ &(predicate_name, arity),
+ ).map(|skeleton| skeleton.is_dynamic)
+ .unwrap_or(false);
+
+ if is_dynamic {
+ loader.add_clause_clause(term.clone())?;
+ }
+ }
+
+ loader.enqueue_term(term);
+ loader.load()
+ };
+
+ let result = enqueue_term();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn conclude_load(&mut self) {
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(1));
+
+ let compile_final_terms = || {
+ if !loader.predicates.is_empty() {
+ loader.compile_and_submit()?;
+ }
+
+ loader.load_state.remove_module_op_exports();
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = compile_final_terms();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+
+ pub(crate)
+ fn load_context_source(&mut self) {
+ if let Some(load_context) = self.load_contexts.last() {
+ let path_str = load_context.path.to_str().unwrap();
+ let path_atom =
+ clause_name!(path_str.to_string(), self.machine_st.atom_tbl);
+
+ let path_addr = Addr::Con(
+ self.machine_st.heap.push(HeapCellValue::Atom(path_atom, None))
+ );
+
+ self.machine_st.unify(path_addr, self.machine_st[temp_v!(1)]);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ pub(crate)
+ fn load_context_file(&mut self) {
+ if let Some(load_context) = self.load_contexts.last() {
+ if let Some(file_name) = load_context.path.file_name() {
+ let file_name_str = file_name.to_str().unwrap();
+ let file_name_atom =
+ clause_name!(file_name_str.to_string(), self.machine_st.atom_tbl);
+
+ let file_name_addr = Addr::Con(
+ self.machine_st.heap.push(HeapCellValue::Atom(file_name_atom, None))
+ );
+
+ self.machine_st.unify(file_name_addr, self.machine_st[temp_v!(1)]);
+ return;
+ }
+ }
+
+ self.machine_st.fail = true;
+ }
+
+ pub(crate)
+ fn load_context_directory(&mut self) {
+ if let Some(load_context) = self.load_contexts.last() {
+ if let Some(directory) = load_context.path.ancestors().next() {
+ let directory_str = directory.to_str().unwrap();
+ let directory_atom =
+ clause_name!(directory_str.to_string(), self.machine_st.atom_tbl);
+
+ let directory_addr = Addr::Con(
+ self.machine_st.heap.push(HeapCellValue::Atom(directory_atom, None))
+ );
+
+ self.machine_st.unify(directory_addr, self.machine_st[temp_v!(1)]);
+ return;
+ }
+ }
+
+ self.machine_st.fail = true;
+ }
+
+ pub(crate)
+ fn load_context_module(&mut self) {
+ if let Some(load_context) = self.load_contexts.last() {
+ let module_name_addr = Addr::Con(
+ self.machine_st.heap.push(HeapCellValue::Atom(
+ load_context.module.clone(),
+ None,
+ ))
+ );
+
+ self.machine_st.unify(module_name_addr, self.machine_st[temp_v!(1)]);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ pub(crate)
+ fn load_context_stream(&mut self) {
+ if let Some(load_context) = self.load_contexts.last() {
+ let stream_addr = Addr::Stream(
+ self.machine_st.heap.push(HeapCellValue::Stream(
+ load_context.stream.clone()
+ ))
+ );
+
+ self.machine_st.unify(stream_addr, self.machine_st[temp_v!(1)]);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ pub(crate)
+ fn compile_user_assert(&mut self, append_or_prepend: AppendOrPrepend) {
+ let key =
+ self.machine_st.read_predicate_key(
+ self.machine_st[temp_v!(3)],
+ self.machine_st[temp_v!(4)],
+ );
+
+ let compile_user_assert = || {
+ let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self);
+
+ let head = loader.read_term_from_heap(temp_v!(1))?;
+ let body = loader.read_term_from_heap(temp_v!(2))?;
+
+ let asserted_clause =
+ Term::Clause(
+ Cell::default(),
+ clause_name!(":-"),
+ vec![Box::new(head.clone()), Box::new(body.clone())],
+ fetch_op_spec(clause_name!(":-"), 2, &loader.load_state.wam.indices.op_dir),
+ );
+
+ loader.incremental_compile_clause(
+ key.clone(),
+ asserted_clause,
+ CompilationTarget::User,
+ false,
+ append_or_prepend,
+ )?;
+
+ // if a new predicate was just created, make it dynamic.
+ loader.load_state.wam.indices.get_predicate_skeleton(
+ &loader.load_state.compilation_target,
+ &key,
+ ).map(|skeleton| skeleton.is_dynamic = true);
+
+ loader.compile_clause_clauses(key, std::iter::once((head, body)), append_or_prepend)?;
+
+ LiveTermStream::evacuate(loader)
+ };
+
+ match compile_user_assert() {
+ Ok(_) => {
+ }
+ Err(e) => {
+ let error_pi =
+ match append_or_prepend {
+ AppendOrPrepend::Append => (clause_name!("assertz"), 1),
+ AppendOrPrepend::Prepend => (clause_name!("asserta"), 1),
+ };
+
+ self.throw_session_error(e, error_pi);
+ }
+ }
+ }
+
+ pub(crate)
+ fn retract_user_clause(&mut self) {
+ let key =
+ self.machine_st.read_predicate_key(
+ self.machine_st[temp_v!(1)],
+ self.machine_st[temp_v!(2)],
+ );
+
+ let target_pos =
+ self.machine_st.store(self.machine_st.deref(self.machine_st[temp_v!(3)]));
+
+ let target_pos =
+ match Number::try_from((target_pos, &self.machine_st.heap)) {
+ Ok(Number::Integer(n)) =>
+ n.to_usize().unwrap(),
+ Ok(Number::Fixnum(n)) =>
+ usize::try_from(n).unwrap(),
+ _ =>
+ unreachable!()
+ };
+
+ let retract_user_clause = || {
+ let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self);
+ let clause_clause_loc = loader.load_state.retract_clause(key, target_pos);
+
+ let clause_assert_margin =
+ loader.load_state.wam.indices.modules.get(&clause_name!("builtins"))
+ .map(|builtins| builtins.clause_assert_margin)
+ .unwrap();
+
+ let target_pos =
+ match loader.load_state.wam.indices.get_predicate_skeleton(
+ &CompilationTarget::Module(clause_name!("builtins")),
+ &(clause_name!("$clause"), 2),
+ ) {
+ Some(skeleton) => {
+ let search_result =
+ skeleton.clause_clause_locs[0 .. clause_assert_margin]
+ .binary_search_by(|loc| clause_clause_loc.cmp(&loc));
+
+ let result =
+ search_result.unwrap_or_else(|_| {
+ skeleton.clause_clause_locs[clause_assert_margin ..]
+ .binary_search_by(|loc| loc.cmp(&clause_clause_loc))
+ .unwrap() + clause_assert_margin
+ });
+
+ if result < clause_assert_margin {
+ loader.load_state.wam.indices.modules.get_mut(&clause_name!("builtins"))
+ .map(|builtins| builtins.clause_assert_margin -= 1);
+ }
+
+ result
+ }
+ None => {
+ unreachable!();
+ }
+ };
+
+
+ let compilation_target = mem::replace(
+ &mut loader.load_state.compilation_target,
+ CompilationTarget::Module(clause_name!("builtins")),
+ );
+
+ loader.load_state.retract_clause((clause_name!("$clause"), 2), target_pos);
+ loader.load_state.compilation_target = compilation_target;
+
+ LiveTermStream::evacuate(loader)
+ };
+
+ match retract_user_clause() {
+ Ok(_) => {
+ }
+ Err(e) => {
+ self.throw_session_error(e, (clause_name!("retract"), 1));
+ }
+ }
+ }
+
+ pub(crate)
+ fn meta_predicate_property(&mut self) {
+ let (predicate_name, arity) =
+ self.machine_st.read_predicate_key(
+ self.machine_st[temp_v!(1)],
+ self.machine_st[temp_v!(2)],
+ );
+
+ let compilation_target =
+ if let Some(load_context) = self.load_contexts.last() {
+ CompilationTarget::Module(load_context.module.clone())
+ } else {
+ CompilationTarget::User
+ };
+
+ match self.indices.get_meta_predicate_spec(predicate_name, arity, &compilation_target) {
+ Some(meta_specs) => {
+ let op_spec = fetch_op_spec(clause_name!(":"), 2, &self.indices.op_dir);
+
+ let list_loc = self.machine_st.heap.to_list(
+ meta_specs.iter().map(|meta_spec| {
+ match meta_spec {
+ MetaSpec::Minus => HeapCellValue::Atom(clause_name!("+"), None),
+ MetaSpec::Plus => HeapCellValue::Atom(clause_name!("-"), None),
+ MetaSpec::Either => HeapCellValue::Atom(clause_name!("?"), None),
+ MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
+ HeapCellValue::Addr(Addr::Usize(*arg_num))
+ }
+ MetaSpec::RequiresExpansion => {
+ HeapCellValue::Atom(clause_name!(":"), op_spec.clone())
+ }
+ }
+ }),
+ );
+
+ let heap_loc = self.machine_st.heap.push(
+ HeapCellValue::NamedStr(1, clause_name!("meta_predicate"), None),
+ );
+
+ self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(list_loc)));
+ self.machine_st.unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(3)]);
+ }
+ None => {
+ self.machine_st.fail = true;
+ }
+ }
+ }
+
+ pub(crate)
+ fn compile_pending_predicates(&mut self) {
+ let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(1));
+
+ let compile_pending_predicates = || {
+ if !loader.predicates.is_empty() {
+ loader.compile_and_submit()?;
+ }
+
+ LiveTermStream::evacuate(loader)
+ };
+
+ let result = compile_pending_predicates();
+ self.restore_load_state_payload(result, evacuable_h);
+ }
+}
+
+impl<'a> Loader<'a, LiveTermStream> {
+ pub(super)
+ fn to_load_state_payload(mut self) -> LoadStatePayload {
+ LoadStatePayload {
+ term_stream:
+ mem::replace(
+ &mut self.term_stream,
+ LiveTermStream::new(ListingSource::User),
+ ),
+ preprocessor:
+ mem::replace(
+ &mut self.preprocessor,
+ Preprocessor::new(self.load_state.wam.machine_st.flags),
+ ),
+ non_counted_bt_preds:
+ mem::replace(
+ &mut self.non_counted_bt_preds,
+ IndexSet::new(),
+ ),
+ compilation_target:
+ self.load_state.compilation_target.take(),
+ retraction_info:
+ mem::replace(
+ &mut self.load_state.retraction_info,
+ RetractionInfo::new(self.load_state.wam.code_repo.code.len()),
+ ),
+ predicates:
+ mem::replace(
+ &mut self.predicates,
+ vec![],
+ ),
+ clause_clauses:
+ mem::replace(
+ &mut self.clause_clauses,
+ vec![],
+ ),
+ module_op_exports:
+ mem::replace(
+ &mut self.load_state.module_op_exports,
+ vec![],
+ ),
+ }
+ }
+
+ pub(super)
+ fn from_load_state_payload(wam: &'a mut Machine, mut payload: LoadStatePayload) -> Self {
+ Loader {
+ term_stream:
+ mem::replace(
+ &mut payload.term_stream,
+ LiveTermStream::new(ListingSource::User),
+ ),
+ preprocessor:
+ mem::replace(
+ &mut payload.preprocessor,
+ Preprocessor::new(MachineFlags::default()),
+ ),
+ non_counted_bt_preds:
+ mem::replace(
+ &mut payload.non_counted_bt_preds,
+ IndexSet::new(),
+ ),
+ clause_clauses:
+ mem::replace(
+ &mut payload.clause_clauses,
+ vec![],
+ ),
+ predicates:
+ mem::replace(
+ &mut payload.predicates,
+ vec![],
+ ),
+ load_state: LoadState {
+ compilation_target: payload.compilation_target.take(),
+ module_op_exports:
+ mem::replace(
+ &mut payload.module_op_exports,
+ vec![],
+ ),
+ retraction_info:
+ mem::replace(
+ &mut payload.retraction_info,
+ RetractionInfo::new(0),
+ ),
+ wam,
+ },
+ }
+ }
+
+ fn incremental_compile_clause(
+ &mut self,
+ key: PredicateKey,
+ term: Term,
+ compilation_target: CompilationTarget,
+ non_counted_bt: bool,
+ append_or_prepend: AppendOrPrepend,
+ ) -> Result<(), SessionError> {
+ let mut preprocessor = Preprocessor::new(self.load_state.wam.machine_st.flags);
+
+ let tl = preprocessor.try_term_to_tl(
+ &mut self.load_state,
+ term,
+ CutContext::BlocksCuts,
+ )?;
+
+ let queue = preprocessor.parse_queue(&mut self.load_state)?;
+
+ let clause =
+ match tl {
+ TopLevel::Fact(fact) => {
+ PredicateClause::Fact(fact)
+ }
+ TopLevel::Rule(rule) => {
+ PredicateClause::Rule(rule)
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ let compilation_target =
+ mem::replace(&mut self.load_state.compilation_target, compilation_target);
+
+ let result = self.load_state.incremental_compile_clause(
+ key,
+ clause,
+ queue,
+ non_counted_bt,
+ append_or_prepend,
+ );
+
+ self.load_state.compilation_target = compilation_target;
+ result?;
+
+ Ok(())
+ }
+
+ #[inline]
+ fn enqueue_term(&mut self, term: Term) {
+ self.term_stream.term_queue.push_back(term);
+ }
+}
+
+#[inline]
+pub(super)
+fn load_module(
+ code_dir: &mut CodeDir,
+ op_dir: &mut OpDir,
+ meta_predicate_dir: &mut MetaPredicateDir,
+ module: &Module,
+) {
+ import_module_exports(
+ &mut RetractionInfo::new(0),
+ &CompilationTarget::User,
+ module,
+ code_dir,
+ op_dir,
+ meta_predicate_dir,
+ );
+}
use crate::prolog_parser::ast::*;
-use crate::forms::{ModuleSource, Number, PredicateKey};
+use crate::forms::{ModuleSource, Number}; //, PredicateKey};
use crate::machine::heap::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
}
}
- 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::CannotOverwriteBuiltIn(pred_str) |
+ /*
SessionError::CannotOverwriteImport(pred_str) => {
Self::permission_error(
h,
functor!(clause_name(pred_str)),
)
}
+ */
SessionError::ExistenceError(err) => {
Self::existence_error(h, err)
}
- SessionError::InvalidFileName(filename) => {
- Self::existence_error(h, ExistenceError::Module(filename))
- }
+ // SessionError::InvalidFileName(filename) => {
+ // Self::existence_error(h, ExistenceError::Module(filename))
+ // }
+ /*
SessionError::ModuleDoesNotContainExport(..) => {
Self::permission_error(
h,
functor!("module_does_not_contain_claimed_export"),
)
}
+ */
+ SessionError::ModuleCannotImportSelf(module_name) => {
+ Self::permission_error(
+ h,
+ Permission::Modify,
+ "module",
+ functor!("module_cannot_import_self", [clause_name(module_name)]),
+ )
+ }
SessionError::NamelessEntry => {
Self::permission_error(
h,
functor!(clause_name(op)),
)
}
- SessionError::ParserError(err) => {
+ SessionError::CompilationError(err) => {
Self::syntax_error(h, err)
}
SessionError::QueryCannotBeDefinedAsFact => {
}
pub(super)
- fn syntax_error(h: usize, err: ParserError) -> Self {
- if let ParserError::Arithmetic(err) = err {
+ fn syntax_error<E: Into<CompilationError>>(h: usize, err: E) -> Self {
+ let err = err.into();
+
+ if let CompilationError::Arithmetic(err) = err {
return Self::arithmetic_error(h, err);
}
let location = err.line_and_col_num();
- let stub = functor!(err.as_str());
+ let stub = err.as_functor(h);
let stub = functor!(
"syntax_error",
}
}
+#[derive(Debug)]
+pub enum CompilationError {
+ Arithmetic(ArithmeticError),
+ ParserError(ParserError),
+ // BadPendingByte,
+ CannotParseCyclicTerm,
+ // ExpandedTermsListNotAList,
+ ExpectedRel,
+ // ExpectedTopLevelTerm,
+ InadmissibleFact,
+ InadmissibleQueryTerm,
+ InconsistentEntry,
+ // InvalidDoubleQuotesDecl,
+ // InvalidHook,
+ InvalidMetaPredicateDecl,
+ InvalidModuleDecl,
+ InvalidModuleExport,
+ InvalidRuleHead,
+ InvalidUseModuleDecl,
+ InvalidModuleResolution(ClauseName),
+ UnreadableTerm,
+}
+
+impl From<ArithmeticError> for CompilationError {
+ #[inline]
+ fn from(err: ArithmeticError) -> CompilationError {
+ CompilationError::Arithmetic(err)
+ }
+}
+
+impl From<ParserError> for CompilationError {
+ #[inline]
+ fn from(err: ParserError) -> CompilationError {
+ CompilationError::ParserError(err)
+ }
+}
+
+impl CompilationError {
+ pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
+ match self {
+ &CompilationError::ParserError(ref err) =>
+ err.line_and_col_num(),
+ _ =>
+ None
+ }
+ }
+
+ pub fn as_functor(&self, _h: usize) -> MachineStub {
+ match self {
+ &CompilationError::Arithmetic(..) =>
+ functor!("arithmetic_error"),
+ // &CompilationError::BadPendingByte =>
+ // functor!("bad_pending_byte"),
+ &CompilationError::CannotParseCyclicTerm =>
+ functor!("cannot_parse_cyclic_term"),
+ // &CompilationError::ExpandedTermsListNotAList =>
+ // functor!("expanded_terms_list_is_not_a_list"),
+ &CompilationError::ExpectedRel =>
+ functor!("expected_relation"),
+ // &CompilationError::ExpectedTopLevelTerm =>
+ // functor!("expected_atom_or_cons_or_clause"),
+ &CompilationError::InadmissibleFact =>
+ functor!("inadmissible_fact"),
+ &CompilationError::InadmissibleQueryTerm =>
+ functor!("inadmissible_query_term"),
+ &CompilationError::InconsistentEntry =>
+ functor!("inconsistent_entry"),
+ // &CompilationError::InvalidDoubleQuotesDecl =>
+ // functor!("invalid_double_quotes_declaration"),
+ // &CompilationError::InvalidHook =>
+ // functor!("invalid_hook"),
+ &CompilationError::InvalidMetaPredicateDecl =>
+ functor!("invalid_meta_predicate_decl"),
+ &CompilationError::InvalidModuleDecl =>
+ functor!("invalid_module_declaration"),
+ &CompilationError::InvalidModuleExport =>
+ functor!("invalid_module_export"),
+ &CompilationError::InvalidModuleResolution(ref module_name) =>
+ functor!(
+ "no_such_module",
+ [clause_name(module_name.clone())]
+ ),
+ &CompilationError::InvalidRuleHead =>
+ functor!("invalid_head_of_rule"),
+ &CompilationError::InvalidUseModuleDecl =>
+ functor!("invalid_use_module_declaration"),
+ &CompilationError::ParserError(ref err) =>
+ functor!(err.as_str()),
+ &CompilationError::UnreadableTerm =>
+ functor!("unreadable_term"),
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy)]
pub enum Permission {
- Access,
+ // Access,
Create,
InputStream,
Modify,
#[inline]
pub fn as_str(self) -> &'static str {
match self {
- Permission::Access => "access",
+ // Permission::Access => "access",
Permission::Create => "create",
Permission::InputStream => "input",
Permission::Modify => "modify",
#[derive(Debug)]
pub enum SessionError {
- CannotOverwriteBuiltIn(ClauseName),
- CannotOverwriteImport(ClauseName),
+ CompilationError(CompilationError),
+ // CannotOverwriteBuiltIn(ClauseName),
+ // CannotOverwriteImport(ClauseName),
ExistenceError(ExistenceError),
- InvalidFileName(ClauseName),
- ModuleDoesNotContainExport(ClauseName, PredicateKey),
+ // InvalidFileName(ClauseName),
+ // ModuleDoesNotContainExport(ClauseName, PredicateKey),
+ ModuleCannotImportSelf(ClauseName),
NamelessEntry,
OpIsInfixAndPostFix(ClauseName),
QueryCannotBeDefinedAsFact,
- ParserError(ParserError),
}
#[derive(Debug)]
pub enum EvalSession {
- EntrySuccess,
+ // EntrySuccess,
Error(SessionError),
}
impl From<SessionError> for EvalSession {
+ #[inline]
fn from(err: SessionError) -> Self {
EvalSession::Error(err)
}
}
+impl From<std::io::Error> for SessionError {
+ #[inline]
+ fn from(err: std::io::Error) -> SessionError {
+ SessionError::from(ParserError::from(err))
+ }
+}
+
impl From<ParserError> for SessionError {
+ #[inline]
fn from(err: ParserError) -> Self {
- SessionError::ParserError(err)
+ SessionError::CompilationError(CompilationError::from(err))
+ }
+}
+
+impl From<CompilationError> for SessionError {
+ #[inline]
+ fn from(err: CompilationError) -> Self {
+ SessionError::CompilationError(err)
}
}
impl From<ParserError> for EvalSession {
+ #[inline]
fn from(err: ParserError) -> Self {
- EvalSession::from(SessionError::ParserError(err))
+ EvalSession::from(SessionError::from(err))
}
}
use crate::prolog_parser::ast::*;
-use crate::prolog_parser::tabled_rc::*;
use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
+use crate::machine::CompilationTarget;
use crate::machine::code_repo::CodeRepo;
use crate::machine::Ball;
use crate::machine::heap::*;
use crate::machine::partial_string::*;
use crate::machine::raw_block::RawBlockTraits;
use crate::machine::streams::Stream;
+use crate::machine::term_stream::LoadStatePayload;
use crate::instructions::*;
use crate::ordered_float::OrderedFloat;
use crate::rug::{Integer, Rational};
use crate::indexmap::IndexMap;
-use std::cell::RefCell;
+use std::cell::Cell;
use std::cmp::Ordering;
-use std::collections::{BTreeMap, BTreeSet, VecDeque};
+use std::collections::{BTreeMap, BTreeSet};
use std::convert::TryFrom;
use std::fmt;
-use std::mem;
+// use std::mem;
use std::net::TcpListener;
-use std::ops::{Add, AddAssign, Sub, SubAssign};
+use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
use std::rc::Rc;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Fixnum(isize),
Float(OrderedFloat<f64>),
Lis(usize),
+ LoadStatePayload(usize),
HeapCell(usize),
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
StackCell(usize, usize),
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
Some(TermOrderCategory::Compound)
}
- Addr::CutPoint(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
+ Addr::CutPoint(_) | Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
None
}
}
Atom(ClauseName, Option<SharedOpDesc>),
DBRef(DBRef),
Integer(Rc<Integer>),
+ LoadStatePayload(LoadStatePayload),
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
Rational(Rc<Rational>),
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
HeapCellValue::Rational(..) => {
Addr::Con(focus)
}
+ HeapCellValue::LoadStatePayload(_) => {
+ Addr::LoadStatePayload(focus)
+ }
HeapCellValue::NamedStr(_, _, _) => {
Addr::Str(focus)
}
&HeapCellValue::Integer(ref n) => {
HeapCellValue::Integer(n.clone())
}
+ &HeapCellValue::LoadStatePayload(_) => {
+ HeapCellValue::Atom(clause_name!("$live_term_stream"), None)
+ }
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
}
}
}
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum IndexPtr {
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
- Undefined,
- InSituDirEntry(usize),
Index(usize),
- UserGoalExpansion,
- UserTermExpansion
+ Undefined,
}
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
-pub struct CodeIndex(pub Rc<RefCell<(IndexPtr, ClauseName)>>);
+pub struct CodeIndex(pub Rc<Cell<IndexPtr>>);
-impl CodeIndex {
- #[inline]
- pub fn new(ptr: IndexPtr, module_name: ClauseName) -> Self {
- CodeIndex(Rc::new(RefCell::new(( ptr, module_name ))))
- }
+impl Deref for CodeIndex {
+ type Target = Cell<IndexPtr>;
#[inline]
- pub fn is_undefined(&self) -> bool {
- let index_ptr = &self.0.borrow().0;
-
- match index_ptr {
- &IndexPtr::Undefined | &IndexPtr::DynamicUndefined => true,
- _ => false
- }
+ fn deref(&self) -> &Self::Target {
+ self.0.deref()
}
+}
+impl CodeIndex {
#[inline]
- pub fn dynamic_undefined(module_name: ClauseName) -> Self {
- CodeIndex(Rc::new(RefCell::new((
- IndexPtr::DynamicUndefined,
- module_name
- ))))
+ pub(super)
+ fn new(ptr: IndexPtr) -> Self {
+ CodeIndex(Rc::new(Cell::new(ptr)))
}
#[inline]
- pub fn module_name(&self) -> ClauseName {
- self.0.borrow().1.clone()
+ pub fn is_undefined(&self) -> bool {
+ match self.0.get() {
+ IndexPtr::Undefined => true, // | &IndexPtr::DynamicUndefined => true,
+ _ => false
+ }
}
pub fn local(&self) -> Option<usize> {
- match self.0.borrow().0 {
+ match self.0.get() {
IndexPtr::Index(i) => Some(i),
_ => None,
}
impl Default for CodeIndex {
fn default() -> Self {
- CodeIndex(Rc::new(RefCell::new((
- IndexPtr::Undefined,
- clause_name!(""),
- ))))
- }
-}
-
-impl From<(usize, ClauseName)> for CodeIndex {
- fn from(value: (usize, ClauseName)) -> Self {
- CodeIndex(Rc::new(RefCell::new((IndexPtr::Index(value.0), value.1))))
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum DynamicAssertPlace {
- Back,
- Front,
-}
-
-impl DynamicAssertPlace {
- #[inline]
- pub fn predicate_name(self) -> ClauseName {
- match self {
- DynamicAssertPlace::Back => clause_name!("assertz"),
- DynamicAssertPlace::Front => clause_name!("asserta"),
- }
- }
-
- #[inline]
- pub fn push_to_queue(self, addrs: &mut VecDeque<Addr>, new_addr: Addr) {
- match self {
- DynamicAssertPlace::Back => addrs.push_back(new_addr),
- DynamicAssertPlace::Front => addrs.push_front(new_addr),
- }
+ CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)))
}
}
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum DynamicTransactionType {
- Abolish,
- Assert(DynamicAssertPlace),
- ModuleAbolish,
- ModuleAssert(DynamicAssertPlace),
- ModuleRetract,
- Retract, // dynamic index of the clause to remove.
-}
-
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr {
- CompileBatch,
+ AddDynamicPredicate,
+ AddGoalExpansionClause,
+ AddTermExpansionClause,
+ ClauseToEvacuable,
+ ConcludeLoad,
+ DeclareModule,
+ LoadCompiledLibrary,
+ LoadContextSource,
+ LoadContextFile,
+ LoadContextDirectory,
+ LoadContextModule,
+ LoadContextStream,
+ PopLoadContext,
+ PopLoadStatePayload,
+ PushLoadContext,
+ PushLoadStatePayload,
UseModule,
- UseQualifiedModule,
- UseModuleFromFile,
- UseQualifiedModuleFromFile
+ MetaPredicateProperty,
+ CompilePendingPredicates,
+ UserAsserta,
+ UserAssertz,
+ UserRetract,
}
#[derive(Debug, Clone, PartialEq)]
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
CallN(usize, LocalCodePtr, bool), // arity, local, last call.
Local(LocalCodePtr),
- DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
+ // DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
}
| &CodePtr::CallN(_, ref local, _)
| &CodePtr::Local(ref local) => local.clone(),
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
- &CodePtr::REPL(_, p) | &CodePtr::DynamicTransaction(_, p) => p,
+ &CodePtr::REPL(_, p) => p // | &CodePtr::DynamicTransaction(_, p) => p,
+ }
+ }
+
+ #[inline]
+ pub fn is_halt(&self) -> bool {
+ if let CodePtr::Local(LocalCodePtr::Halt) = self {
+ true
+ } else {
+ false
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum LocalCodePtr {
- DirEntry(usize), // offset.
- InSituDirEntry(usize),
- TopLevel(usize, usize), // chunk_num, offset.
- UserGoalExpansion(usize),
- UserTermExpansion(usize),
+ DirEntry(usize), // offset
+ Halt,
+ IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset
+ // TopLevel(usize, usize), // chunk_num, offset
}
impl LocalCodePtr {
}
}
+ #[inline]
+ pub(crate)
+ fn abs_loc(&self) -> usize {
+ match self {
+ LocalCodePtr::DirEntry(ref p) => *p,
+ LocalCodePtr::IndexingBuf(ref p, ..) => *p,
+ LocalCodePtr::Halt => unreachable!(),
+ }
+ }
+
pub(crate)
fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool {
match code_repo.lookup_instr(last_call, &CodePtr::Local(*self)) {
[integer(*p)]
));
}
- LocalCodePtr::InSituDirEntry(p) => {
- heap.append(functor!(
- "in_situ_dir_entry",
- [integer(*p)]
- ));
+ LocalCodePtr::Halt => {
+ heap.append(functor!("halt"));
}
+ /*
LocalCodePtr::TopLevel(chunk_num, offset) => {
heap.append(functor!(
"top_level",
[integer(*chunk_num), integer(*offset)]
));
}
- LocalCodePtr::UserGoalExpansion(p) => {
+ */
+ LocalCodePtr::IndexingBuf(p, o, i) => {
heap.append(functor!(
- "user_goal_expansion",
- [integer(*p)]
- ));
- }
- LocalCodePtr::UserTermExpansion(p) => {
- heap.append(functor!(
- "user_term_expansion",
- [integer(*p)]
+ "indexed_buf",
+ [integer(*p), integer(*o), integer(*i)]
));
}
}
}
}
+/*
impl PartialOrd<CodePtr> for CodePtr {
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
match (self, other) {
impl PartialOrd<LocalCodePtr> for LocalCodePtr {
fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
match (self, other) {
- (&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2))
- | (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2))
- | (&LocalCodePtr::UserTermExpansion(p1), &LocalCodePtr::UserTermExpansion(ref p2))
- | (&LocalCodePtr::UserGoalExpansion(p1), &LocalCodePtr::UserGoalExpansion(ref p2))
- | (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
+ (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2)) |
+ (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
p1.partial_cmp(p2)
}
(_, &LocalCodePtr::TopLevel(_, _)) => {
}
}
}
+*/
impl Default for CodePtr {
+ #[inline]
fn default() -> Self {
CodePtr::Local(LocalCodePtr::default())
}
}
impl Default for LocalCodePtr {
+ #[inline]
fn default() -> Self {
- LocalCodePtr::TopLevel(0, 0)
+ LocalCodePtr::DirEntry(0)
}
}
impl Add<usize> for LocalCodePtr {
type Output = LocalCodePtr;
+ #[inline]
fn add(self, rhs: usize) -> Self::Output {
match self {
- LocalCodePtr::InSituDirEntry(p) => LocalCodePtr::InSituDirEntry(p + rhs),
- LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs),
- LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs),
- LocalCodePtr::UserTermExpansion(p) => LocalCodePtr::UserTermExpansion(p + rhs),
- LocalCodePtr::UserGoalExpansion(p) => LocalCodePtr::UserGoalExpansion(p + rhs),
+ LocalCodePtr::DirEntry(p) =>
+ LocalCodePtr::DirEntry(p + rhs),
+ LocalCodePtr::Halt =>
+ unreachable!(),
+ LocalCodePtr::IndexingBuf(p, o, i) =>
+ LocalCodePtr::IndexingBuf(p, o, i + rhs),
}
}
}
impl Sub<usize> for LocalCodePtr {
type Output = Option<LocalCodePtr>;
+ #[inline]
fn sub(self, rhs: usize) -> Self::Output {
match self {
- LocalCodePtr::InSituDirEntry(p) =>
- p.checked_sub(rhs).map(LocalCodePtr::InSituDirEntry),
LocalCodePtr::DirEntry(p) =>
p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
- LocalCodePtr::TopLevel(cn, p) =>
- p.checked_sub(rhs).map(|r| LocalCodePtr::TopLevel(cn, r)),
- LocalCodePtr::UserTermExpansion(p) =>
- p.checked_sub(rhs).map(LocalCodePtr::UserTermExpansion),
- LocalCodePtr::UserGoalExpansion(p) =>
- p.checked_sub(rhs).map(LocalCodePtr::UserGoalExpansion),
+ LocalCodePtr::Halt =>
+ unreachable!(),
+ LocalCodePtr::IndexingBuf(p, o, i) =>
+ i.checked_sub(rhs).map(|r| LocalCodePtr::IndexingBuf(p, o, r)),
}
}
}
+impl SubAssign<usize> for LocalCodePtr {
+ #[inline]
+ fn sub_assign(&mut self, rhs: usize) {
+ match self {
+ LocalCodePtr::DirEntry(ref mut p) =>
+ *p -= rhs,
+ LocalCodePtr::Halt | LocalCodePtr::IndexingBuf(..) =>
+ unreachable!(),
+ }
+ }
+}
+
+
impl AddAssign<usize> for LocalCodePtr {
+ #[inline]
fn add_assign(&mut self, rhs: usize) {
match self {
- &mut LocalCodePtr::InSituDirEntry(ref mut p)
- | &mut LocalCodePtr::UserGoalExpansion(ref mut p)
- | &mut LocalCodePtr::UserTermExpansion(ref mut p)
- | &mut LocalCodePtr::DirEntry(ref mut p)
- | &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs,
+ &mut LocalCodePtr::DirEntry(ref mut p) /* |
+ &mut LocalCodePtr::TopLevel(_, ref mut p) */ => *p += rhs,
+ &mut LocalCodePtr::IndexingBuf(_, _, ref mut i) => *i += rhs,
+ &mut LocalCodePtr::Halt => unreachable!(),
}
}
}
fn add(self, rhs: usize) -> Self::Output {
match self {
- p @ CodePtr::REPL(..)
- | p @ CodePtr::VerifyAttrInterrupt(_)
- | p @ CodePtr::DynamicTransaction(..) => p,
- CodePtr::Local(local) => CodePtr::Local(local + rhs),
+ p @ CodePtr::REPL(..) |
+ p @ CodePtr::VerifyAttrInterrupt(_) => { // |
+ // p @ CodePtr::DynamicTransaction(..) => {
+ p
+ }
+ CodePtr::Local(local) => {
+ CodePtr::Local(local + rhs)
+ }
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
CodePtr::Local(local + rhs)
}
}
}
-pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
-pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
-
-#[derive(Debug, Clone)]
-pub struct DynamicPredicateInfo {
- pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value.
-}
-
-impl Default for DynamicPredicateInfo {
- fn default() -> Self {
- DynamicPredicateInfo {
- clauses_subsection_p: 0,
+impl SubAssign<usize> for CodePtr {
+ #[inline]
+ fn sub_assign(&mut self, rhs: usize) {
+ match self {
+ CodePtr::Local(ref mut local) => *local -= rhs,
+ _ => unreachable!(),
}
}
}
-pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
-// key type: module name, predicate indicator.
-pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
+pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
+pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
+pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
pub type GlobalVarDir = IndexMap<ClauseName, (Ball, Option<usize>)>;
#[derive(Debug)]
pub(crate) struct ModuleStub {
- pub(crate) atom_tbl: TabledData<Atom>,
pub(crate) in_situ_code_dir: InSituCodeDir,
}
-impl ModuleStub {
- pub(crate) fn new(atom_tbl: TabledData<Atom>) -> Self {
- ModuleStub {
- atom_tbl,
- in_situ_code_dir: InSituCodeDir::new(),
- }
- }
-}
-
-pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
+// pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
pub(crate) type StreamDir = BTreeSet<Stream>;
+pub type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>>;
+
+pub type ExtensiblePredicates = IndexMap<PredicateKey, PredicateSkeleton>;
+
#[derive(Debug)]
pub struct IndexStore {
- pub(super) atom_tbl: TabledData<Atom>,
pub(super) code_dir: CodeDir,
- pub(super) dynamic_code_dir: DynamicCodeDir,
+ pub(super) extensible_predicates: ExtensiblePredicates,
pub(super) global_variables: GlobalVarDir,
- pub(super) in_situ_code_dir: InSituCodeDir,
- pub(super) in_situ_module_dir: ModuleStubDir,
- pub(super) module_dir: ModuleDir,
+ pub(super) meta_predicates: MetaPredicateDir,
pub(super) modules: ModuleDir,
pub(super) op_dir: OpDir,
pub(super) streams: StreamDir,
pub(super) stream_aliases: StreamAliasDir,
}
+impl Default for IndexStore {
+ #[inline]
+ fn default() -> Self {
+ index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
+ }
+}
+
impl IndexStore {
- pub fn predicate_exists(
+ pub fn get_predicate_skeleton(
+ &mut self,
+ compilation_target: &CompilationTarget,
+ key: &PredicateKey,
+ ) -> Option<&mut PredicateSkeleton> {
+ match (key.0.as_str(), key.1) {
+ ("term_expansion", 2) => {
+ self.extensible_predicates.get_mut(key)
+ }
+ _ => {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.extensible_predicates.get_mut(key)
+ }
+ CompilationTarget::Module(ref module_name) => {
+ if let Some(module) = self.modules.get_mut(module_name) {
+ module.extensible_predicates.get_mut(key)
+ } else {
+ None
+ }
+ }
+ }
+ }
+ }
+ }
+
+ pub fn remove_predicate_skeleton(
+ &mut self,
+ compilation_target: &CompilationTarget,
+ key: &PredicateKey,
+ ) {
+ match (key.0.as_str(), key.1) {
+ ("term_expansion", 2) => {
+ self.extensible_predicates.remove(key);
+ },
+ _ => {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.extensible_predicates.remove(key);
+ }
+ CompilationTarget::Module(ref module_name) => {
+ if let Some(module) = self.modules.get_mut(module_name) {
+ module.extensible_predicates.remove(key);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ pub fn get_predicate_code_index(
&self,
name: ClauseName,
- module: ClauseName,
arity: usize,
+ module: ClauseName,
op_spec: Option<SharedOpDesc>,
- ) -> bool {
- match self.modules.get(&module) {
- Some(module) => match ClauseType::from(name, arity, op_spec) {
- ClauseType::Named(name, arity, _) => module.code_dir.contains_key(&(name, arity)),
+ ) -> Option<CodeIndex> {
+ if module.as_str() == "user" {
+ match ClauseType::from(name, arity, op_spec) {
+ ClauseType::Named(name, arity, _) => {
+ self.code_dir.get(&(name, arity)).cloned()
+ }
ClauseType::Op(name, spec, ..) => {
- module.code_dir.contains_key(&(name, spec.arity()))
+ self.code_dir.get(&(name, spec.arity())).cloned()
}
- _ => true,
- },
- None => match ClauseType::from(name, arity, op_spec) {
- ClauseType::Named(name, arity, _) => self.code_dir.contains_key(&(name, arity)),
- ClauseType::Op(name, spec, ..) => self.code_dir.contains_key(&(name, spec.arity())),
- _ => true,
- },
+ _ => {
+ None
+ }
+ }
+ } else {
+ self.modules.get(&module).and_then(|module| {
+ match ClauseType::from(name, arity, op_spec) {
+ ClauseType::Named(name, arity, _) => {
+ module.code_dir.get(&(name, arity)).cloned()
+ }
+ ClauseType::Op(name, spec, ..) => {
+ module.code_dir.get(&(name, spec.arity())).cloned()
+ }
+ _ => {
+ None
+ }
+ }
+ })
}
}
- pub fn add_term_and_goal_expansion_indices(&mut self) {
- self.code_dir.insert((clause_name!("term_expansion"), 2),
- CodeIndex(Rc::new(RefCell::new(
- (IndexPtr::UserTermExpansion,
- clause_name!("user"))
- ))));
- self.code_dir.insert((clause_name!("goal_expansion"), 2),
- CodeIndex(Rc::new(RefCell::new(
- (IndexPtr::UserGoalExpansion,
- clause_name!("user"))
- ))));
- }
-
- #[inline]
- pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
- self.dynamic_code_dir.swap_remove(&(module, name, arity));
- }
-
- #[inline]
- pub fn get_clause_subsection(
+ pub fn get_meta_predicate_spec(
&self,
- module: ClauseName,
name: ClauseName,
arity: usize,
- ) -> Option<DynamicPredicateInfo> {
- self.dynamic_code_dir.get(&(module, name, arity)).cloned()
- }
-
- #[inline]
- pub(crate) fn take_in_situ_module_dir(&mut self) -> ModuleStubDir {
- mem::replace(&mut self.in_situ_module_dir, ModuleStubDir::new())
- }
-
- #[inline]
- pub fn take_in_situ_code_dir(&mut self) -> InSituCodeDir {
- mem::replace(&mut self.in_situ_code_dir, InSituCodeDir::new())
- }
-
- #[inline]
- pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
- self.modules.swap_remove(&name)
- }
-
- #[inline]
- pub fn insert_module(&mut self, module: Module) {
- self.modules.insert(module.module_decl.name.clone(), module);
- }
-
- #[inline]
- pub(super) fn new() -> Self {
- IndexStore {
- atom_tbl: TabledData::new(Rc::new("user".to_string())),
- code_dir: CodeDir::new(),
- module_dir: ModuleDir::new(),
- dynamic_code_dir: DynamicCodeDir::new(),
- global_variables: GlobalVarDir::new(),
- in_situ_code_dir: InSituCodeDir::new(),
- in_situ_module_dir: ModuleStubDir::new(),
- op_dir: default_op_dir(),
- modules: ModuleDir::new(),
- stream_aliases: StreamAliasDir::new(),
- streams: StreamDir::new(),
+ compilation_target: &CompilationTarget,
+ ) -> Option<&Vec<MetaSpec>> {
+ match compilation_target {
+ CompilationTarget::User => {
+ self.meta_predicates.get(&(name, arity))
+ }
+ CompilationTarget::Module(ref module_name) => {
+ match self.modules.get(module_name) {
+ Some(ref module) => {
+ module.meta_predicates.get(&(name.clone(), arity))
+ .or_else(|| {
+ self.meta_predicates.get(&(name, arity))
+ })
+ }
+ None => {
+ self.meta_predicates.get(&(name, arity))
+ }
+ }
+ }
}
}
- #[inline]
- pub(super) fn copy_and_swap(&mut self, other: &mut IndexStore) {
- self.code_dir = other.code_dir.clone();
- self.op_dir = other.op_dir.clone();
-
- mem::swap(&mut self.code_dir, &mut other.code_dir);
- mem::swap(&mut self.op_dir, &mut other.op_dir);
- mem::swap(&mut self.modules, &mut other.modules);
+ pub fn is_dynamic_predicate(&self, module_name: ClauseName, key: PredicateKey) -> bool {
+ match module_name.as_str() {
+ "user" => {
+ self.extensible_predicates.get(&key)
+ .map(|skeleton| skeleton.is_dynamic)
+ .unwrap_or(false)
+ }
+ _ => {
+ match self.modules.get(&module_name) {
+ Some(ref module) => {
+ module.extensible_predicates.get(&key)
+ .map(|skeleton| skeleton.is_dynamic)
+ .unwrap_or(false)
+ }
+ None => {
+ false
+ }
+ }
+ }
+ }
}
#[inline]
- fn get_internal(
- &self,
- name: ClauseName,
- arity: usize,
- in_mod: ClauseName,
- ) -> Option<CodeIndex> {
- self.modules
- .get(&in_mod)
- .and_then(|ref module| module.code_dir.get(&(name, arity)))
- .cloned()
+ pub(super) fn new() -> Self {
+ IndexStore::default()
}
- pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
+ pub(super)
+ fn get_cleaner_sites(&self) -> (usize, usize) {
let r_w_h = clause_name!("run_cleaners_with_handling");
let r_wo_h = clause_name!("run_cleaners_without_handling");
-
let iso_ext = clause_name!("iso_ext");
let r_w_h = self
- .get_internal(r_w_h, 0, iso_ext.clone())
+ .get_predicate_code_index(r_w_h, 0, iso_ext.clone(), None)
.and_then(|item| item.local());
let r_wo_h = self
- .get_internal(r_wo_h, 1, iso_ext)
+ .get_predicate_code_index(r_wo_h, 1, iso_ext, None)
.and_then(|item| item.local());
if let Some(r_w_h) = r_w_h {
}
pub type CodeDir = BTreeMap<PredicateKey, CodeIndex>;
-pub type TermDir = IndexMap<PredicateKey, (Predicate, VecDeque<TopLevel>)>;
-
-#[derive(Debug)]
-pub struct TermDirQuantumEntry {
- pub old_terms: (Predicate, VecDeque<TopLevel>),
- pub new_terms: (Predicate, VecDeque<TopLevel>),
- pub is_fresh: bool,
-}
-
-impl TermDirQuantumEntry {
- #[inline]
- pub fn new() -> Self {
- TermDirQuantumEntry {
- old_terms: (Predicate::new(), VecDeque::new()),
- new_terms: (Predicate::new(), VecDeque::new()),
- is_fresh: false,
- }
- }
-
- pub fn from(preds: &Predicate, queue: &VecDeque<TopLevel>) -> Self
- {
- let mut entry = TermDirQuantumEntry::new();
- entry.is_fresh = false;
-
- (entry.old_terms.0).0.extend(preds.0.iter().cloned());
- entry.old_terms.1.extend(queue.iter().cloned());
-
- entry
- }
-}
-
-#[derive(Debug)]
-pub struct TermDirQuantum(IndexMap<PredicateKey, TermDirQuantumEntry>);
-
-impl TermDirQuantum {
- #[inline]
- pub fn new() -> Self {
- TermDirQuantum(IndexMap::new())
- }
-
- #[inline]
- pub fn insert_or_refresh(&mut self, key: PredicateKey, mut entry: TermDirQuantumEntry) {
- if let Some(prev_entry) = self.get_mut(&key) {
- prev_entry.is_fresh = true;
- } else {
- entry.is_fresh = true;
- self.0.insert(key, entry);
- }
- }
-
- #[inline]
- pub fn insert(&mut self, key: PredicateKey, entry: TermDirQuantumEntry) {
- self.0.insert(key, entry);
- }
-
- #[inline]
- pub fn get_mut(&mut self, key: &PredicateKey) -> Option<&mut TermDirQuantumEntry> {
- self.0.get_mut(key)
- }
-
- pub fn consolidate(self) -> TermDir {
- let mut term_dir = TermDir::new();
-
- for (key, entry) in self.0 {
- let (preds, queue) =
- term_dir.entry(key).or_insert((Predicate::new(), VecDeque::new()));
-
- preds.0.extend((entry.new_terms.0).0.into_iter());
- queue.extend(entry.new_terms.1.into_iter());
- }
-
- term_dir
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
-pub enum CompileTimeHook {
- GoalExpansion,
- TermExpansion,
- UserGoalExpansion,
- UserTermExpansion,
-}
-
-impl CompileTimeHook {
- pub fn name(self) -> ClauseName {
- match self {
- CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
- clause_name!("goal_expansion")
- }
- CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
- clause_name!("term_expansion")
- }
- }
- }
-
- #[inline]
- pub fn arity(self) -> usize {
- match self {
- CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => 2,
- CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => 2,
- }
- }
-
- #[inline]
- pub fn user_scope(self) -> Self {
- match self {
- CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
- CompileTimeHook::UserGoalExpansion
- }
- CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
- CompileTimeHook::UserTermExpansion
- }
- }
- }
-
- #[inline]
- pub fn has_module_scope(self) -> bool {
- match self {
- CompileTimeHook::UserTermExpansion | CompileTimeHook::UserGoalExpansion => false,
- _ => true,
- }
- }
-}
pub enum RefOrOwned<'a, T: 'a> {
Borrowed(&'a T),
match self {
&RefOrOwned::Borrowed(ref borrowed) =>
write!(f, "Borrowed({:?})", borrowed),
- &RefOrOwned::Owned(ref owned) => write!(f, "Owned({:?})", owned),
+ &RefOrOwned::Owned(ref owned) =>
+ write!(f, "Owned({:?})", owned),
}
}
}
}
}
- pub fn to_owned(self) -> T
- where
- T: Clone,
+ pub fn to_owned(self) -> T where T: Clone
{
match self {
RefOrOwned::Borrowed(item) => item.clone(),
use crate::machine::heap::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
-use crate::machine::modules::*;
+use crate::machine::partial_string::HeapPStrIter;
use crate::machine::stack::*;
use crate::machine::streams::*;
use crate::rug::Integer;
use crate::downcast::Any;
-use crate::indexmap::{IndexMap, IndexSet};
+use crate::indexmap::IndexMap;
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::mem;
use std::ops::{Index, IndexMut};
-#[derive(Debug)]
-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(&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(Debug, 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_prefixes<'a>(
- i1: &mut HeapPStrIter<'a>,
- i2: &mut HeapPStrIter<'a>,
-) -> Option<Ordering> {
- let mut r1 = i1.next();
- let mut r2 = i2.next();
-
- loop {
- if let Some(r1i) = r1 {
- if let Some(r2i) = r2 {
- match (r1i, r2i) {
- (PStrIteratee::Char(c1), PStrIteratee::Char(c2)) => {
- if c1 != c2 {
- return c1.partial_cmp(&c2);
- }
- }
- (PStrIteratee::Char(c1), PStrIteratee::PStrSegment(h, n)) => {
- if let &HeapCellValue::PartialString(ref pstr, _) = &i2.machine_st.heap[h] {
- if let Some(c2) = pstr.as_str_from(n).chars().next() {
- if c1 != c2 {
- return c1.partial_cmp(&c2);
- } else {
- r1 = i1.next();
- r2 = Some(PStrIteratee::PStrSegment(h, n + c2.len_utf8()));
-
- continue;
- }
- } else {
- r2 = i2.next();
- continue;
- }
- } else {
- unreachable!()
- }
- }
- (PStrIteratee::PStrSegment(h, n), PStrIteratee::Char(c2)) => {
- if let &HeapCellValue::PartialString(ref pstr, _) = &i1.machine_st.heap[h] {
- if let Some(c1) = pstr.as_str_from(n).chars().next() {
- if c1 != c2 {
- return c2.partial_cmp(&c1);
- } else {
- r1 = i1.next();
- r2 = Some(PStrIteratee::PStrSegment(h, n + c1.len_utf8()));
-
- continue;
- }
- } else {
- r1 = i1.next();
- continue;
- }
- } else {
- unreachable!()
- }
- }
- (PStrIteratee::PStrSegment(h1, n1), PStrIteratee::PStrSegment(h2, n2)) => {
- match (&i1.machine_st.heap[h1], &i2.machine_st.heap[h2]) {
- (
- &HeapCellValue::PartialString(ref pstr1, _),
- &HeapCellValue::PartialString(ref pstr2, _),
- ) => {
- let str1 = pstr1.as_str_from(n1);
- let str2 = pstr2.as_str_from(n2);
-
- if str1.starts_with(str2) {
- r1 = Some(PStrIteratee::PStrSegment(h1, n1 + str2.len()));
- r2 = i2.next();
-
- continue;
- } else if str2.starts_with(str1) {
- r1 = i1.next();
- r2 = Some(PStrIteratee::PStrSegment(h2, n2 + str1.len()));
-
- continue;
- } else {
- return str1.partial_cmp(str2);
- }
- }
- _ => {
- unreachable!()
- }
- }
- }
- }
-
- r1 = i1.next();
- r2 = i2.next();
-
- continue;
- }
- }
-
- return match (i1.focus(), i2.focus()) {
- (Addr::EmptyList, Addr::EmptyList) => {
- Some(Ordering::Equal)
- }
- (Addr::EmptyList, _) => {
- Some(Ordering::Less)
- }
- (_, Addr::EmptyList) => {
- Some(Ordering::Greater)
- }
- _ => {
- 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 Some(s_offset);
- }
- }
- 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!()
- }
- }
- }
- }
-
- if s[s_offset ..].is_empty() {
- return Some(s_offset);
- }
- }
-
- Some(s_offset)
-}
-
#[derive(Debug)]
pub struct Ball {
pub(super) boundary: usize,
self.stub.clear();
}
- pub(super)
- fn take(&mut self) -> Ball {
- let boundary = self.boundary;
- self.boundary = 0;
-
- Ball {
- boundary,
- stub: self.stub.take(),
- }
- }
-
pub(super)
fn copy_and_align(&self, h: usize) -> Heap {
let diff = self.boundary as i64 - h as i64;
#[derive(Debug)]
pub struct MachineState {
+ pub(crate) atom_tbl: TabledData<Atom>,
pub(super) s: HeapPtr,
pub(super) p: CodePtr,
pub(super) b: usize,
loop {
match self.read(
stream.clone(),
- indices.atom_tbl.clone(),
+ self.atom_tbl.clone(),
&indices.op_dir,
) {
Ok(term_write_result) => {
let mut list_of_var_eqs = vec![];
for (var, binding) in term_write_result.var_dict.into_iter() {
- let var_atom = clause_name!(var.to_string(), indices.atom_tbl);
+ let var_atom = clause_name!(var.to_string(), self.atom_tbl);
let h = self.heap.h();
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
Ok(Some(printer))
}
+ pub(super)
+ fn throw_undefined_error(&mut self, name: ClauseName, arity: usize) -> MachineStub {
+ let stub = MachineError::functor_stub(name.clone(), arity);
+ let h = self.heap.h();
+ let key = ExistenceError::Procedure(name, arity);
+
+ self.error_form(MachineError::existence_error(h, key), stub)
+ }
+
#[inline]
pub(crate)
fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
Ok(chars)
}
+ pub(super)
+ fn read_predicate_key(&self, name: Addr, arity: Addr) -> (ClauseName, usize) {
+ let predicate_name = atom_from!(self, self.store(self.deref(name)));
+ let arity = self.store(self.deref(arity));
+
+ let arity =
+ match Number::try_from((arity, &self.heap)) {
+ Ok(Number::Integer(n)) if &*n >= &0 && &*n <= &MAX_ARITY =>
+ n.to_usize().unwrap(),
+ Ok(Number::Fixnum(n)) if n >= 0 && n <= MAX_ARITY as isize =>
+ usize::try_from(n).unwrap(),
+ _ =>
+ unreachable!()
+ };
+
+ (predicate_name, arity)
+ }
+
pub(super)
fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
self.cp.assign_if_local(self.p.clone() + 1);
fn module_lookup(
&mut self,
indices: &IndexStore,
+ call_policy: &mut Box<dyn CallPolicy>,
key: PredicateKey,
module_name: ClauseName,
- last_call: bool,
+ _last_call: bool,
+ current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
- let (name, arity) = key;
-
- if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) {
- match idx.0.borrow().0 {
- IndexPtr::Index(compiled_tl_index) => {
- if last_call {
- self.execute_at_index(arity, dir_entry!(compiled_tl_index));
- } else {
- self.call_at_index(arity, dir_entry!(compiled_tl_index));
- }
-
- return Ok(());
- }
- IndexPtr::DynamicUndefined => {
- self.fail = true;
- return Ok(());
- }
- IndexPtr::UserTermExpansion => {
- if last_call {
- self.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
- } else {
- self.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
- }
-
- return Ok(());
- }
- IndexPtr::UserGoalExpansion => {
- if last_call {
- self.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
- } else {
- self.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
- }
-
- return Ok(());
- }
- IndexPtr::InSituDirEntry(p) => {
- if last_call {
- self.execute_at_index(arity, LocalCodePtr::InSituDirEntry(p));
- } else {
- self.call_at_index(arity, LocalCodePtr::InSituDirEntry(p));
- }
-
- return Ok(());
- }
- _ => {}
- }
+ if module_name.as_str() == "user" {
+ return call_policy.call_clause_type(
+ self,
+ key,
+ &indices.code_dir,
+ &indices.op_dir,
+ current_input_stream,
+ current_output_stream,
+ );
+ } else if let Some(module) = indices.modules.get(&module_name) {
+ return call_policy.call_clause_type(
+ self,
+ key,
+ &module.code_dir,
+ &module.op_dir,
+ current_input_stream,
+ current_output_stream,
+ );
}
+ let (name, arity) = key;
+
let h = self.heap.h();
let stub = MachineError::functor_stub(name.clone(), arity);
let err = MachineError::module_resolution_error(h, module_name, name, arity);
}
}
-fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<LocalCodePtr>
-{
- match indices.in_situ_code_dir.get(&(name.clone(), arity)) {
- Some(p) => Some(LocalCodePtr::InSituDirEntry(*p)),
- None =>
- match indices.code_dir.get(&(name, arity)) {
- Some(ref idx) => {
- if let IndexPtr::Index(p) = idx.0.borrow().0 {
- Some(LocalCodePtr::DirEntry(p))
- } else {
- None
- }
- }
- _ => None,
- },
- }
-}
-
-fn try_in_situ(
- machine_st: &mut MachineState,
- name: ClauseName,
- arity: usize,
- indices: &IndexStore,
- last_call: bool,
-) -> CallResult {
- if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
- if last_call {
- machine_st.execute_at_index(arity, p);
- } else {
- machine_st.call_at_index(arity, p);
- }
-
- machine_st.p = CodePtr::Local(p);
- Ok(())
- } else {
- let stub = MachineError::functor_stub(name.clone(), arity);
- let h = machine_st.heap.h();
- let key = ExistenceError::Procedure(name, arity);
-
- Err(machine_st.error_form(MachineError::existence_error(h, key), stub))
- }
-}
-
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
pub(crate) trait CallPolicy: Any + fmt::Debug {
machine_st.attr_var_init.backtrack(attr_var_init_queue_b, attr_var_init_bindings_b);
machine_st.hb = machine_st.heap.h();
- machine_st.p += offset;
+ machine_st.p = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset));
Ok(())
}
machine_st.stack.truncate(b);
machine_st.hb = machine_st.heap.h();
- machine_st.p += offset;
+ machine_st.p = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset));
Ok(())
}
machine_st: &mut MachineState,
name: ClauseName,
arity: usize,
- idx: CodeIndex,
- indices: &mut IndexStore,
+ idx: &CodeIndex,
) -> CallResult {
if machine_st.last_call {
- self.try_execute(machine_st, name, arity, idx, indices)
+ self.try_execute(machine_st, name, arity, idx)
} else {
- self.try_call(machine_st, name, arity, idx, indices)
+ self.try_call(machine_st, name, arity, idx)
}
}
machine_st: &mut MachineState,
name: ClauseName,
arity: usize,
- idx: CodeIndex,
- indices: &IndexStore,
+ idx: &CodeIndex,
) -> CallResult {
- match idx.0.borrow().0 {
+ match idx.get() {
IndexPtr::DynamicUndefined => {
machine_st.fail = true;
+ return Ok(());
}
IndexPtr::Undefined => {
- return try_in_situ(machine_st, name, arity, indices, false);
+ return Err(machine_st.throw_undefined_error(name, arity));
}
IndexPtr::Index(compiled_tl_index) => {
- machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index))
- }
- IndexPtr::UserTermExpansion => {
- machine_st.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
- }
- IndexPtr::UserGoalExpansion => {
- machine_st.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
- }
- IndexPtr::InSituDirEntry(p) => {
- machine_st.call_at_index(arity, LocalCodePtr::InSituDirEntry(p));
+ machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index));
}
}
machine_st: &mut MachineState,
name: ClauseName,
arity: usize,
- idx: CodeIndex,
- indices: &IndexStore,
+ idx: &CodeIndex,
) -> CallResult {
- match idx.0.borrow().0 {
- IndexPtr::DynamicUndefined =>
- machine_st.fail = true,
- IndexPtr::Undefined =>
- return try_in_situ(machine_st, name, arity, indices, true),
- IndexPtr::Index(compiled_tl_index) => {
- machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
- }
- IndexPtr::UserTermExpansion => {
- machine_st.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
+ match idx.get() {
+ IndexPtr::DynamicUndefined => {
+ machine_st.fail = true;
+ return Ok(());
}
- IndexPtr::UserGoalExpansion => {
- machine_st.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
+ IndexPtr::Undefined => {
+ return Err(machine_st.throw_undefined_error(name, arity));
}
- IndexPtr::InSituDirEntry(p) => {
- machine_st.execute_at_index(arity, LocalCodePtr::InSituDirEntry(p));
+ IndexPtr::Index(compiled_tl_index) => {
+ machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
}
}
&mut self,
machine_st: &mut MachineState,
ct: &BuiltInClauseType,
- indices: &mut IndexStore,
+ _code_dir: &CodeDir,
+ op_dir: &OpDir,
current_input_stream: &mut Stream,
current_output_stream: &mut Stream,
) -> CallResult {
let atom = match machine_st.compare_term_test(&a2, &a3) {
Some(Ordering::Greater) => {
- let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
+ let spec = fetch_atom_op_spec(clause_name!(">"), None, op_dir);
HeapCellValue::Atom(clause_name!(">"), spec)
}
Some(Ordering::Equal) => {
- let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
+ let spec = fetch_atom_op_spec(clause_name!("="), None, op_dir);
HeapCellValue::Atom(clause_name!("="), spec)
}
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, op_dir);
HeapCellValue::Atom(clause_name!("<"), spec)
}
};
&BuiltInClauseType::Read => {
match machine_st.read(
current_input_stream.clone(),
- indices.atom_tbl.clone(),
- &indices.op_dir,
+ machine_st.atom_tbl.clone(),
+ op_dir,
) {
Ok(offset) => {
let addr = machine_st[temp_v!(1)];
}
Err(ParserError::UnexpectedEOF) => {
let addr = machine_st[temp_v!(1)];
- let eof = clause_name!("end_of_file".to_string(),
- indices.atom_tbl);
+ let eof = clause_name!("end_of_file".to_string(), machine_st.atom_tbl);
+
let atom = machine_st.heap.to_unifiable(
HeapCellValue::Atom(eof, None)
);
+
machine_st.unify(addr, atom);
}
Err(e) => {
let h = machine_st.heap.h();
let stub = MachineError::functor_stub(clause_name!("read"), 1);
+
let err = MachineError::syntax_error(h, e);
let err = machine_st.error_form(err, stub);
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::Functor => {
- machine_st.try_functor(&indices)?;
+ machine_st.try_functor(op_dir)?;
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::NotEq => {
}
}
- fn compile_hook(
+ fn call_clause_type(
&mut self,
machine_st: &mut MachineState,
- hook: &CompileTimeHook,
+ key: PredicateKey,
+ code_dir: &CodeDir,
+ op_dir: &OpDir,
+ current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
- machine_st.cp = LocalCodePtr::TopLevel(0, 0);
+ let (name, arity) = key;
- machine_st.num_of_args = hook.arity();
- machine_st.b0 = machine_st.b;
+ match ClauseType::from(name.clone(), arity, None) {
+ ClauseType::BuiltIn(built_in) => {
+ machine_st.setup_built_in_call(built_in.clone());
+ self.call_builtin(
+ machine_st,
+ &built_in,
+ code_dir,
+ op_dir,
+ current_input_stream,
+ current_output_stream,
+ )?;
+ }
+ ClauseType::CallN => {
+ machine_st.handle_internal_call_n(arity);
+
+ if machine_st.fail {
+ return Ok(());
+ }
- machine_st.p = match hook {
- CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
- CodePtr::Local(LocalCodePtr::UserTermExpansion(0))
+ machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
}
- CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
- CodePtr::Local(LocalCodePtr::UserGoalExpansion(0))
+ ClauseType::Inlined(inlined) => {
+ machine_st.execute_inlined(&inlined);
+
+ if machine_st.last_call {
+ machine_st.p = CodePtr::Local(machine_st.cp);
+ }
}
- };
+ ClauseType::Op(..) | ClauseType::Named(..) => {
+ if let Some(idx) = code_dir.get(&(name.clone(), arity)) {
+ self.context_call(machine_st, name, arity, idx)?;
+ } else {
+ return Err(machine_st.throw_undefined_error(name, arity));
+ }
+ }
+ ClauseType::System(_) => {
+ let name = functor!(clause_name(name));
+ let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
+
+ return Err(machine_st.error_form(
+ MachineError::type_error(
+ machine_st.heap.h(),
+ ValidType::Callable,
+ name
+ ),
+ stub,
+ ));
+ }
+ }
Ok(())
}
&mut self,
machine_st: &mut MachineState,
arity: usize,
- indices: &mut IndexStore,
+ code_dir: &CodeDir,
+ op_dir: &OpDir,
current_input_stream: &mut Stream,
current_output_stream: &mut Stream,
) -> CallResult {
- if let Some((name, arity)) = machine_st.setup_call_n(arity) {
- match ClauseType::from(name.clone(), arity, None) {
- ClauseType::BuiltIn(built_in) => {
- machine_st.setup_built_in_call(built_in.clone());
- self.call_builtin(
- machine_st,
- &built_in,
- indices,
- current_input_stream,
- current_output_stream,
- )?;
- }
- ClauseType::CallN => {
- machine_st.handle_internal_call_n(arity);
-
- if machine_st.fail {
- return Ok(());
- }
-
- machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
- }
- ClauseType::Inlined(inlined) => {
- machine_st.execute_inlined(&inlined);
-
- if machine_st.last_call {
- machine_st.p = CodePtr::Local(machine_st.cp);
- }
- }
- ClauseType::Op(..) | ClauseType::Named(..) => {
- let module = name.owning_module();
-
- if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
- self.context_call(machine_st, name, arity, idx, indices)?;
- } else {
- try_in_situ(machine_st, name, arity, indices, machine_st.last_call)?;
- }
- }
- ClauseType::Hook(_) | ClauseType::System(_) => {
- let name = functor!(clause_name(name));
- let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
-
- return Err(machine_st.error_form(
- MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name),
- stub,
- ));
- }
- };
+ if let Some(key) = machine_st.setup_call_n(arity) {
+ self.call_clause_type(
+ machine_st,
+ key,
+ code_dir,
+ op_dir,
+ current_input_stream,
+ current_output_stream,
+ )?;
}
Ok(())
machine_st: &mut MachineState,
name: ClauseName,
arity: usize,
- idx: CodeIndex,
- indices: &mut IndexStore,
+ idx: &CodeIndex,
) -> CallResult {
- self.prev_policy
- .context_call(machine_st, name, arity, idx, indices)?;
+ self.prev_policy.context_call(machine_st, name, arity, idx)?;//, indices)?;
self.increment(machine_st)
}
&mut self,
machine_st: &mut MachineState,
ct: &BuiltInClauseType,
- indices: &mut IndexStore,
+ code_dir: &CodeDir,
+ op_dir: &OpDir,
current_input_stream: &mut Stream,
current_output_stream: &mut Stream,
) -> CallResult {
self.prev_policy.call_builtin(
machine_st,
ct,
- indices,
+ code_dir,
+ op_dir,
current_input_stream,
current_output_stream
)?;
&mut self,
machine_st: &mut MachineState,
arity: usize,
- indices: &mut IndexStore,
+ code_dir: &CodeDir,
+ op_dir: &OpDir,
current_input_stream: &mut Stream,
current_output_stream: &mut Stream,
) -> CallResult {
self.prev_policy.call_n(
machine_st,
arity,
- indices,
+ code_dir,
+ op_dir,
current_input_stream,
current_output_stream,
)?;
use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
+use crate::indexing::*;
use crate::instructions::*;
use crate::machine::INTERRUPT;
use crate::machine::attributed_variables::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
+use crate::machine::partial_string::*;
use crate::machine::stack::*;
use crate::machine::streams::*;
use crate::ordered_float::*;
use std::convert::TryFrom;
use std::rc::Rc;
-macro_rules! try_or_fail {
- ($s:ident, $e:expr) => {{
- match $e {
- Ok(val) => val,
- Err(msg) => {
- $s.throw_exception(msg);
- return;
- }
- }
- }};
-}
-
impl MachineState {
pub(crate)
fn new() -> Self {
MachineState {
+ atom_tbl: TabledData::new(Rc::new("".to_owned())),
s: HeapPtr::default(),
p: CodePtr::default(),
b: 0,
}
}
- pub(crate)
- fn with_small_heap() -> Self {
- MachineState {
- s: HeapPtr::default(),
- p: CodePtr::default(),
- b: 0,
- b0: 0,
- e: 0,
- num_of_args: 0,
- cp: LocalCodePtr::default(),
- attr_var_init: AttrVarInitializer::new(0, 0),
- fail: false,
- heap: Heap::new(),
- mode: MachineMode::Write,
- stack: Stack::new(),
- registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used.
- trail: vec![],
- tr: 0,
- hb: 0,
- block: 0,
- ball: Ball::new(),
- lifted_heap: Heap::new(),
- interms: vec![Number::default(); 0],
- last_call: false,
- heap_locs: HeapVarDict::new(),
- flags: MachineFlags::default(),
- at_end_of_expansion: false
- }
- }
-
#[inline]
pub fn machine_flags(&self) -> MachineFlags {
self.flags
}
pub(super)
- fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
- match instr {
- &IndexingInstruction::SwitchOnTerm(arg, v, c, l, s) => {
- let addr = self[temp_v!(arg)];
- let addr = self.store(self.deref(addr));
+ fn execute_indexing_instr(
+ &mut self,
+ indexing_lines: &Vec<IndexingLine>,
+ call_policy: &mut Box<dyn CallPolicy>,
+ ) {
+ let mut index = 0;
+ let addr =
+ match &indexing_lines[0] {
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => {
+ self.store(self.deref(self[temp_v!(arg)]))
+ }
+ _ => {
+ unreachable!()
+ }
+ };
- let offset = match addr {
- Addr::Stream(_) | Addr::TcpListener(_) => {
- 0
- }
- Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => {
- v
- }
- Addr::PStrLocation(..) => {
- l
- }
- Addr::Char(_) | Addr::Con(_) | Addr::CutPoint(_) |
- Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
- c
- }
- Addr::Lis(_) => {
- l
- }
- Addr::Str(_) => {
- s
- }
- };
+ loop {
+ match &indexing_lines[index] {
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, c, l, s)) => {
+ let offset = match addr {
+ Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
+ IndexingCodePtr::Fail
+ }
+ Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => {
+ IndexingCodePtr::External(v)
+ }
+ Addr::PStrLocation(..) => {
+ l
+ }
+ Addr::Char(_) | Addr::Con(_) | Addr::CutPoint(_) |
+ Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
+ c
+ }
+ Addr::Lis(_) => {
+ l
+ }
+ Addr::Str(_) => {
+ s
+ }
+ };
- match offset {
- 0 => self.fail = true,
- o => self.p += o,
- };
- }
- &IndexingInstruction::SwitchOnConstant(arg, _, ref hm) => {
- let addr = self[temp_v!(arg)];
- let addr = self.store(self.deref(addr));
+ match offset {
+ IndexingCodePtr::Fail => {
+ self.fail = true;
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ self.p += o;
+ break;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
+ };
+ }
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
+ let offset =
+ match addr.as_constant_index(&self) {
+ Some(c) => {
+ match hm.get(&c) {
+ Some(offset) => *offset,
+ _ => IndexingCodePtr::Fail,
+ }
+ }
+ None => {
+ IndexingCodePtr::Fail
+ }
+ };
- let offset =
- match addr.as_constant_index(&self) {
- Some(c) => {
- match hm.get(&c) {
- Some(offset) => *offset,
- _ => 0,
+ match offset {
+ IndexingCodePtr::Fail => {
+ self.fail = true;
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ self.p += o;
+ break;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
+ };
+ }
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
+ let offset = match addr {
+ Addr::Str(s) => {
+ if let &HeapCellValue::NamedStr(arity, ref name, _) = &self.heap[s] {
+ match hm.get(&(name.clone(), arity)) {
+ Some(offset) => *offset,
+ _ => IndexingCodePtr::Fail
+ }
+ } else {
+ IndexingCodePtr::Fail
}
}
- None => {
- 0
+ _ => {
+ IndexingCodePtr::Fail
}
};
- match offset {
- 0 => self.fail = true,
- o => self.p += o,
- };
- }
- &IndexingInstruction::SwitchOnStructure(arg, _, ref hm) => {
- let a1 = self.registers[arg];
- let addr = self.store(self.deref(a1));
-
- let offset = match addr {
- Addr::Str(s) => {
- if let &HeapCellValue::NamedStr(arity, ref name, _) = &self.heap[s] {
- match hm.get(&(name.clone(), arity)) {
- Some(offset) => *offset,
- _ => 0,
- }
- } else {
- 0
+ match offset {
+ IndexingCodePtr::Fail => {
+ self.fail = true;
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ self.p += o;
+ break;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
}
}
- _ => {
- 0
+ }
+ &IndexingLine::IndexedChoice(ref instrs) => {
+ if let LocalCodePtr::DirEntry(p) = self.p.local() {
+ self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(p, index, 0));
+ } else {
+ unreachable!()
}
- };
- match offset {
- 0 => self.fail = true,
- o => self.p += o,
- };
+ self.execute_indexed_choice_instr(instrs.first().unwrap(), call_policy);
+ break;
+ }
}
};
}
Some((name, arity + narity - 1))
}
- pub(super) fn unwind_stack(&mut self) {
+ pub(super)
+ fn unwind_stack(&mut self) {
self.b = self.block;
self.fail = true;
}
- pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool {
+ pub(crate)
+ fn is_cyclic_term(&self, addr: Addr) -> bool {
let mut seen = IndexSet::new();
let mut fail = false;
let mut iter = self.pre_order_iter(addr);
+ let is_composite = |addr: &Addr| {
+ match *addr {
+ Addr::Str(_) | Addr::Lis(_) | Addr::PStrLocation(..) => {
+ true
+ }
+ _ => {
+ false
+ }
+ }
+ };
+
loop {
if let Some(addr) = iter.stack().last() {
- if !seen.contains(addr) {
- seen.insert(*addr);
- } else {
- fail = true;
- break;
+ if is_composite(addr) {
+ if !seen.contains(addr) {
+ seen.insert(*addr);
+ } else {
+ fail = true;
+ break;
+ }
}
}
}
pub(super)
- fn try_functor(&mut self, indices: &IndexStore) -> CallResult {
+ fn try_functor(&mut self, op_dir: &OpDir) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("functor"), 3);
let a1 = self.store(self.deref(self[temp_v!(1)]));
name.clone(),
arity,
spec,
- &indices.op_dir,
+ &op_dir,
);
self.try_functor_compound_case(name, arity, spec)
clause_name!("."),
2,
None,
- &indices.op_dir,
+ &op_dir,
);
self.try_functor_compound_case(clause_name!("."), 2, spec)
name,
arity as usize,
spec,
- &indices.op_dir,
+ &op_dir,
a1.as_var().unwrap(),
);
} else {
}
Addr::Char(c) => {
self.try_functor_fabricate_struct(
- clause_name!(c.to_string(), indices.atom_tbl),
+ clause_name!(c.to_string(), self.atom_tbl),
arity as usize,
None,
- &indices.op_dir,
+ &op_dir,
a1.as_var().unwrap(),
);
}
call_policy.call_builtin(
self,
ct,
- indices,
+ &indices.code_dir,
+ &indices.op_dir,
current_input_stream,
current_output_stream,
)
),
&ClauseType::CallN => try_or_fail!(
self,
- call_policy.call_n(self, arity, indices, current_input_stream, current_output_stream)
+ call_policy.call_n(
+ self,
+ arity,
+ &indices.code_dir,
+ &indices.op_dir,
+ current_input_stream,
+ current_output_stream,
+ )
),
- &ClauseType::Hook(ref hook) => try_or_fail!(self, call_policy.compile_hook(self, hook)),
&ClauseType::Inlined(ref ct) => {
self.execute_inlined(ct);
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
try_or_fail!(
self,
- call_policy.context_call(self, name.clone(), arity, idx.clone(), indices)
+ call_policy.context_call(self, name.clone(), arity, idx)
)
}
&ClauseType::System(ref ct) => try_or_fail!(
self.b0 = self.b;
self.p += offset;
}
+ &ControlInstruction::RevJmpBy(offset) => {
+ self.p -= offset;
+ }
&ControlInstruction::Proceed => {
self.p = CodePtr::Local(self.cp);
}
}
self.hb = self.heap.h();
- self.p += offset;
+ self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset));
}
&IndexedChoiceInstruction::Retry(l) => {
try_or_fail!(self, call_policy.retry(self, l));
};
}
- pub(super) fn execute_choice_instr(
+ pub(super)
+ fn execute_choice_instr(
&mut self,
instr: &ChoiceInstruction,
call_policy: &mut Box<dyn CallPolicy>,
let mut call_policy = DefaultCallPolicy {};
try_or_fail!(self, call_policy.retry_me_else(self, offset))
}
- &ChoiceInstruction::DefaultTrustMe => {
+ &ChoiceInstruction::DefaultTrustMe(_) => {
let mut call_policy = DefaultCallPolicy {};
try_or_fail!(self, call_policy.trust_me(self))
}
&ChoiceInstruction::RetryMeElse(offset) => {
try_or_fail!(self, call_policy.retry_me_else(self, offset))
}
- &ChoiceInstruction::TrustMe => {
+ &ChoiceInstruction::TrustMe(_) => {
try_or_fail!(self, call_policy.trust_me(self))
}
}
}
}
}
-
- pub fn reset(&mut self) {
- self.stack.drop_in_place();
-
- self.hb = 0;
- self.e = 0;
- self.b = 0;
- self.b0 = 0;
- self.s = HeapPtr::default();
- self.tr = 0;
- self.p = CodePtr::default();
- self.cp = LocalCodePtr::default();
- self.attr_var_init.reset();
- self.num_of_args = 0;
-
- self.fail = false;
- self.trail.clear();
- self.heap.clear();
- self.mode = MachineMode::Write;
- self.registers = vec![Addr::HeapCell(0); MAX_ARITY + 1]; // self.registers[0] is never used.
- self.block = 0;
-
- self.ball.reset();
- self.heap_locs.clear();
- self.lifted_heap.clear();
- }
}
use crate::clause_types::*;
use crate::forms::*;
-use crate::heap_print::*;
use crate::instructions::*;
use crate::machine::heap::*;
+use crate::machine::loader::*;
+use crate::machine::term_stream::{LiveTermStream, LoadStatePayload, TermStream};
use crate::read::*;
mod attributed_variables;
pub(super) mod code_repo;
pub mod code_walker;
-pub mod compile;
+mod compile;
mod copier;
-mod dynamic_database;
pub mod heap;
+mod load_state;
+mod loader;
pub mod machine_errors;
pub mod machine_indices;
pub(super) mod machine_state;
-pub mod modules;
pub mod partial_string;
+mod preprocessor;
mod raw_block;
mod stack;
pub(crate) mod streams;
-pub(super) mod term_expansion;
-pub mod toplevel;
+mod term_stream;
#[macro_use]
mod arithmetic_ops;
mod machine_state_impl;
mod system_calls;
-use crate::machine::attributed_variables::*;
-use crate::machine::code_repo::*;
+//use crate::machine::attributed_variables::*;
use crate::machine::compile::*;
+use crate::machine::code_repo::*;
+// use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
-use crate::machine::modules::*;
use crate::machine::streams::*;
-use crate::machine::toplevel::*;
use crate::indexmap::IndexMap;
-use std::collections::VecDeque;
-use std::convert::TryFrom;
+//use std::convert::TryFrom;
use std::fs::File;
use std::mem;
-use std::ops::Index;
use std::path::PathBuf;
-use std::rc::Rc;
use std::sync::atomic::AtomicBool;
#[derive(Debug)]
}
#[derive(Debug)]
-pub struct Machine {
- pub(super) machine_st: MachineState,
- pub(super) inner_heap: Heap,
- pub(super) policies: MachinePolicies,
- pub(super) indices: IndexStore,
- pub(super) code_repo: CodeRepo,
- pub(super) toplevel_idx: usize,
- pub(super) current_input_stream: Stream,
- pub(super) current_output_stream: Stream,
+pub(super) struct LoadContext {
+ pub(super) path: PathBuf,
+ pub(super) stream: Stream,
+ pub(super) module: ClauseName,
}
-impl Index<LocalCodePtr> for CodeRepo {
- type Output = Line;
-
- fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
- match ptr {
- LocalCodePtr::InSituDirEntry(p) => &self.in_situ_code[p],
- LocalCodePtr::TopLevel(_, p) => &self.cached_query[p],
- LocalCodePtr::DirEntry(p) => &self.code[p],
- LocalCodePtr::UserGoalExpansion(p) => &self.goal_expanders[p],
- LocalCodePtr::UserTermExpansion(p) => &self.term_expanders[p],
+impl LoadContext {
+ #[inline]
+ fn new(path: &str, stream: Stream) -> Self {
+ LoadContext {
+ path: PathBuf::from(path),
+ stream,
+ module: clause_name!("user"),
}
}
}
-impl Index<LocalCodePtr> for Machine {
- type Output = Line;
-
- fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
- &self.code_repo[ptr]
- }
+#[derive(Debug)]
+pub struct Machine {
+ pub(super) machine_st: MachineState,
+ pub(super) inner_heap: Heap,
+ pub(super) policies: MachinePolicies,
+ pub(super) indices: IndexStore,
+ pub(super) code_repo: CodeRepo,
+ pub(super) user_input: Stream,
+ pub(super) user_output: Stream,
+ pub(super) load_contexts: Vec<LoadContext>,
}
-impl SubModuleUser for IndexStore {
- fn atom_tbl(&self) -> TabledData<Atom> {
- self.atom_tbl.clone()
- }
-
- fn op_dir(&mut self) -> &mut OpDir {
- &mut self.op_dir
- }
-
- fn get_code_index(&self, key: PredicateKey, module_name: ClauseName) -> Option<CodeIndex> {
- match module_name.as_str() {
- "user" => {
- self.code_dir.get(&key).cloned()
- }
- _ => {
- match self.in_situ_module_dir.get(&module_name) {
- Some(ref module_stub) => {
- match module_stub.in_situ_code_dir.get(&key) {
- Some(p) => {
- return Some(CodeIndex::new(
- IndexPtr::InSituDirEntry(*p),
- module_name.clone()
- ));
- }
- None => {
- }
- }
- }
- None => {
- }
- };
-
- self.modules
- .get(&module_name)
- .and_then(|ref module| {
- module.code_dir.get(&key).cloned()
- })
- }
- }
- }
-
- fn remove_code_index(&mut self, key: PredicateKey) {
- self.code_dir.remove(&key);
- }
-
- 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 !code_idx.is_undefined() {
- match (name.as_str(), arity) {
- ("term_expansion", 2) => {
- }
- ("goal_expansion", 2) => {
- }
- _ => {
- println!("Warning: overwriting {}/{}", &name, arity);
- }
- }
- }
-
- let (p, module_name) = idx.0.borrow().clone();
- set_code_index!(code_idx, p, module_name);
- return;
- }
-
- self.code_dir.insert((name.clone(), arity), idx.clone());
- }
+#[inline]
+fn current_dir() -> std::path::PathBuf {
+ let mut path_buf = std::path::PathBuf::from(file!());
- fn use_qualified_module(
- &mut self,
- code_repo: &mut CodeRepo,
- _: MachineFlags,
- submodule: &Module,
- exports: &Vec<ModuleExport>,
- ) -> Result<(), SessionError> {
- use_qualified_module(self, submodule, exports)?;
- submodule
- .dump_expansions(code_repo)
- .map_err(SessionError::from)
- }
-
- fn use_module(
- &mut self,
- code_repo: &mut CodeRepo,
- _: MachineFlags,
- submodule: &Module,
- ) -> Result<(), SessionError> {
- use_module(self, submodule)?;
-
- if !submodule.inserted_expansions {
- submodule
- .dump_expansions(code_repo)
- .map_err(SessionError::from)
- } else {
- Ok(())
- }
- }
+ path_buf.pop();
+ path_buf
}
include!(concat!(env!("OUT_DIR"), "/libraries.rs"));
-static TOPLEVEL: &str = include_str!("../toplevel.pl");
-
impl Machine {
+ /*
fn compile_special_forms(&mut self)
{
let verify_attrs_src = ListingSource::User;
}
}
- fn compile_top_level(&mut self) -> Result<(), SessionError>
- {
- self.toplevel_idx = self.code_repo.code.len();
-
- let top_lvl_src = ListingSource::User;
-
- compile_user_module(
- self,
- Stream::from(TOPLEVEL),
- true,
- top_lvl_src,
- );
-
- if let Some(module) = self.indices.take_module(clause_name!("$toplevel")) {
- self.indices.use_module(
- &mut self.code_repo,
- self.machine_st.flags,
- &module,
- )?;
-
- Ok(self.indices.insert_module(module))
- } else {
- let err = ExistenceError::ModuleSource(ModuleSource::File(
- clause_name!("$toplevel"),
- ));
-
- Err(SessionError::ExistenceError(err))
- }
- }
-
fn compile_scryerrc(&mut self) {
let mut path = match dirs_next::home_dir() {
Some(path) => path,
path.to_path_buf(),
);
- compile_user_module(self, file_src, true, rc_src);
+ compile_user_module(self, file_src, rc_src);
}
}
-
+*/
#[cfg(test)]
pub fn reset(&mut self) {
self.current_input_stream = readline::input_stream();
self.machine_st.reset();
}
- pub fn run_init_code(&mut self, code: Code) -> bool {
- let old_machine_st = self.sink_to_snapshot();
- self.machine_st.reset();
+ fn run_module_predicate(&mut self, module_name: ClauseName, key: PredicateKey) {
+ if let Some(module) = self.indices.modules.get(&module_name) {
+ if let Some(ref code_index) = module.code_dir.get(&key) {
+ let p = code_index.local().unwrap();
+
+ self.machine_st.cp = LocalCodePtr::Halt;
+ self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+
+ return self.run_query();
+ }
+ }
+
+ unreachable!();
+ }
+
+ fn load_file(&mut self, path: String, stream: Stream) {
+ self.machine_st[temp_v!(1)] = Addr::Stream(
+ self.machine_st.heap.push(HeapCellValue::Stream(
+ stream,
+ ))
+ );
+
+ self.machine_st[temp_v!(2)] = Addr::Con(
+ self.machine_st.heap.push(HeapCellValue::Atom(
+ clause_name!(path, self.machine_st.atom_tbl),
+ None,
+ ))
+ );
+
+ self.run_module_predicate(clause_name!("loader"), (clause_name!("file_load"), 2));
+ }
+
+ fn load_top_level(&mut self) {
+ let mut path_buf = current_dir();
+ path_buf.push("toplevel.pl");
- self.code_repo.cached_query = code;
- self.run_query();
+ let path = path_buf.to_str().unwrap().to_string();
- let result = self.machine_st.fail;
- self.absorb_snapshot(old_machine_st);
+ self.load_file(path, Stream::from(include_str!("../toplevel.pl")));
- !result
+ if let Some(toplevel) = self.indices.modules.get(&clause_name!("$toplevel")) {
+ load_module(
+ &mut self.indices.code_dir,
+ &mut self.indices.op_dir,
+ &mut self.indices.meta_predicates,
+ toplevel,
+ );
+ } else {
+ unreachable!()
+ }
+ }
+
+ fn load_special_forms(&mut self) {
+ let mut path_buf = current_dir();
+ path_buf.push("machine/attributed_variables.pl");
+
+ bootstrapping_compile(
+ Stream::from(include_str!("attributed_variables.pl")),
+ self,
+ ListingSource::from_file_and_path(
+ clause_name!("attributed_variables"),
+ path_buf,
+ ),
+ ).unwrap();
+
+ let mut path_buf = current_dir();
+ path_buf.push("machine/project_attributes.pl");
+
+ bootstrapping_compile(
+ Stream::from(include_str!("project_attributes.pl")),
+ self,
+ ListingSource::from_file_and_path(
+ clause_name!("project_attributes"),
+ path_buf,
+ ),
+ ).unwrap();
+
+ if let Some(module) = self.indices.modules.get(&clause_name!("$atts")) {
+ if let Some(code_index) = module.code_dir.get(&(clause_name!("driver"), 2)) {
+ self.machine_st.attr_var_init.verify_attrs_loc = code_index.local().unwrap();
+ }
+ }
+
+ if let Some(module) = self.indices.modules.get(&clause_name!("$project_atts")) {
+ if let Some(code_index) = module.code_dir.get(&(clause_name!("driver"), 2)) {
+ self.machine_st.attr_var_init.project_attrs_loc = code_index.local().unwrap();
+ }
+ }
}
pub fn run_top_level(&mut self) {
}
let list_addr = Addr::HeapCell(self.machine_st.heap.to_list(arg_pstrs.into_iter()));
+
self.machine_st[temp_v!(1)] = list_addr;
- loop {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx));
- self.run_query();
- }
+ // WAS:
+ // self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("$repl"), 1));
+
+ self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("repl"), 0));
}
- pub fn new(current_input_stream: Stream, current_output_stream: Stream) -> Self
+ pub fn new(user_input: Stream, user_output: Stream) -> Self
{
use crate::ref_thread_local::RefThreadLocal;
policies: MachinePolicies::new(),
indices: IndexStore::new(),
code_repo: CodeRepo::new(),
- toplevel_idx: 0,
- current_input_stream,
- current_output_stream,
+ user_input,
+ user_output,
+ load_contexts: vec![],
};
- let atom_tbl = wam.indices.atom_tbl.clone();
+ let mut lib_path = current_dir();
- wam.indices.add_term_and_goal_expansion_indices();
+ lib_path.pop();
+ lib_path.push("lib");
- compile_listing(
+ bootstrapping_compile(
+ Stream::from(LIBRARIES.borrow()["ops_and_meta_predicates"]),
&mut wam,
- Stream::from(LIBRARIES.borrow()["builtins"]),
- default_index_store!(atom_tbl.clone()),
- true,
- ListingSource::User,
- );
+ ListingSource::from_file_and_path(
+ clause_name!("ops_and_meta_predicates.pl"),
+ lib_path.clone(),
+ ),
+ ).unwrap();
- wam.compile_special_forms();
-
- compile_user_module(
- &mut wam,
- Stream::from(LIBRARIES.borrow()["error"]),
- true,
- ListingSource::User,
- );
-
- compile_user_module(
- &mut wam,
- Stream::from(LIBRARIES.borrow()["pairs"]),
- true,
- ListingSource::User,
- );
-
- compile_user_module(
+ bootstrapping_compile(
+ Stream::from(LIBRARIES.borrow()["builtins"]),
&mut wam,
- Stream::from(LIBRARIES.borrow()["lists"]),
- true,
- ListingSource::User,
- );
+ ListingSource::from_file_and_path(
+ clause_name!("builtins.pl"),
+ lib_path.clone(),
+ ),
+ ).unwrap();
+
+ if let Some(builtins) = wam.indices.modules.get(&clause_name!("builtins")) {
+ load_module(
+ &mut wam.indices.code_dir,
+ &mut wam.indices.op_dir,
+ &mut wam.indices.meta_predicates,
+ builtins,
+ );
+ } else {
+ unreachable!()
+ }
- compile_user_module(
- &mut wam,
- Stream::from(LIBRARIES.borrow()["iso_ext"]),
- true,
- ListingSource::User,
- );
+ lib_path.pop(); // remove the "lib" at the end
- compile_user_module(
+ bootstrapping_compile(
+ Stream::from(include_str!("../term_and_goal_expansion.pl")),
&mut wam,
- Stream::from(LIBRARIES.borrow()["si"]),
- true,
- ListingSource::User,
- );
-
- compile_user_module(
+ ListingSource::from_file_and_path(
+ clause_name!("term_and_goal_expansion.pl"),
+ lib_path.clone(),
+ ),
+ ).unwrap();
+
+ bootstrapping_compile(
+ Stream::from(include_str!("../loader.pl")),
&mut wam,
- Stream::from(LIBRARIES.borrow()["charsio"]),
- true,
- ListingSource::User,
- );
-
- if wam.compile_top_level().is_err() {
- panic!("Loading '$toplevel' module failed");
+ ListingSource::from_file_and_path(
+ clause_name!("loader.pl"),
+ lib_path.clone(),
+ ),
+ ).unwrap();
+
+ if let Some(loader) = wam.indices.modules.get(&clause_name!("loader")) {
+ load_module(
+ &mut wam.indices.code_dir,
+ &mut wam.indices.op_dir,
+ &mut wam.indices.meta_predicates,
+ loader,
+ );
+ } else {
+ unreachable!()
}
- wam.compile_scryerrc();
+ wam.load_special_forms();
+ wam.load_top_level();
wam.configure_streams();
wam
}
pub fn configure_streams(&mut self) {
- self.current_input_stream.options.alias = Some(clause_name!("user_input"));
+ self.user_input.options.alias = Some(clause_name!("user_input"));
self.indices.stream_aliases.insert(
clause_name!("user_input"),
- self.current_input_stream.clone(),
+ self.user_input.clone(),
);
self.indices.streams.insert(
- self.current_input_stream.clone()
+ self.user_input.clone()
);
- self.current_output_stream.options.alias = Some(clause_name!("user_output"));
+ self.user_output.options.alias = Some(clause_name!("user_output"));
self.indices.stream_aliases.insert(
clause_name!("user_output"),
- self.current_output_stream.clone(),
+ self.user_output.clone(),
);
self.indices.streams.insert(
- self.current_output_stream.clone()
+ self.user_output.clone()
);
}
- #[inline]
- pub fn machine_flags(&self) -> MachineFlags {
- self.machine_st.flags
- }
-
- pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError> {
- for (key, idx) in &indices.code_dir {
- match ClauseType::from(key.0.clone(), key.1, None) {
- ClauseType::Named(..) | ClauseType::Op(..) => {}
- _ => {
- // ensure we don't try to overwrite the name/arity of a builtin.
- let err_str = format!("{}/{}", key.0, key.1);
- let err_str = clause_name!(err_str, self.indices.atom_tbl());
-
- return Err(SessionError::CannotOverwriteBuiltIn(err_str));
- }
- };
-
- if let Some(ref existing_idx) = self.indices.code_dir.get(&key) {
- // ensure we don't try to overwrite an existing predicate from a different module.
- if !existing_idx.is_undefined() && !idx.is_undefined() {
- // allow the overwriting of user-level predicates by all other predicates.
- if existing_idx.module_name().as_str() == "user" {
- continue;
- }
-
- if existing_idx.module_name() != idx.module_name() {
- let err_str = format!(
- "{}/{} from module {}",
- key.0,
- key.1,
- existing_idx.module_name().as_str()
- );
- let err_str = clause_name!(err_str, self.indices.atom_tbl());
-
- return Err(SessionError::CannotOverwriteImport(err_str));
- }
- }
- }
- }
-
- Ok(())
- }
-
- pub(crate) fn add_batched_code_dir(&mut self, code_dir: CodeDir) {
- // error detection has finished, so update the master index of keys.
- for (key, idx) in code_dir {
- if let Some(ref master_idx) = self.indices.code_dir.get(&key) {
- // ensure we don't double borrow if master_idx == idx.
- // we don't need to modify anything in that case.
- if !Rc::ptr_eq(&master_idx.0, &idx.0) {
- set_code_index!(master_idx, idx.0.borrow().0, idx.module_name());
- }
-
- continue;
- }
-
- self.indices.code_dir.insert(key, idx);
- }
- }
-
- #[inline]
- pub(crate) fn add_batched_ops(&mut self, op_dir: OpDir) {
- self.indices.op_dir.extend(op_dir.into_iter());
- }
-
- pub(crate) fn add_in_situ_module_dir(&mut self, module_dir: ModuleDir) {
- for (module_name, module_skeleton) in module_dir {
- match self.indices.modules.get_mut(&module_name) {
- Some(ref mut module) => {
- for (key, idx) in module_skeleton.code_dir {
- if let Some(existing_idx) = module.code_dir.get(&key) {
- set_code_index!(existing_idx, idx.0.borrow().0, module_name.clone());
- } else {
- module.code_dir.insert(key, idx);
- }
- }
- }
- None => {
- self.add_module(module_skeleton);
- }
- }
- }
- }
-
- #[inline]
- pub fn add_module(&mut self, module: Module) {
- self.indices
- .modules
- .insert(module.module_decl.name.clone(), module);
- }
-
fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
let h = self.machine_st.heap.h();
return;
}
- fn extract_module_export_list(&mut self) -> Result<Vec<ModuleExport>, ParserError>
- {
- let mut export_list = self.machine_st[temp_v!(2)].clone();
- let mut exports = vec![];
-
- while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
- match &self.machine_st.heap[l] {
- &HeapCellValue::Addr(Addr::Str(s)) => {
- match &self.machine_st.heap[s] {
- HeapCellValue::NamedStr(arity, ref name, _)
- if *arity == 2 && name.as_str() == "/" => {
- let name = match &self.machine_st.heap[s+1] {
- &HeapCellValue::Atom(ref name, _) =>
- name.clone(),
- _ =>
- unreachable!()
- };
-
- let arity = match &self.machine_st.heap[s+2] {
- &HeapCellValue::Integer(ref arity) =>
- arity.to_usize().unwrap(),
- &HeapCellValue::Addr(Addr::Fixnum(n)) =>
- usize::try_from(n).unwrap(),
- _ =>
- unreachable!()
- };
-
- exports.push(ModuleExport::PredicateKey((name, arity)));
- }
- HeapCellValue::NamedStr(arity, ref name, _)
- if *arity == 3 && name.as_str() == "op" => {
- let name = match &self.machine_st.heap[s+3] {
- &HeapCellValue::Atom(ref name, _) =>
- name.clone(),
- _ =>
- unreachable!()
- };
-
- let spec = match &self.machine_st.heap[s+2] {
- &HeapCellValue::Atom(ref name, _) =>
- name.clone(),
- _ =>
- unreachable!()
- };
-
- let prec = match &self.machine_st.heap[s+1] {
- &HeapCellValue::Integer(ref arity) =>
- arity.to_usize().unwrap(),
- &HeapCellValue::Addr(Addr::Fixnum(n)) =>
- usize::try_from(n).unwrap(),
- _ =>
- unreachable!()
- };
-
- exports.push(ModuleExport::OpDecl(to_op_decl(
- prec,
- spec.as_str(),
- name,
- )?));
- }
- _ => unreachable!()
- }
- }
- _ => unreachable!()
- }
-
- export_list = self.machine_st.heap[l+1].as_addr(l+1);
- }
-
- Ok(exports)
- }
-
- fn use_module<ToSource>(&mut self, to_src: ToSource)
- where ToSource: Fn(ClauseName) -> ModuleSource
- {
- // the term expander will overwrite the cached query, so save it here.
- let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
-
- let module_spec = self.machine_st[temp_v!(1)].clone();
- let name = {
- let addr = self.machine_st.store(self.machine_st.deref(module_spec));
-
- match self.machine_st.heap.index_addr(&addr).as_ref() {
- HeapCellValue::Atom(name, _) =>
- name.clone(),
- HeapCellValue::Addr(Addr::Char(c)) =>
- clause_name!(c.to_string(), self.indices.atom_tbl),
- HeapCellValue::Addr(addr @ Addr::PStrLocation(..)) => {
- let mut heap_pstr_iter =
- self.machine_st.heap_pstr_iter(*addr);
- clause_name!(
- heap_pstr_iter.to_string(),
- self.indices.atom_tbl
- )
- }
- _ => unreachable!(),
+ fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
+ match code_ptr {
+ REPLCodePtr::AddDynamicPredicate => {
+ self.add_dynamic_predicate();
}
- };
-
- let load_result = match to_src(name) {
- ModuleSource::Library(name) =>
- if let Some(module) = self.indices.take_module(name.clone()) {
- self.indices.remove_module(clause_name!("user"), &module);
- self.indices.modules.insert(name.clone(), module);
-
- Ok(name)
- } else {
- load_library(self, name, false)
- },
- ModuleSource::File(name) =>
- load_module_from_file(self, PathBuf::from(name.as_str()), false)
- };
-
- let result = load_result.and_then(|name| {
- let module = self.indices.take_module(name.clone()).unwrap();
-
- if !module.is_impromptu_module {
- self.indices.use_module(&mut self.code_repo, self.machine_st.flags, &module)?;
+ REPLCodePtr::AddGoalExpansionClause => {
+ self.add_goal_expansion_clause();
}
-
- Ok(self.indices.insert_module(module))
- });
-
- self.code_repo.cached_query = cached_query;
-
- if let Err(e) = result {
- self.throw_session_error(e, (clause_name!("use_module"), 1));
- }
- }
-
- fn use_qualified_module<ToSource>(&mut self, to_src: ToSource)
- where ToSource: Fn(ClauseName) -> ModuleSource
- {
- // the term expander will overwrite the cached query, so save it here.
- let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
-
- let module_spec = self.machine_st[temp_v!(1)].clone();
- let name = {
- let addr = self.machine_st.store(self.machine_st.deref(module_spec));
-
- match self.machine_st.heap.index_addr(&addr).as_ref() {
- HeapCellValue::Atom(name, _) =>
- name.clone(),
- HeapCellValue::Addr(Addr::Char(c)) =>
- clause_name!(c.to_string(), self.indices.atom_tbl),
- _ =>
- unreachable!(),
+ REPLCodePtr::AddTermExpansionClause => {
+ self.add_term_expansion_clause();
}
- };
-
- let exports = match self.extract_module_export_list() {
- Ok(exports) => exports,
- Err(e) => {
- self.throw_session_error(SessionError::from(e), (clause_name!("use_module"), 2));
- return;
+ REPLCodePtr::ClauseToEvacuable => {
+ self.clause_to_evacuable();
}
- };
-
- let load_result = match to_src(name) {
- ModuleSource::Library(name) =>
- if let Some(module) = self.indices.take_module(name.clone()) {
- self.indices.remove_module(clause_name!("user"), &module);
- self.indices.modules.insert(name.clone(), module);
-
- Ok(name)
- } else {
- load_library(self, name, false)
- },
- ModuleSource::File(name) =>
- load_module_from_file(self, PathBuf::from(name.as_str()), false)
- };
-
- let result = load_result.and_then(|name| {
- let module = self.indices.take_module(name.clone()).unwrap();
-
- if !module.is_impromptu_module {
- self.indices.use_qualified_module(&mut self.code_repo,
- self.machine_st.flags,
- &module,
- &exports)?;
+ REPLCodePtr::ConcludeLoad => {
+ self.conclude_load();
}
-
- Ok(self.indices.insert_module(module))
- });
-
- self.code_repo.cached_query = cached_query;
-
- if let Err(e) = result {
- self.throw_session_error(e, (clause_name!("use_module"), 2));
- }
- }
-
- fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
- match code_ptr {
- REPLCodePtr::CompileBatch => {
- let user_src = ListingSource::User;
-
- let src = readline::input_stream();
- readline::set_prompt(false);
-
- if let EvalSession::Error(e) = compile_user_module(self, src, false, user_src) {
- self.throw_session_error(e, (clause_name!("repl"), 0));
- }
+ REPLCodePtr::PopLoadContext => {
+ self.pop_load_context();
+ }
+ REPLCodePtr::PushLoadContext => {
+ self.push_load_context();
+ }
+ REPLCodePtr::PopLoadStatePayload => {
+ self.pop_load_state_payload();
+ }
+ REPLCodePtr::UseModule => {
+ self.use_module();
+ }
+ REPLCodePtr::LoadCompiledLibrary => {
+ self.load_compiled_library();
+ }
+ REPLCodePtr::DeclareModule => {
+ self.declare_module();
+ }
+ REPLCodePtr::PushLoadStatePayload => {
+ self.push_load_state_payload();
+ }
+ REPLCodePtr::LoadContextSource => {
+ self.load_context_source();
+ }
+ REPLCodePtr::LoadContextFile => {
+ self.load_context_file();
+ }
+ REPLCodePtr::LoadContextDirectory => {
+ self.load_context_directory();
+ }
+ REPLCodePtr::LoadContextModule => {
+ self.load_context_module();
+ }
+ REPLCodePtr::LoadContextStream => {
+ self.load_context_stream();
+ }
+ REPLCodePtr::MetaPredicateProperty => {
+ self.meta_predicate_property();
+ }
+ REPLCodePtr::CompilePendingPredicates => {
+ self.compile_pending_predicates();
+ }
+ REPLCodePtr::UserAssertz => {
+ self.compile_user_assert(AppendOrPrepend::Append);
+ }
+ REPLCodePtr::UserAsserta => {
+ self.compile_user_assert(AppendOrPrepend::Prepend);
+ }
+ REPLCodePtr::UserRetract => {
+ self.retract_user_clause();
}
- REPLCodePtr::UseModule =>
- self.use_module(ModuleSource::Library),
- REPLCodePtr::UseModuleFromFile =>
- self.use_module(ModuleSource::File),
- REPLCodePtr::UseQualifiedModule =>
- self.use_qualified_module(ModuleSource::Library),
- REPLCodePtr::UseQualifiedModuleFromFile =>
- self.use_qualified_module(ModuleSource::File)
}
self.machine_st.p = CodePtr::Local(p);
}
- fn sink_to_snapshot(&mut self) -> MachineState {
- let mut snapshot = MachineState::with_small_heap();
-
- snapshot.hb = self.machine_st.hb;
- snapshot.e = self.machine_st.e;
- snapshot.b = self.machine_st.b;
- snapshot.b0 = self.machine_st.b0;
- snapshot.s = self.machine_st.s.clone();
- snapshot.tr = self.machine_st.tr;
- snapshot.num_of_args = self.machine_st.num_of_args;
-
- snapshot.fail = self.machine_st.fail;
- snapshot.trail = mem::replace(&mut self.machine_st.trail, vec![]);
- snapshot.heap = self.machine_st.heap.take();
- snapshot.mode = self.machine_st.mode;
- snapshot.stack = self.machine_st.stack.take();
- snapshot.registers = mem::replace(&mut self.machine_st.registers, vec![]);
- snapshot.block = self.machine_st.block;
-
- snapshot.ball = self.machine_st.ball.take();
- snapshot.lifted_heap = self.machine_st.lifted_heap.take();
-
- snapshot
- }
-
- fn absorb_snapshot(&mut self, mut snapshot: MachineState) {
- self.machine_st.hb = snapshot.hb;
- self.machine_st.e = snapshot.e;
- self.machine_st.b = snapshot.b;
- self.machine_st.b0 = snapshot.b0;
- self.machine_st.s = snapshot.s;
- self.machine_st.tr = snapshot.tr;
- self.machine_st.num_of_args = snapshot.num_of_args;
-
- self.machine_st.fail = snapshot.fail;
- self.machine_st.trail = mem::replace(&mut snapshot.trail, vec![]);
-
- self.inner_heap = self.machine_st.heap.take();
- self.inner_heap.truncate(0);
-
- self.machine_st.heap = snapshot.heap.take();
- self.machine_st.mode = snapshot.mode;
- self.machine_st.stack = snapshot.stack;
- self.machine_st.registers = mem::replace(&mut snapshot.registers, vec![]);
- self.machine_st.block = snapshot.block;
-
- self.machine_st.ball = snapshot.ball.take();
- self.machine_st.lifted_heap = snapshot.lifted_heap.take();
- }
-
- pub(super) fn run_query(&mut self) {
- self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
- let end_ptr = CodePtr::Local(self.machine_st.cp);
-
- while self.machine_st.p < end_ptr {
+ pub(super)
+ fn run_query(&mut self) {
+ while !self.machine_st.p.is_halt() {
self.machine_st.query_stepper(
&mut self.indices,
&mut self.policies,
&mut self.code_repo,
- &mut self.current_input_stream,
- &mut self.current_output_stream,
+ &mut self.user_input,
+ &mut self.user_output,
);
match self.machine_st.p {
- CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {
- }
CodePtr::REPL(code_ptr, p) => {
- self.handle_toplevel_command(code_ptr, p)
+ self.handle_toplevel_command(code_ptr, p);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
}
- CodePtr::DynamicTransaction(trans_type, p) => {
+ /*
+ CodePtr::DynamicTransaction(_trans_type, _p) => {
// 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.
self.machine_st.fail = false;
+ /*
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
- self.dynamic_transaction(trans_type, p);
+ // self.dynamic_transaction(trans_type, p);
self.code_repo.cached_query = cached_query;
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
break;
}
+ */
+ }
+ */
+ _ => {
+ break;
}
- _ =>
- break
};
}
}
indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &CodeRepo,
- current_input_stream: &mut Stream,
- current_output_stream: &mut Stream,
+ user_input: &mut Stream,
+ user_output: &mut Stream,
) {
match instr {
&Line::Arithmetic(ref arith_instr) => {
code_repo,
&mut policies.call_policy,
&mut policies.cut_policy,
- current_input_stream,
- current_output_stream,
+ user_input,
+ user_output,
control_instr,
)
}
self.execute_fact_instr(&fact_instr);
self.p += 1;
}
- &Line::Indexing(ref indexing_instr) => {
- self.execute_indexing_instr(&indexing_instr)
+ &Line::IndexingCode(ref indexing_lines) => {
+ self.execute_indexing_instr(indexing_lines, &mut policies.call_policy)
}
&Line::IndexedChoice(ref choice_instr) => {
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &CodeRepo,
- current_input_stream: &mut Stream,
- current_output_stream: &mut Stream,
+ user_input: &mut Stream,
+ user_output: &mut Stream,
) {
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
Some(instr) => instr,
indices,
policies,
code_repo,
- current_input_stream,
- current_output_stream,
+ user_input,
+ user_output,
);
}
fn backtrack(&mut self) {
- if self.b > 0 {
- let b = self.b;
+ // if self.b > 0 {
+ let b = self.b;
- self.b0 = self.stack.index_or_frame(b).prelude.b0;
- self.p = CodePtr::Local(self.stack.index_or_frame(b).prelude.bp);
+ self.b0 = self.stack.index_or_frame(b).prelude.b0;
+ self.p = CodePtr::Local(self.stack.index_or_frame(b).prelude.bp);
- if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
- self.fail = p == 0;
- } else {
- self.fail = false;
- }
+ /*
+ if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
+ self.fail = p == 0;
} else {
+ */
+ self.fail = false;
+ // }
+ /*} else {
self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
- }
+ }*/
}
fn check_machine_index(&mut self, code_repo: &CodeRepo) -> bool {
match self.p {
- CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < code_repo.code.len() => {}
- CodePtr::Local(LocalCodePtr::UserTermExpansion(p))
- if p < code_repo.term_expanders.len() => {}
- CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.fail = true,
- CodePtr::Local(LocalCodePtr::UserGoalExpansion(p))
- if p < code_repo.goal_expanders.len() => {}
- CodePtr::Local(LocalCodePtr::UserGoalExpansion(_)) => self.fail = true,
- CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) if p < code_repo.in_situ_code.len() => {
+ CodePtr::Local(LocalCodePtr::DirEntry(p)) |
+ CodePtr::Local(LocalCodePtr::IndexingBuf(p, ..))
+ if p < code_repo.code.len() => {
+ }
+ CodePtr::Local(LocalCodePtr::Halt) | CodePtr::REPL(..) => {
+ return false;
}
- CodePtr::Local(_) | CodePtr::REPL(..) => return false,
+ /*
CodePtr::DynamicTransaction(..) => {
// prevent use of dynamic transactions from
// succeeding in expansions. self.fail will be toggled
self.fail = true;
return false;
}
- _ => {}
+ */
+ _ => {
+ }
}
true
indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &mut CodeRepo,
- current_input_stream: &mut Stream,
- current_output_stream: &mut Stream,
+ user_input: &mut Stream,
+ user_output: &mut Stream,
) -> bool {
loop {
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
indices,
policies,
code_repo,
- current_input_stream,
- current_output_stream,
+ user_input,
+ user_output,
);
if self.fail {
indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &mut CodeRepo,
- current_input_stream: &mut Stream,
- current_output_stream: &mut Stream,
+ user_input: &mut Stream,
+ user_output: &mut Stream,
) {
loop {
self.execute_instr(
indices,
policies,
code_repo,
- current_input_stream,
- current_output_stream,
+ user_input,
+ user_output,
);
if self.fail {
indices,
policies,
code_repo,
- current_input_stream,
- current_output_stream,
+ user_input,
+ user_output,
) {
if self.fail {
break;
+++ /dev/null
-use crate::prolog_parser::ast::*;
-use crate::prolog_parser::tabled_rc::*;
-
-use crate::forms::*;
-use crate::machine::code_repo::*;
-use crate::machine::machine_errors::*;
-use crate::machine::machine_indices::*;
-
-use std::collections::VecDeque;
-use std::mem;
-
-// Module's and related types are defined in forms.
-impl Module {
- pub fn new(
- module_decl: ModuleDecl,
- atom_tbl: TabledData<Atom>,
- listing_src: ListingSource,
- ) -> Self
- {
- Module {
- atom_tbl,
- module_decl,
- term_dir: TermDir::new(),
- user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
- user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
- term_expansions: (Predicate::new(), VecDeque::from(vec![])),
- goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
- local_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
- local_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
- code_dir: CodeDir::new(),
- op_dir: default_op_dir(),
- inserted_expansions: false,
- is_impromptu_module: false,
- listing_src,
- }
- }
-
- pub fn dump_expansions(
- &self,
- code_repo: &mut CodeRepo,
- ) -> Result<(), ParserError> {
- {
- let te = code_repo
- .term_dir
- .entry((clause_name!("term_expansion"), 2))
- .or_insert((Predicate::new(), VecDeque::from(vec![])));
-
- (te.0)
- .0
- .extend((self.user_term_expansions.0).0.iter().cloned());
-
- te.1.extend(self.user_term_expansions.1.iter().cloned());
- }
-
- {
- let ge = code_repo
- .term_dir
- .entry((clause_name!("goal_expansion"), 2))
- .or_insert((Predicate::new(), VecDeque::from(vec![])));
-
- (ge.0)
- .0
- .extend((self.user_goal_expansions.0).0.iter().cloned());
-
- ge.1.extend(self.user_goal_expansions.1.iter().cloned());
- }
-
- code_repo.compile_hook(CompileTimeHook::TermExpansion)?;
- code_repo.compile_hook(CompileTimeHook::GoalExpansion)?;
-
- Ok(())
- }
-
- pub fn add_expansion_record(
- &mut self,
- hook: CompileTimeHook,
- clause: PredicateClause,
- queue: VecDeque<TopLevel>,
- ) {
- match hook {
- CompileTimeHook::TermExpansion | CompileTimeHook::UserTermExpansion => {
- (self.term_expansions.0).0.push(clause);
- self.term_expansions.1.extend(queue.into_iter());
- }
- CompileTimeHook::GoalExpansion | CompileTimeHook::UserGoalExpansion => {
- (self.goal_expansions.0).0.push(clause);
- self.goal_expansions.1.extend(queue.into_iter());
- }
- }
- }
-
- pub fn add_local_expansion(
- &mut self,
- hook: CompileTimeHook,
- clause: PredicateClause,
- queue: VecDeque<TopLevel>,
- ) {
- match hook {
- CompileTimeHook::TermExpansion => {
- (self.local_term_expansions.0).0.push(clause);
- self.local_term_expansions.1.extend(queue.into_iter());
- }
- CompileTimeHook::GoalExpansion => {
- (self.local_goal_expansions.0).0.push(clause);
- self.local_goal_expansions.1.extend(queue.into_iter());
- }
- _ => {}
- }
- }
-
- pub fn take_local_expansions(&mut self) -> Vec<(Predicate, VecDeque<TopLevel>)>
- {
- let term_expansions =
- mem::replace(&mut self.local_term_expansions, (Predicate::new(), VecDeque::new()));
- let goal_expansions =
- mem::replace(&mut self.local_goal_expansions, (Predicate::new(), VecDeque::new()));
-
- vec![term_expansions, goal_expansions]
- }
-}
-
-pub trait SubModuleUser {
- fn atom_tbl(&self) -> TabledData<Atom>;
- fn op_dir(&mut self) -> &mut OpDir;
- fn remove_code_index(&mut self, _: PredicateKey);
- fn get_code_index(&self, _: PredicateKey, _: ClauseName) -> Option<CodeIndex>;
-
- fn insert_dir_entry(&mut self, _: ClauseName, _: usize, _: CodeIndex);
-
- fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option<ClauseName> {
- self.op_dir()
- .get(&(name, fixity))
- .map(|op_val| op_val.owning_module())
- }
-
- fn remove_module(&mut self, mod_name: ClauseName, module: &Module) {
- for export in module.module_decl.exports.iter().cloned() {
- match export {
- ModuleExport::PredicateKey((name, arity)) => {
- let name = name.defrock_brackets();
-
- match self.get_code_index((name.clone(), arity), mod_name.clone()) {
- Some(CodeIndex(ref code_idx)) => {
- if &code_idx.borrow().1 != &module.module_decl.name {
- continue;
- }
-
- self.remove_code_index((name.clone(), arity));
-
- // remove or respecify ops.
- if arity == 2 {
- if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) {
- if mod_name == module.module_decl.name {
- self.op_dir().remove(&(name.clone(), Fixity::In));
- }
- }
- } else if arity == 1 {
- if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) {
- if mod_name == module.module_decl.name {
- self.op_dir().remove(&(name.clone(), Fixity::Pre));
- }
- }
-
- if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Post)
- {
- if mod_name == module.module_decl.name {
- self.op_dir().remove(&(name.clone(), Fixity::Post));
- }
- }
- }
- }
- _ => {}
- };
- },
- ModuleExport::OpDecl(op_decl) => {
- let op_dir = self.op_dir();
- op_dir.remove(&(op_decl.name(), op_decl.fixity()));
- }
- }
- }
- }
-
- // returns true on successful import.
- fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
- let name = name.defrock_brackets();
-
- if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
- let name = name.with_table(submodule.atom_tbl.clone());
- let atom_tbl = self.atom_tbl();
-
- atom_tbl.borrow_mut().insert(name.to_rc());
-
- self.insert_dir_entry(name, arity, code_data.clone());
- true
- } else {
- submodule.is_impromptu_module
- }
- }
-
- fn use_qualified_module(
- &mut self,
- _: &mut CodeRepo,
- _: MachineFlags,
- _: &Module,
- _: &Vec<ModuleExport>,
- ) -> Result<(), SessionError>;
-
- fn use_module(
- &mut self,
- _: &mut CodeRepo,
- _: MachineFlags,
- _: &Module
- ) -> Result<(), SessionError>;
-}
-
-pub fn use_qualified_module<User>(
- user: &mut User,
- submodule: &Module,
- exports: &Vec<ModuleExport>,
-) -> Result<(), SessionError>
-where
- User: SubModuleUser,
-{
- for export in exports.iter().cloned() {
- match export {
- ModuleExport::PredicateKey((name, arity)) => {
- if !submodule
- .module_decl
- .exports
- .contains(&ModuleExport::PredicateKey((name.clone(), arity)))
- {
- continue;
- }
-
- if !user.import_decl(name.clone(), arity, submodule) {
- let submodule_name = submodule.module_decl.name.clone();
-
- return Err(SessionError::ModuleDoesNotContainExport(
- submodule_name,
- (name, arity)
- ));
- }
- },
- ModuleExport::OpDecl(op_decl) => {
- if !submodule
- .module_decl
- .exports
- .contains(&ModuleExport::OpDecl(op_decl.clone()))
- {
- continue;
- }
-
- let op_dir = user.op_dir();
- let prec = op_decl.0;
-
- op_decl.insert_into_op_dir(
- submodule.module_decl.name.clone(),
- op_dir,
- prec,
- );
- }
- }
- }
-
- Ok(())
-}
-
-pub fn use_module<User: SubModuleUser>(
- user: &mut User,
- submodule: &Module,
-) -> Result<(), SessionError> {
- for export in submodule.module_decl.exports.iter().cloned() {
- match export {
- ModuleExport::PredicateKey((name, arity)) => {
- if !user.import_decl(name.clone(), arity, submodule) {
- let submodule_name = submodule.module_decl.name.clone();
-
- return Err(SessionError::ModuleDoesNotContainExport(
- submodule_name,
- (name, arity)
- ));
- }
- }
- ModuleExport::OpDecl(op_decl) => {
- let op_dir = user.op_dir();
- let prec = op_decl.0;
-
- op_decl.insert_into_op_dir(
- submodule.module_decl.name.clone(),
- op_dir,
- prec,
- );
- }
- }
- }
-
- Ok(())
-}
-
-impl SubModuleUser for Module {
- fn atom_tbl(&self) -> TabledData<Atom> {
- self.atom_tbl.clone()
- }
-
- fn op_dir(&mut self) -> &mut OpDir {
- &mut self.op_dir
- }
-
- fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option<CodeIndex> {
- self.code_dir.get(&key).cloned()
- }
-
- fn remove_code_index(&mut self, key: PredicateKey) {
- self.code_dir.remove(&key);
- }
-
- fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
- self.code_dir.insert((name, arity), idx);
- }
-
- fn use_qualified_module(
- &mut self,
- _: &mut CodeRepo,
- _: MachineFlags,
- submodule: &Module,
- exports: &Vec<ModuleExport>,
- ) -> Result<(), SessionError> {
- use_qualified_module(self, submodule, exports)?;
-
- (self.user_term_expansions.0)
- .0
- .extend((submodule.term_expansions.0).0.iter().cloned());
- self.user_term_expansions
- .1
- .extend(submodule.term_expansions.1.iter().cloned());
-
- (self.user_goal_expansions.0)
- .0
- .extend((submodule.goal_expansions.0).0.iter().cloned());
- self.user_goal_expansions
- .1
- .extend(submodule.goal_expansions.1.iter().cloned());
-
- Ok(())
- }
-
- fn use_module(
- &mut self,
- _: &mut CodeRepo,
- _: MachineFlags,
- submodule: &Module,
- ) -> Result<(), SessionError> {
- use_module(self, submodule)?;
-
- (self.user_term_expansions.0)
- .0
- .extend((submodule.term_expansions.0).0.iter().cloned());
- self.user_term_expansions
- .1
- .extend(submodule.term_expansions.1.iter().cloned());
-
- (self.user_goal_expansions.0)
- .0
- .extend((submodule.goal_expansions.0).0.iter().cloned());
- self.user_goal_expansions
- .1
- .extend(submodule.goal_expansions.1.iter().cloned());
-
- Ok(())
- }
-}
+use crate::machine::*;
+use crate::machine::machine_indices::*;
+
use core::marker::PhantomData;
use std::alloc;
+use std::cmp::Ordering;
use std::mem;
use std::ptr;
use std::ops::RangeFrom;
use std::slice;
use std::str;
+use indexmap::IndexSet;
+
#[derive(Debug)]
pub struct PartialString {
buf: *const u8,
}
}
}
+
+#[derive(Debug)]
+pub(crate) struct HeapPStrIter<'a> {
+ focus: Addr,
+ machine_st: &'a MachineState,
+ seen: IndexSet<Addr>,
+}
+
+impl<'a> HeapPStrIter<'a> {
+ #[inline]
+ pub(super)
+ fn new(machine_st: &'a MachineState, focus: Addr) -> Self {
+ HeapPStrIter {
+ focus,
+ machine_st,
+ seen: IndexSet::new(),
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn focus(&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(Debug, 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_prefixes<'a>(
+ i1: &mut HeapPStrIter<'a>,
+ i2: &mut HeapPStrIter<'a>,
+) -> Option<Ordering> {
+ let mut r1 = i1.next();
+ let mut r2 = i2.next();
+
+ loop {
+ if let Some(r1i) = r1 {
+ if let Some(r2i) = r2 {
+ match (r1i, r2i) {
+ (PStrIteratee::Char(c1), PStrIteratee::Char(c2)) => {
+ if c1 != c2 {
+ return c1.partial_cmp(&c2);
+ }
+ }
+ (PStrIteratee::Char(c1), PStrIteratee::PStrSegment(h, n)) => {
+ if let &HeapCellValue::PartialString(ref pstr, _) = &i2.machine_st.heap[h] {
+ if let Some(c2) = pstr.as_str_from(n).chars().next() {
+ if c1 != c2 {
+ return c1.partial_cmp(&c2);
+ } else {
+ r1 = i1.next();
+ r2 = Some(PStrIteratee::PStrSegment(h, n + c2.len_utf8()));
+
+ continue;
+ }
+ } else {
+ r2 = i2.next();
+ continue;
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (PStrIteratee::PStrSegment(h, n), PStrIteratee::Char(c2)) => {
+ if let &HeapCellValue::PartialString(ref pstr, _) = &i1.machine_st.heap[h] {
+ if let Some(c1) = pstr.as_str_from(n).chars().next() {
+ if c1 != c2 {
+ return c2.partial_cmp(&c1);
+ } else {
+ r1 = i1.next();
+ r2 = Some(PStrIteratee::PStrSegment(h, n + c1.len_utf8()));
+
+ continue;
+ }
+ } else {
+ r1 = i1.next();
+ continue;
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (PStrIteratee::PStrSegment(h1, n1), PStrIteratee::PStrSegment(h2, n2)) => {
+ match (&i1.machine_st.heap[h1], &i2.machine_st.heap[h2]) {
+ (
+ &HeapCellValue::PartialString(ref pstr1, _),
+ &HeapCellValue::PartialString(ref pstr2, _),
+ ) => {
+ let str1 = pstr1.as_str_from(n1);
+ let str2 = pstr2.as_str_from(n2);
+
+ if str1.starts_with(str2) {
+ r1 = Some(PStrIteratee::PStrSegment(h1, n1 + str2.len()));
+ r2 = i2.next();
+
+ continue;
+ } else if str2.starts_with(str1) {
+ r1 = i1.next();
+ r2 = Some(PStrIteratee::PStrSegment(h2, n2 + str1.len()));
+
+ continue;
+ } else {
+ return str1.partial_cmp(str2);
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+
+ r1 = i1.next();
+ r2 = i2.next();
+
+ continue;
+ }
+ }
+
+ return match (i1.focus(), i2.focus()) {
+ (Addr::EmptyList, Addr::EmptyList) => {
+ Some(Ordering::Equal)
+ }
+ (Addr::EmptyList, _) => {
+ Some(Ordering::Less)
+ }
+ (_, Addr::EmptyList) => {
+ Some(Ordering::Greater)
+ }
+ _ => {
+ 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 Some(s_offset);
+ }
+ }
+ 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!()
+ }
+ }
+ }
+ }
+
+ if s[s_offset ..].is_empty() {
+ return Some(s_offset);
+ }
+ }
+
+ Some(s_offset)
+}
--- /dev/null
+use crate::prolog_parser::ast::*;
+use crate::prolog_parser::tabled_rc::*;
+
+use crate::forms::*;
+use crate::iterators::*;
+use crate::machine::*;
+use crate::machine::load_state::*;
+use crate::machine::machine_errors::*;
+
+use crate::indexmap::IndexSet;
+
+use std::cell::Cell;
+use std::collections::VecDeque;
+use std::convert::TryFrom;
+use std::rc::Rc;
+
+/*
+ * The preprocessor fabricates if-then-else ( .. -> ... ; ...)
+ * clauses into nameless standalone predicates, which it queues for
+ * later preprocessing and compilation. Fabricated predicates inherit
+ * explicit "cut variables" from the handwritten predicate
+ * surrounding their source if-then-else. They must be specially
+ * handled.
+ */
+
+#[derive(Clone, Copy, Debug)]
+pub(crate) enum CutContext {
+ BlocksCuts,
+ HasCutVariable,
+}
+
+pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
+where
+ I: DoubleEndedIterator<Item = Term>,
+{
+ for prec in terms.rev() {
+ term = Term::Clause(
+ Cell::default(),
+ sym.clone(),
+ vec![Box::new(prec), Box::new(term)],
+ None,
+ );
+ }
+
+ term
+}
+
+pub fn to_op_decl(prec: usize, spec: &str, name: ClauseName) -> Result<OpDecl, CompilationError> {
+ match spec {
+ "xfx" => Ok(OpDecl::new(prec, XFX, name)),
+ "xfy" => Ok(OpDecl::new(prec, XFY, name)),
+ "yfx" => Ok(OpDecl::new(prec, YFX, name)),
+ "fx" => Ok(OpDecl::new(prec, FX, name)),
+ "fy" => Ok(OpDecl::new(prec, FY, name)),
+ "xf" => Ok(OpDecl::new(prec, XF, name)),
+ "yf" => Ok(OpDecl::new(prec, YF, name)),
+ _ => Err(CompilationError::InconsistentEntry),
+ }
+}
+
+fn setup_op_decl(
+ mut terms: Vec<Box<Term>>,
+ atom_tbl: TabledData<Atom>,
+) -> Result<OpDecl, CompilationError> {
+ let name = match *terms.pop().unwrap() {
+ Term::Constant(_, Constant::Atom(name, _)) => name,
+ Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl),
+ _ => return Err(CompilationError::InconsistentEntry),
+ };
+
+ let spec = match *terms.pop().unwrap() {
+ Term::Constant(_, Constant::Atom(name, _)) => name,
+ Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl),
+ _ => return Err(CompilationError::InconsistentEntry),
+ };
+
+ let prec = match *terms.pop().unwrap() {
+ Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
+ Ok(n) if n <= 1200 => n,
+ _ => return Err(CompilationError::InconsistentEntry),
+ },
+ _ => return Err(CompilationError::InconsistentEntry),
+ };
+
+ to_op_decl(prec, spec.as_str(), name)
+}
+
+fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError>
+{
+ match term {
+ Term::Clause(_, ref slash, ref mut terms, Some(_))
+ if (slash.as_str() == "/" || slash.as_str() == "//") && terms.len() == 2 =>
+ {
+ let arity = *terms.pop().unwrap();
+ let name = *terms.pop().unwrap();
+
+ let arity = arity
+ .to_constant()
+ .and_then(|c| {
+ match c {
+ Constant::Integer(n) => n.to_usize(),
+ Constant::Fixnum(n) => usize::try_from(n).ok(),
+ _ => None
+ }
+ })
+ .ok_or(CompilationError::InvalidModuleExport)?;
+
+ let name = name
+ .to_constant()
+ .and_then(|c| c.to_atom())
+ .ok_or(CompilationError::InvalidModuleExport)?;
+
+ if slash.as_str() == "/" {
+ Ok((name, arity))
+ } else {
+ Ok((name, arity + 2))
+ }
+ }
+ _ => {
+ Err(CompilationError::InvalidModuleExport)
+ }
+ }
+}
+
+/*
+fn setup_scoped_predicate_indicator(term: &mut Term) -> Result<ScopedPredicateKey, CompilationError>
+{
+ match term {
+ Term::Clause(_, ref name, ref mut terms, Some(_))
+ if name.as_str() == ":" && terms.len() == 2 =>
+ {
+ let mut predicate_indicator = *terms.pop().unwrap();
+ let module_name = *terms.pop().unwrap();
+
+ let module_name = module_name
+ .to_constant()
+ .and_then(|c| c.to_atom())
+ .ok_or(CompilationError::InvalidModuleExport)?;
+
+ let key = setup_predicate_indicator(&mut predicate_indicator)?;
+
+ Ok((module_name, key))
+ }
+ _ => Err(CompilationError::InvalidModuleExport),
+ }
+}
+*/
+
+fn setup_module_export(
+ mut term: Term,
+ atom_tbl: TabledData<Atom>,
+) -> Result<ModuleExport, CompilationError> {
+ setup_predicate_indicator(&mut term)
+ .map(ModuleExport::PredicateKey)
+ .or_else(|_| {
+ if let Term::Clause(_, name, terms, _) = term {
+ if terms.len() == 3 && name.as_str() == "op" {
+ Ok(ModuleExport::OpDecl(setup_op_decl(
+ terms,
+ atom_tbl
+ )?))
+ } else {
+ Err(CompilationError::InvalidModuleDecl)
+ }
+ } else {
+ Err(CompilationError::InvalidModuleDecl)
+ }
+ })
+}
+
+pub(super)
+fn setup_module_export_list(
+ mut export_list: Term,
+ atom_tbl: TabledData<Atom>,
+) -> Result<Vec<ModuleExport>, CompilationError> {
+ let mut exports = vec![];
+
+ while let Term::Cons(_, t1, t2) = export_list {
+ let module_export = setup_module_export(*t1, atom_tbl.clone())?;
+
+ exports.push(module_export);
+ export_list = *t2;
+ }
+
+ if export_list.to_constant() != Some(Constant::EmptyList) {
+ Err(CompilationError::InvalidModuleDecl)
+ } else {
+ Ok(exports)
+ }
+}
+
+fn setup_module_decl(
+ mut terms: Vec<Box<Term>>,
+ atom_tbl: TabledData<Atom>,
+) -> Result<ModuleDecl, CompilationError> {
+ let export_list = *terms.pop().unwrap();
+ let name = terms
+ .pop()
+ .unwrap()
+ .to_constant()
+ .and_then(|c| c.to_atom())
+ .ok_or(CompilationError::InvalidModuleDecl)?;
+
+ let exports = setup_module_export_list(export_list, atom_tbl)?;
+ Ok(ModuleDecl { name, exports })
+}
+
+fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, CompilationError> {
+ match *terms.pop().unwrap() {
+ Term::Clause(_, ref name, ref mut terms, None)
+ if name.as_str() == "library" && terms.len() == 1 =>
+ {
+ terms
+ .pop()
+ .unwrap()
+ .to_constant()
+ .and_then(|c| c.to_atom())
+ .map(|c| ModuleSource::Library(c))
+ .ok_or(CompilationError::InvalidUseModuleDecl)
+ }
+ Term::Constant(_, Constant::Atom(ref name, _)) =>
+ Ok(ModuleSource::File(name.clone())),
+ _ => Err(CompilationError::InvalidUseModuleDecl),
+ }
+}
+
+/*
+fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, CompilationError> {
+ 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(CompilationError::InvalidDoubleQuotesDecl),
+ }
+ }
+ _ => {
+ Err(CompilationError::InvalidDoubleQuotesDecl)
+ }
+ }
+ },
+ _ => {
+ Err(CompilationError::InvalidDoubleQuotesDecl)
+ }
+ }
+}
+ */
+
+type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
+
+fn setup_qualified_import(
+ mut terms: Vec<Box<Term>>,
+ atom_tbl: TabledData<Atom>,
+) -> Result<UseModuleExport, CompilationError> {
+ let mut export_list = *terms.pop().unwrap();
+ let module_src = match *terms.pop().unwrap() {
+ Term::Clause(_, ref name, ref mut terms, None)
+ if name.as_str() == "library" && terms.len() == 1 =>
+ {
+ terms
+ .pop()
+ .unwrap()
+ .to_constant()
+ .and_then(|c| c.to_atom())
+ .map(|c| ModuleSource::Library(c))
+ .ok_or(CompilationError::InvalidUseModuleDecl)
+ }
+ Term::Constant(_, Constant::Atom(ref name, _)) => {
+ Ok(ModuleSource::File(name.clone()))
+ }
+ _ => {
+ Err(CompilationError::InvalidUseModuleDecl)
+ }
+ }?;
+
+ let mut exports = IndexSet::new();
+
+ while let Term::Cons(_, t1, t2) = export_list {
+ exports.insert(setup_module_export(*t1, atom_tbl.clone())?);
+ export_list = *t2;
+ }
+
+ if export_list.to_constant() != Some(Constant::EmptyList) {
+ Err(CompilationError::InvalidModuleDecl)
+ } else {
+ Ok((module_src, exports))
+ }
+}
+
+/*
+ * setup_meta_predicate tries to extract meta-predicate information
+ * from an appropriately formed declaration
+ *
+ * :- meta_predicate maplist(:, ?, ?).
+ *
+ * indicating that, for each QueryTerm call to maplist/3, the first
+ * argument is to be expanded with the call resolution ((:)/2)
+ * operator, the first argument of which is the name of the host
+ * module, as an atom. For example,
+ *
+ * p(X) :- maplist(X, [a,b,c], Result).
+ *
+ * If p/2 is defined in a module named "mod", the call is expanded to
+ *
+ * maplist(mod:X, [a,b,c], Result).
+ *
+ * before the predicate is compiled to WAM instructions.
+ *
+ * If the term bound to X -- the predicate to be called -- is
+ * qualified with (:)/2 already, the innermost qualifier is used for
+ * call resolution.
+ *
+ * The three arguments returned by a successful call are the module name,
+ * predicate name, and the list of meta-specs, one for each predicate argument.
+ *
+ * The module name might be used to specify intra-module meta-predicates whose
+ * module is not yet defined. There are several examples of this
+ * contained in src/lib/ops_and_meta_predicates.pl, which is loaded before
+ * src/lib/builtins.pl.
+ *
+ * Meta-specs have three forms:
+ *
+ * (:) (the argument should be expanded with (:)/2 as described above)
+ * + (mode declarations under the mode syntax, which currently have no effect)
+ * -
+ * ?
+ */
+fn setup_meta_predicate<'a>(
+ mut terms: Vec<Box<Term>>,
+ load_state: &LoadState<'a>,
+) -> Result<(ClauseName, ClauseName, Vec<MetaSpec>), CompilationError>
+{
+ fn get_name_and_meta_specs(
+ name: ClauseName,
+ terms: &mut [Box<Term>],
+ ) -> Result<(ClauseName, Vec<MetaSpec>), CompilationError> {
+ let mut meta_specs = vec![];
+
+ for meta_spec in terms.into_iter() {
+ match &**meta_spec {
+ Term::Constant(_, Constant::Atom(meta_spec, _)) => {
+ let meta_spec =
+ match meta_spec.as_str() {
+ ":" => MetaSpec::RequiresExpansion,
+ "+" => MetaSpec::Plus,
+ "-" => MetaSpec::Minus,
+ "?" => MetaSpec::Either,
+ _ => return Err(CompilationError::InvalidMetaPredicateDecl),
+ };
+
+ meta_specs.push(meta_spec);
+ }
+ Term::Constant(_, Constant::Fixnum(n)) => {
+ match usize::try_from(*n) {
+ Ok(n) if n <= MAX_ARITY => {
+ meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
+ }
+ _ => {
+ return Err(CompilationError::InvalidMetaPredicateDecl);
+ }
+ }
+ }
+ _ => {
+ return Err(CompilationError::InvalidMetaPredicateDecl);
+ }
+ }
+ }
+
+ Ok((name, meta_specs))
+ }
+
+ match *terms.pop().unwrap() {
+ Term::Clause(_, name, mut terms, _)
+ if name.as_str() == ":" && terms.len() == 2 => {
+ let spec = *terms.pop().unwrap();
+ let module_name = *terms.pop().unwrap();
+
+ match module_name {
+ Term::Constant(_, Constant::Atom(module_name, _)) => {
+ match spec {
+ Term::Clause(_, name, mut terms, _) => {
+ let (name, meta_specs) =
+ get_name_and_meta_specs(name, &mut terms)?;
+
+ Ok((module_name, name, meta_specs))
+ }
+ _ => {
+ Err(CompilationError::InvalidMetaPredicateDecl)
+ }
+ }
+ }
+ _ => {
+ Err(CompilationError::InvalidMetaPredicateDecl)
+ }
+ }
+ }
+ Term::Clause(_, name, mut terms, _) => {
+ let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
+ Ok((load_state.module_name(), name, meta_specs))
+ }
+ _ => {
+ Err(CompilationError::InvalidMetaPredicateDecl)
+ }
+ }
+}
+
+fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, CompilationError>
+{
+ let mut clauses = vec![];
+
+ while let Some(tl) = tls.pop_front() {
+ match tl {
+ TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => {
+ return Ok(tl);
+ }
+ TopLevel::Declaration(_) if clauses.is_empty() => {
+ return Ok(tl);
+ }
+ TopLevel::Query(_) => {
+ return Err(CompilationError::InconsistentEntry);
+ }
+ TopLevel::Fact(fact) => {
+ let clause = PredicateClause::Fact(fact);
+ clauses.push(clause);
+ }
+ TopLevel::Rule(rule) => {
+ let clause = PredicateClause::Rule(rule);
+ clauses.push(clause);
+ }
+ TopLevel::Predicate(predicate) => {
+ clauses.extend(predicate.into_iter())
+ }
+ _ => {
+ tls.push_front(tl);
+ break;
+ }
+ }
+ }
+
+ if clauses.is_empty() {
+ Err(CompilationError::InconsistentEntry)
+ } else {
+ Ok(TopLevel::Predicate(clauses))
+ }
+}
+
+fn mark_cut_variables_as(terms: &mut Vec<Term>, name: ClauseName) {
+ for term in terms.iter_mut() {
+ match term {
+ &mut Term::Constant(_, Constant::Atom(ref mut var, _)) if var.as_str() == "!" => {
+ *var = name.clone()
+ }
+ _ => {}
+ }
+ }
+}
+
+fn mark_cut_variable(term: &mut Term) -> bool {
+ let cut_var_found = match term {
+ &mut Term::Constant(_, Constant::Atom(ref var, _)) if var.as_str() == "!" => true,
+ _ => false,
+ };
+
+ if cut_var_found {
+ *term = Term::Var(Cell::default(), rc_atom!("!"));
+ true
+ } else {
+ false
+ }
+}
+
+fn mark_cut_variables(terms: &mut Vec<Term>) -> bool {
+ let mut found_cut_var = false;
+
+ for item in terms.iter_mut() {
+ found_cut_var = mark_cut_variable(item) || found_cut_var;
+ }
+
+ found_cut_var
+}
+
+// terms is a list of goals composing one clause in a (;) functor. it
+// checks that the first (and only) of these clauses is a ->. if so,
+// it expands its terms using a blocked_!.
+fn check_for_internal_if_then(terms: &mut Vec<Term>) {
+ if terms.len() != 1 {
+ return;
+ }
+
+ if let Some(Term::Clause(_, ref name, ref subterms, _)) = terms.last() {
+ if name.as_str() != "->" || subterms.len() != 2 {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if let Some(Term::Clause(_, _, mut subterms, _)) = terms.pop() {
+ let mut conq_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
+ let mut pre_cut_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
+
+ conq_terms.push_front(Term::Constant(
+ Cell::default(),
+ Constant::Atom(clause_name!("blocked_!"), None))
+ );
+
+ while let Some(term) = pre_cut_terms.pop_back() {
+ conq_terms.push_front(term);
+ }
+
+ let tail_term = conq_terms.pop_back().unwrap();
+
+ terms.push(fold_by_str(
+ conq_terms.into_iter(),
+ tail_term,
+ clause_name!(","),
+ ));
+ }
+}
+
+fn setup_declaration<'a>(
+ load_state: &LoadState<'a>,
+ mut terms: Vec<Box<Term>>,
+) -> Result<Declaration, CompilationError> {
+ let term = *terms.pop().unwrap();
+ let atom_tbl = load_state.wam.machine_st.atom_tbl.clone();
+
+ match term {
+ Term::Clause(_, name, mut terms, _) =>
+ match (name.as_str(), terms.len()) {
+ ("dynamic", 1) => {
+ let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
+ Ok(Declaration::Dynamic(name, arity))
+ }
+ ("module", 2) =>
+ Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?)),
+ ("op", 3) =>
+ Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?)),
+ ("non_counted_backtracking", 1) => {
+ let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
+ Ok(Declaration::NonCountedBacktracking(name, arity))
+ }
+ ("use_module", 1) => {
+ Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
+ }
+ ("use_module", 2) => {
+ let (name, exports) = setup_qualified_import(terms, atom_tbl)?;
+ Ok(Declaration::UseQualifiedModule(name, exports))
+ }
+ ("meta_predicate", 1) => {
+ let (module_name, name, meta_specs) = setup_meta_predicate(terms, load_state)?;
+ Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
+ }
+ _ => {
+ Err(CompilationError::InconsistentEntry)
+ }
+ },
+ _ => {
+ Err(CompilationError::InconsistentEntry)
+ }
+ }
+}
+
+#[inline]
+fn clause_to_query_term<'a>(
+ load_state: &mut LoadState<'a>,
+ name: ClauseName,
+ terms: Vec<Box<Term>>,
+ fixity: Option<SharedOpDesc>,
+) -> QueryTerm {
+ let ct = load_state.get_clause_type(name, terms.len(), fixity);
+ QueryTerm::Clause(Cell::default(), ct, terms, false)
+}
+
+#[inline]
+fn qualified_clause_to_query_term<'a>(
+ load_state: &mut LoadState<'a>,
+ module_name: ClauseName,
+ name: ClauseName,
+ terms: Vec<Box<Term>>,
+ fixity: Option<SharedOpDesc>,
+) -> QueryTerm {
+ let ct = load_state.get_qualified_clause_type(module_name, name, terms.len(), fixity);
+ QueryTerm::Clause(Cell::default(), ct, terms, false)
+}
+
+#[derive(Debug)]
+pub(crate) struct Preprocessor {
+ flags: MachineFlags,
+ queue: VecDeque<VecDeque<Term>>,
+}
+
+impl Preprocessor {
+ pub(super)
+ fn new(flags: MachineFlags) -> Self {
+ Preprocessor {
+ flags,
+ queue: VecDeque::new(),
+ }
+ }
+
+ fn setup_fact(&mut self, term: Term) -> Result<Term, CompilationError> {
+ match term {
+ Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => {
+ Ok(term)
+ }
+ _ => {
+ Err(CompilationError::InadmissibleFact)
+ }
+ }
+ }
+
+ fn compute_head(&self, term: &Term) -> Vec<Term> {
+ let mut vars = IndexSet::new();
+
+ for term in post_order_iter(term) {
+ if let TermRef::Var(_, _, v) = term {
+ vars.insert(v.clone());
+ }
+ }
+
+ vars.insert(rc_atom!("!"));
+ vars.into_iter()
+ .map(|v| Term::Var(Cell::default(), v))
+ .collect()
+ }
+
+ fn fabricate_rule_body(&self, vars: &Vec<Term>, body_term: Term) -> Term {
+ let vars_of_head = vars.iter().cloned().map(Box::new).collect();
+ let head_term = Term::Clause(Cell::default(), clause_name!(""), vars_of_head, None);
+
+ let rule = vec![Box::new(head_term), Box::new(body_term)];
+ let turnstile = clause_name!(":-");
+
+ Term::Clause(Cell::default(), turnstile, rule, None)
+ }
+
+ // the terms form the body of the rule. We create a head, by
+ // gathering variables from the body of terms and recording them
+ // in the head clause.
+ fn fabricate_rule(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
+ // collect the vars of body_term into a head, return the num_vars
+ // (the arity) as well.
+ let vars = self.compute_head(&body_term);
+ let rule = self.fabricate_rule_body(&vars, body_term);
+
+ (vars, VecDeque::from(vec![rule]))
+ }
+
+ fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
+ let vars = self.compute_head(&body_term);
+ let results = unfold_by_str(body_term, ";")
+ .into_iter()
+ .map(|term| {
+ let mut subterms = unfold_by_str(term, ",");
+ mark_cut_variables(&mut subterms);
+
+ check_for_internal_if_then(&mut subterms);
+
+ let term = subterms.pop().unwrap();
+ let clause = fold_by_str(subterms.into_iter(), term, clause_name!(","));
+
+ self.fabricate_rule_body(&vars, clause)
+ })
+ .collect();
+
+ (vars, results)
+ }
+
+ fn fabricate_if_then(&self, prec: Term, conq: Term) -> (JumpStub, VecDeque<Term>) {
+ let mut prec_seq = unfold_by_str(prec, ",");
+ let comma_sym = clause_name!(",");
+ let cut_sym = atom!("!");
+
+ prec_seq.push(Term::Constant(Cell::default(), cut_sym));
+
+ mark_cut_variables_as(&mut prec_seq, clause_name!("blocked_!"));
+
+ let mut conq_seq = unfold_by_str(conq, ",");
+
+ mark_cut_variables(&mut conq_seq);
+ prec_seq.extend(conq_seq.into_iter());
+
+ let back_term = Box::new(prec_seq.pop().unwrap());
+ let front_term = Box::new(prec_seq.pop().unwrap());
+
+ let body_term = Term::Clause(
+ Cell::default(),
+ comma_sym.clone(),
+ vec![front_term, back_term],
+ None,
+ );
+
+ self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
+ }
+
+ fn to_query_term<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ term: Term,
+ ) -> Result<QueryTerm, CompilationError> {
+ match term {
+ Term::Constant(_, Constant::Atom(name, fixity)) => {
+ if name.as_str() == "!" || name.as_str() == "blocked_!" {
+ Ok(QueryTerm::BlockedCut)
+ } else {
+ Ok(clause_to_query_term(load_state, name, vec![], fixity))
+ }
+ }
+ Term::Var(_, ref v) if v.as_str() == "!" => {
+ Ok(QueryTerm::UnblockedCut(Cell::default()))
+ }
+ Term::Clause(r, name, mut terms, fixity) => {
+ match (name.as_str(), terms.len()) {
+ (";", 2) => {
+ let term = Term::Clause(r, name.clone(), terms, fixity);
+
+ let (stub, clauses) = self.fabricate_disjunct(term);
+ self.queue.push_back(clauses);
+
+ Ok(QueryTerm::Jump(stub))
+ }
+ ("->", 2) => {
+ let conq = *terms.pop().unwrap();
+ let prec = *terms.pop().unwrap();
+
+ let (stub, clauses) = self.fabricate_if_then(prec, conq);
+ self.queue.push_back(clauses);
+
+ Ok(QueryTerm::Jump(stub))
+ }
+ ("\\+", 1) => {
+ terms.push(Box::new(Term::Constant(
+ Cell::default(),
+ Constant::Atom(clause_name!("$fail"), None)
+ )));
+
+ let conq = Term::Constant(
+ Cell::default(),
+ Constant::Atom(clause_name!("true"), None)
+ );
+
+ let prec = Term::Clause(Cell::default(), clause_name!("->"), terms, None);
+ let terms = vec![Box::new(prec), Box::new(conq)];
+
+ let term = Term::Clause(Cell::default(), clause_name!(";"), terms, None);
+ let (stub, clauses) = self.fabricate_disjunct(term);
+
+ debug_assert!(clauses.len() > 0);
+ self.queue.push_back(clauses);
+
+ Ok(QueryTerm::Jump(stub))
+ }
+ ("$get_level", 1) => {
+ if let Term::Var(_, ref var) = *terms[0] {
+ Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone()))
+ } else {
+ Err(CompilationError::InadmissibleQueryTerm)
+ }
+ }
+ (":", 2) => {
+ let predicate_name = *terms.pop().unwrap();
+ let module_name = *terms.pop().unwrap();
+
+ match (module_name, predicate_name) {
+ (Term::Constant(_, Constant::Atom(module_name, _)),
+ Term::Constant(_, Constant::Atom(predicate_name, fixity))) => {
+ Ok(qualified_clause_to_query_term(
+ load_state,
+ module_name,
+ predicate_name,
+ vec![],
+ fixity,
+ ))
+ }
+ (Term::Constant(_, Constant::Atom(module_name, _)),
+ Term::Clause(_, name, terms, fixity)) => {
+ Ok(qualified_clause_to_query_term(
+ load_state,
+ module_name,
+ name,
+ terms,
+ fixity,
+ ))
+ }
+ (module_name, predicate_name) => {
+ terms.push(Box::new(module_name));
+ terms.push(Box::new(predicate_name));
+
+ Ok(clause_to_query_term(load_state, name, terms, fixity))
+ }
+ }
+ }
+ _ => {
+ Ok(clause_to_query_term(load_state, name, terms, fixity))
+ }
+ }
+ }
+ Term::Var(..) => {
+ Ok(QueryTerm::Clause(
+ Cell::default(),
+ ClauseType::CallN,
+ vec![Box::new(term)],
+ false,
+ ))
+ }
+ _ => {
+ Err(CompilationError::InadmissibleQueryTerm)
+ }
+ }
+ }
+
+ fn pre_query_term<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ term: Term,
+ ) -> Result<QueryTerm, CompilationError> {
+ match term {
+ Term::Clause(r, name, mut subterms, fixity) => {
+ if subterms.len() == 1 && name.as_str() == "$call_with_default_policy" {
+ self.to_query_term(load_state, *subterms.pop().unwrap())
+ .map(|mut query_term| {
+ query_term.set_default_caller();
+ query_term
+ })
+ } else {
+ self.to_query_term(load_state, Term::Clause(r, name, subterms, fixity))
+ }
+ }
+ _ => {
+ self.to_query_term(load_state, term)
+ }
+ }
+ }
+
+ fn setup_query<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ terms: Vec<Box<Term>>,
+ cut_context: CutContext,
+ ) -> Result<Vec<QueryTerm>, CompilationError> {
+ let mut query_terms = vec![];
+ let mut work_queue = VecDeque::from(terms);
+
+ while let Some(term) = work_queue.pop_front() {
+ let mut term = *term;
+
+ if let Term::Clause(cell, name, terms, op_spec) = term {
+ if name.as_str() == "," && terms.len() == 2 {
+ let term = Term::Clause(cell, name, terms, op_spec);
+ let mut subterms = unfold_by_str(term, ",");
+
+ while let Some(subterm) = subterms.pop() {
+ work_queue.push_front(Box::new(subterm));
+ }
+
+ continue;
+ } else {
+ term = Term::Clause(cell, name, terms, op_spec);
+ }
+ }
+
+ if let CutContext::HasCutVariable = cut_context {
+ mark_cut_variable(&mut term);
+ }
+
+ query_terms.push(self.pre_query_term(load_state, term)?);
+ }
+
+ Ok(query_terms)
+ }
+
+ fn setup_rule<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ mut terms: Vec<Box<Term>>,
+ cut_context: CutContext,
+ ) -> Result<Rule, CompilationError> {
+ let post_head_terms: Vec<_> = terms.drain(1 ..).collect();
+
+ let mut query_terms =
+ self.setup_query(load_state, post_head_terms, cut_context)?;
+
+ let clauses = query_terms.drain(1 ..).collect();
+ let qt = query_terms.pop().unwrap();
+
+ match *terms.pop().unwrap() {
+ Term::Clause(_, name, terms, _) => {
+ Ok(Rule {
+ head: (name, terms, qt),
+ clauses,
+ })
+ }
+ Term::Constant(_, Constant::Atom(name, _)) => {
+ Ok(Rule {
+ head: (name, vec![], qt),
+ clauses,
+ })
+ }
+ _ => {
+ Err(CompilationError::InvalidRuleHead)
+ }
+ }
+ }
+
+ fn try_term_to_query<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ terms: Vec<Box<Term>>,
+ cut_context: CutContext,
+ ) -> Result<TopLevel, CompilationError> {
+ Ok(TopLevel::Query(self.setup_query(load_state, terms, cut_context)?))
+ }
+
+ pub(super)
+ fn try_term_to_tl<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ term: Term,
+ cut_context: CutContext,
+ ) -> Result<TopLevel, CompilationError> {
+ match term {
+ Term::Clause(r, name, terms, fixity) => {
+ if name.as_str() == "?-" {
+ self.try_term_to_query(load_state, terms, cut_context)
+ } else if name.as_str() == ":-" && terms.len() == 2 {
+ Ok(TopLevel::Rule(self.setup_rule(
+ load_state,
+ terms,
+ cut_context,
+ )?))
+ } else if name.as_str() == ":-" && terms.len() == 1 {
+ Ok(TopLevel::Declaration(setup_declaration(load_state, terms)?))
+ } else {
+ let term = Term::Clause(r, name, terms, fixity);
+ Ok(TopLevel::Fact(self.setup_fact(term)?))
+ }
+ }
+ term => {
+ Ok(TopLevel::Fact(self.setup_fact(term)?))
+ }
+ }
+ }
+
+ fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ terms: I,
+ cut_context: CutContext,
+ ) -> Result<VecDeque<TopLevel>, CompilationError> {
+ let mut results = VecDeque::new();
+
+ for term in terms.into_iter() {
+ results.push_back(self.try_term_to_tl(load_state, term, cut_context)?);
+ }
+
+ Ok(results)
+ }
+
+ pub(super)
+ fn parse_queue<'a>(
+ &mut self,
+ load_state: &mut LoadState<'a>,
+ ) -> Result<VecDeque<TopLevel>, CompilationError> {
+ let mut queue = VecDeque::new();
+
+ while let Some(terms) = self.queue.pop_front() {
+ let clauses = merge_clauses(
+ &mut self.try_terms_to_tls(
+ load_state,
+ terms,
+ CutContext::HasCutVariable,
+ )?
+ )?;
+
+ queue.push_back(clauses);
+ }
+
+ Ok(queue)
+ }
+}
:- module('$project_atts', [copy_term/3]).
-'$attribute_goals_driver'(QueryVars, AttrVars) :-
- gather_modules(AttrVars, Modules0, _),
+driver(QueryVars, AttrVars) :-
+ gather_attr_modules(AttrVars, Modules0),
sort(Modules0, Modules),
call_project_attributes(Modules, QueryVars, AttrVars),
- call_attribute_goals(Modules, call_query_var_goals, QueryVars),
- call_attribute_goals(Modules, call_attr_var_goals, AttrVars).
+ call_attribute_goals(Modules, '$project_atts':call_query_var_goals, QueryVars),
+ call_attribute_goals(Modules, '$project_atts':call_attr_var_goals, AttrVars).
enqueue_goals(Goals0) :-
nonvar(Goals0),
call_project_attributes(Modules, QueryVars, AttrVars).
call_attribute_goals([], _, _).
-call_attribute_goals([Module | Modules], GoalCaller, AttrVars) :-
+call_attribute_goals([Module|Modules], GoalCaller, AttrVars) :-
call(GoalCaller, AttrVars, Module, Goals),
enqueue_goals(Goals),
call_attribute_goals(Modules, GoalCaller, AttrVars).
call_query_var_goals([], _, []).
call_query_var_goals([AttrVar|AttrVars], Module, Goals) :-
- ( catch(( Module:attribute_goals(AttrVar, Goals, RGoals0)
- , atts:'$default_attr_list'(Module, AttrVar, RGoals0, RGoals)
- ),
- E,
- ( '$print_attribute_goals_exception'(Module, E),
- atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
- ))
+ ( catch(( Module:attribute_goals(AttrVar, Goals, RGoals0),
+ atts:'$default_attr_list'(Module, AttrVar, RGoals0, RGoals)
+ ),
+ E,
+ ( '$project_atts':'$print_attribute_goals_exception'(Module, E),
+ atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
+ ))
-> true
; atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
),
call_attr_var_goals([], _, []).
call_attr_var_goals([AttrVar|AttrVars], Module, Goals) :-
( catch(Module:attribute_goals(AttrVar, Goals, RGoals),
- E,
- '$print_attribute_goals_exception'(Module, E)
- )
+ E,
+ '$project_atts':'$print_attribute_goals_exception'(Module, E)
+ )
-> true
; true
),
call_attr_var_goals(AttrVars, Module, RGoals).
-gather_modules([], [], _).
-gather_modules([AttrVar|AttrVars], Modules, Modules0) :-
- '$get_attr_list'(AttrVar, Attrs),
- gather_modules_for_attrs(Attrs, Modules, Modules0),
- gather_modules(AttrVars, Modules0, _).
-
-gather_modules_for_attrs(Attrs, Modules, Modules) :-
- var(Attrs), !.
-gather_modules_for_attrs([Attr|Attrs], [Module|Modules], Modules0) :-
- '$module_of'(Module, Attr),
- gather_modules_for_attrs(Attrs, Modules, Modules0).
module_prefixed_goals([], _, Gs, Gs).
module_prefixed_goals([G|Gs], Module, [MG|MGs], TailGs) :-
module_prefixed_goals(Goals0, Module, Goals, Gs),
call_attribute_goals_with_module_prefix(Modules, GoalCaller, AttrVars, Gs).
+
+gather_attr_modules([], []).
+gather_attr_modules([AttrVar|AttrVars], Modules) :-
+ '$get_attr_list'(AttrVar, Attrs),
+ copy_attribute_modules(Attrs, Modules, Modules0),
+ gather_attr_modules(AttrVars, Modules0).
+
+copy_attribute_modules(Attrs, Ls, Ls) :-
+ var(Attrs), !.
+copy_attribute_modules([Module:_|Attrs], [Module|Modules0], Modules1) :-
+ copy_attribute_modules(Attrs, Modules0, Modules1).
+
+
copy_term(Source, Dest, Goals) :-
- '$term_attributed_variables'(Source, Vars),
- gather_modules(Vars, Modules0, _),
+ '$term_attributed_variables'(Source, AttrVars),
+ gather_attr_modules(AttrVars, Modules0),
sort(Modules0, Modules),
- call_attribute_goals_with_module_prefix(Modules, call_query_var_goals, Vars, Goals0),
+ call_attribute_goals_with_module_prefix(Modules, '$project_atts':call_query_var_goals,
+ AttrVars, Goals0),
sort(Goals0, Goals1),
!,
'$copy_term_without_attr_vars'([Source | Goals1], [Dest | Goals]).
}
}
- pub fn take(&mut self) -> Self {
- Stack { buf: self.buf.take(), _marker: PhantomData }
- }
-
#[inline]
pub fn truncate(&mut self, b: usize) {
if b == 0 {
fn drop(&mut self) {
match self {
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
- discard_result!(tcp_stream.shutdown(Shutdown::Both));
+ tcp_stream.shutdown(Shutdown::Both).unwrap();
}
StreamInstance::TlsStream(_, ref mut tls_stream) => {
- discard_result!(tls_stream.shutdown());
+ tls_stream.shutdown().unwrap();
}
_ => {
}
use crate::forms::*;
use crate::heap_print::*;
use crate::instructions::*;
+use crate::machine;
use crate::machine::code_repo::CodeRepo;
use crate::machine::copier::*;
use crate::machine::code_walker::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
+use crate::machine::preprocessor::to_op_decl;
use crate::machine::streams::*;
-use crate::machine::toplevel::to_op_decl;
+
use crate::ordered_float::OrderedFloat;
use crate::read::readline;
use crate::rug::Integer;
}
}
- let mode =
- atom_from!(self, indices, self.store(self.deref(self[temp_v!(2)])));
-
+ let mode = atom_from!(self, self.store(self.deref(self[temp_v!(2)])));
let mut open_options = fs::OpenOptions::new();
let (is_input_file, in_append_mode) =
let spec = get_clause_spec(
name.clone(),
*arity,
- composite_op!(&indices.op_dir),
+ &CompositeOpDir::new(&indices.op_dir, None),
);
let addr = self.heap.to_unifiable(HeapCellValue::DBRef(
let mut parser = Parser::new(
&mut stream,
- indices.atom_tbl.clone(),
+ self.atom_tbl.clone(),
self.machine_flags(),
);
- match parser.read_term(composite_op!(&indices.op_dir)) {
+ match parser.read_term(&CompositeOpDir::new(&indices.op_dir, None)) {
Err(err) => {
let h = self.heap.h();
let err = MachineError::syntax_error(h, err);
current_output_stream: &mut Stream,
) -> CallResult {
match ct {
+ /*
&SystemClauseType::AbolishClause => {
let p = self.cp;
let trans_type = DynamicTransactionType::Abolish;
self.p = CodePtr::DynamicTransaction(trans_type, p);
return Ok(());
}
+ */
&SystemClauseType::BindFromRegister => {
let reg = self.store(self.deref(self[temp_v!(2)]));
let n =
self.fail = true;
}
+ /*
&SystemClauseType::AssertDynamicPredicateToFront => {
let p = self.cp;
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
return Ok(());
}
&SystemClauseType::AssertDynamicPredicateToBack => {
- let p = self.cp;
- let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Back);
+ // let p = self.cp;
+ // let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Back);
- self.p = CodePtr::DynamicTransaction(trans_type, p);
+ // self.p = CodePtr::DynamicTransaction(trans_type, p);
+ self.p = CodePtr::REPL(REPLCodePtr::UserAssertz, self.cp);
return Ok(());
}
+ */
&SystemClauseType::CurrentHostname => {
match hostname::get().ok() {
Some(host) => {
match host.into_string().ok() {
Some(host) => {
let hostname = self.heap.to_unifiable(
- HeapCellValue::Atom(clause_name!(host, indices.atom_tbl), None)
+ HeapCellValue::Atom(clause_name!(host, self.atom_tbl), None)
);
self.unify(self[temp_v!(1)], hostname);
return Err(err);
}
};
+
let chars = self.heap.put_complete_string(current);
self.unify(self[temp_v!(1)], chars);
return Ok(());
}
}
+ /*
&SystemClauseType::AtEndOfExpansion => {
if self.cp == LocalCodePtr::TopLevel(0, 0) {
self.at_end_of_expansion = true;
}
}
+ */
&SystemClauseType::AtomChars => {
let a1 = self[temp_v!(1)];
if &string == "[]" {
self.unify(addr, Addr::EmptyList);
} else {
- let chars = clause_name!(string, indices.atom_tbl);
+ let chars = clause_name!(string, self.atom_tbl);
let atom = self.heap.to_unifiable(
HeapCellValue::Atom(chars, None)
);
}
let string = self.heap.to_unifiable(
- HeapCellValue::Atom(clause_name!(chars, indices.atom_tbl), None)
+ HeapCellValue::Atom(clause_name!(chars, self.atom_tbl), None)
);
self.bind(addr.as_var().unwrap(), string);
clause_name!("[]")
}
Addr::Char(c) => {
- clause_name!(c.to_string(), indices.atom_tbl)
+ clause_name!(c.to_string(), self.atom_tbl)
}
_ => {
unreachable!()
}
}
}
+ /*
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
let p = self.cp;
let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Front);
self.p = CodePtr::DynamicTransaction(trans_type, p);
return Ok(());
}
+ */
&SystemClauseType::LiftedHeapLength => {
let a1 = self[temp_v!(1)];
let lh_len = Addr::Usize(self.lifted_heap.h());
self.unify(Addr::Char(c), a1);
}
+/*
&SystemClauseType::GetModuleClause => {
let module = self[temp_v!(3)];
let head = self[temp_v!(1)];
_ => unreachable!(),
};
}
+*/
&SystemClauseType::HeadIsDynamic => {
- let head = self[temp_v!(1)];
+ let module_name = atom_from!(
+ self,
+ self.store(self.deref(
+ self[temp_v!(1)]
+ ))
+ );
- self.fail = !match self.store(self.deref(head)) {
+ self.fail = !match self.store(self.deref(self[temp_v!(2)])) {
Addr::Str(s) => match &self.heap[s] {
- &HeapCellValue::NamedStr(arity, ref name, ..) => indices
- .get_clause_subsection(name.owning_module(), name.clone(), arity)
- .is_some(),
+ &HeapCellValue::NamedStr(arity, ref name, ..) =>
+ indices.is_dynamic_predicate(module_name, (name.clone(), arity)),
_ => unreachable!(),
},
Addr::Con(h) if self.heap.atom_at(h) => {
- if let HeapCellValue::Atom(name, _) = &self.heap[h] {
- indices.get_clause_subsection(name.owning_module(), name.clone(), 0)
- .is_some()
+ if let HeapCellValue::Atom(name, _) = &self.heap[h] {
+ indices.is_dynamic_predicate(module_name, (name.clone(), 0))
} else {
unreachable!()
}
return self.module_lookup(
indices,
+ call_policy,
(name, arity + narity),
module_name,
true,
+ current_input_stream,
+ current_output_stream,
);
} else {
unreachable!()
}
}
Addr::Con(h) if self.heap.atom_at(h) => {
- if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
+ if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
return self.module_lookup(
indices,
+ call_policy,
(name.clone(), narity),
module_name,
true,
+ current_input_stream,
+ current_output_stream,
);
} else {
unreachable!()
}
}
}
+ /*
&SystemClauseType::ExpandGoal => {
self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
return Ok(());
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
return Ok(());
}
+ */
&SystemClauseType::GetNextDBRef => {
let a1 = self[temp_v!(1)];
let spec = get_clause_spec(
name.clone(),
*arity,
- composite_op!(&indices.op_dir),
+ &CompositeOpDir::new(&indices.op_dir, None),
);
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
let op = match self.store(self.deref(op)) {
Addr::Char(c) =>
- clause_name!(c.to_string(), indices.atom_tbl),
+ clause_name!(c.to_string(), self.atom_tbl),
Addr::Con(h) if self.heap.atom_at(h) =>
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
name.clone()
unreachable!(),
};
- let module = op.owning_module();
-
let result = to_op_decl(priority, specifier.as_str(), op)
.map_err(SessionError::from)
- .and_then(|op_decl| {
- if op_decl.0 == 0 {
+ .and_then(|mut op_decl| {
+ if op_decl.prec == 0 {
Ok(op_decl.remove(&mut indices.op_dir))
} else {
- let spec = get_desc(op_decl.name(), composite_op!(&indices.op_dir));
- op_decl.submit(module, spec, &mut indices.op_dir)
+ let spec = get_op_desc(
+ op_decl.name.clone(),
+ &CompositeOpDir::new(&indices.op_dir, None),
+ );
+
+ op_decl.submit(spec, &mut indices.op_dir)
}
});
let mut heap_pstr_iter =
self.heap_pstr_iter(Addr::PStrLocation(h, n));
- let file_spec =
+ let file_spec =
clause_name!(
heap_pstr_iter.to_string(),
- indices.atom_tbl.clone()
+ self.atom_tbl
);
self.stream_from_file_spec(file_spec, indices, &options)?
}
};
}
- &SystemClauseType::ModuleOf => {
- let module = self.store(self.deref(self[temp_v!(2)]));
-
- match module {
- Addr::Con(h) if self.heap.atom_at(h) => {
- if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
- let module = self.heap.to_unifiable(
- HeapCellValue::Atom(
- name.owning_module(),
- None
- ),
- );
-
- let target = self[temp_v!(1)];
-
- self.unify(target, module);
- } else {
- unreachable!()
- }
- }
- Addr::Str(s) => match self.heap.clone(s) {
- HeapCellValue::NamedStr(_, name, ..) => {
- let module = self.heap.to_unifiable(
- HeapCellValue::Atom(
- name.owning_module(),
- None
- ),
- );
-
- let target = self[temp_v!(1)];
-
- self.unify(target, module);
- }
- HeapCellValue::Addr(addr) if addr.is_ref() => {
- let err = MachineError::uninstantiation_error(addr);
- let stub = MachineError::functor_stub(
- clause_name!("$module_of"),
- 2,
- );
-
- return Err(self.error_form(err, stub));
- }
- _ => {
- unreachable!()
- }
- },
- _ => {
- self.fail = true;
- }
- };
- }
&SystemClauseType::NoSuchPredicate => {
- let head = self[temp_v!(1)];
+ let module_name = atom_from!(self, self.store(self.deref(self[temp_v!(1)])));
- self.fail = match self.store(self.deref(head)) {
+ self.fail = match self.store(self.deref(self[temp_v!(2)])) {
Addr::Str(s) => match &self.heap[s] {
&HeapCellValue::NamedStr(arity, ref name, ref spec) => {
- let module = name.owning_module();
- indices.predicate_exists(name.clone(), module, arity, spec.clone())
+ indices.get_predicate_code_index(
+ name.clone(),
+ arity,
+ module_name,
+ spec.clone(),
+ ).is_some()
}
_ => {
unreachable!()
},
Addr::Con(h) if self.heap.atom_at(h) => {
if let &HeapCellValue::Atom(ref name, ref spec) = &self.heap[h] {
- let module = name.owning_module();
let spec = fetch_atom_op_spec(
name.clone(),
spec.clone(),
&indices.op_dir,
);
- indices.predicate_exists(name.clone(), module, 0, spec)
+ indices.get_predicate_code_index(name.clone(), 0, module_name, spec)
+ .is_some()
} else {
unreachable!()
}
&SystemClauseType::REPL(repl_code_ptr) => {
return self.repl_redirect(repl_code_ptr);
}
+ /*
&SystemClauseType::ModuleRetractClause => {
let p = self.cp;
let trans_type = DynamicTransactionType::ModuleRetract;
self.p = CodePtr::DynamicTransaction(trans_type, p);
return Ok(());
}
+ */
&SystemClauseType::ReturnFromVerifyAttr => {
let e = self.e;
let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
self.unify(a1, a2);
}
+/*
&SystemClauseType::GetClause => {
let head = self[temp_v!(1)];
}
},
Addr::Con(h) if self.heap.atom_at(h) => {
- if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] {
indices.get_clause_subsection(
name.owning_module(),
name.clone(),
0,
)
} else {
- unreachable!()
+ unreachable!()
}
}
_ => {
}
}
}
+*/
&SystemClauseType::GetCutPoint => {
let a1 = self[temp_v!(1)];
let a2 = Addr::CutPoint(self.b0);
let term_write_result =
match self.read(
Stream::from(chars),
- indices.atom_tbl.clone(),
+ self.atom_tbl.clone(),
&indices.op_dir,
) {
Ok(term_write_result) => {
let mut rand = RANDOM_STATE.borrow_mut();
rand.seed(&seed);
}
- &SystemClauseType::SkipMaxList =>
+ &SystemClauseType::SkipMaxList => {
if let Err(err) = self.skip_max_list() {
return Err(err);
- },
+ }
+ }
&SystemClauseType::Sleep => {
let time = self.store(self.deref(self[temp_v!(1)]));
let stream =
match TcpStream::connect(&socket_addr).map_err(|e| e.kind()) {
Ok(tcp_stream) => {
- let socket_addr = clause_name!(socket_addr, indices.atom_tbl.clone());
+ let socket_addr = clause_name!(socket_addr, self.atom_tbl);
-
- let mut stream =
- { let tls = match self.store(self.deref(self[temp_v!(8)])) {
+ let mut stream = {
+ let tls = match self.store(self.deref(self[temp_v!(8)])) {
Addr::Con(h) if self.heap.atom_at(h) => {
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
atom.as_str()
unreachable!()
}
};
+
match tls {
"false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) }
"true" => { let connector = TlsConnector::new().unwrap();
_ => { unreachable!() }
}
};
+
stream.options = options;
if let Some(ref alias) = &stream.options.alias {
match tcp_listener.accept().ok() {
Some((tcp_stream, socket_addr)) => {
let client =
- clause_name!(format!("{}", socket_addr), indices.atom_tbl);
+ clause_name!(format!("{}", socket_addr), self.atom_tbl);
let mut tcp_stream =
Stream::from_tcp_stream(client.clone(), tcp_stream);
self.fail = self.structural_eq_test();
}
&SystemClauseType::WAMInstructions => {
- let name = self[temp_v!(1)];
- let arity = self[temp_v!(2)];
+ let module_name = atom_from!(
+ self,
+ self.store(self.deref(self[temp_v!(1)]))
+ );
+
+ let name = self[temp_v!(2)];
+ let arity = self[temp_v!(3)];
let name = match self.store(self.deref(name)) {
Addr::Con(h) if self.heap.atom_at(h) => {
}
};
- let first_idx = match indices
- .code_dir
- .get(&(name.clone(), arity.to_usize().unwrap()))
- {
- Some(ref idx) if idx.local().is_some() => {
- if let Some(idx) = idx.local() {
- idx
- } else {
- unreachable!()
- }
- }
- _ => {
- let arity = arity.to_usize().unwrap();
- let stub = MachineError::functor_stub(name.clone(), arity);
- let h = self.heap.h();
+ let key = (name.clone(), arity.to_usize().unwrap());
- let err = MachineError::existence_error(
- h,
- ExistenceError::Procedure(name, arity),
- );
+ let first_idx = match module_name.as_str() {
+ "user" => indices.code_dir.get(&key),
+ _ => match indices.modules.get(&module_name) {
+ Some(module) => module.code_dir.get(&key),
+ None => {
+ let stub = MachineError::functor_stub(key.0, key.1);
+ let h = self.heap.h();
- let err = self.error_form(err, stub);
+ let err = MachineError::session_error(
+ h,
+ SessionError::from(
+ CompilationError::InvalidModuleResolution(
+ module_name
+ )
+ ),
+ );
- self.throw_exception(err);
- return Ok(());
- }
+ let err = self.error_form(err, stub);
+
+ self.throw_exception(err);
+ return Ok(());
+ }
+ },
};
+ let first_idx =
+ match first_idx {
+ Some(ref idx) if idx.local().is_some() => {
+ if let Some(idx) = idx.local() {
+ idx
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ let arity = arity.to_usize().unwrap();
+ let stub = MachineError::functor_stub(name.clone(), arity);
+ let h = self.heap.h();
+
+ let err = MachineError::existence_error(
+ h,
+ ExistenceError::Procedure(name, arity),
+ );
+
+ let err = self.error_form(err, stub);
+
+ self.throw_exception(err);
+ return Ok(());
+ }
+ };
+
let mut h = self.heap.h();
let mut functors = vec![];
+ let mut functor_list = vec![];
walk_code(
&code_repo.code,
first_idx,
|instr| {
- let section = instr.to_functor(h);
- functors.push(Addr::HeapCell(h));
+ let old_len = functors.len();
+ instr.enqueue_functors(h, &mut functors);
+ let new_len = functors.len();
- h += section.len();
- self.heap.extend(section.into_iter());
+ for index in old_len .. new_len {
+ functor_list.push(Addr::HeapCell(h));
+ h += functors[index].len();
+ }
},
);
- let listing = Addr::HeapCell(self.heap.to_list(functors.into_iter()));
- let listing_var = self[temp_v!(3)];
+ for functor in functors {
+ self.heap.extend(functor.into_iter());
+ }
+
+ let listing = Addr::HeapCell(self.heap.to_list(functor_list.into_iter()));
+ let listing_var = self[temp_v!(4)];
self.unify(listing, listing_var);
}
self.unify(self[temp_v!(2)], cstr);
}
}
+ &SystemClauseType::LoadLibraryAsStream => {
+ let library_name =
+ atom_from!(
+ self,
+ self.store(self.deref(self[temp_v!(1)]))
+ );
+
+ use crate::LIBRARIES;
+
+ match LIBRARIES.borrow().get(library_name.as_str()) {
+ Some(library) => {
+ let var_ref = Ref::HeapCell(self.heap.push(
+ HeapCellValue::Stream(Stream::from(*library))
+ ));
+
+ self.bind(var_ref, self[temp_v!(2)]);
+
+ let mut path_buf = machine::current_dir();
+
+ path_buf.push("/lib");
+ path_buf.push(library_name.as_str());
+
+ let library_path_str = path_buf.to_str().unwrap();
+ let library_path =
+ clause_name!(library_path_str.to_string(), self.atom_tbl);
+
+ let library_path_ref = Ref::HeapCell(
+ self.heap.push(HeapCellValue::Atom(library_path, None))
+ );
+
+ self.bind(library_path_ref, self[temp_v!(3)]);
+ }
+ None => {
+ return Err(
+ self.error_form(
+ MachineError::existence_error(
+ self.heap.h(),
+ ExistenceError::ModuleSource(
+ ModuleSource::Library(library_name)
+ ),
+ ),
+ MachineError::functor_stub(clause_name!("load"), 1),
+ )
+ );
+ }
+ }
+ }
};
return_from_clause!(self.last_call, self)
} else {
let mut avec = Vec::new();
for attr in node.attributes() {
- let chars = clause_name!(String::from(attr.name()), indices.atom_tbl);
+ let chars = clause_name!(String::from(attr.name()), self.atom_tbl);
let name = self.heap.to_unifiable(
HeapCellValue::Atom(chars, None)
);
}
let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter()));
- let chars = clause_name!(String::from(node.tag_name().name()), indices.atom_tbl);
+ let chars = clause_name!(String::from(node.tag_name().name()), self.atom_tbl);
let tag = self.heap.to_unifiable(
HeapCellValue::Atom(chars, None)
);
Some(name) => {
let mut avec = Vec::new();
for attr in node.attrs() {
- let chars = clause_name!(String::from(attr.0), indices.atom_tbl);
+ let chars = clause_name!(String::from(attr.0), self.atom_tbl);
let name = self.heap.to_unifiable(
HeapCellValue::Atom(chars, None)
);
}
let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter()));
- let chars = clause_name!(String::from(name), indices.atom_tbl);
+ let chars = clause_name!(String::from(name), self.atom_tbl);
let tag = self.heap.to_unifiable(
HeapCellValue::Atom(chars, None)
);
+++ /dev/null
-use crate::prolog_parser::ast::*;
-use crate::prolog_parser::parser::*;
-
-use crate::machine::machine_indices::HeapCellValue;
-use crate::machine::*;
-use crate::rug::ops::Pow;
-use crate::rug::Integer;
-
-use std::cell::Cell;
-use std::collections::VecDeque;
-use std::iter::Rev;
-use std::vec::IntoIter;
-
-pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
-where
- I: DoubleEndedIterator<Item = Term>,
-{
- for prec in terms.rev() {
- term = Term::Clause(
- Cell::default(),
- sym.clone(),
- vec![Box::new(prec), Box::new(term)],
- None,
- );
- }
-
- term
-}
-
-fn extract_from_list(
- head: Box<Term>,
- tail: Box<Term>,
-) -> Result<Rev<IntoIter<Term>>, ParserError>
-{
- let mut terms = vec![*head];
- let mut tail = *tail;
-
- while let Term::Cons(_, head, next_tail) = tail {
- terms.push(*head);
- tail = *next_tail;
- }
-
- if let Term::Constant(_, Constant::EmptyList) = tail {
- Ok(terms.into_iter().rev())
- } else {
- Err(ParserError::ExpectedTopLevelTerm)
- }
-}
-
-#[derive(Debug)]
-pub struct TermStream<'a> {
- stack: Vec<Term>,
- pub(crate) wam: &'a mut Machine,
- parser: Parser<'a, Stream>,
- pub(crate) flags: MachineFlags,
- term_expansion_lens: (usize, usize),
- goal_expansion_lens: (usize, usize),
- top_level_terms: Vec<(Term, usize, usize)>, // term, line_num, col_num.
-}
-
-#[derive(Debug)]
-pub struct ExpansionAdditionResult {
- term_expansion_additions: (Predicate, VecDeque<TopLevel>),
- goal_expansion_additions: (Predicate, VecDeque<TopLevel>),
-}
-
-impl ExpansionAdditionResult {
- pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
- let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
- let teqs = mem::replace(&mut self.term_expansion_additions.1, VecDeque::from(vec![]));
-
- (tes, teqs)
- }
-
- pub fn take_goal_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
- let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
- let geqs = mem::replace(&mut self.goal_expansion_additions.1, VecDeque::from(vec![]));
-
- (ges, geqs)
- }
-}
-
-impl<'a> Drop for TermStream<'a> {
- fn drop(&mut self) {
- self.wam.indices.in_situ_code_dir.clear();
- self.wam.indices.in_situ_module_dir.clear();
-
- self.wam.code_repo.in_situ_code.clear();
- discard_result!(self.rollback_expansion_code());
- }
-}
-
-impl<'a> TermStream<'a> {
- pub fn new(
- src: &'a mut ParsingStream<Stream>,
- atom_tbl: TabledData<Atom>,
- flags: MachineFlags,
- wam: &'a mut Machine,
- ) -> Self {
- TermStream {
- stack: Vec::new(),
- term_expansion_lens: wam
- .code_repo
- .term_dir_entry_len((clause_name!("term_expansion"), 2)),
- goal_expansion_lens: wam
- .code_repo
- .term_dir_entry_len((clause_name!("goal_expansion"), 2)),
- wam,
- parser: Parser::new(src, atom_tbl, flags),
- flags,
- top_level_terms: vec![],
- }
- }
-
- #[inline]
- pub fn top_level_terms(&mut self) -> Vec<(Term, usize, usize)> {
- mem::replace(&mut self.top_level_terms, vec![])
- }
-
- #[inline]
- pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) {
- match hook {
- CompileTimeHook::UserTermExpansion => {
- self.term_expansion_lens.0 += len;
- self.term_expansion_lens.1 += queue_len;
- }
- CompileTimeHook::UserGoalExpansion => {
- self.goal_expansion_lens.0 += len;
- self.goal_expansion_lens.1 += queue_len;
- }
- _ => {}
- }
- }
-
- #[inline]
- pub fn line_num(&self) -> usize {
- self.parser.line_num()
- }
-
- #[inline]
- pub fn col_num(&self) -> usize {
- self.parser.col_num()
- }
-
- #[inline]
- pub fn update_expansion_lens(&mut self) {
- let te_key = (clause_name!("term_expansion"), 2);
- let ge_key = (clause_name!("goal_expansion"), 2);
-
- let (tes_len, tes_q_len) = self.wam.code_repo.term_dir_entry_len(te_key);
-
- self.term_expansion_lens.0 = tes_len;
- self.term_expansion_lens.1 = tes_q_len;
-
- let (ges_len, ges_q_len) = self.wam.code_repo.term_dir_entry_len(ge_key);
-
- self.goal_expansion_lens.0 = ges_len;
- self.goal_expansion_lens.1 = ges_q_len;
- }
-
- #[inline]
- pub fn set_atom_tbl(&mut self, atom_tbl: TabledData<Atom>) {
- self.parser.set_atom_tbl(atom_tbl);
- }
-
- #[inline]
- pub fn eof(&mut self) -> Result<bool, ParserError> {
- self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
- Ok(self.stack.is_empty() && self.parser.eof()?)
- }
-
- pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> {
- let te_len = self.term_expansion_lens.0;
- let te_queue_len = self.term_expansion_lens.1;
-
- let ge_len = self.goal_expansion_lens.0;
- let ge_queue_len = self.goal_expansion_lens.1;
-
- let term_expansion_additions = self.wam.code_repo.truncate_terms(
- (clause_name!("term_expansion"), 2),
- te_len,
- te_queue_len,
- );
-
- let goal_expansion_additions = self.wam.code_repo.truncate_terms(
- (clause_name!("goal_expansion"), 2),
- ge_len,
- ge_queue_len,
- );
-
- self.wam
- .code_repo
- .compile_hook(CompileTimeHook::TermExpansion)?;
- self.wam
- .code_repo
- .compile_hook(CompileTimeHook::GoalExpansion)?;
-
- Ok(ExpansionAdditionResult {
- term_expansion_additions,
- goal_expansion_additions,
- })
- }
-
- fn enqueue_term(&mut self, term: Term) -> Result<(), ParserError> {
- match term {
- Term::Cons(_, head, tail) => {
- let iter = extract_from_list(head, tail)?;
- Ok(self.stack.extend(iter))
- }
- Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => {
- Ok(self.stack.push(term))
- }
- _ => {
- Err(ParserError::ExpectedTopLevelTerm)
- }
- }
- }
-
- fn parse_expansion_output(
- &self,
- term_string: &str,
- op_dir: &OpDir,
- ) -> Result<Term, ParserError> {
- let mut stream = parsing_stream(term_string.trim().as_bytes())?;
- let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags);
-
- parser.read_term(composite_op!(
- false,
- &self.wam.indices.op_dir,
- op_dir
- ))
- }
-
- pub fn expand_term(&mut self, term: Term, op_dir: &OpDir) -> Result<Term, ParserError> {
- let mut machine_st = MachineState::new();
-
- self.stack.push(term);
-
- while let Some(term) = self.stack.pop() {
- match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) {
- Some(term_string) => {
- let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
- self.enqueue_term(term)?;
- }
- None => {
- return Ok(term);
- }
- };
- }
-
- unreachable!()
- }
-
- pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> {
- loop {
- if let Some(term) = self.stack.pop() {
- return Ok(self.expand_term(term, op_dir)?);
- }
-
- self.parser.reset();
-
- let line_num = self.line_num();
- let col_num = self.col_num();
-
- let term = self.parser.read_term(composite_op!(
- false,
- &self.wam.indices.op_dir,
- op_dir
- ))?;
-
- // preserve a copy of the original unexpanded term for warning scans,
- // if that stage is reached.
- self.top_level_terms.push((term.clone(), line_num, col_num));
- self.stack.push(term);
- }
- }
-
- pub(super)
- fn expand_goals(
- &mut self,
- machine_st: &mut MachineState,
- op_dir: &OpDir,
- mut terms: VecDeque<Term>,
- ) -> Result<Vec<Term>, ParserError> {
- let mut results = vec![];
-
- while let Some(term) = terms.pop_front() {
- match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion) {
- Some(term_string) => {
- let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
-
- match term {
- Term::Cons(_, head, tail) => {
- for term in extract_from_list(head, tail)? {
- terms.push_front(term);
- }
- }
- term => terms.push_front(term),
- };
- }
- None => results.push(term),
- }
- }
-
- Ok(results)
- }
-}
-
-impl MachineState {
- pub(super)
- fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
- let output = PrinterOutputter::new();
- let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
- let mut max_var_length = 0;
-
- for var in self.heap_locs.keys() {
- max_var_length = std::cmp::max(var.len(), max_var_length);
- }
-
- printer.quoted = 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 names in the
- // 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.print_strings_as_strs = true;
- printer.drop_toplevel_spec();
-
- printer.see_all_locs();
-
- let mut output = printer.print(addr);
-
- output.push_char('.');
- output
- }
-
- // reset the machine, but keep the heap contents as they were.
- // this prevents clashes between underscored variable names in the
- // same query.
- fn reset_with_heap_preservation(&mut self) {
- let heap = self.heap.take();
- self.reset();
- self.heap = heap;
- }
-
- fn try_expand_term(
- &mut self,
- wam: &mut Machine,
- term: &Term,
- hook: CompileTimeHook,
- ) -> Option<String> {
- let term_write_result = write_term_to_heap(term, self);
- let h = self.heap.h();
-
- self[temp_v!(1)] = Addr::HeapCell(term_write_result.heap_loc);
- self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
- self[temp_v!(2)] = Addr::HeapCell(h);
-
- let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
- wam.code_repo.cached_query = code;
-
- self.cp = LocalCodePtr::TopLevel(0, 0);
-
- self.at_end_of_expansion = false;
- self.flags.double_quotes = DoubleQuotes::Chars;
-
- self.query_stepper(
- &mut wam.indices,
- &mut MachinePolicies::default(),
- &mut wam.code_repo,
- &mut readline::input_stream(),
- &mut Stream::stdout(),
- );
-
- if self.fail || self.at_end_of_expansion {
- self.reset_with_heap_preservation();
- None
- } else {
- let TermWriteResult { var_dict, .. } = term_write_result;
-
- self.heap_locs = var_dict;
- let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
-
- self.reset_with_heap_preservation();
-
- Some(output.result())
- }
- }
-}
--- /dev/null
+use crate::prolog_parser::ast::*;
+use crate::prolog_parser::parser::*;
+
+use crate::machine::*;
+use crate::machine::machine_errors::CompilationError;
+use crate::machine::preprocessor::*;
+
+use indexmap::IndexSet;
+
+use std::collections::VecDeque;
+use std::fmt;
+
+pub(crate) trait TermStream : Sized {
+ type Evacuable;
+
+ fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError>;
+ fn eof(&mut self) -> Result<bool, CompilationError>;
+ fn listing_src(&self) -> &ListingSource;
+ fn evacuate<'a>(loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError>;
+}
+
+#[derive(Debug)]
+pub(super) struct BootstrappingTermStream<'a> {
+ listing_src: ListingSource,
+ parser: Parser<'a, Stream>,
+}
+
+impl<'a> BootstrappingTermStream<'a> {
+ #[inline]
+ pub(super)
+ fn from_prolog_stream(
+ stream: &'a mut PrologStream,
+ atom_tbl: TabledData<Atom>,
+ flags: MachineFlags,
+ listing_src: ListingSource,
+ ) -> Self {
+ let parser = Parser::new(stream, atom_tbl, flags);
+ Self { parser, listing_src }
+ }
+}
+
+impl<'a> TermStream for BootstrappingTermStream<'a> {
+ type Evacuable = CompilationTarget;
+
+ #[inline]
+ fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError> {
+ self.parser.reset();
+ self.parser.read_term(op_dir)
+ .map_err(CompilationError::from)
+ }
+
+ #[inline]
+ fn eof(&mut self) -> Result<bool, CompilationError> {
+ self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
+ Ok(self.parser.eof()?)
+ }
+
+ #[inline]
+ fn listing_src(&self) -> &ListingSource {
+ &self.listing_src
+ }
+
+ fn evacuate(mut loader: Loader<Self>) -> Result<Self::Evacuable, SessionError> {
+ if !loader.predicates.is_empty() {
+ loader.compile_and_submit()?;
+ }
+
+ loader.load_state.retraction_info.reset(
+ loader.load_state.wam.code_repo.code.len(),
+ );
+
+ loader.load_state.remove_module_op_exports();
+
+ Ok(loader.load_state.compilation_target.take())
+ }
+}
+
+pub struct LiveTermStream {
+ pub(super) term_queue: VecDeque<Term>,
+ pub(super) listing_src: ListingSource,
+}
+
+impl LiveTermStream {
+ #[inline]
+ pub(super)
+ fn new(listing_src: ListingSource) -> Self {
+ Self {
+ term_queue: VecDeque::new(),
+ listing_src,
+ }
+ }
+}
+
+pub struct LoadStatePayload {
+ pub(super) term_stream: LiveTermStream,
+ pub(super) compilation_target: CompilationTarget,
+ pub(super) retraction_info: RetractionInfo,
+ pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>,
+ pub(super) non_counted_bt_preds: IndexSet<PredicateKey>,
+ pub(super) preprocessor: Preprocessor,
+ pub(super) predicates: Vec<PredicateClause>,
+ pub(super) clause_clauses: Vec<(Term, Term)>,
+}
+
+impl fmt::Debug for LoadStatePayload {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "LoadStatePayload")
+ }
+}
+
+impl LoadStatePayload {
+ pub(super)
+ fn new(wam: &Machine) -> Self {
+ Self {
+ term_stream: LiveTermStream::new(ListingSource::User),
+ compilation_target: CompilationTarget::default(),
+ retraction_info: RetractionInfo::new(wam.code_repo.code.len()),
+ module_op_exports: vec![],
+ non_counted_bt_preds: IndexSet::new(),
+ preprocessor: Preprocessor::new(wam.machine_st.flags),
+ predicates: vec![],
+ clause_clauses: vec![],
+ }
+ }
+}
+
+impl TermStream for LiveTermStream {
+ type Evacuable = LoadStatePayload;
+
+ #[inline]
+ fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
+ Ok(self.term_queue.pop_front().unwrap())
+ }
+
+ #[inline]
+ fn eof(&mut self) -> Result<bool, CompilationError> {
+ return Ok(self.term_queue.is_empty());
+ }
+
+ #[inline]
+ fn listing_src(&self) -> &ListingSource {
+ &self.listing_src
+ }
+
+ #[inline]
+ fn evacuate(loader: Loader<Self>) -> Result<LoadStatePayload, SessionError> {
+ Ok(loader.to_load_state_payload())
+ }
+}
+++ /dev/null
-use crate::prolog_parser::ast::*;
-use crate::prolog_parser::tabled_rc::*;
-
-use crate::forms::*;
-use crate::iterators::*;
-use crate::machine::machine_errors::*;
-use crate::machine::machine_indices::*;
-use crate::machine::term_expansion::*;
-use crate::machine::*;
-
-use crate::indexmap::{IndexMap, IndexSet};
-
-use std::borrow::BorrowMut;
-use std::cell::Cell;
-use std::collections::VecDeque;
-use std::convert::TryFrom;
-use std::fmt;
-use std::mem;
-use std::ops::DerefMut;
-use std::rc::Rc;
-
-enum IndexSource<'a, T> {
- TermStream,
- Local(&'a mut T)
-}
-
-impl<'a, T: fmt::Debug> fmt::Debug for IndexSource<'a, T> {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- match self {
- IndexSource::TermStream => write!(fmt, "TermStream"),
- IndexSource::Local(ref local) => write!(fmt, "Local({:?})", local),
- }
- }
-}
-
-fn op_dir<'a, 'b: 'a>(from: &'b IndexSource<'a, IndexStore>) -> RefOrOwned<'a, OpDir> {
- match from {
- IndexSource::TermStream => RefOrOwned::Owned(OpDir::new()),
- IndexSource::Local(ref indices) => RefOrOwned::Borrowed(&indices.op_dir)
- }
-}
-
-#[derive(Debug)]
-struct CompositeIndices<'a, 'b, 'c> {
- term_stream: &'b mut TermStream<'a>,
- index_src: IndexSource<'c, IndexStore>,
- static_code_dir: Option<IndexSource<'c, CodeDir>>
-}
-
-impl<'a, 'b, 'c> CompositeIndices<'a, 'b, 'c> {
- fn new(
- term_stream: &'b mut TermStream<'a>,
- index_src: IndexSource<'c, IndexStore>,
- static_code_dir: Option<IndexSource<'c, CodeDir>>,
- ) -> Self {
- CompositeIndices {
- term_stream,
- index_src,
- static_code_dir,
- }
- }
-
- fn atom_tbl(&self) -> TabledData<Atom> {
- match self.index_src {
- IndexSource::TermStream => self.term_stream.wam.indices.atom_tbl.clone(),
- IndexSource::Local(ref indices) => indices.atom_tbl.clone(),
- }
- }
-
- fn local_code_dir(&mut self) -> &mut CodeDir {
- match self.index_src {
- IndexSource::TermStream => &mut self.term_stream.wam.indices.code_dir,
- IndexSource::Local(ref mut indices) => &mut indices.code_dir,
- }
- }
-
- fn static_code_dir(&self) -> Option<&CodeDir> {
- match self.static_code_dir {
- Some(IndexSource::TermStream) => Some(&self.term_stream.wam.indices.code_dir),
- Some(IndexSource::Local(ref code_dir)) => Some(code_dir),
- None => None
- }
- }
-
- fn get_code_index(&mut self, name: ClauseName, arity: usize) -> CodeIndex {
- let idx_opt = self.local_code_dir().get(&(name.clone(), arity));
- let idx_opt = match idx_opt {
- Some(idx) => Some(idx.clone()),
- None => match self.static_code_dir() {
- Some(ref code_dir) => code_dir.get(&(name.clone(), arity)).cloned(),
- _ => None,
- }
- };
-
- if let Some(idx) = idx_opt {
- self.local_code_dir().insert((name.clone(), arity), idx.clone());
- idx
- } else {
- let idx = CodeIndex::default();
- self.local_code_dir().insert((name.clone(), arity), idx.clone());
- idx
- }
- }
-
- fn get_clause_type(
- &mut self,
- name: ClauseName,
- arity: usize,
- spec: Option<SharedOpDesc>,
- ) -> ClauseType {
- match ClauseType::from(name, arity, spec) {
- ClauseType::Named(name, arity, _) => {
- let idx = self.get_code_index(name.clone(), arity);
- ClauseType::Named(name, arity, idx.clone())
- }
- ClauseType::Op(name, spec, _) => {
- let idx = self.get_code_index(name.clone(), arity);
- ClauseType::Op(name, spec, idx.clone())
- }
- ct => ct,
- }
- }
-
- fn add_in_situ_module_info(&mut self, module_name: ClauseName, term: &mut Term)
- {
- let atom_tbl =
- match self.term_stream.wam.indices.in_situ_module_dir.get(&module_name) {
- Some(ref module_stub) => module_stub.atom_tbl.clone(),
- None => {
- let atom_tbl = match self.term_stream.wam.indices.modules.get(&module_name) {
- Some(ref module) => module.atom_tbl.clone(),
- None => TabledData::new(module_name.to_rc()),
- };
-
- self.term_stream.wam.indices.in_situ_module_dir.insert(
- module_name.clone(),
- ModuleStub::new(atom_tbl.clone()),
- );
-
- atom_tbl
- }
- };
-
- if let Some(name) = term.name() {
- term.set_name(name.with_table(atom_tbl));
- }
- }
-}
-
-fn as_compile_time_hook(
- name: &str,
- arity: usize,
- terms: &Vec<Box<Term>>,
-) -> Option<CompileTimeHook> {
- match (name, arity) {
- ("term_expansion", 2) => Some(CompileTimeHook::TermExpansion),
- ("goal_expansion", 2) => Some(CompileTimeHook::GoalExpansion),
- (":", 2) => {
- if let &Term::Constant(_, Constant::Atom(ref name, _)) = &terms[0].as_ref() {
- if name.as_str() == "user" {
- if let &Term::Clause(_, ref name, ref terms, _) = &terms[1].as_ref() {
- return match name.as_str() {
- "term_expansion" if terms.len() == 2 => {
- Some(CompileTimeHook::UserTermExpansion)
- }
- "goal_expansion" if terms.len() == 2 => {
- Some(CompileTimeHook::UserGoalExpansion)
- }
- _ => None,
- };
- }
- }
- }
-
- None
- }
- _ => None,
- }
-}
-
-#[inline]
-fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<CompileTimeHook> {
- if name.as_str() == ":-" {
- if let Some(ref term) = terms.first() {
- if let &Term::Clause(_, ref name, ref terms, _) = term.as_ref() {
- return as_compile_time_hook(name.as_str(), terms.len(), terms);
- }
- }
- }
-
- as_compile_time_hook(name.as_str(), terms.len(), terms)
-}
-
-type CompileTimeHookCompileInfo = (CompileTimeHook, PredicateClause, VecDeque<TopLevel>);
-
-pub fn to_op_decl(prec: usize, spec: &str, name: ClauseName) -> Result<OpDecl, ParserError> {
- match spec {
- "xfx" => Ok(OpDecl(prec, XFX, name)),
- "xfy" => Ok(OpDecl(prec, XFY, name)),
- "yfx" => Ok(OpDecl(prec, YFX, name)),
- "fx" => Ok(OpDecl(prec, FX, name)),
- "fy" => Ok(OpDecl(prec, FY, name)),
- "xf" => Ok(OpDecl(prec, XF, name)),
- "yf" => Ok(OpDecl(prec, YF, name)),
- _ => Err(ParserError::InconsistentEntry),
- }
-}
-
-fn setup_op_decl(
- mut terms: Vec<Box<Term>>,
- atom_tbl: TabledData<Atom>,
-) -> Result<OpDecl, ParserError> {
- let name = match *terms.pop().unwrap() {
- Term::Constant(_, Constant::Atom(name, _)) => name,
- Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl.clone()),
- _ => return Err(ParserError::InconsistentEntry),
- };
-
- let spec = match *terms.pop().unwrap() {
- Term::Constant(_, Constant::Atom(name, _)) => name,
- Term::Constant(_, Constant::Char(c)) => clause_name!(c.to_string(), atom_tbl.clone()),
- _ => return Err(ParserError::InconsistentEntry),
- };
-
- let prec = match *terms.pop().unwrap() {
- Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
- Ok(n) if n <= 1200 => n,
- _ => return Err(ParserError::InconsistentEntry),
- },
- _ => return Err(ParserError::InconsistentEntry),
- };
-
- to_op_decl(prec, spec.as_str(), name)
-}
-
-fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserError>
-{
- match term {
- Term::Clause(_, ref slash, ref mut terms, Some(_))
- if (slash.as_str() == "/" || slash.as_str() == "//") && terms.len() == 2 =>
- {
- let arity = *terms.pop().unwrap();
- let name = *terms.pop().unwrap();
-
- let arity = arity
- .to_constant()
- .and_then(|c| {
- match c {
- Constant::Integer(n) => n.to_usize(),
- Constant::Fixnum(n) => usize::try_from(n).ok(),
- _ => None
- }
- })
- .ok_or(ParserError::InvalidModuleExport)?;
-
- let name = name
- .to_constant()
- .and_then(|c| c.to_atom())
- .ok_or(ParserError::InvalidModuleExport)?;
-
- if slash.as_str() == "/" {
- Ok((name, arity))
- } else {
- Ok((name, arity + 2))
- }
- }
- _ => Err(ParserError::InvalidModuleExport),
- }
-}
-
-fn setup_scoped_predicate_indicator(term: &mut Term) -> Result<ScopedPredicateKey, ParserError>
-{
- match term {
- Term::Clause(_, ref name, ref mut terms, Some(_))
- if name.as_str() == ":" && terms.len() == 2 =>
- {
- let mut predicate_indicator = *terms.pop().unwrap();
- let module_name = *terms.pop().unwrap();
-
- let module_name = module_name
- .to_constant()
- .and_then(|c| c.to_atom())
- .ok_or(ParserError::InvalidModuleExport)?;
-
- let key = setup_predicate_indicator(&mut predicate_indicator)?;
-
- Ok((module_name, key))
- }
- _ => Err(ParserError::InvalidModuleExport),
- }
-}
-
-fn setup_module_export(
- mut term: Term,
- atom_tbl: TabledData<Atom>,
-) -> Result<ModuleExport, ParserError> {
- setup_predicate_indicator(&mut term)
- .map(ModuleExport::PredicateKey)
- .or_else(|_| {
- if let Term::Clause(_, name, terms, _) = term {
- if terms.len() == 3 && name.as_str() == "op" {
- Ok(ModuleExport::OpDecl(setup_op_decl(
- terms,
- atom_tbl
- )?))
- } else {
- Err(ParserError::InvalidModuleDecl)
- }
- } else {
- Err(ParserError::InvalidModuleDecl)
- }
- })
-}
-
-fn setup_module_decl(
- mut terms: Vec<Box<Term>>,
- atom_tbl: TabledData<Atom>,
-) -> Result<ModuleDecl, ParserError> {
- let mut export_list = *terms.pop().unwrap();
- let name = terms
- .pop()
- .unwrap()
- .to_constant()
- .and_then(|c| c.to_atom())
- .ok_or(ParserError::InvalidModuleDecl)?;
-
- let mut exports = vec![];
-
- while let Term::Cons(_, t1, t2) = export_list {
- let module_export = setup_module_export(*t1, atom_tbl.clone())?;
-
- exports.push(module_export);
- export_list = *t2;
- }
-
- if export_list.to_constant() != Some(Constant::EmptyList) {
- Err(ParserError::InvalidModuleDecl)
- } else {
- Ok(ModuleDecl { name, exports })
- }
-}
-
-fn read_library_path(
- term: Term,
- atom_tbl: TabledData<Atom>,
-) -> Option<ClauseName> {
- match term {
- Term::Constant(_, Constant::Atom(atom, _)) => {
- Some(atom.defrock_brackets())
- }
- _ => {
- let mut atoms = vec![];
-
- for term in unfold_by_str(term, "/") {
- match term {
- Term::Constant(_, Constant::Atom(atom, _)) => {
- atoms.push(atom.as_str().to_owned());
- }
- _ => return None,
- }
- }
-
- Some(clause_name!(atoms.join("/"), atom_tbl))
- }
- }
-}
-
-fn setup_use_module_decl(mut terms: Vec<Box<Term>>, atom_tbl: TabledData<Atom>) -> Result<ModuleSource, ParserError> {
- match *terms.pop().unwrap() {
- Term::Clause(_, ref name, ref mut terms, None)
- if name.as_str() == "library" && terms.len() == 1 =>
- {
- read_library_path(*terms.pop().unwrap(), atom_tbl)
- .map(|c| ModuleSource::Library(c))
- .ok_or(ParserError::InvalidUseModuleDecl)
- }
- Term::Constant(_, Constant::Atom(ref name, _)) =>
- Ok(ModuleSource::File(name.clone())),
- _ => Err(ParserError::InvalidUseModuleDecl),
- }
-}
-
-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>);
-
-fn setup_qualified_import(
- mut terms: Vec<Box<Term>>,
- atom_tbl: TabledData<Atom>,
-) -> Result<UseModuleExport, ParserError> {
- let mut export_list = *terms.pop().unwrap();
- let module_src = match *terms.pop().unwrap() {
- Term::Clause(_, ref name, ref mut terms, None)
- if name.as_str() == "library" && terms.len() == 1 =>
- {
- read_library_path(*terms.pop().unwrap(), atom_tbl.clone())
- .map(|c| ModuleSource::Library(c))
- .ok_or(ParserError::InvalidUseModuleDecl)
- }
- Term::Constant(_, Constant::Atom(ref name, _)) => Ok(ModuleSource::File(name.clone())),
- _ => Err(ParserError::InvalidUseModuleDecl),
- }?;
-
- let mut exports = vec![];
-
- while let Term::Cons(_, t1, t2) = export_list {
- exports.push(setup_module_export(*t1, atom_tbl.clone())?);
- export_list = *t2;
- }
-
- if export_list.to_constant() != Some(Constant::EmptyList) {
- Err(ParserError::InvalidModuleDecl)
- } else {
- Ok((module_src, exports))
- }
-}
-
-fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, ParserError>
-{
- let mut clauses: Vec<PredicateClause> = vec![];
-
- while let Some(tl) = tls.pop_front() {
- match tl {
- TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => return Ok(tl),
- TopLevel::Declaration(_) if clauses.is_empty() => return Ok(tl),
- TopLevel::Query(_) => return Err(ParserError::InconsistentEntry),
- TopLevel::Fact(..) => {
- if let TopLevel::Fact(fact, line_num, col_num) = tl {
- let clause = PredicateClause::Fact(fact, line_num, col_num);
- clauses.push(clause);
- }
- }
- TopLevel::Rule(..) => {
- if let TopLevel::Rule(rule, line_num, col_num) = tl {
- let clause = PredicateClause::Rule(rule, line_num, col_num);
- clauses.push(clause);
- }
- }
- TopLevel::Predicate(..) => {
- if let TopLevel::Predicate(predicate) = tl {
- clauses.extend(predicate.clauses().into_iter())
- }
- }
- _ => {
- tls.push_front(tl);
- break;
- }
- }
- }
-
- if clauses.is_empty() {
- Err(ParserError::InconsistentEntry)
- } else {
- Ok(TopLevel::Predicate(Predicate(clauses)))
- }
-}
-
-fn mark_cut_variables_as(terms: &mut Vec<Term>, name: ClauseName) {
- for term in terms.iter_mut() {
- match term {
- &mut Term::Constant(_, Constant::Atom(ref mut var, _)) if var.as_str() == "!" => {
- *var = name.clone()
- }
- _ => {}
- }
- }
-}
-
-fn mark_cut_variable(term: &mut Term) -> bool {
- let cut_var_found = match term {
- &mut Term::Constant(_, Constant::Atom(ref var, _)) if var.as_str() == "!" => true,
- _ => false,
- };
-
- if cut_var_found {
- *term = Term::Var(Cell::default(), rc_atom!("!"));
- true
- } else {
- false
- }
-}
-
-fn mark_cut_variables(terms: &mut Vec<Term>) -> bool {
- let mut found_cut_var = false;
-
- for item in terms.iter_mut() {
- found_cut_var = mark_cut_variable(item) || found_cut_var;
- }
-
- found_cut_var
-}
-
-// terms is a list of goals composing one clause in a (;) functor. it
-// checks that the first (and only) of these clauses is a ->. if so,
-// it expands its terms using a blocked_!.
-fn check_for_internal_if_then(terms: &mut Vec<Term>) {
- if terms.len() != 1 {
- return;
- }
-
- if let Some(Term::Clause(_, ref name, ref subterms, _)) = terms.last() {
- if name.as_str() != "->" || subterms.len() != 2 {
- return;
- }
- } else {
- return;
- }
-
- if let Some(Term::Clause(_, _, mut subterms, _)) = terms.pop() {
- let mut conq_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
- let mut pre_cut_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
-
- conq_terms.push_front(Term::Constant(
- Cell::default(),
- Constant::Atom(clause_name!("blocked_!"), None))
- );
-
- while let Some(term) = pre_cut_terms.pop_back() {
- conq_terms.push_front(term);
- }
-
- let tail_term = conq_terms.pop_back().unwrap();
-
- terms.push(fold_by_str(
- conq_terms.into_iter(),
- tail_term,
- clause_name!(","),
- ));
- }
-}
-
-fn flatten_hook(mut term: Term) -> Term {
- if let Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
- match (name.as_str(), terms.len()) {
- (":-", 2) => {
- let inner_term = match terms.first_mut().map(|term| term.borrow_mut()) {
- Some(&mut Term::Clause(_, ref name, ref mut inner_terms, _)) => {
- if name.as_str() == ":" && inner_terms.len() == 2 {
- Some(*inner_terms.pop().unwrap())
- } else {
- None
- }
- }
- _ => None,
- };
-
- if let Some(inner_term) = inner_term {
- mem::swap(&mut terms[0], &mut Box::new(inner_term));
- }
- }
- (":", 2) => return *terms.pop().unwrap(),
- _ => {}
- }
- }
-
- term
-}
-
-fn draw_from_term_dir_impl(
- term_dir: &TermDir,
- term_dirs: &mut TermDirQuantum,
- key: &PredicateKey,
- preds: &mut Vec<PredicateClause>,
- queue: &mut VecDeque<TopLevel>
-) {
- if let Some(entry) = term_dirs.get_mut(key) {
- if entry.is_fresh {
- entry.is_fresh = false;
-
- (entry.new_terms.0).0.extend(preds.drain(0 ..));
- entry.new_terms.1.extend(queue.drain(0 ..));
-
- *preds = (entry.old_terms.0).0
- .iter()
- .cloned()
- .chain((entry.new_terms.0).0.iter().cloned())
- .collect();
-
- *queue = entry.old_terms.1
- .iter()
- .cloned()
- .chain(entry.new_terms.1.iter().cloned())
- .collect();
- } else {
- *entry = TermDirQuantumEntry::new();
- }
- } else if term_dir.contains_key(key) {
- let entry = TermDirQuantumEntry::from(&Predicate::new(), &VecDeque::new());
- term_dirs.insert(key.clone(), entry);
- }
-}
-
-fn draw_from_term_dir(
- indices: &CompositeIndices,
- intra_module_term_dirs: &mut IndexMap<ClauseName, TermDirQuantum>,
- top_level_term_dirs: &mut TermDirQuantum,
- key: &PredicateKey,
- preds: &mut Vec<PredicateClause>,
- queue: &mut VecDeque<TopLevel>,
-) {
- let module = key.0.owning_module();
-
- // aaarghhh..
- match indices.term_stream.wam.indices.in_situ_module_dir.get(&module) {
- // modify module_stub to do this right.
- Some(ref module_stub) if key.0.has_table(&module_stub.atom_tbl) => {
- if let Some(ref mut term_dirs) = intra_module_term_dirs.get_mut(&module) {
- if let Some(ref module) = indices.term_stream.wam.indices.modules.get(&module) {
- return draw_from_term_dir_impl(
- &module.term_dir,
- term_dirs,
- key,
- preds,
- queue,
- );
- }
- }
- }
- _ => {}
- }
-
- draw_from_term_dir_impl(
- &indices.term_stream.wam.code_repo.term_dir,
- top_level_term_dirs,
- key,
- preds,
- queue,
- );
-}
-
-fn setup_declaration<'a, 'b, 'c>(
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- flags: MachineFlags,
- mut terms: Vec<Box<Term>>,
- line_num: usize,
- col_num: usize,
-) -> Result<Declaration, ParserError> {
- let term = *terms.pop().unwrap();
-
- match term {
- Term::Clause(_, name, mut terms, _) =>
- match (name.as_str(), terms.len()) {
- ("dynamic", 1) => {
- let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
- Ok(Declaration::Dynamic(name, arity))
- }
- ("initialization", 1) => {
- let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
- let (query_terms, _) = rel_worker.setup_query(indices, terms, false, false)?;
- let queue = rel_worker.parse_queue(indices)?;
-
- Ok(Declaration::ModuleInitialization(query_terms, queue))
- }
- ("module", 2) =>
- Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
- ("op", 3) =>
- Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
- ("non_counted_backtracking", 1) => {
- let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
- Ok(Declaration::NonCountedBacktracking(name, arity))
- }
- ("set_prolog_flag", 2) => {
- Ok(Declaration::SetPrologFlag(setup_double_quotes(terms)?))
- }
- ("multifile", 1) => {
- let mut term = *terms.pop().unwrap();
-
- match setup_predicate_indicator(&mut term) {
- Ok((name, arity)) => {
- Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity)))
- }
- _ => {
- setup_scoped_predicate_indicator(&mut term)
- .map(|key| {
- Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key))
- })
- }
- }
- }
- ("use_module", 1) => {
- Ok(Declaration::UseModule(setup_use_module_decl(terms, indices.atom_tbl())?))
- }
- ("use_module", 2) => {
- let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
- Ok(Declaration::UseQualifiedModule(name, exports))
- }
- _ => {
- Err(ParserError::InconsistentEntry)
- }
- },
- _ => {
- Err(ParserError::InconsistentEntry)
- }
- }
-}
-
-#[derive(Debug)]
-struct RelationWorker {
- flags: MachineFlags,
- dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
- queue: VecDeque<VecDeque<Term>>,
- line_num: usize,
- col_num: usize
-}
-
-impl RelationWorker {
- fn new(flags: MachineFlags, line_num: usize, col_num: usize) -> Self {
- RelationWorker {
- dynamic_clauses: vec![],
- flags,
- queue: VecDeque::new(),
- line_num,
- col_num
- }
- }
-
- fn setup_fact(&mut self, term: Term, assume_dyn: bool) -> Result<Term, ParserError> {
- match term {
- Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => {
- let tail =
- Term::Constant(Cell::default(), Constant::Atom(clause_name!("true"), None));
-
- if assume_dyn {
- self.dynamic_clauses.push((term.clone(), tail));
- }
-
- Ok(term)
- }
- _ => Err(ParserError::InadmissibleFact),
- }
- }
-
- fn compute_head(&self, term: &Term) -> Vec<Term> {
- let mut vars = IndexSet::new();
-
- for term in post_order_iter(term) {
- if let TermRef::Var(_, _, v) = term {
- vars.insert(v.clone());
- }
- }
-
- vars.insert(rc_atom!("!"));
- vars.into_iter()
- .map(|v| Term::Var(Cell::default(), v))
- .collect()
- }
-
- fn fabricate_rule_body(&self, vars: &Vec<Term>, body_term: Term) -> Term {
- let vars_of_head = vars.iter().cloned().map(Box::new).collect();
- let head_term = Term::Clause(Cell::default(), clause_name!(""), vars_of_head, None);
-
- let rule = vec![Box::new(head_term), Box::new(body_term)];
- let turnstile = clause_name!(":-");
-
- Term::Clause(Cell::default(), turnstile, rule, None)
- }
-
- // the terms form the body of the rule. We create a head, by
- // gathering variables from the body of terms and recording them
- // in the head clause.
- fn fabricate_rule(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
- // collect the vars of body_term into a head, return the num_vars
- // (the arity) as well.
- let vars = self.compute_head(&body_term);
- let rule = self.fabricate_rule_body(&vars, body_term);
-
- (vars, VecDeque::from(vec![rule]))
- }
-
- fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
- let vars = self.compute_head(&body_term);
- let results = unfold_by_str(body_term, ";")
- .into_iter()
- .map(|term| {
- let mut subterms = unfold_by_str(term, ",");
- mark_cut_variables(&mut subterms);
-
- check_for_internal_if_then(&mut subterms);
-
- let term = subterms.pop().unwrap();
- let clause = fold_by_str(subterms.into_iter(), term, clause_name!(","));
-
- self.fabricate_rule_body(&vars, clause)
- })
- .collect();
-
- (vars, results)
- }
-
- fn fabricate_if_then(&self, prec: Term, conq: Term) -> (JumpStub, VecDeque<Term>) {
- let mut prec_seq = unfold_by_str(prec, ",");
- let comma_sym = clause_name!(",");
- let cut_sym = atom!("!");
-
- prec_seq.push(Term::Constant(Cell::default(), cut_sym));
-
- mark_cut_variables_as(&mut prec_seq, clause_name!("blocked_!"));
-
- let mut conq_seq = unfold_by_str(conq, ",");
-
- mark_cut_variables(&mut conq_seq);
- prec_seq.extend(conq_seq.into_iter());
-
- let back_term = Box::new(prec_seq.pop().unwrap());
- let front_term = Box::new(prec_seq.pop().unwrap());
-
- let body_term = Term::Clause(
- Cell::default(),
- comma_sym.clone(),
- vec![front_term, back_term],
- None,
- );
-
- self.fabricate_rule(fold_by_str(prec_seq.into_iter(), body_term, comma_sym))
- }
-
- fn to_query_term<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- term: Term,
- ) -> Result<QueryTerm, ParserError> {
- match term {
- Term::Constant(_, Constant::Atom(name, fixity)) => {
- if name.as_str() == "!" || name.as_str() == "blocked_!" {
- Ok(QueryTerm::BlockedCut)
- } else {
- let ct = indices.get_clause_type(name, 0, fixity);
- Ok(QueryTerm::Clause(Cell::default(), ct, vec![], false))
- }
- }
- Term::Var(_, ref v) if v.as_str() == "!" => {
- Ok(QueryTerm::UnblockedCut(Cell::default()))
- }
- Term::Clause(r, name, mut terms, fixity) => match (name.as_str(), terms.len()) {
- (";", 2) => {
- let term = Term::Clause(r, name.clone(), terms, fixity);
- let (stub, clauses) = self.fabricate_disjunct(term);
-
- self.queue.push_back(clauses);
- Ok(QueryTerm::Jump(stub))
- }
- ("->", 2) => {
- let conq = *terms.pop().unwrap();
- let prec = *terms.pop().unwrap();
-
- let (stub, clauses) = self.fabricate_if_then(prec, conq);
-
- self.queue.push_back(clauses);
- Ok(QueryTerm::Jump(stub))
- }
- ("\\+", 1) => {
- terms.push(Box::new(Term::Constant(
- Cell::default(),
- Constant::Atom(clause_name!("$fail"), None)
- )));
-
- let conq = Term::Constant(
- Cell::default(),
- Constant::Atom(clause_name!("true"), None)
- );
-
- let prec = Term::Clause(Cell::default(), clause_name!("->"), terms, None);
- let terms = vec![Box::new(prec), Box::new(conq)];
-
- let term = Term::Clause(Cell::default(), clause_name!(";"), terms, None);
- let (stub, clauses) = self.fabricate_disjunct(term);
-
- debug_assert!(clauses.len() > 0);
- self.queue.push_back(clauses);
- Ok(QueryTerm::Jump(stub))
- }
- ("$get_level", 1) => {
- if let Term::Var(_, ref var) = *terms[0] {
- Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone()))
- } else {
- Err(ParserError::InadmissibleQueryTerm)
- }
- }
- _ => {
- let ct = indices.get_clause_type(name, terms.len(), fixity);
- Ok(QueryTerm::Clause(Cell::default(), ct, terms, false))
- }
- }
- Term::Var(..) => Ok(QueryTerm::Clause(
- Cell::default(),
- ClauseType::CallN,
- vec![Box::new(term)],
- false,
- )),
- _ => Err(ParserError::InadmissibleQueryTerm),
- }
- }
-
- fn pre_query_term<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- term: Term,
- ) -> Result<QueryTerm, ParserError> {
- match term {
- Term::Clause(r, name, mut subterms, fixity) => {
- if subterms.len() == 1 && name.as_str() == "$call_with_default_policy" {
- self.to_query_term(indices, *subterms.pop().unwrap())
- .map(|mut query_term| {
- query_term.set_default_caller();
- query_term
- })
- } else {
- self.to_query_term(indices, Term::Clause(r, name, subterms, fixity))
- }
- }
- _ => self.to_query_term(indices, term),
- }
- }
-
- fn setup_query<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- terms: Vec<Box<Term>>,
- blocks_cuts: bool,
- assume_dyn: bool,
- ) -> Result<(Vec<QueryTerm>, Term), ParserError> {
- let mut query_terms = vec![];
- let mut work_queue = VecDeque::from(terms);
- let mut machine_st = MachineState::new();
-
- let mut dynamic_clause_terms = vec![];
-
- while let Some(term) = work_queue.pop_front() {
- let term = *term;
- let op_dir = op_dir(&indices.index_src);
-
- let mut expanded_terms = indices.term_stream.expand_goals(
- &mut machine_st,
- op_dir.as_ref(),
- VecDeque::from(vec![term])
- )?;
-
- while let Some(term) = expanded_terms.pop() {
- work_queue.push_front(Box::new(term));
- }
-
- if let Some(term) = work_queue.pop_front() {
- let mut term = *term;
-
- if let Term::Clause(cell, name, terms, op_spec) = term {
- if name.as_str() == "," && terms.len() == 2 {
- let term = Term::Clause(cell, name, terms, op_spec);
- let mut subterms = unfold_by_str(term, ",");
-
- while let Some(subterm) = subterms.pop() {
- work_queue.push_front(Box::new(subterm));
- }
-
- continue;
- } else {
- term = Term::Clause(cell, name, terms, op_spec);
- }
- }
-
- if !blocks_cuts {
- mark_cut_variable(&mut term);
- }
-
- if assume_dyn {
- dynamic_clause_terms.push(term.clone());
- }
-
- query_terms.push(self.pre_query_term(indices, term)?);
- }
- }
-
- let dynamic_clause_body =
- if let Some(term) = dynamic_clause_terms.pop() {
- fold_by_str(dynamic_clause_terms.into_iter(), term, clause_name!(","))
- } else {
- Term::Constant(Cell::default(), Constant::Atom(clause_name!("true"), None))
- };
-
- Ok((query_terms, dynamic_clause_body))
- }
-
- fn setup_hook<'a, 'b, 'c>(
- &mut self,
- hook: CompileTimeHook,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- term: Term,
- ) -> Result<CompileTimeHookCompileInfo, ParserError> {
- match flatten_hook(term) {
- Term::Clause(r, name, terms, _) => {
- if name == hook.name() && terms.len() == hook.arity() {
- let term = self.setup_fact(Term::Clause(r, name, terms, None), false)?;
- Ok((hook, PredicateClause::Fact(term, 0, 0), VecDeque::from(vec![])))
- } else if name.as_str() == ":-" && terms.len() == 2 {
- let rule = self.setup_rule(indices, terms, true, false)?;
- let results_queue = self.parse_queue(indices)?;
-
- Ok((hook, PredicateClause::Rule(rule, 0, 0), results_queue))
- } else {
- Err(ParserError::InvalidHook)
- }
- }
- _ => Err(ParserError::InvalidHook),
- }
- }
-
- fn setup_rule<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- mut terms: Vec<Box<Term>>,
- blocks_cuts: bool,
- assume_dyn: bool,
- ) -> Result<Rule, ParserError> {
- let dynamic_term_head = *terms.first().cloned().unwrap();
- let post_head_terms: Vec<_> = terms.drain(1 ..).collect();
-
- let (mut query_terms, dynamic_term_body) =
- self.setup_query(indices, post_head_terms, blocks_cuts, assume_dyn)?;
-
- if assume_dyn {
- self.dynamic_clauses.push((dynamic_term_head, dynamic_term_body));
- }
-
- let clauses = query_terms.drain(1 ..).collect();
- let qt = query_terms.pop().unwrap();
-
- match *terms.pop().unwrap() {
- Term::Clause(_, name, terms, _) => Ok(Rule {
- head: (name, terms, qt),
- clauses,
- }),
- Term::Constant(_, Constant::Atom(name, _)) => Ok(Rule {
- head: (name, vec![], qt),
- clauses,
- }),
- _ => Err(ParserError::InvalidRuleHead),
- }
- }
-
- fn try_term_to_query<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- terms: Vec<Box<Term>>,
- blocks_cuts: bool,
- ) -> Result<TopLevel, ParserError> {
- let (result, _) = self.setup_query(
- indices,
- terms,
- blocks_cuts,
- false,
- )?;
-
- Ok(TopLevel::Query(result))
- }
-
- fn compact_module_scoped_head<'a, 'b, 'c>(
- &self,
- term: &mut Term,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- ) {
- let inner_term = match term {
- Term::Clause(_, ref name, ref mut inner_terms, _)
- if name.as_str() == ":" && inner_terms.len() == 2 => {
- let module_name = match inner_terms[0].as_ref() {
- &Term::Constant(_, Constant::Atom(ref module, _)) => {
- module.clone()
- }
- _ => {
- return;
- }
- };
-
- indices.add_in_situ_module_info(module_name, inner_terms[1].deref_mut());
- *inner_terms.pop().unwrap()
- }
- _ => {
- return;
- }
- };
-
- *term = inner_term;
- }
-
- fn try_term_to_tl<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- term: Term,
- blocks_cuts: bool,
- ) -> Result<TopLevel, ParserError> {
- match term {
- Term::Clause(r, name, mut terms, fixity) => {
- if let Some(hook) = is_compile_time_hook(&name, &terms) {
- let term = Term::Clause(r, name, terms, fixity);
- let (hook, clause, queue) = self.setup_hook(hook, indices, term)?;
-
- Ok(TopLevel::Declaration(Declaration::Hook(
- hook, clause, queue,
- )))
- } else if name.as_str() == "?-" {
- self.try_term_to_query(indices, terms, blocks_cuts)
- } else if name.as_str() == ":-" && terms.len() == 2 {
- self.compact_module_scoped_head(&mut terms[0], indices);
-
- Ok(TopLevel::Rule(self.setup_rule(
- indices,
- terms,
- blocks_cuts,
- true,
- )?, self.line_num, self.col_num))
- } else if name.as_str() == ":-" && terms.len() == 1 {
- Ok(TopLevel::Declaration(setup_declaration(indices, self.flags, terms,
- self.line_num, self.col_num)?))
- } else {
- let mut term = Term::Clause(r, name, terms, fixity);
- self.compact_module_scoped_head(&mut term, indices);
-
- Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
- }
- }
- term => {
- Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
- }
- }
- }
-
- fn try_terms_to_tls<'a, 'b, 'c, I>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- terms: I,
- blocks_cuts: bool,
- ) -> Result<VecDeque<TopLevel>, ParserError>
- where
- I: IntoIterator<Item = Term>
- {
- let mut results = VecDeque::new();
-
- for term in terms.into_iter() {
- results.push_back(self.try_term_to_tl(indices, term, blocks_cuts)?);
- }
-
- Ok(results)
- }
-
- fn parse_queue<'a, 'b, 'c>(
- &mut self,
- indices: &mut CompositeIndices<'a, 'b, 'c>,
- ) -> Result<VecDeque<TopLevel>, ParserError> {
- let mut queue = VecDeque::new();
-
- while let Some(terms) = self.queue.pop_front() {
- let clauses = merge_clauses(&mut self.try_terms_to_tls(indices, terms, false)?)?;
- queue.push_back(clauses);
- }
-
- Ok(queue)
- }
-
- fn absorb(&mut self, other: RelationWorker) {
- self.queue.extend(other.queue.into_iter());
- self.dynamic_clauses.extend(other.dynamic_clauses.into_iter());
- }
-}
-
-pub type DynamicClause = Vec<(Term, Term)>;
-
-pub type DynamicClauseMap = IndexMap<(ClauseName, usize), DynamicClause>;
-
-#[derive(Debug)]
-pub struct TopLevelBatchWorker<'a> {
- pub(crate) term_stream: TermStream<'a>,
- rel_worker: RelationWorker,
- pub(crate) results: Vec<(Predicate, VecDeque<TopLevel>)>,
- pub(crate) dynamic_clause_map: DynamicClauseMap,
- pub(crate) in_module: bool,
- pub(crate) term_dirs: TermDirQuantum,
- pub(crate) intra_module_term_dirs: IndexMap<ClauseName, TermDirQuantum>,
- pub(crate) non_counted_bt_preds: IndexSet<PredicateKey>,
-}
-
-impl<'a> TopLevelBatchWorker<'a> {
- pub fn new(
- stream: &'a mut ParsingStream<Stream>,
- atom_tbl: TabledData<Atom>,
- flags: MachineFlags,
- wam: &'a mut Machine,
- ) -> Self {
- let term_stream = TermStream::new(stream, atom_tbl, flags, wam);
-
- let line_num = term_stream.line_num();
- let col_num = term_stream.col_num();
-
- TopLevelBatchWorker {
- term_stream,
- rel_worker: RelationWorker::new(flags, line_num, col_num),
- results: vec![],
- dynamic_clause_map: IndexMap::new(),
- in_module: false,
- term_dirs: TermDirQuantum::new(),
- intra_module_term_dirs: IndexMap::new(),
- non_counted_bt_preds: IndexSet::new(),
- }
- }
-
- fn try_term_to_tl(
- &mut self,
- indices: &mut IndexStore,
- term: Term,
- ) -> Result<(TopLevel, RelationWorker), SessionError> {
- let line_num = self.term_stream.line_num();
- let col_num = self.term_stream.col_num();
-
- let mut new_rel_worker = RelationWorker::new(self.rel_worker.flags, line_num, col_num);
- let mut indices = CompositeIndices::new(
- &mut self.term_stream,
- IndexSource::Local(indices),
- if self.in_module { None } else { Some(IndexSource::TermStream) }
- );
-
- Ok((
- new_rel_worker.try_term_to_tl(&mut indices, term, true)?,
- new_rel_worker,
- ))
- }
-
- fn process_result(
- &mut self,
- indices: &mut IndexStore,
- preds: &mut Vec<PredicateClause>,
- ) -> Result<(), SessionError> {
- let mut indices = CompositeIndices::new(
- &mut self.term_stream,
- IndexSource::Local(indices),
- if self.in_module { None } else { Some(IndexSource::TermStream) },
- );
-
- let key = (preds[0].name().unwrap(), preds[0].arity());
-
- let mut preds = mem::replace(preds, vec![]);
- let mut queue = self.rel_worker.parse_queue(&mut indices)?;
-
- draw_from_term_dir(
- &indices,
- &mut self.intra_module_term_dirs,
- &mut self.term_dirs,
- &key,
- &mut preds,
- &mut queue,
- );
-
- let result = (Predicate(preds), queue);
-
- indices.term_stream.wam.code_repo.add_in_situ_result(
- &result,
- &mut indices.term_stream.wam.indices.in_situ_code_dir,
- &mut indices.term_stream.wam.indices.in_situ_module_dir,
- &self.non_counted_bt_preds,
- )?;
-
- Ok(self.results.push(result))
- }
-
- fn take_dynamic_clauses(&mut self) {
- let (name, arity) = match self.rel_worker.dynamic_clauses.first() {
- Some((head, _)) => (head.name().unwrap(), head.arity()),
- None => return,
- };
-
- match self.dynamic_clause_map.get_mut(&(name.clone(), arity)) {
- Some(ref mut entry) => {
- entry.clear(); // don't treat dynamic predicates as if they're discontiguous.
- entry.extend(self.rel_worker.dynamic_clauses.drain(0 ..));
- }
- _ => {
- self.rel_worker.dynamic_clauses.clear();
- }
- }
- }
-
- pub fn consume(
- &mut self,
- indices: &mut IndexStore,
- ) -> Result<Option<Declaration>, SessionError> {
- let mut preds = vec![];
-
- while !self.term_stream.eof()? {
- let term = self.term_stream.read_term(&indices.op_dir)?;
-
- // if is_consistent is false, preds is non-empty.
- let term = if !term.is_consistent(&preds) {
- self.process_result(indices, &mut preds)?;
- self.take_dynamic_clauses();
-
- // expand the term after the addition of the previous
- // predicate.
- self.term_stream.expand_term(term, &indices.op_dir)?
- } else {
- term
- };
-
- let (mut tl, new_rel_worker) = self.try_term_to_tl(indices, term)?;
-
- if tl.is_end_of_file_atom() {
- tl = TopLevel::Declaration(Declaration::EndOfFile);
- }
-
- self.rel_worker.absorb(new_rel_worker);
-
- match tl {
- TopLevel::Fact(fact, line_num, col_num) =>
- preds.push(PredicateClause::Fact(fact, line_num, col_num)),
- TopLevel::Rule(rule, line_num, col_num) =>
- preds.push(PredicateClause::Rule(rule, line_num, col_num)),
- TopLevel::Predicate(pred) =>
- preds.extend(pred.0),
- TopLevel::Declaration(decl) =>
- return Ok(Some(decl)),
- TopLevel::Query(_) =>
- return Err(SessionError::QueryCannotBeDefinedAsFact),
- }
- }
-
- if !preds.is_empty() {
- self.process_result(indices, &mut preds)?;
- self.take_dynamic_clauses();
- }
-
- Ok(None)
- }
-}
});
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
{
+ use crate::machine::heap::*;
+
let arity = count_tt!($($dt) +);
+ #[allow(unused_variables, unused_mut)]
+ let mut addendum = Heap::new();
+
+ let mut result =
+ vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
+ $(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
- vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
- $(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ]
+ result.extend(addendum.into_iter());
+ result
}
});
($name:expr, $fixity:expr) => (
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
$e.into()
);
- (integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
+ (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) => (
+ (indexing_code_ptr($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
+ let stub =
+ match $e {
+ IndexingCodePtr::External(o) => functor!("external", [integer(o)]),
+ IndexingCodePtr::Internal(o) => functor!("internal", [integer(o)]),
+ IndexingCodePtr::Fail => vec![HeapCellValue::Atom(clause_name!("fail"), None)],
+ };
+
+ let len: usize = $aux_lens.iter().sum();
+ let h = len + $arity + 1 + $addendum.h() + $h;
+
+ $addendum.extend(stub.into_iter());
+
+ HeapCellValue::Addr(Addr::HeapCell(h))
+ });
+ (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) => (
+ (atom($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
HeapCellValue::Atom(clause_name!($e), None)
);
(value($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
};
}
-macro_rules! try_eval_session {
- ($e:expr) => {
- match $e {
- Ok(result) => result,
- Err(e) => return EvalSession::from(e),
- }
- };
-}
macro_rules! return_from_clause {
($lco:expr, $machine_st:expr) => {{
if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
};
}
-macro_rules! set_code_index {
- ($idx:expr, $ip:expr, $mod_name:expr) => {{
- let mut idx = $idx.0.borrow_mut();
-
- idx.0 = $ip;
- idx.1 = $mod_name.clone();
- }};
-}
-
macro_rules! index_store {
- ($atom_tbl:expr, $code_dir:expr, $op_dir:expr, $modules:expr) => {
+ ($code_dir:expr, $op_dir:expr, $modules:expr) => {
IndexStore {
- atom_tbl: $atom_tbl,
code_dir: $code_dir,
- module_dir: ModuleDir::new(),
- dynamic_code_dir: DynamicCodeDir::new(),
+ extensible_predicates: ExtensiblePredicates::new(),
global_variables: GlobalVarDir::new(),
- in_situ_code_dir: InSituCodeDir::new(),
- in_situ_module_dir: ModuleStubDir::new(),
- op_dir: $op_dir,
+ meta_predicates: MetaPredicateDir::new(),
modules: $modules,
- stream_aliases: StreamAliasDir::new(),
+ op_dir: $op_dir,
streams: StreamDir::new(),
+ stream_aliases: StreamAliasDir::new(),
}
};
}
-macro_rules! default_index_store {
- ($atom_tbl:expr) => {
- index_store!($atom_tbl, CodeDir::new(), default_op_dir(), IndexMap::new())
- };
-}
-
macro_rules! put_constant {
($lvl:expr, $cons:expr, $r:expr) => {
QueryInstruction::PutConstant($lvl, $cons, $r)
};
}
+/*
macro_rules! unwind_protect {
($e: expr, $protected: expr) => {
match $e {
}
};
}
-
+*/
+/*
macro_rules! discard_result {
($f: expr) => {
match $f {
}
};
}
-
+*/
macro_rules! ar_reg {
($r: expr) => {
ArithmeticTerm::Reg($r)
}
macro_rules! atom_from {
- ($self:expr, $indices:expr, $e:expr) => {
+ ($self:expr, $e:expr) => {
match $e {
Addr::Con(h) if $self.heap.atom_at(h) => {
match &$self.heap[h] {
}
}
Addr::Char(c) => {
- clause_name!(c.to_string(), $indices.atom_tbl.clone())
+ clause_name!(c.to_string(), $self.atom_tbl)
}
_ => {
unreachable!()
}
}
}
+
+macro_rules! try_or_fail {
+ ($s:expr, $e:expr) => {{
+ match $e {
+ Ok(val) => val,
+ Err(msg) => {
+ $s.throw_exception(msg);
+ return;
+ }
+ }
+ }};
+}
mod macros;
mod allocator;
mod arithmetic;
+mod machine;
mod codegen;
mod clause_types;
mod debray_allocator;
mod indexing;
mod instructions;
mod iterators;
-mod machine;
mod read;
mod targets;
mod write;
let term = {
let mut parser = Parser::new(&mut stream, atom_tbl, self.flags);
- parser.read_term(composite_op!(op_dir))?
+ parser.read_term(&CompositeOpDir::new(op_dir, None))?
};
// 'pausing' the stream saves the pending top buffer
--- /dev/null
+% Unsure how to handle the printing of exceptions from term & goal expansion.
+
+'$print_message_and_fail'(Error, Culprit) :-
+% writeq(error(Error, Culprit)),
+% nl,
+ '$fail'.
+
+term_expansion(Term, ExpandedTerm) :-
+ ( catch(user:'$term_expansion'(Term, ExpandedTerm0),
+ E,
+ user:'$print_message_and_fail'(E, user:term_expansion)) ->
+ ( var(ExpandedTerm0) ->
+ error:instantiation_error(term_expansion/2)
+ ; ExpandedTerm0 = [_|_] ->
+ term_expansion_list(ExpandedTerm0, ExpandedTerm, [])
+ ; term_expansion(ExpandedTerm0, ExpandedTerm)
+ )
+ ; Term = ExpandedTerm
+ ).
+
+
+term_expansion_list([], ExpandedTerms, ExpandedTerms).
+term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :-
+ term_expansion(Term, ExpandedTerm0),
+ ( var(ExpandedTerm0) ->
+ error:instantiation_error(term_expansion/2)
+ ; ExpandedTerm0 = [_|_] ->
+ term_expansion_list(ExpandedTerm0, ExpandedTermsHead, ExpandedTerms0Tail),
+ term_expansion_list(Terms, ExpandedTerms0Tail, ExpandedTermsTail)
+ ; ExpandedTermsHead = [ExpandedTerm0 | ExpandedTerms0Tail],
+ term_expansion_list(Terms, ExpandedTerms0Tail, ExpandedTermsTail)
+ ).
+
+
+goal_expansion(Goal, Module, ExpandedGoal) :-
+ ( catch(Module:goal_expansion(Goal, ExpandedGoal0),
+ E,
+ user:'$print_message_and_fail'(E, Module:goal_expansion)) ->
+ ( var(ExpandedGoal0) ->
+ error:instantiation_error(goal_expansion/2)
+ ; goal_expansion(ExpandedGoal0, Module, ExpandedGoal)
+ )
+ ; Goal = ExpandedGoal
+ ).
-:- module('$toplevel', ['$repl'/1, consult/1, use_module/1, use_module/2,
- argv/1]).
+:- module('$toplevel', [argv/1,
+ copy_term/3,
+ predicate_property/2,
+ prolog_load_context/2]).
+
+:- use_module(library(loader)).
:- use_module(library(charsio)).
+:- use_module(library(iso_ext)).
:- use_module(library(lists)).
:- use_module(library(si)).
+:- use_module(library('$project_atts')).
+:- use_module(library('$atts')).
+
:- dynamic(argv/1).
'$repl'([_|Args0]) :-
instruction_match(Term, VarList).
-% make compile_batch, a system routine, callable.
-compile_batch :- '$compile_batch'.
-
instruction_match(Term, VarList) :-
( var(Term) ->
throw(error(instantiation_error, repl/0))
!,
( atom(Item) ->
( Item == user ->
- catch(compile_batch, E, print_exception_with_check(E))
- ; consult(Item)
+ catch(load(user_input), E, print_exception_with_check(E))
+ ;
+ consult(Item)
)
;
- catch(throw(error(type_error(atom, Item), repl/0)),
+ catch(type_error(atom, Item, repl/0),
E,
print_exception_with_check(E))
)
; Term = end_of_file ->
halt
- ; submit_query_and_print_results(Term, VarList)
+ ;
+ submit_query_and_print_results(Term, VarList)
).
-:- use_module(library(iso_ext)).
-% auxiliary predicates, so that using them in setup_call_cleanup/3 works
-get_b_value(B) :- '$get_b_value'(B).
-clear_attribute_goals :- '$clear_attribute_goals'.
+submit_query_and_print_results_(Term, VarList) :-
+ '$get_b_value'(B),
+ call(Term),
+ write_eqs_and_read_input(B, VarList),
+ !.
+submit_query_and_print_results_(_, _) :-
+ % clear attribute goal lists, which may be populated by
+ % copy_term/3 prior to failure.
+ '$clear_attribute_goals',
+ write('false.'),
+ nl.
+
submit_query_and_print_results(Term0, VarList) :-
- ( expand_goals(Term0, Term) -> true
- ; Term0 = Term
- ),
+ expand_goal(call(Term0), user, Term),
+ !,
setup_call_cleanup(bb_put('$first_answer', true),
- ( get_b_value(B), call(Term), write_eqs_and_read_input(B, VarList),
- !
- ; % clear attribute goal lists, which may be populated by
- % copy_term/3 prior to failure.
- clear_attribute_goals, write('false.'), nl
- ),
+ submit_query_and_print_results_(Term, VarList),
bb_put('$first_answer', false)).
+
needs_bracketing(Value, Op) :-
catch((functor(Value, F, _),
current_op(EqPrec, EqSpec, Op),
( B0 == B ->
( Goals == [] ->
write('true.'), nl
- ; thread_goals(Goals, ThreadedGoals, (',')),
+ ; loader:thread_goals(Goals, ThreadedGoals, (',')),
write_eq(ThreadedGoals, NewVarList0, 20),
write('.'),
nl
)
- ; thread_goals(Goals, ThreadedGoals, (',')),
+ ; loader:thread_goals(Goals, ThreadedGoals, (',')),
write_eq(ThreadedGoals, NewVarList0, 20),
read_input(ThreadedGoals, NewVarList0)
).
% is expected to be printed instead.
; print_exception(E)
).
-
-module_export(Source, PI) :-
- ( nonvar(PI) ->
- ( PI = Name / Arity ->
- ( var(Name) -> throw(error(instantiation_error, Source))
- ; integer(Arity) ->
- ( \+ atom(Name) -> throw(error(type_error(atom, Name), Source))
- ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), Source))
- ; true
- )
- ; throw(error(type_error(integer, Arity), Source))
- )
- ; PI = op(Prec, Spec, Name) ->
- ( integer(Prec) ->
- ( \+ atom(Name) ->
- throw(error(type_error(atom, Name), Source))
- ; Prec < 0 ->
- throw(error(domain_error(not_less_than_zero, Prec), Source))
- ; Prec > 1200 ->
- throw(error(domain_error(operator_precision, Prec), Source))
- ; memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf])
- ; throw(error(domain_error(operator_specification, Spec), Source))
- )
- ; throw(error(type_error(integer, Prec), Source))
- )
- ; throw(error(type_error(module_export, PI), Source))
- )
- ; throw(error(instantiation_error, Source))
- ).
-
-consult(Item) :-
- ( atom(Item) -> use_module(Item)
- ; throw(error(type_error(atom, Item), consult/1))
- ).
-
-use_module(Module) :-
- ( nonvar(Module) ->
- ( Module = library(Filename) ->
- write_term_to_chars(Filename, [], FilenameString),
- '$use_module'(FilenameString)
- ; atom(Module) ->
- '$use_module_from_file'(Module)
- ; throw(error(invalid_module_specifier, use_module/1))
- )
- ; throw(error(instantiation_error, use_module/1))
- ).
-
-use_module(Module, QualifiedExports) :-
- ( nonvar(Module) ->
- ( list_si(QualifiedExports) ->
- maplist('$module_export'(use_module/2), QualifiedExports) ->
- ( Module = library(Filename) ->
- write_term_to_chars(Filename, [], FilenameString),
- '$use_qualified_module'(FilenameString, QualifiedExports)
- ; atom(Module) ->
- '$use_qualified_module_from_file'(Module, QualifiedExports)
- ; throw(error(invalid_module_specifier, use_module/2))
- )
- ; throw(error(type_error(list, QualifiedExports), use_module/2))
- )
- ; throw(error(instantiation_error, use_module/2))
- ).
-
-
-% expand goals in initialization directives.
-user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
- nonvar(Term0),
- Term0 = (:- initialization(Goals)),
- expand_goals(Goals, ExpandedGoals),
- Goals \== ExpandedGoals.
-
-module_expand_goal(UnexpandedGoals, ExpandedGoals) :-
- ( '$module_of'(Module, UnexpandedGoals),
- '$module_exists'(Module),
- Module:goal_expansion(UnexpandedGoals, ExpandedGoals),
- UnexpandedGoals \== ExpandedGoals ->
- true
- ; user:goal_expansion(UnexpandedGoals, ExpandedGoals)
- ).
-
-expand_goals(UnexpandedGoals, ExpandedGoals) :-
- nonvar(UnexpandedGoals),
- var(ExpandedGoals),
- ( module_expand_goal(UnexpandedGoals, Goals) ->
- true
- ; Goals = UnexpandedGoals
- ),
- ( Goals = (Goal0, Goals0) ->
- ( expand_goals(Goal0, Goal1) ->
- expand_goals(Goals0, Goals1),
- thread_goals(Goal1, ExpandedGoals, Goals1, (','))
- ; expand_goals(Goals0, Goals1),
- ExpandedGoals = (Goal0, Goals1)
- )
- ; Goals = (Goals0 -> Goals1) ->
- expand_goals(Goals0, ExpandedGoals0),
- expand_goals(Goals1, ExpandedGoals1),
- ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1)
- ; Goals = (Goals0 ; Goals1) ->
- expand_goals(Goals0, ExpandedGoals0),
- expand_goals(Goals1, ExpandedGoals1),
- ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
- ; Goals = (\+ Goals0) ->
- expand_goals(Goals0, Goals1),
- ExpandedGoals = (\+ Goals1)
- ; thread_goals(Goals, ExpandedGoals, (','))
- ; Goals = ExpandedGoals
- ).
-
-thread_goals(Goals0, Goals1, Hole, Functor) :-
- nonvar(Goals0),
- ( Goals0 = [G | Gs] ->
- ( Gs == [] ->
- Goals1 =.. [Functor, G, Hole]
- ; Goals1 =.. [Functor, G, Goals2],
- thread_goals(Gs, Goals2, Hole, Functor)
- )
- ; Goals1 =.. [Functor, Goals0, Hole]
- ).
-
-thread_goals(Goals0, Goals1, Functor) :-
- nonvar(Goals0),
- ( Goals0 = [G | Gs] ->
- ( Gs = [] ->
- Goals1 = G
- ; Goals1 =.. [Functor, G, Goals2],
- thread_goals(Gs, Goals2, Functor)
- )
- ; Goals1 = Goals0
- ).
use crate::clause_types::*;
use crate::forms::*;
+use crate::indexing::IndexingCodePtr;
use crate::instructions::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LocalCodePtr::DirEntry(p) => write!(f, "LocalCodePtr::DirEntry({})", p),
- LocalCodePtr::InSituDirEntry(p) => write!(f, "LocalCodePtr::InSituDirEntry({})", p),
- LocalCodePtr::TopLevel(cn, p) => write!(f, "LocalCodePtr::TopLevel({}, {})", cn, p),
- LocalCodePtr::UserGoalExpansion(p) => {
- write!(f, "LocalCodePtr::UserGoalExpansion({})", p)
- }
- LocalCodePtr::UserTermExpansion(p) => {
- write!(f, "LocalCodePtr::UserTermExpansion({})", p)
- }
+ LocalCodePtr::Halt => write!(f, "LocalCodePtr::Halt"),
+ LocalCodePtr::IndexingBuf(p, o, i) => write!(f, "LocalCodePtr::IndexingBuf({}, {}, {})", p, o, i),
}
}
}
impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- REPLCodePtr::CompileBatch =>
- write!(f, "REPLCodePtr::CompileBatch"),
+ REPLCodePtr::AddDynamicPredicate =>
+ write!(f, "REPLCodePtr::AddDynamicPredicate"),
+ REPLCodePtr::AddGoalExpansionClause =>
+ write!(f, "REPLCodePtr::AddGoalExpansionClause"),
+ REPLCodePtr::AddTermExpansionClause =>
+ write!(f, "REPLCodePtr::AddTermExpansionClause"),
+ REPLCodePtr::UserAssertz =>
+ write!(f, "REPLCodePtr::UserAssertz"),
+ REPLCodePtr::UserAsserta =>
+ write!(f, "REPLCodePtr::UserAsserta"),
+ REPLCodePtr::UserRetract =>
+ write!(f, "REPLCodePtr::UserRetract"),
+ REPLCodePtr::ClauseToEvacuable =>
+ write!(f, "REPLCodePtr::ClauseToEvacuable"),
+ REPLCodePtr::ConcludeLoad =>
+ write!(f, "REPLCodePtr::ConcludeLoad"),
+ REPLCodePtr::DeclareModule =>
+ write!(f, "REPLCodePtr::DeclareModule"),
+ REPLCodePtr::LoadCompiledLibrary =>
+ write!(f, "REPLCodePtr::LoadCompiledLibrary"),
+ REPLCodePtr::LoadContextSource =>
+ write!(f, "REPLCodePtr::LoadContextSource"),
+ REPLCodePtr::LoadContextFile =>
+ write!(f, "REPLCodePtr::LoadContextFile"),
+ REPLCodePtr::LoadContextDirectory =>
+ write!(f, "REPLCodePtr::LoadContextDirectory"),
+ REPLCodePtr::LoadContextModule =>
+ write!(f, "REPLCodePtr::LoadContextModule"),
+ REPLCodePtr::LoadContextStream =>
+ write!(f, "REPLCodePtr::LoadContextStream"),
+ REPLCodePtr::PopLoadContext =>
+ write!(f, "REPLCodePtr::PopLoadContext"),
+ REPLCodePtr::PopLoadStatePayload =>
+ write!(f, "REPLCodePtr::PopLoadStatePayload"),
+ REPLCodePtr::PushLoadContext =>
+ write!(f, "REPLCodePtr::PushLoadContext"),
+ REPLCodePtr::PushLoadStatePayload =>
+ write!(f, "REPLCodePtr::PushLoadStatePayload"),
REPLCodePtr::UseModule =>
write!(f, "REPLCodePtr::UseModule"),
- REPLCodePtr::UseQualifiedModule =>
- write!(f, "REPLCodePtr::UseQualifiedModule"),
- REPLCodePtr::UseModuleFromFile =>
- write!(f, "REPLCodePtr::UseModuleFromFile"),
- REPLCodePtr::UseQualifiedModuleFromFile =>
- write!(f, "REPLCodePtr::UseQualifiedModuleFromFile")
+ REPLCodePtr::MetaPredicateProperty =>
+ write!(f, "REPLCodePtr::MetaPredicateProperty"),
+ REPLCodePtr::CompilePendingPredicates =>
+ write!(f, "REPLCodePtr::CompilePendingPredicates"),
}
}
}
&IndexPtr::DynamicUndefined => write!(f, "undefined"),
&IndexPtr::Undefined => write!(f, "undefined"),
&IndexPtr::Index(i) => write!(f, "{}", i),
- &IndexPtr::InSituDirEntry(i) => write!(f, "in_situ({})", i),
- &IndexPtr::UserTermExpansion => write!(f, "user:term_expansion"),
- &IndexPtr::UserGoalExpansion => write!(f, "user:goal_expansion"),
}
}
}
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
}
- &FactInstruction::GetValue(ref x, ref a) => write!(f, "get_value {}, A{}", x, a),
+ &FactInstruction::GetValue(ref x, ref a) => {
+ write!(f, "get_value {}, A{}", x, a)
+ }
&FactInstruction::GetVariable(ref x, ref a) => {
write!(f, "fact:get_variable {}, A{}", x, a)
}
&FactInstruction::UnifyConstant(ref constant) => {
write!(f, "unify_constant {}", constant)
}
- &FactInstruction::UnifyVariable(ref r) => write!(f, "unify_variable {}", r),
- &FactInstruction::UnifyLocalValue(ref r) => write!(f, "unify_local_value {}", r),
- &FactInstruction::UnifyValue(ref r) => write!(f, "unify_value {}", r),
- &FactInstruction::UnifyVoid(n) => write!(f, "unify_void {}", n),
+ &FactInstruction::UnifyVariable(ref r) => {
+ write!(f, "unify_variable {}", r)
+ }
+ &FactInstruction::UnifyLocalValue(ref r) => {
+ write!(f, "unify_local_value {}", r)
+ }
+ &FactInstruction::UnifyValue(ref r) => {
+ write!(f, "unify_value {}", r)
+ }
+ &FactInstruction::UnifyVoid(n) => {
+ write!(f, "unify_void {}", n)
+ }
}
}
}
impl fmt::Display for ClauseType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &ClauseType::System(SystemClauseType::SetCutPoint(r)) => write!(f, "$set_cp({})", r),
+ &ClauseType::System(SystemClauseType::SetCutPoint(r)) => {
+ write!(f, "$set_cp({})", r)
+ }
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
- let idx = idx.0.borrow();
- write!(f, "{}:{}/{}", idx.1, name, idx.0)
+ let idx = idx.0.get();
+ write!(f, "{}/{}", name, idx)
+ }
+ ref ct => {
+ write!(f, "{}", ct.name())
}
- ref ct => write!(f, "{}", ct.name()),
}
}
}
&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::LoadStatePayload(_) => write!(f, "LoadStatePayload"),
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
f,
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
+ &Addr::LoadStatePayload(s) => write!(f, "Addr::LoadStatePayload({})", s),
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
&ControlInstruction::JmpBy(arity, offset, pvs, true) => {
write!(f, "jmp_by_execute {}/{}, {}", offset, arity, pvs)
}
+ &ControlInstruction::RevJmpBy(offset) => {
+ write!(f, "rev_jmp_by {}", offset)
+ }
&ControlInstruction::Proceed => write!(f, "proceed"),
}
}
impl fmt::Display for ChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &ChoiceInstruction::TryMeElse(offset) => write!(f, "try_me_else {}", offset),
+ &ChoiceInstruction::TryMeElse(offset) =>
+ write!(f, "try_me_else {}", offset),
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
write!(f, "retry_me_else_by_default {}", offset)
}
- &ChoiceInstruction::RetryMeElse(offset) => write!(f, "retry_me_else {}", offset),
- &ChoiceInstruction::DefaultTrustMe => write!(f, "trust_me_by_default"),
- &ChoiceInstruction::TrustMe => write!(f, "trust_me"),
+ &ChoiceInstruction::RetryMeElse(offset) =>
+ write!(f, "retry_me_else {}", offset),
+ &ChoiceInstruction::DefaultTrustMe(_) =>
+ write!(f, "trust_me_by_default"),
+ &ChoiceInstruction::TrustMe(_) =>
+ write!(f, "trust_me"),
+ }
+ }
+}
+
+impl fmt::Display for IndexingCodePtr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ &IndexingCodePtr::External(o) => {
+ write!(f, "IndexingCodePtr::External({})", o)
+ }
+ &IndexingCodePtr::Fail => {
+ write!(f, "IndexingCodePtr::Fail")
+ }
+ &IndexingCodePtr::Internal(o) => {
+ write!(f, "IndexingCodePtr::Internal({})", o)
+ }
}
}
}
&IndexingInstruction::SwitchOnTerm(a, v, c, l, s) => {
write!(f, "switch_on_term {}, {}, {}, {}, {}", a, v, c, l, s)
}
- &IndexingInstruction::SwitchOnConstant(_, num_cs, _) => {
- write!(f, "switch_on_constant {}", num_cs)
+ &IndexingInstruction::SwitchOnConstant(ref constants) => {
+ write!(f, "switch_on_constant {}", constants.len())
}
- &IndexingInstruction::SwitchOnStructure(_, num_ss, _) => {
- write!(f, "switch_on_structure {}", num_ss)
+ &IndexingInstruction::SwitchOnStructure(ref structures) => {
+ write!(f, "switch_on_structure {}", structures.len())
}
}
}
&SessionError::ExistenceError(ref err) => {
write!(f, "{}", err)
}
- &SessionError::CannotOverwriteBuiltIn(ref msg) => {
- write!(f, "cannot overwrite {}", msg)
- }
- &SessionError::CannotOverwriteImport(ref msg) => {
- write!(f, "cannot overwrite import {}", msg)
- }
- &SessionError::InvalidFileName(ref filename) => {
- write!(f, "filename {} is invalid", filename)
- }
- &SessionError::ModuleDoesNotContainExport(ref module, ref key) => {
- write!(
- f,
- "module {} does not contain claimed export {}/{}",
- module,
- key.0,
- key.1,
- )
- }
+ // &SessionError::CannotOverwriteBuiltIn(ref msg) => {
+ // write!(f, "cannot overwrite {}", msg)
+ // }
+ // &SessionError::CannotOverwriteImport(ref msg) => {
+ // write!(f, "cannot overwrite import {}", msg)
+ // }
+ // &SessionError::InvalidFileName(ref filename) => {
+ // write!(f, "filename {} is invalid", filename)
+ // }
+ // &SessionError::ModuleDoesNotContainExport(ref module, ref key) => {
+ // write!(
+ // f,
+ // "module {} does not contain claimed export {}/{}",
+ // module,
+ // key.0,
+ // key.1,
+ // )
+ // }
&SessionError::OpIsInfixAndPostFix(_) => {
write!(f, "cannot define an op to be both postfix and infix.")
}
&SessionError::NamelessEntry => {
write!(f, "the predicate head is not an atom or clause.")
}
- &SessionError::ParserError(ref e) => {
- write!(f, "syntax_error({})", e.as_str())
+ &SessionError::CompilationError(ref e) => {
+ write!(f, "syntax_error({:?})", e)
}
&SessionError::QueryCannotBeDefinedAsFact => {
write!(f, "queries cannot be defined as facts.")
}
+ &SessionError::ModuleCannotImportSelf(ref module_name) => {
+ write!(f, "modules ({}, in this case) cannot import themselves.",
+ module_name)
+ }
}
}
}
}
}
+impl fmt::Display for IndexingLine {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ &IndexingLine::Indexing(ref indexing_instr) => {
+ write!(f, "{}", indexing_instr)
+ }
+ &IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
+ for indexed_choice_instr in indexed_choice_instrs {
+ write!(f, "{}", indexed_choice_instr)?;
+ }
+
+ Ok(())
+ }
+ }
+ }
+}
+
impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Line::Control(ref control_instr) => write!(f, "{}", control_instr),
&Line::Cut(ref cut_instr) => write!(f, "{}", cut_instr),
&Line::Fact(ref fact_instr) => write!(f, "{}", fact_instr),
- &Line::Indexing(ref indexing_instr) => write!(f, "{}", indexing_instr),
+ &Line::IndexingCode(ref indexing_instrs) => {
+ for indexing_instr in indexing_instrs {
+ write!(f, "{}", indexing_instr)?;
+ }
+
+ Ok(())
+ }
&Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr),
&Line::Query(ref query_instr) => write!(f, "{}", query_instr),
}