From a4d15bfb88876ccf1707a8e59535daa6a4436911 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 30 Jan 2021 14:32:47 -0700 Subject: [PATCH 001/137] move to a predicate-based module system, move to loader.[rs|pl]-based compilation, add support for incremental clause compilation --- Cargo.lock | 551 +++--- Cargo.toml | 3 +- build.rs | 2 + src/clause_types.rs | 194 +- src/codegen.rs | 280 ++- src/forms.rs | 483 ++--- src/heap_iter.rs | 15 +- src/heap_print.rs | 13 +- src/indexing.rs | 1391 ++++++++++--- src/instructions.rs | 211 +- src/iterators.rs | 4 +- src/lib/atts.pl | 96 +- src/lib/builtins.pl | 738 ++++--- src/lib/clpb.pl | 4 +- src/lib/dcgs.pl | 10 +- src/lib/diag.pl | 20 +- src/lib/dif.pl | 14 +- src/lib/error.pl | 8 +- src/lib/iso_ext.pl | 11 +- src/lib/lists.pl | 32 +- src/lib/ops_and_meta_predicates.pl | 127 ++ src/lib/pairs.pl | 2 + src/lib/tabling/wrapper.pl | 8 +- src/lib/time.pl | 2 + src/loader.pl | 433 +++++ src/machine/attributed_variables.pl | 17 +- src/machine/attributed_variables.rs | 5 +- src/machine/code_repo.rs | 180 +- src/machine/code_walker.rs | 113 +- src/machine/compile.rs | 2783 +++++++++++++++------------ src/machine/dynamic_database.rs | 396 ---- src/machine/heap.rs | 31 +- src/machine/load_state.rs | 918 +++++++++ src/machine/loader.rs | 1708 ++++++++++++++++ src/machine/machine_errors.rs | 178 +- src/machine/machine_indices.rs | 667 +++---- src/machine/machine_state.rs | 664 ++----- src/machine/machine_state_impl.rs | 322 ++-- src/machine/mod.rs | 973 ++++------ src/machine/modules.rs | 371 ---- src/machine/partial_string.rs | 293 +++ src/machine/preprocessor.rs | 987 ++++++++++ src/machine/project_attributes.pl | 61 +- src/machine/stack.rs | 4 - src/machine/streams.rs | 4 +- src/machine/system_calls.rs | 343 ++-- src/machine/term_expansion.rs | 394 ---- src/machine/term_stream.rs | 149 ++ src/machine/toplevel.rs | 1352 ------------- src/macros.rs | 93 +- src/main.rs | 2 +- src/read.rs | 2 +- src/term_and_goal_expansion.pl | 44 + src/toplevel.pl | 188 +- src/write.rs | 208 +- 55 files changed, 10501 insertions(+), 7601 deletions(-) create mode 100644 src/lib/ops_and_meta_predicates.pl create mode 100644 src/loader.pl delete mode 100644 src/machine/dynamic_database.rs create mode 100644 src/machine/load_state.rs create mode 100644 src/machine/loader.rs delete mode 100644 src/machine/modules.rs create mode 100644 src/machine/preprocessor.rs delete mode 100644 src/machine/term_expansion.rs create mode 100644 src/machine/term_stream.rs delete mode 100644 src/machine/toplevel.rs create mode 100644 src/term_and_goal_expansion.pl diff --git a/Cargo.lock b/Cargo.lock index 0b2ca779..b9f316ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,17 +1,5 @@ # 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" @@ -21,12 +9,6 @@ dependencies = [ "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" @@ -35,21 +17,15 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[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" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a6b78289a33e09b00818ca8c90ab17c5dabb6e74f4b29a6de679c0e0886ade" - -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "e9bcd47d94aa4eb8c076b50fc61a75020789394ffb9bd74a180b3379130f6569" [[package]] name = "base64" @@ -68,9 +44,9 @@ dependencies = [ [[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" @@ -90,17 +66,6 @@ dependencies = [ "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" @@ -124,9 +89,9 @@ dependencies = [ [[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" @@ -136,15 +101,15 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[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" @@ -160,13 +125,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[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]] @@ -178,17 +145,11 @@ dependencies = [ "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", @@ -196,9 +157,9 @@ dependencies = [ [[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" @@ -207,18 +168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" 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]] @@ -234,16 +184,16 @@ dependencies = [ "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]] @@ -265,15 +215,6 @@ dependencies = [ "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" @@ -284,26 +225,15 @@ dependencies = [ "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]] @@ -340,7 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -386,11 +316,11 @@ dependencies = [ [[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", ] @@ -412,21 +342,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" 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" @@ -435,7 +371,7 @@ checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -454,11 +390,12 @@ dependencies = [ [[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]] @@ -472,15 +409,15 @@ dependencies = [ [[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", ] @@ -524,7 +461,7 @@ version = "0.4.6" 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", @@ -533,9 +470,9 @@ dependencies = [ [[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" @@ -559,11 +496,11 @@ dependencies = [ [[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]] @@ -572,6 +509,15 @@ version = "0.1.1" 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" @@ -595,23 +541,17 @@ version = "0.1.0" 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", @@ -628,9 +568,9 @@ dependencies = [ [[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", @@ -640,9 +580,9 @@ dependencies = [ [[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", @@ -658,13 +598,13 @@ dependencies = [ [[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]] @@ -710,19 +650,19 @@ version = "0.2.6" 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]] @@ -731,10 +671,10 @@ version = "0.2.4" 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]] @@ -747,7 +687,7 @@ dependencies = [ "num-bigint", "num-integer", "num-rational", - "num-traits 0.2.11", + "num-traits 0.2.14", ] [[package]] @@ -756,23 +696,23 @@ version = "0.1.43" 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" @@ -782,12 +722,12 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[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", @@ -802,20 +742,20 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[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", @@ -852,9 +792,9 @@ dependencies = [ "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]] @@ -897,15 +837,15 @@ dependencies = [ [[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" @@ -915,9 +855,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[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" @@ -930,18 +870,16 @@ dependencies = [ [[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", @@ -961,11 +899,11 @@ dependencies = [ [[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]] @@ -984,20 +922,19 @@ dependencies = [ "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]] @@ -1012,12 +949,12 @@ dependencies = [ [[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]] @@ -1037,9 +974,9 @@ checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[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", ] @@ -1055,11 +992,11 @@ dependencies = [ [[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]] @@ -1079,7 +1016,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1093,7 +1030,7 @@ dependencies = [ "libc", "rand_core 0.4.2", "rdrand", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1126,19 +1063,27 @@ dependencies = [ [[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]] @@ -1149,18 +1094,18 @@ checksum = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6" [[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", @@ -1168,7 +1113,7 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1193,27 +1138,15 @@ dependencies = [ [[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" @@ -1225,13 +1158,13 @@ dependencies = [ [[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", @@ -1241,14 +1174,14 @@ dependencies = [ "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" @@ -1257,7 +1190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1270,7 +1203,7 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" name = "scryer-prolog" version = "0.8.127" dependencies = [ - "base64 0.12.3", + "base64", "blake2", "chrono", "cpu-time", @@ -1297,15 +1230,16 @@ dependencies = [ "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", @@ -1316,9 +1250,9 @@ dependencies = [ [[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", @@ -1351,26 +1285,26 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[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", @@ -1392,9 +1326,9 @@ dependencies = [ [[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", @@ -1403,11 +1337,10 @@ dependencies = [ [[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", ] @@ -1424,19 +1357,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" 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" @@ -1484,8 +1419,8 @@ checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" 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", ] @@ -1514,34 +1449,34 @@ dependencies = [ [[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", @@ -1555,7 +1490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1566,15 +1501,15 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[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" @@ -1584,17 +1519,17 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[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", ] @@ -1627,9 +1562,9 @@ checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" [[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" @@ -1639,69 +1574,69 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[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", @@ -1715,9 +1650,9 @@ checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[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", @@ -1753,6 +1688,6 @@ dependencies = [ [[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" diff --git a/Cargo.toml b/Cargo.toml index 6d10a3ae..cf1d85e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ libc = "0.2.62" 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" @@ -48,3 +48,4 @@ select = "0.4.3" roxmltree = "0.11.0" base64 = "0.12.3" sodiumoxide = "0.2.6" +slice-deque = "0.3.0" \ No newline at end of file diff --git a/build.rs b/build.rs index a9ec444e..aaa876ab 100644 --- a/build.rs +++ b/build.rs @@ -11,6 +11,7 @@ fn find_prolog_files(libraries: &mut File, prefix: &str, current_dir: &Path) { 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() { @@ -24,6 +25,7 @@ fn find_prolog_files(libraries: &mut File, prefix: &str, current_dir: &Path) { 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, diff --git a/src/clause_types.rs b/src/clause_types.rs index dbaefb69..a0318d8d 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -150,11 +150,11 @@ impl InlinedClauseType { #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum SystemClauseType { - AbolishClause, - AbolishModuleClause, - AssertDynamicPredicateToBack, - AssertDynamicPredicateToFront, - AtEndOfExpansion, + // AbolishClause, + // AbolishModuleClause, + // AssertDynamicPredicateToBack, + // AssertDynamicPredicateToFront, + // AtEndOfExpansion, AtomChars, AtomCodes, AtomLength, @@ -189,8 +189,8 @@ pub enum SystemClauseType { DynamicModuleResolution(usize), EnqueueAttributeGoal, EnqueueAttributedVar, - ExpandGoal, - ExpandTerm, +// ExpandGoal, +// ExpandTerm, FetchGlobalVar, FetchGlobalVarWithOffset, FirstStream, @@ -207,16 +207,16 @@ pub enum SystemClauseType { GetAttrVarQueueDelimiter, GetAttrVarQueueBeyond, GetBValue, - GetClause, +// GetClause, GetContinuationChunk, - GetModuleClause, +// GetModuleClause, GetNextDBRef, GetNextOpDBRef, IsPartialString, LookupDBRef, LookupOpDBRef, Halt, - ModuleHeadIsDynamic, +// ModuleHeadIsDynamic, GetLiftedHeapFromOffset, GetLiftedHeapFromOffsetDiff, GetSCCCleaner, @@ -224,11 +224,11 @@ pub enum SystemClauseType { InstallSCCCleaner, InstallInferenceCounter, LiftedHeapLength, - ModuleAssertDynamicPredicateToFront, - ModuleAssertDynamicPredicateToBack, + LoadLibraryAsStream, + // ModuleAssertDynamicPredicateToFront, + // ModuleAssertDynamicPredicateToBack, ModuleExists, - ModuleOf, - ModuleRetractClause, + // ModuleRetractClause, NextEP, NoSuchPredicate, NumberToChars, @@ -254,7 +254,7 @@ pub enum SystemClauseType { ResetContinuationMarker, ResetGlobalVarAtKey, ResetGlobalVarAtOffset, - RetractClause, + // RetractClause, RestoreCutPolicy, SetCutPoint(RegType), SetInput, @@ -324,11 +324,11 @@ pub enum SystemClauseType { 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"), @@ -356,17 +356,50 @@ impl SystemClauseType { &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"), @@ -374,12 +407,9 @@ impl SystemClauseType { &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"), @@ -405,13 +435,13 @@ impl SystemClauseType { 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"), @@ -430,15 +460,14 @@ impl SystemClauseType { &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"), @@ -483,14 +512,13 @@ impl SystemClauseType { &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"), @@ -533,22 +561,27 @@ impl SystemClauseType { &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 { 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), @@ -559,7 +592,6 @@ impl SystemClauseType { ("$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), @@ -582,8 +614,8 @@ impl SystemClauseType { ("$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), @@ -615,14 +647,14 @@ impl SystemClauseType { } ("$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), @@ -630,10 +662,9 @@ impl SystemClauseType { ("$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), @@ -667,7 +698,7 @@ impl SystemClauseType { ("$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))), @@ -697,15 +728,17 @@ impl SystemClauseType { ("$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), @@ -727,6 +760,17 @@ impl SystemClauseType { ("$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, } } @@ -754,7 +798,6 @@ pub enum BuiltInClauseType { pub enum ClauseType { BuiltIn(BuiltInClauseType), CallN, - Hook(CompileTimeHook), Inlined(InlinedClauseType), Named(ClauseName, usize, CodeIndex), // name, arity, index. Op(ClauseName, SharedOpDesc, CodeIndex), @@ -818,7 +861,6 @@ impl ClauseType { 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(), diff --git a/src/codegen.rs b/src/codegen.rs index d260cfa0..1f349246 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,5 +1,6 @@ /// Code generation to WAM-like instructions. use crate::prolog_parser::ast::*; +use crate::prolog_parser::tabled_rc::TabledData; use crate::allocator::*; use crate::arithmetic::*; @@ -9,20 +10,32 @@ use crate::forms::*; 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 { - marker: TermMarker, - pub var_count: IndexMap, 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)] @@ -97,17 +110,46 @@ impl<'a> ConjunctInfo<'a> { } } -impl<'a, TermMarker: Allocator<'a>> CodeGenerator { - pub fn new(non_counted_bt: bool) -> Self { - CodeGenerator { - marker: Allocator::new(), - var_count: IndexMap::new(), +#[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, } } +} - pub fn take_vars(self) -> AllocVarDict { - self.marker.take_bindings() +#[derive(Debug)] +pub struct CodeGenerator { + atom_tbl: TabledData, + marker: TermMarker, + pub var_count: IndexMap, usize>, + non_counted_bt: bool, + is_extensible: bool, + pub skeleton: PredicateSkeleton, + pub jmp_by_locs: Vec, + global_jmp_by_locs_offset: usize, +} + +impl<'a, TermMarker: Allocator<'a>> CodeGenerator { + pub fn new(atom_tbl: TabledData, settings: CodeGenSettings) -> Self { + CodeGenerator { + atom_tbl, + marker: Allocator::new(), + var_count: IndexMap::new(), + 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, + } } fn update_var_count>>(&mut self, iter: Iter) { @@ -337,16 +379,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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)); + } + _ => { } - _ => {} } } @@ -356,16 +402,22 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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 @@ -377,7 +429,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { terms: &'a Vec>, term_loc: GenContext, code: &mut Code, - ) -> Result<(), ParserError> { + ) -> Result<(), CompilationError> { match ct { &InlinedClauseType::CompareNumber(cmp, ..) => { self.marker.reset_arg(2); @@ -553,7 +605,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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); @@ -656,7 +708,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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() { @@ -669,18 +721,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { &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)? } @@ -714,7 +772,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } } - 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!()), @@ -726,11 +784,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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 { + pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result { let iter = ChunkedIterator::from_rule(rule); let conjunct_info = self.collect_var_data(iter); @@ -739,7 +805,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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); @@ -761,8 +827,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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) } @@ -836,10 +902,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } } - 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) -> Result { +/* + pub fn compile_query(&mut self, query: &'a Vec) -> Result { let iter = ChunkedIterator::from_term_sequence(query); let conjunct_info = self.collect_var_data(iter); @@ -857,6 +924,16 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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 { @@ -925,48 +1002,50 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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 { - let mut code_body = Vec::new(); - let mut code_offsets = CodeOffsets::new(); + ) -> Result { + 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() { @@ -976,47 +1055,86 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { }, 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); } - code_body.append(&mut clause_code); + if !skip_stub_try_me_else { + self.increment_jmp_by_locs_by(code.len()); + } + + 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, - ) -> Result { - let mut code = Vec::new(); + ) -> Result { + 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) diff --git a/src/forms.rs b/src/forms.rs index be572bc4..006371eb 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,6 +1,5 @@ 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::*; @@ -8,15 +7,19 @@ use crate::machine::machine_indices::*; 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; + // vars of predicate, toplevel offset. Vec is always a vector // of vars (we get their adjoining cells this way). pub type JumpStub = Vec; @@ -24,19 +27,24 @@ pub type JumpStub = Vec; #[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), - Rule(Rule, usize, usize), // Rule, line_num, col_num + Rule(Rule), // Rule, line_num, col_num } -impl TopLevel { - pub fn is_end_of_file_atom(&self) -> bool { +#[derive(Debug, Clone, Copy)] +pub enum AppendOrPrepend { + Append, + Prepend +} + +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, } } } @@ -91,30 +99,9 @@ pub struct Rule { pub clauses: Vec, } -#[derive(Debug, Clone)] -pub struct Predicate(pub Vec); - -impl Predicate { - #[inline] - pub fn new() -> Self { - Predicate(vec![]) - } - - #[inline] - pub fn clauses(self) -> Vec { - 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, } @@ -123,98 +110,13 @@ impl ListingSource { 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) -> 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 @@ -222,33 +124,29 @@ pub trait ClauseConsistency { } } - fn name_and_module(&self) -> Option<(ClauseName, ClauseName)>; + fn name(&self) -> Option; 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 { 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 @@ -263,12 +161,12 @@ impl ClauseConsistency for Term { ":-" => { match terms.len() { 1 => 0, - 2 => resolved_term_arity(&terms[0]), + 2 => terms[0].arity(), _ => terms.len(), } } _ => { - resolved_term_arity(self) + terms.len() } }, _ => { @@ -278,9 +176,9 @@ impl ClauseConsistency for Term { } } -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 { + Some(self.head.0.clone()) } fn arity(&self) -> usize { @@ -288,15 +186,14 @@ impl ClauseConsistency for Rule { } } -impl ClauseConsistency for PredicateClause { - fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> { +impl ClauseInfo for PredicateClause { + fn name(&self) -> Option { 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() } } } @@ -313,22 +210,12 @@ impl ClauseConsistency for PredicateClause { } } -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); +// pub type CompiledResult = (Predicate, VecDeque); #[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 { @@ -395,66 +282,61 @@ impl ModuleSource { } } -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), - ModuleInitialization(Vec, VecDeque), // goal + Dynamic(ClauseName, usize), + MetaPredicate(ClauseName, ClauseName, Vec), // module name, name, meta-specs Module(ModuleDecl), - MultiFile(MultiFileIndicator), NonCountedBacktracking(ClauseName, usize), // name, arity Op(OpDecl), - SetPrologFlag(DoubleQuotes), UseModule(ModuleSource), - UseQualifiedModule(ModuleSource, Vec), + UseQualifiedModule(ModuleSource, IndexSet), } -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, @@ -462,29 +344,27 @@ impl OpDecl { } } - pub fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) { - let (spec, name) = (self.1, self.2.clone()); + pub fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<(usize, Specifier)> { + let key = (self.name.clone(), self.fixity()); - let fixity = 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, 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 { @@ -502,7 +382,8 @@ impl OpDecl { } } - Ok(self.insert_into_op_dir(module, op_dir, prec)) + self.insert_into_op_dir(op_dir); + Ok(()) } } @@ -541,7 +422,7 @@ pub fn fetch_op_spec( 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 { @@ -549,15 +430,15 @@ pub fn fetch_op_spec( } }), 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 { @@ -573,7 +454,7 @@ pub fn fetch_op_spec( pub type ModuleDir = IndexMap; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Eq, Hash, PartialEq)] pub enum ModuleExport { OpDecl(OpDecl), PredicateKey(PredicateKey), @@ -587,21 +468,32 @@ pub struct ModuleDecl { #[derive(Debug)] pub struct Module { - pub atom_tbl: TabledData, 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), - pub goal_expansions: (Predicate, VecDeque), - pub user_term_expansions: (Predicate, VecDeque), // term expansions inherited from the user scope. - pub user_goal_expansions: (Predicate, VecDeque), // same for goal_expansions. - pub local_term_expansions: (Predicate, VecDeque), // expansions local to the module. - pub local_goal_expansions: (Predicate, VecDeque), - pub inserted_expansions: bool, // has the module been successfully inserted into toplevel?? + pub meta_predicates: MetaPredicateDir, + pub extensible_predicates: IndexMap, 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 { @@ -709,3 +601,154 @@ impl Number { } } } + +#[derive(Debug, Clone)] +pub enum OptArgIndexKey { + Constant(usize, usize, Constant, Vec), // 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 { + 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 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, + pub clause_clause_locs: SliceDeque, +} + +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, + } + } + */ +} diff --git a/src/heap_iter.rs b/src/heap_iter.rs index a541d12f..44541237 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -45,10 +45,13 @@ impl<'a> HCPreOrderIterator<'a> { | HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => { Addr::Con(h) } + HeapCellValue::LoadStatePayload(_) => { + Addr::LoadStatePayload(h) + } HeapCellValue::Stream(_) => { Addr::Stream(h) } - &HeapCellValue::TcpListener(_) => { + HeapCellValue::TcpListener(_) => { Addr::TcpListener(h) } } @@ -175,13 +178,17 @@ impl<'a> Iterator for HCPostOrderIterator<'a> { } &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!() diff --git a/src/heap_print.rs b/src/heap_print.rs index 2a51fa91..e4792969 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -402,6 +402,7 @@ pub fn requires_space(atom: &str, op: &str) -> bool { } } +/* fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict { machine_st .heap_locs @@ -414,6 +415,7 @@ fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict { }) .collect() } +*/ fn non_quoted_graphic_token>(mut iter: Iter, c: char) -> bool { if c == '/' { @@ -503,7 +505,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { max_depth: 0, } } - +/* pub fn from_heap_locs( machine_st: &'a MachineState, op_dir: &'a OpDir, @@ -520,17 +522,20 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { 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 { @@ -1024,7 +1029,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { 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); } diff --git a/src/indexing.rs b/src/indexing.rs index bf5403bf..f2029a31 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1,203 +1,1091 @@ 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. +} + +impl IndexingCodePtr { + #[inline] + fn is_internal(self) -> bool { + if let IndexingCodePtr::Internal(_) = self { + true + } else { + false + } + } +} + +#[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 + } + } + } +} + +#[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, + offset: usize, + append_or_prepend: AppendOrPrepend, +} + +impl<'a> IndexingCodeMergingPtr<'a> { + #[inline] + fn new( + skeleton: &'a mut [ClauseIndexInfo], + indexing_code: &'a mut Vec, + append_or_prepend: AppendOrPrepend, + ) -> Self { + Self { skeleton, indexing_code, offset: 0, append_or_prepend } + } + + 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 { + self.offset = self.indexing_code.len(); + + self.indexing_code.push(IndexingLine::Indexing( + IndexingInstruction::SwitchOnConstant(constants) + )); + } + } + + 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) + ] + }; + + let indexing_code_len = self.indexing_code.len(); + self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index)); + + 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!() + } + } + } + + 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)); + } + _ => { + unreachable!() + } + } + } + + fn index_overlapping_constant( + &mut self, + orig_constant: &Constant, + overlapping_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(_) => { + let mut constants = IndexMap::new(); + constants.insert(orig_constant.clone(), *c); + + *c = IndexingCodePtr::Internal(indexing_code_len); + + self.indexing_code.push(IndexingLine::Indexing( + IndexingInstruction::SwitchOnConstant(constants) + )); + + self.offset = indexing_code_len; + } + IndexingCodePtr::Internal(o) => { + self.offset += o; + } + } + } + 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); + } + } + + break; + } + IndexingLine::IndexedChoice(_) => { + self.internalize_constant( + IndexingCodePtr::Internal(indexing_code_len - self.offset), + ); + } + _ => { + unreachable!() + } + } + } + } + + 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); + } + } + + break; + } + IndexingLine::IndexedChoice(_) => { + self.internalize_constant( + IndexingCodePtr::Internal(indexing_code_len - self.offset), + ); + } + _ => { + unreachable!() + } + } + } + } + + 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, + ); + + let mut structures = IndexMap::new(); + + 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) + )); + } + } + + 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)); + + match &mut self.indexing_code[self.offset] { + IndexingLine::Indexing( + IndexingInstruction::SwitchOnStructure(ref mut structures) + ) => { + structures.insert(key, IndexingCodePtr::Internal(indexing_code_len - self.offset)); + } + _ => { + unreachable!() + } + } + } + + 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 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) + ] + }; + + 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, + 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!() + } + } + + 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; + } + } +} + +#[inline] +fn remove_instruction_with_offset( + code: &mut SliceDeque, + 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, + 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!() + } + } + + 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!() + } + } + } + } + + 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!() + } + } + } + _ => { + } + } +} + +pub fn remove_structure_index( + name: &ClauseName, + arity: usize, + indexing_code: &mut Vec, + 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!() + } + } + + let mut structures_index = 0; + + loop { + match &mut indexing_code[index] { + IndexingLine::Indexing( + IndexingInstruction::SwitchOnStructure(ref mut structures) + ) => { + structures_index = index; + + 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; + } + } + } + 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!() + } + } + } + + 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!() + } + } + } + _ => { + } + } +} + +pub fn remove_list_index( + indexing_code: &mut Vec, + 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!() + } + } + + match &mut indexing_code[index] { + 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[0] { + IndexingLine::Indexing( + IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _) + ) => { + *l = ext; + } + _ => { + unreachable!() + } + } + } + } + _ => { + unreachable!() + } + } +} + +pub fn remove_index( + //skeleton: &[ClauseIndexInfo], + opt_arg_index_key: &OptArgIndexKey, + indexing_code: &mut Vec, + 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!() + } + } +} + +fn second_level_index( + indices: IndexMap>, + prelude: &mut SliceDeque, +) -> IndexMap +{ + let mut index_locs = IndexMap::new(); + + 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 { + code.first().map(|i| { + index_locs.insert(key, IndexingCodePtr::External(i.offset())); + }); + } + } + + index_locs +} + +fn switch_on( + instr_fn: impl Fn(IndexMap) -> IndexingInstruction, + index: IndexMap>, + prelude: &mut SliceDeque, +) -> 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, + prelude: &mut SliceDeque, +) -> 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); +} + +#[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) -> Vec { + let mut constants = vec![]; + + 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)); + } + } + _ => { + } + } + + constants } #[derive(Debug)] pub struct CodeOffsets { atom_tbl: TabledData, - pub constants: IndexMap, - pub lists: ThirdLevelIndex, - pub structures: IndexMap<(ClauseName, usize), ThirdLevelIndex>, + pub constants: IndexMap>, + pub lists: SliceDeque, + pub structures: IndexMap<(ClauseName, usize), SliceDeque>, + optimal_index: usize, } impl CodeOffsets { - pub fn new() -> Self { + pub fn new(atom_tbl: TabledData, optimal_index: usize) -> Self { CodeOffsets { - atom_tbl: TabledData::new(Rc::new("_index".to_string())), + atom_tbl, constants: IndexMap::new(), - lists: Vec::new(), + lists: sdeq![], structures: IndexMap::new(), + optimal_index } } - fn cap_choice_seq_with_trust(prelude: &mut ThirdLevelIndex) { - prelude.last_mut().map(|instr| { - match instr { - &mut IndexedChoiceInstruction::Retry(i) => { - *instr = IndexedChoiceInstruction::Trust(i) - } - _ => {} - }; - }); + 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 add_index(is_first_index: bool, index: usize) -> IndexedChoiceInstruction { - if is_first_index { - IndexedChoiceInstruction::Try(index) - } else { - IndexedChoiceInstruction::Retry(index) + fn index_constant(&mut self, constant: &Constant, index: usize) -> Vec { + 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); } + + overlapping_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 index_structure(&mut self, name: &ClauseName, arity: usize, index: usize) -> usize { + let code = self + .structures + .entry((name.clone(), arity)) + .or_insert(sdeq![]); - code.push(Self::add_index(code.is_empty(), index)); + let code_len = code.len(); + let is_initial_index = code.is_empty(); - if op.is_some() { - let code = self.constants - .entry(Constant::Atom(name.clone(), None)) - .or_insert(vec![]); - - code.push(Self::add_index(false, 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)); - } - &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![]); - - code.push(Self::add_index(code.is_empty(), index)); - } - &Constant::Fixnum(n) => { - let code = self.constants - .entry(Constant::Integer(Rc::new(Integer::from(n)))) - .or_insert(vec![]); - - code.push(Self::add_index(code.is_empty(), index)); - - if n >= 0 { - if let Ok(n) = usize::try_from(n) { - let code = self.constants - .entry(Constant::Usize(n)) - .or_insert(vec![]); - - code.push(Self::add_index(code.is_empty(), index)); - } - } - } - &Constant::Integer(ref n) => { - if let Some(n) = n.to_isize() { - let code = self.constants - .entry(Constant::Fixnum(n)) - .or_insert(vec![]); - - code.push(Self::add_index(code.is_empty(), index)); - } - - if let Some(n) = n.to_usize() { - let code = self.constants - .entry(Constant::Usize(n)) - .or_insert(vec![]); - - code.push(Self::add_index(code.is_empty(), index)); - } - } - &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)); - - if let Ok(n) = isize::try_from(n) { - let code = self.constants - .entry(Constant::Fixnum(n)) - .or_insert(vec![]); - - code.push(Self::add_index(code.is_empty(), index)); - } - } - _ => { - } - } + code.push_back(compute_index(is_initial_index, index)); + code_len } - pub fn index_term(&mut self, optimal_arg: &Term, index: usize) { + 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, _) => { - let code = self - .structures - .entry((name.clone(), terms.len())) - .or_insert(Vec::new()); + clause_index_info.opt_arg_index_key = + OptArgIndexKey::Structure(self.optimal_index, 0, name.clone(), terms.len()); - let is_initial_index = code.is_empty(); - code.push(Self::add_index(is_initial_index, index)); + self.index_structure(name, terms.len(), index); } &Term::Cons(..) | &Term::Constant(_, Constant::String(_)) => { - let is_initial_index = self.lists.is_empty(); - self.lists.push(Self::add_index(is_initial_index, index)); + clause_index_info.opt_arg_index_key = + OptArgIndexKey::List(self.optimal_index, 0); + + self.index_list(index); } &Term::Constant(_, ref constant) => { - self.intercept_overlapping_constant(constant, index); + let overlapping_constants = + self.index_constant(constant, index); - let code = self.constants - .entry(constant.clone()) - .or_insert(vec![]); - - let is_initial_index = code.is_empty(); - code.push(Self::add_index(is_initial_index, index)); + clause_index_info.opt_arg_index_key = + OptArgIndexKey::Constant( + self.optimal_index, + 0, + constant.clone(), + overlapping_constants, + ); } _ => { } - }; - } - - fn second_level_index( - indices: IndexMap, - prelude: &mut CodeDeque, - ) -> IndexMap - where - Index: Eq + Hash, - { - let mut index_locs = IndexMap::new(); - - 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())); - }); - } } - - index_locs } - fn no_indices(&self) -> bool { + 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(); @@ -205,179 +1093,50 @@ impl CodeOffsets { no_constants && no_structures && no_lists } - fn flatten_index(index: IndexMap, len: usize) -> IndexMap - where - Index: Eq + Hash, - { - let mut flattened_index = IndexMap::new(); - - for (key, int_index) in index.into_iter() { - match int_index { - IntIndex::External(offset) => { - flattened_index.insert(key, offset + len + 1); - } - IntIndex::Internal(offset) => { - flattened_index.insert(key, offset + 1); - } - _ => {} - }; - } - - flattened_index - } - - fn adjust_internal_index(index: IntIndex) -> IntIndex { - match index { - IntIndex::Internal(o) => IntIndex::Internal(o + 1), - IntIndex::External(o) => IntIndex::External(o), - _ => IntIndex::Fail, - } - } - - fn switch_on_constant( - con_ind: IndexMap, - prelude: &mut CodeDeque, - optimal_index: usize, - ) -> IntIndex { - let con_ind = Self::second_level_index(con_ind, prelude); - - if con_ind.len() > 1 { - let index = Self::flatten_index(con_ind, prelude.len()); - let instr = IndexingInstruction::SwitchOnConstant( - optimal_index, - index.len(), - index - ); - - prelude.push_front(Line::from(instr)); - - 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 - ); - - prelude.push_front(Line::from(instr)); - - IntIndex::Internal(1) - } else { - str_ind - .values() - .next() - .map(|index| Self::adjust_internal_index(*index)) - .unwrap_or(IntIndex::Fail) - } - } - - 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) - } - } - - 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, - }, - } - } - - 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, - } - } - - 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. - } - } - - pub fn add_indices(self, code: &mut Code, mut code_body: Code, optimal_index: usize) { + pub fn compute_indices(self, skip_stub_try_me_else: bool) -> Vec { if self.no_indices() { - *code = code_body; - return; + return vec![]; } - let mut prelude = VecDeque::new(); + let mut prelude = sdeq![]; - 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); + let mut lst_loc = switch_on_list(self.lists, &mut prelude); - let prelude_length = prelude.len(); - - 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; - } - _ => { - } - } - } - - 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 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, + ); - *code = Vec::from(prelude); - code.append(&mut code_body); + 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) + )); + + prelude.into_iter().collect() } } diff --git a/src/instructions.rs b/src/instructions.rs index c3de3469..a913f49e 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -2,6 +2,7 @@ use crate::prolog_parser::ast::*; 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::*; @@ -9,7 +10,8 @@ use crate::rug::Integer; use crate::indexmap::IndexMap; -use std::collections::VecDeque; +use slice_deque::SliceDeque; + use std::rc::Rc; fn reg_type_into_functor(r: RegType) -> MachineStub { @@ -48,9 +50,9 @@ impl ArithmeticTerm { #[derive(Debug)] pub enum ChoiceInstruction { DefaultRetryMeElse(usize), - DefaultTrustMe, + DefaultTrustMe(usize), RetryMeElse(usize), - TrustMe, + TrustMe(usize), TryMeElse(usize), } @@ -63,14 +65,14 @@ impl ChoiceInstruction { &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)]) } } } @@ -106,19 +108,13 @@ impl CutInstruction { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub enum IndexedChoiceInstruction { Retry(usize), Trust(usize), Try(usize), } -impl From for Line { - fn from(i: IndexedChoiceInstruction) -> Self { - Line::IndexedChoice(i) - } -} - impl IndexedChoiceInstruction { pub fn offset(&self) -> usize { match self { @@ -144,6 +140,26 @@ impl IndexedChoiceInstruction { } /// A `Line` is an instruction (cf. page 98 of wambook). +#[derive(Debug)] +pub enum IndexingLine { + Indexing(IndexingInstruction), + IndexedChoice(SliceDeque), +} + +impl From for IndexingLine { + #[inline] + fn from(instr: IndexingInstruction) -> Self { + IndexingLine::Indexing(instr) + } +} + +impl From> for IndexingLine { + #[inline] + fn from(instrs: SliceDeque) -> Self { + IndexingLine::IndexedChoice(instrs) + } +} + #[derive(Debug)] pub enum Line { Arithmetic(ArithmeticInstruction), @@ -151,12 +167,13 @@ pub enum Line { Control(ControlInstruction), Cut(CutInstruction), Fact(FactInstruction), - Indexing(IndexingInstruction), + IndexingCode(Vec), IndexedChoice(IndexedChoiceInstruction), Query(QueryInstruction), } impl Line { + #[inline] pub fn is_head_instr(&self) -> bool { match self { &Line::Cut(_) => true, @@ -166,16 +183,64 @@ impl Line { } } - pub fn to_functor(&self, h: usize) -> MachineStub { + pub fn enqueue_functors(&self, mut h: usize, functors: &mut Vec) { 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> { + match line { + Line::IndexingCode(ref mut indexing_code) => { + Some(indexing_code) + } + _ => { + None + } + } +} + +#[inline] +pub fn to_indexing_line(line: &Line) -> Option<&Vec> { + match line { + Line::IndexingCode(ref indexing_code) => { + Some(indexing_code) + } + _ => { + None } } } @@ -386,6 +451,9 @@ pub enum ControlInstruction { 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, } @@ -418,6 +486,9 @@ impl ControlInstruction { &ControlInstruction::JmpBy(_, offset, ..) => { functor!("jmp_by", [integer(offset)]) } + &ControlInstruction::RevJmpBy(offset) => { + functor!("rev_jmp_by", [integer(offset)]) + } &ControlInstruction::Proceed => { functor!("proceed") } @@ -429,40 +500,94 @@ impl ControlInstruction { #[derive(Debug)] pub enum IndexingInstruction { // The first index is the optimal argument being indexed. - SwitchOnTerm(usize, usize, usize, usize, usize), - SwitchOnConstant(usize, usize, IndexMap), - SwitchOnStructure(usize, usize, IndexMap<(ClauseName, usize), usize>), -} - -impl From for Line { - fn from(i: IndexingInstruction) -> Self { - Line::Indexing(i) - } + SwitchOnTerm(usize, usize, IndexingCodePtr, IndexingCodePtr, IndexingCodePtr), + SwitchOnConstant(IndexMap), + 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] ) } } @@ -710,8 +835,4 @@ impl QueryInstruction { pub type CompiledFact = Vec; -pub type ThirdLevelIndex = Vec; - pub type Code = Vec; - -pub type CodeDeque = VecDeque; diff --git a/src/iterators.rs b/src/iterators.rs index 218ed78e..9c549166 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -481,7 +481,7 @@ impl<'a> ChunkedIterator<'a> { } })) } - +/* pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self { ChunkedIterator { chunk_num: 0, @@ -490,7 +490,7 @@ impl<'a> ChunkedIterator<'a> { cut_var_in_head: false, } } - +*/ pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec) -> Self { let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))); diff --git a/src/lib/atts.pl b/src/lib/atts.pl index fbf440d0..8fa16e11 100644 --- a/src/lib/atts.pl +++ b/src/lib/atts.pl @@ -1,4 +1,5 @@ -:- 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, @@ -19,9 +20,7 @@ ). '$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'([], _, _) --> []. @@ -66,7 +65,8 @@ '$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. @@ -75,8 +75,8 @@ ; 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) ) ). @@ -88,66 +88,66 @@ user:term_expansion(Term0, Terms) :- 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). + get_attr(Name, Arity, Module), + get_attrs(Atts, Module). -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))]. +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) --> - { 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) --> + { 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), diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 3d7aa79f..d17faf8c 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -1,45 +1,3 @@ -:- 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, @@ -50,21 +8,21 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :- 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]). @@ -80,13 +38,16 @@ true. 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)) @@ -137,7 +98,6 @@ Module : Predicate :- ; throw(error(type_error(atom, Module), (:)/2)) ). - % flags. current_prolog_flag(Flag, false) :- Flag == bounded, !. @@ -171,7 +131,7 @@ set_prolog_flag(min_integer, Value) :- 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) :- @@ -180,7 +140,7 @@ set_prolog_flag(double_quotes, codes) :- !, '$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 @@ -192,6 +152,8 @@ set_prolog_flag(Flag, _) :- fail :- '$fail'. +:- meta_predicate \+(:). + \+ G :- call(G), !, false. \+ _. @@ -200,6 +162,8 @@ X \= X :- !, false. _ \= _. +:- meta_predicate once(:). + once(G) :- call(G), !. @@ -207,6 +171,20 @@ repeat. 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)) -> @@ -321,19 +299,26 @@ call_or_cut(G, _) :- 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 ) @@ -342,14 +327,17 @@ univ_errors(Term, List, N) :- ; 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), @@ -364,46 +352,78 @@ univ_worker(Term, List, _) :- :- 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)) ). @@ -411,8 +431,10 @@ must_be_var_names_list_([], List). 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)) @@ -455,30 +477,9 @@ select_rightmost_options([Option-Value | OptionPairs], OptionValues) :- 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). @@ -498,20 +499,21 @@ read_term(Term, Options) :- 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), @@ -519,7 +521,14 @@ term_variables(Term, Vars) :- % 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) :- @@ -531,16 +540,30 @@ 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), @@ -550,14 +573,23 @@ throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'. '$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) :- @@ -569,14 +601,16 @@ findall(Template, Goal, Solutions) :- '$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). @@ -588,7 +622,10 @@ set_difference([], _, []) :- !. 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]) :- @@ -611,8 +648,12 @@ rightmost_power(Term, FinalTerm, Xs) :- ; 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), @@ -623,6 +664,9 @@ findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) findall(Witnesses-Template, Goal, PairedSolutions) ). + +:- meta_predicate bagof(?, :, ?). + bagof(Template, Goal, Solution) :- error:can_be(list, Solution), term_variables(Template, TemplateVars0), @@ -643,6 +687,9 @@ iterate_variants_and_sort([V-Solution0|GroupSolutions], V, Solution) :- 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), @@ -659,36 +706,47 @@ setof(Template, Goal, Solution) :- '$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)) ) @@ -698,19 +756,21 @@ clause(H, B) :- 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)) @@ -718,166 +778,218 @@ module_asserta_clause(Head, Body, Module) :- 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) + ( 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 - ). - -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)) @@ -889,6 +1001,7 @@ abolish(Pred) :- '$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)) @@ -909,8 +1022,10 @@ can_be_op_specifier(Spec) :- var(Spec). 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) ). @@ -929,36 +1044,52 @@ op_priority(Priority) :- 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) ). @@ -973,41 +1104,54 @@ halt(N) :- ). 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)) ). @@ -1016,18 +1160,19 @@ atom_concat(Atom_1, Atom_2, Atom_12) :- 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), @@ -1041,9 +1186,12 @@ sub_atom(Atom, Before, Length, After, Sub_atom) :- 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), @@ -1055,11 +1203,14 @@ sub_atom(Atom, Before, Length, After, Sub_atom) :- 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)) ). @@ -1081,7 +1232,8 @@ must_be_number(N, _) :- ), !. 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)) ). @@ -1144,7 +1296,7 @@ set_output(S) :- 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) :- @@ -1191,7 +1343,7 @@ open(SourceSink, Mode, Stream, StreamOptions) :- 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]), ! diff --git a/src/lib/clpb.pl b/src/lib/clpb.pl index 0b802a46..0310e775 100644 --- a/src/lib/clpb.pl +++ b/src/lib/clpb.pl @@ -17,8 +17,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ :- module(clpb, [op(300, fy, ~), - op(500, yfx, #), - sat/1, + op(500, yfx, #), + sat/1, taut/2, labeling/1, sat_count/2, diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl index 942f6b8e..b4e2fafc 100644 --- a/src/lib/dcgs.pl +++ b/src/lib/dcgs.pl @@ -5,13 +5,21 @@ :- 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)) ). diff --git a/src/lib/diag.pl b/src/lib/diag.pl index d135238b..0fa3896f 100644 --- a/src/lib/diag.pl +++ b/src/lib/diag.pl @@ -2,13 +2,23 @@ :- 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)) + ). diff --git a/src/lib/dif.pl b/src/lib/dif.pl index bb92979a..9c3b8ed8 100644 --- a/src/lib/dif.pl +++ b/src/lib/dif.pl @@ -8,8 +8,8 @@ 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])) ). @@ -21,8 +21,8 @@ dif_set_variables([Var|Vars], 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)), @@ -30,8 +30,8 @@ append_goals([Var|Vars], Goals) :- 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 = [] ). @@ -50,7 +50,7 @@ dif(X, Y) :- gather_dif_goals([]) --> []. gather_dif_goals([(X \== Y) | Goals]) --> ( { X \= Y } -> [] - ; [dif(X, Y)] + ; [dif:dif(X, Y)] ), gather_dif_goals(Goals). diff --git a/src/lib/error.pl b/src/lib/error.pl index 7e2189c4..99592790 100644 --- a/src/lib/error.pl +++ b/src/lib/error.pl @@ -44,10 +44,10 @@ must_be_(var, Term) :- ). 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) diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index e5ba94c1..dc83c2a4 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -23,9 +23,9 @@ bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/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)) ). @@ -45,11 +45,16 @@ reset_global_var_at_offset(Key, Value, Offset) :- '$reset_global_var_at_offset'( 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), @@ -117,6 +122,8 @@ handle_ile(B, E, _) :- '$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), diff --git a/src/lib/lists.pl b/src/lib/lists.pl index a1acdb6d..75095715 100644 --- a/src/lib/lists.pl +++ b/src/lib/lists.pl @@ -1,15 +1,29 @@ :- 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)). @@ -66,7 +80,6 @@ reverse([], [], YsRev, YsRev). reverse([_|Xs], [Y1|Ys], YsPreludeRev, Xss) :- reverse(Xs, Ys, [Y1|YsPreludeRev], Xss). - maplist(_, []). maplist(Cont1, [E1|E1s]) :- call(Cont1, E1), @@ -87,21 +100,25 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :- 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), @@ -111,7 +128,7 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7 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)). @@ -132,6 +149,7 @@ foldl_([L|Ls], G_3, A0, A) :- 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), diff --git a/src/lib/ops_and_meta_predicates.pl b/src/lib/ops_and_meta_predicates.pl new file mode 100644 index 00000000..c16af3ad --- /dev/null +++ b/src/lib/ops_and_meta_predicates.pl @@ -0,0 +1,127 @@ +:- 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(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). diff --git a/src/lib/pairs.pl b/src/lib/pairs.pl index adcfb138..85914639 100644 --- a/src/lib/pairs.pl +++ b/src/lib/pairs.pl @@ -5,6 +5,8 @@ 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). diff --git a/src/lib/tabling/wrapper.pl b/src/lib/tabling/wrapper.pl index c66be996..4c902e84 100644 --- a/src/lib/tabling/wrapper.pl +++ b/src/lib/tabling/wrapper.pl @@ -75,7 +75,7 @@ wrappers(Name/Arity) --> 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) @@ -109,10 +109,10 @@ rename_term(Name, WrapName) :- 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). diff --git a/src/lib/time.pl b/src/lib/time.pl index 30ec0f45..933387be 100644 --- a/src/lib/time.pl +++ b/src/lib/time.pl @@ -82,6 +82,8 @@ sleep(T) :- % '$cpu_now' can be replaced by statistics/2 once that is implemented. +:- meta_predicate time(:). + time(Goal) :- '$cpu_now'(T0), setup_call_cleanup(true, diff --git a/src/loader.pl b/src/loader.pl new file mode 100644 index 00000000..9360e260 --- /dev/null +++ b/src/loader.pl @@ -0,0 +1,433 @@ + +:- 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] + ) + ). diff --git a/src/machine/attributed_variables.pl b/src/machine/attributed_variables.pl index 8756eb3c..386ff101 100644 --- a/src/machine/attributed_variables.pl +++ b/src/machine/attributed_variables.pl @@ -13,10 +13,16 @@ iterate([Var|VarBindings], [Value|ValueBindings], [ListOfGoalLists | ListsCubed] 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), !. @@ -24,7 +30,7 @@ call_verify_attributes([], _, _, []). 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(Modules, Var, Value, ListOfGoalLists). verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :- catch(Module:verify_attributes(Var, Value, Goals), @@ -33,6 +39,15 @@ verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :- 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), call_goals(ListsCubed). diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index c7b198d5..790114fc 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -6,9 +6,6 @@ use crate::indexmap::IndexSet; 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)] @@ -126,7 +123,7 @@ impl MachineState { 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] = diff --git a/src/machine/code_repo.rs b/src/machine/code_repo.rs index b9045c72..092f6407 100644 --- a/src/machine/code_repo.rs +++ b/src/machine/code_repo.rs @@ -1,127 +1,52 @@ 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) { - 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, - ) -> 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::::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) @@ -131,32 +56,12 @@ impl CodeRepo { p: &CodePtr, ) -> Option> { 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()), @@ -164,14 +69,27 @@ impl CodeRepo { 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 + } +*/ } } } diff --git a/src/machine/code_walker.rs b/src/machine/code_walker.rs index 152395c5..94944889 100644 --- a/src/machine/code_walker.rs +++ b/src/machine/code_walker.rs @@ -1,73 +1,39 @@ use crate::instructions::*; -use std::collections::VecDeque; +use indexmap::IndexSet; -fn scan_for_trust_me( - code: &Code, - jmp_offsets: &mut VecDeque, - 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) -> bool { + match line { + &Line::Choice(ChoiceInstruction::TryMeElse(offset)) if offset > 0 => { + stack.push(index + 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; } } - } - - // 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) - } - _ => { - } + _ => { } - } + }; - *after_idx += 1; -} - -fn capture_next_range(code: &Code, queue: &mut VecDeque, 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 @@ -76,15 +42,22 @@ fn capture_next_range(code: &Code, queue: &mut VecDeque, last_idx: &mut u */ 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; + while let Some(first_index) = stack.pop() { + if visited_indices.contains(&first_index) { + continue; + } else { + visited_indices.insert(first_index); + } - capture_next_range(code, &mut queue, &mut last_idx); - - 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; + } } } } @@ -92,6 +65,7 @@ pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) /* 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]); @@ -106,3 +80,4 @@ pub fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line } } } +*/ diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 36544eba..7b3fb49f 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1,1454 +1,1677 @@ -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; +use std::ops::Range; -#[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, - mut path: PathBuf, -) -> Result -{ - 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 { - // 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; - - 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 { - 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); + 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, + ); - let file_handle = Stream::from_file_as_input(filename.clone(), File::open(&path_buf).or_else(|_| { - Err(SessionError::InvalidFileName(filename.clone())) - })?); + let loader = Loader::new(term_stream, wam); + loader.load()?; - path_buf.pop(); - - 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); - // throw errors if declaration or query found. +pub(super) fn compile_relation( cg: &mut CodeGenerator, tl: &TopLevel -) -> Result { +) -> Result { 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; - } - } - - for (var, count) in var_count { - if count == 1 && !var.starts_with("_") && var.as_str() != "!" { - singletons.push(var); - } - } - - if let Some(last_var) = singletons.pop() { - print!("Warning: {}:{}: Singleton variables: [", - src_name, line_num); - - for var in singletons { - print!("{}, ", var); - } - - println!("{}]", last_var); - } - } -} - -// 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; - } - _ => {} - }; - } -} - -pub fn compile_appendix( +pub(super) +fn compile_appendix( code: &mut Code, queue: &VecDeque, + jmp_by_locs: Vec, non_counted_bt: bool, -) -> Result<(), ParserError> { + atom_tbl: TabledData, +) -> Result<(), CompilationError> { + let mut jmp_by_locs = VecDeque::from(jmp_by_locs); + for tl in queue.iter() { - set_first_index(code); - let mut cg = CodeGenerator::::new(non_counted_bt); + let code_len = code.len(); + let jmp_by_offset = jmp_by_locs.pop_front().unwrap(); + + match &mut code[jmp_by_offset] { + &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => { + *offset = code_len - jmp_by_offset; + } + _ => { + unreachable!() + } + } + + // false because the inner predicate is a one-off, hence not extensible. + let settings = CodeGenSettings::new(false, non_counted_bt); + + let mut cg = CodeGenerator::::new(atom_tbl.clone(), settings); let decl_code = compile_relation(&mut cg, tl)?; + + jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len())); code.extend(decl_code.into_iter()); } Ok(()) } -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 lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize { + if target_pos == 0 { + return 0; + } - let rule = Rule { - head: (name.clone(), vec![var.clone(), var], body), - clauses: vec![] - }; + let arg_num = skeleton.clauses[target_pos - 1].opt_arg_index_key.arg_num(); - pred.0.push(PredicateClause::Rule(rule, 0, 0)); -} + if arg_num == 0 { + return target_pos - 1; + } -impl CodeRepo { - pub fn compile_hook( - &mut self, - hook: CompileTimeHook, - ) -> Result<(), ParserError> { - let key = (hook.name(), hook.arity()); + for index in (0 .. target_pos - 1).rev() { + let current_arg_num = skeleton.clauses[index].opt_arg_index_key.arg_num(); - match self.term_dir.get_mut(&key) { - Some(ref mut preds) => { - append_trivial_goal(&key.0, &mut preds.0); - - let mut cg = CodeGenerator::::new(false); - let mut code = cg.compile_predicate(&(preds.0).0)?; - - compile_appendix(&mut code, &preds.1, false)?; - - (preds.0).0.pop(); - - Ok(match hook { - CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => { - self.term_expanders = code - } - CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => { - self.goal_expanders = code - } - }) - } - 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::::new(false); - self.term_expanders = cg.compile_predicate(&preds.0)?; - } - } - 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::::new(false); - self.goal_expanders = cg.compile_predicate(&preds.0)?; - } - } - }) + if current_arg_num == 0 || current_arg_num != arg_num { + return index + 1; } } + + 0 } -fn compile_query( - terms: Vec, +fn compile_standalone_clause( + clause: PredicateClause, queue: VecDeque, -) -> Result<(Code, AllocVarDict), ParserError> { - // count backtracking inferences. - let mut cg = CodeGenerator::::new(false); - let mut code = cg.compile_query(&terms)?; + settings: CodeGenSettings, + atom_tbl: TabledData, +) -> Result { + let mut cg = CodeGenerator::::new(atom_tbl.clone(), settings); + let mut clause_code = cg.compile_predicate(&vec![clause])?; - 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), -) { - 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()); -} - -fn setup_module_expansions(wam: &mut Machine, module: &Module) { - let term_expansions = module.term_expansions.clone(); - let goal_expansions = module.goal_expansions.clone(); - - add_hooks_to_mockup( - &mut wam.code_repo, - CompileTimeHook::TermExpansion, - term_expansions, - ); - - add_hooks_to_mockup( - &mut wam.code_repo, - CompileTimeHook::GoalExpansion, - goal_expansions, - ); -} - -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(), - ); - - match compile_into_module_impl(wam, &mut compiler, module, src, indices) { - Ok(()) => { - EvalSession::EntrySuccess - } - 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); - - 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); - - wam.code_repo.compile_hook(CompileTimeHook::TermExpansion)?; - wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion)?; - - let mut results = compiler.gather_items( - wam, - &mut parsing_stream(src)?, - &mut indices, + compile_appendix( + &mut clause_code, + &queue, + cg.jmp_by_locs, + settings.non_counted_bt, + atom_tbl, )?; - 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 mut clause_code_generator = ClauseCodeGenerator::new( - results.in_situ_code.len(), - module_name.clone() - ); - - clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?; - - let top_level_term_dir = results.top_level_term_dirs.consolidate(); - let module = wam.indices.take_module(module_name).unwrap(); - - add_module( - wam, - module, - indices, - top_level_term_dir, - ); - - 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)) + Ok(StandaloneCompileResult { + clause_code, + standalone_skeleton: cg.skeleton, + }) } -#[derive(Debug)] -pub struct GatherResult { - dynamic_clause_map: DynamicClauseMap, - pub(crate) worker_results: Vec, - toplevel_results: Vec, - 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, -} - -#[derive(Debug)] -pub struct ClauseCodeGenerator { - len_offset: usize, - code: Code, - module_name: ClauseName, - pi_to_loc: IndexMap, -} - -impl ClauseCodeGenerator { - #[inline] - fn new(len_offset: usize, module_name: ClauseName) -> Self { - ClauseCodeGenerator { - len_offset, - code: vec![], - module_name, - pi_to_loc: IndexMap::new(), +fn derelictize_try_me_else( + code: &mut Code, + index: usize, + retraction_info: &mut RetractionInfo, +) -> Option { + match &mut code[index] { + Line::Choice(ChoiceInstruction::TryMeElse(0)) => { + None } - } - - // 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; - } - - 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, - ); - - PredicateClause::Fact(clause, 0, 0) - }) - .collect(), + Line::Choice(ChoiceInstruction::TryMeElse(ref mut offset)) => { + retraction_info.push_record( + RetractionRecord::ModifiedTryMeElse(index, *offset), ); - let p = self.code.len() + wam.code_repo.code.len() + self.len_offset; - let mut cg = CodeGenerator::::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()); + Some(mem::replace(offset, 0)) + } + _ => { + unreachable!() } - - Ok(()) } +} - fn add_clause_code(self, wam: &mut Machine, dynamic_code_dir: DynamicClauseMap) - { - wam.code_repo.code.extend(self.code.into_iter()); +fn merge_indices( + code: &mut Code, + target_index_loc: usize, + index_range: Range, + 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); - 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 target_indexing_line = + to_indexing_line_mut(&mut code[target_index_loc]).unwrap(); + + skeleton[clause_index].opt_arg_index_key.set_switch_on_term_loc(target_index_loc); + + merge_clause_index( + target_indexing_line, + &mut skeleton[0 .. clause_index + 1], + clause_loc, + AppendOrPrepend::Append, + ); + + retraction_info.push_record( + RetractionRecord::AddedIndex( + skeleton[clause_index].opt_arg_index_key.clone(), + clause_loc, + ), + ); + } else { + break; + } + } +} + +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; + } + Line::IndexingCode(indexing_code) => { + match &indexing_code[0] { + IndexingLine::Indexing( + IndexingInstruction::SwitchOnTerm(_, v, ..) + ) => { + index += v; + } + _ => { + 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; } } - - for ((name, arity), _) in dynamic_code_dir { - wam.indices.dynamic_code_dir.insert((name.owning_module(), name, arity), - DynamicPredicateInfo::default()); - } - - 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()); - - entry.clauses_subsection_p = p; - } } } -fn insert_or_refresh_term_dir_quantum( - term_dir: &TermDir, - key: PredicateKey, - term_dirs: &mut TermDirQuantum +fn remove_index_from_subsequence( + code: &mut Code, + opt_arg_index_key: &OptArgIndexKey, + clause_start: usize, + retraction_info: &mut RetractionInfo, ) { - match term_dir.get(&key) { - Some((ref preds, ref queue)) => { - let entry = TermDirQuantumEntry::from(preds, queue); - term_dirs.insert_or_refresh(key, entry); + 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); + + let target_indexing_line = + to_indexing_line_mut(&mut code[index_loc]).unwrap(); + + let offset = clause_start - index_loc + 1; + + 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, + ), + ); + } +} + +fn merge_indexed_subsequences( + code: &mut Code, + skeleton: &mut PredicateSkeleton, + lower_upper_bound: usize, + upper_lower_bound: usize, + retraction_info: &mut RetractionInfo, +) -> Option { + // 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 &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)); + } + } + } + } + } + _ => { + } + } + + thread_choice_instr_at_to( + code, + inner_trust_me_loc, + inner_try_me_else_loc, + retraction_info, + ); + + let mut end_of_upper_lower_bound = None; + + 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 outer_threaded_choice_instr_loc = + skeleton.clauses[lower_upper_bound].clause_start - 2; + + 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 => { - let entry = TermDirQuantumEntry::from(&Predicate::new(), &VecDeque::new()); - term_dirs.insert_or_refresh(key, entry); + 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), + ); + + *o = 0; + + return Some(IndexPtr::Index(outer_threaded_choice_instr_loc + 1)); + } + _ => { + } + } + } + } + + None +} + +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, + ), + ); + + clause_clause_loc +} + +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), + ); + + 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), + ); + + 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!() + } } } } -#[derive(Debug)] -pub struct ListingCompiler { - module: Option, - user_term_dir: TermDir, - orig_term_expansion_lens: (usize, usize), - orig_goal_expansion_lens: (usize, usize), - initialization_goals: (Vec, VecDeque), - suppress_warnings: bool, - listing_src: ListingSource, // a file? a module? -} - -fn add_toplevel( - wam: &mut Machine, - indices: IndexStore, - term_dir: TermDir, +fn set_switch_var_offset_to_choice_instr_( + code: &mut Code, + index_loc: usize, + offset: 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); + let target_indexing_line = + to_indexing_line_mut(&mut code[index_loc]).unwrap(); - wam.code_repo.term_dir.extend(term_dir.into_iter()); + let v = + match &mut target_indexing_line[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => { + *v + } + _ => { + unreachable!(); + } + }; + + match &code[index_loc + v] { + Line::Choice(ChoiceInstruction::TryMeElse(_)) => { + } + _ => { + set_switch_var_offset( + code, + index_loc, + offset, + retraction_info, + ); + } + } } #[inline] -fn add_module( - wam: &mut Machine, - mut module: Module, - indices: IndexStore, - term_dir: TermDir, +fn set_switch_var_offset( + code: &mut Code, + index_loc: usize, + offset: usize, + retraction_info: &mut RetractionInfo, ) { - module.code_dir.extend(indices.code_dir); - module.op_dir.extend(indices.op_dir); - module.term_dir.extend(term_dir); + let target_indexing_line = + to_indexing_line_mut(&mut code[index_loc]).unwrap(); - wam.add_in_situ_module_dir(indices.module_dir); - wam.add_module(module); + let old_v = + match &mut target_indexing_line[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => { + mem::replace(v, offset) + } + _ => { + unreachable!() + } + }; + + retraction_info.push_record( + RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v), + ); } -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 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), + ); - let mut clause_code_generator = ClauseCodeGenerator::new(code.len(), clause_name!("user")); - clause_code_generator.generate_clause_code(&dynamic_clause_map, wam)?; - - add_toplevel(wam, indices, term_dir); - wam.code_repo.code.extend(code); - clause_code_generator.add_clause_code(wam, dynamic_clause_map); - - Ok(()) -} - -pub(super) -fn load_library( - wam: &mut Machine, - name: ClauseName, - suppress_warnings: bool, -) -> Result { - match LIBRARIES.borrow().get(name.as_str()) { - Some(code) => { - let listing_src = ListingSource::User; - - load_module( - wam, - Stream::from(*code), - suppress_warnings, - &listing_src, - ) + code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0)); } - None => { - let err = ExistenceError::ModuleSource(ModuleSource::Library( - name.clone() - )); + Line::Choice(ChoiceInstruction::TryMeElse(o)) => { + let o = *o; - Err(SessionError::ExistenceError(err)) - } - } -} + retraction_info.push_record( + RetractionRecord::ModifiedTryMeElse(instr_loc, o), + ); -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 - } - } - - /* 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(); - } - _ => {} + 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)); } - _ => {} - }, + } + } + _ => { + unreachable!(); + } + } +} + +fn thread_choice_instr_at_to( + code: &mut Code, + mut instr_loc: usize, + target_loc: usize, + retraction_info: &mut RetractionInfo, +) { + 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), + ); + + *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), + ); + + *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)); + + return; + } + Line::Choice(ChoiceInstruction::TrustMe(o)) + if *o > 0 => { + instr_loc += *o; + } + _ => { + unreachable!() + } + } + } +} + +fn remove_non_leading_clause( + code: &mut Code, + preceding_choice_instr_loc: usize, + non_indexed_choice_instr_loc: usize, + retraction_info: &mut RetractionInfo, +) -> Option { + 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, + ); + + 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, + ), + ); + + code[preceding_choice_instr_loc] = + Line::Choice(ChoiceInstruction::TrustMe(0)); + + None + } + Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => { + retraction_info.push_record( + RetractionRecord::ModifiedTryMeElse( + preceding_choice_instr_loc, + *o, + ) + ); + + *o = 0; + + Some(IndexPtr::Index(preceding_choice_instr_loc + 1)) + } + _ => { + unreachable!(); + } + } + } + _ => { + unreachable!(); + } + } +} + +fn finalize_retract( + key: PredicateKey, + compilation_target: CompilationTarget, + skeleton: &mut PredicateSkeleton, + code_index: CodeIndex, + target_pos: usize, + index_ptr_opt: Option, + retraction_info: &mut RetractionInfo, +) -> usize { + let clause_clause_loc = + delete_from_dynamic_skeleton( + compilation_target.clone(), + key.clone(), + skeleton, + target_pos, + retraction_info, + ); + + 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) - ); - - 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) +fn remove_leading_unindexed_clause( + code: &mut Code, + non_indexed_choice_instr_loc: usize, + retraction_info: &mut RetractionInfo, +) -> Option { + 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, + ) ); + + 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, - 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![]; - 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 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 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) + 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, + ), ); - } else { - submodule.inserted_expansions = true; - wam_indices.remove_module(clause_name!("user"), &submodule); + + let outer_thread_choice_loc = skeleton.clauses[1].clause_start - 2; + + retraction_info.push_record( + RetractionRecord::SkeletonClauseStartReplaced( + compilation_target, + key.clone(), + 1, + skeleton.clauses[1].clause_start, + ), + ); + + skeleton.clauses[1].clause_start = + find_inner_choice_instr( + code, + skeleton.clauses[1].clause_start, + index_loc, + ); + + let inner_thread_rev_offset = + 3 + prepend_queue.len() + clause_loc - skeleton.clauses[1].clause_start; + + prepend_queue.push_back( + Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), + ); + + prepend_queue.push_front( + Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), + ); + + // prepend_queue is now: + // | TryMeElse N_2 + // | (clause_code) + // +N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1) + + prepend_queue.push_front( + Line::Control(ControlInstruction::RevJmpBy( + 1 + clause_loc - index_loc + )), + ); + + 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. + + let outer_thread_rev_offset = + prepend_queue.len() + 1 + clause_loc - outer_thread_choice_loc - + next_subseq_offset; + + prepend_queue.push_back( + Line::Control(ControlInstruction::RevJmpBy(outer_thread_rev_offset)) + ); + + 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, + ); + + internalize_choice_instr_at(code, skeleton.clauses[1].clause_start, retraction_info); + + code.extend(prepend_queue.into_iter()); + + clause_loc + (outer_thread_choice_offset == 0) as usize } + _ => { + prepend_queue.extend(clause_code.drain(1 ..)); - Ok(wam_indices.insert_module(submodule)) - } else { - let err = ExistenceError::ModuleSource(ModuleSource::File( - module_name - )); + skeleton.clauses[0].opt_arg_index_key += clause_loc; + skeleton.clauses[0].clause_start = clause_loc + 2; - Err(SessionError::ExistenceError(err)) + 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!(); + } + } + + prepend_queue.push_back( + Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), + ); + + 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 ..)); - #[inline] - fn get_module_name(&self) -> ClauseName { - self.module - .as_ref() - .map(|module| module.module_decl.name.clone()) - .unwrap_or(ClauseName::BuiltIn("user")) - } + let old_clause_start = skeleton.clauses[1].clause_start - 2; - fn generate_init_goal_code( - &mut self, - ) -> Result { - let query_terms = mem::replace(&mut self.initialization_goals.0, vec![]); - let queue = mem::replace(&mut self.initialization_goals.1, VecDeque::new()); + let inner_thread_rev_offset = + 1 + prepend_queue.len() + clause_loc - old_clause_start; - compile_query(query_terms, queue) - .map(|(code, _)| code) - .map_err(SessionError::from) - } + prepend_queue.push_back( + Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), + ); - 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::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), + ); - let idx = code_dir - .entry(key.clone()) - .or_insert(CodeIndex::default()); + // prepend_queue is now: + // | TryMeElse(N_2) + // | (clause_code) + // +N_2 | RevJmpBy (RetryMeElse(M_1)) - 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); + internalize_choice_instr_at(code, old_clause_start, retraction_info); + + 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) } None => { - let (decl, queue) = decl; + prepend_queue.extend(clause_code.drain(1 ..)); - let mut cg = CodeGenerator::::new(false); - let mut decl_code = cg.compile_predicate(&decl.0)?; + let old_clause_start = skeleton.clauses[1].clause_start; - compile_appendix(&mut decl_code, &queue, false)?; + let inner_thread_rev_offset = + 1 + prepend_queue.len() + clause_loc - old_clause_start; - let in_situ_p = in_situ_code.len(); + prepend_queue.push_back( + Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), + ); - in_situ_code.extend(decl_code.into_iter()); + prepend_queue.push_front( + Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), + ); - 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); + // prepend_queue is now: + // | TryMeElse(N_2) + // | (clause_code) + // +N_2 | RevJmpBy (RetryMeElse(M_1)) + + internalize_choice_instr_at(code, old_clause_start, retraction_info); + + 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 append_compiled_clause( + code: &mut Code, + mut clause_code: Code, + skeleton: &mut PredicateSkeleton, + retraction_info: &mut RetractionInfo, +) -> Option { + 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); + } + + skeleton.clauses[target_pos - 1].clause_start + } + _ => { + 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 + } + _ => { + if lower_bound == 0 { + code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start); + } + + skeleton.clauses[lower_bound].clause_start + } + } + } + }; + + 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 adapt_in_situ_code( + false +} + +impl<'a> LoadState<'a> { + fn compile( &mut self, - decls: Vec, - 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)?; + key: PredicateKey, + predicates: &Vec, + queue: &VecDeque, + settings: CodeGenSettings, + ) -> Result { + 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 (name, _arity) = key.clone(); - let module_name = name.owning_module(); + let mut cg = CodeGenerator::::new( + self.wam.machine_st.atom_tbl.clone(), + settings, + ); - 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![] - }; + let mut code = cg.compile_predicate(predicates)?; - Module::new( - module_decl, - module_stub.atom_tbl.clone(), - self.listing_src.clone(), - ) - }); + compile_appendix( + &mut code, + queue, + cg.jmp_by_locs, + settings.non_counted_bt, + self.wam.machine_st.atom_tbl.clone(), + )?; - self.set_code_index( - wam, - key, - in_situ_code, - &mut module.code_dir, - &module_stub.in_situ_code_dir, - decl, - )?; + 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; + } + + match &mut code[0] { + Line::Choice(ChoiceInstruction::TryMeElse(0)) => { + code_ptr += 1; } _ => { - self.set_code_index( - wam, - key, - in_situ_code, - code_dir, - in_situ_code_dir, - decl, - )?; + } + } + + 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); } } } - Ok(()) + set_code_index( + &mut self.retraction_info, + &self.compilation_target, + key, + &code_index, + IndexPtr::Index(code_ptr), + ); + + self.wam.code_repo.code.extend(code.into_iter()); + Ok(code_index.get()) } - fn add_term_dir_terms( + 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(super) + fn incremental_compile_clause( &mut self, - hook: CompileTimeHook, - code_repo: &mut CodeRepo, key: PredicateKey, clause: PredicateClause, queue: VecDeque, - ) -> (usize, usize) { - let preds = code_repo - .term_dir - .entry(key.clone()) - .or_insert((Predicate::new(), VecDeque::from(vec![]))); + non_counted_bt: bool, + append_or_prepend: AppendOrPrepend, + ) -> Result { + self.record_incremental_compile(key.clone(), append_or_prepend); - let (mut len, mut queue_len) = ((preds.0).0.len(), preds.1.len()); + 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); + } + }; - 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![]))); + let settings = CodeGenSettings::new(true, non_counted_bt); + let atom_tbl = self.wam.machine_st.atom_tbl.clone(); - 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()); + let StandaloneCompileResult { clause_code, mut standalone_skeleton } = + compile_standalone_clause(clause, queue, settings, atom_tbl)?; + + match append_or_prepend { + AppendOrPrepend::Append => { + skeleton.clauses.push_back(standalone_skeleton.clauses.pop_back().unwrap()); + + self.retraction_info.push_record( + RetractionRecord::SkeletonClausePopBack( + self.compilation_target.clone(), + key.clone(), + ), + ); + + let result = + append_compiled_clause( + &mut self.wam.code_repo.code, + clause_code, + skeleton, + &mut self.retraction_info, + ); + + let code_index = self.get_or_insert_code_index(key.clone()); + + 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(code_index.get()) } + AppendOrPrepend::Prepend => { + skeleton.clauses.push_front(standalone_skeleton.clauses.pop_back().unwrap()); - (module_preds.0).0.push(clause); - module_preds.1.extend(queue.into_iter()); + self.retraction_info.push_record( + RetractionRecord::SkeletonClausePopFront( + self.compilation_target.clone(), + key.clone(), + ), + ); - (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 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, + ); - len += 1; - queue_len += queue.len(); + let code_index = self.get_or_insert_code_index(key.clone()); - (preds.0).0.push(clause); - preds.1.extend(queue.into_iter()); + set_code_index( + &mut self.retraction_info, + &self.compilation_target, + key, + &code_index, + IndexPtr::Index(threaded_choice_instr_loc), + ); - (preds.0).0.extend((module_preds.0).0.iter().cloned()); - preds.1.extend(module_preds.1.iter().cloned()); + Ok(IndexPtr::Index(threaded_choice_instr_loc)) + } } - - (len, queue_len) } - 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 - ), - ); + pub(super) + fn retract_clause(&mut self, key: PredicateKey, target_pos: usize) -> usize { + let code_index = self.get_or_insert_code_index(key.clone()); - op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir) - } + let skeleton = + match self.wam.indices.get_predicate_skeleton( + &self.compilation_target, + &key, + ) { + Some(skeleton) => { + skeleton + } + None => { + unreachable!(); + } + }; - fn process_decl( - &mut self, - decl: Declaration, - wam: &mut Machine, - indices: &mut IndexStore, - flags: MachineFlags, - non_counted_bt_preds: &mut IndexSet, - ) -> Result<(), SessionError> { - match decl { - Declaration::Dynamic(..) => { - Ok(()) - } - Declaration::EndOfFile => { - Ok(()) - } - 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); + 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(); - let result = wam - .code_repo - .compile_hook(hook) - .map_err(SessionError::from); + 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, + ); - wam.code_repo.truncate_terms(key, len, queue_len); + remove_index_from_subsequence( + code, + &skeleton.clauses[target_pos].opt_arg_index_key, + inner_clause_start, + &mut self.retraction_info, + ); - 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()); + 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, + ); - for export in module_decl.exports.iter() { - if let ModuleExport::OpDecl(ref op_decl) = export { - self.submit_op(wam, indices, op_decl)?; + 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, + ); } } - - let listing_src = self.listing_src.clone(); - - 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 - }; - - 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()); - - 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, - ) + None => { + } } } - } - 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; + 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; - insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs); - } - 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()); + 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 + )), + ); - insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs); - } - None => { - let err = ExistenceError::ModuleSource(ModuleSource::File( - module_name, - )); + match target_indexing_line { + Line::IndexingCode(indexing_code) => { + self.retraction_info.push_record( + RetractionRecord::ReplacedIndexingLine( + target_indexing_loc, + indexing_code, + ), + ); + } + _ => { + } + } - return Err(SessionError::ExistenceError(err)); + 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, + ); + } + }; + + 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, + ); + + 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, + ) + } +} + +impl<'a, TS: TermStream> Loader<'a, TS> { + pub(super) + fn compile_clause_clauses>( + &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 compilation_target = mem::replace( + &mut self.load_state.compilation_target, + CompilationTarget::Module(clause_name!("builtins")), + ); + + let mut clause_clause_locs = sdeq![]; + + for clause_predicate in clause_predicates { + clause_clause_locs.push_back(self.load_state.wam.code_repo.code.len()); + + 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, + ); + + if let Err(e) = result { + self.load_state.compilation_target = compilation_target; + return Err(e); + } + } + + 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!(); + } + } + + 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(), + ), + ); + + 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(), + ), + ); + + for loc in clause_clause_locs.iter() { + skeleton.clause_clause_locs.push_front(*loc); + } + + self.load_state.increment_clause_assert_margin( + clause_clause_locs.len() + ); + } + None => { + unreachable!(); + } + } + + self.load_state.compilation_target = compilation_target; Ok(()) } - fn process_and_commit_decl( - &mut self, - decl: Declaration, - worker: &mut TopLevelBatchWorker, - indices: &mut IndexStore, - flags: MachineFlags, - ) -> Result<(), SessionError> { - let mut update_expansion_lengths = false; + pub(super) + fn compile_and_submit(&mut self) -> Result<(), SessionError> { + let queue = self.preprocessor.parse_queue(&mut self.load_state)?; - match &decl { - &Declaration::Dynamic(ref name, arity) => { - worker - .dynamic_clause_map - .entry((name.clone(), arity)) - .or_insert(vec![]); + let key = self.predicates + .first() + .and_then(|cl| { + let arity = cl.arity(); + cl.name().map(|name| (name, arity)) + }) + .ok_or(SessionError::NamelessEntry)?; - 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()) - } - &Declaration::MultiFile(ref indicator) => { - self.setup_multifile_decl(indicator.clone(), worker)?; - } - &Declaration::UseModule(_) | &Declaration::UseQualifiedModule(..) => { - update_expansion_lengths = true - } - _ => {} - }; + 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)); - let result = self.process_decl( - decl, - &mut worker.term_stream.wam, - indices, - flags, - &mut worker.non_counted_bt_preds, - ); + let non_counted_bt = self.non_counted_bt_preds.contains(&key); + let settings = CodeGenSettings::new(is_extensible, non_counted_bt); - if update_expansion_lengths { - worker.term_stream.update_expansion_lens(); + self.load_state.compile(key.clone(), &self.predicates, &queue, settings)?; + + if is_dynamic { + let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter(); + self.compile_clause_clauses(key, iter, AppendOrPrepend::Append)?; } - result - } - - pub(crate) - fn gather_items( - &mut self, - wam: &mut Machine, - src: &mut ParsingStream, - indices: &mut IndexStore, - ) -> Result { - 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()); - - let mut top_level_term_dirs = TermDirQuantum::new(); - - 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; - - self.process_and_commit_decl(decl, &mut worker, indices, flags)?; - - if let Some(ref module) = &self.module { - worker.term_stream.set_atom_tbl(module.atom_tbl.clone()); - - top_level_term_dirs = mem::replace( - &mut worker.term_dirs, - TermDirQuantum::new(), - ); - } - } 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 module_term_dirs = if self.module.is_some() { - worker.term_dirs - } else { - top_level_term_dirs = worker.term_dirs; - TermDirQuantum::new() - }; - - 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(), - }) - } - - 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; - - 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); - - discard_result!(code_repo.compile_hook(CompileTimeHook::UserGoalExpansion)); - discard_result!(code_repo.compile_hook(CompileTimeHook::UserTermExpansion)); - } - - 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(self.predicates.clear()) } } - -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(); - - 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); - - results.worker_results.extend(decls.into_iter()); - } - } - - 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, - )?; - - 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, - )?; - - 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(); - } - } - - 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(), - )) - ) - ); - } - - let mut clause_code_generator = - ClauseCodeGenerator::new(code.len(), module.module_decl.name.clone()); - - wam.check_toplevel_code(&results.toplevel_indices)?; - clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?; - - if let Some(ref module) = wam.indices.modules.swap_remove(&module.module_decl.name) { - wam.indices.remove_module(clause_name!("user"), module); - } - - if module.is_impromptu_module { - add_module(wam, module, indices, module_term_dir); - - let module = wam.indices.take_module(compiler.listing_src.name()).unwrap(); - - 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); - } - - add_toplevel(wam, results.toplevel_indices, top_level_term_dir); - wam.code_repo.code.extend(code.into_iter()); - - 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, - )?; - } - - let init_goal_code = compiler.generate_init_goal_code()?; - - if init_goal_code.len() > 0 { - if !wam.run_init_code(init_goal_code) { - println!("Warning: initialization goal for {} failed", - compiler.listing_src.name()); - } - } - - if !compiler.suppress_warnings { - issue_singleton_warnings( - compiler.listing_src.name(), - results.top_level_terms, - ); - } - - 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 { - 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); - - wam.code_repo.code.extend(results.in_situ_code.into_iter()); - - Ok(p) -} - -#[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); - - match compile_work(&mut compiler, wam, src, indices) { - EvalSession::Error(e) => { - compiler.drop_expansions(&mut wam.code_repo); - compiler.print_error(&e); - - EvalSession::Error(e) - } - 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)) - } -} - -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) -} diff --git a/src/machine/dynamic_database.rs b/src/machine/dynamic_database.rs deleted file mode 100644 index 6fc01b4c..00000000 --- a/src/machine/dynamic_database.rs +++ /dev/null @@ -1,396 +0,0 @@ -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 { - 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, - 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); - } -} diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 8f741f66..612742c9 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -168,6 +168,9 @@ impl HeapTemplate { &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()) } @@ -295,6 +298,9 @@ impl HeapTemplate { val @ HeapCellValue::Rational(_) => { Addr::Con(self.push(val)) } + val @ HeapCellValue::LoadStatePayload(_) => { + Addr::LoadStatePayload(self.push(val)) + } val @ HeapCellValue::NamedStr(..) => { Addr::Str(self.push(val)) } @@ -371,15 +377,6 @@ impl HeapTemplate { } } - #[inline] - pub(crate) - fn take(&mut self) -> Self { - HeapTemplate { - buf: self.buf.take(), - _marker: PhantomData, - } - } - #[inline] pub(crate) fn truncate(&mut self, h: usize) { @@ -479,9 +476,7 @@ impl HeapTemplate { ("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) { @@ -491,13 +486,10 @@ impl HeapTemplate { None } - ("user_goal_expansion", 1) => { - extract_integer(s+1).map(LocalCodePtr::UserGoalExpansion) + */ + _ => { + None } - ("user_term_expansion", 1) => { - extract_integer(s+1).map(LocalCodePtr::UserTermExpansion) - } - _ => None } } _ => unreachable!() @@ -508,8 +500,7 @@ impl HeapTemplate { } #[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]) diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs new file mode 100644 index 00000000..1d5526a5 --- /dev/null +++ b/src/machine/load_state.rs @@ -0,0 +1,918 @@ +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, + 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, + 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, + ) -> 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, + ) -> 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, + ) { + 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, + ) -> 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, + ) -> 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!() + } + } + } + } + } +} diff --git a/src/machine/loader.rs b/src/machine/loader.rs new file mode 100644 index 00000000..a6704894 --- /dev/null +++ b/src/machine/loader.rs @@ -0,0 +1,1708 @@ +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), + 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), + 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), +} + +/* + * 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, +} + +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, + pub(super) clause_clauses: Vec<(Term, Term)>, + term_stream: TermStream, + pub(super) non_counted_bt_preds: IndexSet, + 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 { + while let Some(decl) = self.dequeue_terms()? { + self.load_decl(decl)?; + } + + TS::evacuate(self) + } + + fn dequeue_terms(&mut self) -> Result, 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 { + 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, 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, 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, + 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, + ); +} diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 1dcc1db8..dcea8448 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -1,6 +1,6 @@ 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::*; @@ -355,24 +355,11 @@ impl MachineError { } } - 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, @@ -381,12 +368,14 @@ impl MachineError { 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, @@ -395,6 +384,15 @@ impl MachineError { 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, @@ -411,7 +409,7 @@ impl MachineError { functor!(clause_name(op)), ) } - SessionError::ParserError(err) => { + SessionError::CompilationError(err) => { Self::syntax_error(h, err) } SessionError::QueryCannotBeDefinedAsFact => { @@ -426,13 +424,15 @@ impl MachineError { } pub(super) - fn syntax_error(h: usize, err: ParserError) -> Self { - if let ParserError::Arithmetic(err) = err { + fn syntax_error>(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", @@ -475,9 +475,103 @@ impl MachineError { } } +#[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 for CompilationError { + #[inline] + fn from(err: ArithmeticError) -> CompilationError { + CompilationError::Arithmetic(err) + } +} + +impl From 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, @@ -490,7 +584,7 @@ impl Permission { #[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", @@ -807,37 +901,55 @@ pub enum ExistenceError { #[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 for EvalSession { + #[inline] fn from(err: SessionError) -> Self { EvalSession::Error(err) } } +impl From for SessionError { + #[inline] + fn from(err: std::io::Error) -> SessionError { + SessionError::from(ParserError::from(err)) + } +} + impl From for SessionError { + #[inline] fn from(err: ParserError) -> Self { - SessionError::ParserError(err) + SessionError::CompilationError(CompilationError::from(err)) + } +} + +impl From for SessionError { + #[inline] + fn from(err: CompilationError) -> Self { + SessionError::CompilationError(err) } } impl From for EvalSession { + #[inline] fn from(err: ParserError) -> Self { - EvalSession::from(SessionError::ParserError(err)) + EvalSession::from(SessionError::from(err)) } } diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 13fb6ae7..14489b76 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -1,9 +1,9 @@ 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::*; @@ -11,20 +11,21 @@ use crate::machine::machine_state::*; 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)] @@ -64,6 +65,7 @@ pub enum Addr { Fixnum(isize), Float(OrderedFloat), Lis(usize), + LoadStatePayload(usize), HeapCell(usize), PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes. StackCell(usize, usize), @@ -231,7 +233,7 @@ impl Addr { Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => { Some(TermOrderCategory::Compound) } - Addr::CutPoint(_) | Addr::Stream(_) | Addr::TcpListener(_) => { + Addr::CutPoint(_) | Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => { None } } @@ -369,6 +371,7 @@ pub enum HeapCellValue { Atom(ClauseName, Option), DBRef(DBRef), Integer(Rc), + LoadStatePayload(LoadStatePayload), NamedStr(usize, ClauseName, Option), // arity, name, precedence/Specifier if it has one. Rational(Rc), PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant. @@ -387,6 +390,9 @@ impl HeapCellValue { HeapCellValue::Rational(..) => { Addr::Con(focus) } + HeapCellValue::LoadStatePayload(_) => { + Addr::LoadStatePayload(focus) + } HeapCellValue::NamedStr(_, _, _) => { Addr::Str(focus) } @@ -417,6 +423,9 @@ impl HeapCellValue { &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()) } @@ -443,50 +452,42 @@ impl From for HeapCellValue { } } -#[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>); +pub struct CodeIndex(pub Rc>); + +impl Deref for CodeIndex { + type Target = Cell; + + #[inline] + fn deref(&self) -> &Self::Target { + self.0.deref() + } +} impl CodeIndex { #[inline] - pub fn new(ptr: IndexPtr, module_name: ClauseName) -> Self { - CodeIndex(Rc::new(RefCell::new(( ptr, module_name )))) + pub(super) + fn new(ptr: IndexPtr) -> Self { + CodeIndex(Rc::new(Cell::new(ptr))) } #[inline] pub fn is_undefined(&self) -> bool { - let index_ptr = &self.0.borrow().0; - - match index_ptr { - &IndexPtr::Undefined | &IndexPtr::DynamicUndefined => true, + match self.0.get() { + IndexPtr::Undefined => true, // | &IndexPtr::DynamicUndefined => true, _ => false } } - #[inline] - pub fn dynamic_undefined(module_name: ClauseName) -> Self { - CodeIndex(Rc::new(RefCell::new(( - IndexPtr::DynamicUndefined, - module_name - )))) - } - - #[inline] - pub fn module_name(&self) -> ClauseName { - self.0.borrow().1.clone() - } - pub fn local(&self) -> Option { - match self.0.borrow().0 { + match self.0.get() { IndexPtr::Index(i) => Some(i), _ => None, } @@ -495,60 +496,34 @@ impl CodeIndex { impl Default for CodeIndex { fn default() -> Self { - CodeIndex(Rc::new(RefCell::new(( - IndexPtr::Undefined, - clause_name!(""), - )))) + CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined))) } } -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, new_addr: Addr) { - match self { - DynamicAssertPlace::Back => addrs.push_back(new_addr), - DynamicAssertPlace::Front => addrs.push_front(new_addr), - } - } -} - -#[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)] @@ -556,7 +531,7 @@ pub enum CodePtr { 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. } @@ -568,18 +543,26 @@ impl CodePtr { | &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 { @@ -591,6 +574,16 @@ 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)) { @@ -621,28 +614,21 @@ impl LocalCodePtr { [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)] )); } } @@ -651,6 +637,7 @@ impl LocalCodePtr { } } +/* impl PartialOrd for CodePtr { fn partial_cmp(&self, other: &CodePtr) -> Option { match (self, other) { @@ -667,11 +654,8 @@ impl PartialOrd for CodePtr { impl PartialOrd for LocalCodePtr { fn partial_cmp(&self, other: &LocalCodePtr) -> Option { 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(_, _)) => { @@ -683,29 +667,34 @@ impl PartialOrd for LocalCodePtr { } } } +*/ 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 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), } } } @@ -713,30 +702,40 @@ impl Add for LocalCodePtr { impl Sub for LocalCodePtr { type Output = Option; + #[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 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 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!(), } } } @@ -746,10 +745,14 @@ impl Add for CodePtr { 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) } @@ -767,186 +770,206 @@ impl AddAssign for CodePtr { } } -pub type HeapVarDict = IndexMap, Addr>; -pub type AllocVarDict = IndexMap, 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 for CodePtr { + #[inline] + fn sub_assign(&mut self, rhs: usize) { + match self { + CodePtr::Local(ref mut local) => *local -= rhs, + _ => unreachable!(), } } } + +pub type HeapVarDict = IndexMap, Addr>; +pub type AllocVarDict = IndexMap, VarData>; + pub type InSituCodeDir = IndexMap; - -// key type: module name, predicate indicator. -pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>; - pub type GlobalVarDir = IndexMap)>; #[derive(Debug)] pub(crate) struct ModuleStub { - pub(crate) atom_tbl: TabledData, pub(crate) in_situ_code_dir: InSituCodeDir, } -impl ModuleStub { - pub(crate) fn new(atom_tbl: TabledData) -> Self { - ModuleStub { - atom_tbl, - in_situ_code_dir: InSituCodeDir::new(), - } - } -} - -pub(crate) type ModuleStubDir = IndexMap; +// pub(crate) type ModuleStubDir = IndexMap; pub(crate) type StreamAliasDir = IndexMap; pub(crate) type StreamDir = BTreeSet; +pub type MetaPredicateDir = IndexMap>; + +pub type ExtensiblePredicates = IndexMap; + #[derive(Debug)] pub struct IndexStore { - pub(super) atom_tbl: TabledData, 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( - &self, - name: ClauseName, - module: ClauseName, - arity: usize, - op_spec: Option, - ) -> 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)), - ClauseType::Op(name, spec, ..) => { - module.code_dir.contains_key(&(name, spec.arity())) + 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 + } + } } - _ => 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, - }, + } } } - 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")) - )))); + 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); + } + } + } + } + } } - #[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_predicate_code_index( &self, - module: ClauseName, name: ClauseName, arity: usize, - ) -> Option { - self.dynamic_code_dir.get(&(module, name, arity)).cloned() + module: ClauseName, + op_spec: Option, + ) -> Option { + 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, ..) => { + self.code_dir.get(&(name, spec.arity())).cloned() + } + _ => { + 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 + } + } + }) + } } - #[inline] - pub(crate) fn take_in_situ_module_dir(&mut self) -> ModuleStubDir { - mem::replace(&mut self.in_situ_module_dir, ModuleStubDir::new()) + pub fn get_meta_predicate_spec( + &self, + name: ClauseName, + arity: usize, + compilation_target: &CompilationTarget, + ) -> Option<&Vec> { + 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 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 { - self.modules.swap_remove(&name) - } - - #[inline] - pub fn insert_module(&mut self, module: Module) { - self.modules.insert(module.module_decl.name.clone(), module); + 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] 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(), - } + IndexStore::default() } - #[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); - } - - #[inline] - fn get_internal( - &self, - name: ClauseName, - arity: usize, - in_mod: ClauseName, - ) -> Option { - self.modules - .get(&in_mod) - .and_then(|ref module| module.code_dir.get(&(name, arity))) - .cloned() - } - - 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 { @@ -960,129 +983,6 @@ impl IndexStore { } pub type CodeDir = BTreeMap; -pub type TermDir = IndexMap)>; - -#[derive(Debug)] -pub struct TermDirQuantumEntry { - pub old_terms: (Predicate, VecDeque), - pub new_terms: (Predicate, VecDeque), - 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) -> 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); - -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), @@ -1094,7 +994,8 @@ impl<'a, T: 'a + fmt::Debug> fmt::Debug for RefOrOwned<'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), } } } @@ -1107,9 +1008,7 @@ impl<'a, T> RefOrOwned<'a, T> { } } - 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(), diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index e8799566..ab04a532 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -9,14 +9,14 @@ use crate::machine::copier::*; 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; @@ -25,292 +25,6 @@ use std::io::Write; use std::mem; use std::ops::{Index, IndexMut}; -#[derive(Debug)] -pub(crate) struct HeapPStrIter<'a> { - focus: Addr, - machine_st: &'a MachineState, - seen: IndexSet, -} - -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 { - 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 { - 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 { - 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, @@ -332,17 +46,6 @@ impl Ball { 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; @@ -586,6 +289,7 @@ impl Default for HeapPtr { #[derive(Debug)] pub struct MachineState { + pub(crate) atom_tbl: TabledData, pub(super) s: HeapPtr, pub(super) p: CodePtr, pub(super) b: usize, @@ -640,7 +344,7 @@ impl MachineState { loop { match self.read( stream.clone(), - indices.atom_tbl.clone(), + self.atom_tbl.clone(), &indices.op_dir, ) { Ok(term_write_result) => { @@ -654,7 +358,7 @@ impl MachineState { 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); @@ -854,6 +558,15 @@ impl MachineState { 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> { @@ -895,6 +608,24 @@ impl MachineState { 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); @@ -914,58 +645,35 @@ impl MachineState { fn module_lookup( &mut self, indices: &IndexStore, + call_policy: &mut Box, 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); @@ -974,49 +682,6 @@ impl MachineState { } } -fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option -{ - 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>; pub(crate) trait CallPolicy: Any + fmt::Debug { @@ -1090,7 +755,7 @@ 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(()) } @@ -1130,7 +795,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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(()) } @@ -1180,13 +845,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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) } } @@ -1195,27 +859,18 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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)); } } @@ -1227,26 +882,19 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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), + match idx.get() { + IndexPtr::DynamicUndefined => { + machine_st.fail = true; + return Ok(()); + } + IndexPtr::Undefined => { + return Err(machine_st.throw_undefined_error(name, arity)); + } 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)); - } - IndexPtr::UserGoalExpansion => { - machine_st.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0)); - } - IndexPtr::InSituDirEntry(p) => { - machine_st.execute_at_index(arity, LocalCodePtr::InSituDirEntry(p)); - } } Ok(()) @@ -1256,7 +904,8 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { &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 { @@ -1305,15 +954,15 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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) } }; @@ -1338,8 +987,8 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { &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)]; @@ -1347,16 +996,18 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { } 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); @@ -1382,7 +1033,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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 => { @@ -1453,24 +1104,66 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { } } - 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); - machine_st.p = match hook { - CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => { - CodePtr::Local(LocalCodePtr::UserTermExpansion(0)) + if machine_st.fail { + return Ok(()); + } + + 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(()) } @@ -1479,57 +1172,20 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { &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(()) @@ -1542,11 +1198,9 @@ impl CallPolicy for CWILCallPolicy { 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) } @@ -1574,14 +1228,16 @@ impl CallPolicy for CWILCallPolicy { &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 )?; @@ -1593,14 +1249,16 @@ impl CallPolicy for CWILCallPolicy { &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, )?; diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 5de07140..a387970e 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -4,6 +4,7 @@ use crate::prolog_parser::tabled_rc::*; 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::*; @@ -13,6 +14,7 @@ use crate::machine::heap::*; 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::*; @@ -24,22 +26,11 @@ use std::cmp::Ordering; 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, @@ -67,36 +58,6 @@ impl MachineState { } } - 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 @@ -1390,85 +1351,130 @@ impl MachineState { } 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, + call_policy: &mut Box, + ) { + 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 - } - }; - - 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)); - - let offset = - match addr.as_constant_index(&self) { - Some(c) => { - match hm.get(&c) { - Some(offset) => *offset, - _ => 0, - } + 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 } - None => { - 0 + 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::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, + 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, + } } - } else { - 0 + None => { + IndexingCodePtr::Fail + } + }; + + 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 + } + } + _ => { + IndexingCodePtr::Fail + } + }; + + 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; + } } }; } @@ -1679,23 +1685,38 @@ impl MachineState { 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; + } } } @@ -2513,7 +2534,7 @@ impl MachineState { } 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)])); @@ -2531,7 +2552,7 @@ impl MachineState { name.clone(), arity, spec, - &indices.op_dir, + &op_dir, ); self.try_functor_compound_case(name, arity, spec) @@ -2545,7 +2566,7 @@ impl MachineState { clause_name!("."), 2, None, - &indices.op_dir, + &op_dir, ); self.try_functor_compound_case(clause_name!("."), 2, spec) @@ -2620,7 +2641,7 @@ impl MachineState { name, arity as usize, spec, - &indices.op_dir, + &op_dir, a1.as_var().unwrap(), ); } else { @@ -2637,10 +2658,10 @@ impl MachineState { } 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(), ); } @@ -3156,16 +3177,23 @@ impl MachineState { 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); @@ -3176,7 +3204,7 @@ impl MachineState { &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!( @@ -3234,6 +3262,9 @@ impl MachineState { self.b0 = self.b; self.p += offset; } + &ControlInstruction::RevJmpBy(offset) => { + self.p -= offset; + } &ControlInstruction::Proceed => { self.p = CodePtr::Local(self.cp); } @@ -3272,7 +3303,7 @@ impl MachineState { } 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)); @@ -3283,7 +3314,8 @@ impl MachineState { }; } - pub(super) fn execute_choice_instr( + pub(super) + fn execute_choice_instr( &mut self, instr: &ChoiceInstruction, call_policy: &mut Box, @@ -3320,14 +3352,14 @@ impl MachineState { 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)) } } @@ -3374,30 +3406,4 @@ impl MachineState { } } } - - 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(); - } } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index daaf4e81..f8d661a2 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -3,28 +3,29 @@ use crate::prolog_parser::tabled_rc::*; 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; @@ -32,25 +33,21 @@ 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)] @@ -80,6 +77,24 @@ impl Default for MachinePolicies { } } +#[derive(Debug)] +pub(super) struct LoadContext { + pub(super) path: PathBuf, + pub(super) stream: Stream, + pub(super) module: ClauseName, +} + +impl LoadContext { + #[inline] + fn new(path: &str, stream: Stream) -> Self { + LoadContext { + path: PathBuf::from(path), + stream, + module: clause_name!("user"), + } + } +} + #[derive(Debug)] pub struct Machine { pub(super) machine_st: MachineState, @@ -87,136 +102,23 @@ pub struct Machine { 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) user_input: Stream, + pub(super) user_output: Stream, + pub(super) load_contexts: Vec, } -impl Index for CodeRepo { - type Output = Line; +#[inline] +fn current_dir() -> std::path::PathBuf { + let mut path_buf = std::path::PathBuf::from(file!()); - 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 Index for Machine { - type Output = Line; - - fn index(&self, ptr: LocalCodePtr) -> &Self::Output { - &self.code_repo[ptr] - } -} - -impl SubModuleUser for IndexStore { - fn atom_tbl(&self) -> TabledData { - 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 { - 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()); - } - - fn use_qualified_module( - &mut self, - code_repo: &mut CodeRepo, - _: MachineFlags, - submodule: &Module, - exports: &Vec, - ) -> 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; @@ -250,36 +152,6 @@ impl Machine { } } - 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, @@ -302,10 +174,10 @@ impl Machine { 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(); @@ -313,17 +185,94 @@ impl Machine { 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.code_repo.cached_query = code; - self.run_query(); + self.machine_st.cp = LocalCodePtr::Halt; + self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); - let result = self.machine_st.fail; - self.absorb_snapshot(old_machine_st); + return self.run_query(); + } + } - !result + 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"); + + let path = path_buf.to_str().unwrap().to_string(); + + self.load_file(path, Stream::from(include_str!("../toplevel.pl"))); + + 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) { @@ -336,15 +285,16 @@ impl Machine { } 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; @@ -354,193 +304,107 @@ impl Machine { 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, + ListingSource::from_file_and_path( + clause_name!("ops_and_meta_predicates.pl"), + lib_path.clone(), + ), + ).unwrap(); + + bootstrapping_compile( Stream::from(LIBRARIES.borrow()["builtins"]), - default_index_store!(atom_tbl.clone()), - true, - ListingSource::User, - ); - - wam.compile_special_forms(); - - compile_user_module( &mut wam, - Stream::from(LIBRARIES.borrow()["error"]), - true, - ListingSource::User, - ); + ListingSource::from_file_and_path( + clause_name!("builtins.pl"), + lib_path.clone(), + ), + ).unwrap(); - compile_user_module( - &mut wam, - Stream::from(LIBRARIES.borrow()["pairs"]), - true, - ListingSource::User, - ); - - compile_user_module( - &mut wam, - Stream::from(LIBRARIES.borrow()["lists"]), - true, - ListingSource::User, - ); - - compile_user_module( - &mut wam, - Stream::from(LIBRARIES.borrow()["iso_ext"]), - true, - ListingSource::User, - ); - - compile_user_module( - &mut wam, - Stream::from(LIBRARIES.borrow()["si"]), - true, - ListingSource::User, - ); - - compile_user_module( - &mut wam, - Stream::from(LIBRARIES.borrow()["charsio"]), - true, - ListingSource::User, - ); - - if wam.compile_top_level().is_err() { - panic!("Loading '$toplevel' module failed"); + 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!() } - wam.compile_scryerrc(); + lib_path.pop(); // remove the "lib" at the end + + bootstrapping_compile( + Stream::from(include_str!("../term_and_goal_expansion.pl")), + &mut wam, + 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, + 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.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(); @@ -552,307 +416,118 @@ impl Machine { return; } - fn extract_module_export_list(&mut self) -> Result, 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(&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!(), - } - }; - - 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)?; - } - - 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(&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!(), - } - }; - - 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; - } - }; - - 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)?; - } - - 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::AddDynamicPredicate => { + self.add_dynamic_predicate(); + } + REPLCodePtr::AddGoalExpansionClause => { + self.add_goal_expansion_clause(); + } + REPLCodePtr::AddTermExpansionClause => { + self.add_term_expansion_clause(); + } + REPLCodePtr::ClauseToEvacuable => { + self.clause_to_evacuable(); + } + REPLCodePtr::ConcludeLoad => { + self.conclude_load(); + } + 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 }; } } @@ -865,8 +540,8 @@ impl MachineState { 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) => { @@ -884,8 +559,8 @@ impl MachineState { code_repo, &mut policies.call_policy, &mut policies.cut_policy, - current_input_stream, - current_output_stream, + user_input, + user_output, control_instr, ) } @@ -893,8 +568,8 @@ impl MachineState { 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) @@ -911,8 +586,8 @@ impl MachineState { 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, @@ -924,40 +599,40 @@ impl MachineState { 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 @@ -965,7 +640,9 @@ impl MachineState { self.fail = true; return false; } - _ => {} + */ + _ => { + } } true @@ -977,8 +654,8 @@ impl MachineState { 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) { @@ -999,8 +676,8 @@ impl MachineState { indices, policies, code_repo, - current_input_stream, - current_output_stream, + user_input, + user_output, ); if self.fail { @@ -1025,16 +702,16 @@ impl MachineState { 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 { @@ -1055,8 +732,8 @@ impl MachineState { indices, policies, code_repo, - current_input_stream, - current_output_stream, + user_input, + user_output, ) { if self.fail { break; diff --git a/src/machine/modules.rs b/src/machine/modules.rs deleted file mode 100644 index 42576032..00000000 --- a/src/machine/modules.rs +++ /dev/null @@ -1,371 +0,0 @@ -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, - 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, - ) { - 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, - ) { - 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)> - { - 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; - fn op_dir(&mut self) -> &mut OpDir; - fn remove_code_index(&mut self, _: PredicateKey); - fn get_code_index(&self, _: PredicateKey, _: ClauseName) -> Option; - - fn insert_dir_entry(&mut self, _: ClauseName, _: usize, _: CodeIndex); - - fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option { - 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, - ) -> Result<(), SessionError>; - - fn use_module( - &mut self, - _: &mut CodeRepo, - _: MachineFlags, - _: &Module - ) -> Result<(), SessionError>; -} - -pub fn use_qualified_module( - user: &mut User, - submodule: &Module, - exports: &Vec, -) -> 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: &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 { - self.atom_tbl.clone() - } - - fn op_dir(&mut self) -> &mut OpDir { - &mut self.op_dir - } - - fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option { - 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, - ) -> 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(()) - } -} diff --git a/src/machine/partial_string.rs b/src/machine/partial_string.rs index 1413b37c..7d865d49 100644 --- a/src/machine/partial_string.rs +++ b/src/machine/partial_string.rs @@ -1,12 +1,18 @@ +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, @@ -200,3 +206,290 @@ impl PartialString { } } } + +#[derive(Debug)] +pub(crate) struct HeapPStrIter<'a> { + focus: Addr, + machine_st: &'a MachineState, + seen: IndexSet, +} + +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 { + 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 { + 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 { + 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) +} diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs new file mode 100644 index 00000000..7054796a --- /dev/null +++ b/src/machine/preprocessor.rs @@ -0,0 +1,987 @@ +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(terms: I, mut term: Term, sym: ClauseName) -> Term +where + I: DoubleEndedIterator, +{ + 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 { + 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>, + atom_tbl: TabledData, +) -> Result { + 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 +{ + 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 +{ + 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, +) -> Result { + 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, +) -> Result, 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>, + atom_tbl: TabledData, +) -> Result { + 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>) -> Result { + 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>) -> Result { + 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); + +fn setup_qualified_import( + mut terms: Vec>, + atom_tbl: TabledData, +) -> Result { + 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>, + load_state: &LoadState<'a>, +) -> Result<(ClauseName, ClauseName, Vec), CompilationError> +{ + fn get_name_and_meta_specs( + name: ClauseName, + terms: &mut [Box], + ) -> Result<(ClauseName, Vec), 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) -> Result +{ + 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, 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) -> 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) { + 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>, +) -> Result { + 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>, + fixity: Option, +) -> 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>, + fixity: Option, +) -> 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>, +} + +impl Preprocessor { + pub(super) + fn new(flags: MachineFlags) -> Self { + Preprocessor { + flags, + queue: VecDeque::new(), + } + } + + fn setup_fact(&mut self, term: Term) -> Result { + match term { + Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => { + Ok(term) + } + _ => { + Err(CompilationError::InadmissibleFact) + } + } + } + + fn compute_head(&self, term: &Term) -> Vec { + 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, 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) { + // 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) { + 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) { + 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 { + 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 { + 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>, + cut_context: CutContext, + ) -> Result, 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>, + cut_context: CutContext, + ) -> Result { + 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>, + cut_context: CutContext, + ) -> Result { + 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 { + 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>( + &mut self, + load_state: &mut LoadState<'a>, + terms: I, + cut_context: CutContext, + ) -> Result, 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, 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) + } +} diff --git a/src/machine/project_attributes.pl b/src/machine/project_attributes.pl index 0d7a82d0..cee4f1ce 100644 --- a/src/machine/project_attributes.pl +++ b/src/machine/project_attributes.pl @@ -1,11 +1,11 @@ :- 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), @@ -36,7 +36,7 @@ call_project_attributes([Module|Modules], QueryVars, AttrVars) :- 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). @@ -51,13 +51,13 @@ call_attribute_goals([Module | 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) ), @@ -66,25 +66,14 @@ call_query_var_goals([AttrVar|AttrVars], Module, Goals) :- 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) :- @@ -100,11 +89,25 @@ call_attribute_goals_with_module_prefix([Module | Modules], GoalCaller, AttrVars 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]). diff --git a/src/machine/stack.rs b/src/machine/stack.rs index 4bd3802b..ab7d48e2 100644 --- a/src/machine/stack.rs +++ b/src/machine/stack.rs @@ -246,10 +246,6 @@ impl Stack { } } - pub fn take(&mut self) -> Self { - Stack { buf: self.buf.take(), _marker: PhantomData } - } - #[inline] pub fn truncate(&mut self, b: usize) { if b == 0 { diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 1375cb65..644e6ee7 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -179,10 +179,10 @@ impl Drop for StreamInstance { 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(); } _ => { } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index da31e966..0623df76 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -6,14 +6,16 @@ use crate::clause_types::*; 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; @@ -402,9 +404,7 @@ impl MachineState { } } - 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) = @@ -560,7 +560,7 @@ impl MachineState { 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( @@ -681,11 +681,11 @@ impl MachineState { 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); @@ -792,6 +792,7 @@ impl MachineState { current_output_stream: &mut Stream, ) -> CallResult { match ct { + /* &SystemClauseType::AbolishClause => { let p = self.cp; let trans_type = DynamicTransactionType::Abolish; @@ -806,6 +807,7 @@ impl MachineState { self.p = CodePtr::DynamicTransaction(trans_type, p); return Ok(()); } + */ &SystemClauseType::BindFromRegister => { let reg = self.store(self.deref(self[temp_v!(2)])); let n = @@ -833,6 +835,7 @@ impl MachineState { self.fail = true; } + /* &SystemClauseType::AssertDynamicPredicateToFront => { let p = self.cp; let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front); @@ -841,19 +844,21 @@ impl MachineState { 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); @@ -1016,6 +1021,7 @@ impl MachineState { return Err(err); } }; + let chars = self.heap.put_complete_string(current); self.unify(self[temp_v!(1)], chars); @@ -1092,11 +1098,13 @@ impl MachineState { 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)]; @@ -1139,7 +1147,7 @@ impl MachineState { 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) ); @@ -1254,7 +1262,7 @@ impl MachineState { } 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); @@ -1281,7 +1289,7 @@ impl MachineState { clause_name!("[]") } Addr::Char(c) => { - clause_name!(c.to_string(), indices.atom_tbl) + clause_name!(c.to_string(), self.atom_tbl) } _ => { unreachable!() @@ -1858,6 +1866,7 @@ impl MachineState { } } } + /* &SystemClauseType::ModuleAssertDynamicPredicateToFront => { let p = self.cp; let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Front); @@ -1872,6 +1881,7 @@ impl MachineState { 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()); @@ -2854,6 +2864,7 @@ impl MachineState { self.unify(Addr::Char(c), a1); } +/* &SystemClauseType::GetModuleClause => { let module = self[temp_v!(3)]; let head = self[temp_v!(1)]; @@ -2944,20 +2955,24 @@ impl MachineState { _ => 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!() } @@ -3111,21 +3126,27 @@ impl MachineState { 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!() @@ -3160,6 +3181,7 @@ impl MachineState { } } } + /* &SystemClauseType::ExpandGoal => { self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0)); return Ok(()); @@ -3168,6 +3190,7 @@ impl MachineState { self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0)); return Ok(()); } + */ &SystemClauseType::GetNextDBRef => { let a1 = self[temp_v!(1)]; @@ -3185,7 +3208,7 @@ impl MachineState { 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); @@ -3429,7 +3452,7 @@ impl MachineState { 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() @@ -3440,16 +3463,18 @@ impl MachineState { 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) } }); @@ -3493,10 +3518,10 @@ impl MachineState { 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)? @@ -3901,65 +3926,18 @@ impl MachineState { } }; } - &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!() @@ -3967,14 +3945,14 @@ impl MachineState { }, 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!() } @@ -4116,6 +4094,7 @@ impl MachineState { &SystemClauseType::REPL(repl_code_ptr) => { return self.repl_redirect(repl_code_ptr); } + /* &SystemClauseType::ModuleRetractClause => { let p = self.cp; let trans_type = DynamicTransactionType::ModuleRetract; @@ -4130,6 +4109,7 @@ impl MachineState { 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; @@ -4326,6 +4306,7 @@ impl MachineState { self.unify(a1, a2); } +/* &SystemClauseType::GetClause => { let head = self[temp_v!(1)]; @@ -4343,14 +4324,14 @@ impl MachineState { } }, 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!() } } _ => { @@ -4372,6 +4353,7 @@ impl MachineState { } } } +*/ &SystemClauseType::GetCutPoint => { let a1 = self[temp_v!(1)]; let a2 = Addr::CutPoint(self.b0); @@ -4524,7 +4506,7 @@ impl MachineState { 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) => { @@ -4595,10 +4577,11 @@ impl MachineState { 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)])); @@ -4695,11 +4678,10 @@ impl MachineState { 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() @@ -4711,6 +4693,7 @@ impl MachineState { unreachable!() } }; + match tls { "false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) } "true" => { let connector = TlsConnector::new().unwrap(); @@ -4724,6 +4707,7 @@ impl MachineState { _ => { unreachable!() } } }; + stream.options = options; if let Some(ref alias) = &stream.options.alias { @@ -4877,7 +4861,7 @@ impl MachineState { 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); @@ -5226,8 +5210,13 @@ impl MachineState { 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) => { @@ -5257,51 +5246,84 @@ impl MachineState { } }; - 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 key = (name.clone(), arity.to_usize().unwrap()); + + 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 = MachineError::session_error( + h, + SessionError::from( + CompilationError::InvalidModuleResolution( + module_name + ) + ), + ); + + let err = self.error_form(err, stub); + + self.throw_exception(err); + return Ok(()); } - } - _ => { - 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 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); } @@ -5831,6 +5853,53 @@ impl MachineState { 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) @@ -5905,7 +5974,7 @@ impl MachineState { } 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) ); @@ -5926,7 +5995,7 @@ impl MachineState { } 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) ); @@ -5955,7 +6024,7 @@ impl MachineState { 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) ); @@ -5976,7 +6045,7 @@ impl MachineState { } 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) ); diff --git a/src/machine/term_expansion.rs b/src/machine/term_expansion.rs deleted file mode 100644 index 6ee8f8d3..00000000 --- a/src/machine/term_expansion.rs +++ /dev/null @@ -1,394 +0,0 @@ -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(terms: I, mut term: Term, sym: ClauseName) -> Term -where - I: DoubleEndedIterator, -{ - 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, - tail: Box, -) -> Result>, 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, - 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), - goal_expansion_additions: (Predicate, VecDeque), -} - -impl ExpansionAdditionResult { - pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque) { - 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) { - 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, - atom_tbl: TabledData, - 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) { - self.parser.set_atom_tbl(atom_tbl); - } - - #[inline] - pub fn eof(&mut self) -> Result { - 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 { - 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 { - 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 { - 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 { - 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, - ) -> Result, 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 { - 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()) - } - } -} diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs new file mode 100644 index 00000000..bceec683 --- /dev/null +++ b/src/machine/term_stream.rs @@ -0,0 +1,149 @@ +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; + fn eof(&mut self) -> Result; + fn listing_src(&self) -> &ListingSource; + fn evacuate<'a>(loader: Loader<'a, Self>) -> Result; +} + +#[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, + 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 { + self.parser.reset(); + self.parser.read_term(op_dir) + .map_err(CompilationError::from) + } + + #[inline] + fn eof(&mut self) -> Result { + 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) -> Result { + 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, + 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, + pub(super) preprocessor: Preprocessor, + pub(super) predicates: Vec, + 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 { + Ok(self.term_queue.pop_front().unwrap()) + } + + #[inline] + fn eof(&mut self) -> Result { + return Ok(self.term_queue.is_empty()); + } + + #[inline] + fn listing_src(&self) -> &ListingSource { + &self.listing_src + } + + #[inline] + fn evacuate(loader: Loader) -> Result { + Ok(loader.to_load_state_payload()) + } +} diff --git a/src/machine/toplevel.rs b/src/machine/toplevel.rs deleted file mode 100644 index eaa17691..00000000 --- a/src/machine/toplevel.rs +++ /dev/null @@ -1,1352 +0,0 @@ -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> -} - -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>, - ) -> Self { - CompositeIndices { - term_stream, - index_src, - static_code_dir, - } - } - - fn atom_tbl(&self) -> TabledData { - 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, - ) -> 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>, -) -> Option { - 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>) -> Option { - 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); - -pub fn to_op_decl(prec: usize, spec: &str, name: ClauseName) -> Result { - 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>, - atom_tbl: TabledData, -) -> Result { - 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 -{ - 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 -{ - 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, -) -> Result { - 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>, - atom_tbl: TabledData, -) -> Result { - 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, -) -> Option { - 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>, atom_tbl: TabledData) -> Result { - 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>) -> Result { - 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); - -fn setup_qualified_import( - mut terms: Vec>, - atom_tbl: TabledData, -) -> Result { - 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) -> Result -{ - let mut clauses: Vec = 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, 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) -> 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) { - 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, - queue: &mut VecDeque -) { - 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, - top_level_term_dirs: &mut TermDirQuantum, - key: &PredicateKey, - preds: &mut Vec, - queue: &mut VecDeque, -) { - 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>, - line_num: usize, - col_num: usize, -) -> Result { - 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>, - 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 { - 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 { - 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, 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) { - // 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) { - 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) { - 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 { - 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 { - 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>, - blocks_cuts: bool, - assume_dyn: bool, - ) -> Result<(Vec, 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 { - 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>, - blocks_cuts: bool, - assume_dyn: bool, - ) -> Result { - 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>, - blocks_cuts: bool, - ) -> Result { - 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 { - 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, ParserError> - where - I: IntoIterator - { - 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, 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)>, - pub(crate) dynamic_clause_map: DynamicClauseMap, - pub(crate) in_module: bool, - pub(crate) term_dirs: TermDirQuantum, - pub(crate) intra_module_term_dirs: IndexMap, - pub(crate) non_counted_bt_preds: IndexSet, -} - -impl<'a> TopLevelBatchWorker<'a> { - pub fn new( - stream: &'a mut ParsingStream, - atom_tbl: TabledData, - 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, - ) -> 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, 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) - } -} diff --git a/src/macros.rs b/src/macros.rs index 7de7da2f..aa043327 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -68,10 +68,18 @@ macro_rules! functor { }); ($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({ { - let arity = count_tt!($($dt) +); + use crate::machine::heap::*; - vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None), - $(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ] + 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 ),)+ ]; + + result.extend(addendum.into_iter()); + result } }); ($name:expr, $fixity:expr) => ( @@ -112,13 +120,28 @@ macro_rules! functor_term { (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) => ( @@ -312,14 +335,6 @@ macro_rules! jmp_call { }; } -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 { @@ -342,39 +357,21 @@ macro_rules! dir_entry { }; } -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) @@ -387,6 +384,7 @@ macro_rules! get_level_and_unify { }; } +/* macro_rules! unwind_protect { ($e: expr, $protected: expr) => { match $e { @@ -398,7 +396,8 @@ macro_rules! unwind_protect { } }; } - +*/ +/* macro_rules! discard_result { ($f: expr) => { match $f { @@ -406,7 +405,7 @@ macro_rules! discard_result { } }; } - +*/ macro_rules! ar_reg { ($r: expr) => { ArithmeticTerm::Reg($r) @@ -414,7 +413,7 @@ macro_rules! ar_reg { } 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] { @@ -427,7 +426,7 @@ macro_rules! atom_from { } } Addr::Char(c) => { - clause_name!(c.to_string(), $indices.atom_tbl.clone()) + clause_name!(c.to_string(), $self.atom_tbl) } _ => { unreachable!() @@ -435,3 +434,15 @@ macro_rules! atom_from { } } } + +macro_rules! try_or_fail { + ($s:expr, $e:expr) => {{ + match $e { + Ok(val) => val, + Err(msg) => { + $s.throw_exception(msg); + return; + } + } + }}; +} diff --git a/src/main.rs b/src/main.rs index 89168bf9..2495257e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ use crate::nix::sys::signal; mod macros; mod allocator; mod arithmetic; +mod machine; mod codegen; mod clause_types; mod debray_allocator; @@ -45,7 +46,6 @@ mod heap_print; mod indexing; mod instructions; mod iterators; -mod machine; mod read; mod targets; mod write; diff --git a/src/read.rs b/src/read.rs index 5e972a08..f240ab28 100644 --- a/src/read.rs +++ b/src/read.rs @@ -195,7 +195,7 @@ impl MachineState { 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 diff --git a/src/term_and_goal_expansion.pl b/src/term_and_goal_expansion.pl new file mode 100644 index 00000000..c02bbc94 --- /dev/null +++ b/src/term_and_goal_expansion.pl @@ -0,0 +1,44 @@ +% 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 + ). diff --git a/src/toplevel.pl b/src/toplevel.pl index bbada3a2..9513b671 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -1,10 +1,18 @@ -:- 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]) :- @@ -109,9 +117,6 @@ read_and_match :- 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)) @@ -119,38 +124,43 @@ instruction_match(Term, VarList) :- !, ( 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), @@ -254,12 +264,12 @@ write_eqs_and_read_input(B, VarList) :- ( 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) ). @@ -353,133 +363,3 @@ print_exception_with_check(E) :- % 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 - ). diff --git a/src/write.rs b/src/write.rs index cf40509d..b0dd010a 100644 --- a/src/write.rs +++ b/src/write.rs @@ -1,5 +1,6 @@ use crate::clause_types::*; use crate::forms::*; +use crate::indexing::IndexingCodePtr; use crate::instructions::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; @@ -10,14 +11,8 @@ impl fmt::Display for LocalCodePtr { 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), } } } @@ -25,16 +20,50 @@ impl fmt::Display for LocalCodePtr { 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"), } } } @@ -45,9 +74,6 @@ impl fmt::Display for IndexPtr { &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"), } } } @@ -68,17 +94,27 @@ impl fmt::Display for FactInstruction { &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) + } } } } @@ -141,12 +177,16 @@ impl fmt::Display for CompareTermQT { 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::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => { - let idx = idx.0.borrow(); - write!(f, "{}:{}/{}", idx.1, name, idx.0) + &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.get(); + write!(f, "{}/{}", name, idx) + } + ref ct => { + write!(f, "{}", ct.name()) } - ref ct => write!(f, "{}", ct.name()), } } } @@ -158,6 +198,7 @@ impl fmt::Display for HeapCellValue { &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, @@ -209,6 +250,7 @@ impl fmt::Display for Addr { &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), @@ -244,6 +286,9 @@ impl fmt::Display for ControlInstruction { &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"), } } @@ -262,13 +307,33 @@ impl fmt::Display for IndexedChoiceInstruction { 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) + } } } } @@ -279,11 +344,11 @@ impl fmt::Display for IndexingInstruction { &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()) } } } @@ -295,36 +360,40 @@ impl fmt::Display for SessionError { &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) + } } } } @@ -364,6 +433,23 @@ impl fmt::Display for ModuleSource { } } +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 { @@ -372,7 +458,13 @@ impl fmt::Display for Line { &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), } From c5e5eb8b86feeafae72aa538eeabec7203679604 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 30 Jan 2021 21:28:45 -0700 Subject: [PATCH 002/137] explain motive for Rebis development branch in README.md --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index 8151a333..985ae4a0 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,36 @@ programming, which is itself written in a high-level language. ![Scryer Logo: Cryer](logo/scryer.png) +## Rebis Development Branch + +This is the Rebis development branch, which is planned to converge on +version 0.9.0 of Scryer Prolog. As Rebis progresses to completion, it +will absorb contributions made to complementary parts of the master +branch. As such, it is now the bleeding edge version of Scryer. + +The major contribution of Rebis is the transition to a predicate-based +module system from the atom-based module system of the master +branch. Much of the compilation procedure has been ported from Rust to +Prolog, and is laid out in the files `loader.[rs|pl]`. + +A minimalized bootstrapping procedure written entirely in Rust is used +to load `loader.pl` and several preliminary libraries into Scryer, +which is called from `toplevel.pl` to compile and load new modules. + +Some established features of Scryer have been temporarily disrupted by +Rebis' sweeping changes: + +* Logical update semantics must be re-implemented, although +`asserta/1`, `assertz/1`, `retract/1`, and `clause/2` otherwise +work as expected using the new incremental clause compilation of +`compile.rs`. + +* Metacalls in several libraries must be modified to use the new +predicate-based module system. + +* `multifile` declarations are no longer supported by the Rust loader. +The current plan is to re-implement them mostly in Prolog. + ## Phase 1 Produce an implementation of the Warren Abstract Machine in Rust, done From a239007db06fbc25adbdc4ec7595397223e02144 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 30 Jan 2021 22:03:07 -0700 Subject: [PATCH 003/137] target prolog_parser_rebis on crates.io --- Cargo.lock | 6 ++++-- Cargo.toml | 6 +++--- src/allocator.rs | 2 +- src/arithmetic.rs | 2 +- src/clause_types.rs | 2 +- src/codegen.rs | 4 ++-- src/debray_allocator.rs | 2 +- src/fixtures.rs | 2 +- src/forms.rs | 4 ++-- src/heap_print.rs | 2 +- src/indexing.rs | 4 ++-- src/instructions.rs | 2 +- src/iterators.rs | 2 +- src/machine/arithmetic_ops.rs | 2 +- src/machine/heap.rs | 2 +- src/machine/loader.rs | 2 +- src/machine/machine_errors.rs | 2 +- src/machine/machine_indices.rs | 2 +- src/machine/machine_state.rs | 4 ++-- src/machine/machine_state_impl.rs | 4 ++-- src/machine/mod.rs | 4 ++-- src/machine/preprocessor.rs | 4 ++-- src/machine/streams.rs | 2 +- src/machine/system_calls.rs | 6 +++--- src/machine/term_stream.rs | 4 ++-- src/main.rs | 2 +- src/read.rs | 6 +++--- src/targets.rs | 2 +- 28 files changed, 45 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9f316ba..c54283f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -878,8 +878,10 @@ dependencies = [ ] [[package]] -name = "prolog_parser" +name = "prolog_parser_rebis" version = "0.8.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52213fbb212208bf9e80c6d34bbfeb9ebef4dca28462f034e195e073e79c334" dependencies = [ "lexical", "num-rug-adapter", @@ -1221,7 +1223,7 @@ dependencies = [ "num-rug-adapter", "openssl", "ordered-float", - "prolog_parser", + "prolog_parser_rebis", "ref_thread_local", "ring", "ripemd160", diff --git a/Cargo.toml b/Cargo.toml index cf1d85e3..93caf8ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,8 @@ build = "build.rs" indexmap = "1.0.2" [features] -default = ["rug", "prolog_parser/rug"] -num = ["num-rug-adapter", "prolog_parser/num"] +default = ["rug", "prolog_parser_rebis/rug"] +num = ["num-rug-adapter", "prolog_parser_rebis/num"] [dependencies] cpu-time = "1.0.0" @@ -32,7 +32,7 @@ libc = "0.2.62" nix = "0.15.0" num-rug-adapter = { optional = true, version = "0.1.4" } ordered-float = "0.5.0" -prolog_parser = { version = "0.8.63", path = "../prolog_parser", default-features = false } +prolog_parser_rebis = { version = "0.8.68", default-features = false } ref_thread_local = "0.0.0" rug = { version = "1.4.0", optional = true } rustyline = "7.0.0" diff --git a/src/allocator.rs b/src/allocator.rs index 9034efc5..f2b2cd0c 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::fixtures::*; use crate::forms::*; diff --git a/src/arithmetic.rs b/src/arithmetic.rs index c4cefafe..1231dfa6 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::fixtures::*; diff --git a/src/clause_types.rs b/src/clause_types.rs index a0318d8d..91f6447e 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::forms::Number; use crate::machine::machine_indices::*; diff --git a/src/codegen.rs b/src/codegen.rs index 1f349246..f2a1c5ab 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ /// Code generation to WAM-like instructions. -use crate::prolog_parser::ast::*; -use crate::prolog_parser::tabled_rc::TabledData; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::tabled_rc::TabledData; use crate::allocator::*; use crate::arithmetic::*; diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 9e129828..3c69bda2 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -1,6 +1,6 @@ use crate::indexmap::IndexMap; -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::allocator::*; use crate::fixtures::*; diff --git a/src/fixtures.rs b/src/fixtures.rs index 907c9227..d9034562 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::forms::*; use crate::instructions::*; diff --git a/src/forms.rs b/src/forms.rs index 006371eb..2a4f5d7d 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::parser::OpDesc; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::parser::OpDesc; use crate::clause_types::*; use crate::machine::machine_errors::*; diff --git a/src/heap_print.rs b/src/heap_print.rs index e4792969..29530fa5 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/indexing.rs b/src/indexing.rs index f2029a31..8a231514 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::tabled_rc::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::tabled_rc::*; use crate::forms::*; use crate::instructions::*; diff --git a/src/instructions.rs b/src/instructions.rs index a913f49e..d27d120a 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/iterators.rs b/src/iterators.rs index 9c549166..a3b5956b 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 110353ac..0c8fb8ff 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1,6 +1,6 @@ use crate::divrem::*; -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::arithmetic::*; use crate::clause_types::*; diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 612742c9..0d3a5cf6 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use crate::prolog_parser::ast::Constant; +use crate::prolog_parser_rebis::ast::Constant; use crate::machine::machine_indices::*; use crate::machine::partial_string::*; diff --git a/src/machine/loader.rs b/src/machine/loader.rs index a6704894..ce6e4fc0 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1,4 +1,4 @@ -use prolog_parser::ast::*; +use prolog_parser_rebis::ast::*; use crate::forms::*; use crate::indexing::*; diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index dcea8448..ffb95aef 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; use crate::machine::heap::*; diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 14489b76..21effa5d 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::fixtures::*; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index ab04a532..a49465ec 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::tabled_rc::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::tabled_rc::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index a387970e..277caa08 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::tabled_rc::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::tabled_rc::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/mod.rs b/src/machine/mod.rs index f8d661a2..9fc72720 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::tabled_rc::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::tabled_rc::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 7054796a..1f5de851 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::tabled_rc::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::tabled_rc::*; use crate::forms::*; use crate::iterators::*; diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 644e6ee7..21040c60 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::read::PrologStream; use crate::read::readline::*; diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 0623df76..2ed49409 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1,6 +1,6 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::parser::*; -use crate::prolog_parser::tabled_rc::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::parser::*; +use crate::prolog_parser_rebis::tabled_rc::*; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index bceec683..e408a6f1 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::parser::*; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::parser::*; use crate::machine::*; use crate::machine::machine_errors::CompilationError; diff --git a/src/main.rs b/src/main.rs index 2495257e..07684b61 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ extern crate nix; extern crate openssl; extern crate ordered_float; #[macro_use] -extern crate prolog_parser; +extern crate prolog_parser_rebis; #[macro_use] extern crate ref_thread_local; extern crate ring; diff --git a/src/read.rs b/src/read.rs index f240ab28..ba975201 100644 --- a/src/read.rs +++ b/src/read.rs @@ -1,6 +1,6 @@ -use crate::prolog_parser::ast::*; -use crate::prolog_parser::parser::*; -use crate::prolog_parser::tabled_rc::TabledData; +use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::parser::*; +use crate::prolog_parser_rebis::tabled_rc::TabledData; use crate::forms::*; use crate::iterators::*; diff --git a/src/targets.rs b/src/targets.rs index 643ea1d5..a75d3f79 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser::ast::*; +use crate::prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::forms::*; From c2e3b47d29871aca7338760f09a290c99cd78f24 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 30 Jan 2021 23:37:23 -0700 Subject: [PATCH 004/137] properly thread functors whose first subterm is a variable in thread_goals/4 --- src/loader.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loader.pl b/src/loader.pl index 9360e260..f8f766f7 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -421,7 +421,7 @@ thread_goals(Goals0, Goals1, Functor) :- thread_goals(Goals0, Goals1, Hole, Functor) :- ( var(Goals0) -> - Goals0 = Goals1 + Goals1 =.. [Functor, Goals0, Hole] ; ( Goals0 = [G | Gs] -> ( Gs == [] -> Goals1 =.. [Functor, G, Hole] From 61b14d1cd9aca494e180b57179919cea523cd637 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 31 Jan 2021 01:18:45 -0700 Subject: [PATCH 005/137] fix bug in append_compiled_clause, generalize merging indexed subsequences of clauses --- src/machine/compile.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 7b3fb49f..5311544b 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1002,7 +1002,25 @@ fn append_compiled_clause( ); if lower_bound + 1 == target_pos { - set_switch_var_offset(code, index_loc, 1, retraction_info); + let lower_bound_clause_start = find_inner_choice_instr( + code, + skeleton.clauses[lower_bound].clause_start, + index_loc, + ); + + set_switch_var_offset( + code, + index_loc, + lower_bound_clause_start - index_loc, + retraction_info, + ); + + thread_choice_instr_at_to( + code, + lower_bound_clause_start, + skeleton.clauses[target_pos].clause_start, + retraction_info, + ); } skeleton.clauses[target_pos - 1].clause_start @@ -1389,6 +1407,12 @@ impl<'a> LoadState<'a> { Some(target_indexing_loc) if mergeable_indexed_subsequences(lower_bound, target_pos, skeleton) => { + let lower_bound_clause_start = find_inner_choice_instr( + code, + skeleton.clauses[lower_bound].clause_start, + target_indexing_loc, + ); + let result; match skeleton.clauses[target_pos + 1].opt_arg_index_key.switch_on_term_loc() { @@ -1416,7 +1440,7 @@ impl<'a> LoadState<'a> { set_switch_var_offset( code, later_indexing_loc, - target_indexing_loc - later_indexing_loc + 1, + lower_bound_clause_start - later_indexing_loc, // target_indexing_loc - later_indexing_loc + 1, &mut self.retraction_info, ); @@ -1440,7 +1464,7 @@ impl<'a> LoadState<'a> { set_switch_var_offset_to_choice_instr_( code, target_indexing_loc, - 1, + lower_bound_clause_start - target_indexing_loc, //1, &mut self.retraction_info, ); From 75908ab88fb5a28a1a33cde11aed2cebb2f96f68 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 31 Jan 2021 18:00:10 -0700 Subject: [PATCH 006/137] replace (:) with 0 in meta-predicate declarations, remove support for (:) in meta-predicate declarations --- src/forms.rs | 1 - src/lib/builtins.pl | 38 ++++----- src/lib/iso_ext.pl | 6 +- src/lib/lists.pl | 2 +- src/lib/ops_and_meta_predicates.pl | 130 ++++++++++++++--------------- src/lib/pairs.pl | 2 +- src/lib/time.pl | 2 +- src/machine/loader.rs | 5 -- src/machine/preprocessor.rs | 1 - 9 files changed, 90 insertions(+), 97 deletions(-) diff --git a/src/forms.rs b/src/forms.rs index 35a4a477..c039e603 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -303,7 +303,6 @@ pub enum MetaSpec { Minus, Plus, Either, - RequiresExpansion, RequiresExpansionWithArgument(usize), } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index d17faf8c..3aba986b 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -152,7 +152,7 @@ set_prolog_flag(Flag, _) :- fail :- '$fail'. -:- meta_predicate \+(:). +:- meta_predicate \+(0). \+ G :- call(G), !, false. \+ _. @@ -162,7 +162,7 @@ X \= X :- !, false. _ \= _. -:- meta_predicate once(:). +:- meta_predicate once(0). once(G) :- call(G), !. @@ -172,17 +172,17 @@ repeat :- repeat. -:- meta_predicate ','(:, :). +:- meta_predicate ','(0, 0). -:- meta_predicate ','(:, +, +). +:- meta_predicate ','(0, +, +). -:- meta_predicate ;(:, :). +:- meta_predicate ;(0, 0). -:- meta_predicate ;(:, :, +). +:- meta_predicate ;(0, 0, +). -:- meta_predicate ->(:, :). +:- meta_predicate ->(0, 0). -:- meta_predicate ->(:, :, +). +:- meta_predicate ->(0, 0, +). ','(G1, G2) :- @@ -363,7 +363,7 @@ get_args([Arg|Args], Func, I0, N) :- '$call_with_default_policy'(get_args(Args, Func, I1, N)). -:- meta_predicate parse_options_list(?, :, ?, ?, ?). +:- meta_predicate parse_options_list(?, 0, ?, ?, ?). parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :- '$skip_max_list'(_, -1, Options, Tail), @@ -521,14 +521,14 @@ term_variables(Term, Vars) :- % exceptions. -:- meta_predicate catch(:, ?, :). +:- meta_predicate catch(0, ?, 0). catch(G,C,R) :- '$get_current_block'(Bb), '$call_with_default_policy'(catch(G,C,R,Bb)). -:- meta_predicate catch(:, ?, :, +). +:- meta_predicate catch(0, ?, 0, +). :- non_counted_backtracking catch/4. catch(G,C,R,Bb) :- @@ -549,7 +549,7 @@ end_block(Bb, NBb) :- '$reset_block'(NBb), '$fail'. -:- meta_predicate handle_ball(?, ?, :). +:- meta_predicate handle_ball(?, ?, 0). :- non_counted_backtracking handle_ball/3. handle_ball(C, C, R) :- @@ -562,7 +562,7 @@ handle_ball(_, _, _) :- throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'. -% :- meta_predicate '$iterate_find_all'(?, :, ?, ?). +% :- meta_predicate '$iterate_find_all'(?, 0, ?, ?). :- non_counted_backtracking '$iterate_find_all'/4. '$iterate_find_all'(Template, Goal, _, LhOffset) :- @@ -577,7 +577,7 @@ throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'. truncate_lh_to(LhLength) :- '$truncate_lh_to'(LhLength). -:- meta_predicate findall(?, :, ?). +:- meta_predicate findall(?, 0, ?). findall(Template, Goal, Solutions) :- error:can_be(list, Solutions), @@ -589,7 +589,7 @@ findall(Template, Goal, Solutions) :- ). -% :- meta_predicate '$iterate_find_all_diff'(?, :, ?, ?, ?). +% :- meta_predicate '$iterate_find_all_diff'(?, 0, ?, ?, ?). :- non_counted_backtracking '$iterate_find_all_diff'/5. '$iterate_find_all_diff'(Template, Goal, _, _, LhOffset) :- @@ -601,7 +601,7 @@ findall(Template, Goal, Solutions) :- '$get_lh_from_offset_diff'(LhOffset, Solutions0, Solutions1). -% :- meta_predicate findall(?, :, ?, ?). +% :- meta_predicate findall(?, 0, ?, ?). findall(Template, Goal, Solutions0, Solutions1) :- error:can_be(list, Solutions0), @@ -649,7 +649,7 @@ rightmost_power(Term, FinalTerm, Xs) :- ). -% :- meta_predicate findall_with_existential(?, :, ?, ?, ?). +% :- meta_predicate findall_with_existential(?, 0, ?, ?, ?). findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) :- ( nonvar(Goal), @@ -665,7 +665,7 @@ findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) ). -:- meta_predicate bagof(?, :, ?). +:- meta_predicate bagof(?, 0, ?). bagof(Template, Goal, Solution) :- error:can_be(list, Solution), @@ -688,7 +688,7 @@ iterate_variants_and_sort([_|GroupSolutions], Ws, Solution) :- iterate_variants_and_sort(GroupSolutions, Ws, Solution). -:- meta_predicate setof(?, :, ?). +:- meta_predicate setof(?, 0, ?). setof(Template, Goal, Solution) :- error:can_be(list, Solution), diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index dc83c2a4..b9b3c893 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -46,14 +46,14 @@ 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(:, :). +:- meta_predicate call_cleanup(0, 0). call_cleanup(G, C) :- setup_call_cleanup(true, G, C). % setup_call_cleanup. -:- meta_predicate setup_call_cleanup(:, :, :). +:- meta_predicate setup_call_cleanup(0, 0, 0). setup_call_cleanup(S, G, C) :- '$get_b_value'(B), @@ -122,7 +122,7 @@ handle_ile(B, E, _) :- '$remove_call_policy_check'(B), '$call_with_default_policy'(throw(E)). -:- meta_predicate call_with_inference_limit(:, ?, ?). +:- meta_predicate call_with_inference_limit(0, ?, ?). call_with_inference_limit(G, L, R) :- '$get_current_block'(Bb), diff --git a/src/lib/lists.pl b/src/lib/lists.pl index 75095715..c6160e55 100644 --- a/src/lib/lists.pl +++ b/src/lib/lists.pl @@ -128,7 +128,7 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7 sum_list(Ls, S) :- foldl(sum_, Ls, 0, S). -sum_(L, S0, S) :- is(S, +(S0, L)). +sum_(L, S0, S) :- S is S0 + L. diff --git a/src/lib/ops_and_meta_predicates.pl b/src/lib/ops_and_meta_predicates.pl index c16af3ad..2d78c615 100644 --- a/src/lib/ops_and_meta_predicates.pl +++ b/src/lib/ops_and_meta_predicates.pl @@ -60,68 +60,68 @@ :- 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(:, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(0). +:- meta_predicate call(1, ?). +:- meta_predicate call(2, ?, ?). +:- meta_predicate call(3, ?, ?, ?). +:- meta_predicate call(4, ?, ?, ?, ?). +:- meta_predicate call(5, ?, ?, ?, ?, ?). +:- meta_predicate call(6, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(7, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(8, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(9, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(10, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(11, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(12, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(13, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(14, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(15, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(16, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(17, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(18, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(19, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(20, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(21, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(22, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(23, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(24, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(25, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(26, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(27, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(28, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(29, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(30, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(31, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(32, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(33, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(34, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(35, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(36, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(37, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(38, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(39, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(40, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(41, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(42, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(43, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(44, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(45, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(46, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(47, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(48, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(49, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(50, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(51, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(52, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(53, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(54, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(55, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(56, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(57, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(58, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(59, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(60, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(60, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(61, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(62, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). diff --git a/src/lib/pairs.pl b/src/lib/pairs.pl index 85914639..d8023856 100644 --- a/src/lib/pairs.pl +++ b/src/lib/pairs.pl @@ -5,7 +5,7 @@ map_list_to_pairs/3]). -:- meta_predicate map_list_to_pairs(:, ?, ?). +:- meta_predicate map_list_to_pairs(0, ?, ?). pairs_keys_values([], [], []). pairs_keys_values([A-B|ABs], [A|As], [B|Bs]) :- diff --git a/src/lib/time.pl b/src/lib/time.pl index 933387be..13df2e42 100644 --- a/src/lib/time.pl +++ b/src/lib/time.pl @@ -82,7 +82,7 @@ sleep(T) :- % '$cpu_now' can be replaced by statistics/2 once that is implemented. -:- meta_predicate time(:). +:- meta_predicate time(0). time(Goal) :- '$cpu_now'(T0), diff --git a/src/machine/loader.rs b/src/machine/loader.rs index ce6e4fc0..ef8cbbaf 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1498,8 +1498,6 @@ impl Machine { 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 { @@ -1509,9 +1507,6 @@ impl Machine { MetaSpec::RequiresExpansionWithArgument(ref arg_num) => { HeapCellValue::Addr(Addr::Usize(*arg_num)) } - MetaSpec::RequiresExpansion => { - HeapCellValue::Atom(clause_name!(":"), op_spec.clone()) - } } }), ); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 1f5de851..c063bd6f 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -347,7 +347,6 @@ fn setup_meta_predicate<'a>( Term::Constant(_, Constant::Atom(meta_spec, _)) => { let meta_spec = match meta_spec.as_str() { - ":" => MetaSpec::RequiresExpansion, "+" => MetaSpec::Plus, "-" => MetaSpec::Minus, "?" => MetaSpec::Either, From 08b18af8a06f7816b1092c589909b2c8a40d1568 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 1 Feb 2021 14:48:13 -0700 Subject: [PATCH 007/137] call attribute variable goals with module resolution --- src/indexing.rs | 1 - src/loader.pl | 1 + src/machine/attributed_variables.pl | 35 ++++++++++------------------- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/indexing.rs b/src/indexing.rs index 8a231514..9359e18c 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1019,7 +1019,6 @@ impl CodeOffsets { .or_insert(sdeq![]); let is_initial_index = code.is_empty(); - code.push_back(compute_index(is_initial_index, index)); for constant in &overlapping_constants { diff --git a/src/loader.pl b/src/loader.pl index f8f766f7..88d65770 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -56,6 +56,7 @@ load_loop(Stream, Evacuable) :- ; var(Term) -> instantiation_error(load/1) ; expand_terms_and_goals(Term, Terms), + nl, write('Terms:'), write(Terms), nl, nl, !, ( var(Terms) -> instantiation_error(load/1) diff --git a/src/machine/attributed_variables.pl b/src/machine/attributed_variables.pl index 386ff101..b5049e3a 100644 --- a/src/machine/attributed_variables.pl +++ b/src/machine/attributed_variables.pl @@ -1,5 +1,6 @@ :- module('$atts', []). + driver(Vars, Values) :- iterate(Vars, Values, ListOfListsOfGoalLists), !, @@ -13,12 +14,6 @@ iterate([Var|VarBindings], [Value|ValueBindings], [ListOfGoalLists | ListsCubed] 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]) :- @@ -30,38 +25,32 @@ call_verify_attributes([], _, _, []). 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(Modules, Var, Value, ListOfGoalLists). -verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :- + +verify_attrs([Module|Modules], Var, Value, [Module-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), call_goals(ListsCubed). call_goals([]). -call_goals_0([GoalList | GoalLists]) :- - ( var(GoalList), throw(error(instantiation_error, call_goals_0/1)) +call_goals_0([Module-GoalList | GoalLists]) :- + ( var(GoalList), + throw(error(instantiation_error, call_goals_0/1)) ; true ), - call_goals_1(GoalList), + call_goals_1(GoalList, Module), call_goals_0(GoalLists). call_goals_0([]). -call_goals_1([Goal | Goals]) :- - call(Goal), - call_goals_1(Goals). -call_goals_1([]). +call_goals_1([Goal | Goals], Module) :- + call(Module:Goal), + call_goals_1(Goals, Module). +call_goals_1([], _). From 6ed77675120ff368a9d834239ea28d8c58d7f769 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 1 Feb 2021 16:09:19 -0700 Subject: [PATCH 008/137] add module scoping to predicate_property, expand subgoals in module resolved predicates --- src/clause_types.rs | 2 +- src/loader.pl | 54 ++++++++++++++++++++++++++++--------------- src/machine/loader.rs | 18 ++++++++++----- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 91f6447e..aded0bb2 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -769,7 +769,7 @@ impl SystemClauseType { ("$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)), + ("$cpp_meta_predicate_property", 4) => Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)), ("$compile_pending_predicates", 1) => Some(SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates)), _ => None, } diff --git a/src/loader.pl b/src/loader.pl index 88d65770..2a472ebf 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -56,7 +56,6 @@ load_loop(Stream, Evacuable) :- ; var(Term) -> instantiation_error(load/1) ; expand_terms_and_goals(Term, Terms), - nl, write('Terms:'), write(Terms), nl, nl, !, ( var(Terms) -> instantiation_error(load/1) @@ -100,7 +99,7 @@ module_expanded_head_variables_([HeadArg | HeadArgs], [MetaSpec | MetaSpecs], He ; module_expanded_head_variables_(HeadArgs, MetaSpecs, HeadVars, HeadVars0) ). -module_expanded_head_variables(Head, MetaSpecs, HeadVars) :- +module_expanded_head_variables(Head, HeadVars) :- ( var(Head) -> instantiation_error(load/1) ; predicate_property(Head, meta_predicate(MetaSpecs)), @@ -110,15 +109,12 @@ module_expanded_head_variables(Head, MetaSpecs, HeadVars) :- ). -expand_terms_and_goals(Term, Terms) :- - expand_term(Term, Terms0), - ( var(Terms0) -> - instantiation_error(load/1) - ; Terms0 = (Head1 :- Body0) -> +expand_term_goals(Terms0, Terms) :- + ( Terms0 = (Head1 :- Body0) -> ( var(Head1) -> instantiation_error(load/1) ; prolog_load_context(module, Target), - module_expanded_head_variables(Head1, MetaSpecs, HeadVars), + module_expanded_head_variables(Head1, HeadVars), expand_goal(Body0, Target, Body1, HeadVars) ), Terms = (Head1 :- Body1) @@ -126,6 +122,16 @@ expand_terms_and_goals(Term, Terms) :- ). +expand_terms_and_goals(Term, Terms) :- + expand_term(Term, Terms0), + ( var(Terms0) -> + instantiation_error(load/1) + ; Terms0 = [_|_] -> + maplist(loader:expand_term_goals, Terms0, Terms) + ; expand_term_goals(Terms0, Terms) + ). + + expand_term(UnexpandedTerm, ExpandedTerm) :- user:term_expansion(UnexpandedTerm, ExpandedTerm). @@ -141,8 +147,7 @@ compile_dispatch_or_clause(Term, Evacuable, VNs) :- instantiation_error(load/1) ; compile_dispatch(Term, Evacuable, VNs) -> true - ; - compile_clause(Term, Evacuable, VNs) + ; compile_clause(Term, Evacuable, VNs) ). @@ -286,21 +291,30 @@ use_module(Module, Exports, Evacuable) :- -check_predicate_property(meta_predicate, Name, Arity, MetaPredicateTerm) :- +check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :- must_be(atom, Name), must_be(integer, Arity), - '$cpp_meta_predicate_property'(Name, Arity, MetaPredicateTerm). + '$cpp_meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm). +extract_predicate_property(Property, PropertyType) :- + ( var(Property) -> + true + ; functor(Property, PropertyType, _) + ). + predicate_property(Callable, Property) :- ( var(Callable) -> instantiation_error(load/1) + ; Callable =.. [(:), Module, Callable0], + atom(Module) -> + functor(Callable0, Name, Arity), + extract_predicate_property(Property, PropertyType), + check_predicate_property(PropertyType, Module, Name, Arity, Property) ; functor(Callable, Name, Arity), - ( var(Property) -> - true - ; functor(Property, PropertyType, _) - ), - check_predicate_property(PropertyType, Name, Arity, Property) + extract_predicate_property(Property, PropertyType), + prolog_load_context(module, Module), + check_predicate_property(PropertyType, Module, Name, Arity, Property) ). @@ -363,8 +377,10 @@ expand_meta_predicate_subgoals([], _, _, [], _). expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :- Goals =.. [GoalFunctor | SubGoals], - ( GoalFunctor == (:) -> - false + ( GoalFunctor == (:), + SubGoals = [M, SubGoal] -> + expand_module_names(SubGoal, MetaSpecs, Module, ExpandedSubGoal, HeadVars), + ExpandedGoals = M:ExpandedSubGoal ; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars), ExpandedGoals =.. [GoalFunctor | ExpandedGoalList] ). diff --git a/src/machine/loader.rs b/src/machine/loader.rs index ef8cbbaf..88b023e7 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1483,17 +1483,23 @@ impl Machine { pub(crate) fn meta_predicate_property(&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 (predicate_name, arity) = self.machine_st.read_predicate_key( - self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)], + self.machine_st[temp_v!(3)], ); let compilation_target = - if let Some(load_context) = self.load_contexts.last() { - CompilationTarget::Module(load_context.module.clone()) - } else { - CompilationTarget::User + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), }; match self.indices.get_meta_predicate_spec(predicate_name, arity, &compilation_target) { @@ -1516,7 +1522,7 @@ impl Machine { ); 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)]); + self.machine_st.unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(4)]); } None => { self.machine_st.fail = true; From e1ec4bee75fcde0c93076e8f6e1329a755de4e40 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 1 Feb 2021 16:50:05 -0700 Subject: [PATCH 009/137] move term expansion logic entirely into loader.pl --- src/loader.pl | 66 +++++++++++++++++++++++++++------- src/machine/loader.rs | 2 +- src/machine/mod.rs | 9 ----- src/term_and_goal_expansion.pl | 44 ----------------------- 4 files changed, 55 insertions(+), 66 deletions(-) delete mode 100644 src/term_and_goal_expansion.pl diff --git a/src/loader.pl b/src/loader.pl index 2a472ebf..d0b24f37 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -17,6 +17,51 @@ :- use_module(library(pairs)). +'$print_message_and_fail'(Error, Culprit) :- +% writeq(error(Error, Culprit)), +% nl, + '$fail'. + +expand_term(Term, ExpandedTerm) :- + ( catch(user:term_expansion(Term, ExpandedTerm0), + E, + loader:'$print_message_and_fail'(E, user:term_expansion)) -> + ( var(ExpandedTerm0) -> + error:instantiation_error(term_expansion/2) + ; ExpandedTerm0 = [_|_] -> + term_expansion_list(ExpandedTerm0, ExpandedTerm, []) + ; expand_term(ExpandedTerm0, ExpandedTerm) % term_expansion(ExpandedTerm0, ExpandedTerm) + ) + ; Term = ExpandedTerm + ). + + +term_expansion_list([], ExpandedTerms, ExpandedTerms). +term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- + expand_term(Term, ExpandedTerm0), % 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, + loader:'$print_message_and_fail'(E, Module:goal_expansion)) -> + ( var(ExpandedGoal0) -> + error:instantiation_error(goal_expansion/2) + ; goal_expansion(ExpandedGoal0, Module, ExpandedGoal) + ) + ; Goal = ExpandedGoal + ). + + + create_file_load_context(Stream, Path, Evacuable) :- '$push_load_context'(Stream, Path), '$push_load_state_payload'(Evacuable). @@ -132,10 +177,6 @@ expand_terms_and_goals(Term, Terms) :- ). -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), @@ -158,13 +199,13 @@ compile_dispatch((:- Declaration), Evacuable, _VNs) :- compile_declaration(Declaration, Evacuable) ). compile_dispatch(term_expansion(Term, Terms), Evacuable, VNs) :- - '$add_term_expansion_clause'('$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). + '$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). + '$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). + '$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). @@ -263,6 +304,7 @@ load_context_path(Module, Path) :- Module = Path ). + use_module(Module, Exports, Evacuable) :- ( var(Module) -> instantiation_error(load/1) @@ -334,9 +376,9 @@ strip_module(Goal, M, G) :- expand_subgoal(UnexpandedGoals, MS, Module, ExpandedGoals, HeadVars) :- ( var(UnexpandedGoals) -> UnexpandedGoals = ExpandedGoals - ; user:goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1), + ; goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1), ( Module \== user -> - user:goal_expansion(UnexpandedGoals1, user, Goals) + goal_expansion(UnexpandedGoals1, user, Goals) ; Goals = UnexpandedGoals1 ), ( inner_meta_specs(MS, Goals, _, MetaSpecs) -> @@ -393,9 +435,9 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals) :- expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- ( var(UnexpandedGoals) -> UnexpandedGoals = ExpandedGoals - ; user:goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1), + ; goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1), ( Module \== user -> - user:goal_expansion(UnexpandedGoals1, user, Goals) + goal_expansion(UnexpandedGoals1, user, Goals) ; Goals = UnexpandedGoals1 ), ( Goals = (Goal0, Goals0) -> diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 88b023e7..4560b682 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1045,7 +1045,7 @@ impl Machine { let term = loader.read_term_from_heap(temp_v!(1))?; loader.incremental_compile_clause( - (clause_name!("$term_expansion"), 2), + (clause_name!("term_expansion"), 2), term, CompilationTarget::User, false, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 9fc72720..a2486380 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -345,15 +345,6 @@ impl Machine { lib_path.pop(); // remove the "lib" at the end - bootstrapping_compile( - Stream::from(include_str!("../term_and_goal_expansion.pl")), - &mut wam, - 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, diff --git a/src/term_and_goal_expansion.pl b/src/term_and_goal_expansion.pl deleted file mode 100644 index c02bbc94..00000000 --- a/src/term_and_goal_expansion.pl +++ /dev/null @@ -1,44 +0,0 @@ -% 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 - ). From 814c0346835263fa6f6a437b19222612b151cbde Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 1 Feb 2021 19:26:50 -0700 Subject: [PATCH 010/137] add meta-predicate declarations before their definitions --- src/lib/iso_ext.pl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index b9b3c893..c7c3d6c3 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -11,6 +11,12 @@ :- use_module(library(error), [can_be/2,domain_error/3]). + +:- meta_predicate call_cleanup(0, 0). + +:- meta_predicate setup_call_cleanup(0, 0, 0). + + forall(Generate, Test) :- \+ (Generate, \+ Test). @@ -23,9 +29,9 @@ bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)). bb_b_put(Key, NewValue) :- ( '$bb_get_with_offset'(Key, OldValue, OldOffset) -> - call_cleanup((iso_ext:store_global_var_with_offset(Key, NewValue) ; false), + call_cleanup((store_global_var_with_offset(Key, NewValue) ; false), reset_global_var_at_offset(Key, OldValue, OldOffset)) - ; call_cleanup((iso_ext:store_global_var_with_offset(Key, NewValue) ; false), + ; call_cleanup((store_global_var_with_offset(Key, NewValue) ; false), reset_global_var_at_key(Key)) ). @@ -46,15 +52,11 @@ 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(0, 0). - call_cleanup(G, C) :- setup_call_cleanup(true, G, C). % setup_call_cleanup. -:- meta_predicate setup_call_cleanup(0, 0, 0). - setup_call_cleanup(S, G, C) :- '$get_b_value'(B), call(S), From 8900df6f1330f82909f6a56ba13b69efcccdd99c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 2 Feb 2021 15:03:14 -0700 Subject: [PATCH 011/137] add built_in to predicate_property --- src/clause_types.rs | 3 +++ src/lib/dcgs.pl | 7 +++++-- src/loader.pl | 16 ++++++++------- src/machine/loader.rs | 37 ++++++++++++++++++++++++++++++++++ src/machine/machine_indices.rs | 1 + src/machine/mod.rs | 3 +++ src/write.rs | 2 ++ 7 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index aded0bb2..4c39d5d6 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -398,6 +398,8 @@ impl SystemClauseType { clause_name!("$prolog_lc_stream"), &SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty) => clause_name!("$cpp_meta_predicate_property"), + &SystemClauseType::REPL(REPLCodePtr::BuiltInProperty) => + clause_name!("$cpp_built_in_property"), &SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates) => clause_name!("$compile_pending_predicates"), &SystemClauseType::Close => clause_name!("$close"), @@ -770,6 +772,7 @@ impl SystemClauseType { ("$prolog_lc_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextModule)), ("$prolog_lc_stream", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextStream)), ("$cpp_meta_predicate_property", 4) => Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)), + ("$cpp_built_in_property", 2) => Some(SystemClauseType::REPL(REPLCodePtr::BuiltInProperty)), ("$compile_pending_predicates", 1) => Some(SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates)), _ => None, } diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl index b4e2fafc..6918342e 100644 --- a/src/lib/dcgs.pl +++ b/src/lib/dcgs.pl @@ -16,11 +16,13 @@ phrase(GRBody, S0) :- phrase(GRBody, S0, S) :- - ( var(GRBody) -> throw(error(instantiation_error, phrase/3)) + ( var(GRBody) -> + throw(error(instantiation_error, phrase/3)) ; strip_module(GRBody, _, GRBody0), dcg_constr(GRBody0) -> phrase_(GRBody0, S0, S) - ; functor(GRBody, _, _) -> call(GRBody, S0, S) + ; functor(GRBody, _, _) -> + call(GRBody, S0, S) ; throw(error(type_error(callable, GRBody), phrase/3)) ). @@ -49,6 +51,7 @@ phrase_(phrase(NonTerminal), S0, S) :- phrase_([T|Ts], S0, S) :- append([T|Ts], S, S0). + % The same version of the below two dcg_rule clauses, but with module scoping. dcg_rule(( M:NonTerminal, Terminals --> GRBody ), ( M:Head :- Body )) :- dcg_non_terminal(NonTerminal, S0, S, Head), diff --git a/src/loader.pl b/src/loader.pl index d0b24f37..972fe367 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -112,7 +112,7 @@ load_loop(Stream, Evacuable) :- ). -inner_meta_specs((:), HeadArg, InnerHeadArgs, InnerMetaSpecs) :- +inner_meta_specs(0, HeadArg, InnerHeadArgs, InnerMetaSpecs) :- !, predicate_property(HeadArg, meta_predicate(InnerMetaSpecs)), HeadArg =.. [_ | InnerHeadArgs]. @@ -334,9 +334,9 @@ use_module(Module, Exports, Evacuable) :- check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :- - must_be(atom, Name), - must_be(integer, Arity), '$cpp_meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm). +check_predicate_property(built_in, _, Name, Arity, built_in) :- + '$cpp_built_in_property'(Name, Arity). extract_predicate_property(Property, PropertyType) :- @@ -355,7 +355,10 @@ predicate_property(Callable, Property) :- check_predicate_property(PropertyType, Module, Name, Arity, Property) ; functor(Callable, Name, Arity), extract_predicate_property(Property, PropertyType), - prolog_load_context(module, Module), + ( prolog_load_context(module, Module) -> + true + ; Module = user + ), check_predicate_property(PropertyType, Module, Name, Arity, Property) ). @@ -392,15 +395,14 @@ expand_subgoal(UnexpandedGoals, MS, Module, ExpandedGoals, HeadVars) :- expand_module_name(ESG0, M, ESG) :- ( var(ESG0) -> ESG = M:ESG0 - ; ESG0 = _:ESG1 -> + ; ESG0 = _:_ -> ESG = ESG0 ; ESG = M:ESG0 ). expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars) :- - ( ( MS == (:) - ; integer(MS), + ( ( integer(MS), MS >= 0 ) -> ( var(SG), diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 4560b682..286fa167 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1530,6 +1530,43 @@ impl Machine { } } + pub(crate) + fn builtin_property(&mut self) { + let key = + self.machine_st.read_predicate_key( + self.machine_st[temp_v!(1)], + self.machine_st[temp_v!(2)], + ); + + match ClauseType::from(key.0, key.1, None) { + ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN => { + return; + } + ClauseType::Named(ref name, arity, _) => { + if let Some(module) = self.indices.modules.get(&(clause_name!("builtins"))) { + self.machine_st.fail = !module.code_dir.contains_key( + &(name.clone(), arity), + ); + + return; + } + } + ClauseType::Op(ref name, ref op_desc, _) => { + if let Some(module) = self.indices.modules.get(&(clause_name!("builtins"))) { + self.machine_st.fail = !module.code_dir.contains_key( + &(name.clone(), op_desc.arity()), + ); + + return; + } + } + _ => { + } + } + + 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)); diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 21effa5d..869d4c92 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -505,6 +505,7 @@ pub enum REPLCodePtr { AddDynamicPredicate, AddGoalExpansionClause, AddTermExpansionClause, + BuiltInProperty, ClauseToEvacuable, ConcludeLoad, DeclareModule, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index a2486380..51af9c13 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -463,6 +463,9 @@ impl Machine { REPLCodePtr::MetaPredicateProperty => { self.meta_predicate_property(); } + REPLCodePtr::BuiltInProperty => { + self.builtin_property(); + } REPLCodePtr::CompilePendingPredicates => { self.compile_pending_predicates(); } diff --git a/src/write.rs b/src/write.rs index b0dd010a..bbb28e30 100644 --- a/src/write.rs +++ b/src/write.rs @@ -26,6 +26,8 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::AddGoalExpansionClause"), REPLCodePtr::AddTermExpansionClause => write!(f, "REPLCodePtr::AddTermExpansionClause"), + REPLCodePtr::BuiltInProperty => + write!(f, "REPLCodePtr::BuiltInProperty"), REPLCodePtr::UserAssertz => write!(f, "REPLCodePtr::UserAssertz"), REPLCodePtr::UserAsserta => From 4e29099ed91195a8ce848a102f6568152a33d1a9 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 2 Feb 2021 15:43:52 -0700 Subject: [PATCH 012/137] export loader's public predicates from builtins, handle module resolution from DCGs --- src/lib/dcgs.pl | 23 ++++++++++++++++++++--- src/loader.pl | 4 ++-- src/machine/loader.rs | 3 ++- src/machine/mod.rs | 25 +++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl index 6918342e..f9410d99 100644 --- a/src/lib/dcgs.pl +++ b/src/lib/dcgs.pl @@ -18,9 +18,12 @@ phrase(GRBody, S0) :- phrase(GRBody, S0, S) :- ( var(GRBody) -> throw(error(instantiation_error, phrase/3)) - ; strip_module(GRBody, _, GRBody0), - dcg_constr(GRBody0) -> - phrase_(GRBody0, S0, S) + ; strip_module(GRBody, Module, GRBody0), + dcg_constr(GRBody0), + ( var(Module) -> + phrase_(GRBody0, S0, S) + ; phrase_(Module:GRBody0, S0, S) + ) ; functor(GRBody, _, _) -> call(GRBody, S0, S) ; throw(error(type_error(callable, GRBody), phrase/3)) @@ -30,22 +33,36 @@ phrase_([], S, S). phrase_(!, S, S). phrase_((A, B), S0, S) :- phrase(A, S0, S1), phrase(B, S1, S). +phrase_(M:(A, B), S0, S) :- + phrase(M:A, S0, S1), phrase(M:B, S1, S). phrase_((A -> B ; C), S0, S) :- !, ( phrase(A, S0, S1) -> phrase(B, S1, S) ; phrase(C, S0, S) ). +phrase_(M:(A -> B ; C), S0, S) :- + !, + ( phrase(M:A, S0, S1) -> + phrase(M:B, S1, S) + ; phrase(M:C, S0, S) + ). phrase_((A ; B), S0, S) :- ( phrase(A, S0, S) ; phrase(B, S0, S) ). +phrase_(M:(A ; B), S0, S) :- + ( phrase(M:A, S0, S) ; phrase(M:B, S0, S) ). phrase_((A | B), S0, S) :- ( phrase(A, S0, S) ; phrase(B, S0, S) ). +phrase_(M:(A | B), S0, S) :- + ( phrase(M:A, S0, S) ; phrase(M:B, S0, S) ). phrase_({G}, S0, S) :- ( call(G), S0 = S ). phrase_(call(G), S0, S) :- call(G, S0, S). phrase_((A -> B), S0, S) :- phrase((A -> B ; fail), S0, S). +phrase_(M:(A -> B), S0, S) :- + phrase((M:A -> M:B ; fail), S0, S). phrase_(phrase(NonTerminal), S0, S) :- phrase(NonTerminal, S0, S). phrase_([T|Ts], S0, S) :- diff --git a/src/loader.pl b/src/loader.pl index 972fe367..448960b9 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -30,7 +30,7 @@ expand_term(Term, ExpandedTerm) :- error:instantiation_error(term_expansion/2) ; ExpandedTerm0 = [_|_] -> term_expansion_list(ExpandedTerm0, ExpandedTerm, []) - ; expand_term(ExpandedTerm0, ExpandedTerm) % term_expansion(ExpandedTerm0, ExpandedTerm) + ; expand_term(ExpandedTerm0, ExpandedTerm) ) ; Term = ExpandedTerm ). @@ -38,7 +38,7 @@ expand_term(Term, ExpandedTerm) :- term_expansion_list([], ExpandedTerms, ExpandedTerms). term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- - expand_term(Term, ExpandedTerm0), % term_expansion(Term, ExpandedTerm0), + expand_term(Term, ExpandedTerm0), ( var(ExpandedTerm0) -> error:instantiation_error(term_expansion/2) ; ExpandedTerm0 = [_|_] -> diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 286fa167..d29fe3dc 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1733,11 +1733,12 @@ fn load_module( code_dir: &mut CodeDir, op_dir: &mut OpDir, meta_predicate_dir: &mut MetaPredicateDir, + compilation_target: &CompilationTarget, module: &Module, ) { import_module_exports( &mut RetractionInfo::new(0), - &CompilationTarget::User, + &compilation_target, module, code_dir, op_dir, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 51af9c13..9a75837c 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -230,6 +230,7 @@ impl Machine { &mut self.indices.code_dir, &mut self.indices.op_dir, &mut self.indices.meta_predicates, + &CompilationTarget::User, toplevel, ); } else { @@ -337,6 +338,7 @@ impl Machine { &mut wam.indices.code_dir, &mut wam.indices.op_dir, &mut wam.indices.meta_predicates, + &CompilationTarget::User, builtins, ); } else { @@ -354,13 +356,32 @@ impl Machine { ), ).unwrap(); - if let Some(loader) = wam.indices.modules.get(&clause_name!("loader")) { + if let Some(loader) = wam.indices.modules.swap_remove(&clause_name!("loader")) { + if let Some(builtins) = wam.indices.modules.get_mut(&clause_name!("builtins")) { + // Import loader's exports into the builtins module so they will be + // implicitly included every further module. + load_module( + &mut builtins.code_dir, + &mut builtins.op_dir, + &mut builtins.meta_predicates, + &CompilationTarget::Module(clause_name!("builtins")), + &loader, + ); + + for export in &loader.module_decl.exports { + builtins.module_decl.exports.push(export.clone()); + } + } + load_module( &mut wam.indices.code_dir, &mut wam.indices.op_dir, &mut wam.indices.meta_predicates, - loader, + &CompilationTarget::User, + &loader, ); + + wam.indices.modules.insert(clause_name!("loader"), loader); } else { unreachable!() } From 4ffdd9eb153ac73a41320c7b3b68978ca6c89920 Mon Sep 17 00:00:00 2001 From: Caden Haustein Date: Tue, 2 Feb 2021 18:35:41 -0600 Subject: [PATCH 013/137] Add prolog_parser --- Cargo.lock | 2 - Cargo.toml | 4 +- crates/prolog_parser/Cargo.toml | 21 + crates/prolog_parser/src/ast.rs | 815 ++++++++++++++++++++ crates/prolog_parser/src/lexer.rs | 898 ++++++++++++++++++++++ crates/prolog_parser/src/lib.rs | 15 + crates/prolog_parser/src/macros.rs | 187 +++++ crates/prolog_parser/src/parser.rs | 998 +++++++++++++++++++++++++ crates/prolog_parser/src/put_back_n.rs | 71 ++ crates/prolog_parser/src/tabled_rc.rs | 153 ++++ 10 files changed, 3160 insertions(+), 4 deletions(-) create mode 100644 crates/prolog_parser/Cargo.toml create mode 100644 crates/prolog_parser/src/ast.rs create mode 100644 crates/prolog_parser/src/lexer.rs create mode 100644 crates/prolog_parser/src/lib.rs create mode 100644 crates/prolog_parser/src/macros.rs create mode 100644 crates/prolog_parser/src/parser.rs create mode 100644 crates/prolog_parser/src/put_back_n.rs create mode 100644 crates/prolog_parser/src/tabled_rc.rs diff --git a/Cargo.lock b/Cargo.lock index c54283f8..6c55c9ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -880,8 +880,6 @@ dependencies = [ [[package]] name = "prolog_parser_rebis" version = "0.8.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52213fbb212208bf9e80c6d34bbfeb9ebef4dca28462f034e195e073e79c334" dependencies = [ "lexical", "num-rug-adapter", diff --git a/Cargo.toml b/Cargo.toml index 93caf8ff..084990ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ libc = "0.2.62" nix = "0.15.0" num-rug-adapter = { optional = true, version = "0.1.4" } ordered-float = "0.5.0" -prolog_parser_rebis = { version = "0.8.68", default-features = false } +prolog_parser_rebis = { path = "./crates/prolog_parser", default-features = false } ref_thread_local = "0.0.0" rug = { version = "1.4.0", optional = true } rustyline = "7.0.0" @@ -48,4 +48,4 @@ select = "0.4.3" roxmltree = "0.11.0" base64 = "0.12.3" sodiumoxide = "0.2.6" -slice-deque = "0.3.0" \ No newline at end of file +slice-deque = "0.3.0" diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml new file mode 100644 index 00000000..dfdc5a32 --- /dev/null +++ b/crates/prolog_parser/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "prolog_parser_rebis" +version = "0.8.68" +authors = ["Mark Thom "] +repository = "https://github.com/mthom/prolog_parser" +description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation." +license = "BSD-3-Clause" + +[dependencies] +lexical = "2.1.0" +ordered-float = "0.5.0" +rug = { optional = true, version = "1.4.0" } +num-rug-adapter = { optional = true, version = "0.1.3" } +unicode_reader = "1.0.0" + +[lib] +path = "src/lib.rs" + +[features] +num = ["num-rug-adapter"] +default = ["rug"] diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs new file mode 100644 index 00000000..d337e9c7 --- /dev/null +++ b/crates/prolog_parser/src/ast.rs @@ -0,0 +1,815 @@ +use rug::{Integer, Rational}; +use ordered_float::*; +use tabled_rc::*; + +use put_back_n::*; + +use std::cell::Cell; +use std::cmp::Ordering; +use std::collections::HashMap; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::io::{Bytes, Error as IOError, Read}; +use std::ops::Deref; +use std::rc::Rc; +use std::vec::Vec; + +use unicode_reader::CodePoints; + +pub type Atom = String; + +pub type Var = String; + +pub type Specifier = u32; + +pub const MAX_ARITY: usize = 1023; + +pub const XFX: u32 = 0x0001; +pub const XFY: u32 = 0x0002; +pub const YFX: u32 = 0x0004; +pub const XF: u32 = 0x0010; +pub const YF: u32 = 0x0020; +pub const FX: u32 = 0x0040; +pub const FY: u32 = 0x0080; +pub const DELIMITER: u32 = 0x0100; +pub const TERM: u32 = 0x1000; +pub const LTERM: u32 = 0x3000; + +pub const NEGATIVE_SIGN: u32 = 0x0200; + +#[macro_export] +macro_rules! clause_name { + ($name: expr, $tbl: expr) => ( + ClauseName::User(TabledRc::new($name, $tbl.clone())) + ) ; + ($name: expr) => ( + ClauseName::BuiltIn($name) + ) +} + +#[macro_export] +macro_rules! atom { + ($e:expr, $tbl:expr) => ( + Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)), None) + ); + ($e:expr) => ( + Constant::Atom(clause_name!($e), None) + ) +} + +#[macro_export] +macro_rules! rc_atom { + ($e:expr) => ( + Rc::new(String::from($e)) + ) +} +macro_rules! is_term { + ($x:expr) => ( ($x & TERM) != 0 ) +} + +macro_rules! is_lterm { + ($x:expr) => ( ($x & LTERM) != 0 ) +} + +macro_rules! is_op { + ($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 ) +} + +macro_rules! is_negate { + ($x:expr) => ( ($x & NEGATIVE_SIGN) != 0 ) +} + +#[macro_export] +macro_rules! is_prefix { + ($x:expr) => ( $x & (FX | FY) != 0 ) +} + +#[macro_export] +macro_rules! is_postfix { + ($x:expr) => ( $x & (XF | YF) != 0 ) +} + +#[macro_export] +macro_rules! is_infix { + ($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 ) +} + +#[macro_export] +macro_rules! is_xfx { + ($x:expr) => ( ($x & XFX) != 0 ) +} + +#[macro_export] +macro_rules! is_xfy { + ($x:expr) => ( ($x & XFY) != 0 ) +} + +#[macro_export] +macro_rules! is_yfx { + ($x:expr) => ( ($x & YFX) != 0 ) +} + +#[macro_export] +macro_rules! is_yf { + ($x:expr) => ( ($x & YF) != 0 ) +} + +#[macro_export] +macro_rules! is_xf { + ($x:expr) => ( ($x & XF) != 0 ) +} + +#[macro_export] +macro_rules! is_fx { + ($x:expr) => ( ($x & FX) != 0 ) +} + +#[macro_export] +macro_rules! is_fy { + ($x:expr) => ( ($x & FY) != 0 ) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum RegType { + Perm(usize), + Temp(usize) +} + +impl Default for RegType { + fn default() -> Self { + RegType::Temp(0) + } +} + +impl RegType { + pub fn reg_num(self) -> usize { + match self { + RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num + } + } + + pub fn is_perm(self) -> bool { + match self { + RegType::Perm(_) => true, + _ => false + } + } +} + +impl fmt::Display for RegType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &RegType::Perm(val) => write!(f, "Y{}", val), + &RegType::Temp(val) => write!(f, "X{}", val) + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum VarReg { + ArgAndNorm(RegType, usize), + Norm(RegType) +} + +impl VarReg { + pub fn norm(self) -> RegType { + match self { + VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg + } + } +} + +impl fmt::Display for VarReg { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg), + &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg), + &VarReg::ArgAndNorm(RegType::Perm(reg), arg) => + write!(f, "Y{} A{}", reg, arg), + &VarReg::ArgAndNorm(RegType::Temp(reg), arg) => + write!(f, "X{} A{}", reg, arg) + } + } +} + +impl Default for VarReg { + fn default() -> Self { + VarReg::Norm(RegType::default()) + } +} + +#[macro_export] +macro_rules! temp_v { + ($x:expr) => ( + RegType::Temp($x) + ) +} + +#[macro_export] +macro_rules! perm_v { + ($x:expr) => ( + RegType::Perm($x) + ) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum GenContext { + Head, Mid(usize), Last(usize) // Mid & Last: chunk_num +} + +impl GenContext { + pub fn chunk_num(self) -> usize { + match self { + GenContext::Head => 0, + GenContext::Mid(cn) | GenContext::Last(cn) => cn + } + } +} + +pub type OpDirKey = (ClauseName, Fixity); + +#[derive(Debug, Clone)] +pub struct OpDirValue(pub SharedOpDesc); + +impl OpDirValue { + pub fn new(spec: Specifier, priority: usize) -> Self { + OpDirValue(SharedOpDesc::new(priority, spec)) + } + + #[inline] + pub fn shared_op_desc(&self) -> SharedOpDesc { + self.0.clone() + } +} + +// name and fixity -> operator type and precedence. +pub type OpDir = HashMap; + +#[derive(Debug, Clone, Copy)] +pub struct MachineFlags { + pub double_quotes: DoubleQuotes +} + +impl Default for MachineFlags { + fn default() -> Self { + MachineFlags { double_quotes: DoubleQuotes::default() } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum DoubleQuotes { + Atom, Chars, Codes +} + +impl DoubleQuotes { + pub fn is_chars(self) -> bool { + if let DoubleQuotes::Chars = self { + true + } else { + false + } + } + + pub fn is_atom(self) -> bool { + if let DoubleQuotes::Atom = self { + true + } else { + false + } + } + + pub fn is_codes(self) -> bool { + if let DoubleQuotes::Codes = self { + true + } else { + false + } + } +} + +impl Default for DoubleQuotes { + fn default() -> Self { + DoubleQuotes::Chars + } +} + +pub fn default_op_dir() -> OpDir { + let mut op_dir = OpDir::new(); + + op_dir.insert((clause_name!(":-"), Fixity::In), OpDirValue::new(XFX, 1200)); + op_dir.insert((clause_name!(":-"), Fixity::Pre), OpDirValue::new(FX, 1200)); + op_dir.insert((clause_name!("?-"), Fixity::Pre), OpDirValue::new(FX, 1200)); + op_dir.insert((clause_name!(","), Fixity::In), OpDirValue::new(XFY, 1000)); + + op_dir +} + +#[derive(Debug, Clone)] +pub enum ArithmeticError { + NonEvaluableFunctor(Constant, usize), + UninstantiatedVar +} + +#[derive(Debug)] +pub enum ParserError { + BackQuotedString(usize, usize), + UnexpectedChar(char, usize, usize), + UnexpectedEOF, + IO(IOError), + IncompleteReduction(usize, usize), + InvalidSingleQuotedCharacter(char), + MissingQuote(usize, usize), + NonPrologChar(usize, usize), + ParseBigInt(usize, usize), + Utf8Error(usize, usize) +} + +impl ParserError { + pub fn line_and_col_num(&self) -> Option<(usize, usize)> { + match self { + &ParserError::BackQuotedString(line_num, col_num) + | &ParserError::UnexpectedChar(_, line_num, col_num) + | &ParserError::IncompleteReduction(line_num, col_num) + | &ParserError::MissingQuote(line_num, col_num) + | &ParserError::NonPrologChar(line_num, col_num) + | &ParserError::ParseBigInt(line_num, col_num) + | &ParserError::Utf8Error(line_num, col_num) => + Some((line_num, col_num)), + _ => + None + } + } + + pub fn as_str(&self) -> &'static str { + match self { + &ParserError::BackQuotedString(..) => + "back_quoted_string", + &ParserError::UnexpectedChar(..) => + "unexpected_char", + &ParserError::UnexpectedEOF => + "unexpected_end_of_file", + &ParserError::IncompleteReduction(..) => + "incomplete_reduction", + &ParserError::InvalidSingleQuotedCharacter(..) => + "invalid_single_quoted_character", + &ParserError::IO(_) => + "input_output_error", + &ParserError::MissingQuote(..) => + "missing_quote", + &ParserError::NonPrologChar(..) => + "non_prolog_character", + &ParserError::ParseBigInt(..) => + "cannot_parse_big_int", + &ParserError::Utf8Error(..) => + "utf8_conversion_error", + } + } +} + +impl From for ParserError { + fn from(err: IOError) -> ParserError { + ParserError::IO(err) + } +} + +impl From<&IOError> for ParserError { + fn from(error: &IOError) -> ParserError { + if error.get_ref().filter(|e| e.is::()).is_some() { + ParserError::Utf8Error(0, 0) + } else { + ParserError::IO(error.kind().into()) + } + } +} + + +#[derive(Debug, Clone, Copy)] +pub struct CompositeOpDir<'a, 'b> { + pub primary_op_dir: Option<&'b OpDir>, + pub secondary_op_dir: &'a OpDir, +} + +impl<'a, 'b> CompositeOpDir<'a, 'b> +{ + #[inline] + pub fn new(secondary_op_dir: &'a OpDir, primary_op_dir: Option<&'b OpDir>) -> Self { + CompositeOpDir { primary_op_dir, secondary_op_dir } + } + + #[inline] + pub(crate) + fn get(&self, name: ClauseName, fixity: Fixity) -> Option<&OpDirValue> + { + let entry = + if let Some(ref primary_op_dir) = &self.primary_op_dir { + primary_op_dir.get(&(name.clone(), fixity)) + } else { + None + }; + + entry.or_else(move || self.secondary_op_dir.get(&(name, fixity))) + } +} + + +#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)] +pub enum Fixity { + In, Post, Pre +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct SharedOpDesc(Rc>); + +impl SharedOpDesc { + #[inline] + pub fn new(priority: usize, spec: Specifier) -> Self { + SharedOpDesc(Rc::new(Cell::new((priority, spec)))) + } + + #[inline] + pub fn ptr_eq(lop_desc: &SharedOpDesc, rop_desc: &SharedOpDesc) -> bool { + Rc::ptr_eq(&lop_desc.0, &rop_desc.0) + } + + #[inline] + pub fn arity(&self) -> usize { + if self.get().1 & (XFX | XFY | YFX) == 0 { + 1 + } else { + 2 + } + } + + #[inline] + pub fn get(&self) -> (usize, Specifier) { + self.0.get() + } + + #[inline] + pub fn set(&self, prec: usize, spec: Specifier) { + self.0.set((prec, spec)); + } + + #[inline] + pub fn prec(&self) -> usize { + self.0.get().0 + } + + #[inline] + pub fn assoc(&self) -> Specifier { + self.0.get().1 + } +} + +impl Deref for SharedOpDesc { + type Target = Cell<(usize, Specifier)>; + + #[inline] + fn deref(&self) -> &Self::Target { + self.0.deref() + } +} + +// this ensures that SharedOpDesc (which is not consistently placed in +// every atom!) doesn't affect the value of an atom hash. If +// SharedOpDesc values are to be indexed, a BTreeMap or BTreeSet +// should be used, obviously. +impl Hash for SharedOpDesc { + fn hash(&self, state: &mut H) { + 0.hash(state) + } +} + +#[derive(Debug, Clone, Hash)] +pub enum Constant { + Atom(ClauseName, Option), + Char(char), + EmptyList, + Fixnum(isize), + Integer(Rc), + Rational(Rc), + Float(OrderedFloat), + String(Rc), + Usize(usize), +} + +impl fmt::Display for Constant { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &Constant::Atom(ref atom, _) => + if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) { + write!(f, "'{}'", atom.as_str()) + } else { + write!(f, "{}", atom.as_str()) + }, + &Constant::Char(c) => + write!(f, "'{}'", c as u32), + &Constant::EmptyList => + write!(f, "[]"), + &Constant::Fixnum(n) => + write!(f, "{}", n), + &Constant::Integer(ref n) => + write!(f, "{}", n), + &Constant::Rational(ref n) => + write!(f, "{}", n), + &Constant::Float(ref n) => + write!(f, "{}", n), + &Constant::String(ref s) => + write!(f, "\"{}\"", &s), + &Constant::Usize(integer) => + write!(f, "u{}", integer), + } + } +} + +impl PartialEq for Constant { + fn eq(&self, other: &Constant) -> bool { + match (self, other) { + (&Constant::Atom(ref atom, _), &Constant::Char(c)) + | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => { + atom.is_char() && Some(c) == atom.as_str().chars().next() + }, + (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => + a1.as_str() == a2.as_str(), + (&Constant::Char(c1), &Constant::Char(c2)) => + c1 == c2, + (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => + n1 == n2, + (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) | + (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => { + if let Some(n2) = n2.to_isize() { + n1 == n2 + } else { + false + } + } + (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => + n1 == n2, + (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => + n1 == n2, + (&Constant::Float(ref n1), &Constant::Float(ref n2)) => + n1 == n2, + (&Constant::String(ref s1), &Constant::String(ref s2)) => { + &s1 == &s2 + } + (&Constant::EmptyList, &Constant::EmptyList) => + true, + (&Constant::Usize(u1), &Constant::Usize(u2)) => + u1 == u2, + _ => false + } + } +} + +impl Eq for Constant {} + +impl Constant { + pub fn to_atom(self) -> Option { + match self { + Constant::Atom(a, _) => Some(a.defrock_brackets()), + _ => None + } + } +} + +#[derive(Debug, Clone)] +pub enum ClauseName { + BuiltIn(&'static str), + User(TabledRc) +} + +impl fmt::Display for ClauseName { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl Hash for ClauseName { + fn hash(&self, state: &mut H) { + (*self.as_str()).hash(state) + } +} + +impl PartialEq for ClauseName { + fn eq(&self, other: &ClauseName) -> bool { + *self.as_str() == *other.as_str() + } +} + +impl Eq for ClauseName {} + +impl Ord for ClauseName { + fn cmp(&self, other: &ClauseName) -> Ordering { + (*self.as_str()).cmp(other.as_str()) + } +} + +impl PartialOrd for ClauseName { + fn partial_cmp(&self, other: &ClauseName) -> Option { + Some(self.cmp(other)) + } +} + +impl<'a> From<&'a TabledRc> for ClauseName { + fn from(name: &'a TabledRc) -> ClauseName { + ClauseName::User(name.clone()) + } +} + +impl ClauseName { + #[inline] + pub fn owning_module(&self) -> Self { + match self { + &ClauseName::User(ref name) => { + let module = name.owning_module(); + ClauseName::User(TabledRc { atom: module.clone(), + table: TabledData::new(module) }) + }, + _ => clause_name!("user") + } + } + + #[inline] + pub fn to_rc(&self) -> Rc { + match self { + &ClauseName::BuiltIn(s) => Rc::new(s.to_string()), + &ClauseName::User(ref rc) => rc.inner() + } + } + + #[inline] + pub fn with_table(self, atom_tbl: TabledData) -> Self { + match self { + ClauseName::BuiltIn(_) => self, + ClauseName::User(mut name) => { + name.table = atom_tbl; + ClauseName::User(name) + } + } + } + + #[inline] + pub fn has_table(&self, atom_tbl: &TabledData) -> bool { + match self { + ClauseName::BuiltIn(_) => false, + ClauseName::User(ref name) => &name.table == atom_tbl, + } + } + + #[inline] + pub fn has_table_of(&self, other: &ClauseName) -> bool { + match self { + ClauseName::BuiltIn(_) => { + if let ClauseName::BuiltIn(_) = other { + true + } else { + false + } + } + ClauseName::User(ref name) => { + other.has_table(&name.table) + } + } + } + + #[inline] + pub fn as_str(&self) -> &str { + match self { + &ClauseName::BuiltIn(s) => s, + &ClauseName::User(ref name) => name.as_ref() + } + } + + #[inline] + pub fn is_char(&self) -> bool { + !self.as_str().is_empty() && self.as_str().chars().skip(1).next().is_none() + } + + pub fn defrock_brackets(self) -> Self { + fn defrock_brackets(s: &str) -> &str { + if s.starts_with('(') && s.ends_with(')') { + &s[1 .. s.len() - 1] + } else { + s + } + } + + match self { + ClauseName::BuiltIn(s) => + ClauseName::BuiltIn(defrock_brackets(s)), + ClauseName::User(s) => + ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table)) + } + } +} + +impl AsRef for ClauseName { + #[inline] + fn as_ref(self: &Self) -> &str { + self.as_str() + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Term { + AnonVar, + Clause(Cell, ClauseName, Vec>, Option), + Cons(Cell, Box, Box), + Constant(Cell, Constant), + Var(Cell, Rc) +} + +impl Term { + pub fn shared_op_desc(&self) -> Option { + match self { + &Term::Clause(_, _, _, ref spec) => spec.clone(), + &Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(), + _ => None + } + } + + pub fn to_constant(self) -> Option { + match self { + Term::Constant(_, c) => Some(c), + _ => None + } + } + + pub fn first_arg(&self) -> Option<&Term> { + match self { + &Term::Clause(_, _, ref terms, _) => + terms.first().map(|bt| bt.as_ref()), + _ => None + } + } + + pub fn set_name(&mut self, new_name: ClauseName) { + match self { + Term::Constant(_, Constant::Atom(ref mut atom, _)) + | Term::Clause(_, ref mut atom, ..) => { + *atom = new_name; + } + _ => {} + } + } + + pub fn name(&self) -> Option { + match self { + &Term::Constant(_, Constant::Atom(ref atom, _)) + | &Term::Clause(_, ref atom, ..) => Some(atom.clone()), + _ => None + } + } + + pub fn arity(&self) -> usize { + match self { + &Term::Clause(_, _, ref child_terms, ..) => child_terms.len(), + _ => 0 + } + } +} + +fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)> { + if let &mut Term::Clause(_, ref name, ref mut subterms, _) = term { + if name.as_str() == s && subterms.len() == 2 { + let snd = *subterms.pop().unwrap(); + let fst = *subterms.pop().unwrap(); + + return Some((fst, snd)); + } + } + + None +} + +pub fn unfold_by_str(mut term: Term, s: &str) -> Vec { + let mut terms = vec![]; + + while let Some((fst, snd)) = unfold_by_str_once(&mut term, s) { + terms.push(fst); + term = snd; + } + + terms.push(term); + terms +} + +pub type ParsingStream = PutBackN>>; + +use unicode_reader::BadUtf8Error; + +#[inline] +pub fn parsing_stream(src: R) -> Result, ParserError> { + let mut stream = put_back_n(CodePoints::from(src.bytes())); + match stream.peek() { + None => Ok(stream), // empty stream is handled gracefully by Lexer::eof + Some(Err(error)) => Err(ParserError::from(error)), + Some(Ok(c)) => { + if *c == '\u{feff}' { + // skip UTF-8 BOM + stream.next(); + } + Ok(stream) + } + } +} diff --git a/crates/prolog_parser/src/lexer.rs b/crates/prolog_parser/src/lexer.rs new file mode 100644 index 00000000..b1656a55 --- /dev/null +++ b/crates/prolog_parser/src/lexer.rs @@ -0,0 +1,898 @@ +use crate::lexical::parse_lossy; +use crate::ordered_float::*; +use crate::rug::Integer; + +use ast::*; +use tabled_rc::*; + +use std::convert::TryFrom; +use std::fmt; +use std::io::Read; +use std::rc::Rc; + +macro_rules! is_not_eof { + ($c:expr) => ( + match $c { + Ok(c) => c, + Err(ParserError::UnexpectedEOF) => return Ok(true), + Err(e) => return Err(e) + } + ) +} + +macro_rules! consume_chars_with { + ($token:expr, $e:expr) => { + loop { + match $e { + Ok(Some(c)) => $token.push(c), + Ok(None) => continue, + Err(ParserError::UnexpectedChar(..)) => break, + Err(e) => return Err(e) + } + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Token { + Constant(Constant), + Var(Rc), + Open, // '(' + OpenCT, // '(' + Close, // ')' + OpenList, // '[' + CloseList, // ']' + OpenCurly, // '{' + CloseCurly, // '}' + HeadTailSeparator, // '|' + Comma, // ',' + End +} + +pub struct Lexer<'a, R: Read> { + pub(crate) atom_tbl: TabledData, + pub(crate) reader: &'a mut ParsingStream, + pub(crate) flags: MachineFlags, + pub(crate) line_num: usize, + pub(crate) col_num: usize +} + +impl<'a, R: Read + fmt::Debug> fmt::Debug for Lexer<'a, R> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Lexer") + .field("atom_tbl", &self.atom_tbl) + .field("reader", &"&'a mut ParsingStream") // Hacky solution. + .field("line_num", &self.line_num) + .field("col_num", &self.col_num) + .finish() + } +} + +impl<'a, R: Read> Lexer<'a, R> { + pub fn new( + atom_tbl: TabledData, + flags: MachineFlags, + src: &'a mut ParsingStream, + ) -> Self { + Lexer { atom_tbl, flags, reader: src, line_num: 0, col_num: 0 } + } + + fn return_char(&mut self, c: char) { + if new_line_char!(c) { + self.line_num -= 1; + self.col_num = 0; + } + + self.reader.put_back(Ok(c)); + } + + fn skip_char(&mut self) -> Result { + if let Some(Ok(c)) = self.reader.next() { + self.col_num += 1; + + if new_line_char!(c) { + self.line_num += 1; + self.col_num = 0; + } + + Ok(c) + } else { + Err(ParserError::UnexpectedEOF) + } + } + + pub fn eof(&mut self) -> Result { + if self.reader.peek().is_none() { + return Ok(true); + } + + let mut c = is_not_eof!(self.lookahead_char()); + + while layout_char!(c) { + self.skip_char()?; + + if self.reader.peek().is_none() { + return Ok(true); + } + + c = is_not_eof!(self.lookahead_char()); + } + + Ok(false) + } + + pub fn lookahead_char(&mut self) -> Result { + match self.reader.peek() { + Some(&Ok(c)) => Ok(c), + _ => Err(ParserError::UnexpectedEOF), + } + } + + fn single_line_comment(&mut self) -> Result<(), ParserError> + { + loop { + if self.reader.peek().is_none() || new_line_char!(self.skip_char()?) { + break; + } + } + + Ok(()) + } + + fn bracketed_comment(&mut self) -> Result { + // we have already checked that the current lookahead_char is comment_1_char, just skip it + let c = self.skip_char()?; + + if comment_2_char!(self.lookahead_char()?) { + self.skip_char()?; + + // Keep reading until we find characters '*' and '/' + // Deliberately skip checks for prolog_char to allow comments to contain any characters, + // including so-called "extended characters", without having to explicitly add them to a character class. + let mut c = self.lookahead_char()?; + loop { + while !comment_2_char!(c) { + self.skip_char()?; + c = self.lookahead_char()?; + } + + self.skip_char()?; + + c = self.lookahead_char()?; + if comment_1_char!(c) { + break; + } + } + + if prolog_char!(c) { + self.skip_char()?; + Ok(true) + } else { + Err(ParserError::NonPrologChar(self.line_num, self.col_num)) + } + } else { + self.return_char(c); + Ok(false) + } + } + + fn get_back_quoted_char(&mut self) -> Result { + if back_quote_char!(self.lookahead_char()?) { + let c = self.skip_char()?; + + if !back_quote_char!(self.lookahead_char()?) { + self.return_char(c); + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } else { + self.skip_char() + } + } else if single_quote_char!(self.lookahead_char()?) { + self.skip_char() + } else { + self.get_non_quote_char() + } + } + + fn get_back_quoted_item(&mut self) -> Result, ParserError> { + if backslash_char!(self.lookahead_char()?) { + let c = self.skip_char()?; + + if new_line_char!(self.lookahead_char()?) { + self.skip_char()?; + Ok(None) + } else { + self.return_char(c); + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } + } else { + self.get_back_quoted_char().map(Some) + } + } + + fn get_back_quoted_string(&mut self) -> Result { + let c = self.lookahead_char()?; + + if back_quote_char!(c) { + self.skip_char()?; + + let mut token = String::new(); + consume_chars_with!(token, self.get_back_quoted_item()); + + if back_quote_char!(self.lookahead_char()?) { + self.skip_char()?; + Ok(token) + } else { + Err(ParserError::MissingQuote(self.line_num, self.col_num)) + } + } else { + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } + } + + fn get_single_quoted_item(&mut self) -> Result, ParserError> + { + if backslash_char!(self.lookahead_char()?) { + let c = self.skip_char()?; + + if new_line_char!(self.lookahead_char()?) { + self.skip_char()?; + return Ok(None); + } else { + self.return_char(c); + } + } + + self.get_single_quoted_char().map(Some) + } + + fn get_single_quoted_char(&mut self) -> Result { + let c = self.lookahead_char()?; + + if single_quote_char!(c) { + self.skip_char()?; + + if !single_quote_char!(self.lookahead_char()?) { + self.return_char(c); + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } else { + self.skip_char() + } + } else if double_quote_char!(c) || back_quote_char!(c) { + self.skip_char() + } else { + self.get_non_quote_char() + } + } + + fn get_double_quoted_item(&mut self) -> Result, ParserError> + { + if backslash_char!(self.lookahead_char()?) { + let c = self.skip_char()?; + + if new_line_char!(self.lookahead_char()?) { + self.skip_char()?; + return Ok(None) + } else { + self.return_char(c); + } + } + + self.get_double_quoted_char().map(Some) + } + + fn get_double_quoted_char(&mut self) -> Result { + if double_quote_char!(self.lookahead_char()?) { + let c = self.skip_char()?; + + if !double_quote_char!(self.lookahead_char()?) { + self.return_char(c); + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } else { + self.skip_char() + } + } else if single_quote_char!(self.lookahead_char()?) { + self.skip_char() + } else if back_quote_char!(self.lookahead_char()?) { + self.skip_char() + } else { + self.get_non_quote_char() + } + } + + fn get_control_escape_sequence(&mut self) -> Result + { + let escaped = match self.lookahead_char()? { + 'a' => '\u{07}', // UTF-8 alert + 'b' => '\u{08}', // UTF-8 backspace + 'v' => '\u{0b}', // UTF-8 vertical tab + 'f' => '\u{0c}', // UTF-8 form feed + 't' => '\t', + 'n' => '\n', + 'r' => '\r', + c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + }; + + self.skip_char()?; + return Ok(escaped); + } + + fn get_octal_escape_sequence(&mut self) -> Result + { + self.escape_sequence_to_char(|c| octal_digit_char!(c), 8) + } + + fn get_hexadecimal_escape_sequence(&mut self) -> Result + { + self.skip_char()?; + let c = self.lookahead_char()?; + + if hexadecimal_digit_char!(c) { + self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16) + } else { + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } + } + + fn escape_sequence_to_char( + &mut self, + accept_char: impl Fn(char) -> bool, + radix: u32, + ) -> Result { + let mut c = self.lookahead_char()?; + let mut token = String::new(); + + loop { + token.push(c); + + self.skip_char()?; + c = self.lookahead_char()?; + + if !accept_char(c) { + break; + } + } + + if backslash_char!(c) { + self.skip_char()?; + u32::from_str_radix(&token, radix) + .map_or_else( + |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)), + |n| char::try_from(n) + .map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num)) + ) + } else { + // on failure, restore the token characters and backslash. + self.reader.put_back_all(token.chars().map(Ok)); + self.reader.put_back(Ok('\\')); + + Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + } + } + + fn get_non_quote_char(&mut self) -> Result { + let c = self.lookahead_char()?; + + if graphic_char!(c) || alpha_numeric_char!(c) || solo_char!(c) || space_char!(c) { + self.skip_char() + } else { + if !backslash_char!(c) { + return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)); + } + + self.skip_char()?; + + let c = self.lookahead_char()?; + + if meta_char!(c) { + self.skip_char() + } else if octal_digit_char!(c) { + self.get_octal_escape_sequence() + } else if symbolic_hexadecimal_char!(c) { + self.get_hexadecimal_escape_sequence() + } else { + self.get_control_escape_sequence() + } + } + } + + fn char_code_list_token(&mut self) -> Result { + let mut token = String::new(); + + self.skip_char()?; + consume_chars_with!(token, self.get_double_quoted_item()); + + if double_quote_char!(self.lookahead_char()?) { + self.skip_char()?; + Ok(token) + } else { + Err(ParserError::MissingQuote(self.line_num, self.col_num)) + } + } + + fn hexadecimal_constant(&mut self) -> Result { + self.skip_char()?; + + if hexadecimal_digit_char!(self.lookahead_char()?) { + let mut token = String::new(); + + while hexadecimal_digit_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + } + + isize::from_str_radix(&token, 16) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + Integer::from_str_radix(&token, 16) + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else { + self.return_char('x'); + Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + } + } + + fn octal_constant(&mut self) -> Result { + self.skip_char()?; + + if octal_digit_char!(self.lookahead_char()?) { + let mut token = String::new(); + + while octal_digit_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + } + + isize::from_str_radix(&token, 8) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + Integer::from_str_radix(&token, 8) + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else { + self.return_char('o'); + Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + } + } + + fn binary_constant(&mut self) -> Result { + self.skip_char()?; + + if binary_digit_char!(self.lookahead_char()?) { + let mut token = String::new(); + + while binary_digit_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + } + + isize::from_str_radix(&token, 2) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + Integer::from_str_radix(&token, 2) + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else { + self.return_char('b'); + Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + } + } + + fn variable_token(&mut self) -> Result { + let mut s = String::new(); + s.push(self.skip_char()?); + + while alpha_numeric_char!(self.lookahead_char()?) { + s.push(self.skip_char()?); + } + + Ok(Token::Var(rc_atom!(s))) + } + + fn name_token(&mut self, c: char) -> Result { + let mut token = String::new(); + + if small_letter_char!(c) { + token.push(self.skip_char()?); + + while alpha_numeric_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + } + } else if graphic_token_char!(c) { + token.push(self.skip_char()?); + + while graphic_token_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + } + } else if cut_char!(c) { + token.push(self.skip_char()?); + } else if semicolon_char!(c) { + token.push(self.skip_char()?); + } else if single_quote_char!(c) { + self.skip_char()?; + + consume_chars_with!(token, self.get_single_quoted_item()); + + if single_quote_char!(self.lookahead_char()?) { + self.skip_char()?; + + if !token.is_empty() && token.chars().skip(1).next().is_none() { + if let Some(c) = token.chars().next() { + return Ok(Token::Constant(Constant::Char(c))); + } + } + } else { + return Err(ParserError::InvalidSingleQuotedCharacter(self.lookahead_char()?)) + } + } else { + match self.get_back_quoted_string() { + Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)), + Err(e) => return Err(e) + } + } + + if token.as_str() == "[]" { + Ok(Token::Constant(Constant::EmptyList)) + } else { + Ok(Token::Constant(atom!(token, self.atom_tbl))) + } + } + + fn vacate_with_float(&mut self, mut token: String) -> Token { + self.return_char(token.pop().unwrap()); + + let result = OrderedFloat(parse_lossy::(token.as_bytes())); + Token::Constant(Constant::Float(result)) + } + + pub fn number_token(&mut self) -> Result { + let mut token = String::new(); + + token.push(self.skip_char()?); + let mut c = self.lookahead_char()?; + + while decimal_digit_char!(c) { + token.push(c); + self.skip_char()?; + c = self.lookahead_char()?; + } + + if decimal_point_char!(c) { + self.skip_char()?; + + if self.reader.peek().is_none() { + self.return_char('.'); + + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else if decimal_digit_char!(self.lookahead_char()?) { + token.push('.'); + token.push(self.skip_char()?); + + let mut c = self.lookahead_char()?; + + while decimal_digit_char!(c) { + token.push(c); + self.skip_char()?; + c = self.lookahead_char()?; + } + + if exponent_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + + let c = match self.lookahead_char() { + Err(_) => return Ok(self.vacate_with_float(token)), + Ok(c) => c + }; + + if !sign_char!(c) && !decimal_digit_char!(c) { + return Ok(self.vacate_with_float(token)); + } + + if sign_char!(c) { + token.push(self.skip_char()?); + + let c = match self.lookahead_char() { + Err(_) => { + self.return_char(token.pop().unwrap()); + return Ok(self.vacate_with_float(token)); + }, + Ok(c) => c + }; + + if !decimal_digit_char!(c) { + self.return_char(token.pop().unwrap()); + return Ok(self.vacate_with_float(token)); + } + } + + if decimal_digit_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + + while decimal_digit_char!(self.lookahead_char()?) { + token.push(self.skip_char()?); + } + + let n = OrderedFloat(parse_lossy::(token.as_bytes())); + Ok(Token::Constant(Constant::Float(n))) + } else { + return Ok(self.vacate_with_float(token)); + } + } else { + let n = OrderedFloat(parse_lossy::(token.as_bytes())); + Ok(Token::Constant(Constant::Float(n))) + } + } else { + self.return_char('.'); + + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } + } else { + if token.starts_with('0') && token.len() == 1 { + if c == 'x' { + self.hexadecimal_constant() + .or_else(|e| { + if let ParserError::ParseBigInt(..) = e { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else { + Err(e) + } + }) + } else if c == 'o' { + self.octal_constant() + .or_else(|e| { + if let ParserError::ParseBigInt(..) = e { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else { + Err(e) + } + }) + } else if c == 'b' { + self.binary_constant() + .or_else(|e| { + if let ParserError::ParseBigInt(..) = e { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } else { + Err(e) + } + }) + } else if single_quote_char!(c) { + self.skip_char()?; + + if backslash_char!(self.lookahead_char()?) { + self.skip_char()?; + + if new_line_char!(self.lookahead_char()?) { + self.return_char('\\'); + self.return_char('\''); + + return Ok(Token::Constant(Constant::Fixnum(0))); + } else { + self.return_char('\\'); + } + } + + self.get_single_quoted_char() + .and_then(|c| { + Ok(Token::Constant(Constant::Fixnum(c as isize))) + }) + .or_else(|_| { + self.return_char(c); + + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + }) + } else { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } + } else { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token.parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt( + self.line_num, + self.col_num, + )) + }) + } + } + } + + pub fn scan_for_layout(&mut self) -> Result { + let mut layout_inserted = false; + let mut more_layout = true; + + loop { + let cr = self.lookahead_char(); + + match cr { + Ok(c) if layout_char!(c) || new_line_char!(c) => { + self.skip_char()?; + layout_inserted = true; + }, + Ok(c) if end_line_comment_char!(c) => { + self.single_line_comment()?; + layout_inserted = true; + }, + Ok(c) if comment_1_char!(c) => + if self.bracketed_comment()? { + layout_inserted = true; + } else { + more_layout = false; + }, + _ => more_layout = false + }; + + if !more_layout { + break; + } + } + + Ok(layout_inserted) + } + + pub fn next_token(&mut self) -> Result { + let layout_inserted = self.scan_for_layout()?; + let cr = self.lookahead_char(); + + match cr { + Ok(c) => { + if capital_letter_char!(c) || variable_indicator_char!(c) { + return self.variable_token(); + } + + if c == ',' { + self.skip_char()?; + return Ok(Token::Comma); + } + + if c == ')' { + self.skip_char()?; + return Ok(Token::Close); + } + + if c == '(' { + self.skip_char()?; + return Ok(if layout_inserted { Token::Open } + else { Token::OpenCT }); + } + + if c == '.' { + self.skip_char()?; + + match self.lookahead_char() { + Ok(c) if layout_char!(c) || c == '%' => { + if new_line_char!(c) { + self.skip_char()?; + } + + return Ok(Token::End); + }, + Err(ParserError::UnexpectedEOF) => { + return Ok(Token::End); + } + _ => { + self.return_char('.'); + } + }; + } + + if decimal_digit_char!(c) { + return self.number_token(); + } + + if c == ']' { + self.skip_char()?; + return Ok(Token::CloseList); + } + + if c == '[' { + self.skip_char()?; + return Ok(Token::OpenList); + } + + if c == '|' { + self.skip_char()?; + return Ok(Token::HeadTailSeparator); + } + + if c == '{' { + self.skip_char()?; + return Ok(Token::OpenCurly); + } + + if c == '}' { + self.skip_char()?; + return Ok(Token::CloseCurly); + } + + if c == '"' { + let s = self.char_code_list_token()?; + + if let DoubleQuotes::Atom = self.flags.double_quotes { + let s = clause_name!(s, self.atom_tbl); + return Ok(Token::Constant(Constant::Atom(s, None))); + } else { + let s = Rc::new(s); + return Ok(Token::Constant(Constant::String(s))); + } + } + + self.name_token(c) + }, + Err(e) => Err(e) + } + } +} diff --git a/crates/prolog_parser/src/lib.rs b/crates/prolog_parser/src/lib.rs new file mode 100644 index 00000000..f8ef7536 --- /dev/null +++ b/crates/prolog_parser/src/lib.rs @@ -0,0 +1,15 @@ +extern crate lexical; +extern crate ordered_float; +#[cfg(feature = "rug")] +extern crate rug; +#[cfg(feature = "num-rug-adapter")] +extern crate num_rug_adapter as rug; +extern crate unicode_reader; + +#[macro_use] pub mod tabled_rc; +#[macro_use] pub mod ast; +#[macro_use] pub mod macros; +pub mod parser; +pub mod put_back_n; + +pub mod lexer; diff --git a/crates/prolog_parser/src/macros.rs b/crates/prolog_parser/src/macros.rs new file mode 100644 index 00000000..e4520aba --- /dev/null +++ b/crates/prolog_parser/src/macros.rs @@ -0,0 +1,187 @@ +#[macro_export] +macro_rules! char_class { + ($c: expr, [$head:expr]) => ($c == $head); + ($c: expr, [$head:expr $(, $cs:expr)+]) => ($c == $head || char_class!($c, [$($cs),*])); +} + +#[macro_export] +macro_rules! symbolic_control_char { + ($c: expr) => (char_class!($c, ['a', 'b', 'f', 'n', 'r', 't', 'v', '0'])) +} + +#[macro_export] +macro_rules! space_char { + ($c: expr) => ($c == ' ') +} + +#[macro_export] +macro_rules! layout_char { + ($c: expr) => (char_class!($c, [' ', '\n', '\t', '\u{0B}', '\u{0C}'])) +} + +#[macro_export] +macro_rules! symbolic_hexadecimal_char { + ($c: expr) => ($c == 'x') +} + +#[macro_export] +macro_rules! octal_digit_char { + ($c: expr) => ($c >= '0' && $c <= '7') +} + +#[macro_export] +macro_rules! binary_digit_char { + ($c: expr) => ($c >= '0' && $c <= '1') +} + +#[macro_export] +macro_rules! hexadecimal_digit_char { + ($c: expr) => ($c >= '0' && $c <= '9' || + $c >= 'A' && $c <= 'F' || + $c >= 'a' && $c <= 'f') +} + +#[macro_export] +macro_rules! exponent_char { + ($c: expr) => ($c == 'e' || $c == 'E') +} + +#[macro_export] +macro_rules! sign_char { + ($c: expr) => ($c == '-' || $c == '+') +} + +#[macro_export] +macro_rules! new_line_char { + ($c: expr) => ($c == '\n') +} + +#[macro_export] +macro_rules! end_line_comment_char { + ($c: expr) => ($c == '%') +} + +#[macro_export] +macro_rules! comment_1_char { + ($c: expr) => ($c == '/') +} + +#[macro_export] +macro_rules! comment_2_char { + ($c: expr) => ($c == '*') +} + +#[macro_export] +macro_rules! capital_letter_char { + ($c: expr) => ($c >= 'A' && $c <= 'Z') +} + +#[macro_export] +macro_rules! small_letter_char { + ($c: expr) => ($c >= 'a' && $c <= 'z') +} + +#[macro_export] +macro_rules! variable_indicator_char { + ($c: expr) => ($c == '_') +} + +#[macro_export] +macro_rules! graphic_char { + ($c: expr) => (char_class!($c, ['#', '$', '&', '*', '+', '-', '.', '/', ':', + '<', '=', '>', '?', '@', '^', '~'])) +} + +#[macro_export] +macro_rules! graphic_token_char { + ($c: expr) => (graphic_char!($c) || backslash_char!($c)) +} + +#[macro_export] +macro_rules! alpha_char { + ($c: expr) => + (match $c { + 'a' ..= 'z' => true, + 'A' ..= 'Z' => true, + '_' => true, + '\u{00A0}' ..= '\u{00BF}' => true, + '\u{00C0}' ..= '\u{00D6}' => true, + '\u{00D8}' ..= '\u{00F6}' => true, + '\u{00F8}' ..= '\u{00FF}' => true, + '\u{0100}' ..= '\u{017F}' => true, // Latin Extended-A + '\u{0180}' ..= '\u{024F}' => true, // Latin Extended-B + '\u{0250}' ..= '\u{02AF}' => true, // IPA Extensions + '\u{02B0}' ..= '\u{02FF}' => true, // Spacing Modifier Letters + '\u{0300}' ..= '\u{036F}' => true, // Combining Diacritical Marks + '\u{0370}' ..= '\u{03FF}' => true, // Greek/Coptic + '\u{0400}' ..= '\u{04FF}' => true, // Cyrillic + '\u{0500}' ..= '\u{052F}' => true, // Cyrillic Supplement + '\u{0530}' ..= '\u{058F}' => true, // Armenian + '\u{0590}' ..= '\u{05FF}' => true, // Hebrew + '\u{0600}' ..= '\u{06FF}' => true, // Arabic + '\u{0700}' ..= '\u{074F}' => true, // Syriac + _ => false + }) +} + +#[macro_export] +macro_rules! decimal_digit_char { + ($c: expr) => ($c >= '0' && $c <= '9') +} + +#[macro_export] +macro_rules! decimal_point_char { + ($c: expr) => ($c == '.') +} + +#[macro_export] +macro_rules! alpha_numeric_char { + ($c: expr) => (alpha_char!($c) || decimal_digit_char!($c)) +} + +#[macro_export] +macro_rules! cut_char { + ($c: expr) => ($c == '!') +} + +#[macro_export] +macro_rules! semicolon_char { + ($c: expr) => ($c == ';') +} + +#[macro_export] +macro_rules! backslash_char { + ($c: expr) => ($c == '\\') +} + +#[macro_export] +macro_rules! single_quote_char { + ($c: expr) => ($c == '\'') +} + +#[macro_export] +macro_rules! double_quote_char { + ($c: expr) => ($c == '"') +} + +#[macro_export] +macro_rules! back_quote_char { + ($c: expr) => ($c == '`') +} + +#[macro_export] +macro_rules! meta_char { + ($c: expr) => ( char_class!($c, ['\\', '\'', '"', '`']) ) +} + +#[macro_export] +macro_rules! solo_char { + ($c: expr) => ( char_class!($c, ['!', '(', ')', ',', ';', '[', ']', + '{', '}', '|', '%']) ) +} + +#[macro_export] +macro_rules! prolog_char { + ($c: expr) => (graphic_char!($c) || alpha_numeric_char!($c) || solo_char!($c) || + layout_char!($c) || meta_char!($c)) +} diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs new file mode 100644 index 00000000..19fd7912 --- /dev/null +++ b/crates/prolog_parser/src/parser.rs @@ -0,0 +1,998 @@ +use ast::*; +use lexer::*; +use tabled_rc::*; + +use ordered_float::OrderedFloat; + +use rug::ops::NegAssign; + +use std::cell::Cell; +use std::io::Read; +use std::mem::swap; +use std::rc::Rc; + +#[derive(Debug, Clone, Copy, PartialEq)] +enum TokenType { + Term, + Open, + OpenCT, + OpenList, // '[' + OpenCurly, // '{' + HeadTailSeparator, // '|' + Comma, // ',' + Close, + CloseList, // ']' + CloseCurly, // '}' + End +} + +impl TokenType { + fn is_sep(self) -> bool { + match self { + TokenType::HeadTailSeparator | TokenType::OpenCT | TokenType::Open | + TokenType::Close | TokenType::OpenList | TokenType::CloseList | + TokenType::OpenCurly | TokenType::CloseCurly | TokenType::Comma + => true, + _ => false + } + } +} + +#[derive(Debug, Clone, Copy)] +struct TokenDesc { + tt: TokenType, + priority: usize, + spec: u32 +} + +pub +fn get_clause_spec(name: ClauseName, arity: usize, op_dir: &CompositeOpDir) -> Option +{ + match arity { + 1 => { + /* This is a clause with an operator principal functor. Prefix operators + are supposed over post. + */ + if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Pre) { + return Some(cell.clone()); + } + + if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::Post) { + return Some(cell.clone()); + } + }, + 2 => + if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::In) { + return Some(cell.clone()); + }, + _ => {} + }; + + None +} + +pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option +{ + let mut op_desc = OpDesc { pre: 0, inf: 0, post: 0, spec: 0 }; + + if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Pre) { + let (pri, spec) = cell.get(); + + if pri > 0 { + op_desc.pre = pri; + op_desc.spec |= spec; + } else if name.as_str() == "-" { + op_desc.spec |= NEGATIVE_SIGN; + } + } + + if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Post) { + let (pri, spec) = cell.get(); + + if pri > 0 { + op_desc.post = pri; + op_desc.spec |= spec; + } + } + + if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::In) { + let (pri, spec) = cell.get(); + + if pri > 0 { + op_desc.inf = pri; + op_desc.spec |= spec; + } + } + + if op_desc.pre + op_desc.post + op_desc.inf == 0 && !is_negate!(op_desc.spec) { + None + } else { + Some(op_desc) + } +} + +fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool +{ + d2.priority <= priority + && is_term!(d3.spec) + && is_term!(d1.spec) + && d3.priority < d2.priority + && d1.priority < d2.priority +} + +fn affirm_yfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool +{ + d2.priority <= priority + && ((is_term!(d3.spec) && d3.priority < d2.priority) + || (is_lterm!(d3.spec) && d3.priority == d2.priority)) + && is_term!(d1.spec) + && d1.priority < d2.priority +} + + +fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool +{ + d2.priority < priority + && is_term!(d3.spec) + && d3.priority < d2.priority + && is_term!(d1.spec) + && d1.priority <= d2.priority +} + +fn affirm_yf(d1: TokenDesc, d2: TokenDesc) -> bool +{ + let is_valid_lterm = is_lterm!(d2.spec) && d2.priority == d1.priority; + (is_term!(d2.spec) && d2.priority < d1.priority) || is_valid_lterm +} + +fn affirm_xf(d1: TokenDesc, d2: TokenDesc) -> bool +{ + is_term!(d2.spec) && d2.priority < d1.priority +} + +fn affirm_fy(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool +{ + d2.priority < priority && is_term!(d1.spec) && d1.priority <= d2.priority +} + +fn affirm_fx(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool +{ + d2.priority <= priority && is_term!(d1.spec) && d1.priority < d2.priority +} + +fn sep_to_atom(tt: TokenType) -> Option +{ + match tt { + TokenType::Open | TokenType::OpenCT => + Some(clause_name!("(")), + TokenType::Close => + Some(clause_name!(")")), + TokenType::OpenList => + Some(clause_name!("[")), + TokenType::CloseList => + Some(clause_name!("]")), + TokenType::OpenCurly => + Some(clause_name!("{")), + TokenType::CloseCurly => + Some(clause_name!("}")), + TokenType::HeadTailSeparator => + Some(clause_name!("|")), + TokenType::Comma => + Some(clause_name!(",")), + TokenType::End => + Some(clause_name!(".")), + _ => None + } +} + +#[derive(Debug, Clone, Copy)] +pub struct OpDesc { + pub pre: usize, + pub inf: usize, + pub post: usize, + pub spec: Specifier +} + +#[derive(Debug)] +pub struct Parser<'a, R: Read> { + lexer: Lexer<'a, R>, + tokens: Vec, + stack: Vec, + terms: Vec, +} + +fn read_tokens<'a, R: Read>(lexer: &mut Lexer<'a, R>) -> Result, ParserError> +{ + let mut tokens = vec![]; + + loop { + let token = lexer.next_token()?; + let at_end = Token::End == token; + + tokens.push(token); + + if at_end { + break; + } + } + + tokens.reverse(); + + Ok(tokens) +} + +impl<'a, R: Read> Parser<'a, R> { + pub fn new( + stream: &'a mut ParsingStream, + atom_tbl: TabledData, + flags: MachineFlags, + ) -> Self { + Parser { lexer: Lexer::new(atom_tbl, flags, stream), + tokens: vec![], + stack: Vec::new(), + terms: Vec::new() } + } + + #[inline] + pub fn line_num(&self) -> usize { + self.lexer.line_num + } + + #[inline] + pub fn col_num(&self) -> usize { + self.lexer.col_num + } + + #[inline] + pub fn get_atom_tbl(&self) -> TabledData { + self.lexer.atom_tbl.clone() + } + + #[inline] + pub fn set_atom_tbl(&mut self, atom_tbl: TabledData) { + self.lexer.atom_tbl = atom_tbl; + } + + fn get_term_name(&mut self, td: TokenDesc) -> Option<(ClauseName, Option)> { + match td.tt { + TokenType::HeadTailSeparator => { + Some((clause_name!("|"), Some(SharedOpDesc::new(td.priority, td.spec)))) + } + TokenType::Comma => { + Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY)))) + } + TokenType::Term => { + match self.terms.pop() { + Some(Term::Constant(_, Constant::Atom(atom, spec))) => + Some((atom, spec)), + Some(term) => { + self.terms.push(term); + None + }, + _ => None + } + } + _ => { + None + } + } + } + + fn push_binary_op(&mut self, td: TokenDesc, spec: Specifier) + { + if let Some(arg2) = self.terms.pop() { + if let Some((name, shared_op_desc)) = self.get_term_name(td) { + if let Some(arg1) = self.terms.pop() { + let term = Term::Clause(Cell::default(), + name, + vec![Box::new(arg1), Box::new(arg2)], + shared_op_desc); + + self.terms.push(term); + self.stack.push(TokenDesc { tt: TokenType::Term, + priority: td.priority, + spec }); + } + } + } + } + + fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: u32) + { + if let Some(mut arg1) = self.terms.pop() { + if let Some(mut name) = self.terms.pop() { + if is_postfix!(assoc) { + swap(&mut arg1, &mut name); + } + + if let Term::Constant(_, Constant::Atom(name, shared_op_desc)) = name { + let term = Term::Clause(Cell::default(), name, vec![Box::new(arg1)], + shared_op_desc); + + self.terms.push(term); + self.stack.push(TokenDesc { tt: TokenType::Term, + priority: td.priority, + spec }); + } + } + } + } + + fn promote_atom_op(&mut self, atom: ClauseName, priority: usize, assoc: u32, + op_dir_val: Option<&OpDirValue>) + { + let spec = op_dir_val.map(|op_dir_val| op_dir_val.shared_op_desc()); + + self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, spec))); + self.stack.push(TokenDesc { tt: TokenType::Term, priority, spec: assoc }); + } + + fn shift(&mut self, token: Token, priority: usize, spec: Specifier) + { + let tt = match token { + Token::Constant(Constant::String(s)) + if self.lexer.flags.double_quotes.is_codes() => { + let mut list = Term::Constant(Cell::default(), Constant::EmptyList); + + for c in s.chars().rev() { + list = Term::Cons( + Cell::default(), + Box::new(Term::Constant( + Cell::default(), + Constant::Fixnum(c as isize), + )), + Box::new(list), + ); + } + + self.terms.push(list); + TokenType::Term + } + Token::Constant(c) => { + self.terms.push(Term::Constant(Cell::default(), c)); + TokenType::Term + }, + Token::Var(v) => { + if v.trim() == "_" { + self.terms.push(Term::AnonVar); + } else { + self.terms.push(Term::Var(Cell::default(), v)); + } + + TokenType::Term + }, + Token::Comma => TokenType::Comma, + Token::Open => TokenType::Open, + Token::Close => TokenType::Close, + Token::OpenCT => TokenType::OpenCT, + Token::HeadTailSeparator => TokenType::HeadTailSeparator, + Token::OpenList => TokenType::OpenList, + Token::CloseList => TokenType::CloseList, + Token::OpenCurly => TokenType::OpenCurly, + Token::CloseCurly => TokenType::CloseCurly, + Token::End => TokenType::End, + }; + + self.stack.push(TokenDesc { tt, priority, spec }); + } + + fn reduce_op(&mut self, priority: usize) { + loop { + if let Some(desc1) = self.stack.pop() { + if let Some(desc2) = self.stack.pop() { + if let Some(desc3) = self.stack.pop() { + if is_xfx!(desc2.spec) && affirm_xfx(priority, desc2, desc3, desc1) + { + self.push_binary_op(desc2, LTERM); + continue; + } + else if is_yfx!(desc2.spec) && affirm_yfx(priority, desc2, desc3, desc1) + { + self.push_binary_op(desc2, LTERM); + continue; + } + else if is_xfy!(desc2.spec) && affirm_xfy(priority, desc2, desc3, desc1) + { + self.push_binary_op(desc2, TERM); + continue; + } else { + self.stack.push(desc3); + } + } + + if is_yf!(desc1.spec) && affirm_yf(desc1, desc2) { + self.push_unary_op(desc1, LTERM, YF); + continue; + } else if is_xf!(desc1.spec) && affirm_xf(desc1, desc2) { + self.push_unary_op(desc1, LTERM, XF); + continue; + } else if is_fy!(desc2.spec) && affirm_fy(priority, desc1, desc2) { + self.push_unary_op(desc2, TERM, FY); + continue; + } else if is_fx!(desc2.spec) && affirm_fx(priority, desc1, desc2) { + self.push_unary_op(desc2, TERM, FX); + continue; + } else { + self.stack.push(desc2); + self.stack.push(desc1); + } + } else { + self.stack.push(desc1); + } + } + + break; + } + } + + fn compute_arity_in_brackets(&self) -> Option + { + let mut arity = 0; + + for (i, desc) in self.stack.iter().rev().enumerate() { + if i % 2 == 0 { // expect a term or non-comma operator. + if let TokenType::Comma = desc.tt { + return None; + } else if is_term!(desc.spec) || is_op!(desc.spec) || is_negate!(desc.spec) { + arity += 1; + } else { + return None; + } + } else { + if desc.tt == TokenType::OpenCT { + return Some(arity); + } + + if let TokenType::Comma = desc.tt { + continue; + } else { + return None; + } + } + } + + None + } + + fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool + { + if self.stack.is_empty() { + return false; + } + + self.reduce_op(999); + + let arity = match self.compute_arity_in_brackets() { + Some(arity) => arity, + None => return false + }; + + if self.stack.len() > 2 * arity { + let idx = self.stack.len() - 2 * arity - 1; + + if is_infix!(self.stack[idx].spec) && idx > 0 { + if !is_op!(self.stack[idx - 1].spec) && !self.stack[idx - 1].tt.is_sep() { + return false; + } + } + + if arity >= 2 && is_prefix!(self.stack[idx].spec) && self.stack[idx].priority > 0 { + return false; + } + } else { + return false; + } + + let stack_len = self.stack.len() - 2 * arity - 1; + let idx = self.terms.len() - arity; + + if TokenType::Term == self.stack[stack_len].tt { + if self.atomize_term(&self.terms[idx - 1]).is_some() { + self.stack.truncate(stack_len + 1); + + let mut subterms: Vec<_> = self.terms.drain(idx ..) + .map(|t| Box::new(t)) + .collect(); + + if let Some(name) = self.terms.pop().and_then(|t| self.atomize_term(&t)) { + // reduce the '.' functor to a cons cell if it applies. + if name.as_str() == "." && subterms.len() == 2 { + let tail = subterms.pop().unwrap(); + let head = subterms.pop().unwrap(); + + self.terms.push(Term::Cons(Cell::default(), head, tail)); + } else { + let spec = get_clause_spec(name.clone(), subterms.len(), op_dir); + self.terms.push(Term::Clause(Cell::default(), name, subterms, spec)); + } + + if let Some(&mut TokenDesc { ref mut priority, ref mut spec, + ref mut tt }) = self.stack.last_mut() + { + *tt = TokenType::Term; + *priority = 0; + *spec = TERM; + } + + return true; + } + } + } + + false + } + + pub fn devour_whitespace(&mut self) -> Result<(), ParserError> { + self.lexer.scan_for_layout()?; + Ok(()) + } + + pub fn reset(&mut self) { + self.stack.clear() + } + + fn expand_comma_compacted_terms(&mut self, index: usize) -> usize + { + if let Some(term) = self.terms.pop() { + let op_desc = self.stack[index - 1]; + + if 0 < op_desc.priority && op_desc.priority < self.stack[index].priority { + /* '|' is a head-tail separator here, not + * an operator, so expand the + * terms it compacted out again. */ + match (term.name(), term.arity()) { + (Some(name), 2) if name.as_str() == "," => { + let terms = unfold_by_str(term, ","); + let arity = terms.len() - 1; + + self.terms.extend(terms.into_iter()); + return arity; + } + _ => { + } + } + } + + self.terms.push(term); + } + + 0 + } + + fn compute_arity_in_list(&self) -> Option + { + let mut arity = 0; + + for (i, desc) in self.stack.iter().rev().enumerate() { + if i % 2 == 0 { // expect a term or non-comma operator. + if let TokenType::Comma = desc.tt { + return None; + } else if is_term!(desc.spec) || is_op!(desc.spec) { + arity += 1; + } else { + return None; + } + } else { + if desc.tt == TokenType::HeadTailSeparator { + if arity == 1 { + continue; + } + + return None; + } else if desc.tt == TokenType::OpenList { + return Some(arity); + } else if desc.tt != TokenType::Comma { + return None; + } + } + } + + None + } + + fn reduce_list(&mut self) -> Result + { + if self.stack.is_empty() { + return Ok(false); + } + + if let Some(ref mut td) = self.stack.last_mut() { + if td.tt == TokenType::OpenList { + td.spec = TERM; + td.tt = TokenType::Term; + td.priority = 0; + + self.terms.push(Term::Constant(Cell::default(), Constant::EmptyList)); + return Ok(true); + } + } + + self.reduce_op(1000); + + let mut arity = match self.compute_arity_in_list() { + Some(arity) => arity, + None => return Ok(false) + }; + + // we know that self.stack.len() >= 2 by this point. + let idx = self.stack.len() - 2; + let list_len = self.stack.len() - 2 * arity; + + let end_term = if self.stack[idx].tt != TokenType::HeadTailSeparator { + Term::Constant(Cell::default(), Constant::EmptyList) + } else { + let term = + match self.terms.pop() { + Some(term) => term, + _ => return Err(ParserError::IncompleteReduction(self.lexer.line_num, + self.lexer.col_num)) + }; + + if self.stack[idx].priority > 1000 { + arity += self.expand_comma_compacted_terms(idx); + } + + arity -= 1; + + term + }; + + let idx = self.terms.len() - arity; + + let list = self.terms.drain(idx ..) + .rev() + .fold(end_term, |acc, t| Term::Cons(Cell::default(), + Box::new(t), + Box::new(acc))); + + self.stack.truncate(list_len); + + self.stack.push(TokenDesc { tt: TokenType::Term, priority: 0, spec: TERM }); + self.terms.push(list); + + Ok(true) + } + + fn reduce_curly(&mut self) -> Result { + if self.stack.is_empty() { + return Ok(false); + } + + if let Some(ref mut td) = self.stack.last_mut() { + if td.tt == TokenType::OpenCurly { + td.tt = TokenType::Term; + td.priority = 0; + td.spec = TERM; + + let term = Term::Constant(Cell::default(), + atom!("{}", self.lexer.atom_tbl)); + self.terms.push(term); + return Ok(true); + } + } + + self.reduce_op(1201); + + if self.stack.len() > 1 { + if let Some(td) = self.stack.pop() { + if let Some(ref mut oc) = self.stack.last_mut() { + if td.tt != TokenType::Term { + return Ok(false); + } + + if oc.tt == TokenType::OpenCurly { + oc.tt = TokenType::Term; + oc.priority = 0; + oc.spec = TERM; + + let term = match self.terms.pop() { + Some(term) => term, + _ => return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )) + }; + + self.terms.push(Term::Clause( + Cell::default(), + clause_name!("{}"), + vec![Box::new(term)], + None + )); + + return Ok(true); + } + } + } + } + + Ok(false) + } + + fn reduce_brackets(&mut self) -> bool { + if self.stack.is_empty() { + return false; + } + + self.reduce_op(1400); + + if self.stack.len() == 1 { + return false; + } + + let idx = self.stack.len() - 2; + + match self.stack.remove(idx) { + td => + match td.tt { + TokenType::Open | TokenType::OpenCT => { + if self.stack[idx].tt == TokenType::Comma { + return false; + } + + if let Some(atom) = sep_to_atom(self.stack[idx].tt) { + self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, None))); + } + + self.stack[idx].spec = TERM; + self.stack[idx].tt = TokenType::Term; + self.stack[idx].priority = 0; + true + }, + _ => false + } + } + } + + fn shift_op(&mut self, name: ClauseName, op_dir: &CompositeOpDir) -> Result { + if let Some(OpDesc { pre, inf, post, spec }) = get_op_desc(name.clone(), op_dir) { + if (pre > 0 && inf + post > 0) || is_negate!(spec) { + match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? { + // do this when layout hasn't been inserted, + // ie. why we don't match on Token::Open. + &Token::OpenCT => { + // can't be prefix, so either inf == 0 + // or post == 0. + self.reduce_op(inf + post); + + let fixity = if inf > 0 { Fixity::In } else { Fixity::Post }; + let op_dir_val = op_dir.get(name.clone(), fixity); + + self.promote_atom_op( + name, + inf + post, + spec & (XFX | XFY | YFX | YF | XF), + op_dir_val, + ); + }, + _ => { + self.reduce_op(inf + post); + + if let Some(TokenDesc { spec: pspec, .. }) = self.stack.last().cloned() { + // rterm.c: 412 + if is_term!(pspec) { + let fixity = if inf > 0 { Fixity::In } else { Fixity::Post }; + let op_dir_val = op_dir.get(name.clone(), fixity); + + self.promote_atom_op( + name, + inf + post, + spec & (XFX | XFY | YFX | XF | YF), + op_dir_val, + ); + } else { + let op_dir_val = op_dir.get(name.clone(), Fixity::Pre); + self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN), op_dir_val); + } + } else { + let op_dir_val = op_dir.get(name.clone(), Fixity::Pre); + self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN), op_dir_val); + } + } + } + } else { + let op_dir_val = op_dir.get( + name.clone(), + if pre + inf == 0 { + Fixity::Post + } else if post + pre == 0 { + Fixity::In + } else { + Fixity::Pre + }, + ); + + self.reduce_op(pre + inf + post); // only one non-zero priority among these. + self.promote_atom_op(name, pre + inf + post, spec, op_dir_val); + } + + Ok(true) + } else { // not an operator. + Ok(false) + } + } + + fn atomize_term(&self, term: &Term) -> Option { + match term { + &Term::Constant(_, ref c) => self.atomize_constant(c), + _ => None + } + } + + fn atomize_constant(&self, c: &Constant) -> Option { + match c { + &Constant::Atom(ref name, _) => Some(name.clone()), + &Constant::Char(c) => + Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), + &Constant::EmptyList => + Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), + _ => None + } + } + + fn negate_number( + &mut self, + n: N, + negator: Negator, + constr: ToConstant + ) + where Negator: Fn(N) -> N, + ToConstant: Fn(N) -> Constant + { + if let Some(desc) = self.stack.last().cloned() { + if let Some(term) = self.terms.last().cloned() { + match term { + Term::Constant(_, Constant::Atom(ref name, _)) + if name.as_str() == "-" && (is_prefix!(desc.spec) || is_negate!(desc.spec)) => { + self.stack.pop(); + self.terms.pop(); + + self.shift(Token::Constant(constr(negator(n))), 0, TERM); + return; + }, + _ => {} + } + } + } + + self.shift(Token::Constant(constr(n)), 0, TERM); + } + + fn shift_token(&mut self, token: Token, op_dir: &CompositeOpDir) -> Result<(), ParserError> { + fn negate_rc(mut t: Rc) -> Rc { + match Rc::get_mut(&mut t) { + Some(t) => { + t.neg_assign(); + } + None => { + } + }; + + t + } + + match token { + Token::Constant(Constant::Fixnum(n)) => + self.negate_number(n, |n| -n, Constant::Fixnum), + Token::Constant(Constant::Integer(n)) => + self.negate_number(n, negate_rc, Constant::Integer), + Token::Constant(Constant::Rational(n)) => + self.negate_number(n, negate_rc, Constant::Rational), + Token::Constant(Constant::Float(n)) => + self.negate_number( + n, + |n| OrderedFloat(-n.into_inner()), + |n| Constant::Float(n) + ), + Token::Constant(c) => + if let Some(name) = self.atomize_constant(&c) { + if !self.shift_op(name, op_dir)? { + self.shift(Token::Constant(c), 0, TERM); + } + } else { + self.shift(Token::Constant(c), 0, TERM); + }, + Token::Var(v) => self.shift(Token::Var(v), 0, TERM), + Token::Open => self.shift(Token::Open, 1300, DELIMITER), + Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER), + Token::Close => + if !self.reduce_term(op_dir) { + if !self.reduce_brackets() { + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )); + } + }, + Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER), + Token::CloseList => + if !self.reduce_list()? { + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )); + }, + Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER), + Token::CloseCurly => + if !self.reduce_curly()? { + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )); + }, + Token::HeadTailSeparator => { + /* '|' as an operator must have priority > 1000 and can only be infix. + * See: http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#Res_A78 + */ + let (priority, spec) = get_op_desc(clause_name!("|"), op_dir) + .map(|OpDesc { inf, spec, .. }| (inf, spec)) + .unwrap_or((1000, DELIMITER)); + + self.reduce_op(priority); + self.shift(Token::HeadTailSeparator, priority, spec); + }, + Token::Comma => { + self.reduce_op(1000); + self.shift(Token::Comma, 1000, XFY); + }, + Token::End => + match self.stack.last().map(|t| t.tt) { + Some(TokenType::Open) + | Some(TokenType::OpenCT) + | Some(TokenType::OpenList) + | Some(TokenType::OpenCurly) + | Some(TokenType::HeadTailSeparator) + | Some(TokenType::Comma) + => return Err(ParserError::IncompleteReduction(self.lexer.line_num, + self.lexer.col_num)), + _ => {} + } + } + + Ok(()) + } + + #[inline] + pub fn eof(&mut self) -> Result { + self.lexer.eof() + } + + pub fn read_term(&mut self, op_dir: &CompositeOpDir) -> Result + { + self.tokens = read_tokens(&mut self.lexer)?; + + while let Some(token) = self.tokens.pop() { + self.shift_token(token, op_dir)?; + } + + self.reduce_op(1400); + + if self.terms.len() > 1 || self.stack.len() > 1 { + return Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num)); + } + + match self.terms.pop() { + Some(term) => if self.terms.is_empty() { + Ok(term) + } else { + Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num)) + }, + _ => Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num)) + } + } + + pub fn read(&mut self, op_dir: &CompositeOpDir) -> Result, ParserError> + { + let mut terms = Vec::new(); + + loop { + terms.push(self.read_term(op_dir)?); + + if self.lexer.eof()? { + break; + } + } + + Ok(terms) + } +} diff --git a/crates/prolog_parser/src/put_back_n.rs b/crates/prolog_parser/src/put_back_n.rs new file mode 100644 index 00000000..8bef7f30 --- /dev/null +++ b/crates/prolog_parser/src/put_back_n.rs @@ -0,0 +1,71 @@ +use std::iter::Peekable; + +#[derive(Debug, Clone)] +pub struct PutBackN { + top: Vec, + iter: Peekable, +} + +pub fn put_back_n(iterable: I) -> PutBackN + where I: IntoIterator +{ + PutBackN { + top: Vec::new(), + iter: iterable.into_iter().peekable(), + } +} + +impl PutBackN { + #[inline] + pub(crate) + fn put_back(&mut self, item: I::Item) { + self.top.push(item); + } + + #[inline] + pub fn take_buf(&mut self) -> Vec { + std::mem::replace(&mut self.top, vec![]) + } + + #[inline] + pub(crate) + fn peek(&mut self) -> Option<&I::Item> { + if self.top.is_empty() { + /* This is a kludge for Ctrl-D not being + * handled properly if self.iter().peek() isn't called + * first. */ + match self.iter.peek() { + Some(_) => { + self.iter.next().and_then(move |item| { + self.top.push(item); + self.top.last() + }) + } + None => { + None + } + } + } else { + self.top.last() + } + } + + #[inline] + pub(crate) + fn put_back_all>(&mut self, iter: DEI) { + self.top.extend(iter.rev()); + } +} + +impl Iterator for PutBackN { + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + if self.top.is_empty() { + self.iter.next() + } else { + self.top.pop() + } + } +} diff --git a/crates/prolog_parser/src/tabled_rc.rs b/crates/prolog_parser/src/tabled_rc.rs new file mode 100644 index 00000000..271ad3bf --- /dev/null +++ b/crates/prolog_parser/src/tabled_rc.rs @@ -0,0 +1,153 @@ +use std::cell::{RefCell, RefMut}; +use std::cmp::Ordering; +use std::collections::HashSet; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::Deref; +use std::rc::{Rc}; + +pub struct TabledData { + table: Rc>>>, + pub(crate) module_name: Rc +} + +impl fmt::Debug for TabledData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TabledData") + .field("table", &self.table) + .field("module_name", &self.table) + .finish() + } +} + +impl Clone for TabledData { + fn clone(&self) -> Self { + TabledData { table: self.table.clone(), + module_name: self.module_name.clone() } + } +} + +impl PartialEq for TabledData { + fn eq(&self, other: &TabledData) -> bool + { + Rc::ptr_eq(&self.table, &other.table) && self.module_name == other.module_name + } +} + +impl TabledData { + #[inline] + pub fn new(module_name: Rc) -> Self { + TabledData { + table: Rc::new(RefCell::new(HashSet::new())), + module_name + } + } + + #[inline] + pub fn borrow_mut(&self) -> RefMut>> { + self.table.borrow_mut() + } +} + +pub struct TabledRc { + pub(crate) atom: Rc, + pub table: TabledData +} + +impl fmt::Debug for TabledRc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TabledRc") + .field("atom", &self.atom) + .field("table", &self.table) + .finish() + } +} + +// this Clone instance is manually defined to prevent the compiler +// from complaining when deriving Clone for StringList. +impl Clone for TabledRc { + fn clone(&self) -> Self { + TabledRc { atom: self.atom.clone(), table: self.table.clone() } + } +} + +impl PartialOrd for TabledRc { + fn partial_cmp(&self, other: &Self) -> Option + { + Some(self.atom.cmp(&other.atom)) + } +} + +impl Ord for TabledRc { + fn cmp(&self, other: &Self) -> Ordering + { + self.atom.cmp(&other.atom) + } +} + +impl PartialEq for TabledRc { + fn eq(&self, other: &TabledRc) -> bool + { + self.atom == other.atom + } +} + +impl Eq for TabledRc {} + +impl Hash for TabledRc { + fn hash(&self, state: &mut H) { + self.atom.hash(state) + } +} + +impl TabledRc { + pub fn new(atom: T, table: TabledData) -> Self { + let atom = match table.borrow_mut().take(&atom) { + Some(atom) => atom.clone(), + None => Rc::new(atom) + }; + + table.borrow_mut().insert(atom.clone()); + + TabledRc { atom, table } + } + + #[inline] + pub fn inner(&self) -> Rc { + self.atom.clone() + } + + #[inline] + pub(crate) fn owning_module(&self) -> Rc { + self.table.module_name.clone() + } +} + +impl Drop for TabledRc { + fn drop(&mut self) { + if Rc::strong_count(&self.atom) == 2 { + self.table.borrow_mut().remove(&self.atom); + } + } +} + +impl Deref for TabledRc { + type Target = T; + + fn deref(&self) -> &Self::Target { + &*self.atom + } +} + +impl fmt::Display for TabledRc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", &*self.atom) + } +} + +#[macro_export] +macro_rules! tabled_rc { + ($e:expr, $tbl:expr) => ( + TabledRc::new(String::from($e), $tbl.clone()) + ) +} From 09a089d5f1913c74c9184d77e383742432b6c166 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 2 Feb 2021 17:42:43 -0700 Subject: [PATCH 014/137] set target_pos' clause_start correctly in append_compiled_clause --- src/machine/compile.rs | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 5311544b..13ac32c5 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -434,7 +434,7 @@ fn blunt_leading_choice_instr( } } -fn set_switch_var_offset_to_choice_instr_( +fn set_switch_var_offset_to_choice_instr( code: &mut Code, index_loc: usize, offset: usize, @@ -1014,13 +1014,6 @@ fn append_compiled_clause( lower_bound_clause_start - index_loc, retraction_info, ); - - thread_choice_instr_at_to( - code, - lower_bound_clause_start, - skeleton.clauses[target_pos].clause_start, - retraction_info, - ); } skeleton.clauses[target_pos - 1].clause_start @@ -1037,11 +1030,29 @@ fn append_compiled_clause( skeleton.clauses[lower_bound].clause_start - 2 } - _ => { + None => { if lower_bound == 0 { code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start); } + match skeleton.clauses[target_pos].opt_arg_index_key.switch_on_term_loc() { + Some(index_loc) => { + // point to the inner-threaded TryMeElse(0) if target_pos is + // indexed, and make switch_on_term point one line after it in + // its variable offset. + skeleton.clauses[target_pos].clause_start += 2; + + set_switch_var_offset( + code, + index_loc, + 2, + retraction_info, + ); + } + None => { + } + } + skeleton.clauses[lower_bound].clause_start } } @@ -1440,7 +1451,7 @@ impl<'a> LoadState<'a> { set_switch_var_offset( code, later_indexing_loc, - lower_bound_clause_start - later_indexing_loc, // target_indexing_loc - later_indexing_loc + 1, + lower_bound_clause_start - later_indexing_loc, &mut self.retraction_info, ); @@ -1461,10 +1472,10 @@ impl<'a> LoadState<'a> { ); } _ => { - set_switch_var_offset_to_choice_instr_( + set_switch_var_offset_to_choice_instr( code, target_indexing_loc, - lower_bound_clause_start - target_indexing_loc, //1, + lower_bound_clause_start - target_indexing_loc, &mut self.retraction_info, ); From a2447ecaa32bfff3eafd9b5f4ddda3899154104c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 2 Feb 2021 21:03:15 -0700 Subject: [PATCH 015/137] replace Char '!' with QueryTerm::BlockedCut --- src/machine/preprocessor.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index c063bd6f..a6e3f1e3 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -712,6 +712,9 @@ impl Preprocessor { Ok(clause_to_query_term(load_state, name, vec![], fixity)) } } + Term::Constant(_, Constant::Char('!')) => { + Ok(QueryTerm::BlockedCut) + } Term::Var(_, ref v) if v.as_str() == "!" => { Ok(QueryTerm::UnblockedCut(Cell::default())) } From e928a0aaea3c7fe23856fd437cf1bfd1cb76865b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 2 Feb 2021 21:47:59 -0700 Subject: [PATCH 016/137] expand attributed variable goals --- src/loader.pl | 2 +- src/machine/attributed_variables.pl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index 448960b9..b16150c6 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -460,7 +460,7 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- ; Goals = (\+ Goals0) -> expand_goal(Goals0, Module, Goals1, HeadVars), ExpandedGoals = (\+ Goals1) - ; predicate_property(Goals, meta_predicate(MetaSpecs)) -> + ; predicate_property(Module:Goals, meta_predicate(MetaSpecs)) -> expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) ; thread_goals(Goals, ExpandedGoals, (',')) ; Goals = ExpandedGoals diff --git a/src/machine/attributed_variables.pl b/src/machine/attributed_variables.pl index b5049e3a..3cd4c0f1 100644 --- a/src/machine/attributed_variables.pl +++ b/src/machine/attributed_variables.pl @@ -51,6 +51,7 @@ call_goals_0([Module-GoalList | GoalLists]) :- call_goals_0([]). call_goals_1([Goal | Goals], Module) :- - call(Module:Goal), + expand_goal(Goal, Module, Goal1), % TODO: remove this when goal expansions are added to call/N. + call(Module:Goal1), call_goals_1(Goals, Module). call_goals_1([], _). From 88f1160e2b6199ee613d3501a834a0fb5de54a44 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 01:22:13 -0700 Subject: [PATCH 017/137] use find_inner_choice_instr when appending an indexed clause to an indexed subsequence --- src/machine/compile.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 13ac32c5..2d05ae34 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1001,22 +1001,22 @@ fn append_compiled_clause( AppendOrPrepend::Append, ); - if lower_bound + 1 == target_pos { - let lower_bound_clause_start = find_inner_choice_instr( - code, - skeleton.clauses[lower_bound].clause_start, - index_loc, - ); + let target_pos_clause_start = find_inner_choice_instr( + code, + skeleton.clauses[target_pos - 1].clause_start, + index_loc, + ); + if lower_bound + 1 == target_pos { set_switch_var_offset( code, index_loc, - lower_bound_clause_start - index_loc, + target_pos_clause_start - index_loc, retraction_info, ); } - skeleton.clauses[target_pos - 1].clause_start + target_pos_clause_start // skeleton.clauses[target_pos - 1].clause_start } _ => { skeleton.clauses[target_pos].opt_arg_index_key += clause_loc; From 5749d43fb6b575f47a73b03bc8cacc86d39c8a8f Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 11:19:33 -0700 Subject: [PATCH 018/137] restore prolog_parser test files (#782) --- crates/prolog_parser/Cargo.lock | 265 +++++++++++++++++++++ crates/prolog_parser/tests/bom.rs | 43 ++++ crates/prolog_parser/tests/parse_tokens.rs | 114 +++++++++ 3 files changed, 422 insertions(+) create mode 100644 crates/prolog_parser/Cargo.lock create mode 100644 crates/prolog_parser/tests/bom.rs create mode 100644 crates/prolog_parser/tests/parse_tokens.rs diff --git a/crates/prolog_parser/Cargo.lock b/crates/prolog_parser/Cargo.lock new file mode 100644 index 00000000..f90f0d69 --- /dev/null +++ b/crates/prolog_parser/Cargo.lock @@ -0,0 +1,265 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "az" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84e1d907bfc5795a6addb95ef8666141ee73c8f2f5250ff2a46bf4e4f4aec8a" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "gmp-mpfr-sys" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a57fdb339d49833021b1fded600ed240ae907e33909d5511a61dff884df7f16e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "lexical" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e0d09e60c187a6d0a3fa418aec8587c6a4ae9de872f6126f2134f319b5ed10d" +dependencies = [ + "cfg-if", + "lexical-core", + "rustc_version", +] + +[[package]] +name = "lexical-core" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304bccb228c4b020f3a4835d247df0a02a7c4686098d4167762cfbbe4c5cb14" +dependencies = [ + "arrayvec", + "cfg-if", + "rustc_version", + "ryu", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.14", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits 0.2.14", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits 0.2.14", +] + +[[package]] +name = "num-rug-adapter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7470b6acf85abce0771203112db4181d03f7b8a6be49f0e842a78030192f8a58" +dependencies = [ + "libc", + "num-bigint", + "num-integer", + "num-rational", + "num-traits 0.2.14", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.14", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ordered-float" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d" +dependencies = [ + "num-traits 0.1.43", + "unreachable", +] + +[[package]] +name = "prolog_parser_rebis" +version = "0.8.68" +dependencies = [ + "lexical", + "num-rug-adapter", + "ordered-float", + "rug", + "unicode_reader", +] + +[[package]] +name = "rug" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e538d00da450a8e48aac7e6322e67b2dc86ec71a1feeac0e3954c4f07f01bc45" +dependencies = [ + "az", + "gmp-mpfr-sys", + "libc", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "static_assertions" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode_reader" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b639121690b27acd92c97ed2b52c5e5e8d3d39482e943b4559695cef62f771a" +dependencies = [ + "smallvec", + "unicode-segmentation", +] + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/crates/prolog_parser/tests/bom.rs b/crates/prolog_parser/tests/bom.rs new file mode 100644 index 00000000..25b57104 --- /dev/null +++ b/crates/prolog_parser/tests/bom.rs @@ -0,0 +1,43 @@ +extern crate prolog_parser_rebis; + +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::lexer::{Lexer, Token}; +use prolog_parser_rebis::tabled_rc::TabledData; + +use std::rc::Rc; + +#[test] +fn valid_token() { + let stream = parsing_stream("valid text".as_bytes()); + assert!(stream.is_ok()); +} + +#[test] +fn empty_stream() { + let bytes: &[u8] = &[]; + assert!(parsing_stream(bytes).is_ok()); +} + +#[test] +fn skip_utf8_bom() { + let atom_tbl = TabledData::new(Rc::new("my_module".to_string())); + let flags = MachineFlags::default(); + let bytes: &[u8] = &[0xEF, 0xBB, 0xBF, '4' as u8, '\n' as u8]; + let mut stream = parsing_stream(bytes).expect("valid stream"); + let mut lexer = Lexer::new(atom_tbl, flags, &mut stream); + match lexer.next_token() { + Ok(Token::Constant(Constant::Fixnum(4))) => (), + _ => assert!(false) + } +} + +#[test] +fn invalid_utf16_bom() { + let bytes: &[u8] = &[0xFF, 0xFE, 'a' as u8, '\n' as u8]; + let stream = parsing_stream(bytes); + match stream { + Err(ParserError::Utf8Error(0, 0)) => (), + _ => assert!(false) + } +} + diff --git a/crates/prolog_parser/tests/parse_tokens.rs b/crates/prolog_parser/tests/parse_tokens.rs new file mode 100644 index 00000000..3afb9164 --- /dev/null +++ b/crates/prolog_parser/tests/parse_tokens.rs @@ -0,0 +1,114 @@ +extern crate prolog_parser_rebis; + +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::lexer::{Lexer, Token}; +use prolog_parser_rebis::tabled_rc::TabledData; + +use std::rc::Rc; + +fn read_all_tokens(text: &str) -> Result, ParserError> { + let atom_tbl = TabledData::new(Rc::new("my_module".to_string())); + let flags = MachineFlags::default(); + let mut stream = parsing_stream(text.as_bytes())?; + let mut lexer = Lexer::new(atom_tbl, flags, &mut stream); + + let mut tokens = Vec::new(); + while !lexer.eof()? { + let token = lexer.next_token()?; + tokens.push(token); + } + Ok(tokens) +} + +#[test] +fn empty_multiline_comment() -> Result<(), ParserError> { + let tokens = read_all_tokens("/**/ 4\n")?; + assert_eq!(tokens, [Token::Constant(Constant::Fixnum(4))]); + Ok(()) +} + +#[test] +fn any_char_multiline_comment() -> Result<(), ParserError> { + let tokens = read_all_tokens("/* █╗╚═══╝ © */ 4\n")?; + assert_eq!(tokens, [Token::Constant(Constant::Fixnum(4))]); + Ok(()) +} + +#[test] +fn simple_char() -> Result<(), ParserError> { + let tokens = read_all_tokens("'a'\n")?; + assert_eq!(tokens, [Token::Constant(Constant::Char('a'))]); + Ok(()) +} + +#[test] +fn char_with_meta_seq() -> Result<(), ParserError> { + let tokens = read_all_tokens(r#"'\\' '\'' '\"' '\`' "#)?; // use literal string so \ are escaped + assert_eq!( + tokens, + [ + Token::Constant(Constant::Char('\\')), + Token::Constant(Constant::Char('\'')), + Token::Constant(Constant::Char('"')), + Token::Constant(Constant::Char('`')) + ] + ); + Ok(()) +} + +#[test] +fn char_with_control_seq() -> Result<(), ParserError> { + let tokens = read_all_tokens(r"'\a' '\b' '\r' '\f' '\t' '\n' '\v' ")?; + assert_eq!( + tokens, + [ + Token::Constant(Constant::Char('\u{07}')), + Token::Constant(Constant::Char('\u{08}')), + Token::Constant(Constant::Char('\r')), + Token::Constant(Constant::Char('\u{0c}')), + Token::Constant(Constant::Char('\t')), + Token::Constant(Constant::Char('\n')), + Token::Constant(Constant::Char('\u{0b}')), + ] + ); + Ok(()) +} + +#[test] +fn char_with_octseq() -> Result<(), ParserError> { + let tokens = read_all_tokens(r"'\60433\' ")?; + assert_eq!(tokens, [Token::Constant(Constant::Char('愛'))]); // Japanese character + Ok(()) +} + +#[test] +fn char_with_octseq_0() -> Result<(), ParserError> { + let tokens = read_all_tokens(r"'\0\' ")?; + assert_eq!(tokens, [Token::Constant(Constant::Char('\u{0000}'))]); + Ok(()) +} + +#[test] +fn char_with_hexseq() -> Result<(), ParserError> { + let tokens = read_all_tokens(r"'\x2124\' ")?; + assert_eq!(tokens, [Token::Constant(Constant::Char('ℤ'))]); // Z math symbol + Ok(()) +} + +#[test] +fn char_with_hexseq_invalid() { + assert!(read_all_tokens(r"'\x\' ").is_err()); +} + +#[test] +fn empty() -> Result<(), ParserError> { + let tokens = read_all_tokens("")?; + assert!(tokens.is_empty()); + Ok(()) +} + +#[test] +fn comment_then_eof() -> Result<(), ParserError> { + assert!(read_all_tokens("% only a comment").is_err()); + Ok(()) +} From 48f3f4ca37966c2f748d12c95e71e464a0776697 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 12:46:33 -0700 Subject: [PATCH 019/137] add meta-predicate declarations to reif library --- src/lib/reif.pl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lib/reif.pl b/src/lib/reif.pl index 0e958356..092f93ec 100644 --- a/src/lib/reif.pl +++ b/src/lib/reif.pl @@ -4,6 +4,8 @@ :- use_module(library(dif)). +:- meta_predicate if_(0, 0, 0). + if_(If_1, Then_0, Else_0) :- call(If_1, T), ( T == true -> call(Then_0) @@ -26,6 +28,8 @@ dif(X, Y, T) :- non(true, false). non(false, true). +:- meta_predicate tfilter(1, ?, ?). + tfilter(C_2, Es, Fs) :- i_tfilter(Es, C_2, Fs). @@ -34,6 +38,8 @@ i_tfilter([E|Es], C_2, Fs0) :- if_(call(C_2, E), Fs0 = [E|Fs], Fs0 = Fs), i_tfilter(Es, C_2, Fs). +:- meta_predicate tpartition(1, ?, ?). + tpartition(P_2, Xs, Ts, Fs) :- i_tpartition(Xs, P_2, Ts, Fs). @@ -44,12 +50,18 @@ i_tpartition([X|Xs], P_2, Ts0, Fs0) :- , ( Fs0 = [X|Fs], Ts0 = Ts ) ), i_tpartition(Xs, P_2, Ts, Fs). +:- meta_predicate ','(0, 0, ?). + ','(A_1, B_1, T) :- if_(A_1, call(B_1, T), T = false). +:- meta_predicate ';'(0, 0, ?). + ';'(A_1, B_1, T) :- if_(A_1, T = true, call(B_1, T)). +:- meta_predicate cond_t(0, 0, ?). + cond_t(If_1, Then_0, T) :- if_(If_1, ( Then_0, T = true ), T = false ). @@ -60,8 +72,12 @@ i_memberd_t([], _, false). i_memberd_t([X|Xs], E, T) :- if_( X = E, T = true, i_memberd_t(Xs, E, T) ). +:- meta_predicate tmember(1, ?). + tmember(P_2, [X|Xs]) :- if_( call(P_2, X), true, tmember(P_2, Xs) ). +:- meta_predicate tmember_t(1, ?). + tmember_t(P_2, [X|Xs], T) :- if_( call(P_2, X), T = true, tmember_t(P_2, Xs, T) ). From 88ad2ee103c5f55564c4b8f67e93fc434042a162 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 15:18:38 -0700 Subject: [PATCH 020/137] restore cut after dcg_constr check (#784) --- src/lib/dcgs.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl index f9410d99..05f41cb0 100644 --- a/src/lib/dcgs.pl +++ b/src/lib/dcgs.pl @@ -19,7 +19,7 @@ phrase(GRBody, S0, S) :- ( var(GRBody) -> throw(error(instantiation_error, phrase/3)) ; strip_module(GRBody, Module, GRBody0), - dcg_constr(GRBody0), + dcg_constr(GRBody0) -> ( var(Module) -> phrase_(GRBody0, S0, S) ; phrase_(Module:GRBody0, S0, S) From ae66e299e6867fc8f5cb63cede17bdcb54f990fc Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Fri, 8 Jan 2021 17:28:29 +0100 Subject: [PATCH 021/137] Use term expansion for generated predicates. --- src/lib/clpz.pl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index a4f66256..fda2f309 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -7763,11 +7763,10 @@ zo_t(1, true). Generated predicates - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -generated_clauses(Cs) :- - make_parse_clpz(Cs1), - make_parse_reified(Cs2), - make_matches(Cs3), - append([Cs1,Cs2,Cs3], Cs). +term_expansion(make_parse_clpz, Clauses) :- make_parse_clpz(Clauses). +term_expansion(make_parse_reified, Clauses) :- make_parse_reified(Clauses). +term_expansion(make_matches, Clauses) :- make_matches(Clauses). -:- initialization((generated_clauses(Cs), - maplist(assertz, Cs))). +make_parse_clpz. +make_parse_reified. +make_matches. From cab0e4395ab3c5478d344aa9393cf44499228ead Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 15:37:16 -0700 Subject: [PATCH 022/137] manually expand module names in higher-order predicates of lists.pl and give call_residue_vars/2 a meta-predicate definition --- src/lib/atts.pl | 2 ++ src/lib/lists.pl | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/atts.pl b/src/lib/atts.pl index 8fa16e11..fcd5b2c1 100644 --- a/src/lib/atts.pl +++ b/src/lib/atts.pl @@ -156,6 +156,8 @@ user:goal_expansion(Term, M:get_atts(Var, Attr)) :- nonvar(Term), Term = get_atts(Var, M, Attr). +:- meta_predicate call_residue_vars(0, ?). + call_residue_vars(Goal, Vars) :- '$get_attr_var_queue_delim'(B), call(Goal), diff --git a/src/lib/lists.pl b/src/lib/lists.pl index c6160e55..5549a061 100644 --- a/src/lib/lists.pl +++ b/src/lib/lists.pl @@ -126,7 +126,7 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7 sum_list(Ls, S) :- - foldl(sum_, Ls, 0, S). + foldl(lists:sum_, Ls, 0, S). sum_(L, S0, S) :- S is S0 + L. @@ -164,13 +164,13 @@ lists_transpose([L|Ls], Ts) :- foldl(transpose_, L, Ts, [L|Ls], _). transpose_(_, Fs, Lists0, Lists) :- - maplist(list_first_rest, Lists0, Fs, Lists). + maplist(lists:list_first_rest, Lists0, Fs, Lists). list_first_rest([L|Ls], L, Ls). list_to_set(Ls0, Ls) :- - maplist(with_var, Ls0, LVs0), + maplist(lists:with_var, Ls0, LVs0), keysort(LVs0, LVs), same_elements(LVs), pick_firsts(LVs0, Ls). @@ -188,7 +188,7 @@ with_var(E, E-_). same_elements([]). same_elements([EV|EVs]) :- - foldl(unify_same, EVs, EV, _). + foldl(lists:unify_same, EVs, EV, _). unify_same(E-V, Prev-Var, E-V) :- ( Prev == E -> @@ -221,13 +221,13 @@ nth0_search(N0, N, [_|Es], E) :- list_max([N|Ns], Max) :- - foldl(list_max_, Ns, N, Max). + foldl(lists:list_max_, Ns, N, Max). list_max_(N, Max0, Max) :- Max is max(N, Max0). list_min([N|Ns], Min) :- - foldl(list_min_, Ns, N, Min). + foldl(lists:list_min_, Ns, N, Min). list_min_(N, Min0, Min) :- Min is min(N, Min0). From 24e6c31c4429d52b11b5ed7a4e798c63b27d854e Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Wed, 3 Feb 2021 23:45:06 +0100 Subject: [PATCH 023/137] add meta_predicate declaration for with_local_attributes/3 This is needed for all_distinct/1 etc. Example: ?- all_distinct([X,Y,Z]). clpz:all_distinct([X,Y,Z]) ; false. --- src/lib/clpz.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index fda2f309..e72a33c1 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -6047,6 +6047,8 @@ remove_attr(Var, Attr) :- functor(Term, Attr, 1), put_atts(Var, -Term). +:- meta_predicate with_local_attributes(?, 0, ?). + with_local_attributes(Vars, Goal, Result) :- catch((Goal, maplist(del_all_attrs, Vars), From 94392f248c9a00556a0fcc6d95e7f7fabe1a0853 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 15:48:09 -0700 Subject: [PATCH 024/137] enable phrase_ rules for module resolved grammars (#785) --- src/lib/dcgs.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl index 05f41cb0..a33c870b 100644 --- a/src/lib/dcgs.pl +++ b/src/lib/dcgs.pl @@ -31,6 +31,8 @@ phrase(GRBody, S0, S) :- phrase_([], S, S). phrase_(!, S, S). +phrase_(_:[], S, S). +phrase_(_:!, S, S). phrase_((A, B), S0, S) :- phrase(A, S0, S1), phrase(B, S1, S). phrase_(M:(A, B), S0, S) :- @@ -57,16 +59,24 @@ phrase_(M:(A | B), S0, S) :- ( phrase(M:A, S0, S) ; phrase(M:B, S0, S) ). phrase_({G}, S0, S) :- ( call(G), S0 = S ). +phrase_(M:{G}, S0, S) :- + ( call(M:G), S0 = S ). phrase_(call(G), S0, S) :- call(G, S0, S). +phrase_(M:call(G), S0, S) :- + call(M:G, S0, S). phrase_((A -> B), S0, S) :- phrase((A -> B ; fail), S0, S). phrase_(M:(A -> B), S0, S) :- phrase((M:A -> M:B ; fail), S0, S). phrase_(phrase(NonTerminal), S0, S) :- phrase(NonTerminal, S0, S). +phrase_(M:phrase(NonTerminal), S0, S) :- + phrase(M:NonTerminal, S0, S). phrase_([T|Ts], S0, S) :- append([T|Ts], S, S0). +phrase_(_:[T|Ts], S0, S) :- + append([T|Ts], S, S0). % The same version of the below two dcg_rule clauses, but with module scoping. From b96ff781bc806ff37b4abe9e3b7d986728473b2a Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Wed, 3 Feb 2021 23:49:28 +0100 Subject: [PATCH 025/137] add meta_predicate declaration for must_succeed/1 --- src/lib/clpz.pl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index e72a33c1..b7fa0ea7 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -5884,10 +5884,12 @@ difference_arcs([V|Vs], FL0) --> writeln(T) :- write(T), nl. +:- meta_predicate must_succeed(0). + must_succeed(G) :- - (G -> true - ;write(failed-G), halt - ). + ( G -> true + ; throw(failed-G) + ). enumerate([], _) --> []. enumerate([N|Ns], V) --> From a8a82e45a01fd49cc6876e8e7caf18dcc6af393f Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 16:03:12 -0700 Subject: [PATCH 026/137] introduce cuts over indexed (:)/2 of dcgs:phrase_/3 (#786) --- src/lib/dcgs.pl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib/dcgs.pl b/src/lib/dcgs.pl index a33c870b..07b82b95 100644 --- a/src/lib/dcgs.pl +++ b/src/lib/dcgs.pl @@ -31,11 +31,12 @@ phrase(GRBody, S0, S) :- phrase_([], S, S). phrase_(!, S, S). -phrase_(_:[], S, S). -phrase_(_:!, S, S). +phrase_(_:[], S, S) :- !. +phrase_(_:!, S, S) :- !. phrase_((A, B), S0, S) :- phrase(A, S0, S1), phrase(B, S1, S). phrase_(M:(A, B), S0, S) :- + !, phrase(M:A, S0, S1), phrase(M:B, S1, S). phrase_((A -> B ; C), S0, S) :- !, @@ -52,26 +53,32 @@ phrase_(M:(A -> B ; C), S0, S) :- phrase_((A ; B), S0, S) :- ( phrase(A, S0, S) ; phrase(B, S0, S) ). phrase_(M:(A ; B), S0, S) :- + !, ( phrase(M:A, S0, S) ; phrase(M:B, S0, S) ). phrase_((A | B), S0, S) :- ( phrase(A, S0, S) ; phrase(B, S0, S) ). phrase_(M:(A | B), S0, S) :- + !, ( phrase(M:A, S0, S) ; phrase(M:B, S0, S) ). phrase_({G}, S0, S) :- ( call(G), S0 = S ). phrase_(M:{G}, S0, S) :- + !, ( call(M:G), S0 = S ). phrase_(call(G), S0, S) :- call(G, S0, S). phrase_(M:call(G), S0, S) :- + !, call(M:G, S0, S). phrase_((A -> B), S0, S) :- phrase((A -> B ; fail), S0, S). phrase_(M:(A -> B), S0, S) :- + !, phrase((M:A -> M:B ; fail), S0, S). phrase_(phrase(NonTerminal), S0, S) :- phrase(NonTerminal, S0, S). phrase_(M:phrase(NonTerminal), S0, S) :- + !, phrase(M:NonTerminal, S0, S). phrase_([T|Ts], S0, S) :- append([T|Ts], S, S0). From 2fe55e47153432563a0664921ecf10a03caebb0c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 16:38:44 -0700 Subject: [PATCH 027/137] resolve calls to tranpose_ and same_length in lists.pl (#790) --- src/lib/lists.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/lists.pl b/src/lib/lists.pl index 5549a061..0a799672 100644 --- a/src/lib/lists.pl +++ b/src/lib/lists.pl @@ -160,8 +160,8 @@ transpose(Ls, Ts) :- lists_transpose([], []). lists_transpose([L|Ls], Ts) :- - maplist(same_length(L), Ls), - foldl(transpose_, L, Ts, [L|Ls], _). + maplist(lists:same_length(L), Ls), + foldl(lists:transpose_, L, Ts, [L|Ls], _). transpose_(_, Fs, Lists0, Lists) :- maplist(lists:list_first_rest, Lists0, Fs, Lists). From e17eb01f7617b72805f6c6123264485444329e42 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 3 Feb 2021 16:47:04 -0700 Subject: [PATCH 028/137] respect module context in expand_module_names (#788) --- src/loader.pl | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index b16150c6..06fe2ef2 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -423,7 +423,7 @@ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :- Goals =.. [GoalFunctor | SubGoals], ( GoalFunctor == (:), SubGoals = [M, SubGoal] -> - expand_module_names(SubGoal, MetaSpecs, Module, ExpandedSubGoal, HeadVars), + expand_module_names(SubGoal, MetaSpecs, M, ExpandedSubGoal, HeadVars), ExpandedGoals = M:ExpandedSubGoal ; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars), ExpandedGoals =.. [GoalFunctor | ExpandedGoalList] @@ -434,6 +434,28 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals) :- expand_goal(UnexpandedGoals, Module, ExpandedGoals, []), !. +expand_goal_cases((Goal0, Goals0), Module, ExpandedGoals, HeadVars) :- + ( 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) + ). +expand_goal_cases((Goals0 -> Goals1), Module, ExpandedGoals, HeadVars) :- + expand_goal(Goals0, Module, ExpandedGoals0, HeadVars), + expand_goal(Goals1, Module, ExpandedGoals1, HeadVars), + ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1). +expand_goal_cases((Goals0 ; Goals1), Module, ExpandedGoals, HeadVars) :- + expand_goal(Goals0, Module, ExpandedGoals0, HeadVars), + expand_goal(Goals1, Module, ExpandedGoals1, HeadVars), + ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1). +expand_goal_cases((\+ Goals0), Module, ExpandedGoals, HeadVars) :- + expand_goal(Goals0, Module, Goals1, HeadVars), + ExpandedGoals = (\+ Goals1). +expand_goal_cases((Module:Goals0), _, ExpandedGoals, HeadVars) :- + expand_goal(Goals0, Module, Goals1, HeadVars), + ExpandedGoals = (Module:Goals1). + expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- ( var(UnexpandedGoals) -> UnexpandedGoals = ExpandedGoals @@ -442,24 +464,8 @@ expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- 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) + ( expand_goal_cases(Goals, Module, ExpandedGoals, HeadVars) -> + true ; predicate_property(Module:Goals, meta_predicate(MetaSpecs)) -> expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) ; thread_goals(Goals, ExpandedGoals, (',')) From 164b9930640656700505188eab684b3575ab1fe8 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 4 Feb 2021 20:48:09 +0100 Subject: [PATCH 029/137] preliminary workaround for #788 This change can be reverted once the issue is resolved. --- src/lib/clpz.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index b7fa0ea7..b687354e 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -6090,7 +6090,7 @@ distinct_goals_([flow_to(F,To)|Es], V) --> get_attr(To, lowlink, L2), L1 =\= L2 } -> { get_attr(To, value, N) }, - [neq_num(V, N)] + [clpz:neq_num(V, N)] ; [] ), distinct_goals_(Es, V). @@ -6611,7 +6611,7 @@ gcc_edge_goal(arc_to(_,_,V,F), Val) --> get_attr(Val, lowlink, L2), L1 =\= L2, get_attr(Val, value, Value) } -> - [neq_num(V, Value)] + [clpz:neq_num(V, Value)] ; [] ). From 75a52f032b95fc74c1c3fa93996fd0f61775c28f Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 4 Feb 2021 16:59:16 -0700 Subject: [PATCH 030/137] perform goal expansion in call/N (#788, #797) --- src/clause_types.rs | 4 +- src/lib/builtins.pl | 31 +- src/lib/ops_and_meta_predicates.pl | 2 + src/loader.pl | 751 +++++++++++++++++++++++++++- src/machine/attributed_variables.pl | 3 +- src/machine/load_state.rs | 13 - src/machine/loader.rs | 13 + src/machine/mod.rs | 114 ++--- src/machine/preprocessor.rs | 2 +- 9 files changed, 835 insertions(+), 98 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 4c39d5d6..435e1182 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -863,7 +863,7 @@ impl ClauseType { pub fn name(&self) -> ClauseName { match self { &ClauseType::BuiltIn(ref built_in) => built_in.name(), - &ClauseType::CallN => clause_name!("call"), + &ClauseType::CallN => clause_name!("$call"), &ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()), &ClauseType::Op(ref name, ..) => name.clone(), &ClauseType::Named(ref name, ..) => name.clone(), @@ -882,7 +882,7 @@ impl ClauseType { .unwrap_or_else(|| { if let Some(spec) = spec { ClauseType::Op(name, spec, CodeIndex::default()) - } else if name.as_str() == "call" { + } else if name.as_str() == "$call" { ClauseType::CallN } else { ClauseType::Named(name, arity, CodeIndex::default()) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 3aba986b..fa3844cb 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -4,9 +4,10 @@ abolish/1, asserta/1, assertz/1, at_end_of_stream/0, at_end_of_stream/1, atom_chars/2, atom_codes/2, atom_concat/3, - atom_length/2, bagof/3, catch/3, char_code/2, - clause/2, close/1, close/2, current_input/1, - current_output/1, current_op/3, + atom_length/2, bagof/3, call/1, call/2, call/3, + call/4, call/5, call/6, call/7, call/8, call/9, + catch/3, char_code/2, clause/2, close/1, close/2, + current_input/1, current_output/1, current_op/3, current_predicate/1, current_prolog_flag/2, fail/0, false/0, findall/3, findall/4, flush_output/0, flush_output/1, get_byte/1, @@ -38,6 +39,30 @@ true. false :- '$fail'. + +% These are stub versions of call/{1-9} defined for bootstrapping. +% Once Scryer is bootstrapped, each is replaced with a version that +% uses expand_goal to pass the expanded goal along to '$call'. + +call(G) :- '$call'(G). + +call(G, A) :- '$call'(G, A). + +call(G, A, B) :- '$call'(G, A, B). + +call(G, A, B, C) :- '$call'(G, A, B, C). + +call(G, A, B, C, D) :- '$call'(G, A, B, C, D). + +call(G, A, B, C, D, E) :- '$call'(G, A, B, C, D, E). + +call(G, A, B, C, D, E, F) :- '$call'(G, A, B, C, D, E, F). + +call(G, A, B, C, D, E, F, G) :- '$call'(G, A, B, C, D, E, F, G). + +call(G, A, B, C, D, E, F, G, H) :- '$call'(G, A, B, C, D, E, F, G, H). + + Module : Predicate :- ( atom(Module) -> '$module_call'(Module, Predicate) diff --git a/src/lib/ops_and_meta_predicates.pl b/src/lib/ops_and_meta_predicates.pl index 2d78c615..59a324d4 100644 --- a/src/lib/ops_and_meta_predicates.pl +++ b/src/lib/ops_and_meta_predicates.pl @@ -125,3 +125,5 @@ :- meta_predicate call(61, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). :- meta_predicate call(62, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). :- meta_predicate call(63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(64, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). +:- meta_predicate call(65, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?). diff --git a/src/loader.pl b/src/loader.pl index 06fe2ef2..853842fb 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -18,14 +18,14 @@ '$print_message_and_fail'(Error, Culprit) :- -% writeq(error(Error, Culprit)), -% nl, + % writeq(error(Error, Culprit)), + % nl, '$fail'. expand_term(Term, ExpandedTerm) :- - ( catch(user:term_expansion(Term, ExpandedTerm0), + ( catch('$call'(user:term_expansion(Term, ExpandedTerm0)), E, - loader:'$print_message_and_fail'(E, user:term_expansion)) -> + '$call'(loader:'$print_message_and_fail'(E, user:term_expansion))) -> ( var(ExpandedTerm0) -> error:instantiation_error(term_expansion/2) ; ExpandedTerm0 = [_|_] -> @@ -50,9 +50,9 @@ term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- goal_expansion(Goal, Module, ExpandedGoal) :- - ( catch(Module:goal_expansion(Goal, ExpandedGoal0), + ( catch('$call'(Module:goal_expansion(Goal, ExpandedGoal0)), E, - loader:'$print_message_and_fail'(E, Module:goal_expansion)) -> + '$call'(loader:'$print_message_and_fail'(E, Module:goal_expansion))) -> ( var(ExpandedGoal0) -> error:instantiation_error(goal_expansion/2) ; goal_expansion(ExpandedGoal0, Module, ExpandedGoal) @@ -195,8 +195,7 @@ compile_dispatch_or_clause(Term, Evacuable, VNs) :- compile_dispatch((:- Declaration), Evacuable, _VNs) :- ( var(Declaration) -> instantiation_error(load/1) - ; - compile_declaration(Declaration, Evacuable) + ; compile_declaration(Declaration, Evacuable) ). compile_dispatch(term_expansion(Term, Terms), Evacuable, VNs) :- '$add_term_expansion_clause'(term_expansion(Term, Terms), Evacuable, VNs). @@ -224,13 +223,13 @@ compile_declaration(use_module(Module, Exports), Evacuable) :- ( Exports == [] -> '$remove_module_exports'(Module, Evacuable) % TODO: implement this. ; - use_module(Module, Exports, Evacuable) + use_module(Module, Exports, Evacuable) ). compile_declaration(module(Module, Exports), Evacuable) :- ( atom(Module) -> '$declare_module'(Module, Exports, Evacuable) ; - type_error(atom, Module, load/1) + type_error(atom, Module, load/1) ). compile_declaration(dynamic(Name/Arity), Evacuable) :- must_be(atom, Name), @@ -291,7 +290,7 @@ use_module(Module, Exports) :- ( Exports == [] -> '$remove_module_exports'(Module, Evacuable) ; - use_module(Module, Exports, Evacuable) + use_module(Module, Exports, Evacuable) ). @@ -301,7 +300,7 @@ load_context_path(Module, Path) :- ( prolog_load_context(directory, CurrentDir) -> atom_concat(CurrentDir, Path, Module) ; - Module = Path + Module = Path ). @@ -313,14 +312,14 @@ use_module(Module, Exports, Evacuable) :- ( '$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) + '$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) + type_error(atom, Library, load/1) ) ; atom(Module) -> load_context_path(Module, Path), @@ -328,7 +327,7 @@ use_module(Module, Exports, Evacuable) :- file_load(Stream, Path, Subevacuable), '$use_module'(Evacuable, Subevacuable, Exports) ; - type_error(atom, Library, load/1) + type_error(atom, Library, load/1) ). @@ -345,6 +344,12 @@ extract_predicate_property(Property, PropertyType) :- ; functor(Property, PropertyType, _) ). +load_context(Module) :- + ( prolog_load_context(module, Module) -> + true + ; Module = user + ). + predicate_property(Callable, Property) :- ( var(Callable) -> instantiation_error(load/1) @@ -355,10 +360,7 @@ predicate_property(Callable, Property) :- check_predicate_property(PropertyType, Module, Name, Arity, Property) ; functor(Callable, Name, Arity), extract_predicate_property(Property, PropertyType), - ( prolog_load_context(module, Module) -> - true - ; Module = user - ), + load_context(Module), check_predicate_property(PropertyType, Module, Name, Arity, Property) ). @@ -498,3 +500,710 @@ thread_goals(Goals0, Goals1, Hole, Functor) :- ; Goals1 =.. [Functor, Goals0, Hole] ) ). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% call/{1-64} with dynamic goal expansion. +% +% The program used to generate the call/N predicates: +% +% +% :- use_module(library(between)). +% :- use_module(library(error)). +% :- use_module(library(lists)). +% :- use_module(library(format)). +% +% call_form_generator(N) :- +% length(Args, N), +% CallHead =.. [call, G | Args], +% N1 is N + 1, +% Form = (CallHead :- ( var(G) -> +% instantiation_error(call/N1) +% ; call_clause(G, Args, N1, G0) -> +% '$call'(G0) +% ; type_error(callable, G, call/N1) +% )), +% portray_clause(Form). +% +% generate_call_forms :- +% between(1, 64, N), +% call_form_generator(N), +% nl, +% false. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +call_clause(M:G1, G0) :- + functor(G1, F, _), + atom(F), + atom(M), + F \== [], + !, + expand_goal(M:G1, M, G0). + +% The '$call' functor is an escape hatch from goal expansion. So far, +% it is used only to avoid infinite recursion into expand_goal/3. + +call_clause('$call'(G), G0) :- + ( var(G), + instantiation_error(call/1) + ; G = M:G1, + !, + functor(G1, F, _), + atom(F), + atom(M), + F \== [], + G0 = M:G1 + ; !, + functor(G, F, _), + atom(F), + F \== [], + load_context(M), + G0 = M:G + ). + +call_clause(G, G0) :- + functor(G, F, _), + atom(F), + F \== [], + load_context(M), + expand_goal(M:G, M, G0). + + +call(G) :- + ( var(G) -> + instantiation_error(call/1) + ; call_clause(G, G0) -> + '$call'(G0) + ; type_error(callable, G, call/1) + ). + + +call_clause(M:G1, Args, _, G0) :- + atom(M), + G1 =.. [F | As], + atom(F), + F \== [], + !, + append(As, Args, As1), + G2 =.. [F | As1], + expand_goal(M:G2, M, G0). + +call_clause('$call'(G1), Args, N, G0) :- + ( var(G1), + instantiation_error(call/N) + ; G1 = M:G2, + !, + atom(M), + G2 =.. [F | As], + atom(F), + F \== [], + append(As, Args, As1), + G3 =.. [F | As1], + G0 = M:G3 + ; !, + G1 =.. [F | As], + atom(F), + F \== [], + load_context(M), + append(As, Args, As1), + G2 =.. [F | As1], + G0 = M:G2 + ). + +call_clause(G, Args, _, G0) :- + G =.. [F | As], + atom(F), + F \== [], + load_context(M), + append(As, Args, As1), + G2 =.. [F | As1], + expand_goal(M:G2, M, G0). + + +call(A,B) :- + ( var(A) -> + instantiation_error(call/2) + ; ( call_clause(A,[B],2,C) -> + '$call'(C) + ; type_error(callable,A,call/2) + ) + ). + +call(A,B,C) :- + ( var(A) -> + instantiation_error(call/3) + ; ( call_clause(A,[B,C],3,D) -> + '$call'(D) + ; type_error(callable,A,call/3) + ) + ). + +call(A,B,C,D) :- + ( var(A) -> + instantiation_error(call/4) + ; ( call_clause(A,[B,C,D],4,E) -> + '$call'(E) + ; type_error(callable,A,call/4) + ) + ). + +call(A,B,C,D,E) :- + ( var(A) -> + instantiation_error(call/5) + ; ( call_clause(A,[B,C,D,E],5,F) -> + '$call'(F) + ; type_error(callable,A,call/5) + ) + ). + +call(A,B,C,D,E,F) :- + ( var(A) -> + instantiation_error(call/6) + ; ( call_clause(A,[B,C,D,E,F],6,G) -> + '$call'(G) + ; type_error(callable,A,call/6) + ) + ). + +call(A,B,C,D,E,F,G) :- + ( var(A) -> + instantiation_error(call/7) + ; ( call_clause(A,[B,C,D,E,F,G],7,H) -> + '$call'(H) + ; type_error(callable,A,call/7) + ) + ). + +call(A,B,C,D,E,F,G,H) :- + ( var(A) -> + instantiation_error(call/8) + ; ( call_clause(A,[B,C,D,E,F,G,H],8,I) -> + '$call'(I) + ; type_error(callable,A,call/8) + ) + ). + +call(A,B,C,D,E,F,G,H,I) :- + ( var(A) -> + instantiation_error(call/9) + ; ( call_clause(A,[B,C,D,E,F,G,H,I],9,J) -> + '$call'(J) + ; type_error(callable,A,call/9) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J) :- + ( var(A) -> + instantiation_error(call/10) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J],10,K) -> + '$call'(K) + ; type_error(callable,A,call/10) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K) :- + ( var(A) -> + instantiation_error(call/11) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K],11,L) -> + '$call'(L) + ; type_error(callable,A,call/11) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L) :- + ( var(A) -> + instantiation_error(call/12) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L],12,M) -> + '$call'(M) + ; type_error(callable,A,call/12) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M) :- + ( var(A) -> + instantiation_error(call/13) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M],13,N) -> + '$call'(N) + ; type_error(callable,A,call/13) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N) :- + ( var(A) -> + instantiation_error(call/14) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N],14,O) -> + '$call'(O) + ; type_error(callable,A,call/14) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) :- + ( var(A) -> + instantiation_error(call/15) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O],15,P) -> + '$call'(P) + ; type_error(callable,A,call/15) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) :- + ( var(A) -> + instantiation_error(call/16) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],16,Q) -> + '$call'(Q) + ; type_error(callable,A,call/16) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) :- + ( var(A) -> + instantiation_error(call/17) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q],17,R) -> + '$call'(R) + ; type_error(callable,A,call/17) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) :- + ( var(A) -> + instantiation_error(call/18) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R],18,S) -> + '$call'(S) + ; type_error(callable,A,call/18) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) :- + ( var(A) -> + instantiation_error(call/19) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S],19,T) -> + '$call'(T) + ; type_error(callable,A,call/19) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) :- + ( var(A) -> + instantiation_error(call/20) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T],20,U) -> + '$call'(U) + ; type_error(callable,A,call/20) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) :- + ( var(A) -> + instantiation_error(call/21) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U],21,V) -> + '$call'(V) + ; type_error(callable,A,call/21) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) :- + ( var(A) -> + instantiation_error(call/22) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V],22,W) -> + '$call'(W) + ; type_error(callable,A,call/22) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) :- + ( var(A) -> + instantiation_error(call/23) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W],23,X) -> + '$call'(X) + ; type_error(callable,A,call/23) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) :- + ( var(A) -> + instantiation_error(call/24) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X],24,Y) -> + '$call'(Y) + ; type_error(callable,A,call/24) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) :- + ( var(A) -> + instantiation_error(call/25) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y],25,Z) -> + '$call'(Z) + ; type_error(callable,A,call/25) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) :- + ( var(A) -> + instantiation_error(call/26) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z],26,A1) -> + '$call'(A1) + ; type_error(callable,A,call/26) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1) :- + ( var(A) -> + instantiation_error(call/27) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1],27,B1) -> + '$call'(B1) + ; type_error(callable,A,call/27) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1) :- + ( var(A) -> + instantiation_error(call/28) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1],28,C1) -> + '$call'(C1) + ; type_error(callable,A,call/28) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1) :- + ( var(A) -> + instantiation_error(call/29) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1],29,D1) -> + '$call'(D1) + ; type_error(callable,A,call/29) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1) :- + ( var(A) -> + instantiation_error(call/30) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1],30,E1) -> + '$call'(E1) + ; type_error(callable,A,call/30) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1) :- + ( var(A) -> + instantiation_error(call/31) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1],31,F1) -> + '$call'(F1) + ; type_error(callable,A,call/31) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1) :- + ( var(A) -> + instantiation_error(call/32) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1],32,G1) -> + '$call'(G1) + ; type_error(callable,A,call/32) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1) :- + ( var(A) -> + instantiation_error(call/33) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1],33,H1) -> + '$call'(H1) + ; type_error(callable,A,call/33) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1) :- + ( var(A) -> + instantiation_error(call/34) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1],34,I1) -> + '$call'(I1) + ; type_error(callable,A,call/34) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1) :- + ( var(A) -> + instantiation_error(call/35) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1],35,J1) -> + '$call'(J1) + ; type_error(callable,A,call/35) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1) :- + ( var(A) -> + instantiation_error(call/36) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1],36,K1) -> + '$call'(K1) + ; type_error(callable,A,call/36) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1) :- + ( var(A) -> + instantiation_error(call/37) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1],37,L1) -> + '$call'(L1) + ; type_error(callable,A,call/37) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1) :- + ( var(A) -> + instantiation_error(call/38) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1],38,M1) -> + '$call'(M1) + ; type_error(callable,A,call/38) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1) :- + ( var(A) -> + instantiation_error(call/39) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1],39,N1) -> + '$call'(N1) + ; type_error(callable,A,call/39) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1) :- + ( var(A) -> + instantiation_error(call/40) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1],40,O1) -> + '$call'(O1) + ; type_error(callable,A,call/40) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1) :- + ( var(A) -> + instantiation_error(call/41) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1],41,P1) -> + '$call'(P1) + ; type_error(callable,A,call/41) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1) :- + ( var(A) -> + instantiation_error(call/42) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1],42,Q1) -> + '$call'(Q1) + ; type_error(callable,A,call/42) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1) :- + ( var(A) -> + instantiation_error(call/43) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1],43,R1) -> + '$call'(R1) + ; type_error(callable,A,call/43) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1) :- + ( var(A) -> + instantiation_error(call/44) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1],44,S1) -> + '$call'(S1) + ; type_error(callable,A,call/44) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1) :- + ( var(A) -> + instantiation_error(call/45) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1],45,T1) -> + '$call'(T1) + ; type_error(callable,A,call/45) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1) :- + ( var(A) -> + instantiation_error(call/46) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1],46,U1) -> + '$call'(U1) + ; type_error(callable,A,call/46) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1) :- + ( var(A) -> + instantiation_error(call/47) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1],47,V1) -> + '$call'(V1) + ; type_error(callable,A,call/47) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1) :- + ( var(A) -> + instantiation_error(call/48) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1],48,W1) -> + '$call'(W1) + ; type_error(callable,A,call/48) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1) :- + ( var(A) -> + instantiation_error(call/49) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1],49,X1) -> + '$call'(X1) + ; type_error(callable,A,call/49) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1) :- + ( var(A) -> + instantiation_error(call/50) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1],50,Y1) -> + '$call'(Y1) + ; type_error(callable,A,call/50) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1) :- + ( var(A) -> + instantiation_error(call/51) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1],51,Z1) -> + '$call'(Z1) + ; type_error(callable,A,call/51) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1) :- + ( var(A) -> + instantiation_error(call/52) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1],52,A2) -> + '$call'(A2) + ; type_error(callable,A,call/52) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2) :- + ( var(A) -> + instantiation_error(call/53) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2],53,B2) -> + '$call'(B2) + ; type_error(callable,A,call/53) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2) :- + ( var(A) -> + instantiation_error(call/54) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2],54,C2) -> + '$call'(C2) + ; type_error(callable,A,call/54) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2) :- + ( var(A) -> + instantiation_error(call/55) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2],55,D2) -> + '$call'(D2) + ; type_error(callable,A,call/55) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2) :- + ( var(A) -> + instantiation_error(call/56) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2],56,E2) -> + '$call'(E2) + ; type_error(callable,A,call/56) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2) :- + ( var(A) -> + instantiation_error(call/57) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2],57,F2) -> + '$call'(F2) + ; type_error(callable,A,call/57) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2) :- + ( var(A) -> + instantiation_error(call/58) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2],58,G2) -> + '$call'(G2) + ; type_error(callable,A,call/58) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2) :- + ( var(A) -> + instantiation_error(call/59) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2],59,H2) -> + '$call'(H2) + ; type_error(callable,A,call/59) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2) :- + ( var(A) -> + instantiation_error(call/60) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2],60,I2) -> + '$call'(I2) + ; type_error(callable,A,call/60) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2) :- + ( var(A) -> + instantiation_error(call/61) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2],61,J2) -> + '$call'(J2) + ; type_error(callable,A,call/61) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2) :- + ( var(A) -> + instantiation_error(call/62) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2],62,K2) -> + '$call'(K2) + ; type_error(callable,A,call/62) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2) :- + ( var(A) -> + instantiation_error(call/63) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2],63,L2) -> + '$call'(L2) + ; type_error(callable,A,call/63) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2) :- + ( var(A) -> + instantiation_error(call/64) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2],64,M2) -> + '$call'(M2) + ; type_error(callable,A,call/64) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :- + ( var(A) -> + instantiation_error(call/65) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2],65,N2) -> + '$call'(N2) + ; type_error(callable,A,call/65) + ) + ). + +call(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2) :- + ( var(A) -> + instantiation_error(call/65) + ; ( call_clause(A,[B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2,L2,M2],65,N2) -> + '$call'(N2) + ; type_error(callable,A,call/65) + ) + ). diff --git a/src/machine/attributed_variables.pl b/src/machine/attributed_variables.pl index 3cd4c0f1..b5049e3a 100644 --- a/src/machine/attributed_variables.pl +++ b/src/machine/attributed_variables.pl @@ -51,7 +51,6 @@ call_goals_0([Module-GoalList | GoalLists]) :- call_goals_0([]). call_goals_1([Goal | Goals], Module) :- - expand_goal(Goal, Module, Goal1), % TODO: remove this when goal expansions are added to call/N. - call(Module:Goal1), + call(Module:Goal), call_goals_1(Goals, Module). call_goals_1([], _). diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 1d5526a5..bef493b5 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -528,19 +528,6 @@ impl<'a> LoadState<'a> { } } - #[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, diff --git a/src/machine/loader.rs b/src/machine/loader.rs index d29fe3dc..6687b545 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -573,6 +573,19 @@ impl CompilationTarget { fn take(&mut self) -> CompilationTarget { mem::replace(self, CompilationTarget::User) } + + #[inline] + pub(super) + fn module_name(&self) -> ClauseName { + match self { + CompilationTarget::User => { + clause_name!("user") + } + CompilationTarget::Module(ref module_name) => { + module_name.clone() + } + } + } } pub(crate) struct Loader<'a, TermStream> { diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 9a75837c..9c6acbb3 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -119,39 +119,6 @@ include!(concat!(env!("OUT_DIR"), "/libraries.rs")); impl Machine { /* - fn compile_special_forms(&mut self) - { - let verify_attrs_src = ListingSource::User; - - match compile_special_form( - self, - Stream::from(VERIFY_ATTRS), - verify_attrs_src, - ) - { - Ok(p) => { - self.machine_st.attr_var_init.verify_attrs_loc = p; - } - Err(_) => - panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"), - } - - let project_attrs_src = ListingSource::User; - - match compile_special_form( - self, - Stream::from(PROJECT_ATTRS), - project_attrs_src, - ) - { - Ok(p) => { - self.machine_st.attr_var_init.project_attrs_loc = p; - } - Err(e) => - panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS: {}", e), - } - } - fn compile_scryerrc(&mut self) { let mut path = match dirs_next::home_dir() { Some(path) => path, @@ -177,7 +144,8 @@ impl Machine { compile_user_module(self, file_src, rc_src); } } -*/ + */ + #[cfg(test)] pub fn reset(&mut self) { self.current_input_stream = readline::input_stream(); @@ -289,12 +257,62 @@ impl Machine { self.machine_st[temp_v!(1)] = list_addr; - // WAS: - // self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("$repl"), 1)); - self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("repl"), 0)); } + fn configure_modules(&mut self) { + fn update_call_n_indices(loader: &Module, target_module: &mut Module) { + for arity in 1 .. 66 { + let key = (clause_name!("call"), arity); + + match loader.code_dir.get(&key).cloned() { + Some(src_code_index) => { + let target_code_index = target_module.code_dir + .entry(key.clone()) + .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined)); + + target_code_index.set(src_code_index.get()); + } + None => { + unreachable!(); + } + } + } + } + + if let Some(loader) = self.indices.modules.swap_remove(&clause_name!("loader")) { + if let Some(builtins) = self.indices.modules.get_mut(&clause_name!("builtins")) { + // Import loader's exports into the builtins module so they will be + // implicitly included in every further module. + load_module( + &mut builtins.code_dir, + &mut builtins.op_dir, + &mut builtins.meta_predicates, + &CompilationTarget::Module(clause_name!("builtins")), + &loader, + ); + + for export in &loader.module_decl.exports { + builtins.module_decl.exports.push(export.clone()); + } + + for arity in 10 .. 66 { + builtins.module_decl.exports.push( + ModuleExport::PredicateKey((clause_name!("call"), arity)), + ); + } + } + + for (_, target_module) in self.indices.modules.iter_mut() { + update_call_n_indices(&loader, target_module); + } + + self.indices.modules.insert(clause_name!("loader"), loader); + } else { + unreachable!() + } + } + pub fn new(user_input: Stream, user_output: Stream) -> Self { use crate::ref_thread_local::RefThreadLocal; @@ -356,32 +374,16 @@ impl Machine { ), ).unwrap(); - if let Some(loader) = wam.indices.modules.swap_remove(&clause_name!("loader")) { - if let Some(builtins) = wam.indices.modules.get_mut(&clause_name!("builtins")) { - // Import loader's exports into the builtins module so they will be - // implicitly included every further module. - load_module( - &mut builtins.code_dir, - &mut builtins.op_dir, - &mut builtins.meta_predicates, - &CompilationTarget::Module(clause_name!("builtins")), - &loader, - ); - - for export in &loader.module_decl.exports { - builtins.module_decl.exports.push(export.clone()); - } - } + wam.configure_modules(); + 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, &CompilationTarget::User, - &loader, + loader, ); - - wam.indices.modules.insert(clause_name!("loader"), loader); } else { unreachable!() } diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index a6e3f1e3..ab82b1f9 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -401,7 +401,7 @@ fn setup_meta_predicate<'a>( } 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)) + Ok((load_state.compilation_target.module_name(), name, meta_specs)) } _ => { Err(CompilationError::InvalidMetaPredicateDecl) From 222be9cf6cd2b10bed4ed43076d2984f220bfc7a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 4 Feb 2021 20:51:55 -0700 Subject: [PATCH 031/137] modify rightmost_power/2 to ignore module qualification on (^)/2 (#794) --- src/lib/builtins.pl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index fa3844cb..889977d2 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -665,8 +665,11 @@ iterate_variants([V-Solution|GroupSolutions], V, Solution) :- iterate_variants([_|GroupSolutions], Ws, Solution) :- iterate_variants(GroupSolutions, Ws, Solution). + rightmost_power(Term, FinalTerm, Xs) :- - ( Term = X ^ Y + ( ( Term = X ^ Y + ; Term = _ : X ^ Y + ) -> ( var(Y) -> FinalTerm = Y, Xs = [X] ; Xs = [X | Xss], rightmost_power(Y, FinalTerm, Xss) ) @@ -674,11 +677,11 @@ rightmost_power(Term, FinalTerm, Xs) :- ). -% :- meta_predicate findall_with_existential(?, 0, ?, ?, ?). - findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) :- ( nonvar(Goal), - Goal = _ ^ _ -> + ( Goal = _ ^ _ + ; Goal = _ : (_ ^ _) + ) -> rightmost_power(Goal, Goal1, ExistentialVars0), term_variables(ExistentialVars0, ExistentialVars), sort(Witnesses0, Witnesses1), From 804858d736ef358a7615b3c277abab1fe4018a58 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 4 Feb 2021 21:02:34 -0700 Subject: [PATCH 032/137] remove defunct reset function (#782) --- src/machine/mod.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 9c6acbb3..56d8a704 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -146,13 +146,6 @@ impl Machine { } */ - #[cfg(test)] - pub fn reset(&mut self) { - self.current_input_stream = readline::input_stream(); - self.policies.cut_policy = Box::new(DefaultCutPolicy {}); - 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) { From 2d7f31a60d9376e2c06e168f40d8d7ed50e182f9 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 02:16:14 -0700 Subject: [PATCH 033/137] implement dynamic, multifile, and discontiguous properties and callable type checking for predicate_property/2 --- src/clause_types.rs | 9 +++ src/loader.pl | 25 ++++++-- src/machine/loader.rs | 103 +++++++++++++++++++++++++++++++++ src/machine/machine_indices.rs | 5 +- src/machine/mod.rs | 11 +++- src/write.rs | 10 +++- 6 files changed, 154 insertions(+), 9 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 435e1182..ac431691 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -400,6 +400,12 @@ impl SystemClauseType { clause_name!("$cpp_meta_predicate_property"), &SystemClauseType::REPL(REPLCodePtr::BuiltInProperty) => clause_name!("$cpp_built_in_property"), + &SystemClauseType::REPL(REPLCodePtr::DynamicProperty) => + clause_name!("$cpp_dynamic_property"), + &SystemClauseType::REPL(REPLCodePtr::MultifileProperty) => + clause_name!("$cpp_multifile_property"), + &SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty) => + clause_name!("$cpp_discontiguous_property"), &SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates) => clause_name!("$compile_pending_predicates"), &SystemClauseType::Close => clause_name!("$close"), @@ -773,6 +779,9 @@ impl SystemClauseType { ("$prolog_lc_stream", 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextStream)), ("$cpp_meta_predicate_property", 4) => Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)), ("$cpp_built_in_property", 2) => Some(SystemClauseType::REPL(REPLCodePtr::BuiltInProperty)), + ("$cpp_dynamic_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DynamicProperty)), + ("$cpp_multifile_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::MultifileProperty)), + ("$cpp_discontiguous_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty)), ("$compile_pending_predicates", 1) => Some(SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates)), _ => None, } diff --git a/src/loader.pl b/src/loader.pl index 853842fb..e7bc3fa4 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -336,6 +336,13 @@ check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) '$cpp_meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm). check_predicate_property(built_in, _, Name, Arity, built_in) :- '$cpp_built_in_property'(Name, Arity). +check_predicate_property(dynamic, Module, Name, Arity, dynamic) :- + '$cpp_dynamic_property'(Module, Name, Arity). +check_predicate_property(multifile, Module, Name, Arity, multifile) :- + '$cpp_multifile_property'(Module, Name, Arity). +check_predicate_property(discontiguous, Module, Name, Arity, multifile) :- + '$cpp_discontiguous_property'(Module, Name, Arity). + extract_predicate_property(Property, PropertyType) :- @@ -356,12 +363,20 @@ predicate_property(Callable, Property) :- ; Callable =.. [(:), Module, Callable0], atom(Module) -> functor(Callable0, Name, Arity), - extract_predicate_property(Property, PropertyType), - check_predicate_property(PropertyType, Module, Name, Arity, Property) + ( atom(Name), + Name \== [] -> + extract_predicate_property(Property, PropertyType), + check_predicate_property(PropertyType, Module, Name, Arity, Property) + ; type_error(callable, Callable0, predicate_property/2) + ) ; functor(Callable, Name, Arity), - extract_predicate_property(Property, PropertyType), - load_context(Module), - check_predicate_property(PropertyType, Module, Name, Arity, Property) + ( atom(Name), + Name \== [] -> + extract_predicate_property(Property, PropertyType), + load_context(Module), + check_predicate_property(PropertyType, Module, Name, Arity, Property) + ; type_error(callable, Callable, predicate_property/2) + ) ). diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 6687b545..802fa53e 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -549,6 +549,7 @@ impl<'a> Drop for LoadState<'a> { } } } + // TODO: necessary? unnecessary? // self.wam.code_repo.code.truncate(self.retraction_info.orig_code_extent); } @@ -1543,6 +1544,108 @@ impl Machine { } } + pub(crate) + fn dynamic_property(&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 key = + self.machine_st.read_predicate_key( + self.machine_st[temp_v!(2)], + self.machine_st[temp_v!(3)], + ); + + let compilation_target = + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + match self.indices.get_predicate_skeleton( + &compilation_target, + &key, + ) { + Some(skeleton) => { + self.machine_st.fail = !skeleton.is_dynamic; + } + None => { + self.machine_st.fail = true; + } + } + } + + pub(crate) + fn multifile_property(&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 key = + self.machine_st.read_predicate_key( + self.machine_st[temp_v!(2)], + self.machine_st[temp_v!(3)], + ); + + let compilation_target = + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + match self.indices.get_predicate_skeleton( + &compilation_target, + &key, + ) { + Some(skeleton) => { + self.machine_st.fail = !skeleton.is_multifile; + } + None => { + self.machine_st.fail = true; + } + } + } + + pub(crate) + fn discontiguous_property(&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 key = + self.machine_st.read_predicate_key( + self.machine_st[temp_v!(2)], + self.machine_st[temp_v!(3)], + ); + + let compilation_target = + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + match self.indices.get_predicate_skeleton( + &compilation_target, + &key, + ) { + Some(skeleton) => { + self.machine_st.fail = !skeleton.is_discontiguous; + } + None => { + self.machine_st.fail = true; + } + } + } + pub(crate) fn builtin_property(&mut self) { let key = diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 869d4c92..0b0dc708 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -505,7 +505,6 @@ pub enum REPLCodePtr { AddDynamicPredicate, AddGoalExpansionClause, AddTermExpansionClause, - BuiltInProperty, ClauseToEvacuable, ConcludeLoad, DeclareModule, @@ -520,7 +519,11 @@ pub enum REPLCodePtr { PushLoadContext, PushLoadStatePayload, UseModule, + BuiltInProperty, MetaPredicateProperty, + MultifileProperty, + DiscontiguousProperty, + DynamicProperty, CompilePendingPredicates, UserAsserta, UserAssertz, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 56d8a704..239197ea 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -258,7 +258,7 @@ impl Machine { for arity in 1 .. 66 { let key = (clause_name!("call"), arity); - match loader.code_dir.get(&key).cloned() { + match loader.code_dir.get(&key) { Some(src_code_index) => { let target_code_index = target_module.code_dir .entry(key.clone()) @@ -482,6 +482,15 @@ impl Machine { REPLCodePtr::BuiltInProperty => { self.builtin_property(); } + REPLCodePtr::MultifileProperty => { + self.multifile_property(); + } + REPLCodePtr::DiscontiguousProperty => { + self.discontiguous_property(); + } + REPLCodePtr::DynamicProperty => { + self.dynamic_property(); + } REPLCodePtr::CompilePendingPredicates => { self.compile_pending_predicates(); } diff --git a/src/write.rs b/src/write.rs index bbb28e30..9079a2af 100644 --- a/src/write.rs +++ b/src/write.rs @@ -26,8 +26,6 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::AddGoalExpansionClause"), REPLCodePtr::AddTermExpansionClause => write!(f, "REPLCodePtr::AddTermExpansionClause"), - REPLCodePtr::BuiltInProperty => - write!(f, "REPLCodePtr::BuiltInProperty"), REPLCodePtr::UserAssertz => write!(f, "REPLCodePtr::UserAssertz"), REPLCodePtr::UserAsserta => @@ -64,6 +62,14 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::UseModule"), REPLCodePtr::MetaPredicateProperty => write!(f, "REPLCodePtr::MetaPredicateProperty"), + REPLCodePtr::BuiltInProperty => + write!(f, "REPLCodePtr::BuiltInProperty"), + REPLCodePtr::DynamicProperty => + write!(f, "REPLCodePtr::DynamicProperty"), + REPLCodePtr::MultifileProperty => + write!(f, "REPLCodePtr::MultifileProperty"), + REPLCodePtr::DiscontiguousProperty => + write!(f, "REPLCodePtr::DiscontiguousProperty"), REPLCodePtr::CompilePendingPredicates => write!(f, "REPLCodePtr::CompilePendingPredicates"), } From 81913a598721c2d7994e3b96ff72977fb0528f18 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Fri, 5 Feb 2021 20:59:47 +0100 Subject: [PATCH 034/137] Revert "preliminary workaround for #788" This reverts commit 164b9930640656700505188eab684b3575ab1fe8, which was made obsolete by 75a52f032b95fc74c1c3fa93996fd0f61775c28f. --- src/lib/clpz.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index b687354e..b7fa0ea7 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -6090,7 +6090,7 @@ distinct_goals_([flow_to(F,To)|Es], V) --> get_attr(To, lowlink, L2), L1 =\= L2 } -> { get_attr(To, value, N) }, - [clpz:neq_num(V, N)] + [neq_num(V, N)] ; [] ), distinct_goals_(Es, V). @@ -6611,7 +6611,7 @@ gcc_edge_goal(arc_to(_,_,V,F), Val) --> get_attr(Val, lowlink, L2), L1 =\= L2, get_attr(Val, value, Value) } -> - [clpz:neq_num(V, Value)] + [neq_num(V, Value)] ; [] ). From a228e46a393015546d6993e59bf178739c028aa6 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Fri, 5 Feb 2021 21:06:08 +0100 Subject: [PATCH 035/137] =?UTF-8?q?ENHANCED:=20Enable=20goal=20expansion?= =?UTF-8?q?=20for=20CLP(=E2=84=A4).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is now possible since #445 is resolved. --- src/lib/clpz.pl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index b7fa0ea7..ead80546 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -3068,12 +3068,10 @@ is_false(var(X)) :- nonvar(X). :- dynamic(goal_expansion/1). -% goal expansion is disabled for now, until #445 is resolved -% -% user:goal_expansion(Goal0, Goal) :- -% \+ goal_expansion(false), -% clpz_expandable(Goal0), -% clpz_expansion(Goal0, Goal). +user:goal_expansion(Goal0, Goal) :- + \+ goal_expansion(false), + clpz_expandable(Goal0), + clpz_expansion(Goal0, Goal). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% From 1bc8e9aebf148995662979bb1032a2c104ea1897 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 13:13:54 -0700 Subject: [PATCH 036/137] make load_context_path/2 handle .pl file extensions, remove commented out code --- src/clause_types.rs | 14 -------------- src/loader.pl | 31 +++++++++++++++---------------- src/machine/system_calls.rs | 7 ------- src/toplevel.pl | 6 +----- 4 files changed, 16 insertions(+), 42 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index ac431691..5a1aefe6 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -150,11 +150,6 @@ impl InlinedClauseType { #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum SystemClauseType { - // AbolishClause, - // AbolishModuleClause, - // AssertDynamicPredicateToBack, - // AssertDynamicPredicateToFront, - // AtEndOfExpansion, AtomChars, AtomCodes, AtomLength, @@ -189,8 +184,6 @@ pub enum SystemClauseType { DynamicModuleResolution(usize), EnqueueAttributeGoal, EnqueueAttributedVar, -// ExpandGoal, -// ExpandTerm, FetchGlobalVar, FetchGlobalVarWithOffset, FirstStream, @@ -207,16 +200,13 @@ pub enum SystemClauseType { GetAttrVarQueueDelimiter, GetAttrVarQueueBeyond, GetBValue, -// GetClause, GetContinuationChunk, -// GetModuleClause, GetNextDBRef, GetNextOpDBRef, IsPartialString, LookupDBRef, LookupOpDBRef, Halt, -// ModuleHeadIsDynamic, GetLiftedHeapFromOffset, GetLiftedHeapFromOffsetDiff, GetSCCCleaner, @@ -225,10 +215,7 @@ pub enum SystemClauseType { InstallInferenceCounter, LiftedHeapLength, LoadLibraryAsStream, - // ModuleAssertDynamicPredicateToFront, - // ModuleAssertDynamicPredicateToBack, ModuleExists, - // ModuleRetractClause, NextEP, NoSuchPredicate, NumberToChars, @@ -254,7 +241,6 @@ pub enum SystemClauseType { ResetContinuationMarker, ResetGlobalVarAtKey, ResetGlobalVarAtOffset, - // RetractClause, RestoreCutPolicy, SetCutPoint(RegType), SetInput, diff --git a/src/loader.pl b/src/loader.pl index e7bc3fa4..5f499c7d 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -296,11 +296,13 @@ use_module(Module, Exports) :- %% 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 + ; atom_concat(_, '.pl', Module) -> + Module = Path + ; atom_concat(Module, '.pl', Path) ). @@ -311,23 +313,21 @@ use_module(Module, Exports, Evacuable) :- ( 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) + ; '$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) + ; 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) ) - ; 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) ). @@ -387,7 +387,6 @@ strip_module_(M0, G0, M1, G1) :- ; M0 = M1, G0 = G1 ). - strip_module(Goal, M, G) :- strip_module_(_, Goal, M, G). diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 2ed49409..8762c764 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1098,13 +1098,6 @@ impl MachineState { 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)]; diff --git a/src/toplevel.pl b/src/toplevel.pl index 9513b671..5cf7d5d8 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -1,9 +1,5 @@ :- module('$toplevel', [argv/1, - copy_term/3, - predicate_property/2, - prolog_load_context/2]). - -:- use_module(library(loader)). + copy_term/3]). :- use_module(library(charsio)). :- use_module(library(iso_ext)). From 3fc2c4223b72ffb2c04cb8447f3cb58d21a34f72 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 17:12:25 -0700 Subject: [PATCH 037/137] delay premature set_switch_var_offset_* calls in retract_clause, add module resolution for asserta/assertz/retract/clause --- src/clause_types.rs | 22 +++------ src/lib/builtins.pl | 88 ++++++++++++++++----------------- src/machine/compile.rs | 54 +++++++++++++------- src/machine/loader.rs | 90 ++++++++++++++++++++++++---------- src/machine/machine_indices.rs | 6 +-- src/machine/mod.rs | 12 ++--- src/toplevel.pl | 6 +-- src/write.rs | 12 ++--- 8 files changed, 165 insertions(+), 125 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 5a1aefe6..ab83a3e9 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -358,11 +358,11 @@ impl SystemClauseType { clause_name!("$load_compiled_library"), &SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload) => clause_name!("$push_load_state_payload"), - &SystemClauseType::REPL(REPLCodePtr::UserAsserta) => + &SystemClauseType::REPL(REPLCodePtr::Asserta) => clause_name!("$asserta"), - &SystemClauseType::REPL(REPLCodePtr::UserAssertz) => + &SystemClauseType::REPL(REPLCodePtr::Assertz) => clause_name!("$assertz"), - &SystemClauseType::REPL(REPLCodePtr::UserRetract) => + &SystemClauseType::REPL(REPLCodePtr::Retract) => clause_name!("$retract_clause"), &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"), @@ -568,14 +568,11 @@ impl SystemClauseType { 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), ("$bind_from_register", 2) => Some(SystemClauseType::BindFromRegister), - // ("$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), @@ -608,8 +605,6 @@ impl SystemClauseType { ("$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), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), ("$get_byte", 2) => Some(SystemClauseType::GetByte), @@ -641,8 +636,6 @@ impl SystemClauseType { } ("$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_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset), ("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff), ("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes), @@ -656,8 +649,6 @@ impl SystemClauseType { ("$cpu_now", 1) => Some(SystemClauseType::CpuNow), ("$current_time", 1) => Some(SystemClauseType::CurrentTime), ("$module_exists", 1) => Some(SystemClauseType::ModuleExists), - // ("$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), @@ -692,7 +683,6 @@ impl SystemClauseType { ("$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), ("$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))), @@ -728,9 +718,9 @@ impl SystemClauseType { ("$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)), + ("$asserta", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Asserta)), + ("$assertz", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Assertz)), + ("$retract_clause", 4) => Some(SystemClauseType::REPL(REPLCodePtr::Retract)), ("$variant", 2) => Some(SystemClauseType::Variant), ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions), ("$write_term", 7) => Some(SystemClauseType::WriteTerm), diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 889977d2..6cd87ad9 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -742,13 +742,16 @@ setof(Template, Goal, Solution) :- ). '$module_clause'(H, B, Module) :- - ( 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)) + ; '$no_such_predicate'(Module, H) -> + '$fail' ; '$head_is_dynamic'(Module, H) -> '$clause_body_is_valid'(B), - Module:'$clause'(H, B) %%TODO: how do we show this exists? + Module:'$clause'(H, B) ; throw(error(permission_error(access, private_procedure, Name/Arity), clause/2)) ) @@ -781,24 +784,19 @@ clause(H, B) :- ; throw(error(type_error(callable, H), clause/2)) ). -call_module_asserta(Head, Body, Name, Arity, Module) :- +call_asserta(Head, Body, Name, Arity, Module) :- '$clause_body_is_valid'(Body), - functor(VarHead, Name, Arity), - 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), - '$asserta'(Head, Body, Name, Arity). + functor(_, Name, Arity), + '$asserta'(Head, Body, Name, Arity, Module). module_asserta_clause(Head, Body, Module) :- - ( var(Head) -> throw(error(instantiation_error, asserta/1)) + ( 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) + ( '$head_is_dynamic'(Module, Head) -> + call_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)) @@ -815,9 +813,9 @@ asserta_clause(Head, Body) :- arg(2, Head, F), module_asserta_clause(F, Body, Module) ; '$no_such_predicate'(user, Head) -> - call_asserta(Head, Body, Name, Arity) + call_asserta(Head, Body, Name, Arity, user) ; '$head_is_dynamic'(user, Head) -> - call_asserta(Head, Body, Name, Arity) + call_asserta(Head, Body, Name, Arity, user) ; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1)) ) ; throw(error(type_error(callable, Head), asserta/1)) @@ -826,18 +824,12 @@ asserta_clause(Head, Body) :- asserta(Clause) :- ( Clause \= (_ :- _) -> Head = Clause, - Body = true, asserta_clause(Head, Body) + 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), builtins:clause(Module:VarHead, VarBody), Clauses), - '$module_assertz'((Head :- Body), Clauses, Name, Arity, Module). - module_assertz_clause(Head, Body, Module) :- ( var(Head) -> throw(error(instantiation_error, assertz/1)) @@ -845,17 +837,18 @@ module_assertz_clause(Head, Body, Module) :- 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)) + call_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) :- + +call_assertz(Head, Body, Name, Arity, Module) :- '$clause_body_is_valid'(Body), - functor(VarHead, Name, Arity), - '$assertz'(Head, Body, Name, Arity). + functor(_, Name, Arity), + '$assertz'(Head, Body, Name, Arity, Module). assertz_clause(Head, Body) :- ( var(Head) -> @@ -863,16 +856,17 @@ assertz_clause(Head, Body) :- ; 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)) + ( 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, user) + ; '$head_is_dynamic'(user, Head) -> + call_assertz(Head, Body, Name, Arity, user) + ; throw(error(permission_error(modify, static_procedure, Name/Arity), + assertz/1)) ) ; throw(error(type_error(callable, Head), assertz/1)) ). @@ -889,18 +883,18 @@ assertz(Clause) :- module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :- functor(VarHead, Name, Arity), - findall((VarHead :- VarBody), builtins:clause(Module:VarHead, VarBody), Clauses1), + findall((VarHead :- VarBody), Module:clause(Module:VarHead, VarBody), Clauses1), first_match_index(Clauses1, (Head :- Body), 0, N), ( Clauses0 == [] -> ! ; true ), - '$module_retract_clause'(Name, Arity, N, Clauses1, Module). + '$retract_clause'(Name, Arity, N, 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), builtins:clause(Module:Head, Body), Clauses), + findall((Head :- Body), Module:clause(Module:Head, Body), Clauses), module_retract_clauses(Clauses, Head, Body, Name, Arity, Module). retract_module_clause(Head, Body, Module) :- @@ -909,9 +903,9 @@ retract_module_clause(Head, Body, Module) :- ; functor(Head, Name, Arity), atom(Name), Name \== '.' -> - ( '$module_head_is_dynamic'(Head, Module) -> - call_module_retract(Head, Body, Name, Arity, Module) - ; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1)) + ( '$head_is_dynamic'(Module, Head) -> + 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)) ). @@ -932,7 +926,7 @@ retract_clauses([Clause | Clauses0], Head, Body, Name, Arity) :- ( Clauses0 == [] -> ! ; true ), - '$retract_clause'(Name, Arity, N). + '$retract_clause'(Name, Arity, N, user). retract_clauses([_ | Clauses0], Head, Body, Name, Arity) :- retract_clauses(Clauses0, Head, Body, Name, Arity). diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 2d05ae34..a9ab5108 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1448,13 +1448,6 @@ impl<'a> LoadState<'a> { } } - set_switch_var_offset( - code, - later_indexing_loc, - lower_bound_clause_start - later_indexing_loc, - &mut self.retraction_info, - ); - result = merge_indexed_subsequences( code, skeleton, @@ -1470,15 +1463,15 @@ impl<'a> LoadState<'a> { &mut skeleton.clauses[lower_bound ..], &mut self.retraction_info, ); - } - _ => { - set_switch_var_offset_to_choice_instr( + + set_switch_var_offset( code, - target_indexing_loc, - lower_bound_clause_start - target_indexing_loc, + later_indexing_loc, + lower_bound_clause_start - later_indexing_loc, &mut self.retraction_info, ); - + } + _ => { result = merge_indexed_subsequences( code, skeleton, @@ -1494,6 +1487,13 @@ impl<'a> LoadState<'a> { &mut skeleton.clauses[lower_bound ..], &mut self.retraction_info, ); + + set_switch_var_offset_to_choice_instr( + code, + target_indexing_loc, + lower_bound_clause_start - target_indexing_loc, + &mut self.retraction_info, + ); } }; @@ -1581,6 +1581,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { fn compile_clause_clauses>( &mut self, key: PredicateKey, + compilation_target: CompilationTarget, clause_clauses: ClauseIter, append_or_prepend: AppendOrPrepend, ) -> Result<(), SessionError> { @@ -1596,9 +1597,19 @@ impl<'a, TS: TermStream> Loader<'a, TS> { ) }); - let compilation_target = mem::replace( + let clause_clause_compilation_target = + match compilation_target { + CompilationTarget::User => { + CompilationTarget::Module(clause_name!("builtins")) + } + _ => { + compilation_target.clone() + } + }; + + let old_compilation_target = mem::replace( &mut self.load_state.compilation_target, - CompilationTarget::Module(clause_name!("builtins")), + clause_clause_compilation_target, ); let mut clause_clause_locs = sdeq![]; @@ -1615,7 +1626,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { ); if let Err(e) = result { - self.load_state.compilation_target = compilation_target; + self.load_state.compilation_target = old_compilation_target; return Err(e); } } @@ -1676,7 +1687,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - self.load_state.compilation_target = compilation_target; + self.load_state.compilation_target = old_compilation_target; Ok(()) } @@ -1704,7 +1715,14 @@ impl<'a, TS: TermStream> Loader<'a, TS> { if is_dynamic { let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter(); - self.compile_clause_clauses(key, iter, AppendOrPrepend::Append)?; + let compilation_target = self.load_state.compilation_target.clone(); + + self.compile_clause_clauses( + key, + compilation_target, + iter, + AppendOrPrepend::Append, + )?; } Ok(self.predicates.clear()) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 802fa53e..5dbb5ba3 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1360,14 +1360,26 @@ impl Machine { } 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)], - ); + fn compile_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 module_name = atom_from!( + self.machine_st, + self.machine_st.store(self.machine_st.deref( + self.machine_st[temp_v!(5)] + )) + ); + + let compilation_target = + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + let compile_assert = || { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); let head = loader.read_term_from_heap(temp_v!(1))?; @@ -1384,23 +1396,28 @@ impl Machine { loader.incremental_compile_clause( key.clone(), asserted_clause, - CompilationTarget::User, + compilation_target.clone(), 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, + &compilation_target, &key, ).map(|skeleton| skeleton.is_dynamic = true); - loader.compile_clause_clauses(key, std::iter::once((head, body)), append_or_prepend)?; + loader.compile_clause_clauses( + key, + compilation_target, + std::iter::once((head, body)), + append_or_prepend, + )?; LiveTermStream::evacuate(loader) }; - match compile_user_assert() { + match compile_assert() { Ok(_) => { } Err(e) => { @@ -1416,7 +1433,7 @@ impl Machine { } pub(crate) - fn retract_user_clause(&mut self) { + fn retract_clause(&mut self) { let key = self.machine_st.read_predicate_key( self.machine_st[temp_v!(1)], @@ -1436,18 +1453,44 @@ impl Machine { unreachable!() }; - let retract_user_clause = || { + let module_name = atom_from!( + self.machine_st, + self.machine_st.store(self.machine_st.deref( + self.machine_st[temp_v!(4)] + )) + ); + + let compilation_target = + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + let clause_clause_compilation_target = + match &compilation_target { + CompilationTarget::User => { + CompilationTarget::Module(clause_name!("builtins")) + } + _ => { + compilation_target.clone() + } + }; + + let retract_clause = || { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); + loader.load_state.compilation_target = compilation_target; + 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) + loader.load_state.wam.indices.modules + .get(&clause_clause_compilation_target.module_name()) + .map(|module| module.clause_assert_margin) .unwrap(); let target_pos = match loader.load_state.wam.indices.get_predicate_skeleton( - &CompilationTarget::Module(clause_name!("builtins")), + &clause_clause_compilation_target, &(clause_name!("$clause"), 2), ) { Some(skeleton) => { @@ -1463,8 +1506,9 @@ impl Machine { }); if result < clause_assert_margin { - loader.load_state.wam.indices.modules.get_mut(&clause_name!("builtins")) - .map(|builtins| builtins.clause_assert_margin -= 1); + loader.load_state.wam.indices.modules + .get_mut(&clause_clause_compilation_target.module_name()) + .map(|module| module.clause_assert_margin -= 1); } result @@ -1474,19 +1518,13 @@ impl Machine { } }; - - let compilation_target = mem::replace( - &mut loader.load_state.compilation_target, - CompilationTarget::Module(clause_name!("builtins")), - ); - + loader.load_state.compilation_target = clause_clause_compilation_target; 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() { + match retract_clause() { Ok(_) => { } Err(e) => { diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 0b0dc708..0812c67e 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -525,9 +525,9 @@ pub enum REPLCodePtr { DiscontiguousProperty, DynamicProperty, CompilePendingPredicates, - UserAsserta, - UserAssertz, - UserRetract, + Asserta, + Assertz, + Retract, } #[derive(Debug, Clone, PartialEq)] diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 239197ea..800715e4 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -494,14 +494,14 @@ impl Machine { REPLCodePtr::CompilePendingPredicates => { self.compile_pending_predicates(); } - REPLCodePtr::UserAssertz => { - self.compile_user_assert(AppendOrPrepend::Append); + REPLCodePtr::Assertz => { + self.compile_assert(AppendOrPrepend::Append); } - REPLCodePtr::UserAsserta => { - self.compile_user_assert(AppendOrPrepend::Prepend); + REPLCodePtr::Asserta => { + self.compile_assert(AppendOrPrepend::Prepend); } - REPLCodePtr::UserRetract => { - self.retract_user_clause(); + REPLCodePtr::Retract => { + self.retract_clause(); } } diff --git a/src/toplevel.pl b/src/toplevel.pl index 5cf7d5d8..09f28545 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -14,15 +14,15 @@ '$repl'([_|Args0]) :- \+ argv(_), ( append(Args1, ["--"|Args2], Args0) -> - asserta(argv(Args2)), + asserta('$toplevel':argv(Args2)), Args = Args1 - ; asserta(argv([])), + ; asserta('$toplevel':argv([])), Args = Args0 ), delegate_task(Args, []), repl. '$repl'(_) :- - ( \+ argv(_) -> asserta(argv([])) + ( \+ argv(_) -> asserta('$toplevel':argv([])) ; true ), repl. diff --git a/src/write.rs b/src/write.rs index 9079a2af..963e2599 100644 --- a/src/write.rs +++ b/src/write.rs @@ -26,12 +26,12 @@ impl fmt::Display for REPLCodePtr { 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::Assertz => + write!(f, "REPLCodePtr::Assertz"), + REPLCodePtr::Asserta => + write!(f, "REPLCodePtr::Asserta"), + REPLCodePtr::Retract => + write!(f, "REPLCodePtr::Retract"), REPLCodePtr::ClauseToEvacuable => write!(f, "REPLCodePtr::ClauseToEvacuable"), REPLCodePtr::ConcludeLoad => From 62419e975f9a923c38575fa6771c7e37004e04c9 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 17:16:42 -0700 Subject: [PATCH 038/137] bootstrap the top-level by calling ''/1 as in master (#790) --- src/machine/mod.rs | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 800715e4..d3dc04d7 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -250,7 +250,7 @@ impl Machine { self.machine_st[temp_v!(1)] = list_addr; - self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("repl"), 0)); + self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("$repl"), 1)); } fn configure_modules(&mut self) { @@ -527,23 +527,6 @@ impl Machine { self.machine_st.backtrack(); } } - /* - 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.code_repo.cached_query = cached_query; - - if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p { - break; - } - */ - } - */ _ => { break; } @@ -624,22 +607,12 @@ impl MachineState { } fn backtrack(&mut self) { - // 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); - /* - 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 { @@ -651,15 +624,6 @@ impl MachineState { CodePtr::Local(LocalCodePtr::Halt) | CodePtr::REPL(..) => { return false; } - /* - CodePtr::DynamicTransaction(..) => { - // prevent use of dynamic transactions from - // succeeding in expansions. self.fail will be toggled - // back to false later. - self.fail = true; - return false; - } - */ _ => { } } From bbbf95705b6d0e8063a152bb4be15ff1f70134f9 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 18:06:27 -0700 Subject: [PATCH 039/137] implement abolish/1 --- src/clause_types.rs | 10 +-- src/lib/builtins.pl | 81 +++++++++-------- src/machine/loader.rs | 69 ++++++++++++++ src/machine/machine_indices.rs | 1 + src/machine/mod.rs | 3 + src/machine/system_calls.rs | 160 +-------------------------------- src/write.rs | 2 + 7 files changed, 125 insertions(+), 201 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index ab83a3e9..76c70e74 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -310,11 +310,6 @@ pub enum SystemClauseType { 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::AtomChars => clause_name!("$atom_chars"), &SystemClauseType::AtomCodes => clause_name!("$atom_codes"), &SystemClauseType::AtomLength => clause_name!("$atom_length"), @@ -394,6 +389,8 @@ impl SystemClauseType { clause_name!("$cpp_discontiguous_property"), &SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates) => clause_name!("$compile_pending_predicates"), + &SystemClauseType::REPL(REPLCodePtr::AbolishClause) => + clause_name!("$abolish_clause"), &SystemClauseType::Close => clause_name!("$close"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), @@ -561,7 +558,8 @@ impl SystemClauseType { pub fn from(name: &str, arity: usize) -> Option { match (name, arity) { - // ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause), + ("$abolish_clause", 3) => + Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)), ("$add_dynamic_predicate", 3) => Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate)), ("$add_goal_expansion_clause", 4) => diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 6cd87ad9..2be9c783 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -836,7 +836,9 @@ module_assertz_clause(Head, Body, Module) :- ; functor(Head, Name, Arity), atom(Name), Name \== '.' -> - ( '$head_is_dynamic'(Module, Head) -> + ( '$no_such_predicate'(Module, Head) -> + call_assertz(Head, Body, Name, Arity, Module) + ; '$head_is_dynamic'(Module, Head) -> call_assertz(Head, Body, Name, Arity, Module) ; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1)) @@ -883,7 +885,7 @@ assertz(Clause) :- module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :- functor(VarHead, Name, Arity), - findall((VarHead :- VarBody), Module:clause(Module:VarHead, VarBody), Clauses1), + findall((VarHead :- VarBody), Module:'$clause'(VarHead, VarBody), Clauses1), first_match_index(Clauses1, (Head :- Body), 0, N), ( Clauses0 == [] -> ! ; true @@ -894,7 +896,7 @@ 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), Module:clause(Module:Head, Body), Clauses), + findall((Head :- Body), Module:'$clause'(Head, Body), Clauses), module_retract_clauses(Clauses, Head, Body, Name, Arity, Module). retract_module_clause(Head, Body, Module) :- @@ -904,7 +906,10 @@ retract_module_clause(Head, Body, Module) :- atom(Name), Name \== '.' -> ( '$head_is_dynamic'(Module, Head) -> - call_module_retract(Head, Body, Name, Arity, Module) + ( Module == user -> + call_retract(Head, Body, Name, Arity) + ; 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)) @@ -941,16 +946,16 @@ retract_clause(Head, Body) :- ; 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)) + ( 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)) ). @@ -972,21 +977,21 @@ module_abolish(Pred, Module) :- ( 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) -> + ( '$head_is_dynamic'(Module, Head) -> + '$abolish_clause'(Module, 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, Module:Pred), abolish/1)) + ; throw(error(type_error(predicate_indicator, Module:Pred), abolish/1)) ). abolish(Pred) :- @@ -1000,17 +1005,19 @@ abolish(Pred) :- ; 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'(user, Head) -> + true + ; '$head_is_dynamic'(user, Head) -> + '$abolish_clause'(user, Name, Arity) + ; throw(error(permission_error(modify, static_procedure, Pred), abolish/1)) + ) ) ; throw(error(type_error(integer, Arity), abolish/1)) ) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 5dbb5ba3..eae4ab57 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1432,6 +1432,75 @@ impl Machine { } } + pub(crate) + fn abolish_clause(&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 key = + self.machine_st.read_predicate_key( + self.machine_st[temp_v!(2)], + self.machine_st[temp_v!(3)], + ); + + let compilation_target = + match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); + loader.load_state.compilation_target = compilation_target; + + match loader.load_state.wam.indices.get_predicate_skeleton( + &loader.load_state.compilation_target, + &key + ) { + Some(skeleton) => { + skeleton.clauses.clear(); + skeleton.clause_clause_locs.clear(); + } + _ => { + unreachable!(); + } + } + + let code_index = loader.load_state.get_or_insert_code_index(key); + code_index.set(IndexPtr::DynamicUndefined); + + match loader.load_state.compilation_target { + CompilationTarget::User => { + loader.load_state.compilation_target = + CompilationTarget::Module(clause_name!("builtins")); + } + _ => { + } + }; + + match loader.load_state.wam.indices.get_predicate_skeleton( + &loader.load_state.compilation_target, + &(clause_name!("$clause"), 2), + ) { + Some(skeleton) => { + skeleton.clauses.clear(); + skeleton.clause_clause_locs.clear(); + } + _ => { + unreachable!(); + } + } + + let clause_clause_code_index = loader.load_state.get_or_insert_code_index( + (clause_name!("$clause"), 2), + ); + + clause_clause_code_index.set(IndexPtr::DynamicUndefined); + } + pub(crate) fn retract_clause(&mut self) { let key = diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 0812c67e..7a183ecd 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -525,6 +525,7 @@ pub enum REPLCodePtr { DiscontiguousProperty, DynamicProperty, CompilePendingPredicates, + AbolishClause, Asserta, Assertz, Retract, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index d3dc04d7..0b0439cd 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -503,6 +503,9 @@ impl Machine { REPLCodePtr::Retract => { self.retract_clause(); } + REPLCodePtr::AbolishClause => { + self.abolish_clause(); + } } self.machine_st.p = CodePtr::Local(p); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 8762c764..6990ed40 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -792,22 +792,6 @@ impl MachineState { 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::AbolishModuleClause => { - let p = self.cp; - let trans_type = DynamicTransactionType::ModuleAbolish; - - self.p = CodePtr::DynamicTransaction(trans_type, p); - return Ok(()); - } - */ &SystemClauseType::BindFromRegister => { let reg = self.store(self.deref(self[temp_v!(2)])); let n = @@ -835,23 +819,6 @@ impl MachineState { self.fail = true; } - /* - &SystemClauseType::AssertDynamicPredicateToFront => { - let p = self.cp; - let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front); - - self.p = CodePtr::DynamicTransaction(trans_type, p); - return Ok(()); - } - &SystemClauseType::AssertDynamicPredicateToBack => { - // let p = self.cp; - // let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Back); - - // 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) => { @@ -1755,15 +1722,7 @@ impl MachineState { } else if self.fail { return Ok(()); } - }/* - _ => { - let stub = MachineError::functor_stub(clause_name!("get_char"), 2); - let err = MachineError::representation_error(RepFlag::Character); - let err = self.error_form(err, stub); - - return Err(err); - }*/ - } + } } } } &SystemClauseType::NumberToChars => { @@ -1859,22 +1818,6 @@ impl MachineState { } } } - /* - &SystemClauseType::ModuleAssertDynamicPredicateToFront => { - let p = self.cp; - let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Front); - - self.p = CodePtr::DynamicTransaction(trans_type, p); - return Ok(()); - } - &SystemClauseType::ModuleAssertDynamicPredicateToBack => { - let p = self.cp; - let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Back); - - 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()); @@ -2732,14 +2675,7 @@ impl MachineState { } else if self.fail { return Ok(()); } - }/* - _ => { - let stub = MachineError::functor_stub(clause_name!("get_char"), 2); - let err = MachineError::representation_error(RepFlag::Character); - let err = self.error_form(err, stub); - - return Err(err); - }*/ + } } } } @@ -2857,98 +2793,6 @@ impl MachineState { self.unify(Addr::Char(c), a1); } -/* - &SystemClauseType::GetModuleClause => { - let module = self[temp_v!(3)]; - let head = self[temp_v!(1)]; - - let module = match self.store(self.deref(module)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(module, _) = &self.heap[h] { - module.clone() - } else { - unreachable!() - } - } - _ => { - self.fail = true; - return Ok(()); - } - }; - - let subsection = match self.store(self.deref(head)) { - Addr::Str(s) => match &self.heap[s] { - &HeapCellValue::NamedStr(arity, ref name, ..) => { - indices.get_clause_subsection(module, name.clone(), arity) - } - _ => { - unreachable!() - } - }, - Addr::Con(h) => { - if let HeapCellValue::Atom(name, _) = &self.heap[h] { - indices.get_clause_subsection(module, name.clone(), 0) - } else { - unreachable!() - } - } - - _ => { - unreachable!() - } - }; - - match subsection { - Some(dynamic_predicate_info) => { - self.execute_at_index( - 2, - dir_entry!(dynamic_predicate_info.clauses_subsection_p), - ); - - return Ok(()); - } - None => { - self.fail = true; - } - } - } - &SystemClauseType::ModuleHeadIsDynamic => { - let module = self[temp_v!(2)]; - let head = self[temp_v!(1)]; - - let module = match self.store(self.deref(module)) { - Addr::Con(h) if self.heap.atom_at(h) => - if let HeapCellValue::Atom(module, _) = &self.heap[h] { - module.clone() - } else { - unreachable!() - } - _ => { - self.fail = true; - return Ok(()); - } - }; - - self.fail = !match self.store(self.deref(head)) { - Addr::Str(s) => match &self.heap[s] { - &HeapCellValue::NamedStr(arity, ref name, ..) => { - indices.get_clause_subsection(module, name.clone(), arity) - .is_some() - } - _ => unreachable!(), - }, - Addr::Con(h) => { - if let HeapCellValue::Atom(name, _) = &self.heap[h] { - indices.get_clause_subsection(module, name.clone(), 0) - .is_some() - } else { - unreachable!() - } - } - _ => unreachable!(), - }; - } -*/ &SystemClauseType::HeadIsDynamic => { let module_name = atom_from!( self, diff --git a/src/write.rs b/src/write.rs index 963e2599..17944e9d 100644 --- a/src/write.rs +++ b/src/write.rs @@ -26,6 +26,8 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::AddGoalExpansionClause"), REPLCodePtr::AddTermExpansionClause => write!(f, "REPLCodePtr::AddTermExpansionClause"), + REPLCodePtr::AbolishClause => + write!(f, "REPLCodePtr::AbolishClause"), REPLCodePtr::Assertz => write!(f, "REPLCodePtr::Assertz"), REPLCodePtr::Asserta => From a104b35ceac4803da08300fd275e1a69ef734daf Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 18:40:13 -0700 Subject: [PATCH 040/137] gather initialization goals and call them once load succeeds (#792) --- src/clause_types.rs | 3 --- src/loader.pl | 17 ++++++++++++++--- src/machine/loader.rs | 16 ---------------- src/machine/machine_indices.rs | 1 - src/machine/mod.rs | 3 --- src/write.rs | 2 -- 6 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 76c70e74..6f412b78 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -387,8 +387,6 @@ impl SystemClauseType { clause_name!("$cpp_multifile_property"), &SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty) => clause_name!("$cpp_discontiguous_property"), - &SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates) => - clause_name!("$compile_pending_predicates"), &SystemClauseType::REPL(REPLCodePtr::AbolishClause) => clause_name!("$abolish_clause"), &SystemClauseType::Close => clause_name!("$close"), @@ -756,7 +754,6 @@ impl SystemClauseType { ("$cpp_dynamic_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DynamicProperty)), ("$cpp_multifile_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::MultifileProperty)), ("$cpp_discontiguous_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty)), - ("$compile_pending_predicates", 1) => Some(SystemClauseType::REPL(REPLCodePtr::CompilePendingPredicates)), _ => None, } } diff --git a/src/loader.pl b/src/loader.pl index 5f499c7d..fb9d6840 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -74,6 +74,16 @@ unload_evacuable(Evacuable) :- '$pop_load_state_payload'(Evacuable), '$pop_load_context'. +run_initialization_goals :- + prolog_load_context(module, Module), + ( predicate_property(Module:'$initialization_goals'(_), dynamic) -> + findall(Goal, '$call'(builtins:retract(Module:'$initialization_goals'(Goal))), Goals), + ( maplist(Module:call, Goals) -> + true + ; true %% initialization goals can fail without thwarting the load. + ) + ; true + ). file_load(Stream, Path) :- file_load(Stream, Path, _). @@ -83,6 +93,7 @@ file_load(Stream, Path, Evacuable) :- catch(loader:load_loop(Stream, Evacuable), E, (loader:unload_evacuable(Evacuable), throw(E))), + run_initialization_goals, '$pop_load_context'. @@ -91,6 +102,7 @@ load(Stream) :- catch(loader:load_loop(Stream, Evacuable), E, (loader:unload_evacuable(Evacuable), throw(E))), + run_initialization_goals, '$pop_load_context'. load_loop(Stream, Evacuable) :- @@ -237,9 +249,8 @@ compile_declaration(dynamic(Name/Arity), Evacuable) :- '$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). + assertz(Module:'$initialization_goals'(Goal)). + compile_clause(Clause, Evacuable, VNs) :- diff --git a/src/machine/loader.rs b/src/machine/loader.rs index eae4ab57..e7eb1165 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1789,22 +1789,6 @@ impl Machine { 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> { diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 7a183ecd..b6883e77 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -524,7 +524,6 @@ pub enum REPLCodePtr { MultifileProperty, DiscontiguousProperty, DynamicProperty, - CompilePendingPredicates, AbolishClause, Asserta, Assertz, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 0b0439cd..6a73369e 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -491,9 +491,6 @@ impl Machine { REPLCodePtr::DynamicProperty => { self.dynamic_property(); } - REPLCodePtr::CompilePendingPredicates => { - self.compile_pending_predicates(); - } REPLCodePtr::Assertz => { self.compile_assert(AppendOrPrepend::Append); } diff --git a/src/write.rs b/src/write.rs index 17944e9d..00538abb 100644 --- a/src/write.rs +++ b/src/write.rs @@ -72,8 +72,6 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::MultifileProperty"), REPLCodePtr::DiscontiguousProperty => write!(f, "REPLCodePtr::DiscontiguousProperty"), - REPLCodePtr::CompilePendingPredicates => - write!(f, "REPLCodePtr::CompilePendingPredicates"), } } } From 700778e574596dc80dceb5beae87d81c1f125f8a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 20:18:56 -0700 Subject: [PATCH 041/137] collate paths as atoms in loader.pl (#778) --- src/lib/sockets.pl | 2 +- src/loader.pl | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/lib/sockets.pl b/src/lib/sockets.pl index 108ac9b9..dd386a3b 100644 --- a/src/lib/sockets.pl +++ b/src/lib/sockets.pl @@ -15,7 +15,7 @@ parse_socket_options_(Option, OptionPair) :- parse_socket_options(Options, OptionValues, Stub) :- DefaultOptions = [alias-[], eof_action-eof_code, reposition-false, tls-false, type-text], - builtins:parse_options_list(Options, parse_socket_options_, DefaultOptions, OptionValues, Stub). + builtins:parse_options_list(Options, sockets:parse_socket_options_, DefaultOptions, OptionValues, Stub). socket_client_open(Addr, Stream, Options) :- ( var(Addr) -> diff --git a/src/loader.pl b/src/loader.pl index fb9d6840..2f5f70ff 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -300,8 +300,7 @@ use_module(Module, Exports) :- '$push_load_state_payload'(Evacuable), ( Exports == [] -> '$remove_module_exports'(Module, Evacuable) - ; - use_module(Module, Exports, Evacuable) + ; use_module(Module, Exports, Evacuable) ). @@ -317,14 +316,22 @@ load_context_path(Module, Path) :- ). +path_atom(Dir/File, Path) :- + must_be(atom, File), + !, + path_atom(Dir, DirPath), + foldl(builtins:atom_concat, ['/', DirPath], File, Path). +path_atom(Path, Path) :- + must_be(atom, 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? + ( path_atom(Library, LibraryPath) -> + ( '$load_compiled_library'(LibraryPath, Evacuable) -> %% TODO: What about Exports? true - ; '$load_library_as_stream'(Library, Stream, Path), + ; '$load_library_as_stream'(LibraryPath, Stream, Path), file_load(Stream, Path, Subevacuable), '$use_module'(Evacuable, Subevacuable, Exports) ) @@ -332,8 +339,8 @@ use_module(Module, Exports, Evacuable) :- instantiation_error(load/1) ; type_error(atom, Library, load/1) ) - ; ( atom(Module) -> - load_context_path(Module, Path), + ; ( path_atom(Module, ModulePath) -> + load_context_path(ModulePath, Path), open(Path, read, Stream), file_load(Stream, Path, Subevacuable), '$use_module'(Evacuable, Subevacuable, Exports) From bdb5df104a5904a041715dd3e53e1338624a5bf1 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 22:50:57 -0700 Subject: [PATCH 042/137] shed module names from arguments of the (->)/2, (,)/2, (;)/2 predicates --- src/lib/builtins.pl | 54 +++++++++++++++++++++++++++++++++++++++++++++ src/loader.pl | 8 +++---- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 2be9c783..588a12fe 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -243,15 +243,26 @@ call_or_cut(G, B, ErrorPI) :- call_or_cut(!, B) :- '$set_cp_by_default'(B). +call_or_cut(_:!, B) :- + '$set_cp_by_default'(B). call_or_cut((G1, G2), B) :- !, '$call_with_default_policy'(','(G1, G2, B)). +call_or_cut(_:(G1, G2), B) :- + !, + '$call_with_default_policy'(','(G1, G2, B)). call_or_cut((G1 ; G2), B) :- !, '$call_with_default_policy'(';'(G1, G2, B)). +call_or_cut(_:(G1 ; G2), B) :- + !, + '$call_with_default_policy'(';'(G1, G2, B)). call_or_cut((G1 -> G2), B) :- !, '$call_with_default_policy'(->(G1, G2, B)). +call_or_cut(_:(G1 -> G2), B) :- + !, + '$call_with_default_policy'(->(G1, G2, B)). call_or_cut(G, _) :- '$call_with_default_policy'(G). @@ -261,14 +272,26 @@ call_or_cut(G, _) :- !, '$call_with_default_policy'(','(G1, G2, B)), '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). +','(_:(G1, G2), G3, B) :- + !, + '$call_with_default_policy'(','(G1, G2, B)), + '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). ','((G1; G2), G3, B) :- !, '$call_with_default_policy'(';'(G1, G2, B)), '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). +','(_:(G1; G2), G3, B) :- + !, + '$call_with_default_policy'(';'(G1, G2, B)), + '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). ','((G1 -> G2), G3, B) :- !, '$call_with_default_policy'(->(G1, G2, B)), '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). +','(_:(G1 -> G2), G3, B) :- + !, + '$call_with_default_policy'(->(G1, G2, B)), + '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). ','(G1, G2, B) :- '$call_with_default_policy'(call_or_cut(G1, B, (',')/2)), '$call_with_default_policy'(call_or_cut(G2, B, (',')/2)). @@ -280,17 +303,33 @@ call_or_cut(G, _) :- ( '$call_with_default_policy'(','(G1, G2, B)) ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) ). +';'(_:(G1, G2), G3, B) :- + !, + ( '$call_with_default_policy'(','(G1, G2, B)) + ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ). ';'((G1; G2), G3, B) :- !, ( '$call_with_default_policy'(';'(G1, G2, B)) ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) ). +';'(_:(G1; G2), G3, B) :- + !, + ( '$call_with_default_policy'(';'(G1, G2, B)) + ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ). ';'((G1 -> G2), G3, B) :- !, ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) ). +';'(_:(G1 -> G2), G3, B) :- + !, + ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> + '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) + ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ). ';'(G1, G2, B) :- ( '$call_with_default_policy'(call_or_cut(G1, B, (;)/2)) ; '$call_with_default_policy'(call_or_cut(G2, B, (;)/2)) @@ -303,16 +342,31 @@ call_or_cut(G, _) :- ( '$call_with_default_policy'(','(G1, G2, B)) -> '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) ). +->(_:(G1, G2), G3, B) :- + !, + ( '$call_with_default_policy'(','(G1, G2, B)) -> + '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ). ->((G1 ; G2), G3, B) :- !, ( '$call_with_default_policy'(';'(G1, G2, B)) -> '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) ). +->(_:(G1 ; G2), G3, B) :- + !, + ( '$call_with_default_policy'(';'(G1, G2, B)) -> + '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ). ->((G1 -> G2), G3, B) :- !, ( '$call_with_default_policy'(->(G1, G2, B)) -> '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) ). +->(_:(G1 -> G2), G3, B) :- + !, + ( '$call_with_default_policy'(->(G1, G2, B)) -> + '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ). ->(G1, G2, B) :- ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) diff --git a/src/loader.pl b/src/loader.pl index 2f5f70ff..0ac97ac6 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -398,16 +398,16 @@ predicate_property(Callable, Property) :- ). -strip_module_(M0, G0, M1, G1) :- +strip_module(M0, G0, M1, G1) :- ( nonvar(G0), G0 = (MG1:G2) -> - strip_module_(MG1, G2, M1, G1) + strip_module(MG1, G2, M1, G1) ; M0 = M1, G0 = G1 ). -strip_module(Goal, M, G) :- - strip_module_(_, Goal, M, G). +strip_module(Goal, M, G) :- + strip_module(_, Goal, M, G). expand_subgoal(UnexpandedGoals, MS, Module, ExpandedGoals, HeadVars) :- From 49b1c1368e81555e88d82f6fb619563164d38778 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 5 Feb 2021 23:16:42 -0700 Subject: [PATCH 043/137] remove dynamic clause declaration for clause internal --- src/lib/builtins.pl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 588a12fe..4f2b1825 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -813,8 +813,6 @@ setof(Template, Goal, Solution) :- ). -:- dynamic('$clause'/2). - clause(H, B) :- ( var(H) -> throw(error(instantiation_error, clause/2)) From 3f950490f96b3918582073a5cf4bf54a875e3f34 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 6 Feb 2021 13:47:26 -0700 Subject: [PATCH 044/137] set rustyline to check the cursor position (#802), don't add .pl extension to files in loader.pl (#800) --- src/loader.pl | 5 +---- src/machine/system_calls.rs | 4 ++++ src/read.rs | 8 ++++++-- src/toplevel.pl | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index 0ac97ac6..ca157855 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -35,7 +35,6 @@ expand_term(Term, ExpandedTerm) :- ; Term = ExpandedTerm ). - term_expansion_list([], ExpandedTerms, ExpandedTerms). term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- expand_term(Term, ExpandedTerm0), @@ -310,9 +309,7 @@ use_module(Module, Exports) :- load_context_path(Module, Path) :- ( prolog_load_context(directory, CurrentDir) -> atom_concat(CurrentDir, Path, Module) - ; atom_concat(_, '.pl', Module) -> - Module = Path - ; atom_concat(Module, '.pl', Path) + ; Module = Path ). diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 6990ed40..03aa1244 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -3349,6 +3349,10 @@ impl MachineState { } } } + Addr::Char(c) => { + let atom = clause_name!(c.to_string(), self.atom_tbl); + self.stream_from_file_spec(atom, indices, &options)? + } Addr::PStrLocation(h, n) => { match &self.heap[h] { &HeapCellValue::PartialString(_, true) => { diff --git a/src/read.rs b/src/read.rs index ba975201..4ed74fbf 100644 --- a/src/read.rs +++ b/src/read.rs @@ -17,7 +17,7 @@ pub type PrologStream = ParsingStream; pub mod readline { use crate::machine::streams::Stream; use crate::rustyline::error::ReadlineError; - use crate::rustyline::{Cmd, Editor, KeyEvent}; + use crate::rustyline::{Cmd, Config, Editor, KeyEvent}; use std::io::{Cursor, Error, ErrorKind, Read}; static mut PROMPT: bool = false; @@ -46,7 +46,11 @@ pub mod readline { impl ReadlineStream { #[inline] pub fn new(pending_input: String) -> Self { - let mut rl = Editor::<()>::new(); + let config = Config::builder() + .check_cursor_position(true) + .build(); + + let mut rl = Editor::<()>::with_config(config); //Editor::<()>::new(); if let Some(mut path) = dirs_next::home_dir() { path.push(HISTORY_FILE); if path.exists() { diff --git a/src/toplevel.pl b/src/toplevel.pl index 09f28545..8ff02242 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -37,7 +37,8 @@ delegate_task([Arg0|Args], Goals0) :- ; member(Arg0, ["-v", "--version"]) -> print_version ; member(Arg0, ["-g", "--goal"]) -> gather_goal(g, Args, Goals0) ; atom_chars(Mod, Arg0), - catch(use_module(Mod), E, print_exception(E)) + catch(use_module(Mod), E, print_exception(E)), + nl ), delegate_task(Args, Goals0). @@ -122,7 +123,7 @@ instruction_match(Term, VarList) :- ( Item == user -> catch(load(user_input), E, print_exception_with_check(E)) ; - consult(Item) + submit_query_and_print_results(consult(Item), []) ) ; catch(type_error(atom, Item, repl/0), From b53ef148a096887370443487c1a2678ae3d33ee7 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:21:24 +0100 Subject: [PATCH 045/137] remove extern crate declaration and fix outfall (macros now need to be imported into scope) using use declarations in main.rs so that use paths don't need to be updated as well, this will be done in a later commit --- build.rs | 8 +- src/allocator.rs | 22 +- src/arithmetic.rs | 198 +- src/clause_types.rs | 248 +- src/codegen.rs | 189 +- src/debray_allocator.rs | 5 +- src/forms.rs | 144 +- src/heap_print.rs | 454 ++-- src/indexing.rs | 474 ++-- src/instructions.rs | 255 +- src/iterators.rs | 88 +- src/machine/arithmetic_ops.rs | 577 ++--- src/machine/attributed_variables.rs | 41 +- src/machine/compile.rs | 1245 +++++----- src/machine/load_state.rs | 454 ++-- src/machine/loader.rs | 1399 +++++------ src/machine/machine_errors.rs | 283 +-- src/machine/machine_indices.rs | 463 ++-- src/machine/machine_state.rs | 330 ++- src/machine/machine_state_impl.rs | 1529 +++++------- src/machine/mod.rs | 142 +- src/machine/preprocessor.rs | 423 ++-- src/machine/streams.rs | 707 ++---- src/machine/system_calls.rs | 3581 +++++++++++++-------------- src/main.rs | 63 +- 25 files changed, 5815 insertions(+), 7507 deletions(-) diff --git a/build.rs b/build.rs index aaa876ab..3cd4421d 100644 --- a/build.rs +++ b/build.rs @@ -15,15 +15,13 @@ fn find_prolog_files(libraries: &mut File, prefix: &str, current_dir: &Path) { 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 new_prefix = - prefix.to_owned() + file_name.to_str().unwrap() + "/"; + let new_prefix = prefix.to_owned() + file_name.to_str().unwrap() + "/"; find_prolog_files(libraries, &new_prefix, &entry); } } else if entry.is_file() { let ext = std::ffi::OsStr::new("pl"); if entry.extension() == Some(ext) { - let contain = - String::from_utf8(fs::read(&entry).unwrap()).unwrap(); + let contain = String::from_utf8(fs::read(&entry).unwrap()).unwrap(); let name = entry.file_stem().unwrap().to_str().unwrap(); let line = format!( @@ -47,7 +45,7 @@ fn main() { libraries .write_all( - b"ref_thread_local! { + b"ref_thread_local::ref_thread_local! { pub static managed LIBRARIES: IndexMap<&'static str, &'static str> = { let mut m = IndexMap::new();\n", ) diff --git a/src/allocator.rs b/src/allocator.rs index f2b2cd0c..c0e46da0 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1,4 +1,5 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::temp_v; use crate::fixtures::*; use crate::forms::*; @@ -14,8 +15,13 @@ pub trait Allocator<'a> { fn mark_anon_var(&mut self, _: Level, _: GenContext, _: &mut Vec) where Target: CompilationTarget<'a>; - fn mark_non_var(&mut self, _: Level, _: GenContext, _: &'a Cell, _: &mut Vec) - where + fn mark_non_var( + &mut self, + _: Level, + _: GenContext, + _: &'a Cell, + _: &mut Vec, + ) where Target: CompilationTarget<'a>; fn mark_reserved_var( &mut self, @@ -28,8 +34,14 @@ pub trait Allocator<'a> { _: bool, ) where Target: CompilationTarget<'a>; - fn mark_var(&mut self, _: Rc, _: Level, _: &'a Cell, _: GenContext, _: &mut Vec) - where + fn mark_var( + &mut self, + _: Rc, + _: Level, + _: &'a Cell, + _: GenContext, + _: &mut Vec, + ) where Target: CompilationTarget<'a>; fn reset(&mut self); @@ -47,7 +59,7 @@ pub trait Allocator<'a> { fn drain_var_data( &mut self, vs: VariableFixtures<'a>, - num_of_chunks: usize + num_of_chunks: usize, ) -> VariableFixtures<'a> { let mut perm_vs = VariableFixtures::new(); diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 1231dfa6..c3492f31 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -1,4 +1,5 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::{atom, clause_name}; use crate::clause_types::*; use crate::fixtures::*; @@ -267,9 +268,7 @@ impl<'a> ArithmeticEvaluator<'a> { fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> { match c { - &Constant::Fixnum(n) => self - .interm - .push(ArithmeticTerm::Number(Number::Fixnum(n))), + &Constant::Fixnum(n) => self.interm.push(ArithmeticTerm::Number(Number::Fixnum(n))), &Constant::Integer(ref n) => self .interm .push(ArithmeticTerm::Number(Number::Integer(n.clone()))), @@ -326,17 +325,11 @@ impl<'a> ArithmeticEvaluator<'a> { // integer division rounding function -- 9.1.3.1. pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Number> { match n { - &Number::Integer(_) => { - RefOrOwned::Borrowed(n) - } - &Number::Float(OrderedFloat(f)) => { - RefOrOwned::Owned(Number::from( - Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0)) - )) - } - &Number::Fixnum(n) => { - RefOrOwned::Owned(Number::from(n)) - } + &Number::Integer(_) => RefOrOwned::Borrowed(n), + &Number::Float(OrderedFloat(f)) => RefOrOwned::Owned(Number::from( + Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0)), + )), + &Number::Fixnum(n) => RefOrOwned::Owned(Number::from(n)), &Number::Rational(ref r) => { let r_ref = r.fract_floor_ref(); let (mut fract, mut floor) = (Rational::new(), Integer::new()); @@ -432,31 +425,31 @@ impl Add for Number { Number::from(Integer::from(n1) + Integer::from(n2)) }) } - (Number::Fixnum(n1), Number::Integer(n2)) | - (Number::Integer(n2), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Integer(n2)) + | (Number::Integer(n2), Number::Fixnum(n1)) => { Ok(Number::from(Integer::from(n1) + &*n2)) } - (Number::Fixnum(n1), Number::Rational(n2)) | - (Number::Rational(n2), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Rational(n2)) + | (Number::Rational(n2), Number::Fixnum(n1)) => { Ok(Number::from(Rational::from(n1) + &*n2)) } - (Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) | - (Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) + | (Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => { Ok(Number::Float(add_f(float_fn_to_f(n1)?, n2)?)) } (Number::Integer(n1), Number::Integer(n2)) => { Ok(Number::from(Integer::from(&*n1) + &*n2)) // add_i } (Number::Integer(n1), Number::Float(OrderedFloat(n2))) - | (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => { + | (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => { Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?)) } (Number::Integer(n1), Number::Rational(n2)) - | (Number::Rational(n2), Number::Integer(n1)) => { + | (Number::Rational(n2), Number::Integer(n1)) => { Ok(Number::from(Rational::from(&*n1) + &*n2)) } (Number::Rational(n1), Number::Float(OrderedFloat(n2))) - | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => { + | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => { Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?)) } (Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => { @@ -474,12 +467,13 @@ impl Neg for Number { fn neg(self) -> Self::Output { match self { - Number::Fixnum(n) => + Number::Fixnum(n) => { if let Some(n) = n.checked_neg() { Number::Fixnum(n) } else { Number::from(-Integer::from(n)) } + } Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*n))), Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)), Number::Rational(r) => Number::Rational(Rc::new(-Rational::from(&*r))), @@ -507,16 +501,16 @@ impl Mul for Number { Number::from(Integer::from(n1) * Integer::from(n2)) }) } - (Number::Fixnum(n1), Number::Integer(n2)) | - (Number::Integer(n2), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Integer(n2)) + | (Number::Integer(n2), Number::Fixnum(n1)) => { Ok(Number::from(Integer::from(n1) * &*n2)) } - (Number::Fixnum(n1), Number::Rational(n2)) | - (Number::Rational(n2), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Rational(n2)) + | (Number::Rational(n2), Number::Fixnum(n1)) => { Ok(Number::from(Rational::from(n1) * &*n2)) } - (Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) | - (Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) + | (Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => { Ok(Number::Float(mul_f(float_fn_to_f(n1)?, n2)?)) } (Number::Integer(n1), Number::Integer(n2)) => { @@ -549,72 +543,50 @@ impl Div for Number { fn div(self, rhs: Number) -> Self::Output { match (self, rhs) { - (Number::Fixnum(n1), Number::Fixnum(n2)) => { - Ok(Number::Float(div_f( - float_fn_to_f(n1)?, - float_fn_to_f(n2)?, - )?)) - } - (Number::Fixnum(n1), Number::Integer(n2)) => { - Ok(Number::Float(div_f( - float_fn_to_f(n1)?, - float_i_to_f(&n2)?, - )?)) - } - (Number::Integer(n1), Number::Fixnum(n2)) => { - Ok(Number::Float(div_f( - float_i_to_f(&n1)?, - float_fn_to_f(n2)?, - )?)) - } - (Number::Fixnum(n1), Number::Rational(n2)) => { - Ok(Number::Float(div_f( - float_fn_to_f(n1)?, - float_r_to_f(&n2)?, - )?)) - } - (Number::Rational(n1), Number::Fixnum(n2)) => { - Ok(Number::Float(div_f( - float_r_to_f(&n1)?, - float_fn_to_f(n2)?, - )?)) - } + (Number::Fixnum(n1), Number::Fixnum(n2)) => Ok(Number::Float(div_f( + float_fn_to_f(n1)?, + float_fn_to_f(n2)?, + )?)), + (Number::Fixnum(n1), Number::Integer(n2)) => Ok(Number::Float(div_f( + float_fn_to_f(n1)?, + float_i_to_f(&n2)?, + )?)), + (Number::Integer(n1), Number::Fixnum(n2)) => Ok(Number::Float(div_f( + float_i_to_f(&n1)?, + float_fn_to_f(n2)?, + )?)), + (Number::Fixnum(n1), Number::Rational(n2)) => Ok(Number::Float(div_f( + float_fn_to_f(n1)?, + float_r_to_f(&n2)?, + )?)), + (Number::Rational(n1), Number::Fixnum(n2)) => Ok(Number::Float(div_f( + float_r_to_f(&n1)?, + float_fn_to_f(n2)?, + )?)), (Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) => { - Ok(Number::Float(div_f( - float_fn_to_f(n1)?, - n2, - )?)) + Ok(Number::Float(div_f(float_fn_to_f(n1)?, n2)?)) } (Number::Float(OrderedFloat(n1)), Number::Fixnum(n2)) => { - Ok(Number::Float(div_f( - n1, - float_fn_to_f(n2)?, - )?)) - } - (Number::Integer(n1), Number::Integer(n2)) => { - Ok(Number::Float(div_f( - float_i_to_f(&n1)?, - float_i_to_f(&n2)?, - )?)) + Ok(Number::Float(div_f(n1, float_fn_to_f(n2)?)?)) } + (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Float(div_f( + float_i_to_f(&n1)?, + float_i_to_f(&n2)?, + )?)), (Number::Integer(n1), Number::Float(OrderedFloat(n2))) => { Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?)) } (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => { Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?)) } - (Number::Integer(n1), Number::Rational(n2)) => { - Ok(Number::Float(div_f( - float_i_to_f(&n1)?, - float_r_to_f(&n2)?, - )?)) - } - (Number::Rational(n2), Number::Integer(n1)) => { - Ok(Number::Float(div_f( - float_r_to_f(&n2)?, - float_i_to_f(&n1)?, - )?)) - } + (Number::Integer(n1), Number::Rational(n2)) => Ok(Number::Float(div_f( + float_i_to_f(&n1)?, + float_r_to_f(&n2)?, + )?)), + (Number::Rational(n2), Number::Integer(n1)) => Ok(Number::Float(div_f( + float_r_to_f(&n2)?, + float_i_to_f(&n1)?, + )?)), (Number::Rational(n1), Number::Float(OrderedFloat(n2))) => { Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?)) } @@ -727,12 +699,8 @@ impl<'a> TryFrom<(Addr, &'a Heap)> for Number { fn try_from((addr, heap): (Addr, &'a Heap)) -> Result { match addr { - Addr::Fixnum(n) => { - Ok(Number::from(n)) - } - Addr::Float(n) => { - Ok(Number::Float(n)) - } + Addr::Fixnum(n) => Ok(Number::from(n)), + Addr::Float(n) => Ok(Number::Float(n)), Addr::Usize(n) => { if let Ok(n) = isize::try_from(n) { Ok(Number::from(n)) @@ -740,12 +708,8 @@ impl<'a> TryFrom<(Addr, &'a Heap)> for Number { Ok(Number::from(Integer::from(n))) } } - Addr::Con(h) => { - Number::try_from(&heap[h]) - } - _ => { - Err(()) - } + Addr::Con(h) => Number::try_from(&heap[h]), + _ => Err(()), } } } @@ -755,35 +719,21 @@ impl<'a> TryFrom<&'a HeapCellValue> for Number { fn try_from(value: &'a HeapCellValue) -> Result { match value { - HeapCellValue::Addr(addr) => { - match addr { - &Addr::Fixnum(n) => { + HeapCellValue::Addr(addr) => match addr { + &Addr::Fixnum(n) => Ok(Number::from(n)), + &Addr::Float(n) => Ok(Number::Float(n)), + &Addr::Usize(n) => { + if let Ok(n) = isize::try_from(n) { Ok(Number::from(n)) - } - &Addr::Float(n) => { - Ok(Number::Float(n)) - } - &Addr::Usize(n) => { - if let Ok(n) = isize::try_from(n) { - Ok(Number::from(n)) - } else { - Ok(Number::from(Integer::from(n))) - } - } - _ => { - Err(()) + } else { + Ok(Number::from(Integer::from(n))) } } - } - HeapCellValue::Integer(n) => { - Ok(Number::Integer(n.clone())) - } - HeapCellValue::Rational(n) => { - Ok(Number::Rational(n.clone())) - } - _ => { - Err(()) - } + _ => Err(()), + }, + HeapCellValue::Integer(n) => Ok(Number::Integer(n.clone())), + HeapCellValue::Rational(n) => Ok(Number::Rational(n.clone())), + _ => Err(()), } } } diff --git a/src/clause_types.rs b/src/clause_types.rs index 6f412b78..335e24f8 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -1,10 +1,11 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::{clause_name, temp_v}; use crate::forms::Number; use crate::machine::machine_indices::*; use crate::rug::rand::RandState; -use crate::ref_thread_local::RefThreadLocal; +use crate::ref_thread_local::{ref_thread_local, RefThreadLocal}; use std::collections::BTreeMap; @@ -322,7 +323,9 @@ impl SystemClauseType { &SystemClauseType::ClearAttributeGoals => clause_name!("$clear_attribute_goals"), &SystemClauseType::CloneAttributeGoals => clause_name!("$clone_attribute_goals"), &SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"), - &SystemClauseType::CopyTermWithoutAttrVars => clause_name!("$copy_term_without_attr_vars"), + &SystemClauseType::CopyTermWithoutAttrVars => { + clause_name!("$copy_term_without_attr_vars") + } &SystemClauseType::CreatePartialString => clause_name!("$create_partial_string"), &SystemClauseType::CurrentInput => clause_name!("$current_input"), &SystemClauseType::CurrentHostname => clause_name!("$current_hostname"), @@ -337,58 +340,70 @@ impl SystemClauseType { &SystemClauseType::WorkingDirectory => clause_name!("$working_directory"), &SystemClauseType::PathCanonical => clause_name!("$path_canonical"), &SystemClauseType::FileTime => clause_name!("$file_time"), - &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::Asserta) => - clause_name!("$asserta"), - &SystemClauseType::REPL(REPLCodePtr::Assertz) => - clause_name!("$assertz"), - &SystemClauseType::REPL(REPLCodePtr::Retract) => - 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::BuiltInProperty) => - clause_name!("$cpp_built_in_property"), - &SystemClauseType::REPL(REPLCodePtr::DynamicProperty) => - clause_name!("$cpp_dynamic_property"), - &SystemClauseType::REPL(REPLCodePtr::MultifileProperty) => - clause_name!("$cpp_multifile_property"), - &SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty) => - clause_name!("$cpp_discontiguous_property"), - &SystemClauseType::REPL(REPLCodePtr::AbolishClause) => - clause_name!("$abolish_clause"), + &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::Asserta) => clause_name!("$asserta"), + &SystemClauseType::REPL(REPLCodePtr::Assertz) => clause_name!("$assertz"), + &SystemClauseType::REPL(REPLCodePtr::Retract) => 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::BuiltInProperty) => { + clause_name!("$cpp_built_in_property") + } + &SystemClauseType::REPL(REPLCodePtr::DynamicProperty) => { + clause_name!("$cpp_dynamic_property") + } + &SystemClauseType::REPL(REPLCodePtr::MultifileProperty) => { + clause_name!("$cpp_multifile_property") + } + &SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty) => { + clause_name!("$cpp_discontiguous_property") + } + &SystemClauseType::REPL(REPLCodePtr::AbolishClause) => clause_name!("$abolish_clause"), &SystemClauseType::Close => clause_name!("$close"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), @@ -397,8 +412,9 @@ impl SystemClauseType { &SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"), &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), &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"), @@ -424,13 +440,13 @@ impl SystemClauseType { 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"), @@ -455,7 +471,7 @@ impl SystemClauseType { // &SystemClauseType::ModuleAssertDynamicPredicateToBack => { // clause_name!("$module_assertz") // } -// &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"), + // &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"), &SystemClauseType::ModuleExists => clause_name!("$module_exists"), &SystemClauseType::NextStream => clause_name!("$next_stream"), &SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"), @@ -507,7 +523,9 @@ impl SystemClauseType { &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::ResetGlobalVarAtOffset => { + clause_name!("$reset_global_var_at_offset") + } &SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::ResetContinuationMarker => clause_name!("$reset_cont_marker"), &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), @@ -521,7 +539,9 @@ impl SystemClauseType { &SystemClauseType::SocketServerAccept => clause_name!("$socket_server_accept"), &SystemClauseType::SocketServerClose => clause_name!("$socket_server_close"), &SystemClauseType::Succeed => clause_name!("$succeed"), - &SystemClauseType::TermAttributedVariables => clause_name!("$term_attributed_variables"), + &SystemClauseType::TermAttributedVariables => { + clause_name!("$term_attributed_variables") + } &SystemClauseType::TermVariables => clause_name!("$term_variables"), &SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"), &SystemClauseType::UnifyWithOccursCheck => clause_name!("$unify_with_occurs_check"), @@ -542,7 +562,9 @@ impl SystemClauseType { &SystemClauseType::Ed25519Sign => clause_name!("$ed25519_sign"), &SystemClauseType::Ed25519Verify => clause_name!("$ed25519_verify"), &SystemClauseType::Ed25519NewKeyPair => clause_name!("$ed25519_new_keypair"), - &SystemClauseType::Ed25519KeyPairPublicKey => clause_name!("$ed25519_keypair_public_key"), + &SystemClauseType::Ed25519KeyPairPublicKey => { + clause_name!("$ed25519_keypair_public_key") + } &SystemClauseType::Curve25519ScalarMult => clause_name!("$curve25519_scalar_mult"), &SystemClauseType::LoadHTML => clause_name!("$load_html"), &SystemClauseType::LoadXML => clause_name!("$load_xml"), @@ -556,14 +578,16 @@ impl SystemClauseType { pub fn from(name: &str, arity: usize) -> Option { match (name, arity) { - ("$abolish_clause", 3) => - Some(SystemClauseType::REPL(REPLCodePtr::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)), + ("$abolish_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::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)) + } ("$atom_chars", 2) => Some(SystemClauseType::AtomChars), ("$atom_codes", 2) => Some(SystemClauseType::AtomCodes), ("$atom_length", 2) => Some(SystemClauseType::AtomLength), @@ -602,7 +626,9 @@ impl SystemClauseType { ("$peek_code", 2) => Some(SystemClauseType::PeekCode), ("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), - ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), + ("$fetch_global_var_with_offset", 3) => { + Some(SystemClauseType::FetchGlobalVarWithOffset) + } ("$get_byte", 2) => Some(SystemClauseType::GetByte), ("$get_char", 2) => Some(SystemClauseType::GetChar), ("$get_n_chars", 3) => Some(SystemClauseType::GetNChars), @@ -611,18 +637,10 @@ impl SystemClauseType { ("$points_to_cont_reset_marker", 1) => { Some(SystemClauseType::PointsToContinuationResetMarker) } - ("$put_byte", 2) => { - Some(SystemClauseType::PutByte) - } - ("$put_char", 2) => { - Some(SystemClauseType::PutChar) - } - ("$put_chars", 2) => { - Some(SystemClauseType::PutChars) - } - ("$put_code", 2) => { - Some(SystemClauseType::PutCode) - } + ("$put_byte", 2) => Some(SystemClauseType::PutByte), + ("$put_char", 2) => Some(SystemClauseType::PutChar), + ("$put_chars", 2) => Some(SystemClauseType::PutChars), + ("$put_code", 2) => Some(SystemClauseType::PutCode), ("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState), ("$truncate_if_no_lh_growth", 1) => { Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth) @@ -691,7 +709,9 @@ impl SystemClauseType { ("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept), ("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), - ("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset), + ("$store_global_var_with_offset", 2) => { + Some(SystemClauseType::StoreGlobalVarWithOffset) + } ("$term_attributed_variables", 2) => Some(SystemClauseType::TermAttributedVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), @@ -708,12 +728,18 @@ impl SystemClauseType { ("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory), ("$path_canonical", 2) => Some(SystemClauseType::PathCanonical), ("$file_time", 3) => Some(SystemClauseType::FileTime), - ("$clause_to_evacuable", 3) => Some(SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable)), + ("$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)), + ("$load_compiled_library", 2) => { + Some(SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary)) + } + ("$push_load_state_payload", 1) => { + Some(SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload)) + } ("$asserta", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Asserta)), ("$assertz", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Assertz)), ("$retract_clause", 4) => Some(SystemClauseType::REPL(REPLCodePtr::Retract)), @@ -742,18 +768,38 @@ impl SystemClauseType { ("$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_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_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", 4) => Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)), - ("$cpp_built_in_property", 2) => Some(SystemClauseType::REPL(REPLCodePtr::BuiltInProperty)), - ("$cpp_dynamic_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DynamicProperty)), - ("$cpp_multifile_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::MultifileProperty)), - ("$cpp_discontiguous_property", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty)), + ("$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", 4) => { + Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty)) + } + ("$cpp_built_in_property", 2) => { + Some(SystemClauseType::REPL(REPLCodePtr::BuiltInProperty)) + } + ("$cpp_dynamic_property", 3) => { + Some(SystemClauseType::REPL(REPLCodePtr::DynamicProperty)) + } + ("$cpp_multifile_property", 3) => { + Some(SystemClauseType::REPL(REPLCodePtr::MultifileProperty)) + } + ("$cpp_discontiguous_property", 3) => { + Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty)) + } _ => None, } } @@ -832,10 +878,10 @@ impl ClauseType { match self { &ClauseType::Op(_, ref spec, _) => Some(spec.clone()), &ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) - | &ClauseType::BuiltIn(BuiltInClauseType::Is(..)) - | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_)) - | &ClauseType::BuiltIn(BuiltInClauseType::NotEq) - | &ClauseType::BuiltIn(BuiltInClauseType::Eq) => Some(SharedOpDesc::new(700, XFX)), + | &ClauseType::BuiltIn(BuiltInClauseType::Is(..)) + | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_)) + | &ClauseType::BuiltIn(BuiltInClauseType::NotEq) + | &ClauseType::BuiltIn(BuiltInClauseType::Eq) => Some(SharedOpDesc::new(700, XFX)), _ => None, } } diff --git a/src/codegen.rs b/src/codegen.rs index f2a1c5ab..46e2ea82 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,7 @@ /// Code generation to WAM-like instructions. use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::tabled_rc::TabledData; +use crate::prolog_parser_rebis::{perm_v, temp_v}; use crate::allocator::*; use crate::arithmetic::*; @@ -66,18 +67,14 @@ impl<'a> ConjunctInfo<'a> { self.has_deep_cut as usize } - fn mark_unsafe_vars( - &self, - mut unsafe_var_marker: UnsafeVarMarker, - code: &mut Code, - ) { + fn mark_unsafe_vars(&self, mut unsafe_var_marker: UnsafeVarMarker, code: &mut Code) { if code.is_empty() { return; } let mut code_index = 0; - for phase in 0 .. { + for phase in 0.. { while let Line::Query(ref query_instr) = &code[code_index] { if !unsafe_var_marker.mark_safe_vars(query_instr) { unsafe_var_marker.mark_phase(query_instr, phase); @@ -95,7 +92,7 @@ impl<'a> ConjunctInfo<'a> { code_index = 0; - for phase in 0 .. { + for phase in 0.. { while let Line::Query(ref mut query_instr) = &mut code[code_index] { unsafe_var_marker.mark_unsafe_vars(query_instr, phase); code_index += 1; @@ -173,7 +170,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { code: &mut Code, ) -> RegType { let mut target = Vec::new(); - self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target); + self.marker + .mark_var(name, Level::Shallow, vr, term_loc, &mut target); if !target.is_empty() { code.extend(target.into_iter().map(Line::Query)); @@ -191,9 +189,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { code: &mut Code, ) -> RegType { match self.marker.bindings().get(&name) { - Some(&VarData::Temp(_, t, _)) if t != 0 => { - RegType::Temp(t) - } + Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t), Some(&VarData::Perm(p)) if p != 0 => { if let GenContext::Last(_) = term_loc { self.mark_var_in_non_callable(name.clone(), term_loc, vr, code); @@ -202,9 +198,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { RegType::Perm(p) } } - _ => { - self.mark_var_in_non_callable(name, term_loc, vr, code) - } + _ => self.mark_var_in_non_callable(name, term_loc, vr, code), } } @@ -231,7 +225,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { target: &mut Vec, ) { if is_exposed || self.get_var_count(var.as_ref()) > 1 { - self.marker.mark_var(var.clone(), Level::Deep, cell, term_loc, target); + self.marker + .mark_var(var.clone(), Level::Deep, cell, term_loc, target); } else { Self::add_or_increment_void_instr(target); } @@ -252,7 +247,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { Self::add_or_increment_void_instr(target); } &Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => { - self.marker.mark_non_var(Level::Deep, term_loc, cell, target); + self.marker + .mark_non_var(Level::Deep, term_loc, cell, target); target.push(Target::clause_arg_to_instr(cell.get())); } &Term::Constant(_, ref constant) => { @@ -264,7 +260,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { }; } - fn compile_target( + fn compile_target( &mut self, iter: Iter, term_loc: GenContext, @@ -334,13 +330,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } } - self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target); + self.marker + .mark_var(var.clone(), lvl, cell, term_loc, &mut target); } TermRef::Var(lvl @ Level::Shallow, cell, var) => { - self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target); - } - _ => { + self.marker + .mark_var(var.clone(), lvl, cell, term_loc, &mut target); } + _ => {} }; } @@ -353,8 +350,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() { for (i, chunked_term) in chunked_terms.iter().enumerate() { let term_loc = match chunked_term { - &ChunkedTerm::HeadClause(..) => - GenContext::Head, + &ChunkedTerm::HeadClause(..) => GenContext::Head, &ChunkedTerm::BodyTerm(_) => { if i < chunked_terms.len() - 1 { GenContext::Mid(chunk_num) @@ -391,8 +387,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { &QueryTerm::Clause(_, ref ct, ref terms, false) => { code.push(call_clause!(ct.clone(), terms.len(), pvs)); } - _ => { - } + _ => {} } } @@ -407,8 +402,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { &mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => { *last_call = true; } - &mut ControlInstruction::Proceed => { - } + &mut ControlInstruction::Proceed => {} _ => { dealloc_index += 1; } @@ -416,8 +410,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { Some(&mut Line::Cut(CutInstruction::Cut(_))) => { dealloc_index += 1; } - _ => { - } + _ => {} }; dealloc_index @@ -437,23 +430,17 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?; let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?; - let at_1 = - if let &Term::Var(ref vr, ref name) = terms[0].as_ref() { - ArithmeticTerm::Reg( - self.mark_non_callable(name.clone(), 1, term_loc, vr, code) - ) - } else { - at_1.unwrap_or(interm!(1)) - }; + let at_1 = if let &Term::Var(ref vr, ref name) = terms[0].as_ref() { + ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 1, term_loc, vr, code)) + } else { + at_1.unwrap_or(interm!(1)) + }; - let at_2 = - if let &Term::Var(ref vr, ref name) = terms[1].as_ref() { - ArithmeticTerm::Reg( - self.mark_non_callable(name.clone(), 2, term_loc, vr, code) - ) - } else { - at_2.unwrap_or(interm!(2)) - }; + let at_2 = if let &Term::Var(ref vr, ref name) = terms[1].as_ref() { + ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 2, term_loc, vr, code)) + } else { + at_2.unwrap_or(interm!(2)) + }; code.append(&mut lcode); code.append(&mut rcode); @@ -461,9 +448,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { code.push(compare_number_instr!(cmp, at_1, at_2)); } &InlinedClauseType::IsAtom(..) => match terms[0].as_ref() { - &Term::Constant(_, Constant::Char(_)) | - &Term::Constant(_, Constant::EmptyList) | - &Term::Constant(_, Constant::Atom(..)) => { + &Term::Constant(_, Constant::Char(_)) + | &Term::Constant(_, Constant::EmptyList) + | &Term::Constant(_, Constant::Atom(..)) => { code.push(succeed!()); } &Term::Var(ref vr, ref name) => { @@ -528,11 +515,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } }, &InlinedClauseType::IsNumber(..) => match terms[0].as_ref() { - &Term::Constant(_, Constant::Float(_)) | - &Term::Constant(_, Constant::Rational(_)) | - &Term::Constant(_, Constant::Integer(_)) | - &Term::Constant(_, Constant::Fixnum(_)) | - &Term::Constant(_, Constant::Usize(_)) => { + &Term::Constant(_, Constant::Float(_)) + | &Term::Constant(_, Constant::Rational(_)) + | &Term::Constant(_, Constant::Integer(_)) + | &Term::Constant(_, Constant::Fixnum(_)) + | &Term::Constant(_, Constant::Usize(_)) => { code.push(succeed!()); } &Term::Var(ref vr, ref name) => { @@ -558,9 +545,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } }, &InlinedClauseType::IsInteger(..) => match terms[0].as_ref() { - &Term::Constant(_, Constant::Integer(_)) | - &Term::Constant(_, Constant::Fixnum(_)) | - &Term::Constant(_, Constant::Usize(_)) => { + &Term::Constant(_, Constant::Integer(_)) + | &Term::Constant(_, Constant::Fixnum(_)) + | &Term::Constant(_, Constant::Usize(_)) => { code.push(succeed!()); } &Term::Var(ref vr, ref name) => { @@ -615,14 +602,15 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { &Term::Var(ref vr, ref name) => { let mut target = vec![]; - self.marker.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target); + self.marker + .mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target); if !target.is_empty() { code.extend(target.into_iter().map(Line::Query)); } } - &Term::Constant(_, ref c @ Constant::Integer(_)) | - &Term::Constant(_, ref c @ Constant::Fixnum(_)) => { + &Term::Constant(_, ref c @ Constant::Integer(_)) + | &Term::Constant(_, ref c @ Constant::Fixnum(_)) => { code.push(Line::Query(put_constant!( Level::Shallow, c.clone(), @@ -655,14 +643,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } } - let at = - if let &Term::Var(ref vr, ref name) = terms[1].as_ref() { - ArithmeticTerm::Reg( - self.mark_non_callable(name.clone(), 2, term_loc, vr, code) - ) - } else { - at.unwrap_or(interm!(1)) - }; + let at = if let &Term::Var(ref vr, ref name) = terms[1].as_ref() { + ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 2, term_loc, vr, code)) + } else { + at.unwrap_or(interm!(1)) + }; Ok(if use_default_call_policy { code.push(is_call_by_default!(temp_v!(1), at)); @@ -721,24 +706,18 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { &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)? } @@ -772,7 +751,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } } - fn compile_cleanup(&mut self, 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!()), @@ -786,7 +770,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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 let Some(jmp_by_offset) = self.jmp_by_locs[offset..].last_mut() { if *jmp_by_offset == dealloc_index { *jmp_by_offset += 1; } @@ -905,32 +889,32 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { self.add_conditional_call(code, term, num_perm_vars_left); } -/* - pub fn compile_query(&mut self, query: &'a Vec) -> Result { - let iter = ChunkedIterator::from_term_sequence(query); - let conjunct_info = self.collect_var_data(iter); + /* + pub fn compile_query(&mut self, query: &'a Vec) -> Result { + let iter = ChunkedIterator::from_term_sequence(query); + let conjunct_info = self.collect_var_data(iter); - let mut code = Vec::new(); - self.compile_seq_prelude(&conjunct_info, &mut code); + let mut code = Vec::new(); + self.compile_seq_prelude(&conjunct_info, &mut code); - let iter = ChunkedIterator::from_term_sequence(query); - self.compile_seq(iter, &conjunct_info, &mut code, true)?; + let iter = ChunkedIterator::from_term_sequence(query); + self.compile_seq(iter, &conjunct_info, &mut code, true)?; - conjunct_info.mark_unsafe_vars(UnsafeVarMarker::new(), &mut code); + conjunct_info.mark_unsafe_vars(UnsafeVarMarker::new(), &mut code); - if let Some(query_term) = query.last() { - Self::compile_cleanup(&mut code, &conjunct_info, query_term); + if let Some(query_term) = query.last() { + Self::compile_cleanup(&mut code, &conjunct_info, query_term); + } + + Ok(code) } - - 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 ..] { + for loc in &mut self.jmp_by_locs[offset..] { *loc += incr; } } @@ -1077,7 +1061,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { if skip_stub_try_me_else { // skip the TryMeElse(0) also. - self.increment_jmp_by_locs_by(2); + self.increment_jmp_by_locs_by(2); } else { self.increment_jmp_by_locs_by(1); } @@ -1105,7 +1089,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { for (l, r) in split_pred { let skel_lower_bound = self.skeleton.clauses.len(); - let code_segment = self.compile_pred_subseq(&clauses[l .. r], optimal_index)?; + let code_segment = self.compile_pred_subseq(&clauses[l..r], optimal_index)?; let clause_start_offset = code.len(); if multi_seq { @@ -1123,11 +1107,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { 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() { + 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; + clause_index_info.opt_arg_index_key += clause_start_offset + 1; } } diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 3c69bda2..39b5a886 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -1,6 +1,7 @@ use crate::indexmap::IndexMap; use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::temp_v; use crate::allocator::*; use crate::fixtures::*; @@ -293,9 +294,7 @@ impl<'a> Allocator<'a> for DebrayAllocator { (pr, true) } - r => { - (r, false) - } + r => (r, false), }; self.mark_reserved_var(var, lvl, cell, term_loc, target, r, is_new_var); diff --git a/src/forms.rs b/src/forms.rs index c039e603..f71df86c 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,5 +1,6 @@ use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::parser::OpDesc; +use crate::prolog_parser_rebis::{clause_name, is_infix, is_postfix}; use crate::clause_types::*; use crate::machine::machine_errors::*; @@ -36,7 +37,7 @@ pub enum TopLevel { #[derive(Debug, Clone, Copy)] pub enum AppendOrPrepend { Append, - Prepend + Prepend, } impl AppendOrPrepend { @@ -115,12 +116,8 @@ impl ListingSource { pub trait ClauseInfo { fn is_consistent(&self, clauses: &Vec) -> bool { match clauses.first() { - Some(cl) => { - self.name() == cl.name() && self.arity() == cl.arity() - } - None => { - true - } + Some(cl) => self.name() == cl.name() && self.arity() == cl.arity(), + None => true, } } @@ -140,38 +137,25 @@ impl ClauseInfo for Term { _ => Some(clause_name!(":-")), } } - _ => { - Some(name.clone()) - } + _ => Some(name.clone()), } } - Term::Constant(_, Constant::Atom(ref name, _)) => { - Some(name.clone()) - } - _ => { - None - } + Term::Constant(_, Constant::Atom(ref name, _)) => Some(name.clone()), + _ => None, } } fn arity(&self) -> usize { match self { - Term::Clause(_, ref name, ref terms, _) => - match name.as_str() { - ":-" => { - match terms.len() { - 1 => 0, - 2 => terms[0].arity(), - _ => terms.len(), - } - } - _ => { - terms.len() - } + Term::Clause(_, ref name, ref terms, _) => match name.as_str() { + ":-" => match terms.len() { + 1 => 0, + 2 => terms[0].arity(), + _ => terms.len(), }, - _ => { - 0 - } + _ => terms.len(), + }, + _ => 0, } } } @@ -189,23 +173,15 @@ impl ClauseInfo for Rule { impl ClauseInfo for PredicateClause { fn name(&self) -> Option { match self { - &PredicateClause::Fact(ref term, ..) => { - term.name() - } - &PredicateClause::Rule(ref rule, ..) => { - rule.name() - } + &PredicateClause::Fact(ref term, ..) => term.name(), + &PredicateClause::Rule(ref rule, ..) => rule.name(), } } fn arity(&self) -> usize { match self { - &PredicateClause::Fact(ref term, ..) => { - term.arity() - } - &PredicateClause::Rule(ref rule, ..) => { - rule.arity() - } + &PredicateClause::Fact(ref term, ..) => term.arity(), + &PredicateClause::Rule(ref rule, ..) => rule.arity(), } } } @@ -222,11 +198,9 @@ impl PredicateClause { // TODO: add this to `Term` in `prolog_parser` like `first_arg`. pub fn args(&self) -> Option<&[Box]> { match *self { - PredicateClause::Fact(ref term, ..) => { - match term { - Term::Clause(_, _, args, _) => Some(&args), - _ => None, - } + PredicateClause::Fact(ref term, ..) => match term { + Term::Clause(_, _, args, _) => Some(&args), + _ => None, }, PredicateClause::Rule(ref rule, ..) => { if rule.head.1.is_empty() { @@ -240,14 +214,11 @@ impl PredicateClause { pub fn arity(&self) -> usize { match self { - &PredicateClause::Fact(ref term, ..) => { - term.arity() - } + &PredicateClause::Fact(ref term, ..) => term.arity(), &PredicateClause::Rule(ref rule, ..) => { if rule.head.0.as_str() == ":" && rule.head.1.len() == 2 { match (rule.head.1)[0].as_ref() { - &Term::Constant(_, Constant::Atom(..)) => { - } + &Term::Constant(_, Constant::Atom(..)) => {} _ => { return 2; } @@ -321,7 +292,7 @@ pub enum Declaration { pub struct OpDecl { pub prec: usize, pub spec: Specifier, - pub name: ClauseName + pub name: ClauseName, } impl OpDecl { @@ -345,7 +316,7 @@ impl OpDecl { XFY | XFX | YFX => Fixity::In, XF | YF => Fixity::Post, FX | FY => Fixity::Pre, - _ => unreachable!() + _ => unreachable!(), } } @@ -356,12 +327,12 @@ impl OpDecl { Some(cell) => { return Some(cell.shared_op_desc().replace((self.prec, self.spec))); } - None => { - } + None => {} } - op_dir.insert(key, OpDirValue::new(self.spec, self.prec)) - .map(|op_dir_value| op_dir_value.shared_op_desc().get()) + op_dir + .insert(key, OpDirValue::new(self.spec, self.prec)) + .map(|op_dir_value| op_dir_value.shared_op_desc().get()) } pub fn submit( @@ -419,11 +390,7 @@ pub fn fetch_op_spec_from_existing( spec.or_else(|| fetch_op_spec(name, arity, op_dir)) } -pub fn fetch_op_spec( - name: ClauseName, - arity: usize, - op_dir: &OpDir, -) -> Option { +pub fn fetch_op_spec(name: ClauseName, arity: usize, op_dir: &OpDir) -> Option { match arity { 2 => op_dir .get(&(name, Fixity::In)) @@ -451,9 +418,7 @@ pub fn fetch_op_spec( } }) } - _ => { - None - } + _ => None, } } @@ -499,7 +464,6 @@ impl Module { } } - #[derive(Debug, Clone)] pub enum Number { Float(OrderedFloat), @@ -559,7 +523,6 @@ impl Into for Number { } } - impl Number { #[inline] pub fn is_positive(&self) -> bool { @@ -594,12 +557,13 @@ impl Number { #[inline] pub fn abs(self) -> Self { match self { - Number::Fixnum(n) => + Number::Fixnum(n) => { if let Some(n) = n.checked_abs() { Number::from(n) } else { Number::from(Integer::from(n).abs()) } + } Number::Integer(n) => Number::from(Integer::from(n.abs_ref())), Number::Float(f) => Number::Float(OrderedFloat(f.abs())), Number::Rational(r) => Number::from(Rational::from(r.abs_ref())), @@ -624,15 +588,13 @@ impl OptArgIndexKey { #[inline] pub fn arg_num(&self) -> usize { match &self { - OptArgIndexKey::Constant(arg_num, ..) | - OptArgIndexKey::Structure(arg_num, ..) | - OptArgIndexKey::List(arg_num, _) => { + OptArgIndexKey::Constant(arg_num, ..) + | OptArgIndexKey::Structure(arg_num, ..) + | OptArgIndexKey::List(arg_num, _) => { // these are always at least 1. *arg_num } - OptArgIndexKey::None => { - 0 - } + OptArgIndexKey::None => 0, } } @@ -644,27 +606,22 @@ impl OptArgIndexKey { #[inline] pub fn switch_on_term_loc(&self) -> Option { match &self { - OptArgIndexKey::Constant(_, loc, ..) | - OptArgIndexKey::Structure(_, loc, ..) | - OptArgIndexKey::List(_, loc) => { - Some(*loc) - } - OptArgIndexKey::None => { - None - } + 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) => { + OptArgIndexKey::Constant(_, ref mut loc, ..) + | OptArgIndexKey::Structure(_, ref mut loc, ..) + | OptArgIndexKey::List(_, ref mut loc) => { *loc = value; } - OptArgIndexKey::None => { - } + OptArgIndexKey::None => {} } } } @@ -673,13 +630,12 @@ impl AddAssign 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, ..) => { + OptArgIndexKey::Constant(_, ref mut o, ..) + | OptArgIndexKey::List(_, ref mut o) + | OptArgIndexKey::Structure(_, ref mut o, ..) => { *o += n; } - OptArgIndexKey::None => { - } + OptArgIndexKey::None => {} } } } diff --git a/src/heap_print.rs b/src/heap_print.rs index 29530fa5..d4b9b09f 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1,4 +1,10 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::{ + alpha_char, alpha_numeric_char, backslash_char, capital_letter_char, char_class, clause_name, + cut_char, decimal_digit_char, graphic_char, graphic_token_char, is_fx, is_infix, is_postfix, + is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char, sign_char, single_quote_char, + small_letter_char, solo_char, variable_indicator_char, +}; use crate::clause_types::*; use crate::forms::*; @@ -14,7 +20,7 @@ use crate::indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::convert::TryFrom; -use std::iter::{FromIterator, once}; +use std::iter::{once, FromIterator}; use std::net::{IpAddr, TcpListener}; use std::ops::{Range, RangeFrom}; use std::rc::Rc; @@ -99,10 +105,7 @@ impl<'a> HCPreOrderIterator<'a> { None => return false, }; - let mut parent_spec = DirectedOp::Left( - clause_name!("-"), - SharedOpDesc::new(200, FY), - ); + let mut parent_spec = DirectedOp::Left(clause_name!("-"), SharedOpDesc::new(200, FY)); loop { match self.machine_st.store(self.machine_st.deref(addr)) { @@ -154,12 +157,13 @@ fn char_to_string(is_quoted: bool, c: char) -> String { '\u{07}' if is_quoted => "\\a".to_string(), // UTF-8 alert '"' if is_quoted => "\\\"".to_string(), '\\' if is_quoted => "\\\\".to_string(), - '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => - c.to_string(), - '\u{a0}' ..= '\u{d6}' => c.to_string(), - '\u{d8}' ..= '\u{f6}' => c.to_string(), - '\u{f8}' ..= '\u{74f}' => c.to_string(), - '\x20' ..= '\x7e' => c.to_string(), + '\'' | '\n' | '\r' | '\t' | '\u{0b}' | '\u{0c}' | '\u{08}' | '\u{07}' | '"' | '\\' => { + c.to_string() + } + '\u{a0}'..='\u{d6}' => c.to_string(), + '\u{d8}'..='\u{f6}' => c.to_string(), + '\u{f8}'..='\u{74f}' => c.to_string(), + '\x20'..='\x7e' => c.to_string(), _ => format!("\\x{:x}\\", c as u32), } } @@ -271,25 +275,13 @@ fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool { #[inline] fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option) -> bool { if let Some(ref op) = op { - op.is_negative_sign() && - iter.leftmost_leaf_has_property(|addr, heap| { - match Number::try_from((addr, heap)) { - Ok(Number::Fixnum(n)) => { - n > 0 - } - Ok(Number::Float(f)) => { - f > OrderedFloat(0f64) - } - Ok(Number::Integer(n)) => { - &*n > &0 - } - Ok(Number::Rational(n)) => { - &*n > &0 - } - _ => { - false - } - } + op.is_negative_sign() + && iter.leftmost_leaf_has_property(|addr, heap| match Number::try_from((addr, heap)) { + Ok(Number::Fixnum(n)) => n > 0, + Ok(Number::Float(f)) => f > OrderedFloat(0f64), + Ok(Number::Integer(n)) => &*n > &0, + Ok(Number::Rational(n)) => &*n > &0, + _ => false, }) } else { false @@ -298,8 +290,8 @@ fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option Var { static CHAR_CODES: [char; 26] = [ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ]; let i = n.mod_u(26) as usize; @@ -332,9 +324,7 @@ impl MachineState { None } } - _ => { - None - } + _ => None, } } } @@ -446,8 +436,7 @@ fn non_quoted_graphic_token>(mut iter: Iter, c: char } } -pub(super) -fn non_quoted_token>(mut iter: Iter) -> bool { +pub(super) fn non_quoted_token>(mut iter: Iter) -> bool { if let Some(c) = iter.next() { if small_letter_char!(c) { iter.all(|c| alpha_numeric_char!(c)) @@ -505,37 +494,37 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { max_depth: 0, } } -/* - pub fn from_heap_locs( - machine_st: &'a MachineState, - op_dir: &'a OpDir, - output: Outputter, - ) -> Self { - let mut printer = Self::new(machine_st, op_dir, output); + /* + pub fn from_heap_locs( + machine_st: &'a MachineState, + op_dir: &'a OpDir, + output: Outputter, + ) -> Self { + let mut printer = Self::new(machine_st, op_dir, output); - printer.toplevel_spec = Some(DirectedOp::Right( - clause_name!("="), - SharedOpDesc::new(700, XFX), - )); + printer.toplevel_spec = Some(DirectedOp::Right( + clause_name!("="), + SharedOpDesc::new(700, XFX), + )); - printer.heap_locs = reverse_heap_locs(machine_st); + printer.heap_locs = reverse_heap_locs(machine_st); - 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); + 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 { @@ -555,7 +544,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { iter.stack().pop(); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); return; } @@ -579,7 +569,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { if self.check_max_depth(&mut max_depth) { iter.stack().pop(); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); return; @@ -587,7 +578,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let left_directed_op = DirectedOp::Left(ct.name(), spec.clone()); - self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect( + max_depth, + left_directed_op, + )); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); } else { match ct.name().as_str() { @@ -602,9 +596,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { iter.stack().pop(); iter.stack().pop(); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); return; } @@ -612,11 +608,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let left_directed_op = DirectedOp::Left(ct.name(), spec.clone()); let right_directed_op = DirectedOp::Right(ct.name(), spec.clone()); - self.state_stack - .push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect( + max_depth, + left_directed_op, + )); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); - self.state_stack - .push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect( + max_depth, + right_directed_op, + )); } } @@ -626,15 +626,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { mut max_depth: usize, arity: usize, name: ClauseName, - ) -> bool - { + ) -> bool { if self.check_max_depth(&mut max_depth) { - for _ in 0 .. arity { + for _ in 0..arity { iter.stack().pop(); } self.state_stack.push(TokenOrRedirect::Close); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::Open); self.state_stack.push(TokenOrRedirect::Atom(name)); @@ -644,8 +644,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.state_stack.push(TokenOrRedirect::Close); - for _ in 0 .. arity { - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); + for _ in 0..arity { + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack.push(TokenOrRedirect::Comma); } @@ -662,12 +663,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { iter: &mut HCPreOrderIterator, mut max_depth: usize, name: ClauseName, - spec: SharedOpDesc) - { + spec: SharedOpDesc, + ) { if self.check_max_depth(&mut max_depth) { iter.stack().pop(); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::Space); self.state_stack.push(TokenOrRedirect::Atom(name)); @@ -676,7 +678,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let op = DirectedOp::Left(name.clone(), spec); - self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, op)); + self.state_stack + .push(TokenOrRedirect::CompositeRedirect(max_depth, op)); self.state_stack.push(TokenOrRedirect::Space); self.state_stack.push(TokenOrRedirect::Atom(name)); } @@ -687,14 +690,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { mut max_depth: usize, name: ClauseName, spec: SharedOpDesc, - ) - { + ) { if self.check_max_depth(&mut max_depth) { iter.stack().pop(); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::BarAsOp); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); return; } @@ -702,25 +706,32 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let left_directed_op = DirectedOp::Left(name.clone(), spec.clone()); let right_directed_op = DirectedOp::Right(name.clone(), spec.clone()); - self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect( + max_depth, + left_directed_op, + )); self.state_stack.push(TokenOrRedirect::BarAsOp); - self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect( + max_depth, + right_directed_op, + )); } - fn format_curly_braces(&mut self, iter: &mut HCPreOrderIterator, mut max_depth: usize) -> bool - { + fn format_curly_braces(&mut self, iter: &mut HCPreOrderIterator, mut max_depth: usize) -> bool { if self.check_max_depth(&mut max_depth) { iter.stack().pop(); self.state_stack.push(TokenOrRedirect::RightCurly); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::LeftCurly); return false; } self.state_stack.push(TokenOrRedirect::RightCurly); - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack.push(TokenOrRedirect::LeftCurly); true @@ -795,18 +806,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } match addr { - Addr::Lis(h) | Addr::Str(h) => { - Some(format!("{}", h)) - } + Addr::Lis(h) | Addr::Str(h) => Some(format!("{}", h)), _ => { if let Some(r) = addr.as_var() { match r { - Ref::StackCell(fr, sc) => { - Some(format!("_s_{}_{}", fr, sc)) - } - Ref::HeapCell(h) | Ref::AttrVar(h) => { - Some(format!("_{}", h)) - } + Ref::StackCell(fr, sc) => Some(format!("_s_{}_{}", fr, sc)), + Ref::HeapCell(h) | Ref::AttrVar(h) => Some(format!("_{}", h)), } } else { None @@ -818,8 +823,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn record_children_as_non_cyclic(&mut self, addr: &Addr) { match addr { &Addr::Lis(l) => { - let c1 = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l))); - let c2 = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l + 1))); + let c1 = self + .machine_st + .store(self.machine_st.deref(Addr::HeapCell(l))); + let c2 = self + .machine_st + .store(self.machine_st.deref(Addr::HeapCell(l + 1))); if let Some(c) = functor_location(&c1) { self.non_cyclic_terms.insert(c); @@ -830,18 +839,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } &Addr::Str(s) => { - let arity = - match &self.machine_st.heap[s] { - HeapCellValue::NamedStr(arity, ..) => { - arity - } - _ => { - unreachable!() - } - }; + let arity = match &self.machine_st.heap[s] { + HeapCellValue::NamedStr(arity, ..) => arity, + _ => { + unreachable!() + } + }; - for i in 1 .. arity + 1 { - let c = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(s + i))); + for i in 1..arity + 1 { + let c = self + .machine_st + .store(self.machine_st.deref(Addr::HeapCell(s + i))); if let Some(c) = functor_location(&c) { self.non_cyclic_terms.insert(c); @@ -856,15 +864,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.non_cyclic_terms.insert(c); } } - _ => { - } + _ => {} } } - fn check_for_seen( - &mut self, - iter: &mut HCPreOrderIterator, - ) -> Option { + fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator) -> Option { iter.stack().last().cloned().and_then(|addr| { let addr = self.machine_st.store(self.machine_st.deref(addr)); @@ -889,9 +893,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } None => { let offset = match functor_location(&addr) { - Some(offset) => { - offset - } + Some(offset) => offset, None => { return iter.next(); } @@ -1036,19 +1038,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let rdiv_ct = clause_name!("rdiv"); - let left_directed_op = - if spec.prec() > 0 { - Some(DirectedOp::Left(rdiv_ct.clone(), spec.clone())) - } else { - None - }; + let left_directed_op = if spec.prec() > 0 { + Some(DirectedOp::Left(rdiv_ct.clone(), spec.clone())) + } else { + None + }; - let right_directed_op = - if spec.prec() > 0 { - Some(DirectedOp::Right(rdiv_ct.clone(), spec.clone())) - } else { - None - }; + let right_directed_op = if spec.prec() > 0 { + Some(DirectedOp::Right(rdiv_ct.clone(), spec.clone())) + } else { + None + }; if spec.prec() > 0 { self.state_stack.push(TokenOrRedirect::Number( @@ -1056,10 +1056,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { left_directed_op, )); - self.state_stack.push(TokenOrRedirect::Op( - rdiv_ct, - spec.clone(), - )); + self.state_stack + .push(TokenOrRedirect::Op(rdiv_ct, spec.clone())); self.state_stack.push(TokenOrRedirect::Number( Number::from(r.numer()), @@ -1068,17 +1066,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } else { self.state_stack.push(TokenOrRedirect::Close); - self.state_stack.push(TokenOrRedirect::Number( - Number::from(r.denom()), - None, - )); + self.state_stack + .push(TokenOrRedirect::Number(Number::from(r.denom()), None)); self.state_stack.push(TokenOrRedirect::Comma); - self.state_stack.push(TokenOrRedirect::Number( - Number::from(r.numer()), - None, - )); + self.state_stack + .push(TokenOrRedirect::Number(Number::from(r.numer()), None)); self.state_stack.push(TokenOrRedirect::Open); self.state_stack.push(TokenOrRedirect::Atom(rdiv_ct)); @@ -1092,8 +1086,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - fn print_char(&mut self, is_quoted: bool, c: char) - { + fn print_char(&mut self, is_quoted: bool, c: char) { if non_quoted_token(once(c)) { let c = char_to_string(false, c); @@ -1120,46 +1113,37 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn print_proper_string(&mut self, buf: String, max_depth: usize) { self.push_char('"'); - let buf = - if max_depth == 0 { - String::from_iter(buf.chars().map(|c| { - char_to_string(self.quoted, c) - })) - } else { - let mut char_count = 0; - let mut buf = - String::from_iter(buf.chars().take(max_depth).map(|c| { - char_count += 1; - char_to_string(self.quoted, c) - })); + let buf = if max_depth == 0 { + String::from_iter(buf.chars().map(|c| char_to_string(self.quoted, c))) + } else { + let mut char_count = 0; + let mut buf = String::from_iter(buf.chars().take(max_depth).map(|c| { + char_count += 1; + char_to_string(self.quoted, c) + })); - if char_count == max_depth { - buf += " ..."; - } + if char_count == max_depth { + buf += " ..."; + } - buf - }; + buf + }; self.append_str(&buf); self.push_char('"'); } - fn print_list_like( - &mut self, - iter: &mut HCPreOrderIterator, - addr: Addr, - mut max_depth: usize, - ) { + fn print_list_like(&mut self, iter: &mut HCPreOrderIterator, addr: Addr, mut max_depth: usize) { if self.check_max_depth(&mut max_depth) { iter.stack().pop(); iter.stack().pop(); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); return; } - let mut heap_pstr_iter = - self.machine_st.heap_pstr_iter(addr); + let mut heap_pstr_iter = self.machine_st.heap_pstr_iter(addr); let buf = heap_pstr_iter.to_string(); @@ -1184,12 +1168,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let buf_len = buf.len(); - let buf_iter: Box> = - if self.max_depth == 0 { - Box::new(buf.chars()) - } else { - Box::new(buf.chars().take(max_depth)) - }; + let buf_iter: Box> = if self.max_depth == 0 { + Box::new(buf.chars()) + } else { + Box::new(buf.chars().take(max_depth)) + }; let mut byte_len = 0; @@ -1207,14 +1190,16 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { byte_len += c.len_utf8(); } - for _ in 0 .. char_count { + for _ in 0..char_count { self.state_stack.push(TokenOrRedirect::Close); } if self.max_depth > 0 && buf_len > byte_len { - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); } else { - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth)); iter.stack().push(end_addr); } } else { @@ -1232,15 +1217,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { byte_len += c.len_utf8(); } - self.state_stack.push(TokenOrRedirect::CloseList(Rc::new( - Cell::new((switch, 0)) - ))); + self.state_stack + .push(TokenOrRedirect::CloseList(Rc::new(Cell::new((switch, 0))))); if self.max_depth > 0 && buf_len > byte_len { - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); - } else { - self.outputter.truncate(self.outputter.len() - ','.len_utf8()); - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); + } else { + self.outputter + .truncate(self.outputter.len() - ','.len_utf8()); + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth)); iter.stack().push(end_addr); } @@ -1268,8 +1255,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let cell = Rc::new(Cell::new((true, 0))); - self.state_stack.push(TokenOrRedirect::CloseList(cell.clone())); - self.state_stack.push(TokenOrRedirect::Atom(clause_name!("..."))); + self.state_stack + .push(TokenOrRedirect::CloseList(cell.clone())); + self.state_stack + .push(TokenOrRedirect::Atom(clause_name!("..."))); self.state_stack.push(TokenOrRedirect::OpenList(cell)); return; @@ -1277,11 +1266,14 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let cell = Rc::new(Cell::new((true, max_depth))); - self.state_stack.push(TokenOrRedirect::CloseList(cell.clone())); + self.state_stack + .push(TokenOrRedirect::CloseList(cell.clone())); - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar - self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); + self.state_stack + .push(TokenOrRedirect::FunctorRedirect(max_depth)); self.state_stack.push(TokenOrRedirect::OpenList(cell)); } @@ -1298,23 +1290,24 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { max_depth: usize, ) { let add_brackets = if !self.ignore_ops { - negated_operand || if let Some(ref op) = op { - if self.numbervars && arity == 1 && name.as_str() == "$VAR" { - !iter.immediate_leaf_has_property(|addr, heap| { - match heap.index_addr(&addr).as_ref() { - &HeapCellValue::Integer(ref n) => &**n >= &0, - &HeapCellValue::Addr(Addr::Fixnum(n)) => n >= 0, - &HeapCellValue::Addr(Addr::Float(f)) => f >= OrderedFloat(0f64), - &HeapCellValue::Rational(ref r) => &**r >= &0, - _ => false - } - }) && needs_bracketing(&spec, op) + negated_operand + || if let Some(ref op) = op { + if self.numbervars && arity == 1 && name.as_str() == "$VAR" { + !iter.immediate_leaf_has_property(|addr, heap| { + match heap.index_addr(&addr).as_ref() { + &HeapCellValue::Integer(ref n) => &**n >= &0, + &HeapCellValue::Addr(Addr::Fixnum(n)) => n >= 0, + &HeapCellValue::Addr(Addr::Float(f)) => f >= OrderedFloat(0f64), + &HeapCellValue::Rational(ref r) => &**r >= &0, + _ => false, + } + }) && needs_bracketing(&spec, op) + } else { + needs_bracketing(&spec, op) + } } else { - needs_bracketing(&spec, op) + is_functor_redirect && spec.prec() >= 1000 } - } else { - is_functor_redirect && spec.prec() >= 1000 - } } else { false }; @@ -1344,15 +1337,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { tcp_listener: &TcpListener, max_depth: usize, ) { - let (ip, port) = - if let Some(addr) = tcp_listener.local_addr().ok() { - (addr.ip(), Number::from(addr.port() as isize)) - } else { - let disconnected_atom = clause_name!("$disconnected_tcp_listener"); - self.state_stack.push(TokenOrRedirect::Atom(disconnected_atom)); + let (ip, port) = if let Some(addr) = tcp_listener.local_addr().ok() { + (addr.ip(), Number::from(addr.port() as isize)) + } else { + let disconnected_atom = clause_name!("$disconnected_tcp_listener"); + self.state_stack + .push(TokenOrRedirect::Atom(disconnected_atom)); - return; - }; + return; + }; if self.format_struct(iter, max_depth, 1, clause_name!("$tcp_listener")) { let atom = self.state_stack.pop().unwrap(); @@ -1369,22 +1362,16 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - fn print_stream( - &mut self, - iter: &mut HCPreOrderIterator, - stream: &Stream, - max_depth: usize, - ) { + fn print_stream(&mut self, iter: &mut HCPreOrderIterator, stream: &Stream, max_depth: usize) { if let Some(alias) = &stream.options.alias { self.print_atom(alias); } else { if self.format_struct(iter, max_depth, 1, clause_name!("$stream")) { - let atom = - if stream.is_stdout() || stream.is_stdin() { - TokenOrRedirect::Atom(clause_name!("user")) - } else { - TokenOrRedirect::RawPtr(stream.as_ptr()) - }; + let atom = if stream.is_stdout() || stream.is_stdin() { + TokenOrRedirect::Atom(clause_name!("user")) + } else { + TokenOrRedirect::RawPtr(stream.as_ptr()) + }; let stream_root = self.state_stack.pop().unwrap(); @@ -1414,7 +1401,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { match self.machine_st.heap.index_addr(&addr).as_ref() { &HeapCellValue::NamedStr(arity, ref name, ref spec) => { - let spec = fetch_op_spec_from_existing(name.clone(), arity, spec.clone(), self.op_dir); + let spec = + fetch_op_spec_from_existing(name.clone(), arity, spec.clone(), self.op_dir); if let Some(spec) = spec { self.handle_op_as_struct( diff --git a/src/indexing.rs b/src/indexing.rs index 9359e18c..80bd4c17 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1,4 +1,5 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::clause_name; use crate::prolog_parser_rebis::tabled_rc::*; use crate::forms::*; @@ -43,14 +44,10 @@ 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 - } + (OptArgIndexKey::Constant(..), OptArgIndexKeyType::Constant) + | (OptArgIndexKey::Structure(..), OptArgIndexKeyType::Structure) + | (OptArgIndexKey::List(..), OptArgIndexKeyType::List) => true, + _ => false, } } } @@ -93,16 +90,20 @@ impl<'a> IndexingCodeMergingPtr<'a> { indexing_code: &'a mut Vec, append_or_prepend: AppendOrPrepend, ) -> Self { - Self { skeleton, indexing_code, offset: 0, append_or_prepend } + Self { + skeleton, + indexing_code, + offset: 0, + append_or_prepend, + } } - 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, - ); + 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(); @@ -117,7 +118,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { if let IndexingCodePtr::Internal(_) = constant_ptr { self.indexing_code.push(IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(constants) + IndexingInstruction::SwitchOnConstant(constants), )); let last_index = self.indexing_code.len() - 1; @@ -126,34 +127,39 @@ impl<'a> IndexingCodeMergingPtr<'a> { self.offset = self.indexing_code.len(); self.indexing_code.push(IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(constants) + IndexingInstruction::SwitchOnConstant(constants), )); } } - 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) - ] - }; + 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) + ] + }; let indexing_code_len = self.indexing_code.len(); - self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index)); + self.indexing_code + .push(IndexingLine::IndexedChoice(third_level_index)); match &mut self.indexing_code[self.offset] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(ref mut constants) - ) => { - constants.insert(constant, IndexingCodePtr::Internal(indexing_code_len - self.offset)); + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => { + constants.insert( + constant, + IndexingCodePtr::Internal(indexing_code_len - self.offset), + ); } _ => { unreachable!() @@ -164,10 +170,11 @@ impl<'a> IndexingCodeMergingPtr<'a> { 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)); - } + 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)); @@ -188,9 +195,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { let indexing_code_len = self.indexing_code.len(); match &mut self.indexing_code[self.offset] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { match *c { IndexingCodePtr::Fail => { *c = IndexingCodePtr::External(index); @@ -203,7 +208,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { *c = IndexingCodePtr::Internal(indexing_code_len); self.indexing_code.push(IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(constants) + IndexingInstruction::SwitchOnConstant(constants), )); self.offset = indexing_code_len; @@ -213,12 +218,11 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } } - IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(constants) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => { match constants.get(&overlapping_constant).cloned() { None | Some(IndexingCodePtr::Fail) => { - constants.insert(overlapping_constant, IndexingCodePtr::External(index)); + constants + .insert(overlapping_constant, IndexingCodePtr::External(index)); } Some(IndexingCodePtr::External(o)) => { self.add_indexed_choice_for_constant(o, overlapping_constant, index); @@ -232,9 +236,9 @@ impl<'a> IndexingCodeMergingPtr<'a> { break; } IndexingLine::IndexedChoice(_) => { - self.internalize_constant( - IndexingCodePtr::Internal(indexing_code_len - self.offset), - ); + self.internalize_constant(IndexingCodePtr::Internal( + indexing_code_len - self.offset, + )); } _ => { unreachable!() @@ -248,9 +252,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { let indexing_code_len = self.indexing_code.len(); match &mut self.indexing_code[self.offset] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { match *c { IndexingCodePtr::Fail => { *c = IndexingCodePtr::External(index); @@ -265,9 +267,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } } - IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(constants) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => { match constants.get(&constant).cloned() { None | Some(IndexingCodePtr::Fail) => { constants.insert(constant, IndexingCodePtr::External(index)); @@ -284,9 +284,9 @@ impl<'a> IndexingCodeMergingPtr<'a> { break; } IndexingLine::IndexedChoice(_) => { - self.internalize_constant( - IndexingCodePtr::Internal(indexing_code_len - self.offset), - ); + self.internalize_constant(IndexingCodePtr::Internal( + indexing_code_len - self.offset, + )); } _ => { unreachable!() @@ -295,13 +295,12 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } - 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, - ); + 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, + ); let mut structures = IndexMap::new(); @@ -316,7 +315,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { if let IndexingCodePtr::Internal(_) = structure_ptr { self.indexing_code.push(IndexingLine::Indexing( - IndexingInstruction::SwitchOnStructure(structures) + IndexingInstruction::SwitchOnStructure(structures), )); let last_index = self.indexing_code.len() - 1; @@ -325,34 +324,39 @@ impl<'a> IndexingCodeMergingPtr<'a> { self.offset = self.indexing_code.len(); self.indexing_code.push(IndexingLine::Indexing( - IndexingInstruction::SwitchOnStructure(structures) + IndexingInstruction::SwitchOnStructure(structures), )); } } - 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) - ] - }; + 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)); + self.indexing_code + .push(IndexingLine::IndexedChoice(third_level_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)); + IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => { + structures.insert( + key, + IndexingCodePtr::Internal(indexing_code_len - self.offset), + ); } _ => { unreachable!() @@ -365,26 +369,26 @@ impl<'a> IndexingCodeMergingPtr<'a> { 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::SwitchOnTerm( + _, + _, + _, + _, + ref mut s, + )) => match *s { + IndexingCodePtr::Fail => { + *s = IndexingCodePtr::External(index); + break; } - } - IndexingLine::Indexing( - IndexingInstruction::SwitchOnStructure(structures) - ) => { + 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)); @@ -404,9 +408,9 @@ impl<'a> IndexingCodeMergingPtr<'a> { // 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), - ); + self.internalize_structure(IndexingCodePtr::Internal( + indexing_code_len - self.offset, + )); } _ => { unreachable!() @@ -419,9 +423,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { let indexing_code_len = self.indexing_code.len(); match &mut self.indexing_code[self.offset] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)) => { match *l { IndexingCodePtr::Fail => { *l = IndexingCodePtr::External(index); @@ -429,22 +431,20 @@ impl<'a> IndexingCodeMergingPtr<'a> { IndexingCodePtr::External(o) => { *l = IndexingCodePtr::Internal(indexing_code_len - self.offset); - 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 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) + ] + }; - self.indexing_code.push( - IndexingLine::IndexedChoice(third_level_index), - ); + self.indexing_code + .push(IndexingLine::IndexedChoice(third_level_index)); } IndexingCodePtr::Internal(o) => { self.offset += o; @@ -462,24 +462,16 @@ impl<'a> IndexingCodeMergingPtr<'a> { pub fn merge_clause_index( target_indexing_code: &mut Vec, 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. + 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 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, - ); + 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) => { @@ -488,7 +480,9 @@ pub fn merge_clause_index( for overlapping_constant in overlapping_constants { merging_ptr.index_overlapping_constant( - constant, overlapping_constant.clone(), offset, + constant, + overlapping_constant.clone(), + offset, ); } } @@ -514,10 +508,7 @@ pub fn merge_clause_index( } #[inline] -fn remove_instruction_with_offset( - code: &mut SliceDeque, - offset: usize, -) { +fn remove_instruction_with_offset(code: &mut SliceDeque, offset: usize) { for (index, line) in code.iter().enumerate() { if offset == line.offset() { code.remove(index); @@ -537,9 +528,7 @@ pub fn remove_constant_indices( let iter = once(constant).chain(overlapping_constants.iter()); match &mut indexing_code[index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { match *c { IndexingCodePtr::External(_) => { *c = IndexingCodePtr::Fail; @@ -560,12 +549,13 @@ pub fn remove_constant_indices( let mut constants_index = 0; - for constant in iter { // (constant, index_loc) in iter.zip(index_locs.iter()) { + 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) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant( + ref mut constants, + )) => { constants_index = index; match constants.get(constant).cloned() { @@ -586,18 +576,21 @@ pub fn remove_constant_indices( if indexed_choice_instrs.len() == 1 { let ext = IndexingCodePtr::External( - indexed_choice_instrs.pop_back().unwrap().offset() + indexed_choice_instrs.pop_back().unwrap().offset(), ); match &mut indexing_code[constants_index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( + _, + _, + ref mut c, + .., + )) => { *c = ext; } - IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(ref mut constants) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant( + ref mut constants, + )) => { constants.insert(constant.clone(), ext); } _ => { @@ -616,13 +609,11 @@ pub fn remove_constant_indices( } match &indexing_code[constants_index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnConstant(ref constants) - ) if constants.is_empty() => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref constants)) + if constants.is_empty() => + { match &mut indexing_code[0] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { *c = IndexingCodePtr::Fail; } _ => { @@ -630,8 +621,7 @@ pub fn remove_constant_indices( } } } - _ => { - } + _ => {} } } @@ -644,9 +634,7 @@ pub fn remove_structure_index( let mut index = 0; match &mut indexing_code[index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s)) => { match *s { IndexingCodePtr::External(_) => { *s = IndexingCodePtr::Fail; @@ -669,9 +657,7 @@ pub fn remove_structure_index( loop { match &mut indexing_code[index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnStructure(ref mut structures) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref mut structures)) => { structures_index = index; match structures.get(&(name.clone(), arity)).cloned() { @@ -692,18 +678,22 @@ pub fn remove_structure_index( if indexed_choice_instrs.len() == 1 { let ext = IndexingCodePtr::External( - indexed_choice_instrs.pop_back().unwrap().offset() + indexed_choice_instrs.pop_back().unwrap().offset(), ); match &mut indexing_code[structures_index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( + _, + _, + _, + _, + ref mut s, + )) => { *s = ext; } - IndexingLine::Indexing( - IndexingInstruction::SwitchOnStructure(ref mut structures) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure( + ref mut structures, + )) => { structures.insert((name.clone(), arity), ext); } _ => { @@ -721,13 +711,17 @@ pub fn remove_structure_index( } match &indexing_code[structures_index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnStructure(ref structures) - ) if structures.is_empty() => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref structures)) + if structures.is_empty() => + { match &mut indexing_code[0] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( + _, + _, + _, + _, + ref mut s, + )) => { *s = IndexingCodePtr::Fail; } _ => { @@ -735,21 +729,15 @@ pub fn remove_structure_index( } } } - _ => { - } + _ => {} } } -pub fn remove_list_index( - indexing_code: &mut Vec, - offset: usize, -) { +pub fn remove_list_index(indexing_code: &mut Vec, offset: usize) { let mut index = 0; match &mut indexing_code[index] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)) => { match *l { IndexingCodePtr::External(_) => { *l = IndexingCodePtr::Fail; @@ -773,14 +761,17 @@ pub fn remove_list_index( 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() - ); + let ext = + IndexingCodePtr::External(indexed_choice_instrs.pop_back().unwrap().offset()); match &mut indexing_code[0] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _) - ) => { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( + _, + _, + _, + ref mut l, + _, + )) => { *l = ext; } _ => { @@ -836,8 +827,7 @@ pub fn remove_index( fn second_level_index( indices: IndexMap>, prelude: &mut SliceDeque, -) -> IndexMap -{ +) -> IndexMap { let mut index_locs = IndexMap::new(); for (key, mut code) in indices.into_iter() { @@ -868,10 +858,11 @@ fn switch_on( IndexingCodePtr::Internal(1) } else { - index.into_iter() - .next() - .map(|(_, v)| v) - .unwrap_or(IndexingCodePtr::Fail) + index + .into_iter() + .next() + .map(|(_, v)| v) + .unwrap_or(IndexingCodePtr::Fail) } } @@ -884,9 +875,10 @@ fn switch_on_list( prelude.push_back(IndexingLine::from(lists)); IndexingCodePtr::Internal(1) } else { - lists.first() - .map(|i| IndexingCodePtr::External(i.offset())) - .unwrap_or(IndexingCodePtr::Fail) + lists + .first() + .map(|i| IndexingCodePtr::External(i.offset())) + .unwrap_or(IndexingCodePtr::Fail) } } @@ -978,8 +970,7 @@ pub fn constant_key_alternatives(constant: &Constant, atom_tbl: TabledData constants.push(Constant::Fixnum(n)); } } - _ => { - } + _ => {} } constants @@ -1001,7 +992,7 @@ impl CodeOffsets { constants: IndexMap::new(), lists: sdeq![], structures: IndexMap::new(), - optimal_index + optimal_index, } } @@ -1011,20 +1002,15 @@ impl CodeOffsets { } fn index_constant(&mut self, constant: &Constant, index: usize) -> Vec { - let overlapping_constants = - constant_key_alternatives(constant, self.atom_tbl.clone()); + let overlapping_constants = constant_key_alternatives(constant, self.atom_tbl.clone()); - let code = self.constants - .entry(constant.clone()) - .or_insert(sdeq![]); + 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 code = self.constants.entry(constant.clone()).or_insert(sdeq![]); let is_initial_index = code.is_empty(); let index = compute_index(is_initial_index, index); @@ -1062,25 +1048,21 @@ impl CodeOffsets { 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); + 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); + 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, - ); - } - _ => { + clause_index_info.opt_arg_index_key = OptArgIndexKey::Constant( + self.optimal_index, + 0, + constant.clone(), + overlapping_constants, + ); } + _ => {} } } @@ -1117,8 +1099,7 @@ impl CodeOffsets { IndexingCodePtr::Internal(ref mut i) => { *i += con_loc.is_internal() as usize; } - _ => { - } + _ => {} }; match &mut lst_loc { @@ -1126,15 +1107,18 @@ impl CodeOffsets { *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) - )); + prelude.push_front(IndexingLine::from(IndexingInstruction::SwitchOnTerm( + self.optimal_index, + var_offset, + con_loc, + lst_loc, + str_loc, + ))); prelude.into_iter().collect() } diff --git a/src/instructions.rs b/src/instructions.rs index d27d120a..91982ea2 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,4 +1,5 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::clause_name; use crate::clause_types::*; use crate::forms::*; @@ -34,9 +35,7 @@ impl Level { impl ArithmeticTerm { fn into_functor(&self) -> MachineStub { match self { - &ArithmeticTerm::Reg(r) => { - reg_type_into_functor(r) - } + &ArithmeticTerm::Reg(r) => reg_type_into_functor(r), &ArithmeticTerm::Interm(i) => { functor!("intermediate", [integer(i)]) } @@ -185,16 +184,11 @@ impl Line { pub fn enqueue_functors(&self, mut h: usize, functors: &mut Vec) { match self { - &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::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 { @@ -213,10 +207,10 @@ impl Line { } } } - &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)), + &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)), } } } @@ -224,24 +218,16 @@ impl Line { #[inline] pub fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec> { match line { - Line::IndexingCode(ref mut indexing_code) => { - Some(indexing_code) - } - _ => { - None - } + Line::IndexingCode(ref mut indexing_code) => Some(indexing_code), + _ => None, } } #[inline] pub fn to_indexing_line(line: &Line) -> Option<&Vec> { match line { - Line::IndexingCode(ref indexing_code) => { - Some(indexing_code) - } - _ => { - None - } + Line::IndexingCode(ref indexing_code) => Some(indexing_code), + _ => None, } } @@ -296,11 +282,7 @@ fn arith_instr_unary_functor( ) -> MachineStub { let at_stub = at.into_functor(); - functor!( - name, - [aux(h, 0), integer(t)], - [at_stub] - ) + functor!(name, [aux(h, 0), integer(t)], [at_stub]) } fn arith_instr_bin_functor( @@ -383,39 +365,17 @@ impl ArithmeticInstruction { &ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => { arith_instr_bin_functor(h, "gcd", at_1, at_2, t) } - &ArithmeticInstruction::Sign(ref at, t) => { - arith_instr_unary_functor(h, "sign", at, t) - } - &ArithmeticInstruction::Cos(ref at, t) => { - arith_instr_unary_functor(h, "cos", at, t) - } - &ArithmeticInstruction::Sin(ref at, t) => { - arith_instr_unary_functor(h, "sin", at, t) - } - &ArithmeticInstruction::Tan(ref at, t) => { - arith_instr_unary_functor(h, "tan", at, t) - } - &ArithmeticInstruction::Log(ref at, t) => { - arith_instr_unary_functor(h, "log", at, t) - } - &ArithmeticInstruction::Exp(ref at, t) => { - arith_instr_unary_functor(h, "exp", at, t) - } - &ArithmeticInstruction::ACos(ref at, t) => { - arith_instr_unary_functor(h, "acos", at, t) - } - &ArithmeticInstruction::ASin(ref at, t) => { - arith_instr_unary_functor(h, "asin", at, t) - } - &ArithmeticInstruction::ATan(ref at, t) => { - arith_instr_unary_functor(h, "atan", at, t) - } - &ArithmeticInstruction::Sqrt(ref at, t) => { - arith_instr_unary_functor(h, "sqrt", at, t) - } - &ArithmeticInstruction::Abs(ref at, t) => { - arith_instr_unary_functor(h, "abs", at, t) - } + &ArithmeticInstruction::Sign(ref at, t) => arith_instr_unary_functor(h, "sign", at, t), + &ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t), + &ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t), + &ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t), + &ArithmeticInstruction::Log(ref at, t) => arith_instr_unary_functor(h, "log", at, t), + &ArithmeticInstruction::Exp(ref at, t) => arith_instr_unary_functor(h, "exp", at, t), + &ArithmeticInstruction::ACos(ref at, t) => arith_instr_unary_functor(h, "acos", at, t), + &ArithmeticInstruction::ASin(ref at, t) => arith_instr_unary_functor(h, "asin", at, t), + &ArithmeticInstruction::ATan(ref at, t) => arith_instr_unary_functor(h, "atan", at, t), + &ArithmeticInstruction::Sqrt(ref at, t) => arith_instr_unary_functor(h, "sqrt", at, t), + &ArithmeticInstruction::Abs(ref at, t) => arith_instr_unary_functor(h, "abs", at, t), &ArithmeticInstruction::Float(ref at, t) => { arith_instr_unary_functor(h, "float", at, t) } @@ -431,12 +391,8 @@ impl ArithmeticInstruction { &ArithmeticInstruction::Floor(ref at, t) => { arith_instr_unary_functor(h, "floor", at, t) } - &ArithmeticInstruction::Neg(ref at, t) => { - arith_instr_unary_functor(h, "-", at, t) - } - &ArithmeticInstruction::Plus(ref at, t) => { - arith_instr_unary_functor(h, "+", at, t) - } + &ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(h, "-", at, t), + &ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(h, "+", at, t), &ArithmeticInstruction::BitwiseComplement(ref at, t) => { arith_instr_unary_functor(h, "\\", at, t) } @@ -451,21 +407,18 @@ pub enum ControlInstruction { 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. + RevJmpBy(usize), // notice the lack of context change as in + // JmpBy. RevJmpBy is used only to patch extensible + // predicates together. Proceed, } impl ControlInstruction { pub fn perm_vars(&self) -> Option { match self { - ControlInstruction::CallClause(_, _, num_cells, ..) => - Some(*num_cells), - ControlInstruction::JmpBy(_, _, num_cells, ..) => - Some(*num_cells), - _ => - None + ControlInstruction::CallClause(_, _, num_cells, ..) => Some(*num_cells), + ControlInstruction::JmpBy(_, _, num_cells, ..) => Some(*num_cells), + _ => None, } } @@ -500,7 +453,13 @@ impl ControlInstruction { #[derive(Debug)] pub enum IndexingInstruction { // The first index is the optimal argument being indexed. - SwitchOnTerm(usize, usize, IndexingCodePtr, IndexingCodePtr, IndexingCodePtr), + SwitchOnTerm( + usize, + usize, + IndexingCodePtr, + IndexingCodePtr, + IndexingCodePtr, + ), SwitchOnConstant(IndexMap), SwitchOnStructure(IndexMap<(ClauseName, usize), IndexingCodePtr>), } @@ -511,11 +470,13 @@ impl IndexingInstruction { &IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => { functor!( "switch_on_term", - [integer(arg), - integer(vars), - indexing_code_ptr(h, constants), - indexing_code_ptr(h, lists), - indexing_code_ptr(h, structures)] + [ + integer(arg), + integer(vars), + indexing_code_ptr(h, constants), + indexing_code_ptr(h, lists), + indexing_code_ptr(h, structures) + ] ) } &IndexingInstruction::SwitchOnConstant(ref constants) => { @@ -528,15 +489,14 @@ impl IndexingInstruction { let key_value_pair = functor!( ":", SharedOpDesc::new(600, XFY), - [constant(c), - indexing_code_ptr(h + 3, *ptr)] + [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()) - )); + 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()); @@ -560,23 +520,21 @@ impl IndexingInstruction { let predicate_indicator_stub = functor!( "/", SharedOpDesc::new(400, YFX), - [clause_name(name.clone()), - integer(*arity)] + [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)], + [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()) - )); + 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()); @@ -614,7 +572,7 @@ impl FactInstruction { match self { &FactInstruction::GetConstant(lvl, ref c, r) => { let lvl_stub = lvl.into_functor(); - let rt_stub = reg_type_into_functor(r); + let rt_stub = reg_type_into_functor(r); functor!( "get_constant", @@ -624,17 +582,13 @@ impl FactInstruction { } &FactInstruction::GetList(lvl, r) => { let lvl_stub = lvl.into_functor(); - let rt_stub = reg_type_into_functor(r); + let rt_stub = reg_type_into_functor(r); - functor!( - "get_list", - [aux(h, 0), aux(h, 1)], - [lvl_stub, rt_stub] - ) + functor!("get_list", [aux(h, 0), aux(h, 1)], [lvl_stub, rt_stub]) } &FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => { let lvl_stub = lvl.into_functor(); - let rt_stub = reg_type_into_functor(r); + let rt_stub = reg_type_into_functor(r); functor!( "get_partial_string", @@ -654,20 +608,12 @@ impl FactInstruction { &FactInstruction::GetValue(r, arg) => { let rt_stub = reg_type_into_functor(r); - functor!( - "get_value", - [aux(h, 0), integer(arg)], - [rt_stub] - ) + functor!("get_value", [aux(h, 0), integer(arg)], [rt_stub]) } &FactInstruction::GetVariable(r, arg) => { let rt_stub = reg_type_into_functor(r); - functor!( - "get_variable", - [aux(h, 0), integer(arg)], - [rt_stub] - ) + functor!("get_variable", [aux(h, 0), integer(arg)], [rt_stub]) } &FactInstruction::UnifyConstant(ref c) => { functor!("unify_constant", [constant(h, c)], []) @@ -675,29 +621,17 @@ impl FactInstruction { &FactInstruction::UnifyLocalValue(r) => { let rt_stub = reg_type_into_functor(r); - functor!( - "unify_local_value", - [aux(h, 0)], - [rt_stub] - ) + functor!("unify_local_value", [aux(h, 0)], [rt_stub]) } &FactInstruction::UnifyVariable(r) => { let rt_stub = reg_type_into_functor(r); - functor!( - "unify_variable", - [aux(h, 0)], - [rt_stub] - ) + functor!("unify_variable", [aux(h, 0)], [rt_stub]) } &FactInstruction::UnifyValue(r) => { let rt_stub = reg_type_into_functor(r); - functor!( - "unify_value", - [aux(h, 0)], - [rt_stub] - ) + functor!("unify_value", [aux(h, 0)], [rt_stub]) } &FactInstruction::UnifyVoid(vars) => { functor!("unify_void", [integer(vars)]) @@ -726,13 +660,12 @@ pub enum QueryInstruction { impl QueryInstruction { pub fn to_functor(&self, h: usize) -> MachineStub { match self { - &QueryInstruction::PutUnsafeValue(norm, arg) => functor!( - "put_unsafe_value", - [integer(norm), integer(arg)] - ), + &QueryInstruction::PutUnsafeValue(norm, arg) => { + functor!("put_unsafe_value", [integer(norm), integer(arg)]) + } &QueryInstruction::PutConstant(lvl, ref c, r) => { let lvl_stub = lvl.into_functor(); - let rt_stub = reg_type_into_functor(r); + let rt_stub = reg_type_into_functor(r); functor!( "put_constant", @@ -742,17 +675,13 @@ impl QueryInstruction { } &QueryInstruction::PutList(lvl, r) => { let lvl_stub = lvl.into_functor(); - let rt_stub = reg_type_into_functor(r); + let rt_stub = reg_type_into_functor(r); - functor!( - "put_list", - [aux(h, 0), aux(h, 1)], - [lvl_stub, rt_stub] - ) + functor!("put_list", [aux(h, 0), aux(h, 1)], [lvl_stub, rt_stub]) } &QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => { let lvl_stub = lvl.into_functor(); - let rt_stub = reg_type_into_functor(r); + let rt_stub = reg_type_into_functor(r); functor!( "put_partial_string", @@ -772,29 +701,17 @@ impl QueryInstruction { &QueryInstruction::PutValue(r, arg) => { let rt_stub = reg_type_into_functor(r); - functor!( - "put_value", - [aux(h, 0), integer(arg)], - [rt_stub] - ) + functor!("put_value", [aux(h, 0), integer(arg)], [rt_stub]) } &QueryInstruction::GetVariable(r, arg) => { let rt_stub = reg_type_into_functor(r); - functor!( - "get_variable", - [aux(h, 0), integer(arg)], - [rt_stub] - ) + functor!("get_variable", [aux(h, 0), integer(arg)], [rt_stub]) } &QueryInstruction::PutVariable(r, arg) => { let rt_stub = reg_type_into_functor(r); - functor!( - "put_variable", - [aux(h, 0), integer(arg)], - [rt_stub] - ) + functor!("put_variable", [aux(h, 0), integer(arg)], [rt_stub]) } &QueryInstruction::SetConstant(ref c) => { functor!("set_constant", [constant(h, c)], []) @@ -802,29 +719,17 @@ impl QueryInstruction { &QueryInstruction::SetLocalValue(r) => { let rt_stub = reg_type_into_functor(r); - functor!( - "set_local_value", - [aux(h, 0)], - [rt_stub] - ) + functor!("set_local_value", [aux(h, 0)], [rt_stub]) } &QueryInstruction::SetVariable(r) => { let rt_stub = reg_type_into_functor(r); - functor!( - "set_variable", - [aux(h, 0)], - [rt_stub] - ) + functor!("set_variable", [aux(h, 0)], [rt_stub]) } &QueryInstruction::SetValue(r) => { let rt_stub = reg_type_into_functor(r); - functor!( - "set_value", - [aux(h, 0)], - [rt_stub] - ) + functor!("set_value", [aux(h, 0)], [rt_stub]) } &QueryInstruction::SetVoid(vars) => { functor!("set_void", [integer(vars)]) diff --git a/src/iterators.rs b/src/iterators.rs index a3b5956b..ce3733ec 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -1,4 +1,5 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::rc_atom; use crate::clause_types::*; use crate::forms::*; @@ -25,11 +26,11 @@ impl<'a> TermRef<'a> { pub fn level(self) -> Level { match self { TermRef::AnonVar(lvl) - | TermRef::Cons(lvl, ..) - | TermRef::Constant(lvl, ..) - | TermRef::Var(lvl, ..) - | TermRef::Clause(lvl, ..) => lvl, - | TermRef::PartialString(lvl, ..) => lvl, + | TermRef::Cons(lvl, ..) + | TermRef::Constant(lvl, ..) + | TermRef::Var(lvl, ..) + | TermRef::Clause(lvl, ..) => lvl, + TermRef::PartialString(lvl, ..) => lvl, } } } @@ -51,23 +52,16 @@ pub enum TermIterState<'a> { Var(Level, &'a Cell, Rc), } -fn is_partial_string<'a>( - head: &'a Term, - mut tail: &'a Term, -) -> Option<(String, Option<&'a Term>)> -{ - let mut string = - match head { - &Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => { - atom.as_str().chars().next().unwrap().to_string() - } - &Term::Constant(_, Constant::Char(c)) => { - c.to_string() - } - _ => { - return None; - } - }; +fn is_partial_string<'a>(head: &'a Term, mut tail: &'a Term) -> Option<(String, Option<&'a Term>)> { + let mut string = match head { + &Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => { + atom.as_str().chars().next().unwrap().to_string() + } + &Term::Constant(_, Constant::Char(c)) => c.to_string(), + _ => { + return None; + } + }; while let Term::Cons(_, ref head, ref succ) = tail { match head.as_ref() { @@ -105,9 +99,7 @@ fn is_partial_string<'a>( impl<'a> TermIterState<'a> { pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { match term { - &Term::AnonVar => { - TermIterState::AnonVar(lvl) - } + &Term::AnonVar => TermIterState::AnonVar(lvl), &Term::Clause(ref cell, ref name, ref subterms, ref spec) => { let ct = if let Some(spec) = spec { ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default()) @@ -120,12 +112,8 @@ impl<'a> TermIterState<'a> { &Term::Cons(ref cell, ref head, ref tail) => { TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()) } - &Term::Constant(ref cell, ref constant) => { - TermIterState::Constant(lvl, cell, constant) - } - &Term::Var(ref cell, ref var) => { - TermIterState::Var(lvl, cell, var.clone()) - } + &Term::Constant(ref cell, ref constant) => TermIterState::Constant(lvl, cell, constant), + &Term::Var(ref cell, ref var) => TermIterState::Var(lvl, cell, var.clone()), } } } @@ -175,8 +163,7 @@ impl<'a> QueryIterator<'a> { state_stack: vec![], } } - &Term::Var(ref cell, ref var) => - TermIterState::Var(Level::Root, cell, (*var).clone()), + &Term::Var(ref cell, ref var) => TermIterState::Var(Level::Root, cell, (*var).clone()), }; QueryIterator { @@ -265,18 +252,15 @@ impl<'a> Iterator for QueryIterator<'a> { } TermIterState::InitialCons(lvl, cell, head, tail) => { if let Some((string, tail)) = is_partial_string(head, tail) { - self.state_stack.push(TermIterState::PartialString( - lvl, - cell, - string, - tail, - )); + self.state_stack + .push(TermIterState::PartialString(lvl, cell, string, tail)); if let Some(tail) = tail { self.push_subterm(lvl.child_level(), tail); } } else { - self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail)); + self.state_stack + .push(TermIterState::FinalCons(lvl, cell, head, tail)); self.push_subterm(lvl.child_level(), tail); self.push_subterm(lvl.child_level(), head); @@ -309,7 +293,8 @@ pub struct FactIterator<'a> { impl<'a> FactIterator<'a> { fn push_subterm(&mut self, lvl: Level, term: &'a Term) { - self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term)); + self.state_queue + .push_back(TermIterState::subterm_to_state(lvl, term)); } pub fn from_rule_head_clause(terms: &'a Vec>) -> Self { @@ -393,8 +378,7 @@ impl<'a> Iterator for FactIterator<'a> { TermIterState::Var(lvl, cell, var) => { return Some(TermRef::Var(lvl, cell, var)); } - _ => { - } + _ => {} } } @@ -481,16 +465,16 @@ impl<'a> ChunkedIterator<'a> { } })) } -/* - pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self { - ChunkedIterator { - chunk_num: 0, - iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))), - deep_cut_encountered: false, - cut_var_in_head: false, + /* + pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self { + ChunkedIterator { + chunk_num: 0, + iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))), + deep_cut_encountered: false, + cut_var_in_head: false, + } } - } -*/ + */ pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec) -> Self { let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))); diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 0c8fb8ff..aee346a2 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1,6 +1,7 @@ use crate::divrem::*; use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::clause_name; use crate::arithmetic::*; use crate::clause_types::*; @@ -19,19 +20,16 @@ use std::rc::Rc; #[macro_export] macro_rules! try_numeric_result { - ($s: ident, $e: expr, $caller: expr) => ( + ($s: ident, $e: expr, $caller: expr) => { match $e { - Ok(val) => { - Ok(val) - } + Ok(val) => Ok(val), Err(e) => { - let caller_copy = - $caller.iter().map(|v| v.context_free_clone()).collect(); + let caller_copy = $caller.iter().map(|v| v.context_free_clone()).collect(); Err($s.error_form(MachineError::evaluation_error(e), caller_copy)) } } - ); + }; } fn isize_gcd(n1: isize, n2: isize) -> Option { @@ -83,52 +81,29 @@ fn isize_gcd(n1: isize, n2: isize) -> Option { } impl MachineState { - pub(crate) - fn get_number(&mut self, at: &ArithmeticTerm) -> Result { + pub(crate) fn get_number(&mut self, at: &ArithmeticTerm) -> Result { match at { - &ArithmeticTerm::Reg(r) => { - self.arith_eval_by_metacall(r) - } - &ArithmeticTerm::Interm(i) => Ok(mem::replace( - &mut self.interms[i - 1], - Number::Fixnum(0), - )), - &ArithmeticTerm::Number(ref n) => { - Ok(n.clone()) + &ArithmeticTerm::Reg(r) => self.arith_eval_by_metacall(r), + &ArithmeticTerm::Interm(i) => { + Ok(mem::replace(&mut self.interms[i - 1], Number::Fixnum(0))) } + &ArithmeticTerm::Number(ref n) => Ok(n.clone()), } } - pub(super) - fn rational_from_number( - &self, - n: Number, - ) -> Result, MachineError> { + pub(super) fn rational_from_number(&self, n: Number) -> Result, MachineError> { match n { - Number::Fixnum(n) => { - Ok(Rc::new(Rational::from(n))) - } - Number::Rational(r) => { - Ok(r) - } - Number::Float(OrderedFloat(f)) => { - match Rational::from_f64(f) { - Some(r) => { - Ok(Rc::new(r)) - } - None => { - Err(MachineError::instantiation_error()) - } - } - } - Number::Integer(n) => { - Ok(Rc::new(Rational::from(&*n))) - } + Number::Fixnum(n) => Ok(Rc::new(Rational::from(n))), + Number::Rational(r) => Ok(r), + Number::Float(OrderedFloat(f)) => match Rational::from_f64(f) { + Some(r) => Ok(Rc::new(r)), + None => Err(MachineError::instantiation_error()), + }, + Number::Integer(n) => Ok(Rc::new(Rational::from(&*n))), } } - pub(crate) - fn get_rational( + pub(crate) fn get_rational( &mut self, at: &ArithmeticTerm, caller: MachineStub, @@ -137,12 +112,11 @@ impl MachineState { match self.rational_from_number(n) { Ok(r) => Ok((r, caller)), - Err(e) => Err(self.error_form(e, caller)) + Err(e) => Err(self.error_form(e, caller)), } } - pub(crate) - fn arith_eval_by_metacall(&self, r: RegType) -> Result { + pub(crate) fn arith_eval_by_metacall(&self, r: RegType) -> Result { let caller = MachineError::functor_stub(clause_name!("is"), 2); let mut interms: Vec = Vec::with_capacity(64); @@ -163,9 +137,8 @@ impl MachineState { "min" => interms.push(self.min(a1, a2)?), "rdiv" => { let r1 = self.rational_from_number(a1); - let r2 = r1.and_then(|r1| { - self.rational_from_number(a2).map(|r2| (r1, r2)) - }); + let r2 = + r1.and_then(|r1| self.rational_from_number(a2).map(|r2| (r1, r2))); match r2 { Ok((r1, r2)) => { @@ -242,18 +215,12 @@ impl MachineState { &HeapCellValue::Addr(Addr::Fixnum(n)) => { interms.push(Number::Fixnum(n)); } - &HeapCellValue::Addr(Addr::Float(n)) => { - interms.push(Number::Float(n)) - } - &HeapCellValue::Integer(ref n) => { - interms.push(Number::Integer(n.clone())) - } + &HeapCellValue::Addr(Addr::Float(n)) => interms.push(Number::Float(n)), + &HeapCellValue::Integer(ref n) => interms.push(Number::Integer(n.clone())), &HeapCellValue::Addr(Addr::Usize(n)) => { interms.push(Number::Integer(Rc::new(Integer::from(n)))); } - &HeapCellValue::Rational(ref n) => { - interms.push(Number::Rational(n.clone())) - } + &HeapCellValue::Rational(ref n) => interms.push(Number::Rational(n.clone())), &HeapCellValue::Atom(ref name, _) if name.as_str() == "pi" => { interms.push(Number::Float(OrderedFloat(f64::consts::PI))) } @@ -282,10 +249,7 @@ impl MachineState { )); } &HeapCellValue::Addr(addr) if addr.is_ref() => { - return Err(self.error_form( - MachineError::instantiation_error(), - caller, - )); + return Err(self.error_form(MachineError::instantiation_error(), caller)); } val => { return Err(self.type_error( @@ -301,8 +265,7 @@ impl MachineState { Ok(interms.pop().unwrap()) } - pub(crate) - fn rdiv(&self, r1: Rc, r2: Rc) -> Result { + pub(crate) fn rdiv(&self, r1: Rc, r2: Rc) -> Result { if &*r2 == &0 { let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2); Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) @@ -311,27 +274,21 @@ impl MachineState { } } - pub(crate) - fn int_floor_div(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn int_floor_div(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(div)"), 2); let modulus = self.modulus(n1.clone(), n2.clone())?; self.idiv(try_numeric_result!(self, n1 - modulus, stub)?, n2) } - pub(crate) - fn idiv(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn idiv(&self, n1: Number, n2: Number) -> Result { match (n1, n2) { (Number::Fixnum(n1), Number::Fixnum(n2)) => { if n2 == 0 { let stub = MachineError::functor_stub(clause_name!("(//)"), 2); - Err(self.error_form( - MachineError::evaluation_error( - EvalError::ZeroDivisor - ), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { if let Some(result) = n1.checked_div(n2) { Ok(Number::from(result)) @@ -347,12 +304,8 @@ impl MachineState { if &*n2 == &0 { let stub = MachineError::functor_stub(clause_name!("(//)"), 2); - Err(self.error_form( - MachineError::evaluation_error( - EvalError::ZeroDivisor - ), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { Ok(Number::from(Integer::from(n1) / &*n2)) } @@ -361,12 +314,8 @@ impl MachineState { if n1 == 0 { let stub = MachineError::functor_stub(clause_name!("(//)"), 2); - Err(self.error_form( - MachineError::evaluation_error( - EvalError::ZeroDivisor - ), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { Ok(Number::from(&*n2 / Integer::from(n1))) } @@ -375,25 +324,19 @@ impl MachineState { if &*n2 == &0 { let stub = MachineError::functor_stub(clause_name!("(//)"), 2); - Err(self.error_form( - MachineError::evaluation_error( - EvalError::ZeroDivisor - ), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { - Ok(Number::from(<(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0)) + Ok(Number::from( + <(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0, + )) } } (Number::Fixnum(_), n2) | (Number::Integer(_), n2) => { let stub = MachineError::functor_stub(clause_name!("(//)"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), stub, )) } @@ -401,19 +344,14 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("(//)"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )) } } } - pub(crate) - fn div(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn div(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(/)"), 2); if n2.is_zero() { @@ -423,8 +361,7 @@ impl MachineState { } } - pub(crate) - fn atan2(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn atan2(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("is"), 2); if n1.is_zero() && n2.is_zero() { @@ -437,8 +374,7 @@ impl MachineState { } } - pub(crate) - fn int_pow(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn int_pow(&self, n1: Number, n2: Number) -> Result { if n1.is_zero() && n2.is_negative() { let stub = MachineError::functor_stub(clause_name!("is"), 2); return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)); @@ -451,11 +387,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("^"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Float, - n - ), + MachineError::type_error(self.heap.h(), ValidType::Float, n), stub, )) } else { @@ -477,11 +409,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("^"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Float, - n - ), + MachineError::type_error(self.heap.h(), ValidType::Float, n), stub, )) } else { @@ -495,11 +423,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("^"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Float, - n - ), + MachineError::type_error(self.heap.h(), ValidType::Float, n), stub, )) } else { @@ -513,11 +437,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("^"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Float, - n - ), + MachineError::type_error(self.heap.h(), ValidType::Float, n), stub, )) } else { @@ -548,8 +468,7 @@ impl MachineState { } } - pub(crate) - fn gcd(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn gcd(&self, n1: Number, n2: Number) -> Result { match (n1, n2) { (Number::Fixnum(n1), Number::Fixnum(n2)) => { if let Some(result) = isize_gcd(n1, n2) { @@ -558,8 +477,8 @@ impl MachineState { Ok(Number::from(Integer::from(n1).gcd(&Integer::from(n2)))) } } - (Number::Fixnum(n1), Number::Integer(n2)) | - (Number::Integer(n2), Number::Fixnum(n1)) => { + (Number::Fixnum(n1), Number::Integer(n2)) + | (Number::Integer(n2), Number::Fixnum(n1)) => { let n1 = Integer::from(n1); Ok(Number::from(Integer::from(n2.gcd_ref(&n1)))) } @@ -571,11 +490,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("gcd"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n), stub, )) } @@ -584,19 +499,14 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("gcd"), 2); Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n), stub, )) } } } - pub(crate) - fn float_pow(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn float_pow(&self, n1: Number, n2: Number) -> Result { let f1 = result_f(&n1, rnd_f); let f2 = result_f(&n2, rnd_f); @@ -612,8 +522,12 @@ impl MachineState { )?))) } - pub(crate) - fn pow(&self, n1: Number, n2: Number, culprit: &'static str) -> Result { + pub(crate) fn pow( + &self, + n1: Number, + n2: Number, + culprit: &'static str, + ) -> Result { if n2.is_negative() && n1.is_zero() { let stub = MachineError::functor_stub(clause_name!(culprit), 2); return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)); @@ -623,8 +537,11 @@ impl MachineState { } #[inline] - pub(crate) - fn unary_float_fn_template(&self, n1: Number, f: FloatFn) -> Result + pub(crate) fn unary_float_fn_template( + &self, + n1: Number, + f: FloatFn, + ) -> Result where FloatFn: Fn(f64) -> f64, { @@ -637,56 +554,47 @@ impl MachineState { } #[inline] - pub(crate) - fn sin(&self, n1: Number) -> Result { + pub(crate) fn sin(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.sin()) } #[inline] - pub(crate) - fn cos(&self, n1: Number) -> Result { + pub(crate) fn cos(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.cos()) } #[inline] - pub(crate) - fn tan(&self, n1: Number) -> Result { + pub(crate) fn tan(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.tan()) } #[inline] - pub(crate) - fn log(&self, n1: Number) -> Result { + pub(crate) fn log(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.log(f64::consts::E)) } #[inline] - pub(crate) - fn exp(&self, n1: Number) -> Result { + pub(crate) fn exp(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.exp()) } #[inline] - pub(crate) - fn asin(&self, n1: Number) -> Result { + pub(crate) fn asin(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.asin()) } #[inline] - pub(crate) - fn acos(&self, n1: Number) -> Result { + pub(crate) fn acos(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.acos()) } #[inline] - pub(crate) - fn atan(&self, n1: Number) -> Result { + pub(crate) fn atan(&self, n1: Number) -> Result { self.unary_float_fn_template(n1, |f| f.atan()) } #[inline] - pub(crate) - fn sqrt(&self, n1: Number) -> Result { + pub(crate) fn sqrt(&self, n1: Number) -> Result { if n1.is_negative() { let stub = MachineError::functor_stub(clause_name!("is"), 2); return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)); @@ -696,27 +604,23 @@ impl MachineState { } #[inline] - pub(crate) - fn float(&self, n: Number) -> Result { + pub(crate) fn float(&self, n: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("is"), 2); try_numeric_result!(self, result_f(&n, rnd_f), stub) } #[inline] - pub(crate) - fn floor(&self, n1: Number) -> Number { + pub(crate) fn floor(&self, n1: Number) -> Number { rnd_i(&n1).to_owned() } #[inline] - pub(crate) - fn ceiling(&self, n1: Number) -> Number { + pub(crate) fn ceiling(&self, n1: Number) -> Number { -self.floor(-n1) } #[inline] - pub(crate) - fn truncate(&self, n: Number) -> Number { + pub(crate) fn truncate(&self, n: Number) -> Number { if n.is_negative() { -self.floor(n.abs()) } else { @@ -724,8 +628,7 @@ impl MachineState { } } - pub(crate) - fn round(&self, n: Number) -> Result { + pub(crate) fn round(&self, n: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("is"), 2); let result = n + Number::Float(OrderedFloat(0.5f64)); @@ -734,8 +637,7 @@ impl MachineState { Ok(self.floor(result)) } - pub(crate) - fn shr(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn shr(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(>>)"), 2); match (n1, n2) { @@ -756,38 +658,26 @@ impl MachineState { _ => Ok(Number::from(n1 >> u32::max_value())), } } - (Number::Integer(n1), Number::Fixnum(n2)) => { - match u32::try_from(n2) { - Ok(n2) => Ok(Number::from(Integer::from(&*n1 >> n2))), - _ => Ok(Number::from(Integer::from(&*n1 >> u32::max_value()))), - } - } - (Number::Integer(n1), Number::Integer(n2)) => - match n2.to_u32() { - Some(n2) => Ok(Number::from(Integer::from(&*n1 >> n2))), - _ => Ok(Number::from(Integer::from(&*n1 >> u32::max_value()))), - }, + (Number::Integer(n1), Number::Fixnum(n2)) => match u32::try_from(n2) { + Ok(n2) => Ok(Number::from(Integer::from(&*n1 >> n2))), + _ => Ok(Number::from(Integer::from(&*n1 >> u32::max_value()))), + }, + (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() { + Some(n2) => Ok(Number::from(Integer::from(&*n1 >> n2))), + _ => Ok(Number::from(Integer::from(&*n1 >> u32::max_value()))), + }, (Number::Integer(_), n2) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), stub, )), (n1, _) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )), } } - pub(crate) - fn shl(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn shl(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(<<)"), 2); match (n1, n2) { @@ -808,263 +698,181 @@ impl MachineState { _ => Ok(Number::from(n1 << u32::max_value())), } } - (Number::Integer(n1), Number::Fixnum(n2)) => { - match u32::try_from(n2) { - Ok(n2) => Ok(Number::from(Integer::from(&*n1 << n2))), - _ => Ok(Number::from(Integer::from(&*n1 << u32::max_value()))), - } - } + (Number::Integer(n1), Number::Fixnum(n2)) => match u32::try_from(n2) { + Ok(n2) => Ok(Number::from(Integer::from(&*n1 << n2))), + _ => Ok(Number::from(Integer::from(&*n1 << u32::max_value()))), + }, (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() { Some(n2) => Ok(Number::from(Integer::from(&*n1 << n2))), _ => Ok(Number::from(Integer::from(&*n1 << u32::max_value()))), }, (Number::Integer(_), n2) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), stub, )), (n1, _) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )), } } - pub(crate) - fn bitwise_complement(&self, n1: Number) -> Result { + pub(crate) fn bitwise_complement(&self, n1: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(\\)"), 2); match n1 { Number::Fixnum(n) => Ok(Number::Fixnum(!n)), Number::Integer(n1) => Ok(Number::from(Integer::from(!&*n1))), _ => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )), } } - pub(crate) - fn xor(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn xor(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(xor)"), 2); match (n1, n2) { - (Number::Fixnum(n1), Number::Fixnum(n2)) => { - Ok(Number::from(n1 ^ n2)) - } + (Number::Fixnum(n1), Number::Fixnum(n2)) => Ok(Number::from(n1 ^ n2)), (Number::Fixnum(n1), Number::Integer(n2)) => { let n1 = Integer::from(n1); Ok(Number::from(n1 ^ &*n2)) } - (Number::Integer(n1), Number::Fixnum(n2)) => { - Ok(Number::from(&*n1 ^ Integer::from(n2))) - } + (Number::Integer(n1), Number::Fixnum(n2)) => Ok(Number::from(&*n1 ^ Integer::from(n2))), (Number::Integer(n1), Number::Integer(n2)) => { Ok(Number::from(Integer::from(&*n1 ^ &*n2))) } - (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2 - ), - stub, - )) - } - (n1, _) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1 - ), - stub, - )) - } - } - } - - pub(crate) - fn and(&self, n1: Number, n2: Number) -> Result { - let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2); - - match (n1, n2) { - (Number::Fixnum(n1), Number::Fixnum(n2)) => { - Ok(Number::from(n1 & n2)) - } - (Number::Fixnum(n1), Number::Integer(n2)) => { - let n1 = Integer::from(n1); - Ok(Number::from(n1 & &*n2)) - } - (Number::Integer(n1), Number::Fixnum(n2)) => { - Ok(Number::from(&*n1 & Integer::from(n2))) - } - (Number::Integer(n1), Number::Integer(n2)) => { - Ok(Number::from(Integer::from(&*n1 & &*n2))) - } - (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), - stub, - )) - } + (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), + stub, + )), (n1, _) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )), } } - pub(crate) - fn or(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn and(&self, n1: Number, n2: Number) -> Result { + let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2); + + match (n1, n2) { + (Number::Fixnum(n1), Number::Fixnum(n2)) => Ok(Number::from(n1 & n2)), + (Number::Fixnum(n1), Number::Integer(n2)) => { + let n1 = Integer::from(n1); + Ok(Number::from(n1 & &*n2)) + } + (Number::Integer(n1), Number::Fixnum(n2)) => Ok(Number::from(&*n1 & Integer::from(n2))), + (Number::Integer(n1), Number::Integer(n2)) => { + Ok(Number::from(Integer::from(&*n1 & &*n2))) + } + (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), + stub, + )), + (n1, _) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), + stub, + )), + } + } + + pub(crate) fn or(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2); match (n1, n2) { - (Number::Fixnum(n1), Number::Fixnum(n2)) => { - Ok(Number::from(n1 | n2)) - } + (Number::Fixnum(n1), Number::Fixnum(n2)) => Ok(Number::from(n1 | n2)), (Number::Fixnum(n1), Number::Integer(n2)) => { let n1 = Integer::from(n1); Ok(Number::from(n1 | &*n2)) } - (Number::Integer(n1), Number::Fixnum(n2)) => { - Ok(Number::from(&*n1 | Integer::from(n2))) - } + (Number::Integer(n1), Number::Fixnum(n2)) => Ok(Number::from(&*n1 | Integer::from(n2))), (Number::Integer(n1), Number::Integer(n2)) => { Ok(Number::from(Integer::from(&*n1 | &*n2))) } - (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), - stub, - )) - } - (n1, _) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1 - ), - stub, - )) - } + (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), + stub, + )), + (n1, _) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), + stub, + )), } } - pub(crate) - fn modulus(&self, x: Number, y: Number) -> Result { + pub(crate) fn modulus(&self, x: Number, y: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(mod)"), 2); match (x, y) { (Number::Fixnum(n1), Number::Fixnum(n2)) => { if n2 == 0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { Ok(Number::from(n1.rem_floor(n2))) } } (Number::Fixnum(n1), Number::Integer(n2)) => { if &*n2 == &0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { let n1 = Integer::from(n1); - Ok(Number::from(<(Integer, Integer)>::from(n1.div_rem_floor_ref(&*n2)).1)) + Ok(Number::from( + <(Integer, Integer)>::from(n1.div_rem_floor_ref(&*n2)).1, + )) } } (Number::Integer(n1), Number::Fixnum(n2)) => { if n2 == 0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { let n2 = Integer::from(n2); - Ok(Number::from(<(Integer, Integer)>::from(n1.div_rem_floor_ref(&n2)).1)) + Ok(Number::from( + <(Integer, Integer)>::from(n1.div_rem_floor_ref(&n2)).1, + )) } } (Number::Integer(x), Number::Integer(y)) => { if &*y == &0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { - Ok(Number::from(<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1)) + Ok(Number::from( + <(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1, + )) } } - (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), - stub, - )) - } + (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), + stub, + )), (n1, _) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )), } } - pub(crate) - fn remainder(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn remainder(&self, n1: Number, n2: Number) -> Result { let stub = MachineError::functor_stub(clause_name!("(rem)"), 2); match (n1, n2) { (Number::Fixnum(n1), Number::Fixnum(n2)) => { if n2 == 0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { Ok(Number::from(n1 % n2)) } } (Number::Fixnum(n1), Number::Integer(n2)) => { if &*n2 == &0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { let n1 = Integer::from(n1); Ok(Number::from(n1 % &*n2)) @@ -1072,10 +880,8 @@ impl MachineState { } (Number::Integer(n1), Number::Fixnum(n2)) => { if n2 == 0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { let n2 = Integer::from(n2); Ok(Number::from(&*n1 % n2)) @@ -1083,37 +889,24 @@ impl MachineState { } (Number::Integer(n1), Number::Integer(n2)) => { if &*n2 == &0 { - Err(self.error_form( - MachineError::evaluation_error(EvalError::ZeroDivisor), - stub, - )) + Err(self + .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub)) } else { Ok(Number::from(Integer::from(&*n1 % &*n2))) } } - (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n2, - ), - stub, - )) - } + (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, n2), + stub, + )), (n1, _) => Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - n1, - ), + MachineError::type_error(self.heap.h(), ValidType::Integer, n1), stub, )), } } - pub(crate) - fn max(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn max(&self, n1: Number, n2: Number) -> Result { match (n1, n2) { (Number::Fixnum(n1), Number::Fixnum(n2)) => { if n1 > n2 { @@ -1154,8 +947,7 @@ impl MachineState { } } - pub(crate) - fn min(&self, n1: Number, n2: Number) -> Result { + pub(crate) fn min(&self, n1: Number, n2: Number) -> Result { match (n1, n2) { (Number::Fixnum(n1), Number::Fixnum(n2)) => { if n1 < n2 { @@ -1196,8 +988,7 @@ impl MachineState { } } - pub(crate) - fn sign(&self, n: Number) -> Number { + pub(crate) fn sign(&self, n: Number) -> Number { if n.is_positive() { Number::from(1) } else if n.is_negative() { diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index 790114fc..dff8e90e 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -1,5 +1,6 @@ use crate::heap_iter::*; use crate::machine::*; +use crate::prolog_parser_rebis::temp_v; use crate::indexmap::IndexSet; @@ -20,8 +21,7 @@ pub(super) struct AttrVarInitializer { } impl AttrVarInitializer { - pub(super) - fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self { + pub(super) fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self { AttrVarInitializer { attribute_goals: vec![], attr_var_queue: vec![], @@ -34,24 +34,21 @@ impl AttrVarInitializer { } #[inline] - pub(super) - fn reset(&mut self) { - self.attribute_goals.clear(); + pub(super) fn reset(&mut self) { + self.attribute_goals.clear(); self.attr_var_queue.clear(); self.bindings.clear(); } #[inline] - pub(super) - fn backtrack(&mut self, queue_b: usize, bindings_b: usize) { + pub(super) fn backtrack(&mut self, queue_b: usize, bindings_b: usize) { self.attr_var_queue.truncate(queue_b); self.bindings.truncate(bindings_b); } } impl MachineState { - pub(super) - fn push_attr_var_binding(&mut self, h: usize, addr: Addr) { + pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) { if self.attr_var_init.bindings.is_empty() { self.attr_var_init.instigating_p = self.p.local(); @@ -79,7 +76,7 @@ impl MachineState { let iter = self .attr_var_init .bindings - .drain(0 ..) + .drain(0..) .map(|(_, addr)| HeapCellValue::Addr(addr)); let value_list_addr = Addr::HeapCell(self.heap.to_list(iter)); @@ -97,8 +94,7 @@ impl MachineState { self[temp_v!(2)] = value_list_addr; } - pub(super) - fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter { + pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter { let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..] .iter() .filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) { @@ -107,29 +103,25 @@ impl MachineState { }) .collect(); - attr_vars.sort_unstable_by(|a1, a2| { - self.compare_term_test(a1, a2).unwrap_or(Ordering::Less) - }); + attr_vars + .sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2).unwrap_or(Ordering::Less)); self.term_dedup(&mut attr_vars); attr_vars.into_iter() } - pub(super) - fn verify_attr_interrupt(&mut self, p: usize) { + pub(super) fn verify_attr_interrupt(&mut self, p: usize) { self.allocate(self.num_of_args + 2); let e = self.e; self.stack.index_and_frame_mut(e).prelude.interrupt_cp = self.attr_var_init.cp; - for i in 1 .. self.num_of_args + 1 { + for i in 1..self.num_of_args + 1 { self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)]; } - self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = - Addr::CutPoint(self.b0); - self.stack.index_and_frame_mut(e)[self.num_of_args + 2] = - Addr::Usize(self.num_of_args); + self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = Addr::CutPoint(self.b0); + self.stack.index_and_frame_mut(e)[self.num_of_args + 2] = Addr::Usize(self.num_of_args); self.verify_attributes(); @@ -138,9 +130,8 @@ impl MachineState { self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); } - pub(super) - fn attr_vars_of_term(&self, addr: Addr) -> Vec { - let mut seen_set = IndexSet::new(); + pub(super) fn attr_vars_of_term(&self, addr: Addr) -> Vec { + let mut seen_set = IndexSet::new(); let mut seen_vars = vec![]; let mut iter = self.acyclic_pre_order_iter(addr); diff --git a/src/machine/compile.rs b/src/machine/compile.rs index a9ab5108..766c117a 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1,11 +1,13 @@ +use crate::prolog_parser_rebis::clause_name; + use crate::codegen::*; use crate::debray_allocator::*; 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::loader::*; use crate::machine::term_stream::*; +use crate::machine::*; use slice_deque::sdeq; @@ -18,20 +20,18 @@ struct StandaloneCompileResult { standalone_skeleton: PredicateSkeleton, } -pub(super) -fn bootstrapping_compile( +pub(super) fn bootstrapping_compile( stream: Stream, wam: &mut Machine, 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, - ); + let term_stream = BootstrappingTermStream::from_prolog_stream( + stream, + wam.machine_st.atom_tbl.clone(), + wam.machine_st.flags, + listing_src, + ); let loader = Loader::new(term_stream, wam); loader.load()?; @@ -40,25 +40,19 @@ fn bootstrapping_compile( } // throw errors if declaration or query found. -pub(super) -fn compile_relation( +pub(super) fn compile_relation( cg: &mut CodeGenerator, - tl: &TopLevel + tl: &TopLevel, ) -> Result { match tl { - &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), + &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), } } -pub(super) -fn compile_appendix( +pub(super) fn compile_appendix( code: &mut Code, queue: &VecDeque, jmp_by_locs: Vec, @@ -104,7 +98,7 @@ fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) return target_pos - 1; } - for index in (0 .. target_pos - 1).rev() { + 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 { @@ -144,13 +138,9 @@ fn derelictize_try_me_else( retraction_info: &mut RetractionInfo, ) -> Option { match &mut code[index] { - Line::Choice(ChoiceInstruction::TryMeElse(0)) => { - None - } + Line::Choice(ChoiceInstruction::TryMeElse(0)) => None, Line::Choice(ChoiceInstruction::TryMeElse(ref mut offset)) => { - retraction_info.push_record( - RetractionRecord::ModifiedTryMeElse(index, *offset), - ); + retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *offset)); Some(mem::replace(offset, 0)) } @@ -168,43 +158,41 @@ fn merge_indices( 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() { + 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); - let target_indexing_line = - to_indexing_line_mut(&mut code[target_index_loc]).unwrap(); + let target_indexing_line = to_indexing_line_mut(&mut code[target_index_loc]).unwrap(); - skeleton[clause_index].opt_arg_index_key.set_switch_on_term_loc(target_index_loc); + skeleton[clause_index] + .opt_arg_index_key + .set_switch_on_term_loc(target_index_loc); merge_clause_index( target_indexing_line, - &mut skeleton[0 .. clause_index + 1], + &mut skeleton[0..clause_index + 1], clause_loc, AppendOrPrepend::Append, ); - retraction_info.push_record( - RetractionRecord::AddedIndex( - skeleton[clause_index].opt_arg_index_key.clone(), - clause_loc, - ), - ); + retraction_info.push_record(RetractionRecord::AddedIndex( + skeleton[clause_index].opt_arg_index_key.clone(), + clause_loc, + )); } else { break; } } } -fn find_inner_choice_instr( - code: &Code, - mut index: usize, - index_loc: usize, -) -> usize { +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)) => { + Line::Choice(ChoiceInstruction::TryMeElse(o)) + | Line::Choice(ChoiceInstruction::RetryMeElse(o)) => { if *o > 0 { return index; } else { @@ -214,18 +202,14 @@ fn find_inner_choice_instr( Line::Choice(ChoiceInstruction::TrustMe(_)) => { return index; } - Line::IndexingCode(indexing_code) => { - match &indexing_code[0] { - IndexingLine::Indexing( - IndexingInstruction::SwitchOnTerm(_, v, ..) - ) => { - index += v; - } - _ => { - unreachable!(); - } + Line::IndexingCode(indexing_code) => match &indexing_code[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => { + index += v; } - } + _ => { + unreachable!(); + } + }, Line::Control(ControlInstruction::RevJmpBy(offset)) => { index -= offset; } @@ -250,8 +234,7 @@ fn remove_index_from_subsequence( 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); - let target_indexing_line = - to_indexing_line_mut(&mut code[index_loc]).unwrap(); + let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap(); let offset = clause_start - index_loc + 1; @@ -259,13 +242,11 @@ fn remove_index_from_subsequence( // 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, - ), - ); + retraction_info.push_record(RetractionRecord::RemovedIndex( + index_loc, + opt_arg_index_key.clone(), + offset, + )); } } @@ -281,46 +262,40 @@ fn merge_indexed_subsequences( // 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_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(), + skeleton.clauses[upper_lower_bound] + .opt_arg_index_key + .switch_on_term_loc() + .unwrap(), ); 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, - ), - ); + 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)); + 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)); - } + 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)); + } + }, } } - _ => { - } + _ => {} } thread_choice_instr_at_to( @@ -332,15 +307,14 @@ fn merge_indexed_subsequences( let mut end_of_upper_lower_bound = None; - for index in upper_lower_bound .. skeleton.clauses.len() { + 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 outer_threaded_choice_instr_loc = - skeleton.clauses[lower_upper_bound].clause_start - 2; + let outer_threaded_choice_instr_loc = skeleton.clauses[lower_upper_bound].clause_start - 2; match end_of_upper_lower_bound { Some(outer_threaded_clause_index) => { @@ -351,21 +325,17 @@ fn merge_indexed_subsequences( 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), - ); + 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)); - *o = 0; + *o = 0; - return Some(IndexPtr::Index(outer_threaded_choice_instr_loc + 1)); - } - _ => { - } + return Some(IndexPtr::Index(outer_threaded_choice_instr_loc + 1)); } - } + _ => {} + }, } None @@ -381,15 +351,13 @@ fn delete_from_dynamic_skeleton( 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, - ), - ); + retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause( + compilation_target, + key, + target_pos, + clause_index_info, + clause_clause_loc, + )); clause_clause_loc } @@ -402,18 +370,15 @@ fn blunt_leading_choice_instr( loop { match &mut code[instr_loc] { Line::Choice(ChoiceInstruction::RetryMeElse(o)) => { - retraction_info.push_record( - RetractionRecord::ModifiedRetryMeElse(instr_loc, *o), - ); + retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(instr_loc, *o)); 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), - ); + retraction_info + .push_record(RetractionRecord::AppendedTrustMe(instr_loc, *offset, false)); code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(0)); return instr_loc + 1; @@ -440,29 +405,19 @@ fn set_switch_var_offset_to_choice_instr( offset: usize, retraction_info: &mut RetractionInfo, ) { - let target_indexing_line = - to_indexing_line_mut(&mut code[index_loc]).unwrap(); + let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap(); - let v = - match &mut target_indexing_line[0] { - IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => { - *v - } - _ => { - unreachable!(); - } - }; + let v = match &mut target_indexing_line[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => *v, + _ => { + unreachable!(); + } + }; match &code[index_loc + v] { - Line::Choice(ChoiceInstruction::TryMeElse(_)) => { - } + Line::Choice(ChoiceInstruction::TryMeElse(_)) => {} _ => { - set_switch_var_offset( - code, - index_loc, - offset, - retraction_info, - ); + set_switch_var_offset(code, index_loc, offset, retraction_info); } } } @@ -474,22 +429,20 @@ fn set_switch_var_offset( offset: usize, retraction_info: &mut RetractionInfo, ) { - let target_indexing_line = - to_indexing_line_mut(&mut code[index_loc]).unwrap(); + let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap(); - let old_v = - match &mut target_indexing_line[0] { - IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => { - mem::replace(v, offset) - } - _ => { - unreachable!() - } - }; + let old_v = match &mut target_indexing_line[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => { + mem::replace(v, offset) + } + _ => { + unreachable!() + } + }; - retraction_info.push_record( - RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v), - ); + retraction_info.push_record(RetractionRecord::ReplacedSwitchOnTermVarIndex( + index_loc, old_v, + )); } fn internalize_choice_instr_at( @@ -499,24 +452,19 @@ fn internalize_choice_instr_at( ) { match &mut code[instr_loc] { Line::Choice(ChoiceInstruction::TryMeElse(0)) => { - retraction_info.push_record( - RetractionRecord::ModifiedTryMeElse(instr_loc, 0), - ); + retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(instr_loc, 0)); code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0)); } Line::Choice(ChoiceInstruction::TryMeElse(o)) => { let o = *o; - retraction_info.push_record( - RetractionRecord::ModifiedTryMeElse(instr_loc, o), - ); + 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)); - } + Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => { + code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(o)); + } _ => { code[instr_loc] = Line::Choice(ChoiceInstruction::RetryMeElse(o)); } @@ -536,45 +484,39 @@ fn thread_choice_instr_at_to( ) { 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), - ); + 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)); - *o = target_loc - instr_loc; - return; - } - Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) | - Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) => { + *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), - ); + Line::Control(ControlInstruction::RevJmpBy(ref mut o)) if instr_loc >= target_loc => { + retraction_info.push_record(RetractionRecord::ModifiedRevJmpBy(instr_loc, *o)); - *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()), - ); + *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)); + code[instr_loc] = + Line::Choice(ChoiceInstruction::RetryMeElse(target_loc - instr_loc)); - return; - } - Line::Choice(ChoiceInstruction::TrustMe(o)) - if *o > 0 => { - instr_loc += *o; - } + return; + } + Line::Choice(ChoiceInstruction::TrustMe(o)) if *o > 0 => { + instr_loc += *o; + } _ => { unreachable!() } @@ -604,25 +546,20 @@ fn remove_non_leading_clause( 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, - ), - ); + retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse( + preceding_choice_instr_loc, + *o, + )); - code[preceding_choice_instr_loc] = - Line::Choice(ChoiceInstruction::TrustMe(0)); + code[preceding_choice_instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0)); None } Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => { - retraction_info.push_record( - RetractionRecord::ModifiedTryMeElse( - preceding_choice_instr_loc, - *o, - ) - ); + retraction_info.push_record(RetractionRecord::ModifiedTryMeElse( + preceding_choice_instr_loc, + *o, + )); *o = 0; @@ -648,14 +585,13 @@ fn finalize_retract( index_ptr_opt: Option, retraction_info: &mut RetractionInfo, ) -> usize { - let clause_clause_loc = - delete_from_dynamic_skeleton( - compilation_target.clone(), - key.clone(), - skeleton, - target_pos, - retraction_info, - ); + let clause_clause_loc = delete_from_dynamic_skeleton( + compilation_target.clone(), + key.clone(), + skeleton, + target_pos, + retraction_info, + ); if let Some(index_ptr) = index_ptr_opt { set_code_index( @@ -678,12 +614,10 @@ fn remove_leading_unindexed_clause( 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, - ) - ); + retraction_info.push_record(RetractionRecord::ModifiedTryMeElse( + non_indexed_choice_instr_loc, + *o, + )); let o = mem::replace(o, 0); @@ -718,60 +652,54 @@ fn prepend_compiled_clause( 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() { + 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 ..)); + 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, - ), - ); + retraction_info.push_record(RetractionRecord::AddedIndex( + skeleton.clauses[0].opt_arg_index_key.clone(), + skeleton.clauses[0].clause_start, + )); let outer_thread_choice_loc = skeleton.clauses[1].clause_start - 2; - retraction_info.push_record( - RetractionRecord::SkeletonClauseStartReplaced( - compilation_target, - key.clone(), - 1, - skeleton.clauses[1].clause_start, - ), - ); + retraction_info.push_record(RetractionRecord::SkeletonClauseStartReplaced( + compilation_target, + key.clone(), + 1, + skeleton.clauses[1].clause_start, + )); skeleton.clauses[1].clause_start = - find_inner_choice_instr( - code, - skeleton.clauses[1].clause_start, - index_loc, - ); + find_inner_choice_instr(code, skeleton.clauses[1].clause_start, index_loc); let inner_thread_rev_offset = 3 + prepend_queue.len() + clause_loc - skeleton.clauses[1].clause_start; - prepend_queue.push_back( - Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), - ); + prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy( + inner_thread_rev_offset, + ))); - prepend_queue.push_front( - Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), - ); + prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( + prepend_queue.len(), + ))); // prepend_queue is now: // | TryMeElse N_2 // | (clause_code) // +N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1) - prepend_queue.push_front( - Line::Control(ControlInstruction::RevJmpBy( - 1 + clause_loc - index_loc - )), - ); + prepend_queue.push_front(Line::Control(ControlInstruction::RevJmpBy( + 1 + clause_loc - index_loc, + ))); 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) { @@ -807,9 +735,9 @@ fn prepend_compiled_clause( } }; - prepend_queue.push_front( - Line::Choice(ChoiceInstruction::TryMeElse(outer_thread_choice_offset)), - ); + prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( + outer_thread_choice_offset, + ))); // prepend_queue is now: // | TryMeElse N_3 @@ -828,21 +756,20 @@ fn prepend_compiled_clause( AppendOrPrepend::Prepend, ); - set_switch_var_offset( + set_switch_var_offset(code, index_loc, clause_loc - index_loc + 2, retraction_info); + + internalize_choice_instr_at( code, - index_loc, - clause_loc - index_loc + 2, + skeleton.clauses[1].clause_start, retraction_info, ); - internalize_choice_instr_at(code, skeleton.clauses[1].clause_start, retraction_info); - code.extend(prepend_queue.into_iter()); clause_loc + (outer_thread_choice_offset == 0) as usize } _ => { - prepend_queue.extend(clause_code.drain(1 ..)); + prepend_queue.extend(clause_code.drain(1..)); skeleton.clauses[0].opt_arg_index_key += clause_loc; skeleton.clauses[0].clause_start = clause_loc + 2; @@ -854,29 +781,26 @@ fn prepend_compiled_clause( // this is a stub for chaining inner-threaded choice // instructions. - prepend_queue.push_back( - Line::Control(ControlInstruction::RevJmpBy(0)) - ); + 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; - } + Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) if *o == 0 => { + *o = prepend_queue_len - 2; + } _ => { unreachable!(); } } - prepend_queue.push_back( - Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), - ); + prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy( + inner_thread_rev_offset, + ))); - prepend_queue.push_front( - Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), - ); + prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( + prepend_queue.len(), + ))); // prepend_queue is now: // | TryMeElse(N_2) @@ -895,20 +819,20 @@ fn prepend_compiled_clause( } else { match skeleton.clauses[1].opt_arg_index_key.switch_on_term_loc() { Some(_) => { - prepend_queue.extend(clause_code.drain(1 ..)); + prepend_queue.extend(clause_code.drain(1..)); let old_clause_start = skeleton.clauses[1].clause_start - 2; let inner_thread_rev_offset = 1 + prepend_queue.len() + clause_loc - old_clause_start; - prepend_queue.push_back( - Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), - ); + prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy( + inner_thread_rev_offset, + ))); - prepend_queue.push_front( - Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), - ); + prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( + prepend_queue.len(), + ))); // prepend_queue is now: // | TryMeElse(N_2) @@ -925,20 +849,20 @@ fn prepend_compiled_clause( clause_loc // + (outer_thread_choice_offset == 0 as usize) } None => { - prepend_queue.extend(clause_code.drain(1 ..)); + prepend_queue.extend(clause_code.drain(1..)); let old_clause_start = skeleton.clauses[1].clause_start; let inner_thread_rev_offset = 1 + prepend_queue.len() + clause_loc - old_clause_start; - prepend_queue.push_back( - Line::Control(ControlInstruction::RevJmpBy(inner_thread_rev_offset)), - ); + prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy( + inner_thread_rev_offset, + ))); - prepend_queue.push_front( - Line::Choice(ChoiceInstruction::TryMeElse(prepend_queue.len())), - ); + prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( + prepend_queue.len(), + ))); // prepend_queue is now: // | TryMeElse(N_2) @@ -976,88 +900,88 @@ fn append_compiled_clause( 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 + 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; + // 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, - ), - ); + 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(); + 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, - ); + merge_clause_index( + target_indexing_line, + &mut skeleton.clauses[lower_bound..], + clause_loc, + AppendOrPrepend::Append, + ); - let target_pos_clause_start = find_inner_choice_instr( + let target_pos_clause_start = find_inner_choice_instr( + code, + skeleton.clauses[target_pos - 1].clause_start, + index_loc, + ); + + if lower_bound + 1 == target_pos { + set_switch_var_offset( code, - skeleton.clauses[target_pos - 1].clause_start, index_loc, + target_pos_clause_start - index_loc, + retraction_info, ); - - if lower_bound + 1 == target_pos { - set_switch_var_offset( - code, - index_loc, - target_pos_clause_start - index_loc, - retraction_info, - ); - } - - target_pos_clause_start // skeleton.clauses[target_pos - 1].clause_start } - _ => { - 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); - } + target_pos_clause_start // skeleton.clauses[target_pos - 1].clause_start + } + _ => { + skeleton.clauses[target_pos].opt_arg_index_key += clause_loc; + code.extend(clause_code.drain(1..)); - skeleton.clauses[lower_bound].clause_start - 2 + 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); } - None => { - if lower_bound == 0 { - code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start); - } - match skeleton.clauses[target_pos].opt_arg_index_key.switch_on_term_loc() { - Some(index_loc) => { - // point to the inner-threaded TryMeElse(0) if target_pos is - // indexed, and make switch_on_term point one line after it in - // its variable offset. - skeleton.clauses[target_pos].clause_start += 2; - - set_switch_var_offset( - code, - index_loc, - 2, - retraction_info, - ); - } - None => { - } - } - - skeleton.clauses[lower_bound].clause_start + skeleton.clauses[lower_bound].clause_start - 2 + } + None => { + if lower_bound == 0 { + code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start); } + + match skeleton.clauses[target_pos] + .opt_arg_index_key + .switch_on_term_loc() + { + Some(index_loc) => { + // point to the inner-threaded TryMeElse(0) if target_pos is + // indexed, and make switch_on_term point one line after it in + // its variable offset. + skeleton.clauses[target_pos].clause_start += 2; + + set_switch_var_offset(code, index_loc, 2, retraction_info); + } + None => {} + } + + skeleton.clauses[lower_bound].clause_start } } - }; + } + }; thread_choice_instr_at_to(code, threaded_choice_instr_loc, clause_loc, retraction_info); @@ -1073,7 +997,7 @@ fn mergeable_indexed_subsequences( 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 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; @@ -1094,10 +1018,8 @@ impl<'a> LoadState<'a> { let code_len = self.wam.code_repo.code.len(); let mut code_ptr = code_len; - let mut cg = CodeGenerator::::new( - self.wam.machine_st.atom_tbl.clone(), - settings, - ); + let mut cg = + CodeGenerator::::new(self.wam.machine_st.atom_tbl.clone(), settings); let mut code = cg.compile_predicate(predicates)?; @@ -1119,22 +1041,21 @@ impl<'a> LoadState<'a> { Line::Choice(ChoiceInstruction::TryMeElse(0)) => { code_ptr += 1; } - _ => { - } + _ => {} } - match self.wam.indices.get_predicate_skeleton( - &self.compilation_target, - &key, - ) { + match self + .wam + .indices + .get_predicate_skeleton(&self.compilation_target, &key) + { Some(skeleton) => { - self.retraction_info.push_record( - RetractionRecord::SkeletonClauseTruncateBack( + self.retraction_info + .push_record(RetractionRecord::SkeletonClauseTruncateBack( self.compilation_target.clone(), key.clone(), skeleton.clauses.len(), - ), - ); + )); skeleton.clauses.extend(cg.skeleton.clauses.into_iter()); } @@ -1156,44 +1077,37 @@ impl<'a> LoadState<'a> { Ok(code_index.get()) } - 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, - ) - } + 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) } - } - 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, - ) - } + 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(super) - fn incremental_compile_clause( + pub(super) fn incremental_compile_clause( &mut self, key: PredicateKey, clause: PredicateClause, @@ -1203,45 +1117,45 @@ impl<'a> LoadState<'a> { ) -> Result { 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 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 settings = CodeGenSettings::new(true, non_counted_bt); let atom_tbl = self.wam.machine_st.atom_tbl.clone(); - let StandaloneCompileResult { clause_code, mut standalone_skeleton } = - compile_standalone_clause(clause, queue, settings, atom_tbl)?; + let StandaloneCompileResult { + clause_code, + mut standalone_skeleton, + } = compile_standalone_clause(clause, queue, settings, atom_tbl)?; match append_or_prepend { AppendOrPrepend::Append => { - skeleton.clauses.push_back(standalone_skeleton.clauses.pop_back().unwrap()); + skeleton + .clauses + .push_back(standalone_skeleton.clauses.pop_back().unwrap()); - self.retraction_info.push_record( - RetractionRecord::SkeletonClausePopBack( + self.retraction_info + .push_record(RetractionRecord::SkeletonClausePopBack( self.compilation_target.clone(), key.clone(), - ), - ); + )); - let result = - append_compiled_clause( - &mut self.wam.code_repo.code, - clause_code, - skeleton, - &mut self.retraction_info, - ); + let result = append_compiled_clause( + &mut self.wam.code_repo.code, + clause_code, + skeleton, + &mut self.retraction_info, + ); let code_index = self.get_or_insert_code_index(key.clone()); @@ -1258,25 +1172,25 @@ impl<'a> LoadState<'a> { Ok(code_index.get()) } AppendOrPrepend::Prepend => { - skeleton.clauses.push_front(standalone_skeleton.clauses.pop_back().unwrap()); + skeleton + .clauses + .push_front(standalone_skeleton.clauses.pop_back().unwrap()); - self.retraction_info.push_record( - RetractionRecord::SkeletonClausePopFront( + self.retraction_info + .push_record(RetractionRecord::SkeletonClausePopFront( self.compilation_target.clone(), key.clone(), - ), + )); + + 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, ); - 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, - ); - let code_index = self.get_or_insert_code_index(key.clone()); set_code_index( @@ -1292,22 +1206,19 @@ impl<'a> LoadState<'a> { } } - pub(super) - fn retract_clause(&mut self, key: PredicateKey, target_pos: usize) -> usize { + 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 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); @@ -1316,7 +1227,10 @@ impl<'a> LoadState<'a> { 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() { + 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, @@ -1377,24 +1291,23 @@ impl<'a> LoadState<'a> { ); } None => { - let index_ptr_opt = - if target_pos > 0 { - let preceding_choice_instr_loc = - skeleton.clauses[target_pos - 1].clause_start; + 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, - ) - }; + 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, @@ -1408,161 +1321,166 @@ impl<'a> LoadState<'a> { } } } - None => { - } + None => {} } } - 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 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 lower_bound_clause_start = find_inner_choice_instr( + code, + skeleton.clauses[lower_bound].clause_start, + target_indexing_loc, + ); + + let result; + + match skeleton.clauses[target_pos + 1] + .opt_arg_index_key + .switch_on_term_loc() { - let lower_bound_clause_start = find_inner_choice_instr( - code, - skeleton.clauses[lower_bound].clause_start, - target_indexing_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, + )), + ); - 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, - ), - ); - } - _ => { - } + match target_indexing_line { + Line::IndexingCode(indexing_code) => { + self.retraction_info.push_record( + RetractionRecord::ReplacedIndexingLine( + target_indexing_loc, + indexing_code, + ), + ); } - - 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( - code, - later_indexing_loc, - lower_bound_clause_start - later_indexing_loc, - &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, - ); - - set_switch_var_offset_to_choice_instr( - code, - target_indexing_loc, - lower_bound_clause_start - target_indexing_loc, - &mut self.retraction_info, - ); - } - }; - - result - } - _ => { - if target_pos > 0 { - remove_index_from_subsequence( + result = merge_indexed_subsequences( code, - &skeleton.clauses[target_pos].opt_arg_index_key, - skeleton.clauses[target_pos].clause_start, + skeleton, + lower_bound, + target_pos + 1, &mut self.retraction_info, ); - 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( + merge_indices( code, - skeleton.clauses[target_pos].clause_start, + later_indexing_loc, + 0..target_pos - lower_bound, + &mut skeleton.clauses[lower_bound..], &mut self.retraction_info, - ) + ); + + set_switch_var_offset( + code, + later_indexing_loc, + lower_bound_clause_start - later_indexing_loc, + &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, + ); + + set_switch_var_offset_to_choice_instr( + code, + target_indexing_loc, + lower_bound_clause_start - target_indexing_loc, + &mut self.retraction_info, + ); + } + }; + + 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, + ); + + 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, @@ -1577,35 +1495,26 @@ impl<'a> LoadState<'a> { } impl<'a, TS: TermStream> Loader<'a, TS> { - pub(super) - fn compile_clause_clauses>( + pub(super) fn compile_clause_clauses>( &mut self, key: PredicateKey, compilation_target: CompilationTarget, 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 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 clause_clause_compilation_target = - match compilation_target { - CompilationTarget::User => { - CompilationTarget::Module(clause_name!("builtins")) - } - _ => { - compilation_target.clone() - } - }; + let clause_clause_compilation_target = match compilation_target { + CompilationTarget::User => CompilationTarget::Module(clause_name!("builtins")), + _ => compilation_target.clone(), + }; let old_compilation_target = mem::replace( &mut self.load_state.compilation_target, @@ -1636,7 +1545,9 @@ impl<'a, TS: TermStream> Loader<'a, TS> { &(clause_name!("$clause"), 2), ) { Some(skeleton) if append_or_prepend.is_append() => { - skeleton.clause_clause_locs.extend_from_slice(&clause_clause_locs[0 ..]); + skeleton + .clause_clause_locs + .extend_from_slice(&clause_clause_locs[0..]); } Some(skeleton) => { for loc in clause_clause_locs.iter() { @@ -1648,10 +1559,12 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - match self.load_state.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + 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( @@ -1661,9 +1574,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { ), ); - skeleton.clause_clause_locs.append( - &mut clause_clause_locs - ); + skeleton.clause_clause_locs.append(&mut clause_clause_locs); } Some(skeleton) => { self.load_state.retraction_info.push_record( @@ -1678,9 +1589,8 @@ impl<'a, TS: TermStream> Loader<'a, TS> { skeleton.clause_clause_locs.push_front(*loc); } - self.load_state.increment_clause_assert_margin( - clause_clause_locs.len() - ); + self.load_state + .increment_clause_assert_margin(clause_clause_locs.len()); } None => { unreachable!(); @@ -1691,11 +1601,11 @@ impl<'a, TS: TermStream> Loader<'a, TS> { Ok(()) } - pub(super) - fn compile_and_submit(&mut self) -> Result<(), SessionError> { + pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> { let queue = self.preprocessor.parse_queue(&mut self.load_state)?; - let key = self.predicates + let key = self + .predicates .first() .and_then(|cl| { let arity = cl.arity(); @@ -1703,7 +1613,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { }) .ok_or(SessionError::NamelessEntry)?; - let (is_dynamic, is_extensible) = self.load_state.wam.indices + 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)); @@ -1711,18 +1624,14 @@ impl<'a, TS: TermStream> Loader<'a, TS> { let non_counted_bt = self.non_counted_bt_preds.contains(&key); let settings = CodeGenSettings::new(is_extensible, non_counted_bt); - self.load_state.compile(key.clone(), &self.predicates, &queue, settings)?; + self.load_state + .compile(key.clone(), &self.predicates, &queue, settings)?; if is_dynamic { let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter(); let compilation_target = self.load_state.compilation_target.clone(); - self.compile_clause_clauses( - key, - compilation_target, - iter, - AppendOrPrepend::Append, - )?; + self.compile_clause_clauses(key, compilation_target, iter, AppendOrPrepend::Append)?; } Ok(self.predicates.clear()) diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index bef493b5..466b2f99 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -1,7 +1,8 @@ -use crate::machine::*; use crate::machine::machine_indices::*; -use crate::machine::term_stream::*; +use crate::machine::*; +use crate::prolog_parser_rebis::clause_name; +use crate::machine::term_stream::*; use indexmap::IndexSet; use crate::ref_thread_local::RefThreadLocal; @@ -19,37 +20,35 @@ pub(super) struct LoadState<'a> { pub(super) wam: &'a mut Machine, } -pub(super) -fn set_code_index( +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) - } + 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) - } + } + 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); } @@ -71,16 +70,16 @@ fn add_op_decl_as_module_export( match op_decl.insert_into_op_dir(wam_op_dir) { Some((prec, spec)) => { - retraction_info.push_record( - RetractionRecord::ReplacedUserOp(op_decl.clone(), 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()) - ); + retraction_info.push_record(RetractionRecord::AddedUserOp(op_decl.clone())); module_op_exports.push((op_decl.clone(), None)); } @@ -89,49 +88,45 @@ fn add_op_decl_as_module_export( add_op_decl(retraction_info, compilation_target, module_op_dir, op_decl); } -pub(super) -fn add_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, - ), - ); - } + Some((prec, spec)) => match &compilation_target { + CompilationTarget::User => { + retraction_info.push_record(RetractionRecord::ReplacedUserOp( + 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()), - ); - } + 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( +pub(super) fn import_module_exports( retraction_info: &mut RetractionInfo, compilation_target: &CompilationTarget, imported_module: &Module, @@ -166,12 +161,7 @@ fn import_module_exports( } } ModuleExport::OpDecl(ref op_decl) => { - add_op_decl( - retraction_info, - compilation_target, - op_dir, - op_decl, - ); + add_op_decl(retraction_info, compilation_target, op_dir, op_decl); } } } @@ -185,7 +175,7 @@ fn import_module_exports_into_module( op_dir: &mut OpDir, meta_predicates: &mut MetaPredicateDir, wam_op_dir: &mut OpDir, - module_op_exports: &mut ModuleOpExports + module_op_exports: &mut ModuleOpExports, ) { for export in imported_module.module_decl.exports.iter() { match export { @@ -227,7 +217,6 @@ fn import_module_exports_into_module( } } - fn import_qualified_module_exports( retraction_info: &mut RetractionInfo, compilation_target: &CompilationTarget, @@ -263,12 +252,7 @@ fn import_qualified_module_exports( } } ModuleExport::OpDecl(ref op_decl) => { - add_op_decl( - retraction_info, - compilation_target, - op_dir, - op_decl, - ); + add_op_decl(retraction_info, compilation_target, op_dir, op_decl); } } } @@ -326,29 +310,28 @@ fn import_qualified_module_exports_into_module( impl<'a> LoadState<'a> { #[inline] - pub(super) - fn increment_clause_assert_margin(&mut self, incr: usize) { + pub(super) fn increment_clause_assert_margin(&mut self, incr: usize) { match &self.compilation_target { - CompilationTarget::User => { - } + CompilationTarget::User => {} CompilationTarget::Module(ref module_name) => { - self.retraction_info.push_record( - RetractionRecord::IncreasedClauseAssertMargin( + self.retraction_info + .push_record(RetractionRecord::IncreasedClauseAssertMargin( module_name.clone(), incr, - ), - ); + )); - self.wam.indices.modules.get_mut(module_name) + 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 ..) { + 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 { @@ -365,26 +348,28 @@ impl<'a> LoadState<'a> { 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() - } + 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![] }, + ModuleDecl { + name: module_name.clone(), + exports: vec![], + }, ListingSource::DynamicallyGenerated, ); - let code_index = module.code_dir + 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.retraction_info + .push_record(RetractionRecord::AddedModule(module_name.clone())); self.wam.indices.modules.insert(module_name, module); code_index @@ -392,29 +377,31 @@ impl<'a> LoadState<'a> { } } - pub(super) - fn get_or_insert_code_index(&mut self, key: PredicateKey) -> CodeIndex { + 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::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( + 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 + return self + .wam + .indices + .code_dir .entry(key) .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined)) .clone(); @@ -424,15 +411,20 @@ impl<'a> LoadState<'a> { } #[inline] - pub(super) - fn add_extensible_predicate(&mut self, key: PredicateKey, skeleton: PredicateSkeleton) { + 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.wam + .indices + .extensible_predicates + .insert(key.clone(), skeleton); - self.retraction_info.push_record( - RetractionRecord::AddedUserExtensiblePredicate(key), - ); + 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) { @@ -448,8 +440,7 @@ impl<'a> LoadState<'a> { } } - pub(super) - fn add_op_decl(&mut self, op_decl: &OpDecl) { + pub(super) fn add_op_decl(&mut self, op_decl: &OpDecl) { match &self.compilation_target { CompilationTarget::User => { add_op_decl( @@ -479,8 +470,7 @@ impl<'a> LoadState<'a> { } } - pub(super) - fn get_clause_type( + pub(super) fn get_clause_type( &mut self, name: ClauseName, arity: usize, @@ -495,14 +485,11 @@ impl<'a> LoadState<'a> { let idx = self.get_or_insert_code_index((name.clone(), arity)); ClauseType::Op(name, fixity, idx) } - ct => { - ct - } + ct => ct, } } - pub(super) - fn get_qualified_clause_type( + pub(super) fn get_qualified_clause_type( &mut self, module_name: ClauseName, name: ClauseName, @@ -522,14 +509,11 @@ impl<'a> LoadState<'a> { ClauseType::Op(name, fixity, idx) } - ct => { - ct - } + ct => ct, } } - pub(super) - fn add_meta_predicate_record( + pub(super) fn add_meta_predicate_record( &mut self, module_name: ClauseName, name: ClauseName, @@ -540,20 +524,26 @@ impl<'a> LoadState<'a> { match module_name.as_str() { "user" => { - match self.wam.indices.meta_predicates.insert(key.clone(), meta_specs) { + 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, - ), - ); + 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, - ) - ); + self.retraction_info + .push_record(RetractionRecord::AddedMetaPredicate( + module_name.clone(), + key, + )); } } } @@ -564,15 +554,15 @@ impl<'a> LoadState<'a> { Some(old_meta_specs) => { self.retraction_info.push_record( RetractionRecord::ReplacedMetaPredicate( - module_name.clone(), key.0, old_meta_specs, + module_name.clone(), + key.0, + old_meta_specs, ), ); } None => { self.retraction_info.push_record( - RetractionRecord::AddedMetaPredicate( - module_name.clone(), key, - ) + RetractionRecord::AddedMetaPredicate(module_name.clone(), key), ); } } @@ -588,15 +578,14 @@ impl<'a> LoadState<'a> { 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::AddedMetaPredicate( + module_name.clone(), + key, + )); - self.retraction_info.push_record( - RetractionRecord::AddedModule(module_name.clone()), - ); + self.retraction_info + .push_record(RetractionRecord::AddedModule(module_name.clone())); self.wam.indices.modules.insert(module_name, module); } @@ -623,32 +612,29 @@ impl<'a> LoadState<'a> { } } - pub(crate) - fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) { + 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); + 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(), - ), - ); + 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.listing_src = listing_src; + module + } + None => { + self.retraction_info + .push_record(RetractionRecord::AddedModule(module_name.clone())); - Module::new(module_decl, listing_src) - } - }; + Module::new(module_decl, listing_src) + } + }; self.import_builtins_in_module( &mut module.code_dir, @@ -676,8 +662,7 @@ impl<'a> LoadState<'a> { self.wam.indices.modules.insert(module_name, module); } - pub(super) - fn import_module(&mut self, module_name: ClauseName) -> Result<(), SessionError> { + 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 => { @@ -717,7 +702,9 @@ impl<'a> LoadState<'a> { self.wam.indices.modules.insert(module_name, module); Ok(()) } else { - Err(SessionError::ExistenceError(ExistenceError::Module(module_name))) + Err(SessionError::ExistenceError(ExistenceError::Module( + module_name, + ))) } } @@ -765,41 +752,41 @@ impl<'a> LoadState<'a> { self.wam.indices.modules.insert(module_name, module); Ok(()) } else { - Err(SessionError::ExistenceError(ExistenceError::Module(module_name))) + Err(SessionError::ExistenceError(ExistenceError::Module( + module_name, + ))) } } - pub(crate) - fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> { - let (stream, listing_src) = - match module_src { - ModuleSource::File(filename) => { - let mut path_buf = PathBuf::from(filename.as_str()); - path_buf.set_extension("pl"); - let file = File::open(&path_buf)?; + 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 => { + ( + 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)?; @@ -820,43 +807,39 @@ impl<'a> LoadState<'a> { // nothing to do. Ok(()) } - CompilationTarget::Module(module_name) => { - self.import_module(module_name) - } + CompilationTarget::Module(module_name) => self.import_module(module_name), } } - pub(crate) - fn use_qualified_module( + pub(crate) fn use_qualified_module( &mut self, module_src: ModuleSource, exports: IndexSet, ) -> 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)?; + 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); - } + ( + 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)?; @@ -884,12 +867,9 @@ impl<'a> LoadState<'a> { } #[inline] - pub(super) - fn composite_op_dir(&self) -> CompositeOpDir { + pub(super) fn composite_op_dir(&self) -> CompositeOpDir { match &self.compilation_target { - CompilationTarget::User => { - CompositeOpDir::new(&self.wam.indices.op_dir, None) - } + 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) => { diff --git a/src/machine/loader.rs b/src/machine/loader.rs index e7eb1165..040e478c 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1,11 +1,12 @@ use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::{clause_name, temp_v}; use crate::forms::*; use crate::indexing::*; -use crate::machine::*; use crate::machine::load_state::*; use crate::machine::machine_indices::*; use crate::machine::preprocessor::*; +use crate::machine::*; use indexmap::IndexSet; @@ -77,7 +78,13 @@ pub(crate) enum RetractionRecord { SkeletonClausePopFront(CompilationTarget, PredicateKey), SkeletonClauseTruncateBack(CompilationTarget, PredicateKey, usize), SkeletonClauseStartReplaced(CompilationTarget, PredicateKey, usize, usize), - RemovedDynamicSkeletonClause(CompilationTarget, PredicateKey, usize, ClauseIndexInfo, usize), + RemovedDynamicSkeletonClause( + CompilationTarget, + PredicateKey, + usize, + ClauseIndexInfo, + usize, + ), ReplacedIndexingLine(usize, Vec), } @@ -97,8 +104,7 @@ pub(super) struct RetractionInfo { impl RetractionInfo { #[inline] - pub(super) - fn new(orig_code_extent: usize) -> Self { + pub(super) fn new(orig_code_extent: usize) -> Self { Self { orig_code_extent, records: vec![], //BTreeMap::new(), @@ -106,14 +112,12 @@ impl RetractionInfo { } #[inline] - pub(crate) - fn push_record(&mut self, record: RetractionRecord) { + pub(crate) fn push_record(&mut self, record: RetractionRecord) { self.records.push(record); } #[inline] - pub(crate) - fn reset(&mut self, code_len: usize) -> Self { + pub(crate) fn reset(&mut self, code_len: usize) -> Self { let orig_code_extent = self.orig_code_extent; self.orig_code_extent = code_len; @@ -133,39 +137,34 @@ impl<'a> Drop for LoadState<'a> { "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!() - } + _ => 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, - ); + 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!() - } + _ => 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) => { @@ -185,44 +184,40 @@ impl<'a> Drop for LoadState<'a> { 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 => { + 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, - ); + 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(); - }); + 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(); - }); + 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 => { - } + None => {} } } RetractionRecord::ReplacedModuleOp(module_name, mut op_decl, prec, spec) => { @@ -232,8 +227,7 @@ impl<'a> Drop for LoadState<'a> { op_decl.spec = spec; op_decl.insert_into_op_dir(&mut module.op_dir); } - None => { - } + None => {} } } RetractionRecord::AddedModulePredicate(module_name, key) => { @@ -241,48 +235,49 @@ impl<'a> Drop for LoadState<'a> { Some(ref mut module) => { module.code_dir.remove(&key); } - None => { - } + 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 + module + .code_dir .get_mut(&key) .map(|code_idx| code_idx.replace(old_code_idx)); } - None => { - } + None => {} } } RetractionRecord::AddedUserDynamicPredicate(key) => { - self.wam.indices.extensible_predicates.get_mut(&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, - ); + 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(); - }); + 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(); - }); + 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); @@ -296,24 +291,29 @@ impl<'a> Drop for LoadState<'a> { self.wam.indices.code_dir.remove(&key); } RetractionRecord::ReplacedUserPredicate(key, old_code_idx) => { - self.wam.indices.code_dir + 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) => { + 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!() - } - }; + 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) => { + OptArgIndexKey::Constant( + _, + index_loc, + constant, + overlapping_constants, + ) => { remove_constant_indices( &constant, &overlapping_constants, @@ -348,9 +348,9 @@ impl<'a> Drop for LoadState<'a> { } 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)) => { + Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) + | Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) + | Line::Choice(ChoiceInstruction::DefaultRetryMeElse(ref mut o)) => { *o = offset; } _ => { @@ -374,19 +374,17 @@ impl<'a> Drop for LoadState<'a> { } 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; - } - _ => { - } + 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) => { @@ -406,106 +404,108 @@ impl<'a> Drop for LoadState<'a> { module.clause_assert_margin -= incr; } } - RetractionRecord::SkeletonClauseClausesTruncateFront(compilation_target, key, len) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + 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 => { - } + None => {} } - let compilation_target = - match compilation_target { - CompilationTarget::User => { - CompilationTarget::Module(clause_name!("builtins")) - } - _ => { - compilation_target - } - }; + 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), - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &(clause_name!("$clause"), 2)) + { Some(skeleton) => { skeleton.clause_clause_locs.truncate_front(len); } - None => { - } + None => {} } } - RetractionRecord::SkeletonClauseClausesTruncateBack(compilation_target, key, len) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + 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 => { - } + None => {} } - let compilation_target = - match compilation_target { - CompilationTarget::User => { - CompilationTarget::Module(clause_name!("builtins")) - } - _ => { - compilation_target - } - }; + 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), - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &(clause_name!("$clause"), 2)) + { Some(skeleton) => { skeleton.clause_clause_locs.truncate_back(len); } - None => { - } + None => {} } } RetractionRecord::SkeletonClausePopBack(compilation_target, key) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { skeleton.clauses.pop_back(); } - None => { - } + None => {} } } RetractionRecord::SkeletonClausePopFront(compilation_target, key) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { skeleton.clauses.pop_front(); } - None => { - } + None => {} } } RetractionRecord::SkeletonClauseTruncateBack(compilation_target, key, len) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { skeleton.clauses.truncate_back(len); } - None => { - } + None => {} } } RetractionRecord::SkeletonClauseStartReplaced( @@ -514,15 +514,15 @@ impl<'a> Drop for LoadState<'a> { target_pos, clause_start, ) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { skeleton.clauses[target_pos].clause_start = clause_start; } - None => { - } + None => {} } } RetractionRecord::RemovedDynamicSkeletonClause( @@ -532,16 +532,18 @@ impl<'a> Drop for LoadState<'a> { clause_index_info, clause_clause_loc, ) => { - match self.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { - skeleton.clause_clause_locs.insert(target_pos, clause_clause_loc); + skeleton + .clause_clause_locs + .insert(target_pos, clause_clause_loc); skeleton.clauses.insert(target_pos, clause_index_info); } - None => { - } + None => {} } } RetractionRecord::ReplacedIndexingLine(index_loc, indexing_code) => { @@ -570,21 +572,17 @@ impl Default for CompilationTarget { impl CompilationTarget { #[inline] - pub(super) - fn take(&mut self) -> CompilationTarget { + pub(super) fn take(&mut self) -> CompilationTarget { mem::replace(self, CompilationTarget::User) } #[inline] - pub(super) - fn module_name(&self) -> ClauseName { + pub(super) fn module_name(&self) -> ClauseName { match self { CompilationTarget::User => { clause_name!("user") } - CompilationTarget::Module(ref module_name) => { - module_name.clone() - } + CompilationTarget::Module(ref module_name) => module_name.clone(), } } } @@ -600,8 +598,7 @@ pub(crate) struct Loader<'a, TermStream> { impl<'a, TS: TermStream> Loader<'a, TS> { #[inline] - pub(super) - fn new(term_stream: TS, wam: &'a mut Machine) -> Self { + 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, @@ -620,8 +617,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - pub(crate) - fn load(mut self) -> Result { + pub(crate) fn load(mut self) -> Result { while let Some(decl) = self.dequeue_terms()? { self.load_decl(decl)?; } @@ -645,43 +641,32 @@ impl<'a, TS: TermStream> Loader<'a, TS> { )?; 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), + 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> { + 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, - ); + 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(), - ); + 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)); @@ -700,10 +685,9 @@ impl<'a, TS: TermStream> Loader<'a, TS> { Ok(()) } - pub(super) - fn read_term_from_heap(&self, heap_term_loc: RegType) -> Result { + pub(super) fn read_term_from_heap(&self, heap_term_loc: RegType) -> Result { let machine_st = &self.load_state.wam.machine_st; - let term_addr = machine_st[heap_term_loc]; + let term_addr = machine_st[heap_term_loc]; if machine_st.is_cyclic_term(term_addr) { return Err(SessionError::from(CompilationError::CannotParseCyclicTerm)); @@ -713,31 +697,20 @@ impl<'a, TS: TermStream> Loader<'a, TS> { 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(..)) => { + 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), - )); + 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), - }; + 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), - )); + term_stack.push(Term::Var(Cell::default(), Rc::new(offset_string))); } else { match addr.as_constant_index(machine_st) { Some(constant) => { @@ -762,7 +735,8 @@ impl<'a, TS: TermStream> Loader<'a, TS> { )); } HeapCellValue::NamedStr(arity, ref name, ref shared_op_desc) => { - let subterms = term_stack.drain(term_stack.len() - arity ..) + let subterms = term_stack + .drain(term_stack.len() - arity..) .map(Box::new) .collect(); @@ -810,18 +784,16 @@ impl<'a, TS: TermStream> Loader<'a, TS> { 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(); + 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)); + } + 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)); } @@ -838,59 +810,63 @@ impl<'a, TS: TermStream> Loader<'a, TS> { match &self.load_state.compilation_target { CompilationTarget::User => { - match self.load_state.wam.indices.extensible_predicates.get_mut(&key) { + 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()) + RetractionRecord::AddedUserDynamicPredicate(key.clone()), ); } } None => { - self.load_state.wam.indices.extensible_predicates.insert( - key.clone(), - PredicateSkeleton::new().set_dynamic(true), - ); + 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()) + 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), - ); + 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::AddedModuleExtensiblePredicate( + 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!(); } @@ -911,36 +887,27 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } 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)])); + 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 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)); @@ -950,7 +917,9 @@ impl Machine { if export_list.is_empty() { loader.load_state.use_module(module_src)?; } else { - loader.load_state.use_qualified_module(module_src, export_list)?; + loader + .load_state + .use_qualified_module(module_src, export_list)?; } LiveTermStream::evacuate(loader) @@ -960,13 +929,11 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn load_compiled_library(&mut self) { + 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)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); if let Some(module) = self.indices.modules.get(&library) { @@ -989,13 +956,11 @@ impl Machine { } } - pub(crate) - fn declare_module(&mut self) { + 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)] - )) + 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)); @@ -1018,27 +983,24 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn add_dynamic_predicate(&mut self) { + 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)] - )) + 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 = 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 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)); @@ -1051,8 +1013,7 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn add_term_expansion_clause(&mut self) { + 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 = || { @@ -1073,22 +1034,19 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn add_goal_expansion_clause(&mut self) { + 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)] - )) + 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 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))?; @@ -1108,22 +1066,25 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn loader_from_heap_evacuable(&mut self, r: RegType) -> (Loader, 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!() - } - }; + pub(crate) fn loader_from_heap_evacuable( + &mut self, + r: RegType, + ) -> (Loader, 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) => { @@ -1136,31 +1097,32 @@ impl Machine { } #[inline] - pub(crate) - fn push_load_state_payload(&mut self) { + 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 + .heap + .push(HeapCellValue::LoadStatePayload(payload)), ); - self.machine_st.bind(self.machine_st[temp_v!(1)].as_var().unwrap(), addr); + 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!() - } - }; + 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) => { @@ -1177,46 +1139,39 @@ impl Machine { } #[inline] - pub(crate) - fn pop_load_context(&mut self) { + 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, - ) - ); + 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)] - )) - ); + 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)); + self.load_contexts + .push(LoadContext::new(path.as_str(), stream)); } - pub(crate) - fn restore_load_state_payload( + pub(crate) fn restore_load_state_payload( &mut self, result: Result, evacuable_h: usize, ) { match result { Ok(payload) => { - self.machine_st.heap[evacuable_h] = HeapCellValue::LoadStatePayload( - payload - ); + self.machine_st.heap[evacuable_h] = HeapCellValue::LoadStatePayload(payload); } Err(e) => { self.throw_session_error(e, (clause_name!("load"), 1)); @@ -1224,8 +1179,7 @@ impl Machine { } } - pub(crate) - fn clause_to_evacuable(&mut self) { + pub(crate) fn clause_to_evacuable(&mut self) { let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2)); let enqueue_term = || { @@ -1234,12 +1188,16 @@ impl Machine { if let Some(predicate_name) = ClauseInfo::name(&term) { let arity = ClauseInfo::arity(&term); - let is_dynamic = - loader.load_state.wam.indices.get_predicate_skeleton( + 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); + ) + .map(|skeleton| skeleton.is_dynamic) + .unwrap_or(false); if is_dynamic { loader.add_clause_clause(term.clone())?; @@ -1254,8 +1212,7 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn conclude_load(&mut self) { + pub(crate) fn conclude_load(&mut self) { let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(1)); let compile_final_terms = || { @@ -1271,25 +1228,25 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } - pub(crate) - fn load_context_source(&mut self) { + 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_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 + .heap + .push(HeapCellValue::Atom(path_atom, None)), ); - self.machine_st.unify(path_addr, self.machine_st[temp_v!(1)]); + 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) { + 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(); @@ -1297,10 +1254,13 @@ impl Machine { 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 + .heap + .push(HeapCellValue::Atom(file_name_atom, None)), ); - self.machine_st.unify(file_name_addr, self.machine_st[temp_v!(1)]); + self.machine_st + .unify(file_name_addr, self.machine_st[temp_v!(1)]); return; } } @@ -1308,8 +1268,7 @@ impl Machine { self.machine_st.fail = true; } - pub(crate) - fn load_context_directory(&mut self) { + 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(); @@ -1317,10 +1276,13 @@ impl Machine { 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 + .heap + .push(HeapCellValue::Atom(directory_atom, None)), ); - self.machine_st.unify(directory_addr, self.machine_st[temp_v!(1)]); + self.machine_st + .unify(directory_addr, self.machine_st[temp_v!(1)]); return; } } @@ -1328,56 +1290,51 @@ impl Machine { self.machine_st.fail = true; } - pub(crate) - fn load_context_module(&mut self) { + 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 + .heap + .push(HeapCellValue::Atom(load_context.module.clone(), None)), ); - self.machine_st.unify(module_name_addr, self.machine_st[temp_v!(1)]); + 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) { + 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 + .heap + .push(HeapCellValue::Stream(load_context.stream.clone())), ); - self.machine_st.unify(stream_addr, self.machine_st[temp_v!(1)]); + self.machine_st + .unify(stream_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } } - pub(crate) - fn compile_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)], - ); + pub(crate) fn compile_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 module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(5)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(5)])) ); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; let compile_assert = || { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); @@ -1385,13 +1342,12 @@ impl Machine { 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), - ); + 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(), @@ -1402,10 +1358,12 @@ impl Machine { )?; // if a new predicate was just created, make it dynamic. - loader.load_state.wam.indices.get_predicate_skeleton( - &compilation_target, - &key, - ).map(|skeleton| skeleton.is_dynamic = true); + loader + .load_state + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + .map(|skeleton| skeleton.is_dynamic = true); loader.compile_clause_clauses( key, @@ -1418,48 +1376,43 @@ impl Machine { }; match compile_assert() { - Ok(_) => { - } + Ok(_) => {} Err(e) => { - let error_pi = - match append_or_prepend { - AppendOrPrepend::Append => (clause_name!("assertz"), 1), - AppendOrPrepend::Prepend => (clause_name!("asserta"), 1), - }; + 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 abolish_clause(&mut self) { + pub(crate) fn abolish_clause(&mut self) { let module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(1)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); - let key = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(2)], - self.machine_st[temp_v!(3)], - ); + let key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); loader.load_state.compilation_target = compilation_target; - match loader.load_state.wam.indices.get_predicate_skeleton( - &loader.load_state.compilation_target, - &key - ) { + match loader + .load_state + .wam + .indices + .get_predicate_skeleton(&loader.load_state.compilation_target, &key) + { Some(skeleton) => { skeleton.clauses.clear(); skeleton.clause_clause_locs.clear(); @@ -1477,8 +1430,7 @@ impl Machine { loader.load_state.compilation_target = CompilationTarget::Module(clause_name!("builtins")); } - _ => { - } + _ => {} }; match loader.load_state.wam.indices.get_predicate_skeleton( @@ -1494,56 +1446,43 @@ impl Machine { } } - let clause_clause_code_index = loader.load_state.get_or_insert_code_index( - (clause_name!("$clause"), 2), - ); + let clause_clause_code_index = loader + .load_state + .get_or_insert_code_index((clause_name!("$clause"), 2)); clause_clause_code_index.set(IndexPtr::DynamicUndefined); } - pub(crate) - fn retract_clause(&mut self) { - let key = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(1)], - self.machine_st[temp_v!(2)], - ); + pub(crate) fn retract_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 = 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 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 module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(4)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(4)])) ); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; - let clause_clause_compilation_target = - match &compilation_target { - CompilationTarget::User => { - CompilationTarget::Module(clause_name!("builtins")) - } - _ => { - compilation_target.clone() - } - }; + let clause_clause_compilation_target = match &compilation_target { + CompilationTarget::User => CompilationTarget::Module(clause_name!("builtins")), + _ => compilation_target.clone(), + }; let retract_clause = || { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); @@ -1551,99 +1490,107 @@ impl Machine { let clause_clause_loc = loader.load_state.retract_clause(key, target_pos); - let clause_assert_margin = - loader.load_state.wam.indices.modules - .get(&clause_clause_compilation_target.module_name()) - .map(|module| module.clause_assert_margin) - .unwrap(); + let clause_assert_margin = loader + .load_state + .wam + .indices + .modules + .get(&clause_clause_compilation_target.module_name()) + .map(|module| module.clause_assert_margin) + .unwrap(); - let target_pos = - match loader.load_state.wam.indices.get_predicate_skeleton( - &clause_clause_compilation_target, - &(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 target_pos = match loader.load_state.wam.indices.get_predicate_skeleton( + &clause_clause_compilation_target, + &(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 - }); + 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_clause_compilation_target.module_name()) - .map(|module| module.clause_assert_margin -= 1); - } - - result + if result < clause_assert_margin { + loader + .load_state + .wam + .indices + .modules + .get_mut(&clause_clause_compilation_target.module_name()) + .map(|module| module.clause_assert_margin -= 1); } - None => { - unreachable!(); - } - }; + + result + } + None => { + unreachable!(); + } + }; loader.load_state.compilation_target = clause_clause_compilation_target; - loader.load_state.retract_clause((clause_name!("$clause"), 2), target_pos); + loader + .load_state + .retract_clause((clause_name!("$clause"), 2), target_pos); LiveTermStream::evacuate(loader) }; match retract_clause() { - Ok(_) => { - } + Ok(_) => {} Err(e) => { self.throw_session_error(e, (clause_name!("retract"), 1)); } } } - pub(crate) - fn meta_predicate_property(&mut self) { + pub(crate) fn meta_predicate_property(&mut self) { let module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(1)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); - let (predicate_name, arity) = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(2)], - self.machine_st[temp_v!(3)], - ); + let (predicate_name, arity) = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; - match self.indices.get_meta_predicate_spec(predicate_name, arity, &compilation_target) { + match self + .indices + .get_meta_predicate_spec(predicate_name, arity, &compilation_target) + { Some(meta_specs) => { - 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)) - } + 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)) } - }), - ); + })); - let heap_loc = self.machine_st.heap.push( - HeapCellValue::NamedStr(1, clause_name!("meta_predicate"), None), - ); + 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!(4)]); + self.machine_st + .heap + .push(HeapCellValue::Addr(Addr::HeapCell(list_loc))); + self.machine_st + .unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(4)]); } None => { self.machine_st.fail = true; @@ -1651,31 +1598,26 @@ impl Machine { } } - pub(crate) - fn dynamic_property(&mut self) { + pub(crate) fn dynamic_property(&mut self) { let module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(1)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); - let key = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(2)], - self.machine_st[temp_v!(3)], - ); + let key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; - match self.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { self.machine_st.fail = !skeleton.is_dynamic; } @@ -1685,31 +1627,26 @@ impl Machine { } } - pub(crate) - fn multifile_property(&mut self) { + pub(crate) fn multifile_property(&mut self) { let module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(1)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); - let key = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(2)], - self.machine_st[temp_v!(3)], - ); + let key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; - match self.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { self.machine_st.fail = !skeleton.is_multifile; } @@ -1719,31 +1656,26 @@ impl Machine { } } - pub(crate) - fn discontiguous_property(&mut self) { + pub(crate) fn discontiguous_property(&mut self) { let module_name = atom_from!( self.machine_st, - self.machine_st.store(self.machine_st.deref( - self.machine_st[temp_v!(1)] - )) + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); - let key = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(2)], - self.machine_st[temp_v!(3)], - ); + let key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]); - let compilation_target = - match module_name.as_str() { - "user" => CompilationTarget::User, - _ => CompilationTarget::Module(module_name), - }; + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; - match self.indices.get_predicate_skeleton( - &compilation_target, - &key, - ) { + match self + .indices + .get_predicate_skeleton(&compilation_target, &key) + { Some(skeleton) => { self.machine_st.fail = !skeleton.is_discontiguous; } @@ -1753,13 +1685,10 @@ impl Machine { } } - pub(crate) - fn builtin_property(&mut self) { - let key = - self.machine_st.read_predicate_key( - self.machine_st[temp_v!(1)], - self.machine_st[temp_v!(2)], - ); + pub(crate) fn builtin_property(&mut self) { + let key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)]); match ClauseType::from(key.0, key.1, None) { ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN => { @@ -1767,24 +1696,21 @@ impl Machine { } ClauseType::Named(ref name, arity, _) => { if let Some(module) = self.indices.modules.get(&(clause_name!("builtins"))) { - self.machine_st.fail = !module.code_dir.contains_key( - &(name.clone(), arity), - ); + self.machine_st.fail = !module.code_dir.contains_key(&(name.clone(), arity)); return; } } ClauseType::Op(ref name, ref op_desc, _) => { if let Some(module) = self.indices.modules.get(&(clause_name!("builtins"))) { - self.machine_st.fail = !module.code_dir.contains_key( - &(name.clone(), op_desc.arity()), - ); + self.machine_st.fail = !module + .code_dir + .contains_key(&(name.clone(), op_desc.arity())); return; } } - _ => { - } + _ => {} } self.machine_st.fail = true; @@ -1792,89 +1718,48 @@ impl Machine { } impl<'a> Loader<'a, LiveTermStream> { - pub(super) - fn to_load_state_payload(mut self) -> LoadStatePayload { + 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![], - ), + 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 { + 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![], - ), + 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), - ), + module_op_exports: mem::replace(&mut payload.module_op_exports, vec![]), + retraction_info: mem::replace(&mut payload.retraction_info, RetractionInfo::new(0)), wam, }, } @@ -1890,26 +1775,17 @@ impl<'a> Loader<'a, LiveTermStream> { ) -> 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 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 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); @@ -1935,8 +1811,7 @@ impl<'a> Loader<'a, LiveTermStream> { } #[inline] -pub(super) -fn load_module( +pub(super) fn load_module( code_dir: &mut CodeDir, op_dir: &mut OpDir, meta_predicate_dir: &mut MetaPredicateDir, diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index ffb95aef..1ca1861d 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -1,4 +1,5 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::{clause_name, temp_v}; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; use crate::machine::heap::*; @@ -23,74 +24,59 @@ pub(crate) struct MachineError { from: ErrorProvenance, } -pub(crate) -trait TypeError { +pub(crate) trait TypeError { fn type_error(self, h: usize, valid_type: ValidType) -> MachineError; } impl TypeError for Addr { fn type_error(self, _: usize, valid_type: ValidType) -> MachineError { - let stub = functor!( - "type_error", - [atom(valid_type.as_str()), addr(self)] - ); + let stub = functor!("type_error", [atom(valid_type.as_str()), addr(self)]); MachineError { stub, location: None, - from: ErrorProvenance::Received + from: ErrorProvenance::Received, } } } impl TypeError for HeapCellValue { fn type_error(self, _: usize, valid_type: ValidType) -> MachineError { - let stub = functor!( - "type_error", - [atom(valid_type.as_str()), value(self)] - ); + let stub = functor!("type_error", [atom(valid_type.as_str()), value(self)]); MachineError { stub, location: None, - from: ErrorProvenance::Received + from: ErrorProvenance::Received, } } } impl TypeError for MachineStub { fn type_error(self, h: usize, valid_type: ValidType) -> MachineError { - let stub = functor!( - "type_error", - [atom(valid_type.as_str()), aux(h, 0)], - [self] - ); + let stub = functor!("type_error", [atom(valid_type.as_str()), aux(h, 0)], [self]); MachineError { stub, location: None, - from: ErrorProvenance::Constructed + from: ErrorProvenance::Constructed, } } } impl TypeError for Number { fn type_error(self, _h: usize, valid_type: ValidType) -> MachineError { - let stub = functor!( - "type_error", - [atom(valid_type.as_str()), number(self)] - ); + let stub = functor!("type_error", [atom(valid_type.as_str()), number(self)]); MachineError { stub, location: None, - from: ErrorProvenance::Received + from: ErrorProvenance::Received, } } } -pub(crate) -trait PermissionError { +pub(crate) trait PermissionError { fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError; } @@ -104,7 +90,7 @@ impl PermissionError for Addr { MachineError { stub, location: None, - from: ErrorProvenance::Received + from: ErrorProvenance::Received, } } } @@ -120,22 +106,18 @@ impl PermissionError for MachineStub { MachineError { stub, location: None, - from: ErrorProvenance::Constructed + from: ErrorProvenance::Constructed, } } } -pub(super) -trait DomainError { +pub(super) trait DomainError { fn domain_error(self, error: DomainErrorType) -> MachineError; } impl DomainError for Addr { fn domain_error(self, error: DomainErrorType) -> MachineError { - let stub = functor!( - "domain_error", - [atom(error.as_str()), addr(self)] - ); + let stub = functor!("domain_error", [atom(error.as_str()), addr(self)]); MachineError { stub, @@ -147,10 +129,7 @@ impl DomainError for Addr { impl DomainError for Number { fn domain_error(self, error: DomainErrorType) -> MachineError { - let stub = functor!( - "domain_error", - [atom(error.as_str()), number(self)] - ); + let stub = functor!("domain_error", [atom(error.as_str()), number(self)]); MachineError { stub, @@ -161,8 +140,7 @@ impl DomainError for Number { } impl MachineError { - pub(super) - fn functor_stub(name: ClauseName, arity: usize) -> MachineStub { + pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub { functor!( "/", SharedOpDesc::new(400, YFX), @@ -171,8 +149,7 @@ impl MachineError { } #[inline] - pub(super) - fn interrupt_error() -> Self { + pub(super) fn interrupt_error() -> Self { let stub = functor!("$interrupt_thrown"); MachineError { @@ -182,8 +159,7 @@ impl MachineError { } } - pub(super) - fn evaluation_error(eval_error: EvalError) -> Self { + pub(super) fn evaluation_error(eval_error: EvalError) -> Self { let stub = functor!("evaluation_error", [atom(eval_error.as_str())]); MachineError { @@ -193,13 +169,11 @@ impl MachineError { } } - pub(super) - fn type_error(h: usize, valid_type: ValidType, culprit: T) -> Self { + pub(super) fn type_error(h: usize, valid_type: ValidType, culprit: T) -> Self { culprit.type_error(h, valid_type) } - pub(super) - fn module_resolution_error( + pub(super) fn module_resolution_error( h: usize, mod_name: ClauseName, name: ClauseName, @@ -218,11 +192,7 @@ impl MachineError { [res_stub] ); - let stub = functor!( - "evaluation_error", - [aux(h, 0)], - [ind_stub] - ); + let stub = functor!("evaluation_error", [aux(h, 0)], [ind_stub]); MachineError { stub, @@ -231,14 +201,10 @@ impl MachineError { } } - pub(super) - fn existence_error(h: usize, err: ExistenceError) -> Self { + pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self { match err { ExistenceError::Module(name) => { - let stub = functor!( - "existence_error", - [atom("source_sink"), clause_name(name)] - ); + let stub = functor!("existence_error", [atom("source_sink"), clause_name(name)]); MachineError { stub, @@ -253,11 +219,7 @@ impl MachineError { [clause_name(name), integer(arity)] ); - let stub = functor!( - "existence_error", - [atom("procedure"), aux(h, 0)], - [culprit] - ); + let stub = functor!("existence_error", [atom("procedure"), aux(h, 0)], [culprit]); MachineError { stub, @@ -281,10 +243,7 @@ impl MachineError { } } ExistenceError::SourceSink(culprit) => { - let stub = functor!( - "existence_error", - [atom("source_sink"), addr(culprit)] - ); + let stub = functor!("existence_error", [atom("source_sink"), addr(culprit)]); MachineError { stub, @@ -293,10 +252,7 @@ impl MachineError { } } ExistenceError::Stream(culprit) => { - let stub = functor!( - "existence_error", - [atom("stream"), addr(culprit)] - ); + let stub = functor!("existence_error", [atom("stream"), addr(culprit)]); MachineError { stub, @@ -307,25 +263,18 @@ impl MachineError { } } - pub(super) - fn permission_error( + pub(super) fn permission_error( h: usize, err: Permission, index_str: &'static str, culprit: T, ) -> Self { - culprit.permission_error( - h, - index_str, - err, - ) + culprit.permission_error(h, index_str, err) } fn arithmetic_error(h: usize, err: ArithmeticError) -> Self { match err { - ArithmeticError::UninstantiatedVar => { - Self::instantiation_error() - } + ArithmeticError::UninstantiatedVar => Self::instantiation_error(), ArithmeticError::NonEvaluableFunctor(name, arity) => { let culprit = functor!( "/", @@ -339,13 +288,11 @@ impl MachineError { } #[inline] - pub(super) - fn domain_error(error: DomainErrorType, culprit: T) -> Self { + pub(super) fn domain_error(error: DomainErrorType, culprit: T) -> Self { culprit.domain_error(error) } - pub(super) - fn instantiation_error() -> Self { + pub(super) fn instantiation_error() -> Self { let stub = functor!("instantiation_error"); MachineError { @@ -355,8 +302,7 @@ impl MachineError { } } - pub(super) - fn session_error(h: usize, err: SessionError) -> Self { + pub(super) fn session_error(h: usize, err: SessionError) -> Self { match err { // SessionError::CannotOverwriteBuiltIn(pred_str) | /* @@ -369,9 +315,7 @@ impl MachineError { ) } */ - SessionError::ExistenceError(err) => { - Self::existence_error(h, err) - } + SessionError::ExistenceError(err) => Self::existence_error(h, err), // SessionError::InvalidFileName(filename) => { // Self::existence_error(h, ExistenceError::Module(filename)) // } @@ -385,46 +329,32 @@ impl MachineError { ) } */ - 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, - Permission::Create, - "static_procedure", - functor!("nameless_procedure") - ) - } + 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, + Permission::Create, + "static_procedure", + functor!("nameless_procedure"), + ), SessionError::OpIsInfixAndPostFix(op) => { - Self::permission_error( - h, - Permission::Create, - "operator", - functor!(clause_name(op)), - ) - } - SessionError::CompilationError(err) => { - Self::syntax_error(h, err) - } - SessionError::QueryCannotBeDefinedAsFact => { - Self::permission_error( - h, - Permission::Create, - "static_procedure", - functor!("query_cannot_be_defined_as_fact") - ) + Self::permission_error(h, Permission::Create, "operator", functor!(clause_name(op))) } + SessionError::CompilationError(err) => Self::syntax_error(h, err), + SessionError::QueryCannotBeDefinedAsFact => Self::permission_error( + h, + Permission::Create, + "static_procedure", + functor!("query_cannot_be_defined_as_fact"), + ), } } - pub(super) - fn syntax_error>(h: usize, err: E) -> Self { + pub(super) fn syntax_error>(h: usize, err: E) -> Self { let err = err.into(); if let CompilationError::Arithmetic(err) = err { @@ -434,11 +364,7 @@ impl MachineError { let location = err.line_and_col_num(); let stub = err.as_functor(h); - let stub = functor!( - "syntax_error", - [aux(h, 0)], - [stub] - ); + let stub = functor!("syntax_error", [aux(h, 0)], [stub]); MachineError { stub, @@ -447,8 +373,7 @@ impl MachineError { } } - pub(super) - fn representation_error(flag: RepFlag) -> Self { + pub(super) fn representation_error(flag: RepFlag) -> Self { let stub = functor!("representation_error", [atom(flag.as_str())]); MachineError { @@ -515,56 +440,39 @@ impl From for CompilationError { impl CompilationError { pub fn line_and_col_num(&self) -> Option<(usize, usize)> { match self { - &CompilationError::ParserError(ref err) => - err.line_and_col_num(), - _ => - None + &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::Arithmetic(..) => functor!("arithmetic_error"), // &CompilationError::BadPendingByte => // functor!("bad_pending_byte"), - &CompilationError::CannotParseCyclicTerm => - functor!("cannot_parse_cyclic_term"), + &CompilationError::CannotParseCyclicTerm => functor!("cannot_parse_cyclic_term"), // &CompilationError::ExpandedTermsListNotAList => // functor!("expanded_terms_list_is_not_a_list"), - &CompilationError::ExpectedRel => - functor!("expected_relation"), + &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::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"), + &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"), } } } @@ -715,16 +623,15 @@ impl EvalError { pub(super) enum CycleSearchResult { EmptyList, NotList, - PartialList(usize, Ref), // the list length (up to max), and an offset into the heap. - ProperList(usize), // the list length. + PartialList(usize, Ref), // the list length (up to max), and an offset into the heap. + ProperList(usize), // the list length. PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string. UntouchedList(usize), // the address of an uniterated Addr::Lis(address). } impl MachineState { // see 8.4.3 of Draft Technical Corrigendum 2. - pub(super) - fn check_sort_errors(&self) -> CallResult { + pub(super) fn check_sort_errors(&self) -> CallResult { let stub = MachineError::functor_stub(clause_name!("sort"), 2); let list = self.store(self.deref(self[temp_v!(1)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone())); @@ -734,7 +641,9 @@ impl MachineState { return Err(self.error_form(MachineError::instantiation_error(), stub)) } CycleSearchResult::NotList => { - return Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub)) + return Err( + self.error_form(MachineError::type_error(0, ValidType::List, list), stub) + ) } _ => {} }; @@ -766,7 +675,8 @@ impl MachineState { new_l = l; } HeapCellValue::NamedStr(2, ref name, Some(_)) - if name.as_str() == "-" => { + if name.as_str() == "-" => + { break; } HeapCellValue::Addr(Addr::HeapCell(_)) => { @@ -793,11 +703,10 @@ impl MachineState { } // see 8.4.4 of Draft Technical Corrigendum 2. - pub(super) - fn check_keysort_errors(&self) -> CallResult { + pub(super) fn check_keysort_errors(&self) -> CallResult { let stub = MachineError::functor_stub(clause_name!("keysort"), 2); - let pairs = self.store(self.deref(self[temp_v!(1)].clone())); + let pairs = self.store(self.deref(self[temp_v!(1)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone())); match self.detect_cycles(pairs.clone()) { @@ -814,8 +723,7 @@ impl MachineState { } #[inline] - pub(crate) - fn type_error( + pub(crate) fn type_error( &self, valid_type: ValidType, culprit: T, @@ -823,33 +731,25 @@ impl MachineState { arity: usize, ) -> MachineStub { let stub = MachineError::functor_stub(caller, arity); - let err = MachineError::type_error( - self.heap.h(), - valid_type, - culprit, - ); + let err = MachineError::type_error(self.heap.h(), valid_type, culprit); return self.error_form(err, stub); } #[inline] - pub(crate) - fn representation_error( + pub(crate) fn representation_error( &self, rep_flag: RepFlag, caller: ClauseName, arity: usize, ) -> MachineStub { let stub = MachineError::functor_stub(caller, arity); - let err = MachineError::representation_error( - rep_flag, - ); + let err = MachineError::representation_error(rep_flag); return self.error_form(err, stub); } - pub(super) - fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub { + pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub { let location = err.location; let err_len = err.len(); @@ -874,8 +774,7 @@ impl MachineState { stub } - pub(super) - fn throw_exception(&mut self, err: MachineStub) { + pub(super) fn throw_exception(&mut self, err: MachineStub) { let h = self.heap.h(); self.ball.boundary = 0; diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index b6883e77..b4089147 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -1,18 +1,19 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::clause_name; use crate::clause_types::*; use crate::fixtures::*; use crate::forms::*; -use crate::machine::CompilationTarget; +use crate::instructions::*; use crate::machine::code_repo::CodeRepo; -use crate::machine::Ball; use crate::machine::heap::*; use crate::machine::machine_state::*; 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::machine::Ball; +use crate::machine::CompilationTarget; use crate::ordered_float::OrderedFloat; use crate::rug::{Integer, Rational}; @@ -96,20 +97,14 @@ impl Ord for Ref { fn cmp(&self, other: &Ref) -> Ordering { match (self, other) { (Ref::AttrVar(h1), Ref::AttrVar(h2)) - | (Ref::HeapCell(h1), Ref::HeapCell(h2)) - | (Ref::HeapCell(h1), Ref::AttrVar(h2)) - | (Ref::AttrVar(h1), Ref::HeapCell(h2)) => { - h1.cmp(&h2) - } + | (Ref::HeapCell(h1), Ref::HeapCell(h2)) + | (Ref::HeapCell(h1), Ref::AttrVar(h2)) + | (Ref::AttrVar(h1), Ref::HeapCell(h2)) => h1.cmp(&h2), (Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) => { fr1.cmp(&fr2).then_with(|| sc1.cmp(&sc2)) } - (Ref::StackCell(..), _) => { - Ordering::Greater - } - (_, Ref::StackCell(..)) => { - Ordering::Less - } + (Ref::StackCell(..), _) => Ordering::Greater, + (_, Ref::StackCell(..)) => Ordering::Less, } } } @@ -124,35 +119,23 @@ impl PartialEq for Addr { impl PartialOrd for Addr { fn partial_cmp(&self, r: &Ref) -> Option { match self { - &Addr::StackCell(fr, sc) => { - match *r { - Ref::AttrVar(_) | Ref::HeapCell(_) => { + &Addr::StackCell(fr, sc) => match *r { + Ref::AttrVar(_) | Ref::HeapCell(_) => Some(Ordering::Greater), + Ref::StackCell(fr1, sc1) => { + if fr1 < fr || (fr1 == fr && sc1 < sc) { Some(Ordering::Greater) - } - Ref::StackCell(fr1, sc1) => { - if fr1 < fr || (fr1 == fr && sc1 < sc) { - Some(Ordering::Greater) - } else if fr1 == fr && sc1 == sc { - Some(Ordering::Equal) - } else { - Some(Ordering::Less) - } - } - } - } - &Addr::HeapCell(h) | &Addr::AttrVar(h) => { - match r { - Ref::StackCell(..) => { + } else if fr1 == fr && sc1 == sc { + Some(Ordering::Equal) + } else { Some(Ordering::Less) } - Ref::AttrVar(h1) | Ref::HeapCell(h1) => { - h.partial_cmp(h1) - } } - } - _ => { - None - } + }, + &Addr::HeapCell(h) | &Addr::AttrVar(h) => match r { + Ref::StackCell(..) => Some(Ordering::Less), + Ref::AttrVar(h1) | Ref::HeapCell(h1) => h.partial_cmp(h1), + }, + _ => None, } } } @@ -161,26 +144,21 @@ impl Addr { #[inline] pub fn is_heap_bound(&self) -> bool { match self { - Addr::Char(_) | Addr::EmptyList | - Addr::CutPoint(_) | Addr::Usize(_) | Addr::Fixnum(_) | - Addr::Float(_) => { - false - } - _ => { - true - } + Addr::Char(_) + | Addr::EmptyList + | Addr::CutPoint(_) + | Addr::Usize(_) + | Addr::Fixnum(_) + | Addr::Float(_) => false, + _ => true, } } #[inline] pub fn is_ref(&self) -> bool { match self { - Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => { - true - } - _ => { - false - } + Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => true, + _ => false, } } @@ -194,92 +172,54 @@ impl Addr { } } - pub(super) - fn order_category(&self, heap: &Heap) -> Option { + pub(super) fn order_category(&self, heap: &Heap) -> Option { match Number::try_from((*self, heap)) { Ok(Number::Integer(_)) | Ok(Number::Fixnum(_)) | Ok(Number::Rational(_)) => { Some(TermOrderCategory::Integer) } - Ok(Number::Float(_)) => { - Some(TermOrderCategory::FloatingPoint) - } - _ => { - match self { - Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => { - Some(TermOrderCategory::Variable) - } - Addr::Float(_) => { - Some(TermOrderCategory::FloatingPoint) - } - &Addr::Con(h) => { - match &heap[h] { - HeapCellValue::Atom(..) => { - Some(TermOrderCategory::Atom) - } - HeapCellValue::DBRef(_) => { - None - } - _ => { - unreachable!() - } - } - } - Addr::Char(_) | Addr::EmptyList => { - Some(TermOrderCategory::Atom) - } - Addr::Fixnum(_) | Addr::Usize(_) => { - Some(TermOrderCategory::Integer) - } - Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => { - Some(TermOrderCategory::Compound) - } - Addr::CutPoint(_) | Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => { - None - } + Ok(Number::Float(_)) => Some(TermOrderCategory::FloatingPoint), + _ => match self { + Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => { + Some(TermOrderCategory::Variable) } - } + Addr::Float(_) => Some(TermOrderCategory::FloatingPoint), + &Addr::Con(h) => match &heap[h] { + HeapCellValue::Atom(..) => Some(TermOrderCategory::Atom), + HeapCellValue::DBRef(_) => None, + _ => { + unreachable!() + } + }, + Addr::Char(_) | Addr::EmptyList => Some(TermOrderCategory::Atom), + Addr::Fixnum(_) | Addr::Usize(_) => Some(TermOrderCategory::Integer), + Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => { + Some(TermOrderCategory::Compound) + } + Addr::CutPoint(_) + | Addr::LoadStatePayload(_) + | Addr::Stream(_) + | Addr::TcpListener(_) => None, + }, } } pub fn as_constant_index(&self, machine_st: &MachineState) -> Option { match self { - &Addr::Char(c) => { - Some(Constant::Char(c)) - } - &Addr::Con(h) => { - match &machine_st.heap[h] { - &HeapCellValue::Atom(ref name, _) if name.is_char() => { - Some(Constant::Char(name.as_str().chars().next().unwrap())) - } - &HeapCellValue::Atom(ref name, _) => { - Some(Constant::Atom(name.clone(), None)) - } - &HeapCellValue::Integer(ref n) => { - Some(Constant::Integer(n.clone())) - } - &HeapCellValue::Rational(ref n) => { - Some(Constant::Rational(n.clone())) - } - _ => { - None - } + &Addr::Char(c) => Some(Constant::Char(c)), + &Addr::Con(h) => match &machine_st.heap[h] { + &HeapCellValue::Atom(ref name, _) if name.is_char() => { + Some(Constant::Char(name.as_str().chars().next().unwrap())) } - } - &Addr::EmptyList => { - Some(Constant::EmptyList) - } - &Addr::Fixnum(n) => { - Some(Constant::Fixnum(n)) - } - &Addr::Float(f) => { - Some(Constant::Float(f)) - } - &Addr::Usize(n) => { - Some(Constant::Usize(n)) - } - _ => { - None - } + &HeapCellValue::Atom(ref name, _) => Some(Constant::Atom(name.clone(), None)), + &HeapCellValue::Integer(ref n) => Some(Constant::Integer(n.clone())), + &HeapCellValue::Rational(ref n) => Some(Constant::Rational(n.clone())), + _ => None, + }, + &Addr::EmptyList => Some(Constant::EmptyList), + &Addr::Fixnum(n) => Some(Constant::Fixnum(n)), + &Addr::Float(f) => Some(Constant::Float(f)), + &Addr::Usize(n) => Some(Constant::Usize(n)), + _ => None, } } @@ -383,61 +323,37 @@ impl HeapCellValue { #[inline] pub fn as_addr(&self, focus: usize) -> Addr { match self { - HeapCellValue::Addr(ref a) => { - *a - } - HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) | - HeapCellValue::Rational(..) => { - Addr::Con(focus) - } - HeapCellValue::LoadStatePayload(_) => { - Addr::LoadStatePayload(focus) - } - HeapCellValue::NamedStr(_, _, _) => { - Addr::Str(focus) - } - HeapCellValue::PartialString(..) => { - Addr::PStrLocation(focus, 0) - } - HeapCellValue::Stream(_) => { - Addr::Stream(focus) - } - HeapCellValue::TcpListener(_) => { - Addr::TcpListener(focus) - } + HeapCellValue::Addr(ref a) => *a, + HeapCellValue::Atom(..) + | HeapCellValue::DBRef(..) + | HeapCellValue::Integer(..) + | HeapCellValue::Rational(..) => Addr::Con(focus), + HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(focus), + HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus), + HeapCellValue::PartialString(..) => Addr::PStrLocation(focus, 0), + HeapCellValue::Stream(_) => Addr::Stream(focus), + HeapCellValue::TcpListener(_) => Addr::TcpListener(focus), } } #[inline] pub fn context_free_clone(&self) -> HeapCellValue { match self { - &HeapCellValue::Addr(addr) => { - HeapCellValue::Addr(addr) - } - &HeapCellValue::Atom(ref name, ref op) => { - HeapCellValue::Atom(name.clone(), op.clone()) - } - &HeapCellValue::DBRef(ref db_ref) => { - HeapCellValue::DBRef(db_ref.clone()) - } - &HeapCellValue::Integer(ref n) => { - HeapCellValue::Integer(n.clone()) - } + &HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr), + &HeapCellValue::Atom(ref name, ref op) => HeapCellValue::Atom(name.clone(), op.clone()), + &HeapCellValue::DBRef(ref db_ref) => HeapCellValue::DBRef(db_ref.clone()), + &HeapCellValue::Integer(ref n) => HeapCellValue::Integer(n.clone()), &HeapCellValue::LoadStatePayload(_) => { HeapCellValue::Atom(clause_name!("$live_term_stream"), None) } &HeapCellValue::NamedStr(arity, ref name, ref op) => { HeapCellValue::NamedStr(arity, name.clone(), op.clone()) } - &HeapCellValue::Rational(ref r) => { - HeapCellValue::Rational(r.clone()) - } + &HeapCellValue::Rational(ref r) => HeapCellValue::Rational(r.clone()), &HeapCellValue::PartialString(ref pstr, has_tail) => { HeapCellValue::PartialString(pstr.clone(), has_tail) } - &HeapCellValue::Stream(ref stream) => { - HeapCellValue::Stream(stream.clone()) - } + &HeapCellValue::Stream(ref stream) => HeapCellValue::Stream(stream.clone()), &HeapCellValue::TcpListener(_) => { HeapCellValue::Atom(clause_name!("$tcp_listener"), None) } @@ -473,8 +389,7 @@ impl Deref for CodeIndex { impl CodeIndex { #[inline] - pub(super) - fn new(ptr: IndexPtr) -> Self { + pub(super) fn new(ptr: IndexPtr) -> Self { CodeIndex(Rc::new(Cell::new(ptr))) } @@ -482,7 +397,7 @@ impl CodeIndex { pub fn is_undefined(&self) -> bool { match self.0.get() { IndexPtr::Undefined => true, // | &IndexPtr::DynamicUndefined => true, - _ => false + _ => false, } } @@ -536,7 +451,7 @@ pub enum CodePtr { CallN(usize, LocalCodePtr, bool), // arity, local, last call. Local(LocalCodePtr), // DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer. - REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer. + REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer. VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir. } @@ -544,10 +459,10 @@ impl CodePtr { pub fn local(&self) -> LocalCodePtr { match self { &CodePtr::BuiltInClause(_, ref local) - | &CodePtr::CallN(_, ref local, _) - | &CodePtr::Local(ref local) => local.clone(), + | &CodePtr::CallN(_, ref local, _) + | &CodePtr::Local(ref local) => local.clone(), &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p), - &CodePtr::REPL(_, p) => p // | &CodePtr::DynamicTransaction(_, p) => p, + &CodePtr::REPL(_, p) => p, // | &CodePtr::DynamicTransaction(_, p) => p, } } @@ -566,12 +481,11 @@ pub enum LocalCodePtr { DirEntry(usize), // offset Halt, IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset - // TopLevel(usize, usize), // chunk_num, offset + // TopLevel(usize, usize), // chunk_num, offset } impl LocalCodePtr { - pub(crate) - fn assign_if_local(&mut self, cp: CodePtr) { + pub(crate) fn assign_if_local(&mut self, cp: CodePtr) { match cp { CodePtr::Local(local) => *self = local, _ => {} @@ -579,8 +493,7 @@ impl LocalCodePtr { } #[inline] - pub(crate) - fn abs_loc(&self) -> usize { + pub(crate) fn abs_loc(&self) -> usize { match self { LocalCodePtr::DirEntry(ref p) => *p, LocalCodePtr::IndexingBuf(ref p, ..) => *p, @@ -588,35 +501,28 @@ impl LocalCodePtr { } } - pub(crate) - fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool { + 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)) { - Some(line) => { - match line.as_ref() { - Line::Control(ControlInstruction::CallClause(ref ct, ..)) => { - if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct { - return true; - } + Some(line) => match line.as_ref() { + Line::Control(ControlInstruction::CallClause(ref ct, ..)) => { + if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct { + return true; } - _ => {} } - } + _ => {} + }, None => {} } false } - pub(crate) - fn as_functor(&self, heap: &mut HeapTemplate) -> Addr { + pub(crate) fn as_functor(&self, heap: &mut HeapTemplate) -> Addr { let addr = Addr::HeapCell(heap.h()); match self { LocalCodePtr::DirEntry(p) => { - heap.append(functor!( - "dir_entry", - [integer(*p)] - )); + heap.append(functor!("dir_entry", [integer(*p)])); } LocalCodePtr::Halt => { heap.append(functor!("halt")); @@ -658,7 +564,7 @@ impl PartialOrd for CodePtr { impl PartialOrd for LocalCodePtr { fn partial_cmp(&self, other: &LocalCodePtr) -> Option { match (self, other) { - (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2)) | + (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2)) | (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => { p1.partial_cmp(p2) } @@ -693,12 +599,9 @@ impl Add for LocalCodePtr { #[inline] fn add(self, rhs: usize) -> Self::Output { match self { - LocalCodePtr::DirEntry(p) => - LocalCodePtr::DirEntry(p + rhs), - LocalCodePtr::Halt => - unreachable!(), - LocalCodePtr::IndexingBuf(p, o, i) => - LocalCodePtr::IndexingBuf(p, o, i + rhs), + LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs), + LocalCodePtr::Halt => unreachable!(), + LocalCodePtr::IndexingBuf(p, o, i) => LocalCodePtr::IndexingBuf(p, o, i + rhs), } } } @@ -709,12 +612,11 @@ impl Sub for LocalCodePtr { #[inline] fn sub(self, rhs: usize) -> Self::Output { match self { - LocalCodePtr::DirEntry(p) => - p.checked_sub(rhs).map(LocalCodePtr::DirEntry), - LocalCodePtr::Halt => - unreachable!(), - LocalCodePtr::IndexingBuf(p, o, i) => - i.checked_sub(rhs).map(|r| LocalCodePtr::IndexingBuf(p, o, r)), + LocalCodePtr::DirEntry(p) => p.checked_sub(rhs).map(LocalCodePtr::DirEntry), + LocalCodePtr::Halt => unreachable!(), + LocalCodePtr::IndexingBuf(p, o, i) => i + .checked_sub(rhs) + .map(|r| LocalCodePtr::IndexingBuf(p, o, r)), } } } @@ -723,15 +625,12 @@ impl SubAssign for LocalCodePtr { #[inline] fn sub_assign(&mut self, rhs: usize) { match self { - LocalCodePtr::DirEntry(ref mut p) => - *p -= rhs, - LocalCodePtr::Halt | LocalCodePtr::IndexingBuf(..) => - unreachable!(), + LocalCodePtr::DirEntry(ref mut p) => *p -= rhs, + LocalCodePtr::Halt | LocalCodePtr::IndexingBuf(..) => unreachable!(), } } } - impl AddAssign for LocalCodePtr { #[inline] fn add_assign(&mut self, rhs: usize) { @@ -749,14 +648,12 @@ impl Add for CodePtr { fn add(self, rhs: usize) -> Self::Output { match self { - p @ CodePtr::REPL(..) | - p @ CodePtr::VerifyAttrInterrupt(_) => { // | - // p @ CodePtr::DynamicTransaction(..) => { + p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => { + // | + // p @ CodePtr::DynamicTransaction(..) => { p } - CodePtr::Local(local) => { - CodePtr::Local(local + rhs) - } + CodePtr::Local(local) => CodePtr::Local(local + rhs), CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => { CodePtr::Local(local + rhs) } @@ -784,7 +681,6 @@ impl SubAssign for CodePtr { } } - pub type HeapVarDict = IndexMap, Addr>; pub type AllocVarDict = IndexMap, VarData>; @@ -830,23 +726,17 @@ impl IndexStore { 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 - } + ("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 } } - } + }, } } @@ -858,19 +748,17 @@ impl IndexStore { 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); - } + } + _ => 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); } } - } + }, } } @@ -883,15 +771,9 @@ impl IndexStore { ) -> Option { 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, ..) => { - self.code_dir.get(&(name, spec.arity())).cloned() - } - _ => { - None - } + ClauseType::Named(name, arity, _) => self.code_dir.get(&(name, arity)).cloned(), + ClauseType::Op(name, spec, ..) => self.code_dir.get(&(name, spec.arity())).cloned(), + _ => None, } } else { self.modules.get(&module).and_then(|module| { @@ -902,9 +784,7 @@ impl IndexStore { ClauseType::Op(name, spec, ..) => { module.code_dir.get(&(name, spec.arity())).cloned() } - _ => { - None - } + _ => None, } }) } @@ -917,44 +797,32 @@ impl IndexStore { compilation_target: &CompilationTarget, ) -> Option<&Vec> { 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)) - } - } - } + 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)), + }, } } pub fn is_dynamic_predicate(&self, module_name: ClauseName, key: PredicateKey) -> bool { match module_name.as_str() { - "user" => { - self.extensible_predicates.get(&key) + "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) - } - _ => { - match self.modules.get(&module_name) { - Some(ref module) => { - module.extensible_predicates.get(&key) - .map(|skeleton| skeleton.is_dynamic) - .unwrap_or(false) - } - None => { - false - } - } - } + .unwrap_or(false), + None => false, + }, } } @@ -963,8 +831,7 @@ impl IndexStore { 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"); @@ -996,10 +863,8 @@ pub enum RefOrOwned<'a, T: 'a> { impl<'a, T: 'a + fmt::Debug> fmt::Debug for RefOrOwned<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &RefOrOwned::Borrowed(ref borrowed) => - write!(f, "Borrowed({:?})", borrowed), - &RefOrOwned::Owned(ref owned) => - write!(f, "Owned({:?})", owned), + &RefOrOwned::Borrowed(ref borrowed) => write!(f, "Borrowed({:?})", borrowed), + &RefOrOwned::Owned(ref owned) => write!(f, "Owned({:?})", owned), } } } @@ -1012,7 +877,9 @@ impl<'a, T> RefOrOwned<'a, T> { } } - 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(), diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index a49465ec..c8338c94 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -1,5 +1,6 @@ use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::tabled_rc::*; +use crate::prolog_parser_rebis::{clause_name, temp_v}; use crate::clause_types::*; use crate::forms::*; @@ -14,7 +15,9 @@ use crate::machine::stack::*; use crate::machine::streams::*; use crate::rug::Integer; -use crate::downcast::Any; +use crate::downcast::{ + downcast, downcast_methods, downcast_methods_core, downcast_methods_std, impl_downcast, Any, +}; use crate::indexmap::IndexMap; @@ -32,33 +35,26 @@ pub struct Ball { } impl Ball { - pub(super) - fn new() -> Self { + pub(super) fn new() -> Self { Ball { boundary: 0, stub: Heap::new(), } } - pub(super) - fn reset(&mut self) { + pub(super) fn reset(&mut self) { self.boundary = 0; self.stub.clear(); } - pub(super) - fn copy_and_align(&self, h: usize) -> Heap { + pub(super) fn copy_and_align(&self, h: usize) -> Heap { let diff = self.boundary as i64 - h as i64; let mut stub = Heap::new(); for heap_value in self.stub.iter_from(0) { stub.push(match heap_value { - &HeapCellValue::Addr(addr) => { - HeapCellValue::Addr(addr - diff) - } - heap_value => { - heap_value.context_free_clone() - } + &HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff), + heap_value => heap_value.context_free_clone(), }); } @@ -123,11 +119,7 @@ pub(super) struct CopyBallTerm<'a> { } impl<'a> CopyBallTerm<'a> { - pub(super) fn new( - stack: &'a mut Stack, - heap: &'a mut Heap, - stub: &'a mut Heap, - ) -> Self { + pub(super) fn new(stack: &'a mut Stack, heap: &'a mut Heap, stub: &'a mut Heap) -> Self { let hb = heap.h(); CopyBallTerm { @@ -182,12 +174,8 @@ impl<'a> CopierTarget for CopyBallTerm<'a> { let index = h - self.heap_boundary; self.stub[index].as_addr(h) } - Addr::StackCell(fr, sc) => { - self.stack.index_and_frame(fr)[sc] - } - addr => { - addr - } + Addr::StackCell(fr, sc) => self.stack.index_and_frame(fr)[sc], + addr => addr, } } @@ -226,9 +214,7 @@ impl Index for MachineState { impl IndexMut for MachineState { fn index_mut(&mut self, reg: RegType) -> &mut Self::Output { match reg { - RegType::Temp(temp) => { - &mut self.registers[temp] - } + RegType::Temp(temp) => &mut self.registers[temp], RegType::Perm(perm) => { let e = self.e; @@ -255,15 +241,12 @@ pub(super) enum HeapPtr { impl HeapPtr { #[inline] - pub(super) - fn read(&self, heap: &Heap) -> Addr { + pub(super) fn read(&self, heap: &Heap) -> Addr { match self { - &HeapPtr::HeapCell(h) => { - Addr::HeapCell(h) - } + &HeapPtr::HeapCell(h) => Addr::HeapCell(h), &HeapPtr::PStrChar(h, n) => { if let &HeapCellValue::PartialString(ref pstr, has_tail) = &heap[h] { - if let Some(c) = pstr.range_from(n ..).next() { + if let Some(c) = pstr.range_from(n..).next() { Addr::Char(c) } else if has_tail { Addr::HeapCell(h + 1) @@ -274,9 +257,7 @@ impl HeapPtr { unreachable!() } } - &HeapPtr::PStrLocation(h, n) => { - Addr::PStrLocation(h, n) - } + &HeapPtr::PStrLocation(h, n) => Addr::PStrLocation(h, n), } } } @@ -313,16 +294,11 @@ pub struct MachineState { pub(super) last_call: bool, pub(crate) heap_locs: HeapVarDict, pub(crate) flags: MachineFlags, - pub(crate) at_end_of_expansion: bool + pub(crate) at_end_of_expansion: bool, } impl MachineState { - pub(crate) - fn read_term( - &mut self, - mut stream: Stream, - indices: &mut IndexStore, - ) -> CallResult { + pub(crate) fn read_term(&mut self, mut stream: Stream, indices: &mut IndexStore) -> CallResult { self.check_stream_properties( &mut stream, StreamType::Text, @@ -342,11 +318,7 @@ impl MachineState { let mut orig_stream = stream.clone(); loop { - match self.read( - stream.clone(), - self.atom_tbl.clone(), - &indices.op_dir, - ) { + match self.read(stream.clone(), self.atom_tbl.clone(), &indices.op_dir) { Ok(term_write_result) => { let term = self[temp_v!(2)]; self.unify(Addr::HeapCell(term_write_result.heap_loc), term); @@ -363,7 +335,8 @@ impl MachineState { let h = self.heap.h(); let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir); - self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec)); + self.heap + .push(HeapCellValue::NamedStr(2, clause_name!("="), spec)); self.heap.push(HeapCellValue::Atom(var_atom, None)); self.heap.push(HeapCellValue::Addr(binding)); @@ -406,8 +379,7 @@ impl MachineState { } let vars_addr = self[temp_v!(4)]; - let vars_offset = - Addr::HeapCell(self.heap.to_list(var_list.into_iter())); + let vars_offset = Addr::HeapCell(self.heap.to_list(var_list.into_iter())); self.unify(vars_offset, vars_addr); @@ -427,7 +399,7 @@ impl MachineState { self[temp_v!(2)], &mut orig_stream, clause_name!("read_term"), - 3 + 3, )?; if orig_stream.options.eof_action == EOFAction::Reset { @@ -448,12 +420,10 @@ impl MachineState { } } - pub(crate) - fn write_term<'a>( + pub(crate) fn write_term<'a>( &'a self, op_dir: &'a OpDir, - ) -> Result>, MachineStub> - { + ) -> Result>, MachineStub> { let ignore_ops = self.store(self.deref(self[temp_v!(3)])); let numbervars = self.store(self.deref(self[temp_v!(4)])); let quoted = self.store(self.deref(self[temp_v!(5)])); @@ -462,7 +432,7 @@ impl MachineState { let mut printer = HCPrinter::new(&self, op_dir, PrinterOutputter::new()); if let &Addr::Con(h) = &ignore_ops { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { printer.ignore_ops = name.as_str() == "true"; } else { unreachable!() @@ -470,7 +440,7 @@ impl MachineState { } if let &Addr::Con(h) = &numbervars { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { printer.numbervars = name.as_str() == "true"; } else { unreachable!() @@ -478,7 +448,7 @@ impl MachineState { } if let &Addr::Con(h) = "ed { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { printer.quoted = name.as_str() == "true"; } else { unreachable!() @@ -514,9 +484,7 @@ impl MachineState { for addr in addrs { match addr { Addr::Str(s) => match &self.heap[s] { - &HeapCellValue::NamedStr(2, ref name, _) - if name.as_str() == "=" => - { + &HeapCellValue::NamedStr(2, ref name, _) if name.as_str() == "=" => { let atom = self.heap[s + 1].as_addr(s + 1); let var = self.heap[s + 2].as_addr(s + 2); @@ -540,11 +508,9 @@ impl MachineState { var_names.insert(var, atom); } - _ => { - } + _ => {} }, - _ => { - } + _ => {} } } @@ -558,8 +524,7 @@ impl MachineState { Ok(Some(printer)) } - pub(super) - fn throw_undefined_error(&mut self, name: ClauseName, arity: usize) -> MachineStub { + 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); @@ -568,13 +533,11 @@ impl MachineState { } #[inline] - pub(crate) - fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> { + pub(crate) fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> { HeapPStrIter::new(self, focus) } - pub(super) - fn try_char_list(&self, addrs: Vec) -> Result { + pub(super) fn try_char_list(&self, addrs: Vec) -> Result { let mut chars = String::new(); let mut iter = addrs.iter(); @@ -594,55 +557,46 @@ impl MachineState { } } } - _ => { - } + _ => {} }; let h = self.heap.h(); - return Err( - MachineError::type_error(h, ValidType::Character, addr) - ); + return Err(MachineError::type_error(h, ValidType::Character, addr)); } Ok(chars) } - pub(super) - fn read_predicate_key(&self, name: Addr, arity: Addr) -> (ClauseName, usize) { + 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!() - }; + 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) { + pub(super) fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) { self.cp.assign_if_local(self.p.clone() + 1); self.num_of_args = arity; self.b0 = self.b; self.p = CodePtr::Local(p); } - pub(super) - fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) { + pub(super) fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) { self.num_of_args = arity; self.b0 = self.b; self.p = CodePtr::Local(p); } - pub(super) - fn module_lookup( + pub(super) fn module_lookup( &mut self, indices: &IndexStore, call_policy: &mut Box, @@ -687,10 +641,15 @@ pub(crate) type CallResult = Result<(), Vec>; pub(crate) trait CallPolicy: Any + fmt::Debug { fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { let b = machine_st.b; - let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells; + let n = machine_st + .stack + .index_or_frame(b) + .prelude + .univ_prelude + .num_cells; - for i in 1 .. n + 1 { - machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1]; + for i in 1..n + 1 { + machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i - 1]; } machine_st.num_of_args = n; @@ -706,17 +665,24 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); + machine_st + .heap + .truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_queue_b; + let attr_var_init_bindings_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_bindings_b; - machine_st.attr_var_init.backtrack( - attr_var_init_queue_b, - attr_var_init_bindings_b, - ); + 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 += 1; @@ -726,10 +692,15 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { let b = machine_st.b; - let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells; + let n = machine_st + .stack + .index_or_frame(b) + .prelude + .univ_prelude + .num_cells; - for i in 1 .. n + 1 { - machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1]; + for i in 1..n + 1 { + machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i - 1]; } machine_st.num_of_args = n; @@ -745,14 +716,24 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); + machine_st + .heap + .truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_queue_b; + let attr_var_init_bindings_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_bindings_b; - machine_st.attr_var_init.backtrack(attr_var_init_queue_b, attr_var_init_bindings_b); + 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 = CodePtr::Local(dir_entry!(machine_st.p.local().abs_loc() + offset)); @@ -762,10 +743,15 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { let b = machine_st.b; - let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells; + let n = machine_st + .stack + .index_or_frame(b) + .prelude + .univ_prelude + .num_cells; - for i in 1 .. n + 1 { - machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1]; + for i in 1..n + 1 { + machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i - 1]; } machine_st.num_of_args = n; @@ -779,17 +765,24 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); + machine_st + .heap + .truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_queue_b; + let attr_var_init_bindings_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_bindings_b; - machine_st.attr_var_init.backtrack( - attr_var_init_queue_b, - attr_var_init_bindings_b, - ); + machine_st + .attr_var_init + .backtrack(attr_var_init_queue_b, attr_var_init_bindings_b); machine_st.b = machine_st.stack.index_or_frame(b).prelude.b; machine_st.stack.truncate(b); @@ -802,10 +795,15 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult { let b = machine_st.b; - let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells; + let n = machine_st + .stack + .index_or_frame(b) + .prelude + .univ_prelude + .num_cells; - for i in 1 .. n + 1 { - machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1]; + for i in 1..n + 1 { + machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i - 1]; } machine_st.num_of_args = n; @@ -819,17 +817,24 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); + machine_st + .heap + .truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = - machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_queue_b; + let attr_var_init_bindings_b = machine_st + .stack + .index_or_frame(b) + .prelude + .attr_var_init_bindings_b; - machine_st.attr_var_init.backtrack( - attr_var_init_queue_b, - attr_var_init_bindings_b, - ); + machine_st + .attr_var_init + .backtrack(attr_var_init_queue_b, attr_var_init_bindings_b); machine_st.b = machine_st.stack.index_or_frame(b).prelude.b; machine_st.stack.truncate(b); @@ -928,13 +933,13 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Addr::Con(h) if machine_st.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &machine_st.heap[h] { match atom.as_str() { - ">" | "<" | "=" => { - } + ">" | "<" | "=" => {} _ => { let stub = MachineError::functor_stub(clause_name!("compare"), 3); - let err = MachineError::domain_error(DomainErrorType::Order, a1); + let err = + MachineError::domain_error(DomainErrorType::Order, a1); return Err(machine_st.error_form(err, stub)); } } @@ -948,8 +953,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let err = MachineError::type_error(h, ValidType::Atom, a1); return Err(machine_st.error_form(err, stub)); } - _ => { - } + _ => {} } let atom = match machine_st.compare_term_test(&a2, &a3) { @@ -998,9 +1002,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let addr = machine_st[temp_v!(1)]; let eof = clause_name!("end_of_file".to_string(), machine_st.atom_tbl); - let atom = machine_st.heap.to_unifiable( - HeapCellValue::Atom(eof, None) - ); + let atom = machine_st.heap.to_unifiable(HeapCellValue::Atom(eof, None)); machine_st.unify(addr, atom); } @@ -1056,7 +1058,9 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let mut list = machine_st.try_from_list(temp_v!(1), stub)?; list.sort_unstable_by(|a1, a2| { - machine_st.compare_term_test(a1, a2).unwrap_or(Ordering::Less) + machine_st + .compare_term_test(a1, a2) + .unwrap_or(Ordering::Less) }); machine_st.term_dedup(&mut list); @@ -1081,7 +1085,9 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { } key_pairs.sort_by(|a1, a2| { - machine_st.compare_term_test(&a1.0, &a2.0).unwrap_or(Ordering::Less) + machine_st + .compare_term_test(&a1.0, &a2.0) + .unwrap_or(Ordering::Less) }); let key_pairs = key_pairs.into_iter().map(|kp| kp.1); @@ -1155,11 +1161,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { 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 - ), + MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name), stub, )); } @@ -1200,7 +1202,8 @@ impl CallPolicy for CWILCallPolicy { arity: usize, 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) } @@ -1239,7 +1242,7 @@ impl CallPolicy for CWILCallPolicy { code_dir, op_dir, current_input_stream, - current_output_stream + current_output_stream, )?; self.increment(machine_st) @@ -1283,8 +1286,7 @@ pub(crate) struct CWILCallPolicy { } impl CWILCallPolicy { - pub(crate) - fn new_in_place(policy: &mut Box) { + pub(crate) fn new_in_place(policy: &mut Box) { let mut prev_policy: Box = Box::new(DefaultCallPolicy {}); mem::swap(&mut prev_policy, policy); @@ -1319,8 +1321,7 @@ impl CWILCallPolicy { Ok(()) } - pub(crate) - fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer { + pub(crate) fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer { limit += &self.count; match self.limits.last().cloned() { @@ -1331,8 +1332,7 @@ impl CWILCallPolicy { &self.count } - pub(crate) - fn remove_limit(&mut self, b: usize) -> &Integer { + pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer { if let Some((_, bp)) = self.limits.last().cloned() { if bp == b { self.limits.pop(); @@ -1342,13 +1342,11 @@ impl CWILCallPolicy { &self.count } - pub(crate) - fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.limits.is_empty() } - pub(crate) - fn into_inner(&mut self) -> Box { + pub(crate) fn into_inner(&mut self) -> Box { let mut new_inner: Box = Box::new(DefaultCallPolicy {}); mem::swap(&mut self.prev_policy, &mut new_inner); new_inner diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 1b62431e..d0348f9f 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1,12 +1,12 @@ use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::tabled_rc::*; +use crate::prolog_parser_rebis::{clause_name, perm_v, temp_v}; 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::code_repo::CodeRepo; use crate::machine::copier::*; @@ -17,6 +17,7 @@ use crate::machine::machine_state::*; use crate::machine::partial_string::*; use crate::machine::stack::*; use crate::machine::streams::*; +use crate::machine::INTERRUPT; use crate::ordered_float::*; use crate::rug::Integer; @@ -27,8 +28,7 @@ use std::convert::TryFrom; use std::rc::Rc; impl MachineState { - pub(crate) - fn new() -> Self { + pub(crate) fn new() -> Self { MachineState { atom_tbl: TabledData::new(Rc::new("".to_owned())), s: HeapPtr::default(), @@ -54,7 +54,7 @@ impl MachineState { last_call: false, heap_locs: HeapVarDict::new(), flags: MachineFlags::default(), - at_end_of_expansion: false + at_end_of_expansion: false, } } @@ -63,15 +63,10 @@ impl MachineState { self.flags } - pub(crate) - fn store(&self, addr: Addr) -> Addr { + pub(crate) fn store(&self, addr: Addr) -> Addr { match addr { - Addr::AttrVar(h) | Addr::HeapCell(h) => { - self.heap[h].as_addr(h) - } - Addr::StackCell(fr, sc) => { - self.stack.index_and_frame(fr)[sc] - } + Addr::AttrVar(h) | Addr::HeapCell(h) => self.heap[h].as_addr(h), + Addr::StackCell(fr, sc) => self.stack.index_and_frame(fr)[sc], Addr::PStrLocation(h, n) => { if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.heap[h] { if !pstr.at_end(n) { @@ -85,14 +80,11 @@ impl MachineState { unreachable!() } } - addr => { - addr - } + addr => addr, } } - pub(crate) - fn deref(&self, mut addr: Addr) -> Addr { + pub(crate) fn deref(&self, mut addr: Addr) -> Addr { loop { let value = self.store(addr); @@ -123,8 +115,7 @@ impl MachineState { } } - pub(super) - fn bind(&mut self, r1: Ref, a2: Addr) { + pub(super) fn bind(&mut self, r1: Ref, a2: Addr) { let t1 = self.store(r1.as_addr()); let t2 = self.store(a2); @@ -155,8 +146,7 @@ impl MachineState { Some(Ref::AttrVar(h)) => { self.bind_attr_var(h, t1); } - None => { - } + None => {} } } } @@ -185,8 +175,7 @@ impl MachineState { self.bind(r, addr); } - pub(super) - fn unify_with_occurs_check(&mut self, a1: Addr, a2: Addr) { + pub(super) fn unify_with_occurs_check(&mut self, a1: Addr, a2: Addr) { let mut pdl = vec![a1, a2]; let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new(); @@ -231,10 +220,10 @@ impl MachineState { self.fail = true; } - (Addr::PStrLocation(h, n), Addr::Lis(l)) | - (Addr::Lis(l), Addr::PStrLocation(h, n)) => { + (Addr::PStrLocation(h, n), Addr::Lis(l)) + | (Addr::Lis(l), Addr::PStrLocation(h, n)) => { if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { - if let Some(c) = pstr.range_from(n ..).next() { + if let Some(c) = pstr.range_from(n..).next() { pdl.push(Addr::PStrLocation(h, n + c.len_utf8())); pdl.push(Addr::HeapCell(l + 1)); @@ -248,20 +237,22 @@ impl MachineState { } } (Addr::PStrLocation(h1, n1), Addr::PStrLocation(h2, n2)) => { - if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] { - if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = &self.heap[h2] { + if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] + { + if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = + &self.heap[h2] + { let pstr1_s = pstr1.as_str_from(n1); let pstr2_s = pstr2.as_str_from(n2); - let m_len = - if pstr1_s.starts_with(pstr2_s) { - pstr2_s.len() - } else if pstr2_s.starts_with(pstr1_s) { - pstr1_s.len() - } else { - self.fail = true; - return; - }; + let m_len = if pstr1_s.starts_with(pstr2_s) { + pstr2_s.len() + } else if pstr2_s.starts_with(pstr1_s) { + pstr1_s.len() + } else { + self.fail = true; + return; + }; if pstr1.at_end(n1 + m_len) { if has_tail_1 { @@ -325,34 +316,25 @@ impl MachineState { self.fail = true; } - (Addr::Con(c1), Addr::Con(c2)) => { - match (&self.heap[c1], &self.heap[c2]) { - ( - &HeapCellValue::Atom(ref n1, _), - &HeapCellValue::Atom(ref n2, _), - ) if n1.as_str() == n2.as_str() => { - } - ( - &HeapCellValue::DBRef(ref db_ref_1), - &HeapCellValue::DBRef(ref db_ref_2), - ) if db_ref_1 == db_ref_2 => { - } - ( - v1, - v2, - ) => { - if let Ok(n1) = Number::try_from(v1) { - if let Ok(n2) = Number::try_from(v2) { - if n1 == n2 { - continue; - } + (Addr::Con(c1), Addr::Con(c2)) => match (&self.heap[c1], &self.heap[c2]) { + (&HeapCellValue::Atom(ref n1, _), &HeapCellValue::Atom(ref n2, _)) + if n1.as_str() == n2.as_str() => {} + ( + &HeapCellValue::DBRef(ref db_ref_1), + &HeapCellValue::DBRef(ref db_ref_2), + ) if db_ref_1 == db_ref_2 => {} + (v1, v2) => { + if let Ok(n1) = Number::try_from(v1) { + if let Ok(n2) = Number::try_from(v2) { + if n1 == n2 { + continue; } } - - self.fail = true; } + + self.fail = true; } - } + }, (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => { match &self.heap[h] { &HeapCellValue::Atom(ref name, _) if name.is_char() => { @@ -401,8 +383,7 @@ impl MachineState { } } - pub(super) - fn unify(&mut self, a1: Addr, a2: Addr) { + pub(super) fn unify(&mut self, a1: Addr, a2: Addr) { let mut pdl = vec![a1, a2]; let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new(); @@ -448,37 +429,39 @@ impl MachineState { self.fail = true; } - (Addr::PStrLocation(h, n), Addr::Lis(l)) | - (Addr::Lis(l), Addr::PStrLocation(h, n)) => { - if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { - if let Some(c) = pstr.range_from(n ..).next() { - pdl.push(Addr::PStrLocation(h, n + c.len_utf8())); - pdl.push(Addr::HeapCell(l + 1)); + (Addr::PStrLocation(h, n), Addr::Lis(l)) + | (Addr::Lis(l), Addr::PStrLocation(h, n)) => { + if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { + if let Some(c) = pstr.range_from(n..).next() { + pdl.push(Addr::PStrLocation(h, n + c.len_utf8())); + pdl.push(Addr::HeapCell(l + 1)); - pdl.push(Addr::Char(c)); - pdl.push(Addr::HeapCell(l)); - } else { - unreachable!() - } - } else { - unreachable!() - } + pdl.push(Addr::Char(c)); + pdl.push(Addr::HeapCell(l)); + } else { + unreachable!() + } + } else { + unreachable!() + } } (Addr::PStrLocation(h1, n1), Addr::PStrLocation(h2, n2)) => { - if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] { - if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = &self.heap[h2] { + if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] + { + if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = + &self.heap[h2] + { let pstr1_s = pstr1.as_str_from(n1); let pstr2_s = pstr2.as_str_from(n2); - let m_len = - if pstr1_s.starts_with(pstr2_s) { - pstr2_s.len() - } else if pstr2_s.starts_with(pstr1_s) { - pstr1_s.len() - } else { - self.fail = true; - return; - }; + let m_len = if pstr1_s.starts_with(pstr2_s) { + pstr2_s.len() + } else if pstr2_s.starts_with(pstr1_s) { + pstr1_s.len() + } else { + self.fail = true; + return; + }; if pstr1.at_end(n1 + m_len) { if has_tail_1 { @@ -538,34 +521,25 @@ impl MachineState { self.fail = true; } - (Addr::Con(c1), Addr::Con(c2)) => { - match (&self.heap[c1], &self.heap[c2]) { - ( - &HeapCellValue::Atom(ref n1, _), - &HeapCellValue::Atom(ref n2, _), - ) if n1.as_str() == n2.as_str() => { - } -( - &HeapCellValue::DBRef(ref db_ref_1), - &HeapCellValue::DBRef(ref db_ref_2), - ) if db_ref_1 == db_ref_2 => { - } - ( - v1, - v2, - ) => { - if let Ok(n1) = Number::try_from(v1) { - if let Ok(n2) = Number::try_from(v2) { - if n1 == n2 { - continue; - } + (Addr::Con(c1), Addr::Con(c2)) => match (&self.heap[c1], &self.heap[c2]) { + (&HeapCellValue::Atom(ref n1, _), &HeapCellValue::Atom(ref n2, _)) + if n1.as_str() == n2.as_str() => {} + ( + &HeapCellValue::DBRef(ref db_ref_1), + &HeapCellValue::DBRef(ref db_ref_2), + ) if db_ref_1 == db_ref_2 => {} + (v1, v2) => { + if let Ok(n1) = Number::try_from(v1) { + if let Ok(n2) = Number::try_from(v2) { + if n1 == n2 { + continue; } } - - self.fail = true; } + + self.fail = true; } - } + }, (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => { match &self.heap[h] { &HeapCellValue::Atom(ref name, _) if name.is_char() => { @@ -614,8 +588,7 @@ impl MachineState { } } - pub(super) - fn trail(&mut self, r: TrailRef) { + pub(super) fn trail(&mut self, r: TrailRef) { match r { TrailRef::Ref(Ref::HeapCell(h)) => { if h < self.hb { @@ -655,25 +628,22 @@ impl MachineState { HeapPtr::HeapCell(ref mut h) => { *h += rhs; } - &mut HeapPtr::PStrChar(h, ref mut n) | - &mut HeapPtr::PStrLocation(h, ref mut n) => { + &mut HeapPtr::PStrChar(h, ref mut n) | &mut HeapPtr::PStrLocation(h, ref mut n) => { match &self.heap[h] { &HeapCellValue::PartialString(ref pstr, _) => { - for c in pstr.range_from(*n ..).take(rhs) { + for c in pstr.range_from(*n..).take(rhs) { *n += c.len_utf8(); } self.s = HeapPtr::PStrLocation(h, *n); } - _ => { - } + _ => {} } } } } - pub(super) - fn unwind_trail(&mut self, a1: usize, a2: usize) { + pub(super) fn unwind_trail(&mut self, a1: usize, a2: usize) { // the sequence is reversed to respect the chronology of trail // additions, now that deleted attributes can be undeleted by // backtracking. @@ -698,8 +668,7 @@ impl MachineState { } } - pub(super) - fn tidy_trail(&mut self) { + pub(super) fn tidy_trail(&mut self) { if self.b == 0 { return; } @@ -708,12 +677,12 @@ impl MachineState { let hb = self.hb; let mut offset = 0; - for i in self.stack.index_or_frame(b).prelude.tr .. self.tr { + for i in self.stack.index_or_frame(b).prelude.tr..self.tr { match self.trail[i] { TrailRef::Ref(Ref::AttrVar(tr_i)) - | TrailRef::Ref(Ref::HeapCell(tr_i)) - | TrailRef::AttrVarHeapLink(tr_i) - | TrailRef::AttrVarListLink(tr_i, _) => { + | TrailRef::Ref(Ref::HeapCell(tr_i)) + | TrailRef::AttrVarHeapLink(tr_i) + | TrailRef::AttrVarListLink(tr_i, _) => { if tr_i >= hb { offset += 1; } else { @@ -734,8 +703,7 @@ impl MachineState { self.trail.truncate(self.tr); } - pub(super) - fn match_partial_string(&mut self, addr: Addr, string: &String, has_tail: bool) { + pub(super) fn match_partial_string(&mut self, addr: Addr, string: &String, has_tail: bool) { let mut heap_pstr_iter = self.heap_pstr_iter(addr); match compare_pstr_to_string(&mut heap_pstr_iter, string) { @@ -770,81 +738,64 @@ impl MachineState { } } } - Some(prefix_len) => { - match heap_pstr_iter.focus() { - addr if addr.is_ref() => { - let h = self.heap.h(); + Some(prefix_len) => match heap_pstr_iter.focus() { + addr if addr.is_ref() => { + let h = self.heap.h(); - let pstr_addr = - if has_tail { - self.s = HeapPtr::HeapCell(h+1); - self.mode = MachineMode::Read; + let pstr_addr = if has_tail { + self.s = HeapPtr::HeapCell(h + 1); + self.mode = MachineMode::Read; - self.heap.allocate_pstr(&string[prefix_len ..]) - } else { - self.heap.put_complete_string(&string[prefix_len ..]) - }; + self.heap.allocate_pstr(&string[prefix_len..]) + } else { + self.heap.put_complete_string(&string[prefix_len..]) + }; - self.bind(addr.as_var().unwrap(), pstr_addr); - } - Addr::Lis(l) => { - let h = self.heap.h(); - - let pstr_addr = - if has_tail { - self.s = HeapPtr::HeapCell(h+1); - self.mode = MachineMode::Read; - - self.heap.allocate_pstr(&string[prefix_len ..]) - } else { - self.heap.put_complete_string(&string[prefix_len ..]) - }; - - self.unify(Addr::Lis(l), pstr_addr); - } - _ => { - self.fail = true; - } + self.bind(addr.as_var().unwrap(), pstr_addr); } - } + Addr::Lis(l) => { + let h = self.heap.h(); + + let pstr_addr = if has_tail { + self.s = HeapPtr::HeapCell(h + 1); + self.mode = MachineMode::Read; + + self.heap.allocate_pstr(&string[prefix_len..]) + } else { + self.heap.put_complete_string(&string[prefix_len..]) + }; + + self.unify(Addr::Lis(l), pstr_addr); + } + _ => { + self.fail = true; + } + }, None => { self.fail = true; } } } - pub(super) - fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) { + pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) { match self.store(self.deref(addr)) { Addr::Con(c1) => { match &self.heap[c1] { HeapCellValue::Atom(ref n1, _) => { self.fail = match c { - Constant::Atom(ref n2, _) => { - n1 != n2 - } + Constant::Atom(ref n2, _) => n1 != n2, Constant::Char(c) if n1.is_char() => { Some(*c) != n1.as_str().chars().next() } - _ => { - true - } + _ => true, }; } HeapCellValue::Integer(ref n1) => { self.fail = match c { - Constant::Fixnum(n2) => { - n1.to_isize() != Some(*n2) - } - Constant::Integer(ref n2) => { - n1 != n2 - } - Constant::Usize(n2) => { - n1.to_usize() != Some(*n2) - } - _ => { - true - } + Constant::Fixnum(n2) => n1.to_isize() != Some(*n2), + Constant::Integer(ref n2) => n1 != n2, + Constant::Usize(n2) => n1.to_usize() != Some(*n2), + _ => true, }; } HeapCellValue::Rational(ref r1) => { @@ -856,11 +807,7 @@ impl MachineState { } HeapCellValue::PartialString(..) => { if let Constant::String(ref s2) = c { - self.match_partial_string( - Addr::PStrLocation(c1, 0), - &s2, - false, - ); + self.match_partial_string(Addr::PStrLocation(c1, 0), &s2, false); } else { self.fail = true; } @@ -875,12 +822,8 @@ impl MachineState { Constant::Atom(ref n2, _) if n2.is_char() => { Some(ch) != n2.as_str().chars().next() } - Constant::Char(c) => { - *c != ch - } - _ => { - true - } + Constant::Char(c) => *c != ch, + _ => true, }; } Addr::EmptyList => { @@ -895,11 +838,7 @@ impl MachineState { } Addr::PStrLocation(h, n) => { if let Constant::String(ref s2) = c { - self.match_partial_string( - Addr::PStrLocation(h, n), - &s2, - false, - ) + self.match_partial_string(Addr::PStrLocation(h, n), &s2, false) } else { self.fail = true; }; @@ -919,8 +858,7 @@ impl MachineState { }; } - pub(super) - fn execute_arith_instr(&mut self, instr: &ArithmeticInstruction) { + pub(super) fn execute_arith_instr(&mut self, instr: &ArithmeticInstruction) { let stub = MachineError::functor_stub(clause_name!("is"), 2); match instr { @@ -984,7 +922,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2); let (r1, stub) = try_or_fail!(self, self.get_rational(a1, stub)); - let (r2, _) = try_or_fail!(self, self.get_rational(a2, stub)); + let (r2, _) = try_or_fail!(self, self.get_rational(a2, stub)); self.interms[t - 1] = Number::Rational(Rc::new(try_or_fail!(self, self.rdiv(r1, r2)))); @@ -1190,8 +1128,7 @@ impl MachineState { }; } - pub(super) - fn execute_fact_instr(&mut self, instr: &FactInstruction) { + pub(super) fn execute_fact_instr(&mut self, instr: &FactInstruction) { match instr { &FactInstruction::GetConstant(_, ref c, reg) => { let addr = self[reg]; @@ -1205,9 +1142,9 @@ impl MachineState { self.s = HeapPtr::PStrChar(h, n); self.mode = MachineMode::Read; } - addr @ Addr::AttrVar(_) | - addr @ Addr::StackCell(..) | - addr @ Addr::HeapCell(_) => { + addr @ Addr::AttrVar(_) + | addr @ Addr::StackCell(..) + | addr @ Addr::HeapCell(_) => { let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1))); @@ -1248,7 +1185,8 @@ impl MachineState { let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1))); - self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); + self.heap + .push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); self.bind(addr.as_var().unwrap(), Addr::HeapCell(h)); @@ -1358,22 +1296,20 @@ impl MachineState { }; } - pub(super) - fn execute_indexing_instr( + pub(super) fn execute_indexing_instr( &mut self, indexing_lines: &Vec, call_policy: &mut Box, ) { 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 addr = match &indexing_lines[0] { + &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => { + self.store(self.deref(self[temp_v!(arg)])) + } + _ => { + unreachable!() + } + }; loop { match &indexing_lines[index] { @@ -1385,19 +1321,16 @@ impl MachineState { 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 - } + 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 { @@ -1415,18 +1348,13 @@ impl MachineState { }; } &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, + _ => IndexingCodePtr::Fail, + }, + None => IndexingCodePtr::Fail, + }; match offset { IndexingCodePtr::Fail => { @@ -1448,15 +1376,13 @@ impl MachineState { if let &HeapCellValue::NamedStr(arity, ref name, _) = &self.heap[s] { match hm.get(&(name.clone(), arity)) { Some(offset) => *offset, - _ => IndexingCodePtr::Fail + _ => IndexingCodePtr::Fail, } } else { IndexingCodePtr::Fail } } - _ => { - IndexingCodePtr::Fail - } + _ => IndexingCodePtr::Fail, }; match offset { @@ -1484,7 +1410,7 @@ impl MachineState { break; } } - }; + } } pub(super) fn execute_query_instr(&mut self, instr: &QueryInstruction) { @@ -1499,25 +1425,25 @@ impl MachineState { self[reg] = Addr::Lis(self.heap.h()); } &QueryInstruction::PutPartialString(_, ref string, reg, has_tail) => { - let pstr_addr = - if has_tail { - if !string.is_empty() { - let pstr_addr = self.heap.allocate_pstr(&string); - self.heap.pop(); // the tail will be added by the next instruction. - pstr_addr - } else { - Addr::EmptyList - } + let pstr_addr = if has_tail { + if !string.is_empty() { + let pstr_addr = self.heap.allocate_pstr(&string); + self.heap.pop(); // the tail will be added by the next instruction. + pstr_addr } else { - self.heap.put_complete_string(&string) - }; + Addr::EmptyList + } + } else { + self.heap.put_complete_string(&string) + }; self[reg] = pstr_addr; } &QueryInstruction::PutStructure(ref ct, arity, reg) => { let h = self.heap.h(); - self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); + self.heap + .push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); self[reg] = Addr::Str(h); } &QueryInstruction::PutUnsafeValue(n, arg) => { @@ -1586,7 +1512,7 @@ impl MachineState { &QueryInstruction::SetVoid(n) => { let h = self.heap.h(); - for i in h .. h + n { + for i in h..h + n { self.heap.push(HeapCellValue::Addr(Addr::HeapCell(i))); } } @@ -1606,8 +1532,7 @@ impl MachineState { ); } - pub(super) - fn handle_internal_call_n(&mut self, arity: usize) { + pub(super) fn handle_internal_call_n(&mut self, arity: usize) { let arity = arity + 1; let pred = self.registers[1]; @@ -1623,8 +1548,7 @@ impl MachineState { self.fail = true; } - pub(super) - fn setup_call_n(&mut self, arity: usize) -> Option { + pub(super) fn setup_call_n(&mut self, arity: usize) -> Option { let addr = self.store(self.deref(self.registers[arity])); let (name, narity) = match addr { @@ -1644,11 +1568,11 @@ impl MachineState { return None; } - for i in (1 .. arity).rev() { + for i in (1..arity).rev() { self.registers[i + narity] = self.registers[i]; } - for i in 1 .. narity + 1 { + for i in 1..narity + 1 { self.registers[i] = self.heap[a + i].as_addr(a + i); } @@ -1658,22 +1582,17 @@ impl MachineState { return None; } } - Addr::Con(h) => - match &self.heap[h] { - HeapCellValue::Atom(ref name, _) => { - (name.clone(), 0) - } - _ => { - self.fail = true; - return None; - } + Addr::Con(h) => match &self.heap[h] { + HeapCellValue::Atom(ref name, _) => (name.clone(), 0), + _ => { + self.fail = true; + return None; } + }, Addr::HeapCell(_) | Addr::StackCell(_, _) => { let stub = MachineError::functor_stub(clause_name!("call"), arity + 1); - let instantiation_error = self.error_form( - MachineError::instantiation_error(), - stub, - ); + let instantiation_error = + self.error_form(MachineError::instantiation_error(), stub); self.throw_exception(instantiation_error); return None; @@ -1693,27 +1612,19 @@ impl MachineState { 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 - } - } + let is_composite = |addr: &Addr| match *addr { + Addr::Str(_) | Addr::Lis(_) | Addr::PStrLocation(..) => true, + _ => false, }; loop { @@ -1737,56 +1648,49 @@ impl MachineState { } // arg(+N, +Term, ?Arg) - pub(super) - fn try_arg(&mut self) -> CallResult { + pub(super) fn try_arg(&mut self) -> CallResult { let stub = MachineError::functor_stub(clause_name!("arg"), 3); let n = self.store(self.deref(self[temp_v!(1)])); match n { - Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 a) - return Err(self.error_form(MachineError::instantiation_error(), stub)) + Addr::HeapCell(_) | Addr::StackCell(..) => { + // 8.5.2.3 a) + return Err(self.error_form(MachineError::instantiation_error(), stub)); } addr => { - let n = - match Number::try_from((addr, &self.heap)) { - Ok(Number::Fixnum(n)) => Integer::from(n), - Ok(Number::Integer(n)) => Integer::from(n.as_ref()), - _ => { - return Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - addr, - ), - stub, - )); - } - }; + let n = match Number::try_from((addr, &self.heap)) { + Ok(Number::Fixnum(n)) => Integer::from(n), + Ok(Number::Integer(n)) => Integer::from(n.as_ref()), + _ => { + return Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, addr), + stub, + )); + } + }; - if n < 0 { // 8.5.2.3 e) + if n < 0 { + // 8.5.2.3 e) let n = Number::from(n); - let dom_err = MachineError::domain_error( - DomainErrorType::NotLessThanZero, - n, - ); + let dom_err = MachineError::domain_error(DomainErrorType::NotLessThanZero, n); return Err(self.error_form(dom_err, stub)); } - let n = - match n.to_usize() { - Some(n) => n, - None => { - self.fail = true; - return Ok(()); - } - }; + let n = match n.to_usize() { + Some(n) => n, + None => { + self.fail = true; + return Ok(()); + } + }; let term = self.store(self.deref(self[temp_v!(2)])); match term { - Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => { // 8.5.2.3 b) - return Err(self.error_form(MachineError::instantiation_error(), stub)) + Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => { + // 8.5.2.3 b) + return Err(self.error_form(MachineError::instantiation_error(), stub)); } Addr::Str(o) => match self.heap.clone(o) { HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => { @@ -1814,7 +1718,7 @@ impl MachineState { let a3 = self[temp_v!(3)]; let h_a = if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { - if let Some(c) = pstr.range_from(offset ..).next() { + if let Some(c) = pstr.range_from(offset..).next() { if n == 1 { Addr::Char(c) } else { @@ -1832,15 +1736,12 @@ impl MachineState { self.fail = true; } } - _ => { // 8.5.2.3 d) + _ => { + // 8.5.2.3 d) return Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Compound, - term, - ), + MachineError::type_error(self.heap.h(), ValidType::Compound, term), stub, - )) + )); } } } @@ -1865,8 +1766,7 @@ impl MachineState { self.p += 1; } - pub(super) - fn compare_term(&mut self, qt: CompareTermQT) { + pub(super) fn compare_term(&mut self, qt: CompareTermQT) { let a1 = self[temp_v!(1)]; let a2 = self[temp_v!(2)]; @@ -1890,8 +1790,7 @@ impl MachineState { } // returns true on failure. - pub(super) - fn eq_test(&self, a1: Addr, a2: Addr) -> bool { + pub(super) fn eq_test(&self, a1: Addr, a2: Addr) -> bool { let mut iter = self.zipped_acyclic_pre_order_iter(a1, a2); while let Some((v1, v2)) = iter.next() { @@ -1909,8 +1808,7 @@ impl MachineState { unreachable!() } } - (Addr::PStrLocation(..), Addr::Lis(_)) | - (Addr::Lis(_), Addr::PStrLocation(..)) => { + (Addr::PStrLocation(..), Addr::Lis(_)) | (Addr::Lis(_), Addr::PStrLocation(..)) => { continue; } (pstr1 @ Addr::PStrLocation(..), pstr2 @ Addr::PStrLocation(..)) => { @@ -1939,40 +1837,32 @@ impl MachineState { (Addr::Lis(_), Addr::Lis(_)) => { continue; } - (Addr::Con(h1), Addr::Con(h2)) => { - match (&self.heap[h1], &self.heap[h2]) { - ( - &HeapCellValue::Atom(ref n1, ref spec_1), - &HeapCellValue::Atom(ref n2, ref spec_2), - ) => { - if n1 != n2 || spec_1 != spec_2 { - return true; - } - } - ( - &HeapCellValue::DBRef(ref db_ref_1), - &HeapCellValue::DBRef(ref db_ref_2), - ) => { - if db_ref_1 != db_ref_2 { - return true; - } - } - ( - v1, - v2, - ) => { - if let Ok(n1) = Number::try_from(v1) { - if let Ok(n2) = Number::try_from(v2) { - if n1 == n2 { - continue; - } - } - } - + (Addr::Con(h1), Addr::Con(h2)) => match (&self.heap[h1], &self.heap[h2]) { + ( + &HeapCellValue::Atom(ref n1, ref spec_1), + &HeapCellValue::Atom(ref n2, ref spec_2), + ) => { + if n1 != n2 || spec_1 != spec_2 { return true; } } - } + (&HeapCellValue::DBRef(ref db_ref_1), &HeapCellValue::DBRef(ref db_ref_2)) => { + if db_ref_1 != db_ref_2 { + return true; + } + } + (v1, v2) => { + if let Ok(n1) = Number::try_from(v1) { + if let Ok(n2) = Number::try_from(v2) { + if n1 == n2 { + continue; + } + } + } + + return true; + } + }, (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => { match &self.heap[h] { &HeapCellValue::Atom(ref name, _) if name.is_char() => { @@ -2007,8 +1897,7 @@ impl MachineState { iter.first_to_expire != Ordering::Equal } - pub(super) - fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Option { + pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Option { let mut iter = self.zipped_acyclic_pre_order_iter(*a1, *a2); while let Some((v1, v2)) = iter.next() { @@ -2039,294 +1928,224 @@ impl MachineState { unreachable!() } } - Some(TermOrderCategory::Integer) => { - match (v1, v2) { - ( - Addr::Con(h1), - Addr::Con(h2), - ) => { - if let Ok(n1) = Number::try_from(&self.heap[h1]) { - if let Ok(n2) = Number::try_from(&self.heap[h2]) { - if n1 != n2 { - return Some(n1.cmp(&n2)); - } - } else { - unreachable!() - } - } else { - unreachable!() - } - } - ( - Addr::Con(h1), - v2, - ) => { - if let Ok(n1) = Number::try_from(&self.heap[h1]) { - if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) { - if n1 != n2 { - return Some(n1.cmp(&n2)); - } - } else { - unreachable!() - } - } else { - unreachable!() - } - } - ( - v1, - Addr::Con(h2), - ) => { - if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) { - if let Ok(n2) = Number::try_from(&self.heap[h2]) { - if n1 != n2 { - return Some(n1.cmp(&n2)); - } - } else { - unreachable!() - } - } else { - unreachable!() - } - } - (v1, v2) => { - if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) { - if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) { - if n1 != n2 { - return Some(n1.cmp(&n2)); - } - } else { - unreachable!() + Some(TermOrderCategory::Integer) => match (v1, v2) { + (Addr::Con(h1), Addr::Con(h2)) => { + if let Ok(n1) = Number::try_from(&self.heap[h1]) { + if let Ok(n2) = Number::try_from(&self.heap[h2]) { + if n1 != n2 { + return Some(n1.cmp(&n2)); } } else { unreachable!() } + } else { + unreachable!() } } - } - Some(TermOrderCategory::Atom) => { - match (v1, v2) { - ( - Addr::Con(h1), - Addr::Con(h2), - ) => { - if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] { - if let HeapCellValue::Atom(ref n2, _) = &self.heap[h2] { - if n1 != n2 { - return Some(n1.cmp(&n2)); - } - } else { - unreachable!() + (Addr::Con(h1), v2) => { + if let Ok(n1) = Number::try_from(&self.heap[h1]) { + if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) { + if n1 != n2 { + return Some(n1.cmp(&n2)); } } else { unreachable!() } - } - ( - Addr::Con(h1), - Addr::Char(c), - ) => { - if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] { - if n1.is_char() { - if n1.as_str().chars().next() != Some(c) { - return Some(n1.as_str().chars().next().cmp(&Some(c))); - } - } else { - return Some(Ordering::Greater); - } - } else { - unreachable!() - } - } - ( - Addr::Char(c), - Addr::Con(h1), - ) => { - if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] { - if n1.is_char() { - if n1.as_str().chars().next() != Some(c) { - return Some(Some(c).cmp(&n1.as_str().chars().next())); - } - } else { - return Some(Ordering::Less); - } - } else { - unreachable!() - } - } - ( - Addr::EmptyList, - Addr::Con(h), - ) => { - if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] { - if "[]" != n1.as_str() { - return Some("[]".cmp(n1.as_str())); - } - } else { - unreachable!() - } - } - ( - Addr::Con(h), - Addr::EmptyList, - ) => { - if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] { - if "[]" != n1.as_str() { - return Some(n1.as_str().cmp("[]")); - } - } else { - unreachable!() - } - } - ( - Addr::Char(c1), - Addr::Char(c2), - ) => { - if c1 != c2 { - return Some(c1.cmp(&c2)); - } - } - ( - Addr::Char(c), - Addr::EmptyList, - ) => { - return if c == '[' { - Some(Ordering::Less) - } else { - Some(c.cmp(&'[')) - }; - } - ( - Addr::EmptyList, - Addr::Char(c), - ) => { - return if c == '[' { - Some(Ordering::Greater) - } else { - Some('['.cmp(&c)) - }; - } - ( - Addr::EmptyList, - Addr::EmptyList, - ) => { - } - _ => { - return None; + } else { + unreachable!() } } - } - Some(TermOrderCategory::Compound) => { - match (v1, v2) { - ( - Addr::Lis(_), - Addr::Lis(_), - ) => { - } - ( - pstr1 @ Addr::PStrLocation(..), - pstr2 @ Addr::PStrLocation(..), - ) => { - let mut i1 = self.heap_pstr_iter(pstr1); - let mut i2 = self.heap_pstr_iter(pstr2); - - let ordering = compare_pstr_prefixes(&mut i1, &mut i2); - - if let Some(ordering) = ordering { - if ordering != Ordering::Equal { - return Some(ordering); - } - } else { - let (lstack, rstack) = iter.stack(); - - lstack.pop(); - lstack.pop(); - - rstack.pop(); - rstack.pop(); - - lstack.push(i1.focus()); - rstack.push(i2.focus()); - } - } - ( - Addr::Str(h1), - Addr::Str(h2), - ) => { - if let HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[h1] { - if let HeapCellValue::NamedStr(a2, ref n2, _) = &self.heap[h2] { - if a1 != a2 || n1.as_str() != n2.as_str() { - return Some(a1.cmp(&a2).then_with(|| n1.as_str().cmp(n2.as_str()))); - } - } else { - unreachable!() + (v1, Addr::Con(h2)) => { + if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) { + if let Ok(n2) = Number::try_from(&self.heap[h2]) { + if n1 != n2 { + return Some(n1.cmp(&n2)); } } else { unreachable!() } - } - ( - Addr::Lis(_), - Addr::PStrLocation(..), - ) | - ( - Addr::PStrLocation(..), - Addr::Lis(_), - ) => { - } - ( - Addr::Lis(_), - Addr::Str(s), - ) => { - if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { - if a1 != 2 || n1.as_str() != "." { - return Some(a1.cmp(&2).then_with(|| n1.as_str().cmp("."))); - } - } else { - unreachable!() - } - } - ( - Addr::Str(s), - Addr::Lis(_), - ) => { - if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { - if a1 != 2 || n1.as_str() != "." { - return Some(2.cmp(&a1).then_with(|| ".".cmp(n1.as_str()))); - } - } else { - unreachable!() - } - } - ( - Addr::PStrLocation(..), - Addr::Str(s), - ) => { - if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { - if a1 != 2 || n1.as_str() != "." { - return Some(a1.cmp(&2).then_with(|| n1.as_str().cmp("."))); - } - } else { - unreachable!() - } - } - ( - Addr::Str(s), - Addr::PStrLocation(..), - ) => { - if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { - if a1 != 2 || n1.as_str() != "." { - return Some(2.cmp(&a1).then_with(|| ".".cmp(n1.as_str()))); - } - } else { - unreachable!() - } - } - _ => { - return None; + } else { + unreachable!() } } - } + (v1, v2) => { + if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) { + if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) { + if n1 != n2 { + return Some(n1.cmp(&n2)); + } + } else { + unreachable!() + } + } else { + unreachable!() + } + } + }, + Some(TermOrderCategory::Atom) => match (v1, v2) { + (Addr::Con(h1), Addr::Con(h2)) => { + if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] { + if let HeapCellValue::Atom(ref n2, _) = &self.heap[h2] { + if n1 != n2 { + return Some(n1.cmp(&n2)); + } + } else { + unreachable!() + } + } else { + unreachable!() + } + } + (Addr::Con(h1), Addr::Char(c)) => { + if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] { + if n1.is_char() { + if n1.as_str().chars().next() != Some(c) { + return Some(n1.as_str().chars().next().cmp(&Some(c))); + } + } else { + return Some(Ordering::Greater); + } + } else { + unreachable!() + } + } + (Addr::Char(c), Addr::Con(h1)) => { + if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] { + if n1.is_char() { + if n1.as_str().chars().next() != Some(c) { + return Some(Some(c).cmp(&n1.as_str().chars().next())); + } + } else { + return Some(Ordering::Less); + } + } else { + unreachable!() + } + } + (Addr::EmptyList, Addr::Con(h)) => { + if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] { + if "[]" != n1.as_str() { + return Some("[]".cmp(n1.as_str())); + } + } else { + unreachable!() + } + } + (Addr::Con(h), Addr::EmptyList) => { + if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] { + if "[]" != n1.as_str() { + return Some(n1.as_str().cmp("[]")); + } + } else { + unreachable!() + } + } + (Addr::Char(c1), Addr::Char(c2)) => { + if c1 != c2 { + return Some(c1.cmp(&c2)); + } + } + (Addr::Char(c), Addr::EmptyList) => { + return if c == '[' { + Some(Ordering::Less) + } else { + Some(c.cmp(&'[')) + }; + } + (Addr::EmptyList, Addr::Char(c)) => { + return if c == '[' { + Some(Ordering::Greater) + } else { + Some('['.cmp(&c)) + }; + } + (Addr::EmptyList, Addr::EmptyList) => {} + _ => { + return None; + } + }, + Some(TermOrderCategory::Compound) => match (v1, v2) { + (Addr::Lis(_), Addr::Lis(_)) => {} + (pstr1 @ Addr::PStrLocation(..), pstr2 @ Addr::PStrLocation(..)) => { + let mut i1 = self.heap_pstr_iter(pstr1); + let mut i2 = self.heap_pstr_iter(pstr2); + + let ordering = compare_pstr_prefixes(&mut i1, &mut i2); + + if let Some(ordering) = ordering { + if ordering != Ordering::Equal { + return Some(ordering); + } + } else { + let (lstack, rstack) = iter.stack(); + + lstack.pop(); + lstack.pop(); + + rstack.pop(); + rstack.pop(); + + lstack.push(i1.focus()); + rstack.push(i2.focus()); + } + } + (Addr::Str(h1), Addr::Str(h2)) => { + if let HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[h1] { + if let HeapCellValue::NamedStr(a2, ref n2, _) = &self.heap[h2] { + if a1 != a2 || n1.as_str() != n2.as_str() { + return Some( + a1.cmp(&a2).then_with(|| n1.as_str().cmp(n2.as_str())), + ); + } + } else { + unreachable!() + } + } else { + unreachable!() + } + } + (Addr::Lis(_), Addr::PStrLocation(..)) + | (Addr::PStrLocation(..), Addr::Lis(_)) => {} + (Addr::Lis(_), Addr::Str(s)) => { + if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { + if a1 != 2 || n1.as_str() != "." { + return Some(a1.cmp(&2).then_with(|| n1.as_str().cmp("."))); + } + } else { + unreachable!() + } + } + (Addr::Str(s), Addr::Lis(_)) => { + if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { + if a1 != 2 || n1.as_str() != "." { + return Some(2.cmp(&a1).then_with(|| ".".cmp(n1.as_str()))); + } + } else { + unreachable!() + } + } + (Addr::PStrLocation(..), Addr::Str(s)) => { + if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { + if a1 != 2 || n1.as_str() != "." { + return Some(a1.cmp(&2).then_with(|| n1.as_str().cmp("."))); + } + } else { + unreachable!() + } + } + (Addr::Str(s), Addr::PStrLocation(..)) => { + if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] { + if a1 != 2 || n1.as_str() != "." { + return Some(2.cmp(&a1).then_with(|| ".".cmp(n1.as_str()))); + } + } else { + unreachable!() + } + } + _ => { + return None; + } + }, None => { return None; } @@ -2336,16 +2155,14 @@ impl MachineState { Some(iter.first_to_expire) } - pub(super) - fn reset_block(&mut self, addr: Addr) { + pub(super) fn reset_block(&mut self, addr: Addr) { match self.store(addr) { Addr::Usize(b) => self.block = b, _ => self.fail = true, }; } - pub(super) - fn execute_inlined(&mut self, inlined: &InlinedClauseType) { + pub(super) fn execute_inlined(&mut self, inlined: &InlinedClauseType) { match inlined { &InlinedClauseType::CompareNumber(cmp, ref at_1, ref at_2) => { let n1 = try_or_fail!(self, self.get_number(at_1)); @@ -2357,12 +2174,13 @@ impl MachineState { let d = self.store(self.deref(self[r1])); match d { - Addr::Con(h) => + Addr::Con(h) => { if let HeapCellValue::Atom(..) = &self.heap[h] { self.p += 1; } else { self.fail = true; - }, + } + } Addr::Char(_) => self.p += 1, Addr::EmptyList => self.p += 1, _ => self.fail = true, @@ -2372,12 +2190,12 @@ impl MachineState { let d = self.store(self.deref(self[r1])); match d { - Addr::Char(_) | - Addr::Con(_) | - Addr::EmptyList | - Addr::Fixnum(_) | - Addr::Float(_) | - Addr::Usize(_) => self.p += 1, + Addr::Char(_) + | Addr::Con(_) + | Addr::EmptyList + | Addr::Fixnum(_) + | Addr::Float(_) + | Addr::Usize(_) => self.p += 1, _ => self.fail = true, }; } @@ -2419,29 +2237,27 @@ impl MachineState { _ => self.fail = true, }; } - &InlinedClauseType::IsNumber(r1) => { - match self.store(self.deref(self[r1])) { - Addr::Float(_) => self.p += 1, - d => match Number::try_from((d, &self.heap)) { - Ok(Number::Fixnum(_)) => { + &InlinedClauseType::IsNumber(r1) => match self.store(self.deref(self[r1])) { + Addr::Float(_) => self.p += 1, + d => match Number::try_from((d, &self.heap)) { + Ok(Number::Fixnum(_)) => { + self.p += 1; + } + Ok(Number::Integer(_)) => { + self.p += 1; + } + Ok(Number::Rational(n)) => { + if n.denom() == &1 { self.p += 1; - } - Ok(Number::Integer(_)) => { - self.p += 1; - } - Ok(Number::Rational(n)) => { - if n.denom() == &1 { - self.p += 1; - } else { - self.fail = true; - } - } - _ => { + } else { self.fail = true; } } - } - } + _ => { + self.fail = true; + } + }, + }, &InlinedClauseType::IsRational(r1) => { let d = self.store(self.deref(self[r1])); @@ -2495,11 +2311,7 @@ impl MachineState { self.try_functor_unify_components(name, arity); } - fn try_functor_unify_components( - &mut self, - name: Addr, - arity: usize, - ) { + fn try_functor_unify_components(&mut self, name: Addr, arity: usize) { let a2 = self[temp_v!(2)]; let a3 = self[temp_v!(3)]; @@ -2529,20 +2341,20 @@ impl MachineState { let f_a = if name.as_str() == "." && arity == 2 { Addr::Lis(self.heap.h()) } else { - self.heap.to_unifiable(HeapCellValue::NamedStr(arity, name, spec)) + self.heap + .to_unifiable(HeapCellValue::NamedStr(arity, name, spec)) }; let h = self.heap.h(); - for i in 0 .. arity { + for i in 0..arity { self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + i))); } self.bind(r, f_a); } - pub(super) - fn try_functor(&mut self, op_dir: &OpDir) -> CallResult { + pub(super) 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)])); @@ -2550,18 +2362,17 @@ impl MachineState { Addr::Stream(_) => { self.fail = true; } - Addr::Char(_) | Addr::Con(_) | Addr::Fixnum(_) | - Addr::Float(_) | Addr::EmptyList | Addr::Usize(_) => { + Addr::Char(_) + | Addr::Con(_) + | Addr::Fixnum(_) + | Addr::Float(_) + | Addr::EmptyList + | Addr::Usize(_) => { self.try_functor_unify_components(a1, 0); } Addr::Str(o) => match self.heap.clone(o) { HeapCellValue::NamedStr(arity, name, spec) => { - let spec = fetch_op_spec_from_existing( - name.clone(), - arity, - spec, - &op_dir, - ); + let spec = fetch_op_spec_from_existing(name.clone(), arity, spec, &op_dir); self.try_functor_compound_case(name, arity, spec) } @@ -2570,17 +2381,12 @@ impl MachineState { } }, Addr::Lis(_) | Addr::PStrLocation(..) => { - let spec = fetch_op_spec_from_existing( - clause_name!("."), - 2, - None, - &op_dir, - ); + let spec = fetch_op_spec_from_existing(clause_name!("."), 2, None, &op_dir); self.try_functor_compound_case(clause_name!("."), 2, spec) } Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) => { - let name = self.store(self.deref(self[temp_v!(2)])); + let name = self.store(self.deref(self[temp_v!(2)])); let arity = self.store(self.deref(self[temp_v!(3)])); if name.is_ref() || arity.is_ref() { @@ -2588,35 +2394,22 @@ impl MachineState { return Err(self.error_form(MachineError::instantiation_error(), stub)); } - let arity = - match Number::try_from((arity, &self.heap)) { - Ok(Number::Fixnum(n)) => Some(n), - Ok(Number::Integer(n)) => n.to_isize(), - Ok(Number::Rational(n)) - if n.denom() == &1 => { - n.numer().to_isize() - }, - _ => - match arity { - arity => { - return Err( - self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - arity, - ), - stub, - ) - ); - } - } - }; + let arity = match Number::try_from((arity, &self.heap)) { + Ok(Number::Fixnum(n)) => Some(n), + Ok(Number::Integer(n)) => n.to_isize(), + Ok(Number::Rational(n)) if n.denom() == &1 => n.numer().to_isize(), + _ => match arity { + arity => { + return Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, arity), + stub, + )); + } + }, + }; let arity = match arity { - Some(arity) => { - arity - } + Some(arity) => arity, None => { self.fail = true; return Ok(()); @@ -2630,17 +2423,22 @@ impl MachineState { } else if arity < 0 { // 8.5.1.3 g) let arity = Number::Integer(Rc::new(Integer::from(arity))); - let dom_err = MachineError::domain_error( - DomainErrorType::NotLessThanZero, - arity, - ); + let dom_err = + MachineError::domain_error(DomainErrorType::NotLessThanZero, arity); return Err(self.error_form(dom_err, stub)); } match name { - Addr::Char(_) | Addr::Con(_) | Addr::Fixnum(_) | Addr::Float(_) | - Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) if arity == 0 => { + Addr::Char(_) + | Addr::Con(_) + | Addr::Fixnum(_) + | Addr::Float(_) + | Addr::EmptyList + | Addr::PStrLocation(..) + | Addr::Usize(_) + if arity == 0 => + { self.unify(a1, name); } Addr::Con(h) => { @@ -2655,13 +2453,9 @@ impl MachineState { } else { // 8.5.1.3 e) return Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Atom, - name, - ), + MachineError::type_error(self.heap.h(), ValidType::Atom, name), stub, - )) + )); } } Addr::Char(c) => { @@ -2689,8 +2483,7 @@ impl MachineState { Ok(()) } - pub(super) - fn term_dedup(&self, list: &mut Vec) { + pub(super) fn term_dedup(&self, list: &mut Vec) { let mut result = vec![]; for a2 in list.iter() { @@ -2706,20 +2499,14 @@ impl MachineState { *list = result; } - - pub(super) - fn integers_to_bytevec( - &self, - r: RegType, - caller: MachineStub, - ) -> Vec { - + pub(super) fn integers_to_bytevec(&self, r: RegType, caller: MachineStub) -> Vec { let mut bytes: Vec = Vec::new(); match self.try_from_list(r, caller) { - Err(_) => { unreachable!() } + Err(_) => { + unreachable!() + } Ok(addrs) => { - for addr in addrs { let addr = self.store(self.deref(addr)); @@ -2729,20 +2516,19 @@ impl MachineState { Ok(b) => { bytes.push(b); } - Err(_) => { } + Err(_) => {} } continue; } Ok(Number::Integer(n)) => { if let Some(b) = n.to_u8() { - bytes.push(b); + bytes.push(b); } continue; } - _ => { - } + _ => {} } } } @@ -2750,9 +2536,7 @@ impl MachineState { bytes } - - pub(super) - fn try_from_list( + pub(super) fn try_from_list( &self, r: RegType, caller: MachineStub, @@ -2760,24 +2544,16 @@ impl MachineState { let a1 = self.store(self.deref(self[r])); match a1 { - Addr::Lis(l) => { - self.try_from_inner_list(vec![], l, caller, a1) - } - Addr::PStrLocation(h, n) => { - self.try_from_partial_string(vec![], h, n, caller, a1) - } + Addr::Lis(l) => self.try_from_inner_list(vec![], l, caller, a1), + Addr::PStrLocation(h, n) => self.try_from_partial_string(vec![], h, n, caller, a1), Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => { Err(self.error_form(MachineError::instantiation_error(), caller)) } - Addr::EmptyList => { - Ok(vec![]) - } - _ => { - Err(self.error_form( - MachineError::type_error(self.heap.h(), ValidType::List, a1), - caller, - )) - } + Addr::EmptyList => Ok(vec![]), + _ => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::List, a1), + caller, + )), } } @@ -2793,31 +2569,27 @@ impl MachineState { loop { match &self.heap[l] { - HeapCellValue::Addr(ref addr) => - match self.store(self.deref(*addr)) { - Addr::Lis(hcp) => { - result.push(self.heap[hcp].as_addr(hcp)); - l = hcp + 1; - } - Addr::PStrLocation(h, n) => { - return self.try_from_partial_string(result, h, n, caller, a1); - } - Addr::EmptyList => { - break; - } - Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => { - return Err(self.error_form( - MachineError::instantiation_error(), - caller, - )) - } - _ => { - return Err(self.error_form( - MachineError::type_error(self.heap.h(), ValidType::List, a1), - caller, - )) - } - }, + HeapCellValue::Addr(ref addr) => match self.store(self.deref(*addr)) { + Addr::Lis(hcp) => { + result.push(self.heap[hcp].as_addr(hcp)); + l = hcp + 1; + } + Addr::PStrLocation(h, n) => { + return self.try_from_partial_string(result, h, n, caller, a1); + } + Addr::EmptyList => { + break; + } + Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => { + return Err(self.error_form(MachineError::instantiation_error(), caller)) + } + _ => { + return Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::List, a1), + caller, + )) + } + }, _ => { return Err(self.error_form( MachineError::type_error(self.heap.h(), ValidType::List, a1), @@ -2840,7 +2612,7 @@ impl MachineState { ) -> Result, MachineStub> { loop { if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.heap[h] { - chars.extend(pstr.range_from(n ..).map(Addr::Char)); + chars.extend(pstr.range_from(n..).map(Addr::Char)); if !has_tail { return Ok(chars); @@ -2882,39 +2654,27 @@ impl MachineState { Addr::HeapCell(_) | Addr::StackCell(..) => { Err(self.error_form(MachineError::instantiation_error(), stub)) } - Addr::Str(s) => { - match self.heap.clone(s) { - HeapCellValue::NamedStr(2, ref name, Some(_)) - if *name == clause_name!("-") => { - Ok(Addr::HeapCell(s + 1)) - } - _ => { - Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Pair, - self.heap[s].as_addr(s), - ), - stub, - )) - } + Addr::Str(s) => match self.heap.clone(s) { + HeapCellValue::NamedStr(2, ref name, Some(_)) if *name == clause_name!("-") => { + Ok(Addr::HeapCell(s + 1)) } - } - a => { - Err(self.error_form( + _ => Err(self.error_form( MachineError::type_error( self.heap.h(), ValidType::Pair, - a, + self.heap[s].as_addr(s), ), stub, - )) - } + )), + }, + a => Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Pair, a), + stub, + )), } } - pub(super) - fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) { + pub(super) fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) { let old_h = self.heap.h(); let a1 = self[temp_v!(1)]; @@ -2926,8 +2686,7 @@ impl MachineState { } // returns true on failure. - pub(super) - fn structural_eq_test(&self) -> bool { + pub(super) fn structural_eq_test(&self) -> bool { let a1 = self[temp_v!(1)]; let a2 = self[temp_v!(2)]; @@ -2947,21 +2706,13 @@ impl MachineState { | ( HeapCellValue::Addr(Addr::PStrLocation(..)), HeapCellValue::Addr(Addr::Lis(_)), - ) => { - } - ( - HeapCellValue::NamedStr(ar1, n1, _), - HeapCellValue::NamedStr(ar2, n2, _), - ) => { + ) => {} + (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) => { if ar1 != ar2 || n1 != n2 { return true; } } - ( - HeapCellValue::Addr(Addr::Lis(_)), - HeapCellValue::Addr(Addr::Lis(_)), - ) => { - } + (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => {} ( &HeapCellValue::Addr(v1 @ Addr::HeapCell(_)), &HeapCellValue::Addr(v2 @ Addr::AttrVar(_)), @@ -2997,19 +2748,18 @@ impl MachineState { | ( &HeapCellValue::Addr(v1 @ Addr::StackCell(..)), &HeapCellValue::Addr(v2 @ Addr::HeapCell(_)), - ) => - match (var_pairs.get(&v1), var_pairs.get(&v2)) { - (Some(ref v2_p), Some(ref v1_p)) if **v1_p == v1 && **v2_p == v2 => { - continue; - } - (Some(_), _) | (_, Some(_)) => { - return true; - } - (None, None) => { - var_pairs.insert(v1, v2); - var_pairs.insert(v2, v1); - } - }, + ) => match (var_pairs.get(&v1), var_pairs.get(&v2)) { + (Some(ref v2_p), Some(ref v1_p)) if **v1_p == v1 && **v2_p == v2 => { + continue; + } + (Some(_), _) | (_, Some(_)) => { + return true; + } + (None, None) => { + var_pairs.insert(v1, v2); + var_pairs.insert(v2, v1); + } + }, ( HeapCellValue::PartialString(ref pstr1, has_tail_1), HeapCellValue::PartialString(ref pstr2, has_tail_2), @@ -3018,8 +2768,8 @@ impl MachineState { return true; } - let pstr1_iter = pstr1.range_from(0 ..); - let pstr2_iter = pstr2.range_from(0 ..); + let pstr1_iter = pstr1.range_from(0..); + let pstr2_iter = pstr2.range_from(0..); for (c1, c2) in pstr1_iter.zip(pstr2_iter) { if c1 != c2 { @@ -3030,8 +2780,7 @@ impl MachineState { ( HeapCellValue::Addr(Addr::PStrLocation(..)), HeapCellValue::Addr(Addr::PStrLocation(..)), - ) => { - } + ) => {} ( HeapCellValue::Atom(ref n1, ref spec_1), HeapCellValue::Atom(ref n2, ref spec_2), @@ -3040,18 +2789,12 @@ impl MachineState { return true; } } - ( - HeapCellValue::DBRef(ref db_ref_1), - HeapCellValue::DBRef(ref db_ref_2), - ) => { + (HeapCellValue::DBRef(ref db_ref_1), HeapCellValue::DBRef(ref db_ref_2)) => { if db_ref_1 != db_ref_2 { return true; } } - ( - v1, - v2, - ) => { + (v1, v2) => { if let Ok(n1) = Number::try_from(v1) { if let Ok(n2) = Number::try_from(v2) { if n1 != n2 { @@ -3065,10 +2808,7 @@ impl MachineState { } match (v1, v2) { - ( - HeapCellValue::Addr(a1), - HeapCellValue::Addr(a2), - ) => { + (HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) => { if a1 != a2 { return true; } @@ -3085,8 +2825,7 @@ impl MachineState { } // returns true on failure. - pub(super) - fn ground_test(&self) -> bool { + pub(super) fn ground_test(&self) -> bool { let a = self.store(self.deref(self[temp_v!(1)])); for v in self.acyclic_pre_order_iter(a) { @@ -3101,33 +2840,30 @@ impl MachineState { false } - pub(super) - fn setup_built_in_call(&mut self, ct: BuiltInClauseType) { + pub(super) fn setup_built_in_call(&mut self, ct: BuiltInClauseType) { self.num_of_args = ct.arity(); self.b0 = self.b; self.p = CodePtr::BuiltInClause(ct, self.p.local()); } - pub(super) - fn allocate(&mut self, num_cells: usize) { + pub(super) fn allocate(&mut self, num_cells: usize) { let e = self.stack.allocate_and_frame(num_cells); let and_frame = self.stack.index_and_frame_mut(e); - and_frame.prelude.e = self.e; + and_frame.prelude.e = self.e; and_frame.prelude.cp = self.cp; self.e = e; self.p += 1; } - pub(super) - fn deallocate(&mut self) { + pub(super) fn deallocate(&mut self) { let e = self.e; let frame = self.stack.index_and_frame(e); self.cp = frame.prelude.cp; - self.e = frame.prelude.e; + self.e = frame.prelude.e; if e > self.b { self.stack.truncate(e); @@ -3157,17 +2893,22 @@ impl MachineState { lco: bool, use_default_cp: bool, ) { - let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed); + let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed); - match INTERRUPT.compare_exchange(interrupted, false, std::sync::atomic::Ordering::Relaxed, std::sync::atomic::Ordering::Relaxed) { + match INTERRUPT.compare_exchange( + interrupted, + false, + std::sync::atomic::Ordering::Relaxed, + std::sync::atomic::Ordering::Relaxed, + ) { Ok(interruption) => { if interruption { self.throw_interrupt_exception(); return; } - }, - Err(_) => unreachable!() - } + } + Err(_) => unreachable!(), + } let mut default_call_policy: Box = Box::new(DefaultCallPolicy {}); @@ -3232,8 +2973,7 @@ impl MachineState { self.last_call = false; } - pub(super) - fn execute_ctrl_instr( + pub(super) fn execute_ctrl_instr( &mut self, indices: &mut IndexStore, code_repo: &CodeRepo, @@ -3296,18 +3036,16 @@ impl MachineState { or_frame.prelude.b = self.b; or_frame.prelude.bp = self.p.local() + 1; or_frame.prelude.tr = self.tr; - or_frame.prelude.h = self.heap.h(); + or_frame.prelude.h = self.heap.h(); or_frame.prelude.b0 = self.b0; - or_frame.prelude.attr_var_init_queue_b = - self.attr_var_init.attr_var_queue.len(); - or_frame.prelude.attr_var_init_bindings_b = - self.attr_var_init.bindings.len(); + or_frame.prelude.attr_var_init_queue_b = self.attr_var_init.attr_var_queue.len(); + or_frame.prelude.attr_var_init_bindings_b = self.attr_var_init.bindings.len(); self.b = b; - for i in 1 .. n + 1 { - self.stack.index_or_frame_mut(b)[i-1] = self.registers[i]; + for i in 1..n + 1 { + self.stack.index_or_frame_mut(b)[i - 1] = self.registers[i]; } self.hb = self.heap.h(); @@ -3322,8 +3060,7 @@ impl MachineState { }; } - pub(super) - fn execute_choice_instr( + pub(super) fn execute_choice_instr( &mut self, instr: &ChoiceInstruction, call_policy: &mut Box, @@ -3340,17 +3077,15 @@ impl MachineState { or_frame.prelude.b = self.b; or_frame.prelude.bp = self.p.local() + offset; or_frame.prelude.tr = self.tr; - or_frame.prelude.h = self.heap.h(); + or_frame.prelude.h = self.heap.h(); or_frame.prelude.b0 = self.b0; - or_frame.prelude.attr_var_init_queue_b = - self.attr_var_init.attr_var_queue.len(); - or_frame.prelude.attr_var_init_bindings_b = - self.attr_var_init.attr_var_queue.len(); + or_frame.prelude.attr_var_init_queue_b = self.attr_var_init.attr_var_queue.len(); + or_frame.prelude.attr_var_init_bindings_b = self.attr_var_init.attr_var_queue.len(); self.b = b; - for i in 1 .. n + 1 { - self.stack.index_or_frame_mut(b)[i-1] = self.registers[i]; + for i in 1..n + 1 { + self.stack.index_or_frame_mut(b)[i - 1] = self.registers[i]; } self.hb = self.heap.h(); diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 6a73369e..eb9dd534 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -1,5 +1,8 @@ use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::tabled_rc::*; +use crate::prolog_parser_rebis::{clause_name, temp_v}; + +use crate::lazy_static::lazy_static; use crate::clause_types::*; use crate::forms::*; @@ -34,8 +37,8 @@ mod machine_state_impl; mod system_calls; //use crate::machine::attributed_variables::*; -use crate::machine::compile::*; use crate::machine::code_repo::*; +use crate::machine::compile::*; // use crate::machine::loader::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; @@ -45,6 +48,7 @@ use crate::machine::streams::*; use crate::indexmap::IndexMap; //use std::convert::TryFrom; +use prolog_parser_rebis::ast::ClauseName; use std::fs::File; use std::mem; use std::path::PathBuf; @@ -162,18 +166,13 @@ impl Machine { } 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!(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.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)); } @@ -206,11 +205,9 @@ impl Machine { bootstrapping_compile( Stream::from(include_str!("attributed_variables.pl")), self, - ListingSource::from_file_and_path( - clause_name!("attributed_variables"), - path_buf, - ), - ).unwrap(); + 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"); @@ -218,11 +215,9 @@ impl Machine { bootstrapping_compile( Stream::from(include_str!("project_attributes.pl")), self, - ListingSource::from_file_and_path( - clause_name!("project_attributes"), - path_buf, - ), - ).unwrap(); + 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)) { @@ -255,12 +250,13 @@ impl Machine { fn configure_modules(&mut self) { fn update_call_n_indices(loader: &Module, target_module: &mut Module) { - for arity in 1 .. 66 { + for arity in 1..66 { let key = (clause_name!("call"), arity); match loader.code_dir.get(&key) { Some(src_code_index) => { - let target_code_index = target_module.code_dir + let target_code_index = target_module + .code_dir .entry(key.clone()) .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined)); @@ -289,10 +285,11 @@ impl Machine { builtins.module_decl.exports.push(export.clone()); } - for arity in 10 .. 66 { - builtins.module_decl.exports.push( - ModuleExport::PredicateKey((clause_name!("call"), arity)), - ); + for arity in 10..66 { + builtins + .module_decl + .exports + .push(ModuleExport::PredicateKey((clause_name!("call"), arity))); } } @@ -306,8 +303,7 @@ impl Machine { } } - pub fn new(user_input: Stream, user_output: Stream) -> Self - { + pub fn new(user_input: Stream, user_output: Stream) -> Self { use crate::ref_thread_local::RefThreadLocal; let mut wam = Machine { @@ -333,16 +329,15 @@ impl Machine { clause_name!("ops_and_meta_predicates.pl"), lib_path.clone(), ), - ).unwrap(); + ) + .unwrap(); bootstrapping_compile( Stream::from(LIBRARIES.borrow()["builtins"]), &mut wam, - ListingSource::from_file_and_path( - clause_name!("builtins.pl"), - lib_path.clone(), - ), - ).unwrap(); + 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( @@ -361,11 +356,9 @@ impl Machine { bootstrapping_compile( Stream::from(include_str!("../loader.pl")), &mut wam, - ListingSource::from_file_and_path( - clause_name!("loader.pl"), - lib_path.clone(), - ), - ).unwrap(); + ListingSource::from_file_and_path(clause_name!("loader.pl"), lib_path.clone()), + ) + .unwrap(); wam.configure_modules(); @@ -391,25 +384,19 @@ impl Machine { pub fn configure_streams(&mut self) { self.user_input.options.alias = Some(clause_name!("user_input")); - self.indices.stream_aliases.insert( - clause_name!("user_input"), - self.user_input.clone(), - ); + self.indices + .stream_aliases + .insert(clause_name!("user_input"), self.user_input.clone()); - self.indices.streams.insert( - self.user_input.clone() - ); + self.indices.streams.insert(self.user_input.clone()); self.user_output.options.alias = Some(clause_name!("user_output")); - self.indices.stream_aliases.insert( - clause_name!("user_output"), - self.user_output.clone(), - ); + self.indices + .stream_aliases + .insert(clause_name!("user_output"), self.user_output.clone()); - self.indices.streams.insert( - self.user_output.clone() - ); + self.indices.streams.insert(self.user_output.clone()); } fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) { @@ -508,8 +495,7 @@ impl Machine { self.machine_st.p = CodePtr::Local(p); } - pub(super) - fn run_query(&mut self) { + pub(super) fn run_query(&mut self) { while !self.machine_st.p.is_halt() { self.machine_st.query_stepper( &mut self.indices, @@ -546,26 +532,22 @@ impl MachineState { user_output: &mut Stream, ) { match instr { - &Line::Arithmetic(ref arith_instr) => { - self.execute_arith_instr(arith_instr) - } + &Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr), &Line::Choice(ref choice_instr) => { self.execute_choice_instr(choice_instr, &mut policies.call_policy) } &Line::Cut(ref cut_instr) => { self.execute_cut_instr(cut_instr, &mut policies.cut_policy) } - &Line::Control(ref control_instr) => { - self.execute_ctrl_instr( - indices, - code_repo, - &mut policies.call_policy, - &mut policies.cut_policy, - user_input, - user_output, - control_instr, - ) - } + &Line::Control(ref control_instr) => self.execute_ctrl_instr( + indices, + code_repo, + &mut policies.call_policy, + &mut policies.cut_policy, + user_input, + user_output, + control_instr, + ), &Line::Fact(ref fact_instr) => { self.execute_fact_instr(&fact_instr); self.p += 1; @@ -617,15 +599,13 @@ impl MachineState { fn check_machine_index(&mut self, code_repo: &CodeRepo) -> bool { match self.p { - CodePtr::Local(LocalCodePtr::DirEntry(p)) | - CodePtr::Local(LocalCodePtr::IndexingBuf(p, ..)) - if p < code_repo.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; } - _ => { - } + _ => {} } true @@ -689,13 +669,7 @@ impl MachineState { user_output: &mut Stream, ) { loop { - self.execute_instr( - indices, - policies, - code_repo, - user_input, - user_output, - ); + self.execute_instr(indices, policies, code_repo, user_input, user_output); if self.fail { self.backtrack(); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index ab82b1f9..34d47ebe 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -1,11 +1,12 @@ use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::tabled_rc::*; +use crate::prolog_parser_rebis::{atom, clause_name, rc_atom}; use crate::forms::*; use crate::iterators::*; -use crate::machine::*; use crate::machine::load_state::*; use crate::machine::machine_errors::*; +use crate::machine::*; use crate::indexmap::IndexSet; @@ -85,27 +86,24 @@ fn setup_op_decl( to_op_decl(prec, spec.as_str(), name) } -fn setup_predicate_indicator(term: &mut Term) -> Result -{ +fn setup_predicate_indicator(term: &mut Term) -> Result { 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 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 - } + .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 + let name = name .to_constant() .and_then(|c| c.to_atom()) .ok_or(CompilationError::InvalidModuleExport)?; @@ -116,9 +114,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result { - Err(CompilationError::InvalidModuleExport) - } + _ => Err(CompilationError::InvalidModuleExport), } } @@ -155,10 +151,7 @@ fn setup_module_export( .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 - )?)) + Ok(ModuleExport::OpDecl(setup_op_decl(terms, atom_tbl)?)) } else { Err(CompilationError::InvalidModuleDecl) } @@ -168,8 +161,7 @@ fn setup_module_export( }) } -pub(super) -fn setup_module_export_list( +pub(super) fn setup_module_export_list( mut export_list: Term, atom_tbl: TabledData, ) -> Result, CompilationError> { @@ -218,8 +210,7 @@ fn setup_use_module_decl(mut terms: Vec>) -> Result - Ok(ModuleSource::File(name.clone())), + Term::Constant(_, Constant::Atom(ref name, _)) => Ok(ModuleSource::File(name.clone())), _ => Err(CompilationError::InvalidUseModuleDecl), } } @@ -271,12 +262,8 @@ fn setup_qualified_import( .map(|c| ModuleSource::Library(c)) .ok_or(CompilationError::InvalidUseModuleDecl) } - Term::Constant(_, Constant::Atom(ref name, _)) => { - Ok(ModuleSource::File(name.clone())) - } - _ => { - Err(CompilationError::InvalidUseModuleDecl) - } + Term::Constant(_, Constant::Atom(ref name, _)) => Ok(ModuleSource::File(name.clone())), + _ => Err(CompilationError::InvalidUseModuleDecl), }?; let mut exports = IndexSet::new(); @@ -334,8 +321,7 @@ fn setup_qualified_import( fn setup_meta_predicate<'a>( mut terms: Vec>, load_state: &LoadState<'a>, -) -> Result<(ClauseName, ClauseName, Vec), CompilationError> -{ +) -> Result<(ClauseName, ClauseName, Vec), CompilationError> { fn get_name_and_meta_specs( name: ClauseName, terms: &mut [Box], @@ -345,26 +331,23 @@ fn setup_meta_predicate<'a>( 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::Plus, - "-" => MetaSpec::Minus, - "?" => MetaSpec::Either, - _ => return Err(CompilationError::InvalidMetaPredicateDecl), - }; + let meta_spec = match meta_spec.as_str() { + "+" => 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); - } + 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); } @@ -375,42 +358,35 @@ fn setup_meta_predicate<'a>( } 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(); + 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)?; + 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) - } - } + Ok((module_name, name, meta_specs)) } - _ => { - Err(CompilationError::InvalidMetaPredicateDecl) - } - } + _ => 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.compilation_target.module_name(), name, meta_specs)) - } - _ => { - Err(CompilationError::InvalidMetaPredicateDecl) + Ok(( + load_state.compilation_target.module_name(), + name, + meta_specs, + )) } + _ => Err(CompilationError::InvalidMetaPredicateDecl), } } -fn merge_clauses(tls: &mut VecDeque) -> Result -{ +fn merge_clauses(tls: &mut VecDeque) -> Result { let mut clauses = vec![]; while let Some(tl) = tls.pop_front() { @@ -432,9 +408,7 @@ fn merge_clauses(tls: &mut VecDeque) -> Result { - clauses.extend(predicate.into_iter()) - } + TopLevel::Predicate(predicate) => clauses.extend(predicate.into_iter()), _ => { tls.push_front(tl); break; @@ -506,8 +480,8 @@ fn check_for_internal_if_then(terms: &mut Vec) { conq_terms.push_front(Term::Constant( Cell::default(), - Constant::Atom(clause_name!("blocked_!"), None)) - ); + Constant::Atom(clause_name!("blocked_!"), None), + )); while let Some(term) = pre_cut_terms.pop_back() { conq_terms.push_front(term); @@ -531,38 +505,29 @@ fn setup_declaration<'a>( 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) - } + 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), } } @@ -596,8 +561,7 @@ pub(crate) struct Preprocessor { } impl Preprocessor { - pub(super) - fn new(flags: MachineFlags) -> Self { + pub(super) fn new(flags: MachineFlags) -> Self { Preprocessor { flags, queue: VecDeque::new(), @@ -606,12 +570,8 @@ impl Preprocessor { fn setup_fact(&mut self, term: Term) -> Result { match term { - Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => { - Ok(term) - } - _ => { - Err(CompilationError::InadmissibleFact) - } + Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => Ok(term), + _ => Err(CompilationError::InadmissibleFact), } } @@ -712,109 +672,97 @@ impl Preprocessor { Ok(clause_to_query_term(load_state, name, vec![], fixity)) } } - Term::Constant(_, Constant::Char('!')) => { - Ok(QueryTerm::BlockedCut) - } + Term::Constant(_, Constant::Char('!')) => Ok(QueryTerm::BlockedCut), 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); + 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); + 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(); + 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); + 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) - ))); + 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 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 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); + 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); + 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)) + 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) } } - } - Term::Var(..) => { - Ok(QueryTerm::Clause( - Cell::default(), - ClauseType::CallN, - vec![Box::new(term)], - false, - )) - } - _ => { - 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), } } @@ -835,9 +783,7 @@ impl Preprocessor { self.to_query_term(load_state, Term::Clause(r, name, subterms, fixity)) } } - _ => { - self.to_query_term(load_state, term) - } + _ => self.to_query_term(load_state, term), } } @@ -884,30 +830,23 @@ impl Preprocessor { mut terms: Vec>, cut_context: CutContext, ) -> Result { - let post_head_terms: Vec<_> = terms.drain(1 ..).collect(); + let post_head_terms: Vec<_> = terms.drain(1..).collect(); - let mut query_terms = - self.setup_query(load_state, post_head_terms, cut_context)?; + let mut query_terms = self.setup_query(load_state, post_head_terms, cut_context)?; - let clauses = query_terms.drain(1 ..).collect(); + 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) - } + 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), } } @@ -917,11 +856,14 @@ impl Preprocessor { terms: Vec>, cut_context: CutContext, ) -> Result { - Ok(TopLevel::Query(self.setup_query(load_state, terms, cut_context)?)) + Ok(TopLevel::Query(self.setup_query( + load_state, + terms, + cut_context, + )?)) } - pub(super) - fn try_term_to_tl<'a>( + pub(super) fn try_term_to_tl<'a>( &mut self, load_state: &mut LoadState<'a>, term: Term, @@ -944,9 +886,7 @@ impl Preprocessor { Ok(TopLevel::Fact(self.setup_fact(term)?)) } } - term => { - Ok(TopLevel::Fact(self.setup_fact(term)?)) - } + term => Ok(TopLevel::Fact(self.setup_fact(term)?)), } } @@ -965,21 +905,18 @@ impl Preprocessor { Ok(results) } - pub(super) - fn parse_queue<'a>( + pub(super) fn parse_queue<'a>( &mut self, load_state: &mut LoadState<'a>, ) -> Result, 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, - )? - )?; + let clauses = merge_clauses(&mut self.try_terms_to_tls( + load_state, + terms, + CutContext::HasCutVariable, + )?)?; queue.push_back(clauses); } diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 21040c60..531b47c4 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1,19 +1,20 @@ use crate::prolog_parser_rebis::ast::*; +use crate::prolog_parser_rebis::clause_name; -use crate::read::PrologStream; -use crate::read::readline::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; +use crate::read::readline::*; +use crate::read::PrologStream; -use std::cmp::Ordering; use std::cell::RefCell; +use std::cmp::Ordering; use std::error::Error; use std::fmt; use std::fs::File; +use std::hash::{Hash, Hasher}; use std::io; use std::io::{stdout, Cursor, ErrorKind, Read, Seek, SeekFrom, Write}; -use std::hash::{Hash, Hasher}; use std::mem; use std::net::{Shutdown, TcpStream}; use std::ops::DerefMut; @@ -29,8 +30,7 @@ pub enum StreamType { impl StreamType { #[inline] - pub(crate) - fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { StreamType::Binary => "binary_stream", StreamType::Text => "text_stream", @@ -38,8 +38,7 @@ impl StreamType { } #[inline] - pub(crate) - fn as_property_str(&self) -> &'static str { + pub(crate) fn as_property_str(&self) -> &'static str { match self { StreamType::Binary => "binary", StreamType::Text => "text", @@ -47,8 +46,7 @@ impl StreamType { } #[inline] - pub(crate) - fn other(self) -> StreamType { + pub(crate) fn other(self) -> StreamType { match self { StreamType::Binary => StreamType::Text, StreamType::Text => StreamType::Binary, @@ -67,13 +65,12 @@ pub enum EOFAction { pub enum AtEndOfStream { Not, At, - Past + Past, } impl AtEndOfStream { #[inline] - pub(crate) - fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { AtEndOfStream::Not => "not", AtEndOfStream::Past => "past", @@ -84,8 +81,7 @@ impl AtEndOfStream { impl EOFAction { #[inline] - pub(crate) - fn as_str(&self) -> &'static str { + pub(crate) fn as_str(&self) -> &'static str { match self { EOFAction::EOFCode => "eof_code", EOFAction::Error => "error", @@ -120,7 +116,7 @@ enum StreamInstance { StaticStr(Cursor<&'static str>), Stdout, TcpStream(ClauseName, TcpStream), - TlsStream(ClauseName, TlsStream) + TlsStream(ClauseName, TlsStream), } impl StreamInstance { @@ -141,31 +137,18 @@ impl StreamInstance { if index == buf.len() { Ok(buf.len()) } else { - stream.read(&mut buf[index ..]) - .map(|bytes_read| bytes_read + index) + stream + .read(&mut buf[index..]) + .map(|bytes_read| bytes_read + index) } } - StreamInstance::InputFile(_, ref mut file) => { - file.read(buf) - } - StreamInstance::TcpStream(_, ref mut tcp_stream) => { - tcp_stream.read(buf) - } - StreamInstance::TlsStream(_, ref mut tls_stream) => { - tls_stream.read(buf) - } - StreamInstance::ReadlineStream(ref mut rl_stream) => { - rl_stream.read(buf) - } - StreamInstance::StaticStr(ref mut src) => { - src.read(buf) - } - StreamInstance::Bytes(ref mut cursor) => { - cursor.read(buf) - } - StreamInstance::OutputFile(..) | - StreamInstance::Stdout | - StreamInstance::Null => { + StreamInstance::InputFile(_, ref mut file) => file.read(buf), + StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.read(buf), + StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.read(buf), + StreamInstance::ReadlineStream(ref mut rl_stream) => rl_stream.read(buf), + StreamInstance::StaticStr(ref mut src) => src.read(buf), + StreamInstance::Bytes(ref mut cursor) => cursor.read(buf), + StreamInstance::OutputFile(..) | StreamInstance::Stdout | StreamInstance::Null => { Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::ReadFromOutputStream, @@ -184,8 +167,7 @@ impl Drop for StreamInstance { StreamInstance::TlsStream(_, ref mut tls_stream) => { tls_stream.shutdown().unwrap(); } - _ => { - } + _ => {} } } } @@ -193,26 +175,24 @@ impl Drop for StreamInstance { impl fmt::Debug for StreamInstance { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { - &StreamInstance::Bytes(ref bytes) => - write!(fmt, "Bytes({:?})", bytes), - &StreamInstance::StaticStr(_) => - write!(fmt, "StaticStr(_)"), // Hacky solution. - &StreamInstance::InputFile(_, ref file) => - write!(fmt, "InputFile({:?})", file), - &StreamInstance::OutputFile(_, ref file, _) => - write!(fmt, "OutputFile({:?})", file), - &StreamInstance::Null => - write!(fmt, "Null"), - &StreamInstance::PausedPrologStream(ref put_back, ref stream) => - write!(fmt, "PausedPrologStream({:?}, {:?})", put_back, stream), - &StreamInstance::ReadlineStream(ref readline_stream) => - write!(fmt, "ReadlineStream({:?})", readline_stream), - &StreamInstance::Stdout => - write!(fmt, "Stdout"), - &StreamInstance::TcpStream(_, ref tcp_stream) => - write!(fmt, "TcpStream({:?})", tcp_stream), - &StreamInstance::TlsStream(_, ref tls_stream) => - write!(fmt, "TlsStream({:?})", tls_stream), + &StreamInstance::Bytes(ref bytes) => write!(fmt, "Bytes({:?})", bytes), + &StreamInstance::StaticStr(_) => write!(fmt, "StaticStr(_)"), // Hacky solution. + &StreamInstance::InputFile(_, ref file) => write!(fmt, "InputFile({:?})", file), + &StreamInstance::OutputFile(_, ref file, _) => write!(fmt, "OutputFile({:?})", file), + &StreamInstance::Null => write!(fmt, "Null"), + &StreamInstance::PausedPrologStream(ref put_back, ref stream) => { + write!(fmt, "PausedPrologStream({:?}, {:?})", put_back, stream) + } + &StreamInstance::ReadlineStream(ref readline_stream) => { + write!(fmt, "ReadlineStream({:?})", readline_stream) + } + &StreamInstance::Stdout => write!(fmt, "Stdout"), + &StreamInstance::TcpStream(_, ref tcp_stream) => { + write!(fmt, "TcpStream({:?})", tcp_stream) + } + &StreamInstance::TlsStream(_, ref tls_stream) => { + write!(fmt, "TlsStream({:?})", tls_stream) + } } } } @@ -223,9 +203,7 @@ struct WrappedStreamInstance(Rc>); impl WrappedStreamInstance { #[inline] fn new(stream_inst: StreamInstance) -> Self { - WrappedStreamInstance( - Rc::new(RefCell::new((false, stream_inst))) - ) + WrappedStreamInstance(Rc::new(RefCell::new((false, stream_inst)))) } } @@ -362,8 +340,7 @@ impl From<&'static str> for Stream { impl Stream { #[inline] - pub(crate) - fn as_ptr(&self) -> *const u8 { + pub(crate) fn as_ptr(&self) -> *const u8 { let rc = self.stream_inst.0.clone(); let ptr = Rc::into_raw(rc); @@ -376,21 +353,15 @@ impl Stream { } #[inline] - pub(crate) - fn position(&mut self) -> Option { + pub(crate) fn position(&mut self) -> Option { match self.stream_inst.0.borrow_mut().1 { - StreamInstance::InputFile(_, ref mut file) => { - file.seek(SeekFrom::Current(0)).ok() - } - _ => { - None - } + StreamInstance::InputFile(_, ref mut file) => file.seek(SeekFrom::Current(0)).ok(), + _ => None, } } #[inline] - pub(crate) - fn set_position(&mut self, position: u64) { + pub(crate) fn set_position(&mut self, position: u64) { match self.stream_inst.0.borrow_mut().deref_mut() { (past_end_of_stream, StreamInstance::InputFile(_, ref mut file)) => { file.seek(SeekFrom::Start(position)).unwrap(); @@ -399,32 +370,27 @@ impl Stream { *past_end_of_stream = position > metadata.len(); } } - _ => { - } + _ => {} } } #[inline] - pub(crate) - fn past_end_of_stream(&self) -> bool { + pub(crate) fn past_end_of_stream(&self) -> bool { self.stream_inst.0.borrow_mut().0 } #[inline] - pub(crate) - fn at_end_of_stream(&mut self) -> bool { + pub(crate) fn at_end_of_stream(&mut self) -> bool { self.position_relative_to_end() == AtEndOfStream::At } #[inline] - pub(crate) - fn set_past_end_of_stream(&mut self) { + pub(crate) fn set_past_end_of_stream(&mut self) { self.stream_inst.0.borrow_mut().0 = true; } #[inline] - pub(crate) - fn position_relative_to_end(&mut self) -> AtEndOfStream { + pub(crate) fn position_relative_to_end(&mut self) -> AtEndOfStream { if self.past_end_of_stream() { return AtEndOfStream::Past; } @@ -435,12 +401,8 @@ impl Stream { Ok(metadata) => { if let Ok(position) = file.seek(SeekFrom::Current(0)) { return match position.cmp(&metadata.len()) { - Ordering::Equal => { - AtEndOfStream::At - } - Ordering::Less => { - AtEndOfStream::Not - } + Ordering::Equal => AtEndOfStream::At, + Ordering::Less => AtEndOfStream::Not, Ordering::Greater => { *past_end_of_stream = true; //self.set_past_end_of_stream(); AtEndOfStream::Past @@ -457,56 +419,32 @@ impl Stream { } } } - _ => { - AtEndOfStream::Not - } + _ => AtEndOfStream::Not, } } #[inline] - pub(crate) - fn file_name(&self) -> Option { + pub(crate) fn file_name(&self) -> Option { match self.stream_inst.0.borrow().1 { - StreamInstance::InputFile(ref name, _) => { - Some(name.clone()) - } - StreamInstance::OutputFile(ref name, ..) => { - Some(name.clone()) - } - StreamInstance::TcpStream(ref name, _) => { - Some(name.clone()) - } - _ => { - None - } + StreamInstance::InputFile(ref name, _) => Some(name.clone()), + StreamInstance::OutputFile(ref name, ..) => Some(name.clone()), + StreamInstance::TcpStream(ref name, _) => Some(name.clone()), + _ => None, } } #[inline] - pub(crate) - fn mode(&self) -> &'static str { + pub(crate) fn mode(&self) -> &'static str { match self.stream_inst.0.borrow().1 { - StreamInstance::Bytes(_) | - StreamInstance::PausedPrologStream(..) | - StreamInstance::ReadlineStream(_) | - StreamInstance::StaticStr(_) | - StreamInstance::InputFile(..) => { - "read" - } - StreamInstance::TcpStream(..) | - StreamInstance::TlsStream(..) => { - "read_append" - } - StreamInstance::OutputFile(_, _, true) => { - "append" - } - StreamInstance::Stdout | - StreamInstance::OutputFile(_, _, false) => { - "write" - } - StreamInstance::Null => { - "" - } + StreamInstance::Bytes(_) + | StreamInstance::PausedPrologStream(..) + | StreamInstance::ReadlineStream(_) + | StreamInstance::StaticStr(_) + | StreamInstance::InputFile(..) => "read", + StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append", + StreamInstance::OutputFile(_, _, true) => "append", + StreamInstance::Stdout | StreamInstance::OutputFile(_, _, false) => "write", + StreamInstance::Null => "", } } @@ -514,19 +452,17 @@ impl Stream { fn from_inst(stream_inst: StreamInstance) -> Self { Stream { options: StreamOptions::default(), - stream_inst: WrappedStreamInstance::new(stream_inst) + stream_inst: WrappedStreamInstance::new(stream_inst), } } #[inline] - pub(crate) - fn stdout() -> Self { + pub(crate) fn stdout() -> Self { Stream::from_inst(StreamInstance::Stdout) } #[inline] - pub(crate) - fn from_tcp_stream(address: ClauseName, tcp_stream: TcpStream) -> Self { + pub(crate) fn from_tcp_stream(address: ClauseName, tcp_stream: TcpStream) -> Self { tcp_stream.set_read_timeout(None).unwrap(); tcp_stream.set_write_timeout(None).unwrap(); @@ -534,58 +470,43 @@ impl Stream { } #[inline] - pub(crate) - fn from_tls_stream(address: ClauseName, tls_stream: TlsStream) -> Self { + pub(crate) fn from_tls_stream(address: ClauseName, tls_stream: TlsStream) -> Self { Stream::from_inst(StreamInstance::TlsStream(address, tls_stream)) } #[inline] - pub(crate) - fn from_file_as_output(name: ClauseName, file: File, in_append_mode: bool) -> Self { + pub(crate) fn from_file_as_output(name: ClauseName, file: File, in_append_mode: bool) -> Self { Stream::from_inst(StreamInstance::OutputFile(name, file, in_append_mode)) } #[inline] - pub(crate) - fn from_file_as_input(name: ClauseName, file: File) -> Self { + pub(crate) fn from_file_as_input(name: ClauseName, file: File) -> Self { Stream::from_inst(StreamInstance::InputFile(name, file)) } #[inline] - pub(crate) - fn is_stdout(&self) -> bool { + pub(crate) fn is_stdout(&self) -> bool { match self.stream_inst.0.borrow().1 { - StreamInstance::Stdout => { - true - } - _ => { - false - } + StreamInstance::Stdout => true, + _ => false, } } #[inline] - pub(crate) - fn is_stdin(&self) -> bool { + pub(crate) fn is_stdin(&self) -> bool { match self.stream_inst.0.borrow().1 { - StreamInstance::ReadlineStream(_) => { - true - } - _ => { - false - } + StreamInstance::ReadlineStream(_) => true, + _ => false, } } #[inline] - pub(crate) - fn close(&mut self) { + pub(crate) fn close(&mut self) { self.stream_inst.0.borrow_mut().1 = StreamInstance::Null; } #[inline] - pub(crate) - fn is_null_stream(&self) -> bool { + pub(crate) fn is_null_stream(&self) -> bool { if let StreamInstance::Null = self.stream_inst.0.borrow().1 { true } else { @@ -594,60 +515,49 @@ impl Stream { } #[inline] - pub(crate) - fn is_input_stream(&self) -> bool { + pub(crate) fn is_input_stream(&self) -> bool { match self.stream_inst.0.borrow().1 { - StreamInstance::TcpStream(..) | - StreamInstance::TlsStream(..) | - StreamInstance::Bytes(_) | - StreamInstance::PausedPrologStream(..) | - StreamInstance::ReadlineStream(_) | - StreamInstance::StaticStr(_) | - StreamInstance::InputFile(..) => { - true - } - _ => { - false - } + StreamInstance::TcpStream(..) + | StreamInstance::TlsStream(..) + | StreamInstance::Bytes(_) + | StreamInstance::PausedPrologStream(..) + | StreamInstance::ReadlineStream(_) + | StreamInstance::StaticStr(_) + | StreamInstance::InputFile(..) => true, + _ => false, } } #[inline] - pub(crate) - fn is_output_stream(&self) -> bool { + pub(crate) fn is_output_stream(&self) -> bool { match self.stream_inst.0.borrow().1 { StreamInstance::Stdout - | StreamInstance::TcpStream(..) - | StreamInstance::TlsStream(..) - | StreamInstance::Bytes(_) - | StreamInstance::OutputFile(..) => { - true - } - _ => { - false - } + | StreamInstance::TcpStream(..) + | StreamInstance::TlsStream(..) + | StreamInstance::Bytes(_) + | StreamInstance::OutputFile(..) => true, + _ => false, } } fn unpause_stream(&mut self) { - let stream_inst = - match self.stream_inst.0.borrow_mut().1 { - StreamInstance::PausedPrologStream(ref put_back, ref mut stream_inst) - if put_back.is_empty() => { - mem::replace(&mut **stream_inst, StreamInstance::Null) - } - _ => { - return; - } - }; + let stream_inst = match self.stream_inst.0.borrow_mut().1 { + StreamInstance::PausedPrologStream(ref put_back, ref mut stream_inst) + if put_back.is_empty() => + { + mem::replace(&mut **stream_inst, StreamInstance::Null) + } + _ => { + return; + } + }; self.stream_inst.0.borrow_mut().1 = stream_inst; } // returns true on success. #[inline] - pub(super) - fn reset(&mut self) -> bool { + pub(super) fn reset(&mut self) -> bool { self.stream_inst.0.borrow_mut().0 = false; loop { @@ -676,8 +586,7 @@ impl Stream { } #[inline] - pub(crate) - fn peek_byte(&mut self) -> std::io::Result { + pub(crate) fn peek_byte(&mut self) -> std::io::Result { match self.stream_inst.0.borrow_mut().1 { StreamInstance::Bytes(ref mut cursor) => { let mut b = [0u8; 1]; @@ -688,12 +597,7 @@ impl Stream { cursor.set_position(pos); Ok(b[0]) } - _ => { - Err(std::io::Error::new( - ErrorKind::UnexpectedEof, - "end of file", - )) - } + _ => Err(std::io::Error::new(ErrorKind::UnexpectedEof, "end of file")), } } StreamInstance::InputFile(_, ref mut file) => { @@ -704,34 +608,27 @@ impl Stream { file.seek(SeekFrom::Current(-1))?; Ok(b[0]) } - _ => { - Err(std::io::Error::new( - ErrorKind::UnexpectedEof, - StreamError::PeekByteFailed, - )) - } + _ => Err(std::io::Error::new( + ErrorKind::UnexpectedEof, + StreamError::PeekByteFailed, + )), } } - StreamInstance::ReadlineStream(ref mut stream) => { - stream.peek_byte() - } + StreamInstance::ReadlineStream(ref mut stream) => stream.peek_byte(), StreamInstance::TcpStream(_, ref mut tcp_stream) => { let mut b = [0u8; 1]; tcp_stream.peek(&mut b)?; Ok(b[0]) } - _ => { - Err(std::io::Error::new( - ErrorKind::PermissionDenied, - StreamError::PeekByteFromNonPeekableStream, - )) - } + _ => Err(std::io::Error::new( + ErrorKind::PermissionDenied, + StreamError::PeekByteFromNonPeekableStream, + )), } } #[inline] - pub(crate) - fn peek_char(&mut self) -> std::io::Result { + pub(crate) fn peek_char(&mut self) -> std::io::Result { use crate::unicode_reader::CodePoints; match self.stream_inst.0.borrow_mut().1 { @@ -744,18 +641,16 @@ impl Stream { } else { return Err(std::io::Error::new( ErrorKind::UnexpectedEof, - StreamError::PeekCharFailed + StreamError::PeekCharFailed, )); } }; - file.seek(SeekFrom::Current(- (c.len_utf8() as i64)))?; + file.seek(SeekFrom::Current(-(c.len_utf8() as i64)))?; Ok(c) } - StreamInstance::ReadlineStream(ref mut stream) => { - stream.peek_char() - } + StreamInstance::ReadlineStream(ref mut stream) => stream.peek_char(), StreamInstance::TcpStream(_, ref tcp_stream) => { let c = { let mut buf = [0u8; 8]; @@ -768,45 +663,38 @@ impl Stream { } else { return Err(std::io::Error::new( ErrorKind::UnexpectedEof, - StreamError::PeekCharFailed + StreamError::PeekCharFailed, )); } }; Ok(c) } - _ => { - Err(std::io::Error::new( - ErrorKind::PermissionDenied, - StreamError::PeekCharFromNonPeekableStream, - )) - } + _ => Err(std::io::Error::new( + ErrorKind::PermissionDenied, + StreamError::PeekCharFromNonPeekableStream, + )), } } #[inline] - pub(crate) - fn pause_stream(&mut self, buf: Vec>) -> io::Result<()> { + pub(crate) fn pause_stream(&mut self, buf: Vec>) -> io::Result<()> { match self.stream_inst.0.borrow_mut().1 { StreamInstance::PausedPrologStream(ref mut inner_buf, _) => { inner_buf.extend(parser_top_to_bytes(buf)?.into_iter()); return Ok(()); } - _ => { - } + _ => {} } if !buf.is_empty() { - let stream_inst = mem::replace( - &mut self.stream_inst.0.borrow_mut().1, - StreamInstance::Null, - ); + let stream_inst = + mem::replace(&mut self.stream_inst.0.borrow_mut().1, StreamInstance::Null); - self.stream_inst.0.borrow_mut().1 = - StreamInstance::PausedPrologStream( - parser_top_to_bytes(buf)?, - Box::new(stream_inst), - ); + self.stream_inst.0.borrow_mut().1 = StreamInstance::PausedPrologStream( + parser_top_to_bytes(buf)?, + Box::new(stream_inst), + ); } Ok(()) @@ -815,8 +703,7 @@ impl Stream { impl MachineState { #[inline] - pub(crate) - fn eof_action( + pub(crate) fn eof_action( &mut self, result: Addr, stream: &mut Stream, @@ -829,14 +716,12 @@ impl MachineState { return Err(self.open_past_eos_error(stream.clone(), caller, arity)); } EOFAction::EOFCode => { - let end_of_stream = - if stream.options.stream_type == StreamType::Binary { - Addr::Fixnum(-1) - } else { - self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("end_of_file"), None) - ) - }; + let end_of_stream = if stream.options.stream_type == StreamType::Binary { + Addr::Fixnum(-1) + } else { + self.heap + .to_unifiable(HeapCellValue::Atom(clause_name!("end_of_file"), None)) + }; stream.set_past_end_of_stream(); Ok(self.unify(result, end_of_stream)) @@ -851,114 +736,106 @@ impl MachineState { } } - pub(crate) - fn to_stream_options( + pub(crate) fn to_stream_options( &self, alias: Addr, eof_action: Addr, reposition: Addr, stream_type: Addr, ) -> StreamOptions { - let alias = - match self.store(self.deref(alias)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { - Some(name.clone()) - } else { - unreachable!() - } - } - _ => { - None - } - }; - - let eof_action = - match self.store(self.deref(eof_action)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { - match name.as_str() { - "eof_code" => EOFAction::EOFCode, - "error" => EOFAction::Error, - "reset" => EOFAction::Reset, - _ => unreachable!(), - } - } else { - unreachable!() - } - } - _ => { + let alias = match self.store(self.deref(alias)) { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + Some(name.clone()) + } else { unreachable!() } - }; + } + _ => None, + }; - let reposition = - match self.store(self.deref(reposition)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { - name.as_str() == "true" - } else { - unreachable!() + let eof_action = match self.store(self.deref(eof_action)) { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + match name.as_str() { + "eof_code" => EOFAction::EOFCode, + "error" => EOFAction::Error, + "reset" => EOFAction::Reset, + _ => unreachable!(), } - } - _ => { + } else { unreachable!() } - }; + } + _ => { + unreachable!() + } + }; - let stream_type = - match self.store(self.deref(stream_type)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { - match name.as_str() { - "text" => StreamType::Text, - "binary" => StreamType::Binary, - _ => unreachable!() - } - } else { - unreachable!() - } - } - _ => { + let reposition = match self.store(self.deref(reposition)) { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + name.as_str() == "true" + } else { unreachable!() } - }; + } + _ => { + unreachable!() + } + }; + + let stream_type = match self.store(self.deref(stream_type)) { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + match name.as_str() { + "text" => StreamType::Text, + "binary" => StreamType::Binary, + _ => unreachable!(), + } + } else { + unreachable!() + } + } + _ => { + unreachable!() + } + }; let mut options = StreamOptions::default(); options.stream_type = stream_type; - options.reposition = reposition; + options.reposition = reposition; options.alias = alias; options.eof_action = eof_action; options } - pub(crate) - fn get_stream_or_alias( + pub(crate) fn get_stream_or_alias( &mut self, addr: Addr, indices: &IndexStore, caller: &'static str, arity: usize, - ) -> Result - { + ) -> Result { Ok(match self.store(self.deref(addr)) { Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref atom, ref spec) = self.heap.clone(h) { + if let HeapCellValue::Atom(ref atom, ref spec) = self.heap.clone(h) { match indices.stream_aliases.get(atom) { - Some(stream) if !stream.is_null_stream() => { - stream.clone() - } + Some(stream) if !stream.is_null_stream() => stream.clone(), _ => { let stub = MachineError::functor_stub(clause_name!(caller), arity); - let addr = self.heap.to_unifiable( - HeapCellValue::Atom(atom.clone(), spec.clone()) - ); + let addr = self + .heap + .to_unifiable(HeapCellValue::Atom(atom.clone(), spec.clone())); return Err(self.error_form( - MachineError::existence_error(self.heap.h(), ExistenceError::Stream(addr)), + MachineError::existence_error( + self.heap.h(), + ExistenceError::Stream(addr), + ), stub, )); } @@ -970,11 +847,7 @@ impl MachineState { Addr::Stream(h) => { if let HeapCellValue::Stream(ref stream) = &self.heap[h] { if stream.is_null_stream() { - return Err(self.open_permission_error( - Addr::Stream(h), - caller, - arity, - )); + return Err(self.open_permission_error(Addr::Stream(h), caller, arity)); } else { stream.clone() } @@ -986,10 +859,7 @@ impl MachineState { let stub = MachineError::functor_stub(clause_name!(caller), arity); if addr.is_ref() { - return Err(self.error_form( - MachineError::instantiation_error(), - stub, - )); + return Err(self.error_form(MachineError::instantiation_error(), stub)); } else { return Err(self.error_form( MachineError::domain_error(DomainErrorType::StreamOrAlias, addr), @@ -1000,31 +870,24 @@ impl MachineState { }) } - pub(crate) - fn open_parsing_stream( + pub(crate) fn open_parsing_stream( &self, stream: Stream, stub_name: &'static str, stub_arity: usize, ) -> Result { match parsing_stream(stream) { - Ok(parsing_stream) => { - Ok(parsing_stream) - } + Ok(parsing_stream) => Ok(parsing_stream), Err(e) => { let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity); - let err = MachineError::session_error( - self.heap.h(), - SessionError::from(e), - ); + let err = MachineError::session_error(self.heap.h(), SessionError::from(e)); Err(self.error_form(err, stub)) } } } - pub(crate) - fn stream_permission_error( + pub(crate) fn stream_permission_error( &self, perm: Permission, err_string: &'static str, @@ -1033,23 +896,15 @@ impl MachineState { arity: usize, ) -> MachineStub { let stub = MachineError::functor_stub(caller, arity); - let payload = vec![ - HeapCellValue::Stream(stream) - ]; + let payload = vec![HeapCellValue::Stream(stream)]; - let err = MachineError::permission_error( - self.heap.h(), - perm, - err_string, - payload, - ); + let err = MachineError::permission_error(self.heap.h(), perm, err_string, payload); return self.error_form(err, stub); } #[inline] - pub(crate) - fn open_past_eos_error( + pub(crate) fn open_past_eos_error( &self, stream: Stream, caller: ClauseName, @@ -1064,26 +919,20 @@ impl MachineState { ) } - pub(crate) - fn open_permission_error( + pub(crate) fn open_permission_error( &self, culprit: T, stub_name: &'static str, stub_arity: usize, ) -> MachineStub { let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity); - let err = MachineError::permission_error( - self.heap.h(), - Permission::Open, - "source_sink", - culprit, - ); + let err = + MachineError::permission_error(self.heap.h(), Permission::Open, "source_sink", culprit); return self.error_form(err, stub); } - pub(crate) - fn occupied_alias_permission_error( + pub(crate) fn occupied_alias_permission_error( &self, alias: ClauseName, stub_name: &'static str, @@ -1100,8 +949,7 @@ impl MachineState { return self.error_form(err, stub); } - pub(crate) - fn reposition_error( + pub(crate) fn reposition_error( &self, stub_name: &'static str, stub_arity: usize, @@ -1119,9 +967,7 @@ impl MachineState { return self.error_form(err, stub); } - - pub(crate) - fn check_stream_properties( + pub(crate) fn check_stream_properties( &mut self, stream: &mut Stream, expected_type: StreamType, @@ -1129,19 +975,21 @@ impl MachineState { caller: ClauseName, arity: usize, ) -> CallResult { - let opt_err = - if input.is_some() && !stream.is_input_stream() { - Some("stream") // 8.14.2.3 g) - } else if input.is_none() && !stream.is_output_stream() { - Some("stream") // 8.14.2.3 g) - } else if stream.options.stream_type != expected_type { - Some(expected_type.other().as_str()) // 8.14.2.3 h) - } else { - None - }; + let opt_err = if input.is_some() && !stream.is_input_stream() { + Some("stream") // 8.14.2.3 g) + } else if input.is_none() && !stream.is_output_stream() { + Some("stream") // 8.14.2.3 g) + } else if stream.options.stream_type != expected_type { + Some(expected_type.other().as_str()) // 8.14.2.3 h) + } else { + None + }; - let permission = - if input.is_some() { Permission::InputStream } else { Permission::OutputStream }; + let permission = if input.is_some() { + Permission::InputStream + } else { + Permission::OutputStream + }; if let Some(err_string) = opt_err { return Err(self.stream_permission_error( @@ -1155,12 +1003,7 @@ impl MachineState { if let Some(input) = input { if stream.past_end_of_stream() { - self.eof_action( - input, - stream, - caller, - arity, - )?; + self.eof_action(input, stream, caller, arity)?; } } @@ -1180,61 +1023,37 @@ impl Read for Stream { impl Write for Stream { fn write(&mut self, buf: &[u8]) -> std::io::Result { match self.stream_inst.0.borrow_mut().1 { - StreamInstance::OutputFile(_, ref mut file, _) => { - file.write(buf) - } - StreamInstance::TcpStream(_, ref mut tcp_stream) => { - tcp_stream.write(buf) - } - StreamInstance::TlsStream(_, ref mut tls_stream) => { - tls_stream.write(buf) - } - StreamInstance::Bytes(ref mut cursor) => { - cursor.write(buf) - } - StreamInstance::Stdout => { - stdout().write(buf) - } - StreamInstance::PausedPrologStream(..) | - StreamInstance::StaticStr(_) | - StreamInstance::ReadlineStream(_) | - StreamInstance::InputFile(..) | - StreamInstance::Null => { - Err(std::io::Error::new( - ErrorKind::PermissionDenied, - StreamError::WriteToInputStream, - )) - } + StreamInstance::OutputFile(_, ref mut file, _) => file.write(buf), + StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.write(buf), + StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf), + StreamInstance::Bytes(ref mut cursor) => cursor.write(buf), + StreamInstance::Stdout => stdout().write(buf), + StreamInstance::PausedPrologStream(..) + | StreamInstance::StaticStr(_) + | StreamInstance::ReadlineStream(_) + | StreamInstance::InputFile(..) + | StreamInstance::Null => Err(std::io::Error::new( + ErrorKind::PermissionDenied, + StreamError::WriteToInputStream, + )), } } fn flush(&mut self) -> std::io::Result<()> { match self.stream_inst.0.borrow_mut().1 { - StreamInstance::OutputFile(_, ref mut file, _) => { - file.flush() - } - StreamInstance::TcpStream(_, ref mut tcp_stream) => { - tcp_stream.flush() - } - StreamInstance::TlsStream(_, ref mut tls_stream) => { - tls_stream.flush() - } - StreamInstance::Bytes(ref mut cursor) => { - cursor.flush() - } - StreamInstance::Stdout => { - stdout().flush() - } - StreamInstance::PausedPrologStream(..) | - StreamInstance::StaticStr(_) | - StreamInstance::ReadlineStream(_) | - StreamInstance::InputFile(..) | - StreamInstance::Null => { - Err(std::io::Error::new( - ErrorKind::PermissionDenied, - StreamError::FlushToInputStream, - )) - } + StreamInstance::OutputFile(_, ref mut file, _) => file.flush(), + StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.flush(), + StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(), + StreamInstance::Bytes(ref mut cursor) => cursor.flush(), + StreamInstance::Stdout => stdout().flush(), + StreamInstance::PausedPrologStream(..) + | StreamInstance::StaticStr(_) + | StreamInstance::ReadlineStream(_) + | StreamInstance::InputFile(..) + | StreamInstance::Null => Err(std::io::Error::new( + ErrorKind::PermissionDenied, + StreamError::FlushToInputStream, + )), } } } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 03aa1244..81bf2da5 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1,6 +1,14 @@ use crate::prolog_parser_rebis::ast::*; use crate::prolog_parser_rebis::parser::*; use crate::prolog_parser_rebis::tabled_rc::*; +use crate::prolog_parser_rebis::{ + alpha_char, alpha_numeric_char, backslash_char, binary_digit_char, char_class, clause_name, + decimal_digit_char, exponent_char, graphic_char, graphic_token_char, hexadecimal_digit_char, + layout_char, meta_char, new_line_char, octal_digit_char, prolog_char, sign_char, solo_char, + symbolic_control_char, symbolic_hexadecimal_char, temp_v, +}; + +use crate::lazy_static::lazy_static; use crate::clause_types::*; use crate::forms::*; @@ -8,8 +16,8 @@ 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::copier::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; @@ -25,32 +33,35 @@ use crate::indexmap::IndexSet; use crate::ref_thread_local::RefThreadLocal; use std::cmp; -use std::fs; use std::collections::BTreeSet; use std::convert::TryFrom; +use std::env; +use std::fs; use std::io::{ErrorKind, Read, Write}; use std::iter::{once, FromIterator}; use std::net::{TcpListener, TcpStream}; +use std::num::NonZeroU32; use std::ops::Sub; use std::rc::Rc; -use std::num::NonZeroU32; -use std::env; -use std::time::{Duration, SystemTime}; +use crate::chrono::{offset::Local, DateTime}; use crate::cpu_time::ProcessTime; -use crate::chrono::{offset::Local,DateTime}; +use std::time::{Duration, SystemTime}; use crate::crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; -use crate::crossterm::terminal::{enable_raw_mode, disable_raw_mode}; +use crate::crossterm::terminal::{disable_raw_mode, enable_raw_mode}; +use crate::blake2::{Blake2b, Blake2s}; use crate::ring::rand::{SecureRandom, SystemRandom}; -use crate::ring::{digest,hkdf,pbkdf2,aead,signature::{self,KeyPair}}; -use crate::ripemd160::{Ripemd160, Digest}; +use crate::ring::{ + aead, digest, hkdf, pbkdf2, + signature::{self, KeyPair}, +}; +use crate::ripemd160::{Digest, Ripemd160}; use crate::sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; -use crate::blake2::{Blake2s, Blake2b}; -use crate::openssl::ec::{EcGroup, EcPoint}; use crate::openssl::bn::{BigNum, BigNumContext}; +use crate::openssl::ec::{EcGroup, EcPoint}; use crate::openssl::nid::Nid; use sodiumoxide::crypto::scalarmult::curve25519::*; @@ -58,8 +69,9 @@ use sodiumoxide::crypto::scalarmult::curve25519::*; use crate::native_tls::TlsConnector; extern crate select; -use roxmltree; + use base64; +use roxmltree; pub fn get_key() -> KeyEvent { let key; @@ -72,8 +84,8 @@ pub fn get_key() -> KeyEvent { KeyCode::Char(_) | KeyCode::Enter | KeyCode::Tab => { key = key_; break; - }, - _ => () + } + _ => (), } } } @@ -125,15 +137,9 @@ impl BrentAlgState { addr @ Addr::HeapCell(_) | addr @ Addr::StackCell(..) | addr @ Addr::AttrVar(_) => { CycleSearchResult::PartialList(self.steps, addr.as_var().unwrap()) } - Addr::PStrLocation(h, n) => { - CycleSearchResult::PStrLocation(self.steps, h, n) - } - Addr::EmptyList => { - CycleSearchResult::ProperList(self.steps) - } - _ => { - CycleSearchResult::NotList - } + Addr::PStrLocation(h, n) => CycleSearchResult::PStrLocation(self.steps, h, n), + Addr::EmptyList => CycleSearchResult::ProperList(self.steps), + _ => CycleSearchResult::NotList, } } } @@ -149,50 +155,37 @@ impl MachineState { // a step in Brent's algorithm. fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option { match self.store(self.deref(brent_st.hare)) { - Addr::EmptyList => { - Some(CycleSearchResult::ProperList(brent_st.steps)) - } + Addr::EmptyList => Some(CycleSearchResult::ProperList(brent_st.steps)), addr @ Addr::HeapCell(_) | addr @ Addr::StackCell(..) | addr @ Addr::AttrVar(_) => { Some(CycleSearchResult::PartialList( brent_st.steps, addr.as_var().unwrap(), )) } - Addr::PStrLocation(h, n) => { - match &self.heap[h] { - HeapCellValue::PartialString(ref pstr, _) => { - if let Some(c) = pstr.range_from(n ..).next() { - brent_st.step(Addr::PStrLocation(h, n + c.len_utf8())) - } else { - unreachable!() - } - } - _ => { + Addr::PStrLocation(h, n) => match &self.heap[h] { + HeapCellValue::PartialString(ref pstr, _) => { + if let Some(c) = pstr.range_from(n..).next() { + brent_st.step(Addr::PStrLocation(h, n + c.len_utf8())) + } else { unreachable!() } } - } - Addr::Lis(l) => { - brent_st.step(Addr::HeapCell(l + 1)) - } - _ => { - Some(CycleSearchResult::NotList) - } + _ => { + unreachable!() + } + }, + Addr::Lis(l) => brent_st.step(Addr::HeapCell(l + 1)), + _ => Some(CycleSearchResult::NotList), } } - pub(super) - fn detect_cycles_with_max(&self, max_steps: usize, addr: Addr) -> CycleSearchResult { + pub(super) fn detect_cycles_with_max(&self, max_steps: usize, addr: Addr) -> CycleSearchResult { let hare = match self.store(self.deref(addr)) { - Addr::Lis(offset) if max_steps > 0 => { - Addr::Lis(offset) - } + Addr::Lis(offset) if max_steps > 0 => Addr::Lis(offset), Addr::Lis(offset) => { return CycleSearchResult::UntouchedList(offset); } - Addr::PStrLocation(h, n) if max_steps > 0 => { - Addr::PStrLocation(h, n) - } + Addr::PStrLocation(h, n) if max_steps > 0 => Addr::PStrLocation(h, n), Addr::PStrLocation(h, _) => { return CycleSearchResult::UntouchedList(h); } @@ -231,19 +224,14 @@ impl MachineState { } } - pub(super) - fn detect_cycles(&self, addr: Addr) -> CycleSearchResult { + pub(super) fn detect_cycles(&self, addr: Addr) -> CycleSearchResult { let addr = self.store(self.deref(addr)); let hare = match addr { - Addr::Lis(offset) => { - Addr::Lis(offset) - } + Addr::Lis(offset) => Addr::Lis(offset), Addr::EmptyList => { return CycleSearchResult::EmptyList; } - Addr::PStrLocation(h, n) => { - Addr::PStrLocation(h, n) - } + Addr::PStrLocation(h, n) => Addr::PStrLocation(h, n), Addr::Con(h) => { if let HeapCellValue::PartialString(..) = &self.heap[h] { Addr::PStrLocation(h, 0) @@ -276,33 +264,23 @@ impl MachineState { } fn skip_max_list_result(&mut self, max_steps: Option) { - let search_result = - if let Some(max_steps) = max_steps { - if max_steps == -1 { - self.detect_cycles(self[temp_v!(3)]) - } else { - self.detect_cycles_with_max( - max_steps as usize, - self[temp_v!(3)], - ) - } - } else { + let search_result = if let Some(max_steps) = max_steps { + if max_steps == -1 { self.detect_cycles(self[temp_v!(3)]) - }; + } else { + self.detect_cycles_with_max(max_steps as usize, self[temp_v!(3)]) + } + } else { + self.detect_cycles(self[temp_v!(3)]) + }; match search_result { CycleSearchResult::PStrLocation(steps, h, n) => { self.finalize_skip_max_list(steps, Addr::PStrLocation(h, n)); } - CycleSearchResult::UntouchedList(l) => { - self.finalize_skip_max_list(0, Addr::Lis(l)) - } - CycleSearchResult::EmptyList => { - self.finalize_skip_max_list(0, Addr::EmptyList) - } - CycleSearchResult::PartialList(n, r) => { - self.finalize_skip_max_list(n, r.as_addr()) - } + CycleSearchResult::UntouchedList(l) => self.finalize_skip_max_list(0, Addr::Lis(l)), + CycleSearchResult::EmptyList => self.finalize_skip_max_list(0, Addr::EmptyList), + CycleSearchResult::PartialList(n, r) => self.finalize_skip_max_list(n, r.as_addr()), CycleSearchResult::ProperList(steps) => { self.finalize_skip_max_list(steps, Addr::EmptyList) } @@ -313,8 +291,7 @@ impl MachineState { }; } - pub(super) - fn skip_max_list(&mut self) -> CallResult { + pub(super) fn skip_max_list(&mut self) -> CallResult { let max_steps = self.store(self.deref(self[temp_v!(2)])); match max_steps { @@ -323,12 +300,11 @@ impl MachineState { return Err(self.error_form(MachineError::instantiation_error(), stub)); } addr => { - let max_steps_n = - match Number::try_from((max_steps, &self.heap)) { - Ok(Number::Integer(n)) => n.to_isize(), - Ok(Number::Fixnum(n)) => Some(n), - _ => None, - }; + let max_steps_n = match Number::try_from((max_steps, &self.heap)) { + Ok(Number::Integer(n)) => n.to_isize(), + Ok(Number::Fixnum(n)) => Some(n), + _ => None, + }; if max_steps_n.map(|i| i >= -1).unwrap_or(false) { let n = self.store(self.deref(self[temp_v!(1)])); @@ -337,7 +313,7 @@ impl MachineState { Ok(Number::Integer(n)) => { if n.as_ref() == &0 { let xs0 = self[temp_v!(3)]; - let xs = self[temp_v!(4)]; + let xs = self[temp_v!(4)]; self.unify(xs0, xs); } else { @@ -347,7 +323,7 @@ impl MachineState { Ok(Number::Fixnum(n)) => { if n == 0 { let xs0 = self[temp_v!(3)]; - let xs = self[temp_v!(4)]; + let xs = self[temp_v!(4)]; self.unify(xs0, xs); } else { @@ -360,16 +336,10 @@ impl MachineState { } } else { let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4); - return Err( - self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - addr - ), - stub, - ) - ); + return Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, addr), + stub, + )); } } } @@ -385,10 +355,7 @@ impl MachineState { ) -> Result { if file_spec.as_str().is_empty() { let stub = MachineError::functor_stub(clause_name!("open"), 4); - let err = MachineError::domain_error( - DomainErrorType::SourceSink, - self[temp_v!(1)], - ); + let err = MachineError::domain_error(DomainErrorType::SourceSink, self[temp_v!(1)]); return Err(self.error_form(err, stub)); } @@ -396,84 +363,72 @@ impl MachineState { // 8.11.5.3l) if let Some(ref alias) = &options.alias { if indices.stream_aliases.contains_key(alias) { - return Err(self.occupied_alias_permission_error( - alias.clone(), - "open", - 4, - )); + return Err(self.occupied_alias_permission_error(alias.clone(), "open", 4)); } } 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) = - match mode.as_str() { - "read" => { - open_options.read(true).write(false).create(false); - (true, false) - } - "write" => { - open_options.read(false).write(true).truncate(true).create(true); - (false, false) - } - "append" => { - open_options.read(false).write(true).create(true).append(true); - (false, true) - } - _ => { - let stub = MachineError::functor_stub(clause_name!("open"), 4); - let err = MachineError::domain_error( - DomainErrorType::IOMode, - self[temp_v!(2)], - ); + let (is_input_file, in_append_mode) = match mode.as_str() { + "read" => { + open_options.read(true).write(false).create(false); + (true, false) + } + "write" => { + open_options + .read(false) + .write(true) + .truncate(true) + .create(true); + (false, false) + } + "append" => { + open_options + .read(false) + .write(true) + .create(true) + .append(true); + (false, true) + } + _ => { + let stub = MachineError::functor_stub(clause_name!("open"), 4); + let err = MachineError::domain_error(DomainErrorType::IOMode, self[temp_v!(2)]); - // 8.11.5.3h) - return Err(self.error_form(err, stub)); - } - }; + // 8.11.5.3h) + return Err(self.error_form(err, stub)); + } + }; - let file = - match open_options.open(file_spec.as_str()) { - Ok(file) => { - file - } - Err(err) => { - match err.kind() { - ErrorKind::NotFound => { - // 8.11.5.3j) - let stub = MachineError::functor_stub( - clause_name!("open"), - 4, - ); + let file = match open_options.open(file_spec.as_str()) { + Ok(file) => file, + Err(err) => { + match err.kind() { + ErrorKind::NotFound => { + // 8.11.5.3j) + let stub = MachineError::functor_stub(clause_name!("open"), 4); - let err = MachineError::existence_error( - self.heap.h(), - ExistenceError::SourceSink(self[temp_v!(1)]), - ); + let err = MachineError::existence_error( + self.heap.h(), + ExistenceError::SourceSink(self[temp_v!(1)]), + ); - return Err(self.error_form(err, stub)); - } - ErrorKind::PermissionDenied => { - // 8.11.5.3k) - return Err(self.open_permission_error(self[temp_v!(1)], "open", 4)); - } - _ => { - let stub = MachineError::functor_stub( - clause_name!("open"), - 4, - ); + return Err(self.error_form(err, stub)); + } + ErrorKind::PermissionDenied => { + // 8.11.5.3k) + return Err(self.open_permission_error(self[temp_v!(1)], "open", 4)); + } + _ => { + let stub = MachineError::functor_stub(clause_name!("open"), 4); - let err = MachineError::syntax_error( - self.heap.h(), - ParserError::IO(err), - ); + let err = MachineError::syntax_error(self.heap.h(), ParserError::IO(err)); - return Err(self.error_form(err, stub)); - } + return Err(self.error_form(err, stub)); } } - }; + } + }; Ok(if is_input_file { Stream::from_file_as_input(file_spec, file) @@ -496,11 +451,8 @@ impl MachineState { fn copy_findall_solution(&mut self, lh_offset: usize, copy_target: Addr) -> usize { let threshold = self.lifted_heap.h() - lh_offset; - let mut copy_ball_term = CopyBallTerm::new( - &mut self.stack, - &mut self.heap, - &mut self.lifted_heap, - ); + let mut copy_ball_term = + CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.lifted_heap); copy_ball_term.push(HeapCellValue::Addr(Addr::Lis(threshold + 1))); copy_ball_term.push(HeapCellValue::Addr(Addr::HeapCell(threshold + 3))); @@ -531,7 +483,8 @@ impl MachineState { self.lifted_heap.truncate(lh_offset); } else { let threshold = self.lifted_heap.h() - lh_offset; - self.lifted_heap.push(HeapCellValue::Addr(addr_constr(threshold))); + self.lifted_heap + .push(HeapCellValue::Addr(addr_constr(threshold))); } } _ => self.fail = true, @@ -563,13 +516,13 @@ impl MachineState { &CompositeOpDir::new(&indices.op_dir, None), ); - let addr = self.heap.to_unifiable(HeapCellValue::DBRef( - DBRef::NamedPred( + let addr = self + .heap + .to_unifiable(HeapCellValue::DBRef(DBRef::NamedPred( name.clone(), *arity, spec, - ) - )); + ))); self.bind(r, addr); @@ -593,17 +546,13 @@ impl MachineState { let a2 = self[temp_v!(2)]; if let Some(r) = a2.as_var() { - let addr = self.heap.to_unifiable( - HeapCellValue::DBRef( - DBRef::Op( - *priority, - *spec, - name.clone(), - op_dir.clone(), - SharedOpDesc::new(*priority, *spec) - ), - ), - ); + let addr = self.heap.to_unifiable(HeapCellValue::DBRef(DBRef::Op( + *priority, + *spec, + name.clone(), + op_dir.clone(), + SharedOpDesc::new(*priority, *spec), + ))); self.bind(r, addr); } else { @@ -621,8 +570,7 @@ impl MachineState { n: &Integer, stub: &'static str, arity: usize, - ) -> Result - { + ) -> Result { let c = n.to_u32().and_then(std::char::from_u32); if let Some(c) = c { @@ -664,26 +612,16 @@ impl MachineState { string.push('.'); - let mut stream = - match parsing_stream(std::io::Cursor::new(string)) { - Ok(stream) => { - stream - } - Err(e) => { - let err = MachineError::session_error( - self.heap.h(), - SessionError::from(e), - ); + let mut stream = match parsing_stream(std::io::Cursor::new(string)) { + Ok(stream) => stream, + Err(e) => { + let err = MachineError::session_error(self.heap.h(), SessionError::from(e)); - return Err(self.error_form(err, stub)); - } - }; + return Err(self.error_form(err, stub)); + } + }; - let mut parser = Parser::new( - &mut stream, - self.atom_tbl.clone(), - self.machine_flags(), - ); + let mut parser = Parser::new(&mut stream, self.atom_tbl.clone(), self.machine_flags()); match parser.read_term(&CompositeOpDir::new(&indices.op_dir, None)) { Err(err) => { @@ -743,7 +681,7 @@ impl MachineState { match &self.heap[s] { HeapCellValue::NamedStr(arity, ..) => { let num_cells = arity - 1; - let p_functor = self.heap[s+1].as_addr(s+1); + let p_functor = self.heap[s + 1].as_addr(s + 1); let cp = self.heap.to_local_code_ptr(&p_functor).unwrap(); let prev_e = self.e; @@ -751,37 +689,36 @@ impl MachineState { let e = self.stack.allocate_and_frame(num_cells); let and_frame = self.stack.index_and_frame_mut(e); - and_frame.prelude.e = prev_e; + and_frame.prelude.e = prev_e; and_frame.prelude.cp = return_p; self.p = CodePtr::Local(cp + 1); // adjust cut point to occur after call_continuation. if num_cells > 0 { - if let Addr::CutPoint(_) = self.heap[s+2].as_addr(s+2) { + if let Addr::CutPoint(_) = self.heap[s + 2].as_addr(s + 2) { and_frame[1] = Addr::CutPoint(self.b); } else { - and_frame[1] = self.heap[s+2].as_addr(s+2); + and_frame[1] = self.heap[s + 2].as_addr(s + 2); } } - for index in s+3 .. s+2+num_cells { - and_frame[index - (s+1)] = self.heap[index].as_addr(index); + for index in s + 3..s + 2 + num_cells { + and_frame[index - (s + 1)] = self.heap[index].as_addr(index); } self.e = e; self.p.local() } - _ => unreachable!() + _ => unreachable!(), } } - _ => unreachable!() + _ => unreachable!(), } } - pub(super) - fn system_call( + pub(super) fn system_call( &mut self, ct: &SystemClauseType, code_repo: &CodeRepo, @@ -794,23 +731,18 @@ impl MachineState { match ct { &SystemClauseType::BindFromRegister => { let reg = self.store(self.deref(self[temp_v!(2)])); - let n = - match Number::try_from((reg, &self.heap)) { - Ok(Number::Integer(n)) => { - n.to_usize() - } - Ok(Number::Fixnum(n)) => { - usize::try_from(n).ok() - } - _ => { - unreachable!() - } - }; + let n = match Number::try_from((reg, &self.heap)) { + Ok(Number::Integer(n)) => n.to_usize(), + Ok(Number::Fixnum(n)) => usize::try_from(n).ok(), + _ => { + unreachable!() + } + }; if let Some(n) = n { if n <= MAX_ARITY { let target = self[temp_v!(n)]; - let addr = self[temp_v!(1)]; + let addr = self[temp_v!(1)]; self.unify(addr, target); return return_from_clause!(self.last_call, self); @@ -821,22 +753,19 @@ impl MachineState { } &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, self.atom_tbl), None) - ); + Some(host) => match host.into_string().ok() { + Some(host) => { + let hostname = self.heap.to_unifiable(HeapCellValue::Atom( + clause_name!(host, self.atom_tbl), + None, + )); - self.unify(self[temp_v!(1)], hostname); - return return_from_clause!(self.last_call, self); - } - None => { - } + self.unify(self[temp_v!(1)], hostname); + return return_from_clause!(self.last_call, self); } - } - None => { - } + None => {} + }, + None => {} } self.fail = true; @@ -860,15 +789,9 @@ impl MachineState { } } addr => { - let stub = MachineError::functor_stub( - clause_name!("current_input"), - 1, - ); + let stub = MachineError::functor_stub(clause_name!("current_input"), 1); - let err = MachineError::domain_error( - DomainErrorType::Stream, - addr, - ); + let err = MachineError::domain_error(DomainErrorType::Stream, addr); return Err(self.error_form(err, stub)); } @@ -891,15 +814,9 @@ impl MachineState { } } addr => { - let stub = MachineError::functor_stub( - clause_name!("current_input"), - 1, - ); + let stub = MachineError::functor_stub(clause_name!("current_input"), 1); - let err = MachineError::domain_error( - DomainErrorType::Stream, - addr, - ); + let err = MachineError::domain_error(DomainErrorType::Stream, addr); return Err(self.error_form(err, stub)); } @@ -914,10 +831,16 @@ impl MachineState { for entry in entries { if let Ok(entry) = entry { match entry.file_name().into_string() { - Ok(name) => { files.push(self.heap.put_complete_string(&name)); } + Ok(name) => { + files.push(self.heap.put_complete_string(&name)); + } _ => { - let stub = MachineError::functor_stub(clause_name!("directory_files"), 2); - let err = MachineError::representation_error(RepFlag::Character); + let stub = MachineError::functor_stub( + clause_name!("directory_files"), + 2, + ); + let err = + MachineError::representation_error(RepFlag::Character); let err = self.error_form(err, stub); return Err(err); @@ -940,29 +863,35 @@ impl MachineState { } &SystemClauseType::FileExists => { let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); - if !std::path::Path::new(&file).exists() || !fs::metadata(&file).unwrap().is_file() { + if !std::path::Path::new(&file).exists() || !fs::metadata(&file).unwrap().is_file() + { self.fail = true; return Ok(()); } } &SystemClauseType::DirectoryExists => { let directory = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); - if !std::path::Path::new(&directory).exists() || !fs::metadata(&directory).unwrap().is_dir() { + if !std::path::Path::new(&directory).exists() + || !fs::metadata(&directory).unwrap().is_dir() + { self.fail = true; return Ok(()); } } &SystemClauseType::DirectorySeparator => { - let addr = self.heap.put_constant(Constant::Char(std::path::MAIN_SEPARATOR)); + let addr = self + .heap + .put_constant(Constant::Char(std::path::MAIN_SEPARATOR)); self.unify(self[temp_v!(1)], addr); } &SystemClauseType::MakeDirectory => { let directory = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); match fs::create_dir(directory) { - Ok(_) => { } - _ => { self.fail = true; - return Ok(()); + Ok(_) => {} + _ => { + self.fail = true; + return Ok(()); } } } @@ -970,24 +899,26 @@ impl MachineState { let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); match fs::remove_file(file) { - Ok(_) => { } - _ => { self.fail = true; - return Ok(()); + Ok(_) => {} + _ => { + self.fail = true; + return Ok(()); } } } &SystemClauseType::WorkingDirectory => { if let Ok(dir) = env::current_dir() { - let current = - match dir.to_str() { - Some(d) => { d } - _ => { let stub = MachineError::functor_stub(clause_name!("working_directory"), 2); - let err = MachineError::representation_error(RepFlag::Character); - let err = self.error_form(err, stub); + let current = match dir.to_str() { + Some(d) => d, + _ => { + let stub = + MachineError::functor_stub(clause_name!("working_directory"), 2); + let err = MachineError::representation_error(RepFlag::Character); + let err = self.error_form(err, stub); - return Err(err); - } - }; + return Err(err); + } + }; let chars = self.heap.put_complete_string(current); self.unify(self[temp_v!(1)], chars); @@ -995,9 +926,10 @@ impl MachineState { let next = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); match env::set_current_dir(std::path::Path::new(&next)) { - Ok(_) => { } - _ => { self.fail = true; - return Ok(()); + Ok(_) => {} + _ => { + self.fail = true; + return Ok(()); } } } else { @@ -1010,17 +942,17 @@ impl MachineState { match fs::canonicalize(path) { Ok(canonical) => { - let cs = - match canonical.to_str() { - Some(s) => { s } - _ => { - let stub = MachineError::functor_stub(clause_name!("path_canonical"), 2); - let err = MachineError::representation_error(RepFlag::Character); - let err = self.error_form(err, stub); + let cs = match canonical.to_str() { + Some(s) => s, + _ => { + let stub = + MachineError::functor_stub(clause_name!("path_canonical"), 2); + let err = MachineError::representation_error(RepFlag::Character); + let err = self.error_form(err, stub); - return Err(err); - } - }; + return Err(err); + } + }; let chars = self.heap.put_complete_string(cs); self.unify(self[temp_v!(2)], chars); } @@ -1047,13 +979,14 @@ impl MachineState { }; if let Ok(md) = fs::metadata(file) { - if let Ok(time) = - match which { - "modification" => { md.modified() } - "access" => { md.accessed() } - "creation" => { md.created() } - _ => { unreachable!() } - } { + if let Ok(time) = match which { + "modification" => md.modified(), + "access" => md.accessed(), + "creation" => md.created(), + _ => { + unreachable!() + } + } { let chars = self.systemtime_to_timestamp(time); self.unify(self[temp_v!(3)], chars); } else { @@ -1077,8 +1010,8 @@ impl MachineState { self.unify(a2, list_of_chars); } Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(name, _) = self.heap.clone(h) { - let s = self.heap.put_complete_string(name.as_str()); + if let HeapCellValue::Atom(name, _) = self.heap.clone(h) { + let s = self.heap.put_complete_string(name.as_str()); let a2 = self[temp_v!(2)]; self.unify(s, a2); @@ -1088,13 +1021,9 @@ impl MachineState { } Addr::EmptyList => { let a2 = self[temp_v!(2)]; - let chars = vec![ - Addr::Char('['), - Addr::Char(']'), - ]; + let chars = vec![Addr::Char('['), Addr::Char(']')]; - let list_of_chars = - Addr::HeapCell(self.heap.to_list(chars.into_iter())); + let list_of_chars = Addr::HeapCell(self.heap.to_list(chars.into_iter())); self.unify(a2, list_of_chars); } @@ -1108,19 +1037,16 @@ impl MachineState { self.unify(addr, Addr::EmptyList); } else { let chars = clause_name!(string, self.atom_tbl); - let atom = self.heap.to_unifiable( - HeapCellValue::Atom(chars, None) - ); + let atom = + self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); self.unify(addr, atom); } } focus => { if let Addr::Lis(l) = focus { - let stub = MachineError::functor_stub( - clause_name!("atom_chars"), - 2, - ); + let stub = + MachineError::functor_stub(clause_name!("atom_chars"), 2); let err = MachineError::type_error( self.heap.h(), @@ -1150,13 +1076,10 @@ impl MachineState { self.unify(a2, list_of_codes); } 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) { let a2 = self.store(self.deref(self[temp_v!(2)])); - let iter = name - .as_str() - .chars() - .map(|c| Addr::Fixnum(c as isize)); + let iter = name.as_str().chars().map(|c| Addr::Fixnum(c as isize)); let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); @@ -1166,10 +1089,7 @@ impl MachineState { } } Addr::EmptyList => { - let chars = vec![ - Addr::Fixnum('[' as isize), - Addr::Fixnum(']' as isize), - ]; + let chars = vec![Addr::Fixnum('[' as isize), Addr::Fixnum(']' as isize)]; let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter())); let a2 = self[temp_v!(2)]; @@ -1221,9 +1141,10 @@ impl MachineState { } } - let string = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!(chars, self.atom_tbl), None) - ); + let string = self.heap.to_unifiable(HeapCellValue::Atom( + clause_name!(chars, self.atom_tbl), + None, + )); self.bind(addr.as_var().unwrap(), string); } @@ -1292,22 +1213,17 @@ impl MachineState { Err(e) => { return Err(e); } - Ok(addrs) => { - match self.try_char_list(addrs) { - Ok(string) => { - let stub = MachineError::functor_stub(clause_name!("number_chars"), 2); - self.parse_number_from_string(string, indices, stub)?; - } - Err(err) => { - let stub = MachineError::functor_stub( - clause_name!("number_chars"), - 2, - ); - - return Err(self.error_form(err, stub)); - } + Ok(addrs) => match self.try_char_list(addrs) { + Ok(string) => { + let stub = MachineError::functor_stub(clause_name!("number_chars"), 2); + self.parse_number_from_string(string, indices, stub)?; } - } + Err(err) => { + let stub = MachineError::functor_stub(clause_name!("number_chars"), 2); + + return Err(self.error_form(err, stub)); + } + }, } } &SystemClauseType::CreatePartialString => { @@ -1350,24 +1266,20 @@ impl MachineState { self.fail = true; return Ok(()); } - _ => { - } + _ => {} } let mut heap_pstr_iter = self.heap_pstr_iter(addr); while let Some(_) = heap_pstr_iter.next() {} - self.fail = - match heap_pstr_iter.focus() { - Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) | - Addr::EmptyList => { - false - } - _ => { - true - } - }; + self.fail = match heap_pstr_iter.focus() { + Addr::AttrVar(_) + | Addr::HeapCell(_) + | Addr::StackCell(..) + | Addr::EmptyList => false, + _ => true, + }; } &SystemClauseType::PartialStringTail => { let pstr = self.store(self.deref(self[temp_v!(1)])); @@ -1422,48 +1334,43 @@ impl MachineState { return return_from_clause!(self.last_call, self); } - let addr = - match self.store(self.deref(self[temp_v!(2)])) { - addr if addr.is_ref() => { - addr - } - addr => { - match Number::try_from((addr, &self.heap)) { - Ok(Number::Integer(n)) => { - if let Some(nb) = n.to_u8() { - Addr::Usize(nb as usize) - } else { - return Err(self.type_error( - ValidType::InByte, - addr, - clause_name!("peek_byte"), - 2, - )); - } - } - Ok(Number::Fixnum(n)) => { - if let Ok(nb) = u8::try_from(n) { - Addr::Usize(nb as usize) - } else { - return Err(self.type_error( - ValidType::InByte, - addr, - clause_name!("peek_byte"), - 2, - )); - } - } - _ => { - return Err(self.type_error( - ValidType::InByte, - addr, - clause_name!("peek_byte"), - 2, - )); - } + let addr = match self.store(self.deref(self[temp_v!(2)])) { + addr if addr.is_ref() => addr, + addr => match Number::try_from((addr, &self.heap)) { + Ok(Number::Integer(n)) => { + if let Some(nb) = n.to_u8() { + Addr::Usize(nb as usize) + } else { + return Err(self.type_error( + ValidType::InByte, + addr, + clause_name!("peek_byte"), + 2, + )); } } - }; + Ok(Number::Fixnum(n)) => { + if let Ok(nb) = u8::try_from(n) { + Addr::Usize(nb as usize) + } else { + return Err(self.type_error( + ValidType::InByte, + addr, + clause_name!("peek_byte"), + 2, + )); + } + } + _ => { + return Err(self.type_error( + ValidType::InByte, + addr, + clause_name!("peek_byte"), + 2, + )); + } + }, + }; loop { match stream.peek_byte().map_err(|e| e.kind()) { @@ -1521,9 +1428,9 @@ impl MachineState { if stream.at_end_of_stream() { let end_of_file = clause_name!("end_of_file"); - let end_of_file = self.heap.to_unifiable( - HeapCellValue::Atom(end_of_file, None), - ); + let end_of_file = self + .heap + .to_unifiable(HeapCellValue::Atom(end_of_file, None)); stream.set_past_end_of_stream(); @@ -1531,42 +1438,35 @@ impl MachineState { return return_from_clause!(self.last_call, self); } - let addr = - match self.store(self.deref(self[temp_v!(2)])) { - addr if addr.is_ref() => { - addr - } - Addr::Con(h) if self.heap.atom_at(h) => { - match &self.heap[h] { - HeapCellValue::Atom(ref atom, _) if atom.is_char() => { - if let Some(c) = atom.as_str().chars().next() { - Addr::Char(c) - } else { - unreachable!() - } - } - culprit => { - return Err(self.type_error( - ValidType::InCharacter, - culprit.as_addr(h), - clause_name!("peek_char"), - 2, - )); - } + let addr = match self.store(self.deref(self[temp_v!(2)])) { + addr if addr.is_ref() => addr, + Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { + HeapCellValue::Atom(ref atom, _) if atom.is_char() => { + if let Some(c) = atom.as_str().chars().next() { + Addr::Char(c) + } else { + unreachable!() } } - Addr::Char(d) => { - Addr::Char(d) - } culprit => { return Err(self.type_error( ValidType::InCharacter, - culprit, + culprit.as_addr(h), clause_name!("peek_char"), 2, )); } - }; + }, + Addr::Char(d) => Addr::Char(d), + culprit => { + return Err(self.type_error( + ValidType::InCharacter, + culprit, + clause_name!("peek_char"), + 2, + )); + } + }; loop { match stream.peek_char().map_err(|e| e.kind()) { @@ -1598,14 +1498,14 @@ impl MachineState { } else if self.fail { return Ok(()); } - }/* - _ => { - let stub = MachineError::functor_stub(clause_name!("peek_char"), 2); - let err = MachineError::representation_error(RepFlag::Character); - let err = self.error_form(err, stub); + } /* + _ => { + let stub = MachineError::functor_stub(clause_name!("peek_char"), 2); + let err = MachineError::representation_error(RepFlag::Character); + let err = self.error_form(err, stub); - return Err(err); - }*/ + return Err(err); + }*/ } } } @@ -1631,9 +1531,9 @@ impl MachineState { if stream.at_end_of_stream() { let end_of_file = clause_name!("end_of_file"); - let end_of_file = self.heap.to_unifiable( - HeapCellValue::Atom(end_of_file, None), - ); + let end_of_file = self + .heap + .to_unifiable(HeapCellValue::Atom(end_of_file, None)); stream.set_past_end_of_stream(); @@ -1641,54 +1541,49 @@ impl MachineState { return return_from_clause!(self.last_call, self); } - let addr = - match self.store(self.deref(self[temp_v!(2)])) { - addr if addr.is_ref() => { - addr - } - addr => { - match Number::try_from((addr, &self.heap)) { - Ok(Number::Integer(n)) => { - let n = n.to_u32().and_then(|n| { - std::char::from_u32(n).and_then(|_| Some(n)) - }); + let addr = match self.store(self.deref(self[temp_v!(2)])) { + addr if addr.is_ref() => addr, + addr => match Number::try_from((addr, &self.heap)) { + Ok(Number::Integer(n)) => { + let n = n + .to_u32() + .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n))); - if let Some(n) = n { - Addr::Fixnum(n as isize) - } else { - return Err(self.representation_error( - RepFlag::InCharacterCode, - clause_name!("peek_code"), - 2, - )); - } - } - Ok(Number::Fixnum(n)) => { - let n = u32::try_from(n).ok().and_then(|n| { - std::char::from_u32(n).and_then(|_| Some(n)) - }); - - if let Some(n) = n { - Addr::Fixnum(n as isize) - } else { - return Err(self.representation_error( - RepFlag::InCharacterCode, - clause_name!("peek_code"), - 2, - )); - } - } - _ => { - return Err(self.type_error( - ValidType::Integer, - self[temp_v!(2)], - clause_name!("peek_code"), - 2, - )); - } + if let Some(n) = n { + Addr::Fixnum(n as isize) + } else { + return Err(self.representation_error( + RepFlag::InCharacterCode, + clause_name!("peek_code"), + 2, + )); } } - }; + Ok(Number::Fixnum(n)) => { + let n = u32::try_from(n) + .ok() + .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n))); + + if let Some(n) = n { + Addr::Fixnum(n as isize) + } else { + return Err(self.representation_error( + RepFlag::InCharacterCode, + clause_name!("peek_code"), + 2, + )); + } + } + _ => { + return Err(self.type_error( + ValidType::Integer, + self[temp_v!(2)], + clause_name!("peek_code"), + 2, + )); + } + }, + }; loop { let result = stream.peek_char(); @@ -1722,7 +1617,8 @@ impl MachineState { } else if self.fail { return Ok(()); } - } } + } + } } } &SystemClauseType::NumberToChars => { @@ -1731,27 +1627,22 @@ impl MachineState { let n = self.store(self.deref(n)); - let string = - match Number::try_from((n, &self.heap)) { - Ok(Number::Float(OrderedFloat(n))) => { - format!("{0:<20?}", n) - } - Ok(Number::Fixnum(n)) => { - n.to_string() - } - Ok(Number::Integer(n)) => { - n.to_string() - } - Ok(Number::Rational(r)) => { - // n has already been confirmed as an integer, and - // internally, Rational is assumed reduced, so its denominator - // must be 1. - r.numer().to_string() - } - _ => { - unreachable!() - } - }; + let string = match Number::try_from((n, &self.heap)) { + Ok(Number::Float(OrderedFloat(n))) => { + format!("{0:<20?}", n) + } + Ok(Number::Fixnum(n)) => n.to_string(), + Ok(Number::Integer(n)) => n.to_string(), + Ok(Number::Rational(r)) => { + // n has already been confirmed as an integer, and + // internally, Rational is assumed reduced, so its denominator + // must be 1. + r.numer().to_string() + } + _ => { + unreachable!() + } + }; let chars = string.trim().chars().map(|c| Addr::Char(c)); let char_list = Addr::HeapCell(self.heap.to_list(chars)); @@ -1762,32 +1653,24 @@ impl MachineState { let n = self[temp_v!(1)]; let chs = self[temp_v!(2)]; - let string = - match Number::try_from((n, &self.heap)) { - Ok(Number::Float(OrderedFloat(n))) => { - format!("{0:<20?}", n) - } - Ok(Number::Fixnum(n)) => { - n.to_string() - } - Ok(Number::Integer(n)) => { - n.to_string() - } - Ok(Number::Rational(r)) => { - // n has already been confirmed as an integer, and - // internally, Rational is assumed reduced, so its - // denominator must be 1. - r.numer().to_string() - } - _ => { - unreachable!() - } - }; + let string = match Number::try_from((n, &self.heap)) { + Ok(Number::Float(OrderedFloat(n))) => { + format!("{0:<20?}", n) + } + Ok(Number::Fixnum(n)) => n.to_string(), + Ok(Number::Integer(n)) => n.to_string(), + Ok(Number::Rational(r)) => { + // n has already been confirmed as an integer, and + // internally, Rational is assumed reduced, so its + // denominator must be 1. + r.numer().to_string() + } + _ => { + unreachable!() + } + }; - let codes = string - .trim() - .chars() - .map(|c| Addr::Fixnum(c as isize)); + let codes = string.trim().chars().map(|c| Addr::Fixnum(c as isize)); let codes_list = Addr::HeapCell(self.heap.to_list(codes)); @@ -1800,22 +1683,17 @@ impl MachineState { Err(e) => { return Err(e); } - Ok(addrs) => { - match self.try_char_list(addrs) { - Ok(chars) => { - let stub = MachineError::functor_stub(clause_name!("number_codes"), 2); - self.parse_number_from_string(chars, indices, stub)?; - } - Err(err) => { - let stub = MachineError::functor_stub( - clause_name!("number_codes"), - 2, - ); - - return Err(self.error_form(err, stub)); - } + Ok(addrs) => match self.try_char_list(addrs) { + Ok(chars) => { + let stub = MachineError::functor_stub(clause_name!("number_codes"), 2); + self.parse_number_from_string(chars, indices, stub)?; } - } + Err(err) => { + let stub = MachineError::functor_stub(clause_name!("number_codes"), 2); + + return Err(self.error_form(err, stub)); + } + }, } } &SystemClauseType::LiftedHeapLength => { @@ -1829,17 +1707,16 @@ impl MachineState { match self.store(self.deref(a1)) { Addr::Con(h) if self.heap.atom_at(h) => { - let c = - if let HeapCellValue::Atom(name, _) = &self.heap[h] { - if name.is_char() { - name.as_str().chars().next().unwrap() - } else { - self.fail = true; - return Ok(()); - } + let c = if let HeapCellValue::Atom(name, _) = &self.heap[h] { + if name.is_char() { + name.as_str().chars().next().unwrap() } else { - unreachable!() - }; + self.fail = true; + return Ok(()); + } + } else { + unreachable!() + }; let a2 = self[temp_v!(2)]; self.unify(Addr::Fixnum(c as isize), a2); @@ -1853,9 +1730,7 @@ impl MachineState { let a2 = self.store(self.deref(a2)); let c = match Number::try_from((a2, &self.heap)) { - Ok(Number::Integer(n)) => { - self.int_to_char(&n, "char_code", 2)? - } + Ok(Number::Integer(n)) => self.int_to_char(&n, "char_code", 2)?, Ok(Number::Fixnum(n)) => { self.int_to_char(&Integer::from(n), "char_code", 2)? } @@ -1881,45 +1756,41 @@ impl MachineState { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(name, _) = &self.heap[h] { name.as_str().chars().next().unwrap() - } - else { + } else { unreachable!() } } - _ => unreachable!() + _ => unreachable!(), }; let chars = match a2 { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(name, _) = &self.heap[h] { name.as_str().to_string() - } - else { + } else { unreachable!() } } - Addr::Char(c) => { - c.to_string() - } - _ => unreachable!() + Addr::Char(c) => c.to_string(), + _ => unreachable!(), }; self.fail = true; // This predicate fails by default. macro_rules! macro_check { ($id:ident, $name:tt) => { - if $id!(c) && chars == $name { - self.fail = false; + if $id!(c) && chars == $name { + self.fail = false; - return return_from_clause!(self.last_call, self); - } - } + return return_from_clause!(self.last_call, self); + } + }; } macro_rules! method_check { ($id:ident, $name:tt) => { - if c.$id() && chars == $name { - self.fail = false; + if c.$id() && chars == $name { + self.fail = false; - return return_from_clause!(self.last_call, self); - } - } + return return_from_clause!(self.last_call, self); + } + }; } macro_check!(symbolic_control_char, "symbolic_control"); // macro_check!(space_char, "space"); @@ -2006,9 +1877,7 @@ impl MachineState { self.heap.extend(stub.into_iter()); self.unify(addr, Addr::HeapCell(h)); } - Some((_, Some(h))) => { - self.unify(addr, Addr::HeapCell(*h)) - } + Some((_, Some(h))) => self.unify(addr, Addr::HeapCell(*h)), None => self.fail = true, }; } @@ -2049,9 +1918,7 @@ impl MachineState { self.unify(addr, Addr::HeapCell(*h)); } } - None => { - self.fail = true - } + None => self.fail = true, }; } &SystemClauseType::PutCode => { @@ -2082,7 +1949,9 @@ impl MachineState { } } Ok(Number::Fixnum(n)) => { - if let Some(c) = u32::try_from(n).ok().and_then(|c| char::try_from(c).ok()) { + if let Some(c) = + u32::try_from(n).ok().and_then(|c| char::try_from(c).ok()) + { write!(&mut stream, "{}", c).unwrap(); return return_from_clause!(self.last_call, self); } @@ -2100,9 +1969,7 @@ impl MachineState { } let stub = MachineError::functor_stub(clause_name!("put_code"), 2); - let err = MachineError::representation_error( - RepFlag::CharacterCode, - ); + let err = MachineError::representation_error(RepFlag::CharacterCode); return Err(self.error_form(err, stub)); } @@ -2129,34 +1996,27 @@ impl MachineState { } addr => { match self.store(self.deref(self[temp_v!(2)])) { - Addr::Con(h) if self.heap.atom_at(h) => { - match &self.heap[h] { - HeapCellValue::Atom(ref atom, _) if atom.is_char() => { - if let Some(c) = atom.as_str().chars().next() { - write!(&mut stream, "{}", c).unwrap(); - return return_from_clause!(self.last_call, self); - } else { - unreachable!() - } - } - _ => { + Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { + HeapCellValue::Atom(ref atom, _) if atom.is_char() => { + if let Some(c) = atom.as_str().chars().next() { + write!(&mut stream, "{}", c).unwrap(); + return return_from_clause!(self.last_call, self); + } else { + unreachable!() } } - } + _ => {} + }, Addr::Char(c) => { write!(&mut stream, "{}", c).unwrap(); return return_from_clause!(self.last_call, self); } - _ => { - } + _ => {} } let stub = MachineError::functor_stub(clause_name!("put_char"), 2); - let err = MachineError::type_error( - self.heap.h(), - ValidType::Character, - addr, - ); + let err = + MachineError::type_error(self.heap.h(), ValidType::Character, addr); return Err(self.error_form(err, stub)); } @@ -2172,7 +2032,6 @@ impl MachineState { if stream.options.stream_type == StreamType::Binary { for c in string.chars() { if c as u32 > 255 { - let stub = MachineError::functor_stub(clause_name!("$put_chars"), 2); let err = MachineError::type_error( @@ -2195,14 +2054,11 @@ impl MachineState { return return_from_clause!(self.last_call, self); } _ => { - let stub = MachineError::functor_stub( - clause_name!("$put_chars"), - 2, - ); + let stub = MachineError::functor_stub(clause_name!("$put_chars"), 2); - let addr = self.heap.to_unifiable( - HeapCellValue::Stream(stream.clone()), - ); + let addr = self + .heap + .to_unifiable(HeapCellValue::Stream(stream.clone())); return Err(self.error_form( MachineError::existence_error( @@ -2289,8 +2145,7 @@ impl MachineState { } } } - _ => { - } + _ => {} } let stub = MachineError::functor_stub(clause_name!("put_byte"), 2); @@ -2317,12 +2172,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - self.eof_action( - self[temp_v!(2)], - &mut stream, - clause_name!("get_byte"), - 2, - )?; + self.eof_action(self[temp_v!(2)], &mut stream, clause_name!("get_byte"), 2)?; if EOFAction::Reset != stream.options.eof_action { return return_from_clause!(self.last_call, self); @@ -2331,48 +2181,43 @@ impl MachineState { } } - let addr = - match self.store(self.deref(self[temp_v!(2)])) { - addr if addr.is_ref() => { - addr - } - addr => { - match Number::try_from((addr, &self.heap)) { - Ok(Number::Integer(n)) => { - if let Some(nb) = n.to_u8() { - Addr::Usize(nb as usize) - } else { - return Err(self.type_error( - ValidType::InByte, - addr, - clause_name!("get_byte"), - 2, - )); - } - } - Ok(Number::Fixnum(n)) => { - if let Ok(nb) = u8::try_from(n) { - Addr::Usize(nb as usize) - } else { - return Err(self.type_error( - ValidType::InByte, - addr, - clause_name!("get_byte"), - 2, - )); - } - } - _ => { - return Err(self.type_error( - ValidType::InByte, - addr, - clause_name!("get_byte"), - 2, - )); - } + let addr = match self.store(self.deref(self[temp_v!(2)])) { + addr if addr.is_ref() => addr, + addr => match Number::try_from((addr, &self.heap)) { + Ok(Number::Integer(n)) => { + if let Some(nb) = n.to_u8() { + Addr::Usize(nb as usize) + } else { + return Err(self.type_error( + ValidType::InByte, + addr, + clause_name!("get_byte"), + 2, + )); } } - }; + Ok(Number::Fixnum(n)) => { + if let Ok(nb) = u8::try_from(n) { + Addr::Usize(nb as usize) + } else { + return Err(self.type_error( + ValidType::InByte, + addr, + clause_name!("get_byte"), + 2, + )); + } + } + _ => { + return Err(self.type_error( + ValidType::InByte, + addr, + clause_name!("get_byte"), + 2, + )); + } + }, + }; loop { let mut b = [0u8; 1]; @@ -2419,9 +2264,9 @@ impl MachineState { if stream.at_end_of_stream() { let end_of_file = clause_name!("end_of_file"); - let end_of_file = self.heap.to_unifiable( - HeapCellValue::Atom(end_of_file, None), - ); + let end_of_file = self + .heap + .to_unifiable(HeapCellValue::Atom(end_of_file, None)); stream.set_past_end_of_stream(); @@ -2429,48 +2274,37 @@ impl MachineState { return return_from_clause!(self.last_call, self); } - let mut iter = self.open_parsing_stream( - stream.clone(), - "get_char", - 2, - )?; + let mut iter = self.open_parsing_stream(stream.clone(), "get_char", 2)?; - let addr = - match self.store(self.deref(self[temp_v!(2)])) { - addr if addr.is_ref() => { - addr - } - Addr::Con(h) if self.heap.atom_at(h) => { - match &self.heap[h] { - HeapCellValue::Atom(ref atom, _) if atom.is_char() => { - if let Some(c) = atom.as_str().chars().next() { - Addr::Char(c) - } else { - unreachable!() - } - } - culprit => { - return Err(self.type_error( - ValidType::InCharacter, - culprit.as_addr(h), - clause_name!("get_char"), - 2, - )); - } + let addr = match self.store(self.deref(self[temp_v!(2)])) { + addr if addr.is_ref() => addr, + Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { + HeapCellValue::Atom(ref atom, _) if atom.is_char() => { + if let Some(c) = atom.as_str().chars().next() { + Addr::Char(c) + } else { + unreachable!() } } - Addr::Char(d) => { - Addr::Char(d) - } culprit => { return Err(self.type_error( ValidType::InCharacter, - culprit, + culprit.as_addr(h), clause_name!("get_char"), 2, )); } - }; + }, + Addr::Char(d) => Addr::Char(d), + culprit => { + return Err(self.type_error( + ValidType::InCharacter, + culprit, + clause_name!("get_char"), + 2, + )); + } + }; loop { let result = iter.next(); @@ -2500,14 +2334,14 @@ impl MachineState { } else if self.fail { return Ok(()); } - }/* - _ => { - let stub = MachineError::functor_stub(clause_name!("get_char"), 2); - let err = MachineError::representation_error(RepFlag::Character); - let err = self.error_form(err, stub); + } /* + _ => { + let stub = MachineError::functor_stub(clause_name!("get_char"), 2); + let err = MachineError::representation_error(RepFlag::Character); + let err = self.error_form(err, stub); - return Err(err); - }*/ + return Err(err); + }*/ } } } @@ -2515,19 +2349,19 @@ impl MachineState { let stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "get_n_chars", 3)?; - let num = - match Number::try_from((self[temp_v!(2)], &self.heap)) { - Ok(Number::Fixnum(n)) => { - usize::try_from(n).unwrap() + let num = match Number::try_from((self[temp_v!(2)], &self.heap)) { + Ok(Number::Fixnum(n)) => usize::try_from(n).unwrap(), + Ok(Number::Integer(n)) => match n.to_usize() { + Some(u) => u, + _ => { + self.fail = true; + return Ok(()); } - Ok(Number::Integer(n)) => { - match n.to_usize() { - Some(u) => { u } - _ => { self.fail = true; return Ok(()); } - } - } - _ => { unreachable!() } - }; + }, + _ => { + unreachable!() + } + }; let mut string = String::new(); @@ -2539,23 +2373,20 @@ impl MachineState { string.push(c as char); } } else { - let mut iter = self.open_parsing_stream( - stream.clone(), - "get_n_chars", - 2, - )?; + let mut iter = self.open_parsing_stream(stream.clone(), "get_n_chars", 2)?; for _ in 0..num { - let result = iter.next(); + let result = iter.next(); - match result { - Some(Ok(c)) => { + match result { + Some(Ok(c)) => { string.push(c); - } - _ => { break; - } - } - } + } + _ => { + break; + } + } + } }; let string = self.heap.put_complete_string(&string); self.unify(self[temp_v!(3)], string); @@ -2582,9 +2413,9 @@ impl MachineState { if stream.at_end_of_stream() { let end_of_file = clause_name!("end_of_file"); - let end_of_file = self.heap.to_unifiable( - HeapCellValue::Atom(end_of_file, None), - ); + let end_of_file = self + .heap + .to_unifiable(HeapCellValue::Atom(end_of_file, None)); stream.set_past_end_of_stream(); @@ -2592,60 +2423,51 @@ impl MachineState { return return_from_clause!(self.last_call, self); } - let addr = - match self.store(self.deref(self[temp_v!(2)])) { - addr if addr.is_ref() => { - addr - } - addr => { - match Number::try_from((addr, &self.heap)) { - Ok(Number::Integer(n)) => { - let n = n.to_u32().and_then(|n| { - std::char::from_u32(n).and_then(|_| Some(n)) - }); + let addr = match self.store(self.deref(self[temp_v!(2)])) { + addr if addr.is_ref() => addr, + addr => match Number::try_from((addr, &self.heap)) { + Ok(Number::Integer(n)) => { + let n = n + .to_u32() + .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n))); - if let Some(n) = n { - Addr::Fixnum(n as isize) - } else { - return Err(self.representation_error( - RepFlag::InCharacterCode, - clause_name!("get_code"), - 2, - )); - } - } - Ok(Number::Fixnum(n)) => { - let n = u32::try_from(n).ok().and_then(|n| { - std::char::from_u32(n).and_then(|_| Some(n)) - }); - - if let Some(n) = n { - Addr::Fixnum(n as isize) - } else { - return Err(self.representation_error( - RepFlag::InCharacterCode, - clause_name!("get_code"), - 2, - )); - } - } - _ => { - return Err(self.type_error( - ValidType::Integer, - self[temp_v!(2)], - clause_name!("get_code"), - 2, - )); - } + if let Some(n) = n { + Addr::Fixnum(n as isize) + } else { + return Err(self.representation_error( + RepFlag::InCharacterCode, + clause_name!("get_code"), + 2, + )); } } - }; + Ok(Number::Fixnum(n)) => { + let n = u32::try_from(n) + .ok() + .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n))); - let mut iter = self.open_parsing_stream( - stream.clone(), - "get_code", - 2, - )?; + if let Some(n) = n { + Addr::Fixnum(n as isize) + } else { + return Err(self.representation_error( + RepFlag::InCharacterCode, + clause_name!("get_code"), + 2, + )); + } + } + _ => { + return Err(self.type_error( + ValidType::Integer, + self[temp_v!(2)], + clause_name!("get_code"), + 2, + )); + } + }, + }; + + let mut iter = self.open_parsing_stream(stream.clone(), "get_code", 2)?; loop { let result = iter.next(); @@ -2705,24 +2527,28 @@ impl MachineState { } } &SystemClauseType::NextStream => { - let prev_stream = - match self.store(self.deref(self[temp_v!(1)])) { - Addr::Stream(h) => { - if let HeapCellValue::Stream(ref stream) = &self.heap[h] { - stream.clone() - } else { - unreachable!() - } - } - _ => { + let prev_stream = match self.store(self.deref(self[temp_v!(1)])) { + Addr::Stream(h) => { + if let HeapCellValue::Stream(ref stream) = &self.heap[h] { + stream.clone() + } else { unreachable!() } - }; + } + _ => { + unreachable!() + } + }; - let mut next_stream = None; + let mut next_stream = None; let mut null_streams = BTreeSet::new(); - for stream in indices.streams.range(prev_stream.clone() ..).skip(1).cloned() { + for stream in indices + .streams + .range(prev_stream.clone()..) + .skip(1) + .cloned() + { if !stream.is_null_stream() { next_stream = Some(stream); break; @@ -2750,9 +2576,7 @@ impl MachineState { if !stream.is_output_stream() { let stub = MachineError::functor_stub(clause_name!("flush_output"), 1); - let addr = vec![ - HeapCellValue::Stream(stream) - ]; + let addr = vec![HeapCellValue::Stream(stream)]; let err = MachineError::permission_error( self.heap.h(), @@ -2769,14 +2593,11 @@ impl MachineState { &SystemClauseType::GetSingleChar => { let ctrl_c = KeyEvent { code: KeyCode::Char('c'), - modifiers: KeyModifiers::CONTROL + modifiers: KeyModifiers::CONTROL, }; let key = get_key(); if key == ctrl_c { - let stub = MachineError::functor_stub( - clause_name!("get_single_char"), - 1 - ); + let stub = MachineError::functor_stub(clause_name!("get_single_char"), 1); let err = MachineError::interrupt_error(); let err = self.error_form(err, stub); @@ -2786,7 +2607,7 @@ impl MachineState { KeyCode::Enter => '\n', KeyCode::Tab => '\t', KeyCode::Char(c) => c, - _ => unreachable!() + _ => unreachable!(), }; let a1 = self[temp_v!(1)]; @@ -2794,21 +2615,17 @@ impl MachineState { self.unify(Addr::Char(c), a1); } &SystemClauseType::HeadIsDynamic => { - let module_name = atom_from!( - self, - self.store(self.deref( - 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(self[temp_v!(2)])) { Addr::Str(s) => match &self.heap[s] { - &HeapCellValue::NamedStr(arity, ref name, ..) => - indices.is_dynamic_predicate(module_name, (name.clone(), arity)), + &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] { + if let HeapCellValue::Atom(name, _) = &self.heap[h] { indices.is_dynamic_predicate(module_name, (name.clone(), 0)) } else { unreachable!() @@ -2820,8 +2637,7 @@ impl MachineState { }; } &SystemClauseType::Close => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "close", 2)?; + let mut stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "close", 2)?; if !stream.is_input_stream() { stream.flush().unwrap(); // 8.11.6.1b) @@ -2830,15 +2646,19 @@ impl MachineState { indices.streams.remove(&stream); if stream == *current_input_stream { - *current_input_stream = indices.stream_aliases.get( - &clause_name!("user_input") - ).cloned().unwrap(); + *current_input_stream = indices + .stream_aliases + .get(&clause_name!("user_input")) + .cloned() + .unwrap(); indices.streams.insert(current_input_stream.clone()); } else if stream == *current_output_stream { - *current_output_stream = indices.stream_aliases.get( - &clause_name!("user_output") - ).cloned().unwrap(); + *current_output_stream = indices + .stream_aliases + .get(&clause_name!("user_output")) + .cloned() + .unwrap(); indices.streams.insert(current_output_stream.clone()); } @@ -2851,31 +2671,29 @@ impl MachineState { } } } - &SystemClauseType::CopyToLiftedHeap => { - match self.store(self.deref(self[temp_v!(1)])) { - Addr::Usize(lh_offset) => { - let copy_target = self[temp_v!(2)]; + &SystemClauseType::CopyToLiftedHeap => match self.store(self.deref(self[temp_v!(1)])) { + Addr::Usize(lh_offset) => { + let copy_target = self[temp_v!(2)]; - let old_threshold = self.copy_findall_solution(lh_offset, copy_target); - let new_threshold = self.lifted_heap.h() - lh_offset; + let old_threshold = self.copy_findall_solution(lh_offset, copy_target); + let new_threshold = self.lifted_heap.h() - lh_offset; - self.lifted_heap[old_threshold] = - HeapCellValue::Addr(Addr::HeapCell(new_threshold)); + self.lifted_heap[old_threshold] = + HeapCellValue::Addr(Addr::HeapCell(new_threshold)); - for addr in self.lifted_heap.iter_mut_from(old_threshold + 1) { - match addr { - HeapCellValue::Addr(ref mut addr) => { - *addr -= self.heap.h() + lh_offset; - } - _ => {} + for addr in self.lifted_heap.iter_mut_from(old_threshold + 1) { + match addr { + HeapCellValue::Addr(ref mut addr) => { + *addr -= self.heap.h() + lh_offset; } + _ => {} } } - _ => { - self.fail = true; - } } - } + _ => { + self.fail = true; + } + }, &SystemClauseType::DeleteAttribute => { let ls0 = self.store(self.deref(self[temp_v!(1)])); @@ -2893,7 +2711,7 @@ impl MachineState { let trail_ref = match old_addr { Addr::HeapCell(h) => TrailRef::AttrVarHeapLink(h), Addr::Lis(l) => TrailRef::AttrVarListLink(l1 + 1, l), - _ => unreachable!() + _ => unreachable!(), }; self.heap[l1 + 1] = HeapCellValue::Addr(tail); @@ -2953,11 +2771,11 @@ impl MachineState { match self.store(self.deref(self[temp_v!(2 + narity)])) { Addr::Str(a) => { if let HeapCellValue::NamedStr(arity, name, _) = self.heap.clone(a) { - for i in (arity + 1 .. arity + narity + 1).rev() { + for i in (arity + 1..arity + narity + 1).rev() { self.registers[i] = self.registers[i - arity]; } - for i in 1 .. arity + 1 { + for i in 1..arity + 1 { self.registers[i] = self.heap[a + i].as_addr(a + i); } @@ -2975,7 +2793,7 @@ impl MachineState { } } 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, @@ -2992,11 +2810,8 @@ impl MachineState { addr => { let stub = MachineError::functor_stub(clause_name!("(:)"), 2); - let type_error = MachineError::type_error( - self.heap.h(), - ValidType::Callable, - addr, - ); + let type_error = + MachineError::type_error(self.heap.h(), ValidType::Callable, addr); let type_error = self.error_form(type_error, stub); return Err(type_error); @@ -3014,8 +2829,7 @@ impl MachineState { Addr::AttrVar(h) => { self.attr_var_init.attr_var_queue.push(h); } - _ => { - } + _ => {} } } /* @@ -3033,8 +2847,8 @@ impl MachineState { match self.store(self.deref(a1)) { addr @ Addr::HeapCell(_) - | addr @ Addr::StackCell(..) - | addr @ Addr::AttrVar(_) => { + | addr @ Addr::StackCell(..) + | addr @ Addr::AttrVar(_) => { let mut iter = indices.code_dir.iter(); while let Some(((name, arity), _)) = iter.next() { @@ -3051,9 +2865,7 @@ impl MachineState { let db_ref = DBRef::NamedPred(name.clone(), *arity, spec); let r = addr.as_var().unwrap(); - let addr = self.heap.to_unifiable( - HeapCellValue::DBRef(db_ref) - ); + let addr = self.heap.to_unifiable(HeapCellValue::DBRef(db_ref)); self.bind(r, addr); @@ -3062,19 +2874,17 @@ impl MachineState { self.fail = true; } - Addr::Con(h) => { - match self.heap.clone(h) { - HeapCellValue::DBRef(DBRef::Op(..)) => { - self.fail = true; - } - HeapCellValue::DBRef(ref db_ref) => { - self.get_next_db_ref(indices, db_ref); - } - _ => { - self.fail = true; - } + Addr::Con(h) => match self.heap.clone(h) { + HeapCellValue::DBRef(DBRef::Op(..)) => { + self.fail = true; } - } + HeapCellValue::DBRef(ref db_ref) => { + self.get_next_db_ref(indices, db_ref); + } + _ => { + self.fail = true; + } + }, _ => { self.fail = true; } @@ -3085,8 +2895,8 @@ impl MachineState { match self.store(self.deref(a1)) { addr @ Addr::HeapCell(_) - | addr @ Addr::StackCell(..) - | addr @ Addr::AttrVar(_) => { + | addr @ Addr::StackCell(..) + | addr @ Addr::AttrVar(_) => { let mut unossified_op_dir = OssifiedOpDir::new(); unossified_op_dir.extend(indices.op_dir.iter().filter_map( @@ -3118,9 +2928,7 @@ impl MachineState { ); let r = addr.as_var().unwrap(); - let addr = self.heap.to_unifiable( - HeapCellValue::DBRef(db_ref) - ); + let addr = self.heap.to_unifiable(HeapCellValue::DBRef(db_ref)); self.bind(r, addr); } @@ -3130,19 +2938,17 @@ impl MachineState { } } } - Addr::Con(h) => { - match self.heap.clone(h) { - HeapCellValue::DBRef(DBRef::NamedPred(..)) => { - self.fail = true; - } - HeapCellValue::DBRef(ref db_ref) => { - self.get_next_db_ref(indices, db_ref); - } - _ => { - self.fail = true; - } + Addr::Con(h) => match self.heap.clone(h) { + HeapCellValue::DBRef(DBRef::NamedPred(..)) => { + self.fail = true; } - } + HeapCellValue::DBRef(ref db_ref) => { + self.get_next_db_ref(indices, db_ref); + } + _ => { + self.fail = true; + } + }, _ => { self.fail = true; } @@ -3152,27 +2958,23 @@ impl MachineState { let a1 = self[temp_v!(1)]; match self.store(self.deref(a1)) { - Addr::Con(h) => { - match self.heap.clone(h) { - HeapCellValue::DBRef(DBRef::NamedPred(name, arity, spec)) => { - let a2 = self[temp_v!(2)]; - let a3 = self[temp_v!(3)]; + Addr::Con(h) => match self.heap.clone(h) { + HeapCellValue::DBRef(DBRef::NamedPred(name, arity, spec)) => { + let a2 = self[temp_v!(2)]; + let a3 = self[temp_v!(3)]; - let atom = self.heap.to_unifiable( - HeapCellValue::Atom(name, spec) - ); + let atom = self.heap.to_unifiable(HeapCellValue::Atom(name, spec)); - self.unify(a2, atom); + self.unify(a2, atom); - if !self.fail { - self.unify(a3, Addr::Usize(arity)); - } - } - _ => { - self.fail = true; + if !self.fail { + self.unify(a3, Addr::Usize(arity)); } } - } + _ => { + self.fail = true; + } + }, _ => { self.fail = true; } @@ -3182,56 +2984,54 @@ impl MachineState { let a1 = self[temp_v!(1)]; match self.store(self.deref(a1)) { - Addr::Con(h) => { - match self.heap.clone(h) { - HeapCellValue::DBRef(DBRef::Op( - priority, - spec, - name, - _, - shared_op_desc, - )) => { - let prec = self[temp_v!(2)]; - let specifier = self[temp_v!(3)]; - let op = self[temp_v!(4)]; + Addr::Con(h) => match self.heap.clone(h) { + HeapCellValue::DBRef(DBRef::Op( + priority, + spec, + name, + _, + shared_op_desc, + )) => { + let prec = self[temp_v!(2)]; + let specifier = self[temp_v!(3)]; + let op = self[temp_v!(4)]; - let spec = match spec { - FX => "fx", - FY => "fy", - XF => "xf", - YF => "yf", - XFX => "xfx", - XFY => "xfy", - YFX => "yfx", - _ => { - self.fail = true; - return Ok(()); - } - }; - - let a3 = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!(spec), None) - ); - - let a4 = self.heap.to_unifiable( - HeapCellValue::Atom(name, Some(shared_op_desc)) - ); - - self.unify(Addr::Usize(priority), prec); - - if !self.fail { - self.unify(a3, specifier); + let spec = match spec { + FX => "fx", + FY => "fy", + XF => "xf", + YF => "yf", + XFX => "xfx", + XFY => "xfy", + YFX => "yfx", + _ => { + self.fail = true; + return Ok(()); } + }; - if !self.fail { - self.unify(a4, op); - } + let a3 = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!(spec), None)); + + let a4 = self + .heap + .to_unifiable(HeapCellValue::Atom(name, Some(shared_op_desc))); + + self.unify(Addr::Usize(priority), prec); + + if !self.fail { + self.unify(a3, specifier); } - _ => { - self.fail = true; + + if !self.fail { + self.unify(a4, op); } } - } + _ => { + self.fail = true; + } + }, _ => { self.fail = true; } @@ -3263,41 +3063,35 @@ impl MachineState { let priority = self.store(self.deref(priority)); - let priority = - match Number::try_from((priority, &self.heap)) { - Ok(Number::Integer(n)) => { - n.to_usize().unwrap() - } - Ok(Number::Fixnum(n)) => { - usize::try_from(n).unwrap() - } - _ => { - unreachable!(); - } - }; + let priority = match Number::try_from((priority, &self.heap)) { + Ok(Number::Integer(n)) => n.to_usize().unwrap(), + Ok(Number::Fixnum(n)) => usize::try_from(n).unwrap(), + _ => { + unreachable!(); + } + }; let specifier = match self.store(self.deref(specifier)) { - Addr::Con(h) if self.heap.atom_at(h) => + Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref specifier, _) = &self.heap[h] { specifier.clone() } else { unreachable!() - }, - _ => - unreachable!(), + } + } + _ => unreachable!(), }; let op = match self.store(self.deref(op)) { - Addr::Char(c) => - clause_name!(c.to_string(), self.atom_tbl), - Addr::Con(h) if self.heap.atom_at(h) => + Addr::Char(c) => 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() } else { unreachable!() - }, - _ => - unreachable!(), + } + } + _ => unreachable!(), }; let result = to_op_decl(priority, specifier.as_str(), op) @@ -3316,8 +3110,7 @@ impl MachineState { }); match result { - Ok(()) => { - } + Ok(()) => {} Err(e) => { // 8.14.3.3 l) let e = MachineError::session_error(self.heap.h(), e); @@ -3334,48 +3127,33 @@ impl MachineState { let reposition = self[temp_v!(6)]; let stream_type = self[temp_v!(7)]; - let options = - self.to_stream_options(alias, eof_action, reposition, stream_type); + let options = self.to_stream_options(alias, eof_action, reposition, stream_type); - let mut stream = - match self.store(self.deref(self[temp_v!(1)])) { - Addr::Con(h) if self.heap.atom_at(h) => { - match &self.heap[h] { - &HeapCellValue::Atom(ref atom, _) => { - self.stream_from_file_spec(atom.clone(), indices, &options)? - } - _ => { - unreachable!() - } - } - } - Addr::Char(c) => { - let atom = clause_name!(c.to_string(), self.atom_tbl); - self.stream_from_file_spec(atom, indices, &options)? - } - Addr::PStrLocation(h, n) => { - match &self.heap[h] { - &HeapCellValue::PartialString(_, true) => { - let mut heap_pstr_iter = - self.heap_pstr_iter(Addr::PStrLocation(h, n)); - - let file_spec = - clause_name!( - heap_pstr_iter.to_string(), - self.atom_tbl - ); - - self.stream_from_file_spec(file_spec, indices, &options)? - } - _ => { - self.stream_from_file_spec(clause_name!(""), indices, &options)? - } - } + let mut stream = match self.store(self.deref(self[temp_v!(1)])) { + Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { + &HeapCellValue::Atom(ref atom, _) => { + self.stream_from_file_spec(atom.clone(), indices, &options)? } _ => { - self.stream_from_file_spec(clause_name!(""), indices, &options)? + unreachable!() } - }; + }, + Addr::Char(c) => { + let atom = clause_name!(c.to_string(), self.atom_tbl); + self.stream_from_file_spec(atom, indices, &options)? + } + Addr::PStrLocation(h, n) => match &self.heap[h] { + &HeapCellValue::PartialString(_, true) => { + let mut heap_pstr_iter = self.heap_pstr_iter(Addr::PStrLocation(h, n)); + + let file_spec = clause_name!(heap_pstr_iter.to_string(), self.atom_tbl); + + self.stream_from_file_spec(file_spec, indices, &options)? + } + _ => self.stream_from_file_spec(clause_name!(""), indices, &options)?, + }, + _ => self.stream_from_file_spec(clause_name!(""), indices, &options)?, + }; stream.options = options; @@ -3405,27 +3183,23 @@ impl MachineState { } &SystemClauseType::GetAttributedVariableList => { let attr_var = self.store(self.deref(self[temp_v!(1)])); - let attr_var_list = - match attr_var { - Addr::AttrVar(h) => { - h + 1 - } - attr_var @ Addr::HeapCell(_) | - attr_var @ Addr::StackCell(..) => { - // create an AttrVar in the heap. - let h = self.heap.h(); + let attr_var_list = match attr_var { + Addr::AttrVar(h) => h + 1, + attr_var @ Addr::HeapCell(_) | attr_var @ Addr::StackCell(..) => { + // create an AttrVar in the heap. + let h = self.heap.h(); - self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h))); - self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1))); + self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h))); + self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1))); - self.bind(Ref::AttrVar(h), attr_var); - h + 1 - } - _ => { - self.fail = true; - return Ok(()); - } - }; + self.bind(Ref::AttrVar(h), attr_var); + h + 1 + } + _ => { + self.fail = true; + return Ok(()); + } + }; let list_addr = self[temp_v!(2)]; self.bind(Ref::HeapCell(attr_var_list), list_addr); @@ -3440,26 +3214,17 @@ impl MachineState { let addr = self[temp_v!(1)]; let addr = self.store(self.deref(addr)); - let b = - match addr { - Addr::Usize(b) => { - Some(b) - } + let b = match addr { + Addr::Usize(b) => Some(b), + _ => match Number::try_from((addr, &self.heap)) { + Ok(Number::Integer(n)) => n.to_usize(), + Ok(Number::Fixnum(n)) => usize::try_from(n).ok(), _ => { - match Number::try_from((addr, &self.heap)) { - Ok(Number::Integer(n)) => { - n.to_usize() - } - Ok(Number::Fixnum(n)) => { - usize::try_from(n).ok() - } - _ => { - self.fail = true; - return Ok(()); - } - } + self.fail = true; + return Ok(()); } - }; + }, + }; if let Some(b) = b { let iter = self.gather_attr_vars_created_since(b); @@ -3483,22 +3248,21 @@ impl MachineState { let p_functor = self.store(self.deref(self[temp_v!(2)])); let p = self.heap.to_local_code_ptr(&p_functor).unwrap(); - let num_cells = - match code_repo.lookup_instr(self.last_call, &CodePtr::Local(p)) { - Some(line) => { - let perm_vars = match line.as_ref() { - Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(), - _ => None - }; + let num_cells = match code_repo.lookup_instr(self.last_call, &CodePtr::Local(p)) { + Some(line) => { + let perm_vars = match line.as_ref() { + Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(), + _ => None, + }; - perm_vars.unwrap() - } - _ => unreachable!() - }; + perm_vars.unwrap() + } + _ => unreachable!(), + }; let mut addrs = vec![]; - for index in 1 .. num_cells + 1 { + for index in 1..num_cells + 1 { addrs.push(self.stack.index_and_frame(e)[index]); } @@ -3606,23 +3370,23 @@ impl MachineState { match self.flags.double_quotes { DoubleQuotes::Chars => { - let atom = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("chars"), None) - ); + let atom = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("chars"), None)); self.unify(a1, atom); } - DoubleQuotes::Atom => { - let atom = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("atom"), None) - ); + DoubleQuotes::Atom => { + let atom = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("atom"), None)); self.unify(a1, atom); } DoubleQuotes::Codes => { - let atom = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("codes"), None) - ); + let atom = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("codes"), None)); self.unify(a1, atom); } @@ -3648,8 +3412,7 @@ impl MachineState { } } } - None => { - } + None => {} }; self.fail = true; @@ -3666,7 +3429,9 @@ impl MachineState { // denominator must be 1. r.numer().to_i32().unwrap() } - _ => { unreachable!() } + _ => { + unreachable!() + } }; std::process::exit(code); @@ -3701,39 +3466,30 @@ impl MachineState { CWILCallPolicy::new_in_place(call_policy); } - let n = - match Number::try_from((a2, &self.heap)) { - Ok(Number::Integer(n)) => { - Integer::from(&*n.clone()) - } - Ok(Number::Fixnum(n)) => { - Integer::from(n) - } - _ => { - let stub = MachineError::functor_stub( - clause_name!("call_with_inference_limit"), - 3, - ); + let n = match Number::try_from((a2, &self.heap)) { + Ok(Number::Integer(n)) => Integer::from(&*n.clone()), + Ok(Number::Fixnum(n)) => Integer::from(n), + _ => { + let stub = MachineError::functor_stub( + clause_name!("call_with_inference_limit"), + 3, + ); - return Err(self.error_form( - MachineError::type_error( - self.heap.h(), - ValidType::Integer, - a2, - ), - stub, - )); - } - }; + return Err(self.error_form( + MachineError::type_error(self.heap.h(), ValidType::Integer, a2), + stub, + )); + } + }; match a1 { Addr::Usize(bp) | Addr::CutPoint(bp) => { match call_policy.downcast_mut::().ok() { Some(call_policy) => { let count = call_policy.add_limit(n, bp).clone(); - let count = self.heap.to_unifiable( - HeapCellValue::Integer(Rc::new(count)) - ); + let count = self + .heap + .to_unifiable(HeapCellValue::Integer(Rc::new(count))); let a3 = self[temp_v!(3)]; self.unify(a3, count); @@ -3756,7 +3512,7 @@ impl MachineState { match module { Addr::Con(h) => { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { self.fail = !indices.modules.contains_key(name); } else { unreachable!() @@ -3772,34 +3528,33 @@ impl MachineState { 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) => { - indices.get_predicate_code_index( + &HeapCellValue::NamedStr(arity, ref name, ref spec) => indices + .get_predicate_code_index( name.clone(), arity, module_name, spec.clone(), - ).is_some() - } + ) + .is_some(), _ => { unreachable!() } }, Addr::Con(h) if self.heap.atom_at(h) => { - if let &HeapCellValue::Atom(ref name, ref spec) = &self.heap[h] { - let spec = fetch_atom_op_spec( - name.clone(), - spec.clone(), - &indices.op_dir, - ); + if let &HeapCellValue::Atom(ref name, ref spec) = &self.heap[h] { + let spec = + fetch_atom_op_spec(name.clone(), spec.clone(), &indices.op_dir); - indices.get_predicate_code_index(name.clone(), 0, module_name, spec) - .is_some() + indices + .get_predicate_code_index(name.clone(), 0, module_name, spec) + .is_some() } else { unreachable!() } } head => { - let err = MachineError::type_error(self.heap.h(), ValidType::Callable, head); + let err = + MachineError::type_error(self.heap.h(), ValidType::Callable, head); let stub = MachineError::functor_stub(clause_name!("clause"), 2); return Err(self.error_form(err, stub)); @@ -3807,7 +3562,7 @@ impl MachineState { }; } &SystemClauseType::RedoAttrVarBinding => { - let var = self.store(self.deref(self[temp_v!(1)])); + let var = self.store(self.deref(self[temp_v!(1)])); let value = self.store(self.deref(self[temp_v!(2)])); match var { @@ -3872,34 +3627,33 @@ impl MachineState { indices.global_variables.insert(key, (ball, None)); } } - }, + } &SystemClauseType::ResetAttrVarState => { self.attr_var_init.reset(); } &SystemClauseType::RemoveCallPolicyCheck => { - let restore_default = - match call_policy.downcast_mut::().ok() { - Some(call_policy) => { - let a1 = self.store(self.deref(self[temp_v!(1)])); + let restore_default = match call_policy.downcast_mut::().ok() { + Some(call_policy) => { + let a1 = self.store(self.deref(self[temp_v!(1)])); - match a1 { - Addr::Usize(bp) | Addr::CutPoint(bp) => { - if call_policy.is_empty() && bp == self.b { - Some(call_policy.into_inner()) - } else { - None - } - } - _ => { - panic!("remove_call_policy_check: expected Usize in A1."); + match a1 { + Addr::Usize(bp) | Addr::CutPoint(bp) => { + if call_policy.is_empty() && bp == self.b { + Some(call_policy.into_inner()) + } else { + None } } + _ => { + panic!("remove_call_policy_check: expected Usize in A1."); + } } - None => panic!( - "remove_call_policy_check: requires \\ + } + None => panic!( + "remove_call_policy_check: requires \\ CWILCallPolicy." - ), - }; + ), + }; if let Some(new_policy) = restore_default { *call_policy = new_policy; @@ -3913,9 +3667,9 @@ impl MachineState { match a1 { Addr::Usize(bp) | Addr::CutPoint(bp) => { let count = call_policy.remove_limit(bp).clone(); - let count = self.heap.to_unifiable( - HeapCellValue::Integer(Rc::new(count)), - ); + let count = self + .heap + .to_unifiable(HeapCellValue::Integer(Rc::new(count))); let a2 = self[temp_v!(2)]; @@ -3955,7 +3709,7 @@ impl MachineState { let e = self.e; let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells; - for i in 1 .. frame_len - 1 { + for i in 1..frame_len - 1 { self[RegType::Temp(i)] = self.stack.index_and_frame(e)[i]; } @@ -3989,22 +3743,17 @@ impl MachineState { return Ok(()); } } - &SystemClauseType::SetCutPointByDefault(r) => { - deref_cut(self, r) - } + &SystemClauseType::SetCutPointByDefault(r) => deref_cut(self, r), &SystemClauseType::SetInput => { let addr = self.store(self.deref(self[temp_v!(1)])); let stream = self.get_stream_or_alias(addr, indices, "set_input", 1)?; if !stream.is_input_stream() { - let stub = MachineError::functor_stub( - clause_name!("set_input"), - 1, - ); + let stub = MachineError::functor_stub(clause_name!("set_input"), 1); - let user_alias = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("user"), None), - ); + let user_alias = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("user"), None)); let err = MachineError::permission_error( self.heap.h(), @@ -4023,14 +3772,11 @@ impl MachineState { let stream = self.get_stream_or_alias(addr, indices, "set_output", 1)?; if !stream.is_output_stream() { - let stub = MachineError::functor_stub( - clause_name!("set_input"), - 1, - ); + let stub = MachineError::functor_stub(clause_name!("set_input"), 1); - let user_alias = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("user"), None), - ); + let user_alias = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("user"), None)); let err = MachineError::permission_error( self.heap.h(), @@ -4044,29 +3790,26 @@ impl MachineState { *current_output_stream = stream; } - &SystemClauseType::SetDoubleQuotes => { - match self[temp_v!(1)] { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - self.flags.double_quotes = - match atom.as_str() { - "atom" => DoubleQuotes::Atom, - "chars" => DoubleQuotes::Chars, - "codes" => DoubleQuotes::Codes, - _ => { - self.fail = true; - return Ok(()); - } - }; - } else { - unreachable!() - } - } - _ => { - self.fail = true; + &SystemClauseType::SetDoubleQuotes => match self[temp_v!(1)] { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { + self.flags.double_quotes = match atom.as_str() { + "atom" => DoubleQuotes::Atom, + "chars" => DoubleQuotes::Chars, + "codes" => DoubleQuotes::Codes, + _ => { + self.fail = true; + return Ok(()); + } + }; + } else { + unreachable!() } } - } + _ => { + self.fail = true; + } + }, &SystemClauseType::InferenceLevel => { let a1 = self[temp_v!(1)]; let a2 = self.store(self.deref(self[temp_v!(2)])); @@ -4076,15 +3819,15 @@ impl MachineState { let prev_b = self.stack.index_or_frame(self.b).prelude.b; if prev_b <= bp { - let a2 = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("!"), None) - ); + let a2 = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("!"), None)); self.unify(a1, a2); } else { - let a2 = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("true"), None) - ); + let a2 = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("true"), None)); self.unify(a1, a2); } @@ -4147,54 +3890,54 @@ impl MachineState { self.unify(a1, a2); } -/* - &SystemClauseType::GetClause => { - let head = self[temp_v!(1)]; + /* + &SystemClauseType::GetClause => { + let head = self[temp_v!(1)]; - let subsection = match self.store(self.deref(head)) { - Addr::Str(s) => match &self.heap[s] { - &HeapCellValue::NamedStr(arity, ref name, ..) => { - indices.get_clause_subsection( - name.owning_module(), - name.clone(), - arity, - ) - } - _ => { + let subsection = match self.store(self.deref(head)) { + Addr::Str(s) => match &self.heap[s] { + &HeapCellValue::NamedStr(arity, ref name, ..) => { + indices.get_clause_subsection( + name.owning_module(), + name.clone(), + arity, + ) + } + _ => { + unreachable!() + } + }, + Addr::Con(h) if self.heap.atom_at(h) => { + if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] { + indices.get_clause_subsection( + name.owning_module(), + name.clone(), + 0, + ) + } else { unreachable!() - } - }, - Addr::Con(h) if self.heap.atom_at(h) => { - if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] { - indices.get_clause_subsection( - name.owning_module(), - name.clone(), - 0, - ) - } else { - unreachable!() - } - } - _ => { - unreachable!() - } - }; + } + } + _ => { + unreachable!() + } + }; - match subsection { - Some(dynamic_predicate_info) => { - self.execute_at_index( - 2, - dir_entry!(dynamic_predicate_info.clauses_subsection_p), - ); + match subsection { + Some(dynamic_predicate_info) => { + self.execute_at_index( + 2, + dir_entry!(dynamic_predicate_info.clauses_subsection_p), + ); - return Ok(()); - } - _ => { - unreachable!() - } - } - } -*/ + return Ok(()); + } + _ => { + unreachable!() + } + } + } + */ &SystemClauseType::GetCutPoint => { let a1 = self[temp_v!(1)]; let a2 = Addr::CutPoint(self.b0); @@ -4216,7 +3959,8 @@ impl MachineState { return Ok(()); } - let cp = (self.stack.index_and_frame(self.e).prelude.cp - 1).unwrap(); + let cp = + (self.stack.index_and_frame(self.e).prelude.cp - 1).unwrap(); let e = self.stack.index_and_frame(self.e).prelude.e; let e = Addr::Usize(e); @@ -4265,9 +4009,7 @@ impl MachineState { let addr = self.store(self.deref(self[temp_v!(1)])); let p = match self.heap.to_local_code_ptr(&addr) { - Some(p) => { - p + 1 - } + Some(p) => p + 1, None => { self.fail = true; return Ok(()); @@ -4290,19 +4032,15 @@ impl MachineState { let n = n.and_then(std::char::from_u32); self.fail = match n { - Some(c) => { - non_quoted_token(once(c)) - } - None => { - true - } + Some(c) => non_quoted_token(once(c)), + None => true, }; } Addr::Char(c) => { self.fail = non_quoted_token(once(c)); } Addr::Con(h) => { - if let HeapCellValue::Atom(atom, _) = &self.heap[h] { + if let HeapCellValue::Atom(atom, _) = &self.heap[h] { self.fail = non_quoted_token(atom.as_str().chars()); } } @@ -4319,8 +4057,7 @@ impl MachineState { readline::set_prompt(false); match result { - Ok(()) => { - } + Ok(()) => {} Err(e) => { *current_input_stream = readline::input_stream(); return Err(e); @@ -4330,12 +4067,7 @@ impl MachineState { &SystemClauseType::ReadTerm => { readline::set_prompt(false); - let stream = self.get_stream_or_alias( - self[temp_v!(1)], - indices, - "read_term", - 3, - )?; + let stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "read_term", 3)?; self.read_term(stream, indices)?; } @@ -4344,27 +4076,22 @@ impl MachineState { let chars = heap_pstr_iter.to_string(); if let Addr::EmptyList = heap_pstr_iter.focus() { - let term_write_result = - match self.read( - Stream::from(chars), - self.atom_tbl.clone(), - &indices.op_dir, - ) { - Ok(term_write_result) => { - term_write_result - } - Err(e) => { - let stub = MachineError::functor_stub( - clause_name!("read_term_from_chars"), - 2, - ); + let term_write_result = match self.read( + Stream::from(chars), + self.atom_tbl.clone(), + &indices.op_dir, + ) { + Ok(term_write_result) => term_write_result, + Err(e) => { + let stub = + MachineError::functor_stub(clause_name!("read_term_from_chars"), 2); - let h = self.heap.h(); - let e = MachineError::session_error(h, SessionError::from(e)); + let h = self.heap.h(); + let e = MachineError::session_error(h, SessionError::from(e)); - return Err(self.error_form(e, stub)); - } - }; + return Err(self.error_form(e, stub)); + } + }; let result = Addr::HeapCell(term_write_result.heap_loc); @@ -4382,9 +4109,9 @@ impl MachineState { self.reset_block(addr); } &SystemClauseType::ResetContinuationMarker => { - self[temp_v!(3)] = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!("none"), None) - ); + self[temp_v!(3)] = self + .heap + .to_unifiable(HeapCellValue::Atom(clause_name!("none"), None)); let h = self.heap.h(); @@ -4397,23 +4124,15 @@ impl MachineState { &SystemClauseType::SetSeed => { let seed = self.store(self.deref(self[temp_v!(1)])); - let seed = - match Number::try_from((seed, &self.heap)) { - Ok(Number::Fixnum(n)) => { - Integer::from(n) - } - Ok(Number::Integer(n)) => { - Integer::from(n.as_ref()) - } - Ok(Number::Rational(n)) - if n.denom() == &1 => { - n.numer().clone() - } - _ => { - self.fail = true; - return Ok(()); - } - }; + let seed = match Number::try_from((seed, &self.heap)) { + Ok(Number::Fixnum(n)) => Integer::from(n), + Ok(Number::Integer(n)) => Integer::from(n.as_ref()), + Ok(Number::Rational(n)) if n.denom() == &1 => n.numer().clone(), + _ => { + self.fail = true; + return Ok(()); + } + }; let mut rand = RANDOM_STATE.borrow_mut(); rand.seed(&seed); @@ -4443,64 +4162,50 @@ impl MachineState { let addr = self.store(self.deref(self[temp_v!(1)])); let port = self.store(self.deref(self[temp_v!(2)])); - let socket_atom = - match addr { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { - name.clone() - } else { - unreachable!() - } - } - _ => { - unreachable!() - } - }; - - let port = - match port { - Addr::Fixnum(n) => { - n.to_string() - } - Addr::Usize(n) => { - n.to_string() - } - Addr::Con(h) => { - match &self.heap[h] { - HeapCellValue::Atom(ref name, _) => { - name.as_str().to_string() - } - HeapCellValue::Integer(ref n) => { - n.to_string() - } - _ => { - unreachable!() - } - } - } - _ => { - unreachable!() - } - }; - - let socket_addr = - format!( - "{}:{}", - if socket_atom.as_str() == "" { - "127.0.0.1" + let socket_atom = match addr { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { + name.clone() } else { - socket_atom.as_str() - }, - port, - ); + unreachable!() + } + } + _ => { + unreachable!() + } + }; + + let port = match port { + Addr::Fixnum(n) => n.to_string(), + Addr::Usize(n) => n.to_string(), + Addr::Con(h) => match &self.heap[h] { + HeapCellValue::Atom(ref name, _) => name.as_str().to_string(), + HeapCellValue::Integer(ref n) => n.to_string(), + _ => { + unreachable!() + } + }, + _ => { + unreachable!() + } + }; + + let socket_addr = format!( + "{}:{}", + if socket_atom.as_str() == "" { + "127.0.0.1" + } else { + socket_atom.as_str() + }, + port, + ); let alias = self[temp_v!(4)]; let eof_action = self[temp_v!(5)]; let reposition = self[temp_v!(6)]; let stream_type = self[temp_v!(7)]; - let options = - self.to_stream_options(alias, eof_action, reposition, stream_type); + let options = self.to_stream_options(alias, eof_action, reposition, stream_type); if options.reposition { return Err(self.reposition_error("socket_client_open", 3)); @@ -4516,122 +4221,111 @@ impl MachineState { } } - let stream = - match TcpStream::connect(&socket_addr).map_err(|e| e.kind()) { - Ok(tcp_stream) => { - let socket_addr = clause_name!(socket_addr, self.atom_tbl); + let stream = match TcpStream::connect(&socket_addr).map_err(|e| e.kind()) { + Ok(tcp_stream) => { + let socket_addr = clause_name!(socket_addr, self.atom_tbl); - 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() - } else { - unreachable!() - } - } - _ => { + 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() + } else { unreachable!() } - }; - - match tls { - "false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) } - "true" => { let connector = TlsConnector::new().unwrap(); - let stream = match connector.connect(socket_atom.as_str(), tcp_stream) { - Ok(tls_stream) => { tls_stream } - Err(_) => { return Err(self.open_permission_error(addr, "socket_client_open", 3)); } - }; - - Stream::from_tls_stream(socket_addr, stream) - } - _ => { unreachable!() } } - }; + _ => { + unreachable!() + } + }; - stream.options = options; + match tls { + "false" => Stream::from_tcp_stream(socket_addr, tcp_stream), + "true" => { + let connector = TlsConnector::new().unwrap(); + let stream = + match connector.connect(socket_atom.as_str(), tcp_stream) { + Ok(tls_stream) => tls_stream, + Err(_) => { + return Err(self.open_permission_error( + addr, + "socket_client_open", + 3, + )); + } + }; - if let Some(ref alias) = &stream.options.alias { - indices.stream_aliases.insert(alias.clone(), stream.clone()); + Stream::from_tls_stream(socket_addr, stream) + } + _ => { + unreachable!() + } } + }; - indices.streams.insert(stream.clone()); + stream.options = options; - self.heap.to_unifiable(HeapCellValue::Stream(stream)) + if let Some(ref alias) = &stream.options.alias { + indices.stream_aliases.insert(alias.clone(), stream.clone()); } - Err(ErrorKind::PermissionDenied) => { - return Err(self.open_permission_error(addr, "socket_client_open", 3)); - } - Err(ErrorKind::NotFound) => { - let stub = MachineError::functor_stub( - clause_name!("socket_client_open"), - 3, - ); - let err = MachineError::existence_error( - self.heap.h(), - ExistenceError::SourceSink(addr), - ); + indices.streams.insert(stream.clone()); - return Err(self.error_form(err, stub)); - } - Err(_) => { - // for now, just fail. expand to meaningful error messages later. - self.fail = true; - return Ok(()); - } - }; + self.heap.to_unifiable(HeapCellValue::Stream(stream)) + } + Err(ErrorKind::PermissionDenied) => { + return Err(self.open_permission_error(addr, "socket_client_open", 3)); + } + Err(ErrorKind::NotFound) => { + let stub = + MachineError::functor_stub(clause_name!("socket_client_open"), 3); + + let err = MachineError::existence_error( + self.heap.h(), + ExistenceError::SourceSink(addr), + ); + + return Err(self.error_form(err, stub)); + } + Err(_) => { + // for now, just fail. expand to meaningful error messages later. + self.fail = true; + return Ok(()); + } + }; let stream_addr = self.store(self.deref(self[temp_v!(3)])); self.bind(stream_addr.as_var().unwrap(), stream); } &SystemClauseType::SocketServerOpen => { let addr = self.store(self.deref(self[temp_v!(1)])); - let socket_atom = - match addr { - Addr::EmptyList => { - "127.0.0.1".to_string() - } - Addr::Con(h) if self.heap.atom_at(h) => { - match &self.heap[h] { - HeapCellValue::Atom(ref name, _) => { - name.as_str().to_string() - } - _ => { - unreachable!() - } - } - } + let socket_atom = match addr { + Addr::EmptyList => "127.0.0.1".to_string(), + Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { + HeapCellValue::Atom(ref name, _) => name.as_str().to_string(), _ => { unreachable!() } - }; + }, + _ => { + unreachable!() + } + }; - let port = - match self.store(self.deref(self[temp_v!(2)])) { - Addr::Fixnum(n) => { - n.to_string() - } - Addr::Usize(n) => { - n.to_string() - } - Addr::Con(h) => { - match &self.heap[h] { - HeapCellValue::Integer(ref n) => { - n.to_string() - } - _ => { - unreachable!() - } - } - } - addr if addr.is_ref() => { - "0".to_string() - } + let port = match self.store(self.deref(self[temp_v!(2)])) { + Addr::Fixnum(n) => n.to_string(), + Addr::Usize(n) => n.to_string(), + Addr::Con(h) => match &self.heap[h] { + HeapCellValue::Integer(ref n) => n.to_string(), _ => { unreachable!() } - }; + }, + addr if addr.is_ref() => "0".to_string(), + _ => { + unreachable!() + } + }; let had_zero_port = &port == "0"; @@ -4648,7 +4342,8 @@ impl MachineState { if let Some(port) = port { ( - self.heap.to_unifiable(HeapCellValue::TcpListener(tcp_listener)), + self.heap + .to_unifiable(HeapCellValue::TcpListener(tcp_listener)), port as usize, ) } else { @@ -4678,8 +4373,7 @@ impl MachineState { let reposition = self[temp_v!(6)]; let stream_type = self[temp_v!(7)]; - let options = - self.to_stream_options(alias, eof_action, reposition, stream_type); + let options = self.to_stream_options(alias, eof_action, reposition, stream_type); if options.reposition { return Err(self.reposition_error("socket_server_accept", 4)); @@ -4696,58 +4390,55 @@ impl MachineState { } match self.store(self.deref(self[temp_v!(1)])) { - Addr::TcpListener(h) => { - match &mut self.heap[h] { - HeapCellValue::TcpListener(ref mut tcp_listener) => { - match tcp_listener.accept().ok() { - Some((tcp_stream, socket_addr)) => { - let client = - clause_name!(format!("{}", socket_addr), self.atom_tbl); + Addr::TcpListener(h) => match &mut self.heap[h] { + HeapCellValue::TcpListener(ref mut tcp_listener) => { + match tcp_listener.accept().ok() { + Some((tcp_stream, socket_addr)) => { + let client = + clause_name!(format!("{}", socket_addr), self.atom_tbl); - let mut tcp_stream = - Stream::from_tcp_stream(client.clone(), tcp_stream); + let mut tcp_stream = + Stream::from_tcp_stream(client.clone(), tcp_stream); - tcp_stream.options = options; + tcp_stream.options = options; - if let Some(ref alias) = &tcp_stream.options.alias { - indices.stream_aliases.insert( - alias.clone(), - tcp_stream.clone(), - ); - } - - indices.streams.insert(tcp_stream.clone()); - - let tcp_stream = - self.heap.to_unifiable(HeapCellValue::Stream(tcp_stream)); - - let client = - self.heap.to_unifiable(HeapCellValue::Atom(client, None)); - - let client_addr = self.store(self.deref(self[temp_v!(2)])); - let stream_addr = self.store(self.deref(self[temp_v!(3)])); - - self.bind(client_addr.as_var().unwrap(), client); - self.bind(stream_addr.as_var().unwrap(), tcp_stream); - } - None => { - self.fail = true; - return Ok(()); + if let Some(ref alias) = &tcp_stream.options.alias { + indices + .stream_aliases + .insert(alias.clone(), tcp_stream.clone()); } + + indices.streams.insert(tcp_stream.clone()); + + let tcp_stream = + self.heap.to_unifiable(HeapCellValue::Stream(tcp_stream)); + + let client = + self.heap.to_unifiable(HeapCellValue::Atom(client, None)); + + let client_addr = self.store(self.deref(self[temp_v!(2)])); + let stream_addr = self.store(self.deref(self[temp_v!(3)])); + + self.bind(client_addr.as_var().unwrap(), client); + self.bind(stream_addr.as_var().unwrap(), tcp_stream); + } + None => { + self.fail = true; + return Ok(()); } } - culprit => { - let culprit = culprit.as_addr(h); - - return Err(self.type_error( - ValidType::TcpListener, - culprit, - clause_name!("socket_server_accept"), - 4, - )); - } } - } + culprit => { + let culprit = culprit.as_addr(h); + + return Err(self.type_error( + ValidType::TcpListener, + culprit, + clause_name!("socket_server_accept"), + 4, + )); + } + }, culprit => { return Err(self.type_error( ValidType::TcpListener, @@ -4775,12 +4466,8 @@ impl MachineState { } } &SystemClauseType::SetStreamPosition => { - let mut stream = self.get_stream_or_alias( - self[temp_v!(1)], - indices, - "set_stream_position", - 2, - )?; + let mut stream = + self.get_stream_or_alias(self[temp_v!(1)], indices, "set_stream_position", 2)?; if !stream.options.reposition { let stub = MachineError::functor_stub(clause_name!("set_stream_position"), 2); @@ -4797,132 +4484,98 @@ impl MachineState { let position = self.store(self.deref(self[temp_v!(2)])); - let position = - match Number::try_from((position, &self.heap)) { - Ok(Number::Fixnum(n)) => { - n as u64 + let position = match Number::try_from((position, &self.heap)) { + Ok(Number::Fixnum(n)) => n as u64, + Ok(Number::Integer(n)) => { + if let Some(n) = n.to_u64() { + n + } else { + self.fail = true; + return Ok(()); } - Ok(Number::Integer(n)) => { - if let Some(n) = n.to_u64() { - n - } else { - self.fail = true; - return Ok(()); - } - } - _ => { - unreachable!() - } - }; + } + _ => { + unreachable!() + } + }; stream.set_position(position); } &SystemClauseType::StreamProperty => { - let mut stream = self.get_stream_or_alias( - self[temp_v!(1)], - indices, - "stream_property", - 2, - )?; + let mut stream = + self.get_stream_or_alias(self[temp_v!(1)], indices, "stream_property", 2)?; - let property = - match self.store(self.deref(self[temp_v!(2)])) { - Addr::Con(h) if self.heap.atom_at(h) => { - match &self.heap[h] { - HeapCellValue::Atom(ref name, _) => { - match name.as_str() { - "file_name" => { - if let Some(file_name) = stream.file_name() { - HeapCellValue::Atom( - file_name, - None, - ) - } else { - self.fail = true; - return Ok(()); - } - } - "mode" => { - HeapCellValue::Atom( - clause_name!(stream.mode()), - None, - ) - } - "direction" => { - HeapCellValue::Atom( - if stream.is_input_stream() && stream.is_output_stream() { - clause_name!("input_output") - } else if stream.is_input_stream() { - clause_name!("input") - } else { - clause_name!("output") - }, - None, - ) - } - "alias" => { - if let Some(alias) = &stream.options.alias { - HeapCellValue::Atom( - alias.clone(), - None, - ) - } else { - self.fail = true; - return Ok(()); - } - } - "position" => { - if let Some(position) = stream.position() { - HeapCellValue::Addr(Addr::Usize(position as usize)) - } else { - self.fail = true; - return Ok(()); - } - } - "end_of_stream" => { - let end_of_stream_pos = stream.position_relative_to_end(); - - HeapCellValue::Atom( - clause_name!(end_of_stream_pos.as_str()), - None, - ) - } - "eof_action" => { - HeapCellValue::Atom( - clause_name!(stream.options.eof_action.as_str()), - None, - ) - } - "reposition" => { - HeapCellValue::Atom( - clause_name!(if stream.options.reposition { - "true" - } else { - "false" - }), - None, - ) - } - "type" => { - HeapCellValue::Atom( - clause_name!(stream.options.stream_type.as_property_str()), - None, - ) - } - _ => { - unreachable!() - } - } - } - _ => { - unreachable!() + let property = match self.store(self.deref(self[temp_v!(2)])) { + Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { + HeapCellValue::Atom(ref name, _) => match name.as_str() { + "file_name" => { + if let Some(file_name) = stream.file_name() { + HeapCellValue::Atom(file_name, None) + } else { + self.fail = true; + return Ok(()); } } - } + "mode" => HeapCellValue::Atom(clause_name!(stream.mode()), None), + "direction" => HeapCellValue::Atom( + if stream.is_input_stream() && stream.is_output_stream() { + clause_name!("input_output") + } else if stream.is_input_stream() { + clause_name!("input") + } else { + clause_name!("output") + }, + None, + ), + "alias" => { + if let Some(alias) = &stream.options.alias { + HeapCellValue::Atom(alias.clone(), None) + } else { + self.fail = true; + return Ok(()); + } + } + "position" => { + if let Some(position) = stream.position() { + HeapCellValue::Addr(Addr::Usize(position as usize)) + } else { + self.fail = true; + return Ok(()); + } + } + "end_of_stream" => { + let end_of_stream_pos = stream.position_relative_to_end(); + + HeapCellValue::Atom(clause_name!(end_of_stream_pos.as_str()), None) + } + "eof_action" => HeapCellValue::Atom( + clause_name!(stream.options.eof_action.as_str()), + None, + ), + "reposition" => HeapCellValue::Atom( + clause_name!(if stream.options.reposition { + "true" + } else { + "false" + }), + None, + ), + "type" => HeapCellValue::Atom( + clause_name!(stream.options.stream_type.as_property_str()), + None, + ), + _ => { + unreachable!() + } + }, _ => { unreachable!() } - }; + }, + _ => { + unreachable!() + } + }; let property = self.heap.to_unifiable(property); self.unify(self[temp_v!(3)], property); @@ -4991,8 +4644,7 @@ impl MachineState { self.unify(value, Addr::HeapCell(h)); } - &SystemClauseType::Succeed => { - } + &SystemClauseType::Succeed => {} &SystemClauseType::TermAttributedVariables => { let seen_vars = self.attr_vars_of_term(self[temp_v!(1)]); let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); @@ -5001,7 +4653,7 @@ impl MachineState { } &SystemClauseType::TermVariables => { let a1 = self[temp_v!(1)]; - let mut seen_set = IndexSet::new(); + let mut seen_set = IndexSet::new(); let mut seen_vars = vec![]; for addr in self.acyclic_pre_order_iter(a1) { @@ -5016,10 +4668,8 @@ impl MachineState { } &SystemClauseType::TruncateLiftedHeapTo => { match self.store(self.deref(self[temp_v!(1)])) { - Addr::Usize(lh_offset) => - self.lifted_heap.truncate(lh_offset), - _ => - self.fail = true, + Addr::Usize(lh_offset) => self.lifted_heap.truncate(lh_offset), + _ => self.fail = true, } } &SystemClauseType::UnifyWithOccursCheck => { @@ -5051,12 +4701,9 @@ impl MachineState { self.fail = self.structural_eq_test(); } &SystemClauseType::WAMInstructions => { - let module_name = atom_from!( - self, - self.store(self.deref(self[temp_v!(1)])) - ); + let module_name = atom_from!(self, self.store(self.deref(self[temp_v!(1)]))); - let name = self[temp_v!(2)]; + let name = self[temp_v!(2)]; let arity = self[temp_v!(3)]; let name = match self.store(self.deref(name)) { @@ -5074,18 +4721,13 @@ impl MachineState { let arity = self.store(self.deref(arity)); - let arity = - match Number::try_from((arity, &self.heap)) { - Ok(Number::Fixnum(n)) => { - Integer::from(n) - } - Ok(Number::Integer(n)) => { - Integer::from(n.as_ref()) - } - _ => { - unreachable!() - } - }; + let arity = match Number::try_from((arity, &self.heap)) { + Ok(Number::Fixnum(n)) => Integer::from(n), + Ok(Number::Integer(n)) => Integer::from(n.as_ref()), + _ => { + unreachable!() + } + }; let key = (name.clone(), arity.to_usize().unwrap()); @@ -5099,11 +4741,9 @@ impl MachineState { let err = MachineError::session_error( h, - SessionError::from( - CompilationError::InvalidModuleResolution( - module_name - ) - ), + SessionError::from(CompilationError::InvalidModuleResolution( + module_name, + )), ); let err = self.error_form(err, stub); @@ -5114,50 +4754,45 @@ impl MachineState { }, }; - let first_idx = - match first_idx { - Some(ref idx) if idx.local().is_some() => { - if let Some(idx) = idx.local() { - idx - } else { - unreachable!() - } + 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 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 = MachineError::existence_error( + h, + ExistenceError::Procedure(name, arity), + ); - let err = self.error_form(err, stub); + let err = self.error_form(err, stub); - self.throw_exception(err); - return Ok(()); - } - }; + 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 old_len = functors.len(); - instr.enqueue_functors(h, &mut functors); - let new_len = functors.len(); + walk_code(&code_repo.code, first_idx, |instr| { + let old_len = functors.len(); + instr.enqueue_functors(h, &mut functors); + let new_len = functors.len(); - for index in old_len .. new_len { - functor_list.push(Addr::HeapCell(h)); - h += functors[index].len(); - } - }, - ); + for index in old_len..new_len { + functor_list.push(Addr::HeapCell(h)); + h += functors[index].len(); + } + }); for functor in functors { self.heap.extend(functor.into_iter()); @@ -5169,12 +4804,8 @@ impl MachineState { self.unify(listing, listing_var); } &SystemClauseType::WriteTerm => { - let mut stream = self.get_stream_or_alias( - self[temp_v!(1)], - indices, - "write_term", - 3, - )?; + let mut stream = + self.get_stream_or_alias(self[temp_v!(1)], indices, "write_term", 3)?; self.check_stream_properties( &mut stream, @@ -5184,14 +4815,13 @@ impl MachineState { 3, )?; - let opt_err = - if !stream.is_output_stream() { - Some("stream") // 8.14.2.3 g) - } else if stream.options.stream_type == StreamType::Binary { - Some("binary_stream") // 8.14.2.3 h) - } else { - None - }; + let opt_err = if !stream.is_output_stream() { + Some("stream") // 8.14.2.3 g) + } else if stream.options.stream_type == StreamType::Binary { + Some("binary_stream") // 8.14.2.3 h) + } else { + None + }; if let Some(err_string) = opt_err { return Err(self.stream_permission_error( @@ -5205,22 +4835,18 @@ impl MachineState { let addr = self[temp_v!(2)]; - let printer = - match self.write_term(&indices.op_dir)? { - None => { - self.fail = true; - return Ok(()); - } - Some(printer) => { - printer - } - }; + let printer = match self.write_term(&indices.op_dir)? { + None => { + self.fail = true; + return Ok(()); + } + Some(printer) => printer, + }; let output = printer.print(addr); match write!(&mut stream, "{}", output.result()) { - Ok(_) => { - } + Ok(_) => {} Err(_) => { let stub = MachineError::functor_stub(clause_name!("open"), 4); let err = MachineError::existence_error( @@ -5237,16 +4863,13 @@ impl MachineState { &SystemClauseType::WriteTermToChars => { let addr = self[temp_v!(2)]; - let printer = - match self.write_term(&indices.op_dir)? { - None => { - self.fail = true; - return Ok(()); - } - Some(printer) => { - printer - } - }; + let printer = match self.write_term(&indices.op_dir)? { + None => { + self.fail = true; + return Ok(()); + } + Some(printer) => printer, + }; let result = printer.print(addr).result(); let chars = self.heap.put_complete_string(&result); @@ -5262,8 +4885,7 @@ impl MachineState { &SystemClauseType::ScryerPrologVersion => { use crate::git_version::git_version; let version = self[temp_v!(1)]; - let buffer = - git_version!(cargo_prefix = "cargo:", fallback = "unknown"); + let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown"); let chars = buffer.chars().map(|c| Addr::Char(c)); let result = Addr::HeapCell(self.heap.to_list(chars)); self.unify(version, result); @@ -5273,8 +4895,7 @@ impl MachineState { let mut bytes: [u8; 1] = [0]; match rng().fill(&mut bytes) { - Ok(()) => { - } + Ok(()) => {} Err(_) => { // the error payload here is of type 'Unspecified', // which contains no information whatsoever. So, for now, @@ -5284,9 +4905,9 @@ impl MachineState { } } - let byte = self.heap.to_unifiable( - HeapCellValue::Integer(Rc::new(Integer::from(bytes[0]))) - ); + let byte = self + .heap + .to_unifiable(HeapCellValue::Integer(Rc::new(Integer::from(bytes[0])))); self.unify(arg, byte); } @@ -5296,41 +4917,120 @@ impl MachineState { let algorithm = self.atom_argument_to_string(4); - let ints_list = - match algorithm.as_str() { - "sha3_224" => { let mut context = Sha3_224::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - "sha3_256" => { let mut context = Sha3_256::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - "sha3_384" => { let mut context = Sha3_384::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - "sha3_512" => { let mut context = Sha3_512::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - "blake2s256" => { let mut context = Blake2s::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - "blake2b512" => { let mut context = Blake2b::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - "ripemd160" => { let mut context = Ripemd160::new(); - context.input(&bytes); - Addr::HeapCell(self.heap.to_list(context.result().as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) } - _ => { let ints = digest::digest( - match algorithm.as_str() { - "sha256" => { &digest::SHA256 } - "sha384" => { &digest::SHA384 } - "sha512" => { &digest::SHA512 } - "sha512_256" => { &digest::SHA512_256 } - _ => { unreachable!() } - }, - &bytes); - Addr::HeapCell(self.heap.to_list(ints.as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) - } - }; + let ints_list = match algorithm.as_str() { + "sha3_224" => { + let mut context = Sha3_224::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + "sha3_256" => { + let mut context = Sha3_256::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + "sha3_384" => { + let mut context = Sha3_384::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + "sha3_512" => { + let mut context = Sha3_512::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + "blake2s256" => { + let mut context = Blake2s::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + "blake2b512" => { + let mut context = Blake2b::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + "ripemd160" => { + let mut context = Ripemd160::new(); + context.input(&bytes); + Addr::HeapCell( + self.heap.to_list( + context + .result() + .as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + _ => { + let ints = digest::digest( + match algorithm.as_str() { + "sha256" => &digest::SHA256, + "sha384" => &digest::SHA384, + "sha512" => &digest::SHA512, + "sha512_256" => &digest::SHA512_256, + _ => { + unreachable!() + } + }, + &bytes, + ); + Addr::HeapCell( + self.heap.to_list( + ints.as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + } + }; self.unify(self[temp_v!(3)], ints_list); } @@ -5346,38 +5046,51 @@ impl MachineState { let length = self.store(self.deref(self[temp_v!(6)])); - let length = - match Number::try_from((length, &self.heap)) { - Ok(Number::Fixnum(n)) => { - usize::try_from(n).unwrap() + let length = match Number::try_from((length, &self.heap)) { + Ok(Number::Fixnum(n)) => usize::try_from(n).unwrap(), + Ok(Number::Integer(n)) => match n.to_usize() { + Some(u) => u, + _ => { + self.fail = true; + return Ok(()); } - Ok(Number::Integer(n)) => { - match n.to_usize() { - Some(u) => { u } - _ => { self.fail = true; return Ok(()); } - } + }, + _ => { + unreachable!() + } + }; + + let ints_list = { + let digest_alg = match algorithm.as_str() { + "sha256" => hkdf::HKDF_SHA256, + "sha384" => hkdf::HKDF_SHA384, + "sha512" => hkdf::HKDF_SHA512, + _ => { + self.fail = true; + return Ok(()); } - _ => { unreachable!() } }; + let salt = hkdf::Salt::new(digest_alg, &salt); + let mut bytes: Vec = Vec::new(); + bytes.resize(length, 0); + match salt.extract(&data).expand(&[&info[..]], MyKey(length)) { + Ok(r) => { + r.fill(&mut bytes).unwrap(); + } + _ => { + self.fail = true; + return Ok(()); + } + } - let ints_list = - { let digest_alg = - match algorithm.as_str() { - "sha256" => { hkdf::HKDF_SHA256 } - "sha384" => { hkdf::HKDF_SHA384 } - "sha512" => { hkdf::HKDF_SHA512 } - _ => { self.fail = true; return Ok(()); } - }; - let salt = hkdf::Salt::new(digest_alg, &salt); - let mut bytes : Vec = Vec::new(); - bytes.resize(length, 0); - match salt.extract(&data).expand(&[&info[..]], MyKey(length)) { - Ok(r) => { r.fill(&mut bytes).unwrap(); } - _ => { self.fail = true; return Ok(()); } - } - - Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) - }; + Addr::HeapCell( + self.heap.to_list( + bytes + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + }; self.unify(self[temp_v!(7)], ints_list); } @@ -5389,33 +5102,38 @@ impl MachineState { let iterations = self.store(self.deref(self[temp_v!(3)])); - let iterations = - match Number::try_from((iterations, &self.heap)) { - Ok(Number::Fixnum(n)) => { - u64::try_from(n).unwrap() + let iterations = match Number::try_from((iterations, &self.heap)) { + Ok(Number::Fixnum(n)) => u64::try_from(n).unwrap(), + Ok(Number::Integer(n)) => match n.to_u64() { + Some(i) => i, + None => { + self.fail = true; + return Ok(()); } - Ok(Number::Integer(n)) => { - match n.to_u64() { - Some(i) => { i } - None => { - self.fail = true; - return Ok(()); - } - } - } - _ => { - unreachable!() - } - }; + }, + _ => { + unreachable!() + } + }; - let ints_list = - { let mut bytes = [0u8; digest::SHA512_OUTPUT_LEN]; - pbkdf2::derive(pbkdf2::PBKDF2_HMAC_SHA512, - NonZeroU32::new(iterations as u32).unwrap(), &salt, - &data, &mut bytes); + let ints_list = { + let mut bytes = [0u8; digest::SHA512_OUTPUT_LEN]; + pbkdf2::derive( + pbkdf2::PBKDF2_HMAC_SHA512, + NonZeroU32::new(iterations as u32).unwrap(), + &salt, + &data, + &mut bytes, + ); - Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))) - }; + Addr::HeapCell( + self.heap.to_list( + bytes + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ) + }; self.unify(self[temp_v!(4)], ints_list); } @@ -5433,19 +5151,30 @@ impl MachineState { let key = aead::LessSafeKey::new(unbound_key); let mut in_out = data.clone(); - let tag = - match key.seal_in_place_separate_tag(nonce, aead::Aad::from(aad), &mut in_out) { - Ok(d) => { d } - _ => { self.fail = true; return Ok(()); } - }; + let tag = match key.seal_in_place_separate_tag( + nonce, + aead::Aad::from(aad), + &mut in_out, + ) { + Ok(d) => d, + _ => { + self.fail = true; + return Ok(()); + } + }; - let tag_list = - Addr::HeapCell(self.heap.to_list(tag.as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))); + let tag_list = Addr::HeapCell( + self.heap.to_list( + tag.as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ); let complete_string = { - let buffer = String::from_iter(in_out.iter().map(|b| *b as char)); - self.heap.put_complete_string(&buffer) - }; + let buffer = String::from_iter(in_out.iter().map(|b| *b as char)); + self.heap.put_complete_string(&buffer) + }; self.unify(self[temp_v!(6)], tag_list); self.unify(self[temp_v!(7)], complete_string); @@ -5466,47 +5195,53 @@ impl MachineState { let mut in_out = data.clone(); let complete_string = { - let decrypted_data = - match key.open_in_place(nonce, aead::Aad::from(aad), &mut in_out) { - Ok(d) => { d } - _ => { self.fail = true; return Ok(()); } - }; + let decrypted_data = + match key.open_in_place(nonce, aead::Aad::from(aad), &mut in_out) { + Ok(d) => d, + _ => { + self.fail = true; + return Ok(()); + } + }; - let buffer = match encoding.as_str() { - "octet" => { String::from_iter(decrypted_data.iter().map(|b| *b as char)) } - "utf8" => { match String::from_utf8(decrypted_data.to_vec()) { - Ok(str) => { str } - _ => { self.fail = true; return Ok(()); } - } - } - _ => { unreachable!() } - }; + let buffer = match encoding.as_str() { + "octet" => String::from_iter(decrypted_data.iter().map(|b| *b as char)), + "utf8" => match String::from_utf8(decrypted_data.to_vec()) { + Ok(str) => str, + _ => { + self.fail = true; + return Ok(()); + } + }, + _ => { + unreachable!() + } + }; - self.heap.put_complete_string(&buffer) - }; + self.heap.put_complete_string(&buffer) + }; self.unify(self[temp_v!(6)], complete_string); } &SystemClauseType::CryptoCurveScalarMult => { let curve = self.atom_argument_to_string(1); let curve_id = match curve.as_str() { - "secp112r1" => { Nid::SECP112R1 } - "secp256k1" => { Nid::SECP256K1 } - _ => { unreachable!() } - }; + "secp112r1" => Nid::SECP112R1, + "secp256k1" => Nid::SECP256K1, + _ => { + unreachable!() + } + }; let scalar = self.store(self.deref(self[temp_v!(2)])); - let scalar = - match Number::try_from((scalar, &self.heap)) { - Ok(Number::Fixnum(n)) => { - Integer::from(n) - } - Ok(Number::Integer(n)) => { - Integer::from(&*n.clone()) - } - _ => { unreachable!() } - }; + let scalar = match Number::try_from((scalar, &self.heap)) { + Ok(Number::Fixnum(n)) => Integer::from(n), + Ok(Number::Integer(n)) => Integer::from(&*n.clone()), + _ => { + unreachable!() + } + }; let stub = MachineError::functor_stub(clause_name!("crypto_curve_scalar_mult"), 5); let qbytes = self.integers_to_bytevec(temp_v!(3), stub); @@ -5520,9 +5255,15 @@ impl MachineState { let mut rx = BigNum::new().unwrap(); let mut ry = BigNum::new().unwrap(); - result.affine_coordinates_gfp(&group, &mut rx, &mut ry, &mut bnctx).ok(); - let sx = self.heap.put_complete_string(&rx.to_dec_str().unwrap().to_string()); - let sy = self.heap.put_complete_string(&ry.to_dec_str().unwrap().to_string()); + result + .affine_coordinates_gfp(&group, &mut rx, &mut ry, &mut bnctx) + .ok(); + let sx = self + .heap + .put_complete_string(&rx.to_dec_str().unwrap().to_string()); + let sy = self + .heap + .put_complete_string(&ry.to_dec_str().unwrap().to_string()); self.unify(self[temp_v!(4)], sx); self.unify(self[temp_v!(5)], sy); @@ -5530,9 +5271,9 @@ impl MachineState { &SystemClauseType::Ed25519NewKeyPair => { let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap(); let complete_string = { - let buffer = String::from_iter(pkcs8_bytes.as_ref().iter().map(|b| *b as char)); - self.heap.put_complete_string(&buffer) - }; + let buffer = String::from_iter(pkcs8_bytes.as_ref().iter().map(|b| *b as char)); + self.heap.put_complete_string(&buffer) + }; self.unify(self[temp_v!(1)], complete_string); } @@ -5540,14 +5281,19 @@ impl MachineState { let bytes = self.string_encoding_bytes(1, "octet"); let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&bytes) { - Ok(kp) => { kp } - _ => { self.fail = true; return Ok(()); } - }; + Ok(kp) => kp, + _ => { + self.fail = true; + return Ok(()); + } + }; let complete_string = { - let buffer = String::from_iter(key_pair.public_key().as_ref().iter().map(|b| *b as char)); - self.heap.put_complete_string(&buffer) - }; + let buffer = String::from_iter( + key_pair.public_key().as_ref().iter().map(|b| *b as char), + ); + self.heap.put_complete_string(&buffer) + }; self.unify(self[temp_v!(2)], complete_string); } @@ -5557,14 +5303,22 @@ impl MachineState { let data = self.string_encoding_bytes(2, &encoding); let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&key) { - Ok(kp) => { kp } - _ => { self.fail = true; return Ok(()); } - }; + Ok(kp) => kp, + _ => { + self.fail = true; + return Ok(()); + } + }; let sig = key_pair.sign(&data); - let sig_list = - Addr::HeapCell(self.heap.to_list(sig.as_ref().iter().map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))))); + let sig_list = Addr::HeapCell( + self.heap.to_list( + sig.as_ref() + .iter() + .map(|b| HeapCellValue::from(Addr::Fixnum(*b as isize))), + ), + ); self.unify(self[temp_v!(4)], sig_list); } @@ -5577,8 +5331,11 @@ impl MachineState { let peer_public_key = signature::UnparsedPublicKey::new(&signature::ED25519, &key); match peer_public_key.verify(&data, &signature) { - Ok(_) => { } - _ => { self.fail = true; return Ok(()); } + Ok(_) => {} + _ => { + self.fail = true; + return Ok(()); + } } } &SystemClauseType::Curve25519ScalarMult => { @@ -5606,11 +5363,13 @@ impl MachineState { &SystemClauseType::LoadXML => { let string = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); match roxmltree::Document::parse(&string) { - Ok(doc) => { let result = self.xml_node_to_term(indices, doc.root_element()); - self.unify(self[temp_v!(2)], result); + Ok(doc) => { + let result = self.xml_node_to_term(indices, doc.root_element()); + self.unify(self[temp_v!(2)], result); } - _ => { self.fail = true; - return Ok(()); + _ => { + self.fail = true; + return Ok(()); } } } @@ -5640,20 +5399,19 @@ impl MachineState { let padding = self.atom_argument_to_string(3); let charset = self.atom_argument_to_string(4); - let config = - if padding == "true" { - if charset == "standard" { - base64::STANDARD - } else { - base64::URL_SAFE - } + let config = if padding == "true" { + if charset == "standard" { + base64::STANDARD } else { - if charset == "standard" { - base64::STANDARD_NO_PAD - } else { - base64::URL_SAFE_NO_PAD - } - }; + base64::URL_SAFE + } + } else { + if charset == "standard" { + base64::STANDARD_NO_PAD + } else { + base64::URL_SAFE_NO_PAD + } + }; if self.store(self.deref(self[temp_v!(1)])).is_ref() { let b64 = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); @@ -5674,7 +5432,6 @@ impl MachineState { let mut bytes = vec![]; for c in self.heap_pstr_iter(self[temp_v!(1)]).to_string().chars() { if c as u32 > 255 { - let stub = MachineError::functor_stub(clause_name!("chars_base64"), 3); let err = MachineError::type_error( @@ -5695,19 +5452,16 @@ impl MachineState { } } &SystemClauseType::LoadLibraryAsStream => { - let library_name = - atom_from!( - self, - self.store(self.deref(self[temp_v!(1)])) - ); + 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)) - )); + let var_ref = Ref::HeapCell( + self.heap + .push(HeapCellValue::Stream(Stream::from(*library))), + ); self.bind(var_ref, self[temp_v!(2)]); @@ -5720,24 +5474,19 @@ impl MachineState { 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)) - ); + 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 Err(self.error_form( + MachineError::existence_error( + self.heap.h(), + ExistenceError::ModuleSource(ModuleSource::Library(library_name)), + ), + MachineError::functor_stub(clause_name!("load"), 1), + )); } } } @@ -5746,15 +5495,14 @@ impl MachineState { return_from_clause!(self.last_call, self) } - pub(super) - fn systemtime_to_timestamp( - &mut self, - system_time: SystemTime - ) -> Addr { + pub(super) fn systemtime_to_timestamp(&mut self, system_time: SystemTime) -> Addr { let datetime: DateTime = system_time.into(); let mut fstr = "[".to_string(); - let specifiers = vec!["Y","m","d","H","M","S","y","b","B","a","A","w","u","U","W","j","D","x","v"]; + let specifiers = vec![ + "Y", "m", "d", "H", "M", "S", "y", "b", "B", "a", "A", "w", "u", "U", "W", "j", "D", + "x", "v", + ]; for spec in specifiers { fstr.push_str(&format!("'{}'=\"%{}\", ", spec, spec).to_string()); } @@ -5763,11 +5511,7 @@ impl MachineState { self.heap.put_complete_string(&s) } - pub(super) - fn atom_argument_to_string( - &mut self, - atom_arg: usize, - ) -> String { + pub(super) fn atom_argument_to_string(&mut self, atom_arg: usize) -> String { match self.store(self.deref(self[temp_v!(atom_arg)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { @@ -5782,29 +5526,25 @@ impl MachineState { } } - pub(super) - fn string_encoding_bytes( - &mut self, - data_arg: usize, - encoding: &str, - ) -> Vec { + pub(super) fn string_encoding_bytes(&mut self, data_arg: usize, encoding: &str) -> Vec { let data = self.heap_pstr_iter(self[temp_v!(data_arg)]).to_string(); match encoding { - "utf8" => { data.into_bytes() } + "utf8" => data.into_bytes(), "octet" => { let mut buf = vec![]; - for c in data.chars() { + for c in data.chars() { buf.push(c as u8); } buf } - _ => { unreachable!() } + _ => { + unreachable!() + } } } - pub(super) - fn xml_node_to_term( + pub(super) fn xml_node_to_term( &mut self, indices: &mut IndexStore, node: roxmltree::Node, @@ -5816,15 +5556,14 @@ impl MachineState { let mut avec = Vec::new(); for attr in node.attributes() { let chars = clause_name!(String::from(attr.name()), self.atom_tbl); - let name = self.heap.to_unifiable( - HeapCellValue::Atom(chars, None) - ); + let name = self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); let value = self.heap.put_complete_string(&attr.value()); avec.push(HeapCellValue::Addr(Addr::HeapCell(self.heap.h()))); - self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), None)); + self.heap + .push(HeapCellValue::NamedStr(2, clause_name!("="), None)); self.heap.push(HeapCellValue::Addr(name)); self.heap.push(HeapCellValue::Addr(value)); } @@ -5837,13 +5576,12 @@ impl MachineState { let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter())); let chars = clause_name!(String::from(node.tag_name().name()), self.atom_tbl); - let tag = self.heap.to_unifiable( - HeapCellValue::Atom(chars, None) - ); + let tag = self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); let result = Addr::HeapCell(self.heap.h()); - self.heap.push(HeapCellValue::NamedStr(3, clause_name!("element"), None)); + self.heap + .push(HeapCellValue::NamedStr(3, clause_name!("element"), None)); self.heap.push(HeapCellValue::Addr(tag)); self.heap.push(HeapCellValue::Addr(attrs)); self.heap.push(HeapCellValue::Addr(children)); @@ -5852,29 +5590,28 @@ impl MachineState { } } - pub(super) - fn html_node_to_term( + pub(super) fn html_node_to_term( &mut self, indices: &mut IndexStore, node: select::node::Node, ) -> Addr { match node.name() { - None => { let string = String::from(node.text()); - self.heap.put_complete_string(&string) + None => { + let string = String::from(node.text()); + self.heap.put_complete_string(&string) } Some(name) => { let mut avec = Vec::new(); for attr in node.attrs() { let chars = clause_name!(String::from(attr.0), self.atom_tbl); - let name = self.heap.to_unifiable( - HeapCellValue::Atom(chars, None) - ); + let name = self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); let value = self.heap.put_complete_string(&String::from(attr.1)); avec.push(HeapCellValue::Addr(Addr::HeapCell(self.heap.h()))); - self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), None)); + self.heap + .push(HeapCellValue::NamedStr(2, clause_name!("="), None)); self.heap.push(HeapCellValue::Addr(name)); self.heap.push(HeapCellValue::Addr(value)); } @@ -5887,13 +5624,12 @@ impl MachineState { let children = Addr::HeapCell(self.heap.to_list(cvec.into_iter())); let chars = clause_name!(String::from(name), self.atom_tbl); - let tag = self.heap.to_unifiable( - HeapCellValue::Atom(chars, None) - ); + let tag = self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); let result = Addr::HeapCell(self.heap.h()); - self.heap.push(HeapCellValue::NamedStr(3, clause_name!("element"), None)); + self.heap + .push(HeapCellValue::NamedStr(3, clause_name!("element"), None)); self.heap.push(HeapCellValue::Addr(tag)); self.heap.push(HeapCellValue::Addr(attrs)); self.heap.push(HeapCellValue::Addr(children)); @@ -5904,7 +5640,6 @@ impl MachineState { } } - fn rng() -> &'static dyn SecureRandom { use std::ops::Deref; diff --git a/src/main.rs b/src/main.rs index 07684b61..82b89c95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,43 +1,35 @@ -extern crate blake2; -extern crate chrono; -extern crate cpu_time; -extern crate crossterm; -extern crate divrem; -#[macro_use] -extern crate downcast; -extern crate git_version; -extern crate hostname; -extern crate indexmap; -#[macro_use] -extern crate lazy_static; -extern crate libc; -extern crate native_tls; -extern crate nix; -extern crate openssl; -extern crate ordered_float; -#[macro_use] -extern crate prolog_parser_rebis; -#[macro_use] -extern crate ref_thread_local; -extern crate ring; -extern crate ripemd160; -#[cfg(feature = "rug")] -extern crate rug; -#[cfg(feature = "num-rug-adapter")] -extern crate num_rug_adapter as rug; -extern crate rustyline; -extern crate sha3; -extern crate unicode_reader; +use blake2; +use chrono; +use cpu_time; +use crossterm; +use divrem; +use downcast; +use git_version; +use indexmap; +use lazy_static; +use native_tls; +use nix::sys::signal; +use openssl; +use ordered_float; +use prolog_parser_rebis; +use ref_thread_local; +use ring; +use ripemd160; +use rustyline; +use sha3; +use unicode_reader; -use crate::nix::sys::signal; +#[cfg(feature = "num-rug-adapter")] +use num_rug_adapter as rug; +#[cfg(feature = "rug")] +use rug; #[macro_use] mod macros; mod allocator; mod arithmetic; -mod machine; -mod codegen; mod clause_types; +mod codegen; mod debray_allocator; mod fixtures; mod forms; @@ -46,17 +38,18 @@ mod heap_print; mod indexing; mod instructions; mod iterators; +mod machine; mod read; mod targets; mod write; -use machine::*; use machine::streams::*; +use machine::*; use read::*; use std::sync::atomic::Ordering; -extern fn handle_sigint(signal: libc::c_int) { +extern "C" fn handle_sigint(signal: libc::c_int) { let signal = signal::Signal::from_c_int(signal).unwrap(); if signal == signal::Signal::SIGINT { INTERRUPT.store(true, Ordering::Relaxed); From 8e5954f36f6d08be9422c8edfe3fb24df1eeb1d8 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:30:46 +0100 Subject: [PATCH 046/137] remove use statements from main.rs that temporary replaced extern crate and fixed paths that previously used them --- src/allocator.rs | 4 +- src/arithmetic.rs | 6 +- src/clause_types.rs | 6 +- src/codegen.rs | 8 +- src/debray_allocator.rs | 6 +- src/fixtures.rs | 23 +-- src/forms.rs | 10 +- src/heap_iter.rs | 68 +++---- src/heap_print.rs | 8 +- src/indexing.rs | 8 +- src/instructions.rs | 6 +- src/iterators.rs | 4 +- src/machine/arithmetic_ops.rs | 8 +- src/machine/attributed_variables.rs | 4 +- src/machine/compile.rs | 2 +- src/machine/heap.rs | 272 ++++++++++------------------ src/machine/load_state.rs | 4 +- src/machine/machine_errors.rs | 4 +- src/machine/machine_indices.rs | 8 +- src/machine/machine_state.rs | 10 +- src/machine/machine_state_impl.rs | 10 +- src/machine/mod.rs | 12 +- src/machine/preprocessor.rs | 8 +- src/machine/streams.rs | 8 +- src/machine/system_calls.rs | 44 ++--- src/machine/term_stream.rs | 34 ++-- src/main.rs | 22 +-- src/read.rs | 123 ++++++------- src/targets.rs | 2 +- 29 files changed, 302 insertions(+), 430 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index c0e46da0..8d447fb1 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::temp_v; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::temp_v; use crate::fixtures::*; use crate::forms::*; diff --git a/src/arithmetic.rs b/src/arithmetic.rs index c3492f31..68f9f483 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::{atom, clause_name}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::{atom, clause_name}; use crate::clause_types::*; use crate::fixtures::*; @@ -11,9 +11,9 @@ use crate::machine::heap::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; -use crate::ordered_float::*; use crate::rug::ops::PowAssign; use crate::rug::{Assign, Integer, Rational}; +use ordered_float::*; use std::cell::Cell; use std::cmp::{max, min, Ordering}; diff --git a/src/clause_types.rs b/src/clause_types.rs index 335e24f8..5096ffad 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -1,11 +1,11 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::{clause_name, temp_v}; use crate::forms::Number; use crate::machine::machine_indices::*; use crate::rug::rand::RandState; -use crate::ref_thread_local::{ref_thread_local, RefThreadLocal}; +use ref_thread_local::{ref_thread_local, RefThreadLocal}; use std::collections::BTreeMap; diff --git a/src/codegen.rs b/src/codegen.rs index 46e2ea82..41bd72c6 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,7 @@ /// Code generation to WAM-like instructions. -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::tabled_rc::TabledData; -use crate::prolog_parser_rebis::{perm_v, temp_v}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::tabled_rc::TabledData; +use prolog_parser_rebis::{perm_v, temp_v}; use crate::allocator::*; use crate::arithmetic::*; @@ -15,7 +15,7 @@ use crate::targets::*; use crate::machine::machine_errors::*; -use crate::indexmap::{IndexMap, IndexSet}; +use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::collections::VecDeque; diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 39b5a886..ed0b9704 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -1,7 +1,7 @@ -use crate::indexmap::IndexMap; +use indexmap::IndexMap; -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::temp_v; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::temp_v; use crate::allocator::*; use crate::fixtures::*; diff --git a/src/fixtures.rs b/src/fixtures.rs index d9034562..002774de 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -1,10 +1,10 @@ -use crate::prolog_parser_rebis::ast::*; +use prolog_parser_rebis::ast::*; use crate::forms::*; use crate::instructions::*; use crate::iterators::*; -use crate::indexmap::{IndexMap, IndexSet}; +use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::collections::BTreeSet; @@ -83,18 +83,17 @@ impl TempVarData { type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); #[derive(Debug)] -pub struct VariableFixtures<'a>{ +pub struct VariableFixtures<'a> { perm_vars: IndexMap, VariableFixture<'a>>, - last_chunk_temp_vars: IndexSet> + last_chunk_temp_vars: IndexSet>, } impl<'a> VariableFixtures<'a> { pub fn new() -> Self { VariableFixtures { perm_vars: IndexMap::new(), - last_chunk_temp_vars: IndexSet::new() + last_chunk_temp_vars: IndexSet::new(), } - } pub fn insert(&mut self, var: Rc, vs: VariableFixture<'a>) { @@ -262,34 +261,32 @@ impl UnsafeVarMarker { pub fn new() -> Self { UnsafeVarMarker { unsafe_vars: IndexMap::new(), - safe_vars: IndexSet::new() + safe_vars: IndexSet::new(), } } pub fn from_safe_vars(safe_vars: IndexSet) -> Self { UnsafeVarMarker { unsafe_vars: IndexMap::new(), - safe_vars + safe_vars, } } pub fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) -> bool { match query_instr { &QueryInstruction::PutVariable(r @ RegType::Temp(_), _) - | &QueryInstruction::SetVariable(r) => { + | &QueryInstruction::SetVariable(r) => { self.safe_vars.insert(r); true } - _ => { - false - } + _ => false, } } pub fn mark_phase(&mut self, query_instr: &QueryInstruction, phase: usize) { match query_instr { &QueryInstruction::PutValue(r @ RegType::Perm(_), _) - | &QueryInstruction::SetValue(r) => { + | &QueryInstruction::SetValue(r) => { let p = self.unsafe_vars.entry(r).or_insert(0); *p = phase; } diff --git a/src/forms.rs b/src/forms.rs index f71df86c..5dfc680d 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,14 +1,14 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::parser::OpDesc; -use crate::prolog_parser_rebis::{clause_name, is_infix, is_postfix}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::parser::OpDesc; +use prolog_parser_rebis::{clause_name, is_infix, is_postfix}; use crate::clause_types::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; -use crate::ordered_float::OrderedFloat; use crate::rug::{Integer, Rational}; +use ordered_float::OrderedFloat; -use crate::indexmap::{IndexMap, IndexSet}; +use indexmap::{IndexMap, IndexSet}; use slice_deque::*; diff --git a/src/heap_iter.rs b/src/heap_iter.rs index 44541237..a6d2e5fa 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -1,7 +1,7 @@ use crate::machine::machine_indices::*; use crate::machine::machine_state::*; -use crate::indexmap::IndexSet; +use indexmap::IndexSet; use std::cmp::Ordering; use std::ops::Deref; @@ -29,31 +29,21 @@ impl<'a> HCPreOrderIterator<'a> { fn follow_heap(&mut self, h: usize) -> Addr { match &self.machine_st.heap[h] { &HeapCellValue::NamedStr(arity, _, _) => { - for idx in (1 .. arity + 1).rev() { + for idx in (1..arity + 1).rev() { self.state_stack.push(Addr::HeapCell(h + idx)); } Addr::Str(h) } - &HeapCellValue::Addr(a) => { - self.follow(a) - } - HeapCellValue::PartialString(..) => { - self.follow(Addr::PStrLocation(h, 0)) - } - HeapCellValue::Atom(..) | HeapCellValue::DBRef(_) - | HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => { - Addr::Con(h) - } - HeapCellValue::LoadStatePayload(_) => { - Addr::LoadStatePayload(h) - } - HeapCellValue::Stream(_) => { - Addr::Stream(h) - } - HeapCellValue::TcpListener(_) => { - Addr::TcpListener(h) - } + &HeapCellValue::Addr(a) => self.follow(a), + HeapCellValue::PartialString(..) => self.follow(Addr::PStrLocation(h, 0)), + HeapCellValue::Atom(..) + | HeapCellValue::DBRef(_) + | HeapCellValue::Integer(_) + | HeapCellValue::Rational(_) => Addr::Con(h), + HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(h), + HeapCellValue::Stream(_) => Addr::Stream(h), + HeapCellValue::TcpListener(_) => Addr::TcpListener(h), } } @@ -71,10 +61,12 @@ impl<'a> HCPreOrderIterator<'a> { da } Addr::PStrLocation(h, n) => { - if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] { - if let Some(c) = pstr.range_from(n ..).next() { + if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] + { + if let Some(c) = pstr.range_from(n..).next() { if !pstr.at_end(n + c.len_utf8()) { - self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8())); + self.state_stack + .push(Addr::PStrLocation(h, n + c.len_utf8())); } else if has_tail { self.state_stack.push(Addr::HeapCell(h + 1)); } else { @@ -95,8 +87,9 @@ impl<'a> HCPreOrderIterator<'a> { self.follow_heap(s) // record terms of structure. } Addr::Con(h) => { - if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] { - if let Some(c) = pstr.range_from(0 ..).next() { + if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] + { + if let Some(c) = pstr.range_from(0..).next() { self.state_stack.push(Addr::PStrLocation(h, c.len_utf8())); self.state_stack.push(Addr::Char(c)); @@ -110,9 +103,7 @@ impl<'a> HCPreOrderIterator<'a> { Addr::Con(h) } } - da => { - da - } + da => da, } } } @@ -125,7 +116,9 @@ impl<'a> Iterator for HCPreOrderIterator<'a> { } } -pub trait MutStackHCIterator<'b> where Self: Iterator +pub trait MutStackHCIterator<'b> +where + Self: Iterator, { type MutStack; @@ -178,7 +171,8 @@ impl<'a> Iterator for HCPostOrderIterator<'a> { } &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(); @@ -215,7 +209,7 @@ impl MachineState { HCPostOrderIterator::new(HCPreOrderIterator::new(self, a)) } - pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr,) -> HCAcyclicIterator<'a> { + pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr) -> HCAcyclicIterator<'a> { HCAcyclicIterator::new(HCPreOrderIterator::new(self, a)) } @@ -270,8 +264,7 @@ impl<'b, 'a: 'b> MutStackHCIterator<'b> for HCAcyclicIterator<'a> { } } -impl<'a> Iterator for HCAcyclicIterator<'a> -{ +impl<'a> Iterator for HCAcyclicIterator<'a> { type Item = Addr; fn next(&mut self) -> Option { @@ -315,8 +308,7 @@ impl<'a> HCZippedAcyclicIterator<'a> { } } -impl<'a> Iterator for HCZippedAcyclicIterator<'a> -{ +impl<'a> Iterator for HCZippedAcyclicIterator<'a> { type Item = (Addr, Addr); fn next(&mut self) -> Option { @@ -341,9 +333,7 @@ impl<'a> Iterator for HCZippedAcyclicIterator<'a> self.first_to_expire = Ordering::Less; None } - _ => { - None - } + _ => None, } } } diff --git a/src/heap_print.rs b/src/heap_print.rs index d4b9b09f..2bd5e3bf 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::{ +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::{ alpha_char, alpha_numeric_char, backslash_char, capital_letter_char, char_class, clause_name, cut_char, decimal_digit_char, graphic_char, graphic_token_char, is_fx, is_infix, is_postfix, is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char, sign_char, single_quote_char, @@ -13,10 +13,10 @@ use crate::machine::heap::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; use crate::machine::streams::*; -use crate::ordered_float::OrderedFloat; use crate::rug::{Integer, Rational}; +use ordered_float::OrderedFloat; -use crate::indexmap::{IndexMap, IndexSet}; +use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; use std::convert::TryFrom; diff --git a/src/indexing.rs b/src/indexing.rs index 80bd4c17..1b14f301 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1,12 +1,12 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::clause_name; -use crate::prolog_parser_rebis::tabled_rc::*; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::clause_name; +use prolog_parser_rebis::tabled_rc::*; use crate::forms::*; use crate::instructions::*; -use crate::indexmap::IndexMap; use crate::rug::Integer; +use indexmap::IndexMap; use slice_deque::{sdeq, SliceDeque}; diff --git a/src/instructions.rs b/src/instructions.rs index 91982ea2..585cd2cb 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::clause_name; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::clause_name; use crate::clause_types::*; use crate::forms::*; @@ -9,7 +9,7 @@ use crate::machine::machine_errors::MachineStub; use crate::machine::machine_indices::*; use crate::rug::Integer; -use crate::indexmap::IndexMap; +use indexmap::IndexMap; use slice_deque::SliceDeque; diff --git a/src/iterators.rs b/src/iterators.rs index ce3733ec..beb81ca4 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::rc_atom; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::rc_atom; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index aee346a2..b21cb7a9 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1,7 +1,7 @@ -use crate::divrem::*; +use divrem::*; -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::clause_name; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::clause_name; use crate::arithmetic::*; use crate::clause_types::*; @@ -9,8 +9,8 @@ use crate::forms::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; -use crate::ordered_float::*; use crate::rug::{Integer, Rational}; +use ordered_float::*; use std::cmp; use std::convert::TryFrom; diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index dff8e90e..4bc90fc4 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -1,8 +1,8 @@ use crate::heap_iter::*; use crate::machine::*; -use crate::prolog_parser_rebis::temp_v; +use prolog_parser_rebis::temp_v; -use crate::indexmap::IndexSet; +use indexmap::IndexSet; use std::cmp::Ordering; use std::vec::IntoIter; diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 766c117a..1ab52a73 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser_rebis::clause_name; +use prolog_parser_rebis::clause_name; use crate::codegen::*; use crate::debray_allocator::*; diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 0d3a5cf6..c6115662 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use crate::prolog_parser_rebis::ast::Constant; +use prolog_parser_rebis::ast::Constant; use crate::machine::machine_indices::*; use crate::machine::partial_string::*; @@ -42,16 +42,17 @@ impl Drop for HeapTemplate { } #[derive(Debug)] -pub(crate) -struct HeapIntoIter { +pub(crate) struct HeapIntoIter { offset: usize, buf: RawBlock, } impl Drop for HeapIntoIter { fn drop(&mut self) { - let mut heap = - HeapTemplate { buf: self.buf.take(), _marker: PhantomData }; + let mut heap = HeapTemplate { + buf: self.buf.take(), + _marker: PhantomData, + }; heap.truncate(self.offset / mem::size_of::()); heap.buf.deallocate(); @@ -66,9 +67,7 @@ impl Iterator for HeapIntoIter { self.offset += mem::size_of::(); if ptr < self.buf.top as usize { - unsafe { - Some(ptr::read(ptr as *const HeapCellValue)) - } + unsafe { Some(ptr::read(ptr as *const HeapCellValue)) } } else { None } @@ -76,15 +75,13 @@ impl Iterator for HeapIntoIter { } #[derive(Debug)] -pub(crate) -struct HeapIter<'a, T: RawBlockTraits> { +pub(crate) struct HeapIter<'a, T: RawBlockTraits> { offset: usize, buf: &'a RawBlock, } impl<'a, T: RawBlockTraits> HeapIter<'a, T> { - pub(crate) - fn new(buf: &'a RawBlock, offset: usize) -> Self { + pub(crate) fn new(buf: &'a RawBlock, offset: usize) -> Self { HeapIter { buf, offset } } } @@ -97,9 +94,7 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIter<'a, T> { self.offset += mem::size_of::(); if ptr < self.buf.top as usize { - unsafe { - Some(&*(ptr as *const _)) - } + unsafe { Some(&*(ptr as *const _)) } } else { None } @@ -107,23 +102,20 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIter<'a, T> { } #[allow(dead_code)] -pub(crate) -fn print_heap_terms<'a, I: Iterator>(heap: I, h: usize) { +pub(crate) fn print_heap_terms<'a, I: Iterator>(heap: I, h: usize) { for (index, term) in heap.enumerate() { println!("{} : {}", h + index, term); } } #[derive(Debug)] -pub(crate) -struct HeapIterMut<'a, T: RawBlockTraits> { +pub(crate) struct HeapIterMut<'a, T: RawBlockTraits> { offset: usize, buf: &'a mut RawBlock, } impl<'a, T: RawBlockTraits> HeapIterMut<'a, T> { - pub(crate) - fn new(buf: &'a mut RawBlock, offset: usize) -> Self { + pub(crate) fn new(buf: &'a mut RawBlock, offset: usize) -> Self { HeapIterMut { buf, offset } } } @@ -136,9 +128,7 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIterMut<'a, T> { self.offset += mem::size_of::(); if ptr < self.buf.top as usize { - unsafe { - Some(&mut *(ptr as *mut _)) - } + unsafe { Some(&mut *(ptr as *mut _)) } } else { None } @@ -147,51 +137,33 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIterMut<'a, T> { impl HeapTemplate { #[inline] - pub(crate) - fn new() -> Self { - HeapTemplate { buf: RawBlock::new(), _marker: PhantomData } - } - - #[inline] - pub(crate) - fn clone(&self, h: usize) -> HeapCellValue { - match &self[h] { - &HeapCellValue::Addr(addr) => { - HeapCellValue::Addr(addr) - } - &HeapCellValue::Atom(ref name, ref op) => { - HeapCellValue::Atom(name.clone(), op.clone()) - } - &HeapCellValue::DBRef(ref db_ref) => { - HeapCellValue::DBRef(db_ref.clone()) - } - &HeapCellValue::Integer(ref n) => { - HeapCellValue::Integer(n.clone()) - } - &HeapCellValue::LoadStatePayload(_) => { - HeapCellValue::Addr(Addr::LoadStatePayload(h)) - } - &HeapCellValue::NamedStr(arity, ref name, ref op) => { - HeapCellValue::NamedStr(arity, name.clone(), op.clone()) - } - &HeapCellValue::PartialString(..) => { - HeapCellValue::Addr(Addr::PStrLocation(h, 0)) - } - &HeapCellValue::Rational(ref r) => { - HeapCellValue::Rational(r.clone()) - } - &HeapCellValue::Stream(_) => { - HeapCellValue::Addr(Addr::Stream(h)) - } - &HeapCellValue::TcpListener(_) => { - HeapCellValue::Addr(Addr::TcpListener(h)) - } + pub(crate) fn new() -> Self { + HeapTemplate { + buf: RawBlock::new(), + _marker: PhantomData, } } #[inline] - pub(crate) - fn put_complete_string(&mut self, s: &str) -> Addr { + pub(crate) fn clone(&self, h: usize) -> HeapCellValue { + match &self[h] { + &HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr), + &HeapCellValue::Atom(ref name, ref op) => HeapCellValue::Atom(name.clone(), op.clone()), + &HeapCellValue::DBRef(ref db_ref) => HeapCellValue::DBRef(db_ref.clone()), + &HeapCellValue::Integer(ref n) => HeapCellValue::Integer(n.clone()), + &HeapCellValue::LoadStatePayload(_) => HeapCellValue::Addr(Addr::LoadStatePayload(h)), + &HeapCellValue::NamedStr(arity, ref name, ref op) => { + HeapCellValue::NamedStr(arity, name.clone(), op.clone()) + } + &HeapCellValue::PartialString(..) => HeapCellValue::Addr(Addr::PStrLocation(h, 0)), + &HeapCellValue::Rational(ref r) => HeapCellValue::Rational(r.clone()), + &HeapCellValue::Stream(_) => HeapCellValue::Addr(Addr::Stream(h)), + &HeapCellValue::TcpListener(_) => HeapCellValue::Addr(Addr::TcpListener(h)), + } + } + + #[inline] + pub(crate) fn put_complete_string(&mut self, s: &str) -> Addr { if s.is_empty() { return Addr::EmptyList; } @@ -214,30 +186,15 @@ impl HeapTemplate { } #[inline] - pub(crate) - fn put_constant(&mut self, c: Constant) -> Addr { + pub(crate) fn put_constant(&mut self, c: Constant) -> Addr { match c { - Constant::Atom(name, op) => { - Addr::Con(self.push(HeapCellValue::Atom(name, op))) - } - Constant::Char(c) => { - Addr::Char(c) - } - Constant::EmptyList => { - Addr::EmptyList - } - Constant::Fixnum(n) => { - Addr::Fixnum(n) - } - Constant::Integer(n) => { - Addr::Con(self.push(HeapCellValue::Integer(n))) - } - Constant::Rational(r) => { - Addr::Con(self.push(HeapCellValue::Rational(r))) - } - Constant::Float(f) => { - Addr::Float(f) - } + Constant::Atom(name, op) => Addr::Con(self.push(HeapCellValue::Atom(name, op))), + Constant::Char(c) => Addr::Char(c), + Constant::EmptyList => Addr::EmptyList, + Constant::Fixnum(n) => Addr::Fixnum(n), + Constant::Integer(n) => Addr::Con(self.push(HeapCellValue::Integer(n))), + Constant::Rational(r) => Addr::Con(self.push(HeapCellValue::Rational(r))), + Constant::Float(f) => Addr::Float(f), Constant::String(s) => { if s.is_empty() { Addr::EmptyList @@ -245,15 +202,12 @@ impl HeapTemplate { self.put_complete_string(&s) } } - Constant::Usize(n) => { - Addr::Usize(n) - } + Constant::Usize(n) => Addr::Usize(n), } } #[inline] - pub(crate) - fn pop(&mut self) { + pub(crate) fn pop(&mut self) { let h = self.h(); if h > 0 { @@ -262,8 +216,7 @@ impl HeapTemplate { } #[inline] - pub(crate) - fn push(&mut self, val: HeapCellValue) -> usize { + pub(crate) fn push(&mut self, val: HeapCellValue) -> usize { let h = self.h(); unsafe { @@ -276,8 +229,7 @@ impl HeapTemplate { } #[inline] - pub(crate) - fn atom_at(&self, h: usize) -> bool { + pub(crate) fn atom_at(&self, h: usize) -> bool { if let HeapCellValue::Atom(..) = &self[h] { true } else { @@ -286,24 +238,15 @@ impl HeapTemplate { } #[inline] - pub(crate) - fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr { + pub(crate) fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr { match non_heap_value { - HeapCellValue::Addr(addr) => { - addr - } - val @ HeapCellValue::Atom(..) | - val @ HeapCellValue::Integer(_) | - val @ HeapCellValue::DBRef(_) | - val @ HeapCellValue::Rational(_) => { - Addr::Con(self.push(val)) - } - val @ HeapCellValue::LoadStatePayload(_) => { - Addr::LoadStatePayload(self.push(val)) - } - val @ HeapCellValue::NamedStr(..) => { - Addr::Str(self.push(val)) - } + HeapCellValue::Addr(addr) => addr, + val @ HeapCellValue::Atom(..) + | val @ HeapCellValue::Integer(_) + | val @ HeapCellValue::DBRef(_) + | val @ HeapCellValue::Rational(_) => Addr::Con(self.push(val)), + val @ HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(self.push(val)), + val @ HeapCellValue::NamedStr(..) => Addr::Str(self.push(val)), HeapCellValue::PartialString(pstr, has_tail) => { let h = self.push(HeapCellValue::PartialString(pstr, has_tail)); @@ -313,20 +256,14 @@ impl HeapTemplate { Addr::Con(h) } - val @ HeapCellValue::Stream(..) => { - Addr::Stream(self.push(val)) - } - val @ HeapCellValue::TcpListener(..) => { - Addr::TcpListener(self.push(val)) - } + val @ HeapCellValue::Stream(..) => Addr::Stream(self.push(val)), + val @ HeapCellValue::TcpListener(..) => Addr::TcpListener(self.push(val)), } } #[inline] - pub(crate) - fn allocate_pstr(&mut self, src: &str) -> Addr { - self.write_pstr(src) - .unwrap_or_else(|| Addr::EmptyList) + pub(crate) fn allocate_pstr(&mut self, src: &str) -> Addr { + self.write_pstr(src).unwrap_or_else(|| Addr::EmptyList) } #[inline] @@ -347,23 +284,20 @@ impl HeapTemplate { let h = self.h(); - let (pstr, rest_src) = - match PartialString::new(src) { - Some(tuple) => { - tuple + let (pstr, rest_src) = match PartialString::new(src) { + Some(tuple) => tuple, + None => { + if src.len() > '\u{0}'.len_utf8() { + src = &src['\u{0}'.len_utf8()..]; + continue; + } else if orig_h == h { + return None; + } else { + self[h - 1] = HeapCellValue::Addr(Addr::HeapCell(h - 1)); + return Some(Addr::PStrLocation(orig_h, 0)); } - None => { - if src.len() > '\u{0}'.len_utf8() { - src = &src['\u{0}'.len_utf8() ..]; - continue; - } else if orig_h == h { - return None; - } else { - self[h - 1] = HeapCellValue::Addr(Addr::HeapCell(h - 1)); - return Some(Addr::PStrLocation(orig_h, 0)); - } - } - }; + } + }; self.push(HeapCellValue::PartialString(pstr, true)); @@ -378,8 +312,7 @@ impl HeapTemplate { } #[inline] - pub(crate) - fn truncate(&mut self, h: usize) { + pub(crate) fn truncate(&mut self, h: usize) { let new_top = h * mem::size_of::() + self.buf.base as usize; let mut h = new_top; @@ -395,30 +328,27 @@ impl HeapTemplate { } #[inline] - pub(crate) - fn h(&self) -> usize { + pub(crate) fn h(&self) -> usize { (self.buf.top as usize - self.buf.base as usize) / mem::size_of::() } - pub(crate) - fn append(&mut self, vals: Vec) { + pub(crate) fn append(&mut self, vals: Vec) { for val in vals { self.push(val); } } - pub(crate) - fn clear(&mut self) { + pub(crate) fn clear(&mut self) { if !self.buf.base.is_null() { self.truncate(0); self.buf.top = self.buf.base; } } - pub(crate) - fn to_list(&mut self, values: Iter) -> usize - where Iter: Iterator, - SrcT: Into + pub(crate) fn to_list(&mut self, values: Iter) -> usize + where + Iter: Iterator, + SrcT: Into, { let head_addr = self.h(); let mut h = head_addr; @@ -436,35 +366,33 @@ impl HeapTemplate { } /* Create an iterator starting from the passed offset. */ - pub(crate) - fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> { + pub(crate) fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> { HeapIter::new(&self.buf, offset * mem::size_of::()) } - pub(crate) - fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> { + pub(crate) fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> { HeapIterMut::new(&mut self.buf, offset * mem::size_of::()) } - pub(crate) - fn into_iter(mut self) -> HeapIntoIter { - HeapIntoIter { buf: self.buf.take(), offset: 0 } + pub(crate) fn into_iter(mut self) -> HeapIntoIter { + HeapIntoIter { + buf: self.buf.take(), + offset: 0, + } } - pub(crate) - fn extend>(&mut self, iter: Iter) { + pub(crate) fn extend>(&mut self, iter: Iter) { for hcv in iter { self.push(hcv); } } - pub(crate) - fn to_local_code_ptr(&self, addr: &Addr) -> Option { + pub(crate) fn to_local_code_ptr(&self, addr: &Addr) -> Option { let extract_integer = |s: usize| -> Option { match &self[s] { &HeapCellValue::Addr(Addr::Fixnum(n)) => usize::try_from(n).ok(), &HeapCellValue::Integer(ref n) => n.to_usize(), - _ => None + _ => None, } }; @@ -473,9 +401,7 @@ impl HeapTemplate { match &self[*s] { HeapCellValue::NamedStr(arity, ref name, _) => { match (name.as_str(), *arity) { - ("dir_entry", 1) => { - extract_integer(s+1).map(LocalCodePtr::DirEntry) - } + ("dir_entry", 1) => extract_integer(s + 1).map(LocalCodePtr::DirEntry), /* ("top_level", 2) => { if let Some(chunk_num) = extract_integer(s+1) { @@ -487,15 +413,13 @@ impl HeapTemplate { None } */ - _ => { - None - } + _ => None, } } - _ => unreachable!() + _ => unreachable!(), } } - _ => None + _ => None, } } @@ -505,9 +429,7 @@ impl HeapTemplate { &Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => { RefOrOwned::Borrowed(&self[h]) } - addr => { - RefOrOwned::Owned(HeapCellValue::Addr(*addr)) - } + addr => RefOrOwned::Owned(HeapCellValue::Addr(*addr)), } } } diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 466b2f99..5ddd2c9f 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -1,11 +1,11 @@ use crate::machine::machine_indices::*; use crate::machine::*; -use crate::prolog_parser_rebis::clause_name; +use prolog_parser_rebis::clause_name; use crate::machine::term_stream::*; use indexmap::IndexSet; -use crate::ref_thread_local::RefThreadLocal; +use ref_thread_local::RefThreadLocal; type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>; diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 1ca1861d..b1d60bb3 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::{clause_name, temp_v}; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; use crate::machine::heap::*; diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index b4089147..918af24c 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::clause_name; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::clause_name; use crate::clause_types::*; use crate::fixtures::*; @@ -14,10 +14,10 @@ use crate::machine::streams::Stream; use crate::machine::term_stream::LoadStatePayload; use crate::machine::Ball; use crate::machine::CompilationTarget; -use crate::ordered_float::OrderedFloat; use crate::rug::{Integer, Rational}; +use ordered_float::OrderedFloat; -use crate::indexmap::IndexMap; +use indexmap::IndexMap; use std::cell::Cell; use std::cmp::Ordering; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index c8338c94..f7160134 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -1,6 +1,6 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::tabled_rc::*; -use crate::prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::tabled_rc::*; +use prolog_parser_rebis::{clause_name, temp_v}; use crate::clause_types::*; use crate::forms::*; @@ -15,11 +15,11 @@ use crate::machine::stack::*; use crate::machine::streams::*; use crate::rug::Integer; -use crate::downcast::{ +use downcast::{ downcast, downcast_methods, downcast_methods_core, downcast_methods_std, impl_downcast, Any, }; -use crate::indexmap::IndexMap; +use indexmap::IndexMap; use std::cmp::Ordering; use std::convert::TryFrom; diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index d0348f9f..141ec43f 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1,6 +1,6 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::tabled_rc::*; -use crate::prolog_parser_rebis::{clause_name, perm_v, temp_v}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::tabled_rc::*; +use prolog_parser_rebis::{clause_name, perm_v, temp_v}; use crate::clause_types::*; use crate::forms::*; @@ -18,10 +18,10 @@ use crate::machine::partial_string::*; use crate::machine::stack::*; use crate::machine::streams::*; use crate::machine::INTERRUPT; -use crate::ordered_float::*; use crate::rug::Integer; +use ordered_float::*; -use crate::indexmap::{IndexMap, IndexSet}; +use indexmap::{IndexMap, IndexSet}; use std::cmp::Ordering; use std::convert::TryFrom; diff --git a/src/machine/mod.rs b/src/machine/mod.rs index eb9dd534..c0550c1e 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -1,8 +1,8 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::tabled_rc::*; -use crate::prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::tabled_rc::*; +use prolog_parser_rebis::{clause_name, temp_v}; -use crate::lazy_static::lazy_static; +use lazy_static::lazy_static; use crate::clause_types::*; use crate::forms::*; @@ -45,7 +45,7 @@ use crate::machine::machine_indices::*; use crate::machine::machine_state::*; use crate::machine::streams::*; -use crate::indexmap::IndexMap; +use indexmap::IndexMap; //use std::convert::TryFrom; use prolog_parser_rebis::ast::ClauseName; @@ -304,7 +304,7 @@ impl Machine { } pub fn new(user_input: Stream, user_output: Stream) -> Self { - use crate::ref_thread_local::RefThreadLocal; + use ref_thread_local::RefThreadLocal; let mut wam = Machine { machine_st: MachineState::new(), diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 34d47ebe..f0c7f8b5 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -1,6 +1,6 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::tabled_rc::*; -use crate::prolog_parser_rebis::{atom, clause_name, rc_atom}; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::tabled_rc::*; +use prolog_parser_rebis::{atom, clause_name, rc_atom}; use crate::forms::*; use crate::iterators::*; @@ -8,7 +8,7 @@ use crate::machine::load_state::*; use crate::machine::machine_errors::*; use crate::machine::*; -use crate::indexmap::IndexSet; +use indexmap::IndexSet; use std::cell::Cell; use std::collections::VecDeque; diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 531b47c4..dfa98eb3 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1,5 +1,5 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::clause_name; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::clause_name; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; @@ -20,7 +20,7 @@ use std::net::{Shutdown, TcpStream}; use std::ops::DerefMut; use std::rc::Rc; -use crate::native_tls::TlsStream; +use native_tls::TlsStream; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum StreamType { @@ -629,7 +629,7 @@ impl Stream { #[inline] pub(crate) fn peek_char(&mut self) -> std::io::Result { - use crate::unicode_reader::CodePoints; + use unicode_reader::CodePoints; match self.stream_inst.0.borrow_mut().1 { StreamInstance::InputFile(_, ref mut file) => { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 81bf2da5..cfad12af 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1,14 +1,14 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::parser::*; -use crate::prolog_parser_rebis::tabled_rc::*; -use crate::prolog_parser_rebis::{ +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::parser::*; +use prolog_parser_rebis::tabled_rc::*; +use prolog_parser_rebis::{ alpha_char, alpha_numeric_char, backslash_char, binary_digit_char, char_class, clause_name, decimal_digit_char, exponent_char, graphic_char, graphic_token_char, hexadecimal_digit_char, layout_char, meta_char, new_line_char, octal_digit_char, prolog_char, sign_char, solo_char, symbolic_control_char, symbolic_hexadecimal_char, temp_v, }; -use crate::lazy_static::lazy_static; +use lazy_static::lazy_static; use crate::clause_types::*; use crate::forms::*; @@ -24,13 +24,13 @@ use crate::machine::machine_state::*; use crate::machine::preprocessor::to_op_decl; use crate::machine::streams::*; -use crate::ordered_float::OrderedFloat; use crate::read::readline; use crate::rug::Integer; +use ordered_float::OrderedFloat; -use crate::indexmap::IndexSet; +use indexmap::IndexSet; -use crate::ref_thread_local::RefThreadLocal; +use ref_thread_local::RefThreadLocal; use std::cmp; use std::collections::BTreeSet; @@ -44,29 +44,29 @@ use std::num::NonZeroU32; use std::ops::Sub; use std::rc::Rc; -use crate::chrono::{offset::Local, DateTime}; -use crate::cpu_time::ProcessTime; +use chrono::{offset::Local, DateTime}; +use cpu_time::ProcessTime; use std::time::{Duration, SystemTime}; -use crate::crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; -use crate::crossterm::terminal::{disable_raw_mode, enable_raw_mode}; +use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers}; +use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; -use crate::blake2::{Blake2b, Blake2s}; -use crate::ring::rand::{SecureRandom, SystemRandom}; -use crate::ring::{ +use blake2::{Blake2b, Blake2s}; +use ring::rand::{SecureRandom, SystemRandom}; +use ring::{ aead, digest, hkdf, pbkdf2, signature::{self, KeyPair}, }; -use crate::ripemd160::{Digest, Ripemd160}; -use crate::sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; +use ripemd160::{Digest, Ripemd160}; +use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; -use crate::openssl::bn::{BigNum, BigNumContext}; -use crate::openssl::ec::{EcGroup, EcPoint}; -use crate::openssl::nid::Nid; +use openssl::bn::{BigNum, BigNumContext}; +use openssl::ec::{EcGroup, EcPoint}; +use openssl::nid::Nid; use sodiumoxide::crypto::scalarmult::curve25519::*; -use crate::native_tls::TlsConnector; +use native_tls::TlsConnector; extern crate select; @@ -4883,7 +4883,7 @@ impl MachineState { } } &SystemClauseType::ScryerPrologVersion => { - use crate::git_version::git_version; + use git_version::git_version; let version = self[temp_v!(1)]; let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown"); let chars = buffer.chars().map(|c| Addr::Char(c)); diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index e408a6f1..1305ad65 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -1,16 +1,16 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::parser::*; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::parser::*; -use crate::machine::*; use crate::machine::machine_errors::CompilationError; use crate::machine::preprocessor::*; +use crate::machine::*; use indexmap::IndexSet; use std::collections::VecDeque; use std::fmt; -pub(crate) trait TermStream : Sized { +pub(crate) trait TermStream: Sized { type Evacuable; fn next(&mut self, op_dir: &CompositeOpDir) -> Result; @@ -27,15 +27,17 @@ pub(super) struct BootstrappingTermStream<'a> { impl<'a> BootstrappingTermStream<'a> { #[inline] - pub(super) - fn from_prolog_stream( + pub(super) fn from_prolog_stream( stream: &'a mut PrologStream, atom_tbl: TabledData, flags: MachineFlags, listing_src: ListingSource, ) -> Self { let parser = Parser::new(stream, atom_tbl, flags); - Self { parser, listing_src } + Self { + parser, + listing_src, + } } } @@ -45,13 +47,14 @@ impl<'a> TermStream for BootstrappingTermStream<'a> { #[inline] fn next(&mut self, op_dir: &CompositeOpDir) -> Result { self.parser.reset(); - self.parser.read_term(op_dir) + self.parser + .read_term(op_dir) .map_err(CompilationError::from) } #[inline] fn eof(&mut self) -> Result { - self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF. + self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF. Ok(self.parser.eof()?) } @@ -65,9 +68,10 @@ impl<'a> TermStream for BootstrappingTermStream<'a> { loader.compile_and_submit()?; } - loader.load_state.retraction_info.reset( - loader.load_state.wam.code_repo.code.len(), - ); + loader + .load_state + .retraction_info + .reset(loader.load_state.wam.code_repo.code.len()); loader.load_state.remove_module_op_exports(); @@ -82,8 +86,7 @@ pub struct LiveTermStream { impl LiveTermStream { #[inline] - pub(super) - fn new(listing_src: ListingSource) -> Self { + pub(super) fn new(listing_src: ListingSource) -> Self { Self { term_queue: VecDeque::new(), listing_src, @@ -109,8 +112,7 @@ impl fmt::Debug for LoadStatePayload { } impl LoadStatePayload { - pub(super) - fn new(wam: &Machine) -> Self { + pub(super) fn new(wam: &Machine) -> Self { Self { term_stream: LiveTermStream::new(ListingSource::User), compilation_target: CompilationTarget::default(), diff --git a/src/main.rs b/src/main.rs index 82b89c95..a79563b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,3 @@ -use blake2; -use chrono; -use cpu_time; -use crossterm; -use divrem; -use downcast; -use git_version; -use indexmap; -use lazy_static; -use native_tls; -use nix::sys::signal; -use openssl; -use ordered_float; -use prolog_parser_rebis; -use ref_thread_local; -use ring; -use ripemd160; -use rustyline; -use sha3; -use unicode_reader; - #[cfg(feature = "num-rug-adapter")] use num_rug_adapter as rug; #[cfg(feature = "rug")] @@ -47,6 +26,7 @@ use machine::streams::*; use machine::*; use read::*; +use nix::sys::signal; use std::sync::atomic::Ordering; extern "C" fn handle_sigint(signal: libc::c_int) { diff --git a/src/read.rs b/src/read.rs index 4ed74fbf..ac2d3fa0 100644 --- a/src/read.rs +++ b/src/read.rs @@ -1,6 +1,6 @@ -use crate::prolog_parser_rebis::ast::*; -use crate::prolog_parser_rebis::parser::*; -use crate::prolog_parser_rebis::tabled_rc::TabledData; +use prolog_parser_rebis::ast::*; +use prolog_parser_rebis::parser::*; +use prolog_parser_rebis::tabled_rc::TabledData; use crate::forms::*; use crate::iterators::*; @@ -16,8 +16,8 @@ pub type PrologStream = ParsingStream; pub mod readline { use crate::machine::streams::Stream; - use crate::rustyline::error::ReadlineError; - use crate::rustyline::{Cmd, Config, Editor, KeyEvent}; + use rustyline::error::ReadlineError; + use rustyline::{Cmd, Config, Editor, KeyEvent}; use std::io::{Cursor, Error, ErrorKind, Read}; static mut PROMPT: bool = false; @@ -33,7 +33,11 @@ pub mod readline { #[inline] fn get_prompt() -> &'static str { unsafe { - if PROMPT { "?- " } else { "" } + if PROMPT { + "?- " + } else { + "" + } } } @@ -61,7 +65,10 @@ pub mod readline { } rl.bind_sequence(KeyEvent::from('\t'), Cmd::Insert(1, "\t".to_string())); - ReadlineStream { rl, pending_input: Cursor::new(pending_input) } + ReadlineStream { + rl, + pending_input: Cursor::new(pending_input), + } } #[inline] @@ -89,12 +96,8 @@ pub mod readline { self.pending_input.read(buf) } - Err(ReadlineError::Eof) => { - Ok(0) - } - Err(e) => { - Err(Error::new(ErrorKind::InvalidInput, e)) - } + Err(ReadlineError::Eof) => Ok(0), + Err(e) => Err(Error::new(ErrorKind::InvalidInput, e)), } } @@ -121,21 +124,15 @@ pub mod readline { Some(b) => { return Ok(b); } - None => { - match self.call_readline(&mut []) { - Err(e) => { - return Err(e); - } - Ok(0) => { - return Err(Error::new( - ErrorKind::UnexpectedEof, - "end of file", - )); - } - _ => { - } + None => match self.call_readline(&mut []) { + Err(e) => { + return Err(e); } - } + Ok(0) => { + return Err(Error::new(ErrorKind::UnexpectedEof, "end of file")); + } + _ => {} + }, } } } @@ -148,21 +145,15 @@ pub mod readline { Some(c) => { return Ok(c); } - None => { - match self.call_readline(&mut []) { - Err(e) => { - return Err(e); - } - Ok(0) => { - return Err(Error::new( - ErrorKind::UnexpectedEof, - "end of file", - )); - } - _ => { - } + None => match self.call_readline(&mut []) { + Err(e) => { + return Err(e); } - } + Ok(0) => { + return Err(Error::new(ErrorKind::UnexpectedEof, "end of file")); + } + _ => {} + }, } } } @@ -171,12 +162,8 @@ pub mod readline { impl Read for ReadlineStream { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { match self.pending_input.read(buf) { - Ok(0) => { - self.call_readline(buf) - } - result => { - result - } + Ok(0) => self.call_readline(buf), + result => result, } } } @@ -214,8 +201,7 @@ impl MachineState { } #[inline] -pub(crate) -fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult { +pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult { let term_writer = TermWriter::new(machine_st); term_writer.write_term_to_heap(term) } @@ -246,8 +232,7 @@ impl<'a> TermWriter<'a> { #[inline] fn modify_head_of_queue(&mut self, term: &TermRef<'a>, h: usize) { if let Some((arity, site_h)) = self.queue.pop_front() { - self.machine_st.heap[site_h] = - HeapCellValue::Addr(self.term_as_addr(term, h)); + self.machine_st.heap[site_h] = HeapCellValue::Addr(self.term_as_addr(term, h)); if arity > 1 { self.queue.push_front((arity - 1, site_h + 1)); @@ -258,26 +243,18 @@ impl<'a> TermWriter<'a> { #[inline] fn push_stub_addr(&mut self) { let h = self.machine_st.heap.h(); - self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); + self.machine_st + .heap + .push(HeapCellValue::Addr(Addr::HeapCell(h))); } fn term_as_addr(&mut self, term: &TermRef<'a>, h: usize) -> Addr { match term { - &TermRef::AnonVar(_) | &TermRef::Var(..) => { - Addr::HeapCell(h) - } - &TermRef::Cons(..) => { - Addr::HeapCell(h) - } - &TermRef::Constant(_, _, c) => { - self.machine_st.heap.put_constant(c.clone()) - } - &TermRef::Clause(..) => { - Addr::Str(h) - } - &TermRef::PartialString(..) => { - Addr::PStrLocation(h, 0) - } + &TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h), + &TermRef::Cons(..) => Addr::HeapCell(h), + &TermRef::Constant(_, _, c) => self.machine_st.heap.put_constant(c.clone()), + &TermRef::Clause(..) => Addr::Str(h), + &TermRef::PartialString(..) => Addr::PStrLocation(h, 0), } } @@ -290,7 +267,9 @@ impl<'a> TermWriter<'a> { match &term { &TermRef::Cons(lvl, ..) => { self.queue.push_back((2, h + 1)); - self.machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1))); + self.machine_st + .heap + .push(HeapCellValue::Addr(Addr::Lis(h + 1))); self.push_stub_addr(); self.push_stub_addr(); @@ -359,13 +338,15 @@ impl<'a> TermWriter<'a> { continue; } - _ => { - } + _ => {} }; self.modify_head_of_queue(&term, h); } - TermWriteResult { heap_loc, var_dict: self.var_dict } + TermWriteResult { + heap_loc, + var_dict: self.var_dict, + } } } diff --git a/src/targets.rs b/src/targets.rs index a75d3f79..c59fe47f 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -1,4 +1,4 @@ -use crate::prolog_parser_rebis::ast::*; +use prolog_parser_rebis::ast::*; use crate::clause_types::*; use crate::forms::*; From bc6159c5380e728a3e41f52005a13c4f492e90fc Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:32:52 +0100 Subject: [PATCH 047/137] change prolog_parse_rebis to use 2018 edition rust so all crates use the same edition --- crates/prolog_parser/Cargo.toml | 1 + crates/prolog_parser/src/ast.rs | 351 +++++++++--------- crates/prolog_parser/src/lexer.rs | 303 ++++++++-------- crates/prolog_parser/src/lib.rs | 18 +- crates/prolog_parser/src/parser.rs | 561 +++++++++++++++-------------- 5 files changed, 626 insertions(+), 608 deletions(-) diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml index dfdc5a32..83114a6e 100644 --- a/crates/prolog_parser/Cargo.toml +++ b/crates/prolog_parser/Cargo.toml @@ -2,6 +2,7 @@ name = "prolog_parser_rebis" version = "0.8.68" authors = ["Mark Thom "] +edition = "2018" repository = "https://github.com/mthom/prolog_parser" description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation." license = "BSD-3-Clause" diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index d337e9c7..ba480415 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -1,8 +1,8 @@ -use rug::{Integer, Rational}; +use crate::tabled_rc::*; use ordered_float::*; -use tabled_rc::*; +use rug::{Integer, Rational}; -use put_back_n::*; +use crate::put_back_n::*; use std::cell::Cell; use std::cmp::Ordering; @@ -27,112 +27,140 @@ pub const MAX_ARITY: usize = 1023; pub const XFX: u32 = 0x0001; pub const XFY: u32 = 0x0002; pub const YFX: u32 = 0x0004; -pub const XF: u32 = 0x0010; -pub const YF: u32 = 0x0020; -pub const FX: u32 = 0x0040; -pub const FY: u32 = 0x0080; +pub const XF: u32 = 0x0010; +pub const YF: u32 = 0x0020; +pub const FX: u32 = 0x0040; +pub const FY: u32 = 0x0080; pub const DELIMITER: u32 = 0x0100; -pub const TERM: u32 = 0x1000; +pub const TERM: u32 = 0x1000; pub const LTERM: u32 = 0x3000; pub const NEGATIVE_SIGN: u32 = 0x0200; #[macro_export] macro_rules! clause_name { - ($name: expr, $tbl: expr) => ( + ($name: expr, $tbl: expr) => { ClauseName::User(TabledRc::new($name, $tbl.clone())) - ) ; - ($name: expr) => ( + }; + ($name: expr) => { ClauseName::BuiltIn($name) - ) + }; } #[macro_export] macro_rules! atom { - ($e:expr, $tbl:expr) => ( + ($e:expr, $tbl:expr) => { Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)), None) - ); - ($e:expr) => ( + }; + ($e:expr) => { Constant::Atom(clause_name!($e), None) - ) + }; } #[macro_export] macro_rules! rc_atom { - ($e:expr) => ( + ($e:expr) => { Rc::new(String::from($e)) - ) + }; } macro_rules! is_term { - ($x:expr) => ( ($x & TERM) != 0 ) + ($x:expr) => { + ($x & TERM) != 0 + }; } macro_rules! is_lterm { - ($x:expr) => ( ($x & LTERM) != 0 ) + ($x:expr) => { + ($x & LTERM) != 0 + }; } macro_rules! is_op { - ($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 ) + ($x:expr) => { + $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 + }; } macro_rules! is_negate { - ($x:expr) => ( ($x & NEGATIVE_SIGN) != 0 ) + ($x:expr) => { + ($x & NEGATIVE_SIGN) != 0 + }; } #[macro_export] macro_rules! is_prefix { - ($x:expr) => ( $x & (FX | FY) != 0 ) + ($x:expr) => { + $x & (FX | FY) != 0 + }; } #[macro_export] macro_rules! is_postfix { - ($x:expr) => ( $x & (XF | YF) != 0 ) + ($x:expr) => { + $x & (XF | YF) != 0 + }; } #[macro_export] macro_rules! is_infix { - ($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 ) + ($x:expr) => { + ($x & (XFX | XFY | YFX)) != 0 + }; } #[macro_export] macro_rules! is_xfx { - ($x:expr) => ( ($x & XFX) != 0 ) + ($x:expr) => { + ($x & XFX) != 0 + }; } #[macro_export] macro_rules! is_xfy { - ($x:expr) => ( ($x & XFY) != 0 ) + ($x:expr) => { + ($x & XFY) != 0 + }; } #[macro_export] macro_rules! is_yfx { - ($x:expr) => ( ($x & YFX) != 0 ) + ($x:expr) => { + ($x & YFX) != 0 + }; } #[macro_export] macro_rules! is_yf { - ($x:expr) => ( ($x & YF) != 0 ) + ($x:expr) => { + ($x & YF) != 0 + }; } #[macro_export] macro_rules! is_xf { - ($x:expr) => ( ($x & XF) != 0 ) + ($x:expr) => { + ($x & XF) != 0 + }; } #[macro_export] macro_rules! is_fx { - ($x:expr) => ( ($x & FX) != 0 ) + ($x:expr) => { + ($x & FX) != 0 + }; } #[macro_export] macro_rules! is_fy { - ($x:expr) => ( ($x & FY) != 0 ) + ($x:expr) => { + ($x & FY) != 0 + }; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum RegType { Perm(usize), - Temp(usize) + Temp(usize), } impl Default for RegType { @@ -144,14 +172,14 @@ impl Default for RegType { impl RegType { pub fn reg_num(self) -> usize { match self { - RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num + RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num, } } pub fn is_perm(self) -> bool { match self { RegType::Perm(_) => true, - _ => false + _ => false, } } } @@ -160,7 +188,7 @@ impl fmt::Display for RegType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &RegType::Perm(val) => write!(f, "Y{}", val), - &RegType::Temp(val) => write!(f, "X{}", val) + &RegType::Temp(val) => write!(f, "X{}", val), } } } @@ -168,13 +196,13 @@ impl fmt::Display for RegType { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum VarReg { ArgAndNorm(RegType, usize), - Norm(RegType) + Norm(RegType), } impl VarReg { pub fn norm(self) -> RegType { match self { - VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg + VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg, } } } @@ -184,10 +212,8 @@ impl fmt::Display for VarReg { match self { &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg), &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg), - &VarReg::ArgAndNorm(RegType::Perm(reg), arg) => - write!(f, "Y{} A{}", reg, arg), - &VarReg::ArgAndNorm(RegType::Temp(reg), arg) => - write!(f, "X{} A{}", reg, arg) + &VarReg::ArgAndNorm(RegType::Perm(reg), arg) => write!(f, "Y{} A{}", reg, arg), + &VarReg::ArgAndNorm(RegType::Temp(reg), arg) => write!(f, "X{} A{}", reg, arg), } } } @@ -200,28 +226,30 @@ impl Default for VarReg { #[macro_export] macro_rules! temp_v { - ($x:expr) => ( + ($x:expr) => { RegType::Temp($x) - ) + }; } #[macro_export] macro_rules! perm_v { - ($x:expr) => ( + ($x:expr) => { RegType::Perm($x) - ) + }; } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum GenContext { - Head, Mid(usize), Last(usize) // Mid & Last: chunk_num + Head, + Mid(usize), + Last(usize), // Mid & Last: chunk_num } impl GenContext { pub fn chunk_num(self) -> usize { match self { GenContext::Head => 0, - GenContext::Mid(cn) | GenContext::Last(cn) => cn + GenContext::Mid(cn) | GenContext::Last(cn) => cn, } } } @@ -247,18 +275,22 @@ pub type OpDir = HashMap; #[derive(Debug, Clone, Copy)] pub struct MachineFlags { - pub double_quotes: DoubleQuotes + pub double_quotes: DoubleQuotes, } impl Default for MachineFlags { fn default() -> Self { - MachineFlags { double_quotes: DoubleQuotes::default() } + MachineFlags { + double_quotes: DoubleQuotes::default(), + } } } #[derive(Debug, Clone, Copy)] pub enum DoubleQuotes { - Atom, Chars, Codes + Atom, + Chars, + Codes, } impl DoubleQuotes { @@ -296,10 +328,10 @@ impl Default for DoubleQuotes { pub fn default_op_dir() -> OpDir { let mut op_dir = OpDir::new(); - op_dir.insert((clause_name!(":-"), Fixity::In), OpDirValue::new(XFX, 1200)); - op_dir.insert((clause_name!(":-"), Fixity::Pre), OpDirValue::new(FX, 1200)); - op_dir.insert((clause_name!("?-"), Fixity::Pre), OpDirValue::new(FX, 1200)); - op_dir.insert((clause_name!(","), Fixity::In), OpDirValue::new(XFY, 1000)); + op_dir.insert((clause_name!(":-"), Fixity::In), OpDirValue::new(XFX, 1200)); + op_dir.insert((clause_name!(":-"), Fixity::Pre), OpDirValue::new(FX, 1200)); + op_dir.insert((clause_name!("?-"), Fixity::Pre), OpDirValue::new(FX, 1200)); + op_dir.insert((clause_name!(","), Fixity::In), OpDirValue::new(XFY, 1000)); op_dir } @@ -307,7 +339,7 @@ pub fn default_op_dir() -> OpDir { #[derive(Debug, Clone)] pub enum ArithmeticError { NonEvaluableFunctor(Constant, usize), - UninstantiatedVar + UninstantiatedVar, } #[derive(Debug)] @@ -321,47 +353,35 @@ pub enum ParserError { MissingQuote(usize, usize), NonPrologChar(usize, usize), ParseBigInt(usize, usize), - Utf8Error(usize, usize) + Utf8Error(usize, usize), } impl ParserError { pub fn line_and_col_num(&self) -> Option<(usize, usize)> { match self { &ParserError::BackQuotedString(line_num, col_num) - | &ParserError::UnexpectedChar(_, line_num, col_num) - | &ParserError::IncompleteReduction(line_num, col_num) - | &ParserError::MissingQuote(line_num, col_num) - | &ParserError::NonPrologChar(line_num, col_num) - | &ParserError::ParseBigInt(line_num, col_num) - | &ParserError::Utf8Error(line_num, col_num) => - Some((line_num, col_num)), - _ => - None + | &ParserError::UnexpectedChar(_, line_num, col_num) + | &ParserError::IncompleteReduction(line_num, col_num) + | &ParserError::MissingQuote(line_num, col_num) + | &ParserError::NonPrologChar(line_num, col_num) + | &ParserError::ParseBigInt(line_num, col_num) + | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)), + _ => None, } } pub fn as_str(&self) -> &'static str { match self { - &ParserError::BackQuotedString(..) => - "back_quoted_string", - &ParserError::UnexpectedChar(..) => - "unexpected_char", - &ParserError::UnexpectedEOF => - "unexpected_end_of_file", - &ParserError::IncompleteReduction(..) => - "incomplete_reduction", - &ParserError::InvalidSingleQuotedCharacter(..) => - "invalid_single_quoted_character", - &ParserError::IO(_) => - "input_output_error", - &ParserError::MissingQuote(..) => - "missing_quote", - &ParserError::NonPrologChar(..) => - "non_prolog_character", - &ParserError::ParseBigInt(..) => - "cannot_parse_big_int", - &ParserError::Utf8Error(..) => - "utf8_conversion_error", + &ParserError::BackQuotedString(..) => "back_quoted_string", + &ParserError::UnexpectedChar(..) => "unexpected_char", + &ParserError::UnexpectedEOF => "unexpected_end_of_file", + &ParserError::IncompleteReduction(..) => "incomplete_reduction", + &ParserError::InvalidSingleQuotedCharacter(..) => "invalid_single_quoted_character", + &ParserError::IO(_) => "input_output_error", + &ParserError::MissingQuote(..) => "missing_quote", + &ParserError::NonPrologChar(..) => "non_prolog_character", + &ParserError::ParseBigInt(..) => "cannot_parse_big_int", + &ParserError::Utf8Error(..) => "utf8_conversion_error", } } } @@ -382,39 +402,38 @@ impl From<&IOError> for ParserError { } } - #[derive(Debug, Clone, Copy)] pub struct CompositeOpDir<'a, 'b> { pub primary_op_dir: Option<&'b OpDir>, pub secondary_op_dir: &'a OpDir, } -impl<'a, 'b> CompositeOpDir<'a, 'b> -{ +impl<'a, 'b> CompositeOpDir<'a, 'b> { #[inline] pub fn new(secondary_op_dir: &'a OpDir, primary_op_dir: Option<&'b OpDir>) -> Self { - CompositeOpDir { primary_op_dir, secondary_op_dir } + CompositeOpDir { + primary_op_dir, + secondary_op_dir, + } } #[inline] - pub(crate) - fn get(&self, name: ClauseName, fixity: Fixity) -> Option<&OpDirValue> - { - let entry = - if let Some(ref primary_op_dir) = &self.primary_op_dir { - primary_op_dir.get(&(name.clone(), fixity)) - } else { - None - }; + pub(crate) fn get(&self, name: ClauseName, fixity: Fixity) -> Option<&OpDirValue> { + let entry = if let Some(ref primary_op_dir) = &self.primary_op_dir { + primary_op_dir.get(&(name.clone(), fixity)) + } else { + None + }; entry.or_else(move || self.secondary_op_dir.get(&(name, fixity))) } } - #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)] pub enum Fixity { - In, Post, Pre + In, + Post, + Pre, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -496,28 +515,21 @@ pub enum Constant { impl fmt::Display for Constant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &Constant::Atom(ref atom, _) => + &Constant::Atom(ref atom, _) => { if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) { write!(f, "'{}'", atom.as_str()) } else { write!(f, "{}", atom.as_str()) - }, - &Constant::Char(c) => - write!(f, "'{}'", c as u32), - &Constant::EmptyList => - write!(f, "[]"), - &Constant::Fixnum(n) => - write!(f, "{}", n), - &Constant::Integer(ref n) => - write!(f, "{}", n), - &Constant::Rational(ref n) => - write!(f, "{}", n), - &Constant::Float(ref n) => - write!(f, "{}", n), - &Constant::String(ref s) => - write!(f, "\"{}\"", &s), - &Constant::Usize(integer) => - write!(f, "u{}", integer), + } + } + &Constant::Char(c) => write!(f, "'{}'", c as u32), + &Constant::EmptyList => write!(f, "[]"), + &Constant::Fixnum(n) => write!(f, "{}", n), + &Constant::Integer(ref n) => write!(f, "{}", n), + &Constant::Rational(ref n) => write!(f, "{}", n), + &Constant::Float(ref n) => write!(f, "{}", n), + &Constant::String(ref s) => write!(f, "\"{}\"", &s), + &Constant::Usize(integer) => write!(f, "u{}", integer), } } } @@ -526,37 +538,27 @@ impl PartialEq for Constant { fn eq(&self, other: &Constant) -> bool { match (self, other) { (&Constant::Atom(ref atom, _), &Constant::Char(c)) - | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => { - atom.is_char() && Some(c) == atom.as_str().chars().next() - }, - (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => - a1.as_str() == a2.as_str(), - (&Constant::Char(c1), &Constant::Char(c2)) => - c1 == c2, - (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => - n1 == n2, - (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) | - (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => { + | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => { + atom.is_char() && Some(c) == atom.as_str().chars().next() + } + (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(), + (&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2, + (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => n1 == n2, + (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) + | (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => { if let Some(n2) = n2.to_isize() { n1 == n2 } else { false } } - (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => - n1 == n2, - (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => - n1 == n2, - (&Constant::Float(ref n1), &Constant::Float(ref n2)) => - n1 == n2, - (&Constant::String(ref s1), &Constant::String(ref s2)) => { - &s1 == &s2 - } - (&Constant::EmptyList, &Constant::EmptyList) => - true, - (&Constant::Usize(u1), &Constant::Usize(u2)) => - u1 == u2, - _ => false + (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2, + (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2, + (&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2, + (&Constant::String(ref s1), &Constant::String(ref s2)) => &s1 == &s2, + (&Constant::EmptyList, &Constant::EmptyList) => true, + (&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2, + _ => false, } } } @@ -567,7 +569,7 @@ impl Constant { pub fn to_atom(self) -> Option { match self { Constant::Atom(a, _) => Some(a.defrock_brackets()), - _ => None + _ => None, } } } @@ -575,7 +577,7 @@ impl Constant { #[derive(Debug, Clone)] pub enum ClauseName { BuiltIn(&'static str), - User(TabledRc) + User(TabledRc), } impl fmt::Display for ClauseName { @@ -622,10 +624,12 @@ impl ClauseName { match self { &ClauseName::User(ref name) => { let module = name.owning_module(); - ClauseName::User(TabledRc { atom: module.clone(), - table: TabledData::new(module) }) - }, - _ => clause_name!("user") + ClauseName::User(TabledRc { + atom: module.clone(), + table: TabledData::new(module), + }) + } + _ => clause_name!("user"), } } @@ -633,7 +637,7 @@ impl ClauseName { pub fn to_rc(&self) -> Rc { match self { &ClauseName::BuiltIn(s) => Rc::new(s.to_string()), - &ClauseName::User(ref rc) => rc.inner() + &ClauseName::User(ref rc) => rc.inner(), } } @@ -666,9 +670,7 @@ impl ClauseName { false } } - ClauseName::User(ref name) => { - other.has_table(&name.table) - } + ClauseName::User(ref name) => other.has_table(&name.table), } } @@ -676,7 +678,7 @@ impl ClauseName { pub fn as_str(&self) -> &str { match self { &ClauseName::BuiltIn(s) => s, - &ClauseName::User(ref name) => name.as_ref() + &ClauseName::User(ref name) => name.as_ref(), } } @@ -688,17 +690,17 @@ impl ClauseName { pub fn defrock_brackets(self) -> Self { fn defrock_brackets(s: &str) -> &str { if s.starts_with('(') && s.ends_with(')') { - &s[1 .. s.len() - 1] + &s[1..s.len() - 1] } else { s } } match self { - ClauseName::BuiltIn(s) => - ClauseName::BuiltIn(defrock_brackets(s)), - ClauseName::User(s) => + ClauseName::BuiltIn(s) => ClauseName::BuiltIn(defrock_brackets(s)), + ClauseName::User(s) => { ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table)) + } } } } @@ -713,10 +715,15 @@ impl AsRef for ClauseName { #[derive(Debug, PartialEq, Eq, Clone)] pub enum Term { AnonVar, - Clause(Cell, ClauseName, Vec>, Option), + Clause( + Cell, + ClauseName, + Vec>, + Option, + ), Cons(Cell, Box, Box), Constant(Cell, Constant), - Var(Cell, Rc) + Var(Cell, Rc), } impl Term { @@ -724,30 +731,29 @@ impl Term { match self { &Term::Clause(_, _, _, ref spec) => spec.clone(), &Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(), - _ => None + _ => None, } } pub fn to_constant(self) -> Option { match self { Term::Constant(_, c) => Some(c), - _ => None + _ => None, } } pub fn first_arg(&self) -> Option<&Term> { match self { - &Term::Clause(_, _, ref terms, _) => - terms.first().map(|bt| bt.as_ref()), - _ => None + &Term::Clause(_, _, ref terms, _) => terms.first().map(|bt| bt.as_ref()), + _ => None, } } pub fn set_name(&mut self, new_name: ClauseName) { match self { Term::Constant(_, Constant::Atom(ref mut atom, _)) - | Term::Clause(_, ref mut atom, ..) => { - *atom = new_name; + | Term::Clause(_, ref mut atom, ..) => { + *atom = new_name; } _ => {} } @@ -755,16 +761,17 @@ impl Term { pub fn name(&self) -> Option { match self { - &Term::Constant(_, Constant::Atom(ref atom, _)) - | &Term::Clause(_, ref atom, ..) => Some(atom.clone()), - _ => None + &Term::Constant(_, Constant::Atom(ref atom, _)) | &Term::Clause(_, ref atom, ..) => { + Some(atom.clone()) + } + _ => None, } } pub fn arity(&self) -> usize { match self { &Term::Clause(_, _, ref child_terms, ..) => child_terms.len(), - _ => 0 + _ => 0, } } } diff --git a/crates/prolog_parser/src/lexer.rs b/crates/prolog_parser/src/lexer.rs index b1656a55..16c60d19 100644 --- a/crates/prolog_parser/src/lexer.rs +++ b/crates/prolog_parser/src/lexer.rs @@ -1,9 +1,9 @@ -use crate::lexical::parse_lossy; -use crate::ordered_float::*; use crate::rug::Integer; +use lexical::parse_lossy; +use ordered_float::*; -use ast::*; -use tabled_rc::*; +use crate::ast::*; +use crate::tabled_rc::*; use std::convert::TryFrom; use std::fmt; @@ -11,13 +11,13 @@ use std::io::Read; use std::rc::Rc; macro_rules! is_not_eof { - ($c:expr) => ( + ($c:expr) => { match $c { Ok(c) => c, Err(ParserError::UnexpectedEOF) => return Ok(true), - Err(e) => return Err(e) + Err(e) => return Err(e), } - ) + }; } macro_rules! consume_chars_with { @@ -27,26 +27,26 @@ macro_rules! consume_chars_with { Ok(Some(c)) => $token.push(c), Ok(None) => continue, Err(ParserError::UnexpectedChar(..)) => break, - Err(e) => return Err(e) + Err(e) => return Err(e), } } - } + }; } #[derive(Debug, Clone, PartialEq)] pub enum Token { Constant(Constant), Var(Rc), - Open, // '(' - OpenCT, // '(' - Close, // ')' - OpenList, // '[' - CloseList, // ']' - OpenCurly, // '{' - CloseCurly, // '}' + Open, // '(' + OpenCT, // '(' + Close, // ')' + OpenList, // '[' + CloseList, // ']' + OpenCurly, // '{' + CloseCurly, // '}' HeadTailSeparator, // '|' - Comma, // ',' - End + Comma, // ',' + End, } pub struct Lexer<'a, R: Read> { @@ -54,17 +54,17 @@ pub struct Lexer<'a, R: Read> { pub(crate) reader: &'a mut ParsingStream, pub(crate) flags: MachineFlags, pub(crate) line_num: usize, - pub(crate) col_num: usize + pub(crate) col_num: usize, } impl<'a, R: Read + fmt::Debug> fmt::Debug for Lexer<'a, R> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Lexer") - .field("atom_tbl", &self.atom_tbl) - .field("reader", &"&'a mut ParsingStream") // Hacky solution. - .field("line_num", &self.line_num) - .field("col_num", &self.col_num) - .finish() + .field("atom_tbl", &self.atom_tbl) + .field("reader", &"&'a mut ParsingStream") // Hacky solution. + .field("line_num", &self.line_num) + .field("col_num", &self.col_num) + .finish() } } @@ -74,7 +74,13 @@ impl<'a, R: Read> Lexer<'a, R> { flags: MachineFlags, src: &'a mut ParsingStream, ) -> Self { - Lexer { atom_tbl, flags, reader: src, line_num: 0, col_num: 0 } + Lexer { + atom_tbl, + flags, + reader: src, + line_num: 0, + col_num: 0, + } } fn return_char(&mut self, c: char) { @@ -128,8 +134,7 @@ impl<'a, R: Read> Lexer<'a, R> { } } - fn single_line_comment(&mut self) -> Result<(), ParserError> - { + fn single_line_comment(&mut self) -> Result<(), ParserError> { loop { if self.reader.peek().is_none() || new_line_char!(self.skip_char()?) { break; @@ -229,8 +234,7 @@ impl<'a, R: Read> Lexer<'a, R> { } } - fn get_single_quoted_item(&mut self) -> Result, ParserError> - { + fn get_single_quoted_item(&mut self) -> Result, ParserError> { if backslash_char!(self.lookahead_char()?) { let c = self.skip_char()?; @@ -264,14 +268,13 @@ impl<'a, R: Read> Lexer<'a, R> { } } - fn get_double_quoted_item(&mut self) -> Result, ParserError> - { + fn get_double_quoted_item(&mut self) -> Result, ParserError> { if backslash_char!(self.lookahead_char()?) { let c = self.skip_char()?; if new_line_char!(self.lookahead_char()?) { self.skip_char()?; - return Ok(None) + return Ok(None); } else { self.return_char(c); } @@ -299,8 +302,7 @@ impl<'a, R: Read> Lexer<'a, R> { } } - fn get_control_escape_sequence(&mut self) -> Result - { + fn get_control_escape_sequence(&mut self) -> Result { let escaped = match self.lookahead_char()? { 'a' => '\u{07}', // UTF-8 alert 'b' => '\u{08}', // UTF-8 backspace @@ -309,20 +311,18 @@ impl<'a, R: Read> Lexer<'a, R> { 't' => '\t', 'n' => '\n', 'r' => '\r', - c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)), }; self.skip_char()?; return Ok(escaped); } - fn get_octal_escape_sequence(&mut self) -> Result - { + fn get_octal_escape_sequence(&mut self) -> Result { self.escape_sequence_to_char(|c| octal_digit_char!(c), 8) } - fn get_hexadecimal_escape_sequence(&mut self) -> Result - { + fn get_hexadecimal_escape_sequence(&mut self) -> Result { self.skip_char()?; let c = self.lookahead_char()?; @@ -354,12 +354,13 @@ impl<'a, R: Read> Lexer<'a, R> { if backslash_char!(c) { self.skip_char()?; - u32::from_str_radix(&token, radix) - .map_or_else( - |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)), - |n| char::try_from(n) + u32::from_str_radix(&token, radix).map_or_else( + |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)), + |n| { + char::try_from(n) .map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num)) - ) + }, + ) } else { // on failure, restore the token characters and backslash. self.reader.put_back_all(token.chars().map(Ok)); @@ -423,11 +424,8 @@ impl<'a, R: Read> Lexer<'a, R> { .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { Integer::from_str_radix(&token, 16) - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } else { self.return_char('x'); @@ -449,11 +447,8 @@ impl<'a, R: Read> Lexer<'a, R> { .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { Integer::from_str_radix(&token, 8) - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } else { self.return_char('o'); @@ -475,11 +470,8 @@ impl<'a, R: Read> Lexer<'a, R> { .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { Integer::from_str_radix(&token, 2) - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } else { self.return_char('b'); @@ -531,12 +523,14 @@ impl<'a, R: Read> Lexer<'a, R> { } } } else { - return Err(ParserError::InvalidSingleQuotedCharacter(self.lookahead_char()?)) + return Err(ParserError::InvalidSingleQuotedCharacter( + self.lookahead_char()?, + )); } } else { match self.get_back_quoted_string() { - Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)), - Err(e) => return Err(e) + Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)), + Err(e) => return Err(e), } } @@ -575,12 +569,10 @@ impl<'a, R: Read> Lexer<'a, R> { isize::from_str_radix(&token, 10) .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } else if decimal_digit_char!(self.lookahead_char()?) { token.push('.'); @@ -599,7 +591,7 @@ impl<'a, R: Read> Lexer<'a, R> { let c = match self.lookahead_char() { Err(_) => return Ok(self.vacate_with_float(token)), - Ok(c) => c + Ok(c) => c, }; if !sign_char!(c) && !decimal_digit_char!(c) { @@ -613,8 +605,8 @@ impl<'a, R: Read> Lexer<'a, R> { Err(_) => { self.return_char(token.pop().unwrap()); return Ok(self.vacate_with_float(token)); - }, - Ok(c) => c + } + Ok(c) => c, }; if !decimal_digit_char!(c) { @@ -645,70 +637,65 @@ impl<'a, R: Read> Lexer<'a, R> { isize::from_str_radix(&token, 10) .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } } else { if token.starts_with('0') && token.len() == 1 { if c == 'x' { - self.hexadecimal_constant() - .or_else(|e| { - if let ParserError::ParseBigInt(..) = e { - isize::from_str_radix(&token, 10) - .map(|n| Token::Constant(Constant::Fixnum(n))) - .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) - }) - } else { - Err(e) - } - }) + self.hexadecimal_constant().or_else(|e| { + if let ParserError::ParseBigInt(..) = e { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| { + ParserError::ParseBigInt(self.line_num, self.col_num) + }) + }) + } else { + Err(e) + } + }) } else if c == 'o' { - self.octal_constant() - .or_else(|e| { - if let ParserError::ParseBigInt(..) = e { - isize::from_str_radix(&token, 10) - .map(|n| Token::Constant(Constant::Fixnum(n))) - .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) - }) - } else { - Err(e) - } - }) + self.octal_constant().or_else(|e| { + if let ParserError::ParseBigInt(..) = e { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| { + ParserError::ParseBigInt(self.line_num, self.col_num) + }) + }) + } else { + Err(e) + } + }) } else if c == 'b' { - self.binary_constant() - .or_else(|e| { - if let ParserError::ParseBigInt(..) = e { - isize::from_str_radix(&token, 10) - .map(|n| Token::Constant(Constant::Fixnum(n))) - .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) - }) - } else { - Err(e) - } - }) + self.binary_constant().or_else(|e| { + if let ParserError::ParseBigInt(..) = e { + isize::from_str_radix(&token, 10) + .map(|n| Token::Constant(Constant::Fixnum(n))) + .or_else(|_| { + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| { + ParserError::ParseBigInt(self.line_num, self.col_num) + }) + }) + } else { + Err(e) + } + }) } else if single_quote_char!(c) { self.skip_char()?; @@ -726,45 +713,39 @@ impl<'a, R: Read> Lexer<'a, R> { } self.get_single_quoted_char() - .and_then(|c| { - Ok(Token::Constant(Constant::Fixnum(c as isize))) - }) + .and_then(|c| Ok(Token::Constant(Constant::Fixnum(c as isize)))) .or_else(|_| { self.return_char(c); isize::from_str_radix(&token, 10) .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| { + ParserError::ParseBigInt(self.line_num, self.col_num) + }) }) }) } else { isize::from_str_radix(&token, 10) .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } } else { isize::from_str_radix(&token, 10) .map(|n| Token::Constant(Constant::Fixnum(n))) .or_else(|_| { - token.parse::() - .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) - .map_err(|_| ParserError::ParseBigInt( - self.line_num, - self.col_num, - )) + token + .parse::() + .map(|n| Token::Constant(Constant::Integer(Rc::new(n)))) + .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) }) } } @@ -781,18 +762,19 @@ impl<'a, R: Read> Lexer<'a, R> { Ok(c) if layout_char!(c) || new_line_char!(c) => { self.skip_char()?; layout_inserted = true; - }, + } Ok(c) if end_line_comment_char!(c) => { self.single_line_comment()?; layout_inserted = true; - }, - Ok(c) if comment_1_char!(c) => + } + Ok(c) if comment_1_char!(c) => { if self.bracketed_comment()? { layout_inserted = true; } else { more_layout = false; - }, - _ => more_layout = false + } + } + _ => more_layout = false, }; if !more_layout { @@ -825,8 +807,11 @@ impl<'a, R: Read> Lexer<'a, R> { if c == '(' { self.skip_char()?; - return Ok(if layout_inserted { Token::Open } - else { Token::OpenCT }); + return Ok(if layout_inserted { + Token::Open + } else { + Token::OpenCT + }); } if c == '.' { @@ -839,7 +824,7 @@ impl<'a, R: Read> Lexer<'a, R> { } return Ok(Token::End); - }, + } Err(ParserError::UnexpectedEOF) => { return Ok(Token::End); } @@ -891,8 +876,8 @@ impl<'a, R: Read> Lexer<'a, R> { } self.name_token(c) - }, - Err(e) => Err(e) + } + Err(e) => Err(e), } } } diff --git a/crates/prolog_parser/src/lib.rs b/crates/prolog_parser/src/lib.rs index f8ef7536..2c37cea6 100644 --- a/crates/prolog_parser/src/lib.rs +++ b/crates/prolog_parser/src/lib.rs @@ -1,14 +1,14 @@ -extern crate lexical; -extern crate ordered_float; -#[cfg(feature = "rug")] -extern crate rug; #[cfg(feature = "num-rug-adapter")] -extern crate num_rug_adapter as rug; -extern crate unicode_reader; +use num_rug_adapter as rug; +#[cfg(feature = "rug")] +use rug; -#[macro_use] pub mod tabled_rc; -#[macro_use] pub mod ast; -#[macro_use] pub mod macros; +#[macro_use] +pub mod tabled_rc; +#[macro_use] +pub mod ast; +#[macro_use] +pub mod macros; pub mod parser; pub mod put_back_n; diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index 19fd7912..87785daa 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -1,10 +1,10 @@ -use ast::*; -use lexer::*; -use tabled_rc::*; +use crate::ast::*; +use crate::lexer::*; +use crate::tabled_rc::*; use ordered_float::OrderedFloat; -use rug::ops::NegAssign; +use crate::rug::ops::NegAssign; use std::cell::Cell; use std::io::Read; @@ -16,24 +16,29 @@ enum TokenType { Term, Open, OpenCT, - OpenList, // '[' - OpenCurly, // '{' + OpenList, // '[' + OpenCurly, // '{' HeadTailSeparator, // '|' - Comma, // ',' + Comma, // ',' Close, - CloseList, // ']' - CloseCurly, // '}' - End + CloseList, // ']' + CloseCurly, // '}' + End, } impl TokenType { fn is_sep(self) -> bool { match self { - TokenType::HeadTailSeparator | TokenType::OpenCT | TokenType::Open | - TokenType::Close | TokenType::OpenList | TokenType::CloseList | - TokenType::OpenCurly | TokenType::CloseCurly | TokenType::Comma - => true, - _ => false + TokenType::HeadTailSeparator + | TokenType::OpenCT + | TokenType::Open + | TokenType::Close + | TokenType::OpenList + | TokenType::CloseList + | TokenType::OpenCurly + | TokenType::CloseCurly + | TokenType::Comma => true, + _ => false, } } } @@ -42,12 +47,14 @@ impl TokenType { struct TokenDesc { tt: TokenType, priority: usize, - spec: u32 + spec: u32, } -pub -fn get_clause_spec(name: ClauseName, arity: usize, op_dir: &CompositeOpDir) -> Option -{ +pub fn get_clause_spec( + name: ClauseName, + arity: usize, + op_dir: &CompositeOpDir, +) -> Option { match arity { 1 => { /* This is a clause with an operator principal functor. Prefix operators @@ -60,20 +67,25 @@ fn get_clause_spec(name: ClauseName, arity: usize, op_dir: &CompositeOpDir) -> O if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::Post) { return Some(cell.clone()); } - }, - 2 => + } + 2 => { if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::In) { return Some(cell.clone()); - }, + } + } _ => {} }; None } -pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option -{ - let mut op_desc = OpDesc { pre: 0, inf: 0, post: 0, spec: 0 }; +pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option { + let mut op_desc = OpDesc { + pre: 0, + inf: 0, + post: 0, + spec: 0, + }; if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Pre) { let (pri, spec) = cell.get(); @@ -111,8 +123,7 @@ pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option } } -fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool -{ +fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool { d2.priority <= priority && is_term!(d3.spec) && is_term!(d1.spec) @@ -120,18 +131,15 @@ fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> b && d1.priority < d2.priority } -fn affirm_yfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool -{ +fn affirm_yfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool { d2.priority <= priority - && ((is_term!(d3.spec) && d3.priority < d2.priority) - || (is_lterm!(d3.spec) && d3.priority == d2.priority)) + && ((is_term!(d3.spec) && d3.priority < d2.priority) + || (is_lterm!(d3.spec) && d3.priority == d2.priority)) && is_term!(d1.spec) && d1.priority < d2.priority } - -fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool -{ +fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool { d2.priority < priority && is_term!(d3.spec) && d3.priority < d2.priority @@ -139,49 +147,35 @@ fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> b && d1.priority <= d2.priority } -fn affirm_yf(d1: TokenDesc, d2: TokenDesc) -> bool -{ +fn affirm_yf(d1: TokenDesc, d2: TokenDesc) -> bool { let is_valid_lterm = is_lterm!(d2.spec) && d2.priority == d1.priority; (is_term!(d2.spec) && d2.priority < d1.priority) || is_valid_lterm } -fn affirm_xf(d1: TokenDesc, d2: TokenDesc) -> bool -{ +fn affirm_xf(d1: TokenDesc, d2: TokenDesc) -> bool { is_term!(d2.spec) && d2.priority < d1.priority } -fn affirm_fy(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool -{ +fn affirm_fy(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool { d2.priority < priority && is_term!(d1.spec) && d1.priority <= d2.priority } -fn affirm_fx(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool -{ +fn affirm_fx(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool { d2.priority <= priority && is_term!(d1.spec) && d1.priority < d2.priority } -fn sep_to_atom(tt: TokenType) -> Option -{ +fn sep_to_atom(tt: TokenType) -> Option { match tt { - TokenType::Open | TokenType::OpenCT => - Some(clause_name!("(")), - TokenType::Close => - Some(clause_name!(")")), - TokenType::OpenList => - Some(clause_name!("[")), - TokenType::CloseList => - Some(clause_name!("]")), - TokenType::OpenCurly => - Some(clause_name!("{")), - TokenType::CloseCurly => - Some(clause_name!("}")), - TokenType::HeadTailSeparator => - Some(clause_name!("|")), - TokenType::Comma => - Some(clause_name!(",")), - TokenType::End => - Some(clause_name!(".")), - _ => None + TokenType::Open | TokenType::OpenCT => Some(clause_name!("(")), + TokenType::Close => Some(clause_name!(")")), + TokenType::OpenList => Some(clause_name!("[")), + TokenType::CloseList => Some(clause_name!("]")), + TokenType::OpenCurly => Some(clause_name!("{")), + TokenType::CloseCurly => Some(clause_name!("}")), + TokenType::HeadTailSeparator => Some(clause_name!("|")), + TokenType::Comma => Some(clause_name!(",")), + TokenType::End => Some(clause_name!(".")), + _ => None, } } @@ -190,7 +184,7 @@ pub struct OpDesc { pub pre: usize, pub inf: usize, pub post: usize, - pub spec: Specifier + pub spec: Specifier, } #[derive(Debug)] @@ -201,8 +195,7 @@ pub struct Parser<'a, R: Read> { terms: Vec, } -fn read_tokens<'a, R: Read>(lexer: &mut Lexer<'a, R>) -> Result, ParserError> -{ +fn read_tokens<'a, R: Read>(lexer: &mut Lexer<'a, R>) -> Result, ParserError> { let mut tokens = vec![]; loop { @@ -227,10 +220,12 @@ impl<'a, R: Read> Parser<'a, R> { atom_tbl: TabledData, flags: MachineFlags, ) -> Self { - Parser { lexer: Lexer::new(atom_tbl, flags, stream), - tokens: vec![], - stack: Vec::new(), - terms: Vec::new() } + Parser { + lexer: Lexer::new(atom_tbl, flags, stream), + tokens: vec![], + stack: Vec::new(), + terms: Vec::new(), + } } #[inline] @@ -255,50 +250,46 @@ impl<'a, R: Read> Parser<'a, R> { fn get_term_name(&mut self, td: TokenDesc) -> Option<(ClauseName, Option)> { match td.tt { - TokenType::HeadTailSeparator => { - Some((clause_name!("|"), Some(SharedOpDesc::new(td.priority, td.spec)))) - } - TokenType::Comma => { - Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY)))) - } - TokenType::Term => { - match self.terms.pop() { - Some(Term::Constant(_, Constant::Atom(atom, spec))) => - Some((atom, spec)), - Some(term) => { - self.terms.push(term); - None - }, - _ => None + TokenType::HeadTailSeparator => Some(( + clause_name!("|"), + Some(SharedOpDesc::new(td.priority, td.spec)), + )), + TokenType::Comma => Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY)))), + TokenType::Term => match self.terms.pop() { + Some(Term::Constant(_, Constant::Atom(atom, spec))) => Some((atom, spec)), + Some(term) => { + self.terms.push(term); + None } - } - _ => { - None - } + _ => None, + }, + _ => None, } } - fn push_binary_op(&mut self, td: TokenDesc, spec: Specifier) - { + fn push_binary_op(&mut self, td: TokenDesc, spec: Specifier) { if let Some(arg2) = self.terms.pop() { if let Some((name, shared_op_desc)) = self.get_term_name(td) { if let Some(arg1) = self.terms.pop() { - let term = Term::Clause(Cell::default(), - name, - vec![Box::new(arg1), Box::new(arg2)], - shared_op_desc); + let term = Term::Clause( + Cell::default(), + name, + vec![Box::new(arg1), Box::new(arg2)], + shared_op_desc, + ); self.terms.push(term); - self.stack.push(TokenDesc { tt: TokenType::Term, - priority: td.priority, - spec }); + self.stack.push(TokenDesc { + tt: TokenType::Term, + priority: td.priority, + spec, + }); } } } } - fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: u32) - { + fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: u32) { if let Some(mut arg1) = self.terms.pop() { if let Some(mut name) = self.terms.pop() { if is_postfix!(assoc) { @@ -306,52 +297,61 @@ impl<'a, R: Read> Parser<'a, R> { } if let Term::Constant(_, Constant::Atom(name, shared_op_desc)) = name { - let term = Term::Clause(Cell::default(), name, vec![Box::new(arg1)], - shared_op_desc); + let term = + Term::Clause(Cell::default(), name, vec![Box::new(arg1)], shared_op_desc); self.terms.push(term); - self.stack.push(TokenDesc { tt: TokenType::Term, - priority: td.priority, - spec }); + self.stack.push(TokenDesc { + tt: TokenType::Term, + priority: td.priority, + spec, + }); } } } } - fn promote_atom_op(&mut self, atom: ClauseName, priority: usize, assoc: u32, - op_dir_val: Option<&OpDirValue>) - { + fn promote_atom_op( + &mut self, + atom: ClauseName, + priority: usize, + assoc: u32, + op_dir_val: Option<&OpDirValue>, + ) { let spec = op_dir_val.map(|op_dir_val| op_dir_val.shared_op_desc()); - self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, spec))); - self.stack.push(TokenDesc { tt: TokenType::Term, priority, spec: assoc }); + self.terms + .push(Term::Constant(Cell::default(), Constant::Atom(atom, spec))); + self.stack.push(TokenDesc { + tt: TokenType::Term, + priority, + spec: assoc, + }); } - fn shift(&mut self, token: Token, priority: usize, spec: Specifier) - { + fn shift(&mut self, token: Token, priority: usize, spec: Specifier) { let tt = match token { - Token::Constant(Constant::String(s)) - if self.lexer.flags.double_quotes.is_codes() => { - let mut list = Term::Constant(Cell::default(), Constant::EmptyList); + Token::Constant(Constant::String(s)) if self.lexer.flags.double_quotes.is_codes() => { + let mut list = Term::Constant(Cell::default(), Constant::EmptyList); - for c in s.chars().rev() { - list = Term::Cons( + for c in s.chars().rev() { + list = Term::Cons( + Cell::default(), + Box::new(Term::Constant( Cell::default(), - Box::new(Term::Constant( - Cell::default(), - Constant::Fixnum(c as isize), - )), - Box::new(list), - ); - } - - self.terms.push(list); - TokenType::Term + Constant::Fixnum(c as isize), + )), + Box::new(list), + ); } + + self.terms.push(list); + TokenType::Term + } Token::Constant(c) => { self.terms.push(Term::Constant(Cell::default(), c)); TokenType::Term - }, + } Token::Var(v) => { if v.trim() == "_" { self.terms.push(Term::AnonVar); @@ -360,7 +360,7 @@ impl<'a, R: Read> Parser<'a, R> { } TokenType::Term - }, + } Token::Comma => TokenType::Comma, Token::Open => TokenType::Open, Token::Close => TokenType::Close, @@ -381,18 +381,13 @@ impl<'a, R: Read> Parser<'a, R> { if let Some(desc1) = self.stack.pop() { if let Some(desc2) = self.stack.pop() { if let Some(desc3) = self.stack.pop() { - if is_xfx!(desc2.spec) && affirm_xfx(priority, desc2, desc3, desc1) - { + if is_xfx!(desc2.spec) && affirm_xfx(priority, desc2, desc3, desc1) { self.push_binary_op(desc2, LTERM); continue; - } - else if is_yfx!(desc2.spec) && affirm_yfx(priority, desc2, desc3, desc1) - { + } else if is_yfx!(desc2.spec) && affirm_yfx(priority, desc2, desc3, desc1) { self.push_binary_op(desc2, LTERM); continue; - } - else if is_xfy!(desc2.spec) && affirm_xfy(priority, desc2, desc3, desc1) - { + } else if is_xfy!(desc2.spec) && affirm_xfy(priority, desc2, desc3, desc1) { self.push_binary_op(desc2, TERM); continue; } else { @@ -425,12 +420,12 @@ impl<'a, R: Read> Parser<'a, R> { } } - fn compute_arity_in_brackets(&self) -> Option - { + fn compute_arity_in_brackets(&self) -> Option { let mut arity = 0; for (i, desc) in self.stack.iter().rev().enumerate() { - if i % 2 == 0 { // expect a term or non-comma operator. + if i % 2 == 0 { + // expect a term or non-comma operator. if let TokenType::Comma = desc.tt { return None; } else if is_term!(desc.spec) || is_op!(desc.spec) || is_negate!(desc.spec) { @@ -454,8 +449,7 @@ impl<'a, R: Read> Parser<'a, R> { None } - fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool - { + fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool { if self.stack.is_empty() { return false; } @@ -464,7 +458,7 @@ impl<'a, R: Read> Parser<'a, R> { let arity = match self.compute_arity_in_brackets() { Some(arity) => arity, - None => return false + None => return false, }; if self.stack.len() > 2 * arity { @@ -490,9 +484,7 @@ impl<'a, R: Read> Parser<'a, R> { if self.atomize_term(&self.terms[idx - 1]).is_some() { self.stack.truncate(stack_len + 1); - let mut subterms: Vec<_> = self.terms.drain(idx ..) - .map(|t| Box::new(t)) - .collect(); + let mut subterms: Vec<_> = self.terms.drain(idx..).map(|t| Box::new(t)).collect(); if let Some(name) = self.terms.pop().and_then(|t| self.atomize_term(&t)) { // reduce the '.' functor to a cons cell if it applies. @@ -503,11 +495,15 @@ impl<'a, R: Read> Parser<'a, R> { self.terms.push(Term::Cons(Cell::default(), head, tail)); } else { let spec = get_clause_spec(name.clone(), subterms.len(), op_dir); - self.terms.push(Term::Clause(Cell::default(), name, subterms, spec)); + self.terms + .push(Term::Clause(Cell::default(), name, subterms, spec)); } - if let Some(&mut TokenDesc { ref mut priority, ref mut spec, - ref mut tt }) = self.stack.last_mut() + if let Some(&mut TokenDesc { + ref mut priority, + ref mut spec, + ref mut tt, + }) = self.stack.last_mut() { *tt = TokenType::Term; *priority = 0; @@ -523,7 +519,7 @@ impl<'a, R: Read> Parser<'a, R> { } pub fn devour_whitespace(&mut self) -> Result<(), ParserError> { - self.lexer.scan_for_layout()?; + self.lexer.scan_for_layout()?; Ok(()) } @@ -531,8 +527,7 @@ impl<'a, R: Read> Parser<'a, R> { self.stack.clear() } - fn expand_comma_compacted_terms(&mut self, index: usize) -> usize - { + fn expand_comma_compacted_terms(&mut self, index: usize) -> usize { if let Some(term) = self.terms.pop() { let op_desc = self.stack[index - 1]; @@ -548,8 +543,7 @@ impl<'a, R: Read> Parser<'a, R> { self.terms.extend(terms.into_iter()); return arity; } - _ => { - } + _ => {} } } @@ -559,12 +553,12 @@ impl<'a, R: Read> Parser<'a, R> { 0 } - fn compute_arity_in_list(&self) -> Option - { + fn compute_arity_in_list(&self) -> Option { let mut arity = 0; for (i, desc) in self.stack.iter().rev().enumerate() { - if i % 2 == 0 { // expect a term or non-comma operator. + if i % 2 == 0 { + // expect a term or non-comma operator. if let TokenType::Comma = desc.tt { return None; } else if is_term!(desc.spec) || is_op!(desc.spec) { @@ -590,8 +584,7 @@ impl<'a, R: Read> Parser<'a, R> { None } - fn reduce_list(&mut self) -> Result - { + fn reduce_list(&mut self) -> Result { if self.stack.is_empty() { return Ok(false); } @@ -602,7 +595,8 @@ impl<'a, R: Read> Parser<'a, R> { td.tt = TokenType::Term; td.priority = 0; - self.terms.push(Term::Constant(Cell::default(), Constant::EmptyList)); + self.terms + .push(Term::Constant(Cell::default(), Constant::EmptyList)); return Ok(true); } } @@ -611,7 +605,7 @@ impl<'a, R: Read> Parser<'a, R> { let mut arity = match self.compute_arity_in_list() { Some(arity) => arity, - None => return Ok(false) + None => return Ok(false), }; // we know that self.stack.len() >= 2 by this point. @@ -621,12 +615,15 @@ impl<'a, R: Read> Parser<'a, R> { let end_term = if self.stack[idx].tt != TokenType::HeadTailSeparator { Term::Constant(Cell::default(), Constant::EmptyList) } else { - let term = - match self.terms.pop() { - Some(term) => term, - _ => return Err(ParserError::IncompleteReduction(self.lexer.line_num, - self.lexer.col_num)) - }; + let term = match self.terms.pop() { + Some(term) => term, + _ => { + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )) + } + }; if self.stack[idx].priority > 1000 { arity += self.expand_comma_compacted_terms(idx); @@ -639,15 +636,17 @@ impl<'a, R: Read> Parser<'a, R> { let idx = self.terms.len() - arity; - let list = self.terms.drain(idx ..) - .rev() - .fold(end_term, |acc, t| Term::Cons(Cell::default(), - Box::new(t), - Box::new(acc))); + let list = self.terms.drain(idx..).rev().fold(end_term, |acc, t| { + Term::Cons(Cell::default(), Box::new(t), Box::new(acc)) + }); self.stack.truncate(list_len); - self.stack.push(TokenDesc { tt: TokenType::Term, priority: 0, spec: TERM }); + self.stack.push(TokenDesc { + tt: TokenType::Term, + priority: 0, + spec: TERM, + }); self.terms.push(list); Ok(true) @@ -664,8 +663,7 @@ impl<'a, R: Read> Parser<'a, R> { td.priority = 0; td.spec = TERM; - let term = Term::Constant(Cell::default(), - atom!("{}", self.lexer.atom_tbl)); + let term = Term::Constant(Cell::default(), atom!("{}", self.lexer.atom_tbl)); self.terms.push(term); return Ok(true); } @@ -687,17 +685,19 @@ impl<'a, R: Read> Parser<'a, R> { let term = match self.terms.pop() { Some(term) => term, - _ => return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, - )) + _ => { + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )) + } }; self.terms.push(Term::Clause( Cell::default(), clause_name!("{}"), vec![Box::new(term)], - None + None, )); return Ok(true); @@ -723,29 +723,35 @@ impl<'a, R: Read> Parser<'a, R> { let idx = self.stack.len() - 2; match self.stack.remove(idx) { - td => - match td.tt { - TokenType::Open | TokenType::OpenCT => { - if self.stack[idx].tt == TokenType::Comma { - return false; - } + td => match td.tt { + TokenType::Open | TokenType::OpenCT => { + if self.stack[idx].tt == TokenType::Comma { + return false; + } - if let Some(atom) = sep_to_atom(self.stack[idx].tt) { - self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, None))); - } + if let Some(atom) = sep_to_atom(self.stack[idx].tt) { + self.terms + .push(Term::Constant(Cell::default(), Constant::Atom(atom, None))); + } - self.stack[idx].spec = TERM; - self.stack[idx].tt = TokenType::Term; - self.stack[idx].priority = 0; - true - }, - _ => false + self.stack[idx].spec = TERM; + self.stack[idx].tt = TokenType::Term; + self.stack[idx].priority = 0; + true } + _ => false, + }, } } fn shift_op(&mut self, name: ClauseName, op_dir: &CompositeOpDir) -> Result { - if let Some(OpDesc { pre, inf, post, spec }) = get_op_desc(name.clone(), op_dir) { + if let Some(OpDesc { + pre, + inf, + post, + spec, + }) = get_op_desc(name.clone(), op_dir) + { if (pre > 0 && inf + post > 0) || is_negate!(spec) { match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? { // do this when layout hasn't been inserted, @@ -764,7 +770,7 @@ impl<'a, R: Read> Parser<'a, R> { spec & (XFX | XFY | YFX | YF | XF), op_dir_val, ); - }, + } _ => { self.reduce_op(inf + post); @@ -782,11 +788,21 @@ impl<'a, R: Read> Parser<'a, R> { ); } else { let op_dir_val = op_dir.get(name.clone(), Fixity::Pre); - self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN), op_dir_val); + self.promote_atom_op( + name, + pre, + spec & (FX | FY | NEGATIVE_SIGN), + op_dir_val, + ); } } else { let op_dir_val = op_dir.get(name.clone(), Fixity::Pre); - self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN), op_dir_val); + self.promote_atom_op( + name, + pre, + spec & (FX | FY | NEGATIVE_SIGN), + op_dir_val, + ); } } } @@ -807,7 +823,8 @@ impl<'a, R: Read> Parser<'a, R> { } Ok(true) - } else { // not an operator. + } else { + // not an operator. Ok(false) } } @@ -815,41 +832,37 @@ impl<'a, R: Read> Parser<'a, R> { fn atomize_term(&self, term: &Term) -> Option { match term { &Term::Constant(_, ref c) => self.atomize_constant(c), - _ => None + _ => None, } } fn atomize_constant(&self, c: &Constant) -> Option { match c { &Constant::Atom(ref name, _) => Some(name.clone()), - &Constant::Char(c) => - Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), - &Constant::EmptyList => - Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), - _ => None + &Constant::Char(c) => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), + &Constant::EmptyList => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), + _ => None, } } - fn negate_number( - &mut self, - n: N, - negator: Negator, - constr: ToConstant - ) - where Negator: Fn(N) -> N, - ToConstant: Fn(N) -> Constant + fn negate_number(&mut self, n: N, negator: Negator, constr: ToConstant) + where + Negator: Fn(N) -> N, + ToConstant: Fn(N) -> Constant, { if let Some(desc) = self.stack.last().cloned() { if let Some(term) = self.terms.last().cloned() { match term { Term::Constant(_, Constant::Atom(ref name, _)) - if name.as_str() == "-" && (is_prefix!(desc.spec) || is_negate!(desc.spec)) => { - self.stack.pop(); - self.terms.pop(); + if name.as_str() == "-" + && (is_prefix!(desc.spec) || is_negate!(desc.spec)) => + { + self.stack.pop(); + self.terms.pop(); - self.shift(Token::Constant(constr(negator(n))), 0, TERM); - return; - }, + self.shift(Token::Constant(constr(negator(n))), 0, TERM); + return; + } _ => {} } } @@ -864,38 +877,36 @@ impl<'a, R: Read> Parser<'a, R> { Some(t) => { t.neg_assign(); } - None => { - } + None => {} }; t } match token { - Token::Constant(Constant::Fixnum(n)) => - self.negate_number(n, |n| -n, Constant::Fixnum), - Token::Constant(Constant::Integer(n)) => - self.negate_number(n, negate_rc, Constant::Integer), - Token::Constant(Constant::Rational(n)) => - self.negate_number(n, negate_rc, Constant::Rational), - Token::Constant(Constant::Float(n)) => - self.negate_number( - n, - |n| OrderedFloat(-n.into_inner()), - |n| Constant::Float(n) - ), - Token::Constant(c) => + Token::Constant(Constant::Fixnum(n)) => self.negate_number(n, |n| -n, Constant::Fixnum), + Token::Constant(Constant::Integer(n)) => { + self.negate_number(n, negate_rc, Constant::Integer) + } + Token::Constant(Constant::Rational(n)) => { + self.negate_number(n, negate_rc, Constant::Rational) + } + Token::Constant(Constant::Float(n)) => { + self.negate_number(n, |n| OrderedFloat(-n.into_inner()), |n| Constant::Float(n)) + } + Token::Constant(c) => { if let Some(name) = self.atomize_constant(&c) { if !self.shift_op(name, op_dir)? { self.shift(Token::Constant(c), 0, TERM); } } else { self.shift(Token::Constant(c), 0, TERM); - }, + } + } Token::Var(v) => self.shift(Token::Var(v), 0, TERM), - Token::Open => self.shift(Token::Open, 1300, DELIMITER), + Token::Open => self.shift(Token::Open, 1300, DELIMITER), Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER), - Token::Close => + Token::Close => { if !self.reduce_term(op_dir) { if !self.reduce_brackets() { return Err(ParserError::IncompleteReduction( @@ -903,23 +914,26 @@ impl<'a, R: Read> Parser<'a, R> { self.lexer.col_num, )); } - }, - Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER), - Token::CloseList => + } + } + Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER), + Token::CloseList => { if !self.reduce_list()? { return Err(ParserError::IncompleteReduction( self.lexer.line_num, self.lexer.col_num, )); - }, + } + } Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER), - Token::CloseCurly => + Token::CloseCurly => { if !self.reduce_curly()? { return Err(ParserError::IncompleteReduction( self.lexer.line_num, self.lexer.col_num, )); - }, + } + } Token::HeadTailSeparator => { /* '|' as an operator must have priority > 1000 and can only be infix. * See: http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#Res_A78 @@ -930,23 +944,25 @@ impl<'a, R: Read> Parser<'a, R> { self.reduce_op(priority); self.shift(Token::HeadTailSeparator, priority, spec); - }, + } Token::Comma => { self.reduce_op(1000); self.shift(Token::Comma, 1000, XFY); - }, - Token::End => - match self.stack.last().map(|t| t.tt) { - Some(TokenType::Open) - | Some(TokenType::OpenCT) - | Some(TokenType::OpenList) - | Some(TokenType::OpenCurly) - | Some(TokenType::HeadTailSeparator) - | Some(TokenType::Comma) - => return Err(ParserError::IncompleteReduction(self.lexer.line_num, - self.lexer.col_num)), - _ => {} + } + Token::End => match self.stack.last().map(|t| t.tt) { + Some(TokenType::Open) + | Some(TokenType::OpenCT) + | Some(TokenType::OpenList) + | Some(TokenType::OpenCurly) + | Some(TokenType::HeadTailSeparator) + | Some(TokenType::Comma) => { + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )) } + _ => {} + }, } Ok(()) @@ -957,8 +973,7 @@ impl<'a, R: Read> Parser<'a, R> { self.lexer.eof() } - pub fn read_term(&mut self, op_dir: &CompositeOpDir) -> Result - { + pub fn read_term(&mut self, op_dir: &CompositeOpDir) -> Result { self.tokens = read_tokens(&mut self.lexer)?; while let Some(token) = self.tokens.pop() { @@ -968,21 +983,31 @@ impl<'a, R: Read> Parser<'a, R> { self.reduce_op(1400); if self.terms.len() > 1 || self.stack.len() > 1 { - return Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num)); + return Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )); } match self.terms.pop() { - Some(term) => if self.terms.is_empty() { - Ok(term) - } else { - Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num)) - }, - _ => Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num)) + Some(term) => { + if self.terms.is_empty() { + Ok(term) + } else { + Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )) + } + } + _ => Err(ParserError::IncompleteReduction( + self.lexer.line_num, + self.lexer.col_num, + )), } } - pub fn read(&mut self, op_dir: &CompositeOpDir) -> Result, ParserError> - { + pub fn read(&mut self, op_dir: &CompositeOpDir) -> Result, ParserError> { let mut terms = Vec::new(); loop { From 64433bd8ddfac748971d0e850184f4274b1b2bda Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:39:02 +0100 Subject: [PATCH 048/137] fix macro hygien --- crates/prolog_parser/src/ast.rs | 50 +++++--- crates/prolog_parser/src/lexer.rs | 4 +- crates/prolog_parser/src/macros.rs | 173 +++++++++++++++++--------- crates/prolog_parser/src/tabled_rc.rs | 39 +++--- src/heap_print.rs | 8 +- src/machine/system_calls.rs | 9 +- 6 files changed, 176 insertions(+), 107 deletions(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index ba480415..5810b94c 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -40,20 +40,23 @@ pub const NEGATIVE_SIGN: u32 = 0x0200; #[macro_export] macro_rules! clause_name { ($name: expr, $tbl: expr) => { - ClauseName::User(TabledRc::new($name, $tbl.clone())) + $crate::ast::ClauseName::User($crate::tabled_rc::TabledRc::new($name, $tbl.clone())) }; ($name: expr) => { - ClauseName::BuiltIn($name) + $crate::ast::ClauseName::BuiltIn($name) }; } #[macro_export] macro_rules! atom { ($e:expr, $tbl:expr) => { - Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)), None) + $crate::ast::Constant::Atom( + $crate::ast::ClauseName::User($crate::tabled_rc!($e, $tbl)), + None, + ) }; ($e:expr) => { - Constant::Atom(clause_name!($e), None) + $crate::ast::Constant::Atom($crate::clause_name!($e), None) }; } @@ -65,95 +68,102 @@ macro_rules! rc_atom { } macro_rules! is_term { ($x:expr) => { - ($x & TERM) != 0 + ($x & $crate::ast::TERM) != 0 }; } macro_rules! is_lterm { ($x:expr) => { - ($x & LTERM) != 0 + ($x & $crate::ast::LTERM) != 0 }; } macro_rules! is_op { ($x:expr) => { - $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 + $x & ($crate::ast::XF + | $crate::ast::YF + | $crate::ast::FX + | $crate::ast::FY + | $crate::ast::XFX + | $crate::ast::XFY + | $crate::ast::YFX) + != 0 }; } macro_rules! is_negate { ($x:expr) => { - ($x & NEGATIVE_SIGN) != 0 + ($x & $crate::ast::NEGATIVE_SIGN) != 0 }; } #[macro_export] macro_rules! is_prefix { ($x:expr) => { - $x & (FX | FY) != 0 + $x & ($crate::ast::FX | $crate::ast::FY) != 0 }; } #[macro_export] macro_rules! is_postfix { ($x:expr) => { - $x & (XF | YF) != 0 + $x & ($crate::ast::XF | $crate::ast::YF) != 0 }; } #[macro_export] macro_rules! is_infix { ($x:expr) => { - ($x & (XFX | XFY | YFX)) != 0 + ($x & ($crate::ast::XFX | $crate::ast::XFY | $crate::ast::YFX)) != 0 }; } #[macro_export] macro_rules! is_xfx { ($x:expr) => { - ($x & XFX) != 0 + ($x & $crate::ast::XFX) != 0 }; } #[macro_export] macro_rules! is_xfy { ($x:expr) => { - ($x & XFY) != 0 + ($x & $crate::ast::XFY) != 0 }; } #[macro_export] macro_rules! is_yfx { ($x:expr) => { - ($x & YFX) != 0 + ($x & $crate::ast::YFX) != 0 }; } #[macro_export] macro_rules! is_yf { ($x:expr) => { - ($x & YF) != 0 + ($x & $crate::ast::YF) != 0 }; } #[macro_export] macro_rules! is_xf { ($x:expr) => { - ($x & XF) != 0 + ($x & $crate::ast::XF) != 0 }; } #[macro_export] macro_rules! is_fx { ($x:expr) => { - ($x & FX) != 0 + ($x & $crate::ast::FX) != 0 }; } #[macro_export] macro_rules! is_fy { ($x:expr) => { - ($x & FY) != 0 + ($x & $crate::ast::FY) != 0 }; } @@ -227,14 +237,14 @@ impl Default for VarReg { #[macro_export] macro_rules! temp_v { ($x:expr) => { - RegType::Temp($x) + $crate::ast::RegType::Temp($x) }; } #[macro_export] macro_rules! perm_v { ($x:expr) => { - RegType::Perm($x) + $crate::ast::RegType::Perm($x) }; } diff --git a/crates/prolog_parser/src/lexer.rs b/crates/prolog_parser/src/lexer.rs index 16c60d19..aff75d23 100644 --- a/crates/prolog_parser/src/lexer.rs +++ b/crates/prolog_parser/src/lexer.rs @@ -14,7 +14,7 @@ macro_rules! is_not_eof { ($c:expr) => { match $c { Ok(c) => c, - Err(ParserError::UnexpectedEOF) => return Ok(true), + Err($crate::ast::ParserError::UnexpectedEOF) => return Ok(true), Err(e) => return Err(e), } }; @@ -26,7 +26,7 @@ macro_rules! consume_chars_with { match $e { Ok(Some(c)) => $token.push(c), Ok(None) => continue, - Err(ParserError::UnexpectedChar(..)) => break, + Err($crate::ast::ParserError::UnexpectedChar(..)) => break, Err(e) => return Err(e), } } diff --git a/crates/prolog_parser/src/macros.rs b/crates/prolog_parser/src/macros.rs index e4520aba..a28d7e22 100644 --- a/crates/prolog_parser/src/macros.rs +++ b/crates/prolog_parser/src/macros.rs @@ -1,187 +1,246 @@ #[macro_export] macro_rules! char_class { ($c: expr, [$head:expr]) => ($c == $head); - ($c: expr, [$head:expr $(, $cs:expr)+]) => ($c == $head || char_class!($c, [$($cs),*])); + ($c: expr, [$head:expr $(, $cs:expr)+]) => ($c == $head || $crate::char_class!($c, [$($cs),*])); } #[macro_export] macro_rules! symbolic_control_char { - ($c: expr) => (char_class!($c, ['a', 'b', 'f', 'n', 'r', 't', 'v', '0'])) + ($c: expr) => { + $crate::char_class!($c, ['a', 'b', 'f', 'n', 'r', 't', 'v', '0']) + }; } #[macro_export] macro_rules! space_char { - ($c: expr) => ($c == ' ') + ($c: expr) => { + $c == ' ' + }; } #[macro_export] macro_rules! layout_char { - ($c: expr) => (char_class!($c, [' ', '\n', '\t', '\u{0B}', '\u{0C}'])) + ($c: expr) => { + $crate::char_class!($c, [' ', '\n', '\t', '\u{0B}', '\u{0C}']) + }; } #[macro_export] macro_rules! symbolic_hexadecimal_char { - ($c: expr) => ($c == 'x') + ($c: expr) => { + $c == 'x' + }; } #[macro_export] macro_rules! octal_digit_char { - ($c: expr) => ($c >= '0' && $c <= '7') + ($c: expr) => { + $c >= '0' && $c <= '7' + }; } #[macro_export] macro_rules! binary_digit_char { - ($c: expr) => ($c >= '0' && $c <= '1') + ($c: expr) => { + $c >= '0' && $c <= '1' + }; } #[macro_export] macro_rules! hexadecimal_digit_char { - ($c: expr) => ($c >= '0' && $c <= '9' || - $c >= 'A' && $c <= 'F' || - $c >= 'a' && $c <= 'f') + ($c: expr) => { + $c >= '0' && $c <= '9' || $c >= 'A' && $c <= 'F' || $c >= 'a' && $c <= 'f' + }; } #[macro_export] macro_rules! exponent_char { - ($c: expr) => ($c == 'e' || $c == 'E') + ($c: expr) => { + $c == 'e' || $c == 'E' + }; } #[macro_export] macro_rules! sign_char { - ($c: expr) => ($c == '-' || $c == '+') + ($c: expr) => { + $c == '-' || $c == '+' + }; } #[macro_export] macro_rules! new_line_char { - ($c: expr) => ($c == '\n') + ($c: expr) => { + $c == '\n' + }; } #[macro_export] macro_rules! end_line_comment_char { - ($c: expr) => ($c == '%') + ($c: expr) => { + $c == '%' + }; } #[macro_export] macro_rules! comment_1_char { - ($c: expr) => ($c == '/') + ($c: expr) => { + $c == '/' + }; } #[macro_export] macro_rules! comment_2_char { - ($c: expr) => ($c == '*') + ($c: expr) => { + $c == '*' + }; } #[macro_export] macro_rules! capital_letter_char { - ($c: expr) => ($c >= 'A' && $c <= 'Z') + ($c: expr) => { + $c >= 'A' && $c <= 'Z' + }; } #[macro_export] macro_rules! small_letter_char { - ($c: expr) => ($c >= 'a' && $c <= 'z') + ($c: expr) => { + $c >= 'a' && $c <= 'z' + }; } #[macro_export] macro_rules! variable_indicator_char { - ($c: expr) => ($c == '_') + ($c: expr) => { + $c == '_' + }; } #[macro_export] macro_rules! graphic_char { - ($c: expr) => (char_class!($c, ['#', '$', '&', '*', '+', '-', '.', '/', ':', + ($c: expr) => ($crate::char_class!($c, ['#', '$', '&', '*', '+', '-', '.', '/', ':', '<', '=', '>', '?', '@', '^', '~'])) } #[macro_export] macro_rules! graphic_token_char { - ($c: expr) => (graphic_char!($c) || backslash_char!($c)) + ($c: expr) => { + $crate::graphic_char!($c) || $crate::backslash_char!($c) + }; } #[macro_export] macro_rules! alpha_char { - ($c: expr) => - (match $c { - 'a' ..= 'z' => true, - 'A' ..= 'Z' => true, + ($c: expr) => { + match $c { + 'a'..='z' => true, + 'A'..='Z' => true, '_' => true, - '\u{00A0}' ..= '\u{00BF}' => true, - '\u{00C0}' ..= '\u{00D6}' => true, - '\u{00D8}' ..= '\u{00F6}' => true, - '\u{00F8}' ..= '\u{00FF}' => true, - '\u{0100}' ..= '\u{017F}' => true, // Latin Extended-A - '\u{0180}' ..= '\u{024F}' => true, // Latin Extended-B - '\u{0250}' ..= '\u{02AF}' => true, // IPA Extensions - '\u{02B0}' ..= '\u{02FF}' => true, // Spacing Modifier Letters - '\u{0300}' ..= '\u{036F}' => true, // Combining Diacritical Marks - '\u{0370}' ..= '\u{03FF}' => true, // Greek/Coptic - '\u{0400}' ..= '\u{04FF}' => true, // Cyrillic - '\u{0500}' ..= '\u{052F}' => true, // Cyrillic Supplement - '\u{0530}' ..= '\u{058F}' => true, // Armenian - '\u{0590}' ..= '\u{05FF}' => true, // Hebrew - '\u{0600}' ..= '\u{06FF}' => true, // Arabic - '\u{0700}' ..= '\u{074F}' => true, // Syriac - _ => false - }) + '\u{00A0}'..='\u{00BF}' => true, + '\u{00C0}'..='\u{00D6}' => true, + '\u{00D8}'..='\u{00F6}' => true, + '\u{00F8}'..='\u{00FF}' => true, + '\u{0100}'..='\u{017F}' => true, // Latin Extended-A + '\u{0180}'..='\u{024F}' => true, // Latin Extended-B + '\u{0250}'..='\u{02AF}' => true, // IPA Extensions + '\u{02B0}'..='\u{02FF}' => true, // Spacing Modifier Letters + '\u{0300}'..='\u{036F}' => true, // Combining Diacritical Marks + '\u{0370}'..='\u{03FF}' => true, // Greek/Coptic + '\u{0400}'..='\u{04FF}' => true, // Cyrillic + '\u{0500}'..='\u{052F}' => true, // Cyrillic Supplement + '\u{0530}'..='\u{058F}' => true, // Armenian + '\u{0590}'..='\u{05FF}' => true, // Hebrew + '\u{0600}'..='\u{06FF}' => true, // Arabic + '\u{0700}'..='\u{074F}' => true, // Syriac + _ => false, + } + }; } #[macro_export] macro_rules! decimal_digit_char { - ($c: expr) => ($c >= '0' && $c <= '9') + ($c: expr) => { + $c >= '0' && $c <= '9' + }; } #[macro_export] macro_rules! decimal_point_char { - ($c: expr) => ($c == '.') + ($c: expr) => { + $c == '.' + }; } #[macro_export] macro_rules! alpha_numeric_char { - ($c: expr) => (alpha_char!($c) || decimal_digit_char!($c)) + ($c: expr) => { + $crate::alpha_char!($c) || $crate::decimal_digit_char!($c) + }; } #[macro_export] macro_rules! cut_char { - ($c: expr) => ($c == '!') + ($c: expr) => { + $c == '!' + }; } #[macro_export] macro_rules! semicolon_char { - ($c: expr) => ($c == ';') + ($c: expr) => { + $c == ';' + }; } #[macro_export] macro_rules! backslash_char { - ($c: expr) => ($c == '\\') + ($c: expr) => { + $c == '\\' + }; } #[macro_export] macro_rules! single_quote_char { - ($c: expr) => ($c == '\'') + ($c: expr) => { + $c == '\'' + }; } #[macro_export] macro_rules! double_quote_char { - ($c: expr) => ($c == '"') + ($c: expr) => { + $c == '"' + }; } #[macro_export] macro_rules! back_quote_char { - ($c: expr) => ($c == '`') + ($c: expr) => { + $c == '`' + }; } #[macro_export] macro_rules! meta_char { - ($c: expr) => ( char_class!($c, ['\\', '\'', '"', '`']) ) + ($c: expr) => { + $crate::char_class!($c, ['\\', '\'', '"', '`']) + }; } #[macro_export] macro_rules! solo_char { - ($c: expr) => ( char_class!($c, ['!', '(', ')', ',', ';', '[', ']', - '{', '}', '|', '%']) ) + ($c: expr) => { + $crate::char_class!($c, ['!', '(', ')', ',', ';', '[', ']', '{', '}', '|', '%']) + }; } #[macro_export] macro_rules! prolog_char { - ($c: expr) => (graphic_char!($c) || alpha_numeric_char!($c) || solo_char!($c) || - layout_char!($c) || meta_char!($c)) + ($c: expr) => { + $crate::graphic_char!($c) + || $crate::alpha_numeric_char!($c) + || $crate::solo_char!($c) + || $crate::layout_char!($c) + || $crate::meta_char!($c) + }; } diff --git a/crates/prolog_parser/src/tabled_rc.rs b/crates/prolog_parser/src/tabled_rc.rs index 271ad3bf..8fcf4b86 100644 --- a/crates/prolog_parser/src/tabled_rc.rs +++ b/crates/prolog_parser/src/tabled_rc.rs @@ -4,11 +4,11 @@ use std::collections::HashSet; use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::Deref; -use std::rc::{Rc}; +use std::rc::Rc; pub struct TabledData { table: Rc>>>, - pub(crate) module_name: Rc + pub(crate) module_name: Rc, } impl fmt::Debug for TabledData { @@ -22,14 +22,15 @@ impl fmt::Debug for TabledData { impl Clone for TabledData { fn clone(&self) -> Self { - TabledData { table: self.table.clone(), - module_name: self.module_name.clone() } + TabledData { + table: self.table.clone(), + module_name: self.module_name.clone(), + } } } impl PartialEq for TabledData { - fn eq(&self, other: &TabledData) -> bool - { + fn eq(&self, other: &TabledData) -> bool { Rc::ptr_eq(&self.table, &other.table) && self.module_name == other.module_name } } @@ -39,7 +40,7 @@ impl TabledData { pub fn new(module_name: Rc) -> Self { TabledData { table: Rc::new(RefCell::new(HashSet::new())), - module_name + module_name, } } @@ -51,7 +52,7 @@ impl TabledData { pub struct TabledRc { pub(crate) atom: Rc, - pub table: TabledData + pub table: TabledData, } impl fmt::Debug for TabledRc { @@ -67,27 +68,27 @@ impl fmt::Debug for TabledRc { // from complaining when deriving Clone for StringList. impl Clone for TabledRc { fn clone(&self) -> Self { - TabledRc { atom: self.atom.clone(), table: self.table.clone() } + TabledRc { + atom: self.atom.clone(), + table: self.table.clone(), + } } } impl PartialOrd for TabledRc { - fn partial_cmp(&self, other: &Self) -> Option - { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.atom.cmp(&other.atom)) } } impl Ord for TabledRc { - fn cmp(&self, other: &Self) -> Ordering - { + fn cmp(&self, other: &Self) -> Ordering { self.atom.cmp(&other.atom) } } impl PartialEq for TabledRc { - fn eq(&self, other: &TabledRc) -> bool - { + fn eq(&self, other: &TabledRc) -> bool { self.atom == other.atom } } @@ -104,7 +105,7 @@ impl TabledRc { pub fn new(atom: T, table: TabledData) -> Self { let atom = match table.borrow_mut().take(&atom) { Some(atom) => atom.clone(), - None => Rc::new(atom) + None => Rc::new(atom), }; table.borrow_mut().insert(atom.clone()); @@ -147,7 +148,7 @@ impl fmt::Display for TabledRc { #[macro_export] macro_rules! tabled_rc { - ($e:expr, $tbl:expr) => ( - TabledRc::new(String::from($e), $tbl.clone()) - ) + ($e:expr, $tbl:expr) => { + $crate::tabled_rc::TabledRc::new(String::from($e), $tbl.clone()) + }; } diff --git a/src/heap_print.rs b/src/heap_print.rs index 2bd5e3bf..a4c1354a 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1,9 +1,9 @@ use prolog_parser_rebis::ast::*; use prolog_parser_rebis::{ - alpha_char, alpha_numeric_char, backslash_char, capital_letter_char, char_class, clause_name, - cut_char, decimal_digit_char, graphic_char, graphic_token_char, is_fx, is_infix, is_postfix, - is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char, sign_char, single_quote_char, - small_letter_char, solo_char, variable_indicator_char, + alpha_numeric_char, capital_letter_char, clause_name, cut_char, decimal_digit_char, + graphic_token_char, is_fx, is_infix, is_postfix, is_prefix, is_xf, is_xfx, is_xfy, is_yfx, + semicolon_char, sign_char, single_quote_char, small_letter_char, solo_char, + variable_indicator_char, }; use crate::clause_types::*; diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index cfad12af..61c7fbfe 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1,11 +1,10 @@ use prolog_parser_rebis::ast::*; use prolog_parser_rebis::parser::*; -use prolog_parser_rebis::tabled_rc::*; use prolog_parser_rebis::{ - alpha_char, alpha_numeric_char, backslash_char, binary_digit_char, char_class, clause_name, - decimal_digit_char, exponent_char, graphic_char, graphic_token_char, hexadecimal_digit_char, - layout_char, meta_char, new_line_char, octal_digit_char, prolog_char, sign_char, solo_char, - symbolic_control_char, symbolic_hexadecimal_char, temp_v, + alpha_char, binary_digit_char, clause_name, decimal_digit_char, exponent_char, graphic_char, + graphic_token_char, hexadecimal_digit_char, layout_char, meta_char, new_line_char, + octal_digit_char, prolog_char, sign_char, solo_char, symbolic_control_char, + symbolic_hexadecimal_char, temp_v, }; use lazy_static::lazy_static; From 9107b3ddbe4a5f55c85f6eb3b6a828f98f6f4097 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:45:21 +0100 Subject: [PATCH 049/137] fix some clippy lint warnings --- crates/prolog_parser/src/ast.rs | 76 +++++++++++++-------------- crates/prolog_parser/src/lexer.rs | 4 +- crates/prolog_parser/src/parser.rs | 49 +++++++++-------- crates/prolog_parser/src/tabled_rc.rs | 2 +- 4 files changed, 65 insertions(+), 66 deletions(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index 5810b94c..6f05bcba 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -197,8 +197,8 @@ impl RegType { impl fmt::Display for RegType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &RegType::Perm(val) => write!(f, "Y{}", val), - &RegType::Temp(val) => write!(f, "X{}", val), + RegType::Perm(val) => write!(f, "Y{}", val), + RegType::Temp(val) => write!(f, "X{}", val), } } } @@ -220,10 +220,10 @@ impl VarReg { impl fmt::Display for VarReg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg), - &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg), - &VarReg::ArgAndNorm(RegType::Perm(reg), arg) => write!(f, "Y{} A{}", reg, arg), - &VarReg::ArgAndNorm(RegType::Temp(reg), arg) => write!(f, "X{} A{}", reg, arg), + VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg), + VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg), + VarReg::ArgAndNorm(RegType::Perm(reg), arg) => write!(f, "Y{} A{}", reg, arg), + VarReg::ArgAndNorm(RegType::Temp(reg), arg) => write!(f, "X{} A{}", reg, arg), } } } @@ -382,16 +382,16 @@ impl ParserError { pub fn as_str(&self) -> &'static str { match self { - &ParserError::BackQuotedString(..) => "back_quoted_string", - &ParserError::UnexpectedChar(..) => "unexpected_char", - &ParserError::UnexpectedEOF => "unexpected_end_of_file", - &ParserError::IncompleteReduction(..) => "incomplete_reduction", - &ParserError::InvalidSingleQuotedCharacter(..) => "invalid_single_quoted_character", - &ParserError::IO(_) => "input_output_error", - &ParserError::MissingQuote(..) => "missing_quote", - &ParserError::NonPrologChar(..) => "non_prolog_character", - &ParserError::ParseBigInt(..) => "cannot_parse_big_int", - &ParserError::Utf8Error(..) => "utf8_conversion_error", + ParserError::BackQuotedString(..) => "back_quoted_string", + ParserError::UnexpectedChar(..) => "unexpected_char", + ParserError::UnexpectedEOF => "unexpected_end_of_file", + ParserError::IncompleteReduction(..) => "incomplete_reduction", + ParserError::InvalidSingleQuotedCharacter(..) => "invalid_single_quoted_character", + ParserError::IO(_) => "input_output_error", + ParserError::MissingQuote(..) => "missing_quote", + ParserError::NonPrologChar(..) => "non_prolog_character", + ParserError::ParseBigInt(..) => "cannot_parse_big_int", + ParserError::Utf8Error(..) => "utf8_conversion_error", } } } @@ -525,21 +525,21 @@ pub enum Constant { impl fmt::Display for Constant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &Constant::Atom(ref atom, _) => { + Constant::Atom(ref atom, _) => { if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) { write!(f, "'{}'", atom.as_str()) } else { write!(f, "{}", atom.as_str()) } } - &Constant::Char(c) => write!(f, "'{}'", c as u32), - &Constant::EmptyList => write!(f, "[]"), - &Constant::Fixnum(n) => write!(f, "{}", n), - &Constant::Integer(ref n) => write!(f, "{}", n), - &Constant::Rational(ref n) => write!(f, "{}", n), - &Constant::Float(ref n) => write!(f, "{}", n), - &Constant::String(ref s) => write!(f, "\"{}\"", &s), - &Constant::Usize(integer) => write!(f, "u{}", integer), + Constant::Char(c) => write!(f, "'{}'", *c as u32), + Constant::EmptyList => write!(f, "[]"), + Constant::Fixnum(n) => write!(f, "{}", n), + Constant::Integer(ref n) => write!(f, "{}", n), + Constant::Rational(ref n) => write!(f, "{}", n), + Constant::Float(ref n) => write!(f, "{}", n), + Constant::String(ref s) => write!(f, "\"{}\"", &s), + Constant::Usize(integer) => write!(f, "u{}", integer), } } } @@ -549,7 +549,7 @@ impl PartialEq for Constant { match (self, other) { (&Constant::Atom(ref atom, _), &Constant::Char(c)) | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => { - atom.is_char() && Some(c) == atom.as_str().chars().next() + atom.is_char() && atom.as_str().starts_with(c) } (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(), (&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2, @@ -565,7 +565,7 @@ impl PartialEq for Constant { (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2, (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2, (&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2, - (&Constant::String(ref s1), &Constant::String(ref s2)) => &s1 == &s2, + (&Constant::String(ref s1), &Constant::String(ref s2)) => s1 == s2, (&Constant::EmptyList, &Constant::EmptyList) => true, (&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2, _ => false, @@ -632,7 +632,7 @@ impl ClauseName { #[inline] pub fn owning_module(&self) -> Self { match self { - &ClauseName::User(ref name) => { + ClauseName::User(ref name) => { let module = name.owning_module(); ClauseName::User(TabledRc { atom: module.clone(), @@ -646,8 +646,8 @@ impl ClauseName { #[inline] pub fn to_rc(&self) -> Rc { match self { - &ClauseName::BuiltIn(s) => Rc::new(s.to_string()), - &ClauseName::User(ref rc) => rc.inner(), + ClauseName::BuiltIn(s) => Rc::new(s.to_string()), + ClauseName::User(ref rc) => rc.inner(), } } @@ -687,14 +687,14 @@ impl ClauseName { #[inline] pub fn as_str(&self) -> &str { match self { - &ClauseName::BuiltIn(s) => s, - &ClauseName::User(ref name) => name.as_ref(), + ClauseName::BuiltIn(s) => s, + ClauseName::User(ref name) => name.as_ref(), } } #[inline] pub fn is_char(&self) -> bool { - !self.as_str().is_empty() && self.as_str().chars().skip(1).next().is_none() + !self.as_str().is_empty() && self.as_str().chars().nth(1).is_none() } pub fn defrock_brackets(self) -> Self { @@ -739,8 +739,8 @@ pub enum Term { impl Term { pub fn shared_op_desc(&self) -> Option { match self { - &Term::Clause(_, _, _, ref spec) => spec.clone(), - &Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(), + Term::Clause(_, _, _, ref spec) => spec.clone(), + Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(), _ => None, } } @@ -754,7 +754,7 @@ impl Term { pub fn first_arg(&self) -> Option<&Term> { match self { - &Term::Clause(_, _, ref terms, _) => terms.first().map(|bt| bt.as_ref()), + Term::Clause(_, _, ref terms, _) => terms.first().map(|bt| bt.as_ref()), _ => None, } } @@ -780,14 +780,14 @@ impl Term { pub fn arity(&self) -> usize { match self { - &Term::Clause(_, _, ref child_terms, ..) => child_terms.len(), + Term::Clause(_, _, ref child_terms, ..) => child_terms.len(), _ => 0, } } } fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)> { - if let &mut Term::Clause(_, ref name, ref mut subterms, _) = term { + if let Term::Clause(_, ref name, ref mut subterms, _) = term { if name.as_str() == s && subterms.len() == 2 { let snd = *subterms.pop().unwrap(); let fst = *subterms.pop().unwrap(); diff --git a/crates/prolog_parser/src/lexer.rs b/crates/prolog_parser/src/lexer.rs index aff75d23..75a3a91e 100644 --- a/crates/prolog_parser/src/lexer.rs +++ b/crates/prolog_parser/src/lexer.rs @@ -517,7 +517,7 @@ impl<'a, R: Read> Lexer<'a, R> { if single_quote_char!(self.lookahead_char()?) { self.skip_char()?; - if !token.is_empty() && token.chars().skip(1).next().is_none() { + if !token.is_empty() && token.chars().nth(1).is_none() { if let Some(c) = token.chars().next() { return Ok(Token::Constant(Constant::Char(c))); } @@ -713,7 +713,7 @@ impl<'a, R: Read> Lexer<'a, R> { } self.get_single_quoted_char() - .and_then(|c| Ok(Token::Constant(Constant::Fixnum(c as isize)))) + .map(|c| Token::Constant(Constant::Fixnum(c as isize))) .or_else(|_| { self.return_char(c); diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index 87785daa..4ff09eb6 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -484,7 +484,7 @@ impl<'a, R: Read> Parser<'a, R> { if self.atomize_term(&self.terms[idx - 1]).is_some() { self.stack.truncate(stack_len + 1); - let mut subterms: Vec<_> = self.terms.drain(idx..).map(|t| Box::new(t)).collect(); + let mut subterms: Vec<_> = self.terms.drain(idx..).map(Box::new).collect(); if let Some(name) = self.terms.pop().and_then(|t| self.atomize_term(&t)) { // reduce the '.' functor to a cons cell if it applies. @@ -722,25 +722,24 @@ impl<'a, R: Read> Parser<'a, R> { let idx = self.stack.len() - 2; - match self.stack.remove(idx) { - td => match td.tt { - TokenType::Open | TokenType::OpenCT => { - if self.stack[idx].tt == TokenType::Comma { - return false; - } - - if let Some(atom) = sep_to_atom(self.stack[idx].tt) { - self.terms - .push(Term::Constant(Cell::default(), Constant::Atom(atom, None))); - } - - self.stack[idx].spec = TERM; - self.stack[idx].tt = TokenType::Term; - self.stack[idx].priority = 0; - true + let td = self.stack.remove(idx); + match td.tt { + TokenType::Open | TokenType::OpenCT => { + if self.stack[idx].tt == TokenType::Comma { + return false; } - _ => false, - }, + + if let Some(atom) = sep_to_atom(self.stack[idx].tt) { + self.terms + .push(Term::Constant(Cell::default(), Constant::Atom(atom, None))); + } + + self.stack[idx].spec = TERM; + self.stack[idx].tt = TokenType::Term; + self.stack[idx].priority = 0; + true + } + _ => false, } } @@ -756,7 +755,7 @@ impl<'a, R: Read> Parser<'a, R> { match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? { // do this when layout hasn't been inserted, // ie. why we don't match on Token::Open. - &Token::OpenCT => { + Token::OpenCT => { // can't be prefix, so either inf == 0 // or post == 0. self.reduce_op(inf + post); @@ -831,16 +830,16 @@ impl<'a, R: Read> Parser<'a, R> { fn atomize_term(&self, term: &Term) -> Option { match term { - &Term::Constant(_, ref c) => self.atomize_constant(c), + Term::Constant(_, ref c) => self.atomize_constant(c), _ => None, } } fn atomize_constant(&self, c: &Constant) -> Option { match c { - &Constant::Atom(ref name, _) => Some(name.clone()), - &Constant::Char(c) => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), - &Constant::EmptyList => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), + Constant::Atom(ref name, _) => Some(name.clone()), + Constant::Char(c) => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), + Constant::EmptyList => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)), _ => None, } } @@ -892,7 +891,7 @@ impl<'a, R: Read> Parser<'a, R> { self.negate_number(n, negate_rc, Constant::Rational) } Token::Constant(Constant::Float(n)) => { - self.negate_number(n, |n| OrderedFloat(-n.into_inner()), |n| Constant::Float(n)) + self.negate_number(n, |n| OrderedFloat(-n.into_inner()), Constant::Float) } Token::Constant(c) => { if let Some(name) = self.atomize_constant(&c) { diff --git a/crates/prolog_parser/src/tabled_rc.rs b/crates/prolog_parser/src/tabled_rc.rs index 8fcf4b86..47f87d30 100644 --- a/crates/prolog_parser/src/tabled_rc.rs +++ b/crates/prolog_parser/src/tabled_rc.rs @@ -104,7 +104,7 @@ impl Hash for TabledRc { impl TabledRc { pub fn new(atom: T, table: TabledData) -> Self { let atom = match table.borrow_mut().take(&atom) { - Some(atom) => atom.clone(), + Some(atom) => atom, None => Rc::new(atom), }; From eb2133e648a94b58bbe1c0fd31385829c17ebe2f Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:49:32 +0100 Subject: [PATCH 050/137] fix clippy lint `Manual RangeInclusive::contains implementation` --- crates/prolog_parser/src/macros.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/prolog_parser/src/macros.rs b/crates/prolog_parser/src/macros.rs index a28d7e22..c05ed69b 100644 --- a/crates/prolog_parser/src/macros.rs +++ b/crates/prolog_parser/src/macros.rs @@ -35,7 +35,7 @@ macro_rules! symbolic_hexadecimal_char { #[macro_export] macro_rules! octal_digit_char { ($c: expr) => { - $c >= '0' && $c <= '7' + ('0'..='7').contains(&$c) }; } @@ -49,7 +49,7 @@ macro_rules! binary_digit_char { #[macro_export] macro_rules! hexadecimal_digit_char { ($c: expr) => { - $c >= '0' && $c <= '9' || $c >= 'A' && $c <= 'F' || $c >= 'a' && $c <= 'f' + ('0'..='9').contains(&$c) || ('A'..='F').contains(&$c) || ('a'..='f').contains(&$c) }; } @@ -98,14 +98,14 @@ macro_rules! comment_2_char { #[macro_export] macro_rules! capital_letter_char { ($c: expr) => { - $c >= 'A' && $c <= 'Z' + ('A'..='Z').contains(&$c) }; } #[macro_export] macro_rules! small_letter_char { ($c: expr) => { - $c >= 'a' && $c <= 'z' + ('a'..='z').contains(&$c) }; } @@ -160,7 +160,7 @@ macro_rules! alpha_char { #[macro_export] macro_rules! decimal_digit_char { ($c: expr) => { - $c >= '0' && $c <= '9' + ('0'..='9').contains(&$c) }; } From 1571690bbbdfcc8d3997ea00f5b07291b26ab6dc Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:52:41 +0100 Subject: [PATCH 051/137] fix clippy lint match|if let looks like matches! macro --- crates/prolog_parser/src/ast.rs | 29 +++++------------------------ crates/prolog_parser/src/parser.rs | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index 6f05bcba..6b7534cf 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -187,10 +187,7 @@ impl RegType { } pub fn is_perm(self) -> bool { - match self { - RegType::Perm(_) => true, - _ => false, - } + matches!(self, RegType::Perm(_)) } } @@ -305,27 +302,15 @@ pub enum DoubleQuotes { impl DoubleQuotes { pub fn is_chars(self) -> bool { - if let DoubleQuotes::Chars = self { - true - } else { - false - } + matches!(self, DoubleQuotes::Chars) } pub fn is_atom(self) -> bool { - if let DoubleQuotes::Atom = self { - true - } else { - false - } + matches!(self, DoubleQuotes::Atom) } pub fn is_codes(self) -> bool { - if let DoubleQuotes::Codes = self { - true - } else { - false - } + matches!(self, DoubleQuotes::Codes) } } @@ -674,11 +659,7 @@ impl ClauseName { pub fn has_table_of(&self, other: &ClauseName) -> bool { match self { ClauseName::BuiltIn(_) => { - if let ClauseName::BuiltIn(_) = other { - true - } else { - false - } + matches!(other, ClauseName::BuiltIn(_)) } ClauseName::User(ref name) => other.has_table(&name.table), } diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index 4ff09eb6..b67924c0 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -28,18 +28,18 @@ enum TokenType { impl TokenType { fn is_sep(self) -> bool { - match self { + matches!( + self, TokenType::HeadTailSeparator - | TokenType::OpenCT - | TokenType::Open - | TokenType::Close - | TokenType::OpenList - | TokenType::CloseList - | TokenType::OpenCurly - | TokenType::CloseCurly - | TokenType::Comma => true, - _ => false, - } + | TokenType::OpenCT + | TokenType::Open + | TokenType::Close + | TokenType::OpenList + | TokenType::CloseList + | TokenType::OpenCurly + | TokenType::CloseCurly + | TokenType::Comma + ) } } From 1eb9fcf521e797c3132041a21352f9bc7e635232 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:53:53 +0100 Subject: [PATCH 052/137] more clippy lints --- crates/prolog_parser/src/ast.rs | 2 +- crates/prolog_parser/src/parser.rs | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index 6b7534cf..2f976a0e 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -698,7 +698,7 @@ impl ClauseName { impl AsRef for ClauseName { #[inline] - fn as_ref(self: &Self) -> &str { + fn as_ref(&self) -> &str { self.as_str() } } diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index b67924c0..60cebc90 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -195,7 +195,7 @@ pub struct Parser<'a, R: Read> { terms: Vec, } -fn read_tokens<'a, R: Read>(lexer: &mut Lexer<'a, R>) -> Result, ParserError> { +fn read_tokens(lexer: &mut Lexer) -> Result, ParserError> { let mut tokens = vec![]; loop { @@ -872,11 +872,8 @@ impl<'a, R: Read> Parser<'a, R> { fn shift_token(&mut self, token: Token, op_dir: &CompositeOpDir) -> Result<(), ParserError> { fn negate_rc(mut t: Rc) -> Rc { - match Rc::get_mut(&mut t) { - Some(t) => { - t.neg_assign(); - } - None => {} + if let Some(t) = Rc::get_mut(&mut t) { + t.neg_assign(); }; t From 3f7a60d84b58a13eb38cd31f622797d2d7140a81 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 19:58:31 +0100 Subject: [PATCH 053/137] more clippy lints --- crates/prolog_parser/src/ast.rs | 6 +++--- src/machine/preprocessor.rs | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index 2f976a0e..37c98b55 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -561,7 +561,7 @@ impl PartialEq for Constant { impl Eq for Constant {} impl Constant { - pub fn to_atom(self) -> Option { + pub fn to_atom(&self) -> Option { match self { Constant::Atom(a, _) => Some(a.defrock_brackets()), _ => None, @@ -678,7 +678,7 @@ impl ClauseName { !self.as_str().is_empty() && self.as_str().chars().nth(1).is_none() } - pub fn defrock_brackets(self) -> Self { + pub fn defrock_brackets(&self) -> Self { fn defrock_brackets(s: &str) -> &str { if s.starts_with('(') && s.ends_with(')') { &s[1..s.len() - 1] @@ -726,7 +726,7 @@ impl Term { } } - pub fn to_constant(self) -> Option { + pub fn into_constant(self) -> Option { match self { Term::Constant(_, c) => Some(c), _ => None, diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index f0c7f8b5..a15924c1 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -95,7 +95,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result n.to_usize(), Constant::Fixnum(n) => usize::try_from(n).ok(), @@ -104,7 +104,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result>) -> Result Date: Sat, 6 Feb 2021 20:26:22 +0100 Subject: [PATCH 054/137] fix incorrect rug path --- crates/prolog_parser/src/ast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index 37c98b55..fcde5b5a 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -1,6 +1,6 @@ +use crate::rug::{Integer, Rational}; use crate::tabled_rc::*; use ordered_float::*; -use rug::{Integer, Rational}; use crate::put_back_n::*; From 5041042925cf0b6a97a9bb8a8f7007b4b70d9cbe Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 6 Feb 2021 21:57:27 +0100 Subject: [PATCH 055/137] rename `prolog_parser_rebis` to `prolog_parser` also remove remaining extern crate statements that slipped through earlier --- Cargo.lock | 4 ++-- Cargo.toml | 6 +++--- build.rs | 2 -- crates/prolog_parser/Cargo.lock | 2 +- crates/prolog_parser/Cargo.toml | 2 +- crates/prolog_parser/tests/bom.rs | 13 +++++-------- crates/prolog_parser/tests/parse_tokens.rs | 8 +++----- src/allocator.rs | 4 ++-- src/arithmetic.rs | 4 ++-- src/clause_types.rs | 4 ++-- src/codegen.rs | 6 +++--- src/debray_allocator.rs | 4 ++-- src/fixtures.rs | 2 +- src/forms.rs | 6 +++--- src/heap_print.rs | 4 ++-- src/indexing.rs | 6 +++--- src/instructions.rs | 4 ++-- src/iterators.rs | 4 ++-- src/machine/arithmetic_ops.rs | 4 ++-- src/machine/attributed_variables.rs | 2 +- src/machine/compile.rs | 2 +- src/machine/heap.rs | 2 +- src/machine/load_state.rs | 2 +- src/machine/loader.rs | 4 ++-- src/machine/machine_errors.rs | 4 ++-- src/machine/machine_indices.rs | 4 ++-- src/machine/machine_state.rs | 6 +++--- src/machine/machine_state_impl.rs | 6 +++--- src/machine/mod.rs | 8 ++++---- src/machine/preprocessor.rs | 6 +++--- src/machine/streams.rs | 4 ++-- src/machine/system_calls.rs | 9 ++++----- src/machine/term_stream.rs | 4 ++-- src/read.rs | 6 +++--- src/targets.rs | 2 +- 35 files changed, 76 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef3f28a0..43771e59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -878,7 +878,7 @@ dependencies = [ ] [[package]] -name = "prolog_parser_rebis" +name = "prolog_parser" version = "0.8.68" dependencies = [ "lexical", @@ -1221,7 +1221,7 @@ dependencies = [ "num-rug-adapter", "openssl", "ordered-float", - "prolog_parser_rebis", + "prolog_parser", "ref_thread_local", "ring", "ripemd160", diff --git a/Cargo.toml b/Cargo.toml index c49eebcf..708125ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,8 @@ members = ["crates/prolog_parser"] indexmap = "1.0.2" [features] -default = ["rug", "prolog_parser_rebis/rug"] -num = ["num-rug-adapter", "prolog_parser_rebis/num"] +default = ["rug", "prolog_parser/rug"] +num = ["num-rug-adapter", "prolog_parser/num"] [dependencies] cpu-time = "1.0.0" @@ -35,7 +35,7 @@ libc = "0.2.62" nix = "0.15.0" num-rug-adapter = { optional = true, version = "0.1.4" } ordered-float = "0.5.0" -prolog_parser_rebis = { path = "./crates/prolog_parser", default-features = false } +prolog_parser = { path = "./crates/prolog_parser", default-features = false } ref_thread_local = "0.0.0" rug = { version = "1.4.0", optional = true } rustyline = "7.0.0" diff --git a/build.rs b/build.rs index 3cd4421d..c0865b52 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,3 @@ -extern crate indexmap; - use std::env; use std::fs; use std::fs::File; diff --git a/crates/prolog_parser/Cargo.lock b/crates/prolog_parser/Cargo.lock index f90f0d69..57d62880 100644 --- a/crates/prolog_parser/Cargo.lock +++ b/crates/prolog_parser/Cargo.lock @@ -148,7 +148,7 @@ dependencies = [ ] [[package]] -name = "prolog_parser_rebis" +name = "prolog_parser" version = "0.8.68" dependencies = [ "lexical", diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml index 83114a6e..17f0c27f 100644 --- a/crates/prolog_parser/Cargo.toml +++ b/crates/prolog_parser/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "prolog_parser_rebis" +name = "prolog_parser" version = "0.8.68" authors = ["Mark Thom "] edition = "2018" diff --git a/crates/prolog_parser/tests/bom.rs b/crates/prolog_parser/tests/bom.rs index 25b57104..8a92c127 100644 --- a/crates/prolog_parser/tests/bom.rs +++ b/crates/prolog_parser/tests/bom.rs @@ -1,8 +1,6 @@ -extern crate prolog_parser_rebis; - -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::lexer::{Lexer, Token}; -use prolog_parser_rebis::tabled_rc::TabledData; +use prolog_parser::ast::*; +use prolog_parser::lexer::{Lexer, Token}; +use prolog_parser::tabled_rc::TabledData; use std::rc::Rc; @@ -27,7 +25,7 @@ fn skip_utf8_bom() { let mut lexer = Lexer::new(atom_tbl, flags, &mut stream); match lexer.next_token() { Ok(Token::Constant(Constant::Fixnum(4))) => (), - _ => assert!(false) + _ => assert!(false), } } @@ -37,7 +35,6 @@ fn invalid_utf16_bom() { let stream = parsing_stream(bytes); match stream { Err(ParserError::Utf8Error(0, 0)) => (), - _ => assert!(false) + _ => assert!(false), } } - diff --git a/crates/prolog_parser/tests/parse_tokens.rs b/crates/prolog_parser/tests/parse_tokens.rs index 3afb9164..69b63286 100644 --- a/crates/prolog_parser/tests/parse_tokens.rs +++ b/crates/prolog_parser/tests/parse_tokens.rs @@ -1,8 +1,6 @@ -extern crate prolog_parser_rebis; - -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::lexer::{Lexer, Token}; -use prolog_parser_rebis::tabled_rc::TabledData; +use prolog_parser::ast::*; +use prolog_parser::lexer::{Lexer, Token}; +use prolog_parser::tabled_rc::TabledData; use std::rc::Rc; diff --git a/src/allocator.rs b/src/allocator.rs index 8d447fb1..73d281cd 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::temp_v; +use prolog_parser::ast::*; +use prolog_parser::temp_v; use crate::fixtures::*; use crate::forms::*; diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 68f9f483..7941ed3b 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::{atom, clause_name}; +use prolog_parser::ast::*; +use prolog_parser::{atom, clause_name}; use crate::clause_types::*; use crate::fixtures::*; diff --git a/src/clause_types.rs b/src/clause_types.rs index 5096ffad..a3fa0ee8 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::{clause_name, temp_v}; use crate::forms::Number; use crate::machine::machine_indices::*; diff --git a/src/codegen.rs b/src/codegen.rs index 41bd72c6..cb9c4a97 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,7 @@ /// Code generation to WAM-like instructions. -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::tabled_rc::TabledData; -use prolog_parser_rebis::{perm_v, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::TabledData; +use prolog_parser::{perm_v, temp_v}; use crate::allocator::*; use crate::arithmetic::*; diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index ed0b9704..4d69a344 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -1,7 +1,7 @@ use indexmap::IndexMap; -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::temp_v; +use prolog_parser::ast::*; +use prolog_parser::temp_v; use crate::allocator::*; use crate::fixtures::*; diff --git a/src/fixtures.rs b/src/fixtures.rs index 002774de..94d10c25 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -1,4 +1,4 @@ -use prolog_parser_rebis::ast::*; +use prolog_parser::ast::*; use crate::forms::*; use crate::instructions::*; diff --git a/src/forms.rs b/src/forms.rs index 5dfc680d..11090601 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::parser::OpDesc; -use prolog_parser_rebis::{clause_name, is_infix, is_postfix}; +use prolog_parser::ast::*; +use prolog_parser::parser::OpDesc; +use prolog_parser::{clause_name, is_infix, is_postfix}; use crate::clause_types::*; use crate::machine::machine_errors::*; diff --git a/src/heap_print.rs b/src/heap_print.rs index a4c1354a..aadd2e0f 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::{ +use prolog_parser::ast::*; +use prolog_parser::{ alpha_numeric_char, capital_letter_char, clause_name, cut_char, decimal_digit_char, graphic_token_char, is_fx, is_infix, is_postfix, is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char, sign_char, single_quote_char, small_letter_char, solo_char, diff --git a/src/indexing.rs b/src/indexing.rs index 1b14f301..16f0ce33 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::clause_name; -use prolog_parser_rebis::tabled_rc::*; +use prolog_parser::ast::*; +use prolog_parser::clause_name; +use prolog_parser::tabled_rc::*; use crate::forms::*; use crate::instructions::*; diff --git a/src/instructions.rs b/src/instructions.rs index 585cd2cb..98002bce 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::clause_name; +use prolog_parser::ast::*; +use prolog_parser::clause_name; use crate::clause_types::*; use crate::forms::*; diff --git a/src/iterators.rs b/src/iterators.rs index beb81ca4..fc4fbdc3 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::rc_atom; +use prolog_parser::ast::*; +use prolog_parser::rc_atom; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index b21cb7a9..63ec2d6d 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1,7 +1,7 @@ use divrem::*; -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::clause_name; +use prolog_parser::ast::*; +use prolog_parser::clause_name; use crate::arithmetic::*; use crate::clause_types::*; diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index 4bc90fc4..aee385f0 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -1,6 +1,6 @@ use crate::heap_iter::*; use crate::machine::*; -use prolog_parser_rebis::temp_v; +use prolog_parser::temp_v; use indexmap::IndexSet; diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 1ab52a73..af25b3e8 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1,4 +1,4 @@ -use prolog_parser_rebis::clause_name; +use prolog_parser::clause_name; use crate::codegen::*; use crate::debray_allocator::*; diff --git a/src/machine/heap.rs b/src/machine/heap.rs index c6115662..7f9323c1 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use prolog_parser_rebis::ast::Constant; +use prolog_parser::ast::Constant; use crate::machine::machine_indices::*; use crate::machine::partial_string::*; diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 5ddd2c9f..ebca8518 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -1,6 +1,6 @@ use crate::machine::machine_indices::*; use crate::machine::*; -use prolog_parser_rebis::clause_name; +use prolog_parser::clause_name; use crate::machine::term_stream::*; use indexmap::IndexSet; diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 040e478c..91d41c7f 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::{clause_name, temp_v}; use crate::forms::*; use crate::indexing::*; diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index b1d60bb3..eab52770 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::{clause_name, temp_v}; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; use crate::machine::heap::*; diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 918af24c..6bb9dffd 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::clause_name; +use prolog_parser::ast::*; +use prolog_parser::clause_name; use crate::clause_types::*; use crate::fixtures::*; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index f7160134..6fedf6bb 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::tabled_rc::*; -use prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; +use prolog_parser::{clause_name, temp_v}; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 141ec43f..c7075940 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::tabled_rc::*; -use prolog_parser_rebis::{clause_name, perm_v, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; +use prolog_parser::{clause_name, perm_v, temp_v}; use crate::clause_types::*; use crate::forms::*; diff --git a/src/machine/mod.rs b/src/machine/mod.rs index c0550c1e..17ab0222 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::tabled_rc::*; -use prolog_parser_rebis::{clause_name, temp_v}; +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; +use prolog_parser::{clause_name, temp_v}; use lazy_static::lazy_static; @@ -48,7 +48,7 @@ use crate::machine::streams::*; use indexmap::IndexMap; //use std::convert::TryFrom; -use prolog_parser_rebis::ast::ClauseName; +use prolog_parser::ast::ClauseName; use std::fs::File; use std::mem; use std::path::PathBuf; diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index a15924c1..4a8bd7b4 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::tabled_rc::*; -use prolog_parser_rebis::{atom, clause_name, rc_atom}; +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; +use prolog_parser::{atom, clause_name, rc_atom}; use crate::forms::*; use crate::iterators::*; diff --git a/src/machine/streams.rs b/src/machine/streams.rs index dfa98eb3..21ffbbda 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::clause_name; +use prolog_parser::ast::*; +use prolog_parser::clause_name; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 61c7fbfe..a7574333 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::parser::*; -use prolog_parser_rebis::{ +use prolog_parser::ast::*; +use prolog_parser::parser::*; +use prolog_parser::{ alpha_char, binary_digit_char, clause_name, decimal_digit_char, exponent_char, graphic_char, graphic_token_char, hexadecimal_digit_char, layout_char, meta_char, new_line_char, octal_digit_char, prolog_char, sign_char, solo_char, symbolic_control_char, @@ -67,10 +67,9 @@ use sodiumoxide::crypto::scalarmult::curve25519::*; use native_tls::TlsConnector; -extern crate select; - use base64; use roxmltree; +use select; pub fn get_key() -> KeyEvent { let key; diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index 1305ad65..d87f9e25 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -1,5 +1,5 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::parser::*; +use prolog_parser::ast::*; +use prolog_parser::parser::*; use crate::machine::machine_errors::CompilationError; use crate::machine::preprocessor::*; diff --git a/src/read.rs b/src/read.rs index ac2d3fa0..b55849a9 100644 --- a/src/read.rs +++ b/src/read.rs @@ -1,6 +1,6 @@ -use prolog_parser_rebis::ast::*; -use prolog_parser_rebis::parser::*; -use prolog_parser_rebis::tabled_rc::TabledData; +use prolog_parser::ast::*; +use prolog_parser::parser::*; +use prolog_parser::tabled_rc::TabledData; use crate::forms::*; use crate::iterators::*; diff --git a/src/targets.rs b/src/targets.rs index c59fe47f..956da22a 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -1,4 +1,4 @@ -use prolog_parser_rebis::ast::*; +use prolog_parser::ast::*; use crate::clause_types::*; use crate::forms::*; From d89eb9ff0e2595f19b98fa23ff85e470f42d4ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Sat, 6 Feb 2021 22:38:40 +0100 Subject: [PATCH 056/137] change reposity url --- crates/prolog_parser/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml index 17f0c27f..e022c66c 100644 --- a/crates/prolog_parser/Cargo.toml +++ b/crates/prolog_parser/Cargo.toml @@ -3,7 +3,7 @@ name = "prolog_parser" version = "0.8.68" authors = ["Mark Thom "] edition = "2018" -repository = "https://github.com/mthom/prolog_parser" +repository = "https://github.com/mthom/scryer-prolog" description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation." license = "BSD-3-Clause" From df82dbe5f5f82c446c7892695d1a2d86d7974dee Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 7 Feb 2021 13:47:06 -0700 Subject: [PATCH 057/137] use parent() instead of ancestors().next() in load_context_directory() --- src/machine/loader.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 91d41c7f..e713916f 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1270,8 +1270,11 @@ impl Machine { 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() { + if let Some(directory) = load_context.path.parent() { + // canonicalize returns the absolute path of the directory. + let directory = directory.canonicalize().unwrap(); let directory_str = directory.to_str().unwrap(); + let directory_atom = clause_name!(directory_str.to_string(), self.machine_st.atom_tbl); From 4995c0ed949a8d992a07ae5e2f2b170e613b2e56 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 7 Feb 2021 15:38:03 -0700 Subject: [PATCH 058/137] append .pl to names of files that do not exist in loader.pl --- src/loader.pl | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index ca157855..95917c05 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -308,11 +308,13 @@ use_module(Module, Exports) :- load_context_path(Module, Path) :- ( prolog_load_context(directory, CurrentDir) -> - atom_concat(CurrentDir, Path, Module) + % Rust's Path module never ends a directory path with '/', so + % add one here. + atom_concat(CurrentDir, '/', CurrentDirSlashed), + atom_concat(CurrentDirSlashed, Module, Path) ; Module = Path ). - path_atom(Dir/File, Path) :- must_be(atom, File), !, @@ -321,6 +323,18 @@ path_atom(Dir/File, Path) :- path_atom(Path, Path) :- must_be(atom, Path). +% Try to open the file with the Path name as given; if that fails, +% append '.pl' and try again. +open_file(Path, Stream) :- + ( atom_concat(_, '.pl', Path) -> + open(Path, read, Stream) + ; catch(open(Path, read, Stream), + error(existence_error(source_sink, Path), _), + ( atom_concat(Path, '.pl', ExtendedPath), + open(ExtendedPath, read, Stream) ) + ) + ). + use_module(Module, Exports, Evacuable) :- ( var(Module) -> instantiation_error(load/1) @@ -338,7 +352,7 @@ use_module(Module, Exports, Evacuable) :- ) ; ( path_atom(Module, ModulePath) -> load_context_path(ModulePath, Path), - open(Path, read, Stream), + open_file(Path, Stream), file_load(Stream, Path, Subevacuable), '$use_module'(Evacuable, Subevacuable, Exports) ; type_error(atom, Library, load/1) @@ -375,7 +389,9 @@ load_context(Module) :- predicate_property(Callable, Property) :- ( var(Callable) -> instantiation_error(load/1) - ; Callable =.. [(:), Module, Callable0], + ; functor(Callable, (:), 2), % Callable =.. [(:), Module, Callable0], + arg(1, Callable, Module), + arg(2, Callable, Callable0), atom(Module) -> functor(Callable0, Name, Arity), ( atom(Name), From 1dabe958997712bd7a6a8599dbb85bae0fb9f791 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 7 Feb 2021 15:39:48 -0700 Subject: [PATCH 059/137] remove tidy_trail --- src/machine/machine_state.rs | 2 -- src/machine/machine_state_impl.rs | 39 ++----------------------------- 2 files changed, 2 insertions(+), 39 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 6fedf6bb..96964b1e 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -1367,7 +1367,6 @@ fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool { &Addr::CutPoint(b0) | &Addr::Usize(b0) => { if b > b0 { machine_st.b = b0; - machine_st.tidy_trail(); } } _ => { @@ -1455,7 +1454,6 @@ impl CutPolicy for SCCCutPolicy { Addr::Usize(b0) | Addr::CutPoint(b0) => { if b > b0 { machine_st.b = b0; - machine_st.tidy_trail(); } } _ => { diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index c7075940..d92a4f6f 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -588,7 +588,8 @@ impl MachineState { } } - pub(super) fn trail(&mut self, r: TrailRef) { + pub(super) + fn trail(&mut self, r: TrailRef) { match r { TrailRef::Ref(Ref::HeapCell(h)) => { if h < self.hb { @@ -668,41 +669,6 @@ impl MachineState { } } - pub(super) fn tidy_trail(&mut self) { - if self.b == 0 { - return; - } - - let b = self.b; - let hb = self.hb; - let mut offset = 0; - - for i in self.stack.index_or_frame(b).prelude.tr..self.tr { - match self.trail[i] { - TrailRef::Ref(Ref::AttrVar(tr_i)) - | TrailRef::Ref(Ref::HeapCell(tr_i)) - | TrailRef::AttrVarHeapLink(tr_i) - | TrailRef::AttrVarListLink(tr_i, _) => { - if tr_i >= hb { - offset += 1; - } else { - self.trail[i - offset] = self.trail[i]; - } - } - TrailRef::Ref(Ref::StackCell(b, _)) => { - if b < self.b { - self.trail[i - offset] = self.trail[i]; - } else { - offset += 1; - } - } - } - } - - self.tr -= offset; - self.trail.truncate(self.tr); - } - pub(super) fn match_partial_string(&mut self, addr: Addr, string: &String, has_tail: bool) { let mut heap_pstr_iter = self.heap_pstr_iter(addr); @@ -3120,7 +3086,6 @@ impl MachineState { if b > b0 { self.b = b0; - self.tidy_trail(); if b > self.e { self.stack.truncate(b); From 30602c084923405ebe0ee18614cb63bfd8176f2b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 7 Feb 2021 21:13:27 -0700 Subject: [PATCH 060/137] clean up implementation of (->)/2, (;)/2, and (,)/2 --- src/lib/builtins.pl | 198 +++++++++++++++++++++----------------------- 1 file changed, 95 insertions(+), 103 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 4f2b1825..824c4dd2 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -234,6 +234,8 @@ G1 -> G2 :- ). +:-non_counted_backtracking call_or_cut/3. + call_or_cut(G, B, ErrorPI) :- ( '$call_with_default_policy'(var(G)) -> throw(error(instantiation_error, ErrorPI)) @@ -241,94 +243,71 @@ call_or_cut(G, B, ErrorPI) :- ). -call_or_cut(!, B) :- +:- non_counted_backtracking call_or_cut/2. + +call_or_cut(M:G, B) :- + !, + ( nonvar(G), + '$call_with_default_policy'(call_or_cut_interp(G, B)) -> + true + ; call(M:G) + ). +call_or_cut(G, B) :- + ( '$call_with_default_policy'(call_or_cut_interp(G, B)) -> + true + ; call(G) + ). + + +:- non_counted_backtracking call_or_cut_interp/2. + +call_or_cut_interp(!, B) :- '$set_cp_by_default'(B). -call_or_cut(_:!, B) :- - '$set_cp_by_default'(B). -call_or_cut((G1, G2), B) :- - !, +call_or_cut_interp((G1, G2), B) :- '$call_with_default_policy'(','(G1, G2, B)). -call_or_cut(_:(G1, G2), B) :- - !, - '$call_with_default_policy'(','(G1, G2, B)). -call_or_cut((G1 ; G2), B) :- - !, +call_or_cut_interp((G1 ; G2), B) :- '$call_with_default_policy'(';'(G1, G2, B)). -call_or_cut(_:(G1 ; G2), B) :- - !, - '$call_with_default_policy'(';'(G1, G2, B)). -call_or_cut((G1 -> G2), B) :- - !, +call_or_cut_interp((G1 -> G2), B) :- '$call_with_default_policy'(->(G1, G2, B)). -call_or_cut(_:(G1 -> G2), B) :- - !, - '$call_with_default_policy'(->(G1, G2, B)). -call_or_cut(G, _) :- - '$call_with_default_policy'(G). :- non_counted_backtracking (',')/3. -','((G1, G2), G3, B) :- + +','(M:G1, G2, B) :- !, - '$call_with_default_policy'(','(G1, G2, B)), - '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). -','(_:(G1, G2), G3, B) :- - !, - '$call_with_default_policy'(','(G1, G2, B)), - '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). -','((G1; G2), G3, B) :- - !, - '$call_with_default_policy'(';'(G1, G2, B)), - '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). -','(_:(G1; G2), G3, B) :- - !, - '$call_with_default_policy'(';'(G1, G2, B)), - '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). -','((G1 -> G2), G3, B) :- - !, - '$call_with_default_policy'(->(G1, G2, B)), - '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). -','(_:(G1 -> G2), G3, B) :- - !, - '$call_with_default_policy'(->(G1, G2, B)), - '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). + ( nonvar(G1), + '$call_with_default_policy'(',-interp'(G1, G2, B)) -> + true + ; call(M:G1), + '$call_with_default_policy'(call_or_cut(G2, B, (',')/2)) + ). ','(G1, G2, B) :- '$call_with_default_policy'(call_or_cut(G1, B, (',')/2)), '$call_with_default_policy'(call_or_cut(G2, B, (',')/2)). +:- non_counted_backtracking (',-interp')/3. + +',-interp'((G1, G2), G3, B) :- + '$call_with_default_policy'(','(G1, G2, B)), + '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). +',-interp'((G1; G2), G3, B) :- + '$call_with_default_policy'(';'(G1, G2, B)), + '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). +',-interp'((G1 -> G2), G3, B) :- + '$call_with_default_policy'(->(G1, G2, B)), + '$call_with_default_policy'(call_or_cut(G3, B, (',')/2)). + + :- non_counted_backtracking (;)/3. -';'((G1, G2), G3, B) :- + +';'(M:G1, G2, B) :- !, - ( '$call_with_default_policy'(','(G1, G2, B)) - ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) - ). -';'(_:(G1, G2), G3, B) :- - !, - ( '$call_with_default_policy'(','(G1, G2, B)) - ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) - ). -';'((G1; G2), G3, B) :- - !, - ( '$call_with_default_policy'(';'(G1, G2, B)) - ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) - ). -';'(_:(G1; G2), G3, B) :- - !, - ( '$call_with_default_policy'(';'(G1, G2, B)) - ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) - ). -';'((G1 -> G2), G3, B) :- - !, - ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> - '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) - ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) - ). -';'(_:(G1 -> G2), G3, B) :- - !, - ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> - '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) - ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ( nonvar(G1), + '$call_with_default_policy'(';-interp'(G1, G2, B)) -> + true + ; call(M:G1) + ; '$call_with_default_policy'(call_or_cut(G2, B, (;)/2)) ). ';'(G1, G2, B) :- ( '$call_with_default_policy'(call_or_cut(G1, B, (;)/2)) @@ -336,42 +315,55 @@ call_or_cut(G, _) :- ). +:- non_counted_backtracking ';-interp'/3. + +';-interp'((G1, G2), G3, B) :- + ( '$call_with_default_policy'(','(G1, G2, B)) + ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ). +';-interp'((G1; G2), G3, B) :- + ( '$call_with_default_policy'(';'(G1, G2, B)) + ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ). +';-interp'((G1 -> G2), G3, B) :- + ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> + '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) + ; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2)) + ). + + :- non_counted_backtracking (->)/3. -->((G1, G2), G3, B) :- + +->(M:G1, G2, B) :- !, - ( '$call_with_default_policy'(','(G1, G2, B)) -> - '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) - ). -->(_:(G1, G2), G3, B) :- - !, - ( '$call_with_default_policy'(','(G1, G2, B)) -> - '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) - ). -->((G1 ; G2), G3, B) :- - !, - ( '$call_with_default_policy'(';'(G1, G2, B)) -> - '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) - ). -->(_:(G1 ; G2), G3, B) :- - !, - ( '$call_with_default_policy'(';'(G1, G2, B)) -> - '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) - ). -->((G1 -> G2), G3, B) :- - !, - ( '$call_with_default_policy'(->(G1, G2, B)) -> - '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) - ). -->(_:(G1 -> G2), G3, B) :- - !, - ( '$call_with_default_policy'(->(G1, G2, B)) -> - '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ( nonvar(G1), + '$call_with_default_policy'('->-interp'(G1, G2, B)) -> + true + ; call(M:G1) -> + '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) ). ->(G1, G2, B) :- - ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) - -> '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) + ( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) -> + '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) ). + +:- non_counted_backtracking '->-interp'/3. + +'->-interp'((G1, G2), G3, B) :- + ( '$call_with_default_policy'(','(G1, G2, B)) -> + '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ). +'->-interp'((G1 ; G2), G3, B) :- + ( '$call_with_default_policy'(';'(G1, G2, B)) -> + '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ). +'->-interp'((G1 -> G2), G3, B) :- + ( '$call_with_default_policy'(->(G1, G2, B)) -> + '$call_with_default_policy'(call_or_cut(G3, B, (->)/2)) + ). + + % univ. :- non_counted_backtracking univ_errors/3. From cc7e21170ff3f35acadfd1a3313dbdb5382d78c0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 8 Feb 2021 18:46:33 -0700 Subject: [PATCH 061/137] correct faulty removal of clauses in abolish/1 --- src/forms.rs | 18 +++- src/machine/compile.rs | 10 +- src/machine/loader.rs | 168 ++++++++++++++++++++------------- src/machine/machine_indices.rs | 22 ++++- src/machine/system_calls.rs | 2 +- 5 files changed, 148 insertions(+), 72 deletions(-) diff --git a/src/forms.rs b/src/forms.rs index 11090601..408d691d 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -711,5 +711,21 @@ impl PredicateSkeleton { clauses: self.clauses, } } - */ + */ + + pub fn target_pos_of_clause_clause_loc( + &self, + clause_clause_loc: usize, + clause_assert_margin: usize, + ) -> usize { + let search_result = self.clause_clause_locs[0..clause_assert_margin] + .binary_search_by(|loc| clause_clause_loc.cmp(&loc)); + + search_result.unwrap_or_else(|_| { + self.clause_clause_locs[clause_assert_margin..] + .binary_search_by(|loc| loc.cmp(&clause_clause_loc)) + .unwrap() + + clause_assert_margin + }) + } } diff --git a/src/machine/compile.rs b/src/machine/compile.rs index af25b3e8..faac9421 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1047,7 +1047,7 @@ impl<'a> LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&self.compilation_target, &key) + .get_predicate_skeleton_mut(&self.compilation_target, &key) { Some(skeleton) => { self.retraction_info @@ -1120,7 +1120,7 @@ impl<'a> LoadState<'a> { let skeleton = match self .wam .indices - .get_predicate_skeleton(&self.compilation_target, &key) + .get_predicate_skeleton_mut(&self.compilation_target, &key) { Some(skeleton) if !skeleton.clauses.is_empty() => skeleton, _ => { @@ -1212,7 +1212,7 @@ impl<'a> LoadState<'a> { let skeleton = match self .wam .indices - .get_predicate_skeleton(&self.compilation_target, &key) + .get_predicate_skeleton_mut(&self.compilation_target, &key) { Some(skeleton) => skeleton, None => { @@ -1540,7 +1540,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - match self.load_state.wam.indices.get_predicate_skeleton( + match self.load_state.wam.indices.get_predicate_skeleton_mut( &self.load_state.compilation_target, &(clause_name!("$clause"), 2), ) { @@ -1563,7 +1563,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { .load_state .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) if append_or_prepend.is_append() => { self.load_state.retraction_info.push_record( diff --git a/src/machine/loader.rs b/src/machine/loader.rs index e713916f..90364ce7 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -199,7 +199,7 @@ impl<'a> Drop for LoadState<'a> { RetractionRecord::AppendedModuleExtensiblePredicate(module_name, key) => { self.wam .indices - .get_predicate_skeleton(&CompilationTarget::Module(module_name), &key) + .get_predicate_skeleton_mut(&CompilationTarget::Module(module_name), &key) .map(|skeleton| { skeleton.clauses.pop_back(); }); @@ -207,7 +207,7 @@ impl<'a> Drop for LoadState<'a> { RetractionRecord::PrependedModuleExtensiblePredicate(module_name, key) => { self.wam .indices - .get_predicate_skeleton(&CompilationTarget::Module(module_name), &key) + .get_predicate_skeleton_mut(&CompilationTarget::Module(module_name), &key) .map(|skeleton| { skeleton.clauses.pop_front(); }); @@ -266,7 +266,7 @@ impl<'a> Drop for LoadState<'a> { RetractionRecord::AppendedUserExtensiblePredicate(key) => { self.wam .indices - .get_predicate_skeleton(&CompilationTarget::User, &key) + .get_predicate_skeleton_mut(&CompilationTarget::User, &key) .map(|skeleton| { skeleton.clauses.pop_back(); }); @@ -274,7 +274,7 @@ impl<'a> Drop for LoadState<'a> { RetractionRecord::PrependedUserExtensiblePredicate(key) => { self.wam .indices - .get_predicate_skeleton(&CompilationTarget::User, &key) + .get_predicate_skeleton_mut(&CompilationTarget::User, &key) .map(|skeleton| { skeleton.clauses.pop_front(); }); @@ -412,7 +412,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton.clause_clause_locs.truncate_front(len); @@ -430,7 +430,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &(clause_name!("$clause"), 2)) + .get_predicate_skeleton_mut(&compilation_target, &(clause_name!("$clause"), 2)) { Some(skeleton) => { skeleton.clause_clause_locs.truncate_front(len); @@ -446,7 +446,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton.clause_clause_locs.truncate_back(len); @@ -464,7 +464,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &(clause_name!("$clause"), 2)) + .get_predicate_skeleton_mut(&compilation_target, &(clause_name!("$clause"), 2)) { Some(skeleton) => { skeleton.clause_clause_locs.truncate_back(len); @@ -476,7 +476,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton.clauses.pop_back(); @@ -488,7 +488,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton.clauses.pop_front(); @@ -500,7 +500,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton.clauses.truncate_back(len); @@ -517,7 +517,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton.clauses[target_pos].clause_start = clause_start; @@ -535,7 +535,7 @@ impl<'a> Drop for LoadState<'a> { match self .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) { Some(skeleton) => { skeleton @@ -1365,7 +1365,7 @@ impl Machine { .load_state .wam .indices - .get_predicate_skeleton(&compilation_target, &key) + .get_predicate_skeleton_mut(&compilation_target, &key) .map(|skeleton| skeleton.is_dynamic = true); loader.compile_clause_clauses( @@ -1407,53 +1407,98 @@ impl Machine { _ => CompilationTarget::Module(module_name), }; - let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); - loader.load_state.compilation_target = compilation_target; + let abolish_clause = || { + let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); + loader.load_state.compilation_target = compilation_target; - match loader - .load_state - .wam - .indices - .get_predicate_skeleton(&loader.load_state.compilation_target, &key) - { - Some(skeleton) => { - skeleton.clauses.clear(); - skeleton.clause_clause_locs.clear(); - } - _ => { - unreachable!(); - } - } + let clause_clause_compilation_target = + match &loader.load_state.compilation_target { + CompilationTarget::User => { + CompilationTarget::Module(clause_name!("builtins")) + } + module => { + module.clone() + } + }; - let code_index = loader.load_state.get_or_insert_code_index(key); - code_index.set(IndexPtr::DynamicUndefined); + let mut clause_assert_margin = loader + .load_state + .wam + .indices + .modules + .get(&clause_clause_compilation_target.module_name()) + .map(|module| module.clause_assert_margin) + .unwrap(); - match loader.load_state.compilation_target { - CompilationTarget::User => { - loader.load_state.compilation_target = - CompilationTarget::Module(clause_name!("builtins")); + let mut clause_clause_target_poses: Vec<_> = loader + .load_state + .wam + .indices + .get_predicate_skeleton(&loader.load_state.compilation_target, &key) + .map(|skeleton| { + loader + .load_state + .wam + .indices + .get_predicate_skeleton( + &clause_clause_compilation_target, + &(clause_name!("$clause"), 2), + ) + .map(|clause_clause_skeleton| { + skeleton.clause_clause_locs + .iter() + .map(|clause_clause_loc| { + clause_clause_skeleton.target_pos_of_clause_clause_loc( + *clause_clause_loc, + clause_assert_margin, + ) + }) + .collect() + }) + .unwrap() + }) + .unwrap(); + + loader + .load_state + .wam + .indices + .get_predicate_skeleton_mut(&loader.load_state.compilation_target, &key) + .map(|skeleton| { + skeleton.clauses.clear(); + skeleton.clause_clause_locs.clear(); + }); + + let code_index = loader.load_state.get_or_insert_code_index(key); + code_index.set(IndexPtr::DynamicUndefined); + + loader.load_state.compilation_target = clause_clause_compilation_target; + + while let Some(target_pos) = clause_clause_target_poses.pop() { + loader.load_state.retract_clause((clause_name!("$clause"), 2), target_pos); + + if target_pos < clause_assert_margin { + clause_assert_margin -= 1; + } } - _ => {} + + loader + .load_state + .wam + .indices + .modules + .get_mut(&loader.load_state.compilation_target.module_name()) + .map(|module| module.clause_assert_margin = clause_assert_margin); + + LiveTermStream::evacuate(loader) }; - match loader.load_state.wam.indices.get_predicate_skeleton( - &loader.load_state.compilation_target, - &(clause_name!("$clause"), 2), - ) { - Some(skeleton) => { - skeleton.clauses.clear(); - skeleton.clause_clause_locs.clear(); - } - _ => { - unreachable!(); + match abolish_clause() { + Ok(_) => {} + Err(e) => { + self.throw_session_error(e, (clause_name!("abolish"), 1)); } } - - let clause_clause_code_index = loader - .load_state - .get_or_insert_code_index((clause_name!("$clause"), 2)); - - clause_clause_code_index.set(IndexPtr::DynamicUndefined); } pub(crate) fn retract_clause(&mut self) { @@ -1507,17 +1552,12 @@ impl Machine { &(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 target_pos = skeleton.target_pos_of_clause_clause_loc( + clause_clause_loc, + clause_assert_margin, + ); - 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 { + if target_pos < clause_assert_margin { loader .load_state .wam @@ -1527,7 +1567,7 @@ impl Machine { .map(|module| module.clause_assert_margin -= 1); } - result + target_pos } None => { unreachable!(); diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 6bb9dffd..cb39fede 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -720,7 +720,7 @@ impl Default for IndexStore { } impl IndexStore { - pub fn get_predicate_skeleton( + pub fn get_predicate_skeleton_mut( &mut self, compilation_target: &CompilationTarget, key: &PredicateKey, @@ -740,6 +740,26 @@ impl IndexStore { } } + pub fn get_predicate_skeleton( + &self, + compilation_target: &CompilationTarget, + key: &PredicateKey, + ) -> Option<&PredicateSkeleton> { + match (key.0.as_str(), key.1) { + ("term_expansion", 2) => self.extensible_predicates.get(key), + _ => match compilation_target { + CompilationTarget::User => self.extensible_predicates.get(key), + CompilationTarget::Module(ref module_name) => { + if let Some(module) = self.modules.get(module_name) { + module.extensible_predicates.get(key) + } else { + None + } + } + }, + } + } + pub fn remove_predicate_skeleton( &mut self, compilation_target: &CompilationTarget, diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index a7574333..8251c3fe 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -4631,7 +4631,7 @@ impl MachineState { copy_term( CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub), - value.clone(), + value, AttrVarPolicy::DeepCopy, ); From 195273f01d09b63d9655b9424b83b450fb24e6ae Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 9 Feb 2021 12:17:34 -0700 Subject: [PATCH 062/137] throw exceptions when modules do not contain claimed exports --- src/machine/load_state.rs | 47 ++++++++++++++++++++++++----------- src/machine/loader.rs | 2 +- src/machine/machine_errors.rs | 9 +++---- src/write.rs | 18 +++++++------- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index ebca8518..8ed61cef 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -80,7 +80,6 @@ fn add_op_decl_as_module_export( } None => { retraction_info.push_record(RetractionRecord::AddedUserOp(op_decl.clone())); - module_op_exports.push((op_decl.clone(), None)); } } @@ -133,7 +132,7 @@ pub(super) fn import_module_exports( code_dir: &mut CodeDir, op_dir: &mut OpDir, meta_predicates: &mut MetaPredicateDir, -) { +) -> Result<(), SessionError> { for export in imported_module.module_decl.exports.iter() { match export { ModuleExport::PredicateKey((ref name, arity)) => { @@ -157,7 +156,10 @@ pub(super) fn import_module_exports( src_code_index.get(), ); } else { - unreachable!() + return Err(SessionError::ModuleDoesNotContainExport( + imported_module.module_decl.name.clone(), + (name.clone(), *arity), + )); } } ModuleExport::OpDecl(ref op_decl) => { @@ -165,6 +167,8 @@ pub(super) fn import_module_exports( } } } + + Ok(()) } fn import_module_exports_into_module( @@ -176,7 +180,7 @@ fn import_module_exports_into_module( meta_predicates: &mut MetaPredicateDir, wam_op_dir: &mut OpDir, module_op_exports: &mut ModuleOpExports, -) { +) -> Result<(), SessionError> { for export in imported_module.module_decl.exports.iter() { match export { ModuleExport::PredicateKey((ref name, arity)) => { @@ -200,7 +204,10 @@ fn import_module_exports_into_module( src_code_index.get(), ); } else { - unreachable!() + return Err(SessionError::ModuleDoesNotContainExport( + imported_module.module_decl.name.clone(), + (name.clone(), *arity), + )); } } ModuleExport::OpDecl(ref op_decl) => { @@ -215,6 +222,8 @@ fn import_module_exports_into_module( } } } + + Ok(()) } fn import_qualified_module_exports( @@ -224,7 +233,7 @@ fn import_qualified_module_exports( exports: &IndexSet, code_dir: &mut CodeDir, op_dir: &mut OpDir, -) { +) -> Result<(), SessionError> { for export in imported_module.module_decl.exports.iter() { if !exports.contains(export) { continue; @@ -248,7 +257,10 @@ fn import_qualified_module_exports( src_code_index.get(), ); } else { - unreachable!() + return Err(SessionError::ModuleDoesNotContainExport( + imported_module.module_decl.name.clone(), + (name.clone(), *arity), + )); } } ModuleExport::OpDecl(ref op_decl) => { @@ -256,6 +268,8 @@ fn import_qualified_module_exports( } } } + + Ok(()) } fn import_qualified_module_exports_into_module( @@ -267,7 +281,7 @@ fn import_qualified_module_exports_into_module( op_dir: &mut OpDir, wam_op_dir: &mut OpDir, module_op_exports: &mut ModuleOpExports, -) { +) -> Result<(), SessionError> { for export in imported_module.module_decl.exports.iter() { if !exports.contains(export) { continue; @@ -291,7 +305,10 @@ fn import_qualified_module_exports_into_module( src_code_index.get(), ); } else { - unreachable!() + return Err(SessionError::ModuleDoesNotContainExport( + imported_module.module_decl.name.clone(), + (name.clone(), *arity), + )); } } ModuleExport::OpDecl(ref op_decl) => { @@ -306,6 +323,8 @@ fn import_qualified_module_exports_into_module( } } } + + Ok(()) } impl<'a> LoadState<'a> { @@ -608,7 +627,7 @@ impl<'a> LoadState<'a> { code_dir, op_dir, meta_predicates, - ); + ).unwrap(); } } @@ -673,7 +692,7 @@ impl<'a> LoadState<'a> { &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) { @@ -687,7 +706,7 @@ impl<'a> LoadState<'a> { &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 @@ -723,7 +742,7 @@ impl<'a> LoadState<'a> { &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) { @@ -737,7 +756,7 @@ impl<'a> LoadState<'a> { &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 diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 90364ce7..95a1f13a 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1868,5 +1868,5 @@ pub(super) fn load_module( code_dir, op_dir, meta_predicate_dir, - ); + ).unwrap(); } diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index eab52770..2e3b5e91 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -2,6 +2,7 @@ use prolog_parser::ast::*; use prolog_parser::{clause_name, temp_v}; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; +use crate::machine::PredicateKey; use crate::machine::heap::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; @@ -319,7 +320,6 @@ impl MachineError { // SessionError::InvalidFileName(filename) => { // Self::existence_error(h, ExistenceError::Module(filename)) // } - /* SessionError::ModuleDoesNotContainExport(..) => { Self::permission_error( h, @@ -328,7 +328,6 @@ impl MachineError { functor!("module_does_not_contain_claimed_export"), ) } - */ SessionError::ModuleCannotImportSelf(module_name) => Self::permission_error( h, Permission::Modify, @@ -479,7 +478,7 @@ impl CompilationError { #[derive(Debug, Clone, Copy)] pub enum Permission { - // Access, + Access, Create, InputStream, Modify, @@ -492,7 +491,7 @@ impl Permission { #[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", @@ -805,7 +804,7 @@ pub enum SessionError { // CannotOverwriteImport(ClauseName), ExistenceError(ExistenceError), // InvalidFileName(ClauseName), - // ModuleDoesNotContainExport(ClauseName, PredicateKey), + ModuleDoesNotContainExport(ClauseName, PredicateKey), ModuleCannotImportSelf(ClauseName), NamelessEntry, OpIsInfixAndPostFix(ClauseName), diff --git a/src/write.rs b/src/write.rs index 00538abb..4137cf05 100644 --- a/src/write.rs +++ b/src/write.rs @@ -377,15 +377,15 @@ impl fmt::Display for SessionError { // &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::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.") } From 1bdfc5a1a4e683ad5c86f2b0fa573887d7418bef Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Tue, 9 Feb 2021 20:52:26 +0100 Subject: [PATCH 063/137] ~| now incorporates the number of characters described so far Therefore, subsequent uses of ~N| now yield the specified column, instead of potentially overshooting. Example: ?- format("hello~|~t~8|!", []). hello ! true. Such cases are probably rather uncommon: Relative positioning with ~N+ is more likely to be used in such cases, and that worked as intended also previously as it does now: ?- format("hello~|~t~3+!", []). hello ! true. In fact, if absolute positions are used, then ~| can be omitted entirely: ?- format("hello~t~8|!", []). hello ! true. --- src/lib/format.pl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/lib/format.pl b/src/lib/format.pl index 540bdb9f..fc4c49bb 100644 --- a/src/lib/format.pl +++ b/src/lib/format.pl @@ -1,5 +1,5 @@ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Written March 2020 by Markus Triska (triska@metalevel.at) + Written 2020, 2021 by Markus Triska (triska@metalevel.at) Part of Scryer Prolog. This library provides the nonterminal format_//2 to describe @@ -141,7 +141,7 @@ element_gluevar(glue(_,V), N, N) --> [V]. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Our key datastructure is a list of cells and newlines. - A cell has the shape from_to(From,To,Elements), where + A cell has the shape cell(From,To,Elements), where From and To denote the positions of surrounding tab stops. Elements is a list of elements that occur in a cell, @@ -263,6 +263,11 @@ cells([~,'`',Char,t|Fs], Args, Tab, Es, VNs) --> !, cells(Fs, Args, Tab, [glue(Char,_)|Es], VNs). cells([~,t|Fs], Args, Tab, Es, VNs) --> !, cells(Fs, Args, Tab, [glue(' ',_)|Es], VNs). +cells([~,'|'|Fs], Args, Tab0, Es, VNs) --> !, + { phrase(elements_gluevars(Es, 0, Width), _), + Tab is Tab0 + Width }, + cell(Tab0, Tab, Es), + cells(Fs, Args, Tab, [], VNs). cells([~|Fs0], Args0, Tab, Es, VNs) --> { numeric_argument(Fs0, Num, ['|'|Fs], Args0, Args) }, !, @@ -381,15 +386,15 @@ format(Stream, Fs, Args) :- flush_output(Stream). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -?- phrase(cells("hello", [], 0, []), Cs). +?- phrase(format:cells("hello", [], 0, [], []), Cs). -?- phrase(cells("hello~10|", [], 0, []), Cs). -?- phrase(cells("~ta~t~10|", [], 0, []), Cs). +?- phrase(format:cells("hello~10|", [], 0, [], []), Cs). +?- phrase(format:cells("~ta~t~10|", [], 0, [], []), Cs). ?- phrase(format_("~`at~50|", []), Ls). -?- phrase(cells("~`at~50|", [], 0, []), Cs), - phrase(format_cells(Cs), Ls). +?- phrase(format:cells("~`at~50|", [], 0, [], []), Cs), + phrase(format:format_cells(Cs), Ls). ?- phrase(format:cells("~ta~t~tb~tc~21|", [], 0, [], []), Cs). Cs = [cell(0,21,[glue(' ',_A),chars("a"),glue(' ',_B),glue(' ',_C),chars("b"),glue(' ',_D),chars("c ...")])] ?- phrase(format:cells("~ta~t~4|", [], 0, [], []), Cs). From 547c63b28ebdb646c552e86c746c68921aa63575 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 9 Feb 2021 15:47:14 -0700 Subject: [PATCH 064/137] qualify exception handling code in loader.pl (#809) --- src/loader.pl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index 95917c05..c4235eaf 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -25,7 +25,7 @@ expand_term(Term, ExpandedTerm) :- ( catch('$call'(user:term_expansion(Term, ExpandedTerm0)), E, - '$call'(loader:'$print_message_and_fail'(E, user:term_expansion))) -> + '$call'(loader:'$print_message_and_fail'(E, user:term_expansion/2))) -> ( var(ExpandedTerm0) -> error:instantiation_error(term_expansion/2) ; ExpandedTerm0 = [_|_] -> @@ -51,7 +51,7 @@ term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- goal_expansion(Goal, Module, ExpandedGoal) :- ( catch('$call'(Module:goal_expansion(Goal, ExpandedGoal0)), E, - '$call'(loader:'$print_message_and_fail'(E, Module:goal_expansion))) -> + '$call'(loader:'$print_message_and_fail'(E, Module:goal_expansion/2))) -> ( var(ExpandedGoal0) -> error:instantiation_error(goal_expansion/2) ; goal_expansion(ExpandedGoal0, Module, ExpandedGoal) @@ -91,7 +91,8 @@ 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))), + builtins:(loader:unload_evacuable(Evacuable), + builtins:throw(E))), run_initialization_goals, '$pop_load_context'. @@ -100,7 +101,8 @@ load(Stream) :- create_load_context(Stream, Evacuable), catch(loader:load_loop(Stream, Evacuable), E, - (loader:unload_evacuable(Evacuable), throw(E))), + builtins:(loader:unload_evacuable(Evacuable), + builtins:throw(E))), run_initialization_goals, '$pop_load_context'. From 4d29a3ae3cc7ae118d8ff3f10b762fd4b8c509bd Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 9 Feb 2021 16:40:25 -0700 Subject: [PATCH 065/137] check for control functors (,/;/->) before jumping to internal interpretation (#815) --- src/lib/builtins.pl | 28 ++++++++++++++++++---------- src/loader.pl | 4 ++-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 824c4dd2..1396179b 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -243,18 +243,26 @@ call_or_cut(G, B, ErrorPI) :- ). +:- non_counted_backtracking control_functor/1. + +control_functor(!). +control_functor((_,_)). +control_functor((_;_)). +control_functor((_->_)). + + :- non_counted_backtracking call_or_cut/2. call_or_cut(M:G, B) :- !, ( nonvar(G), - '$call_with_default_policy'(call_or_cut_interp(G, B)) -> - true + '$call_with_default_policy'(control_functor(G)) -> + '$call_with_default_policy'(call_or_cut_interp(G, B)) ; call(M:G) ). call_or_cut(G, B) :- - ( '$call_with_default_policy'(call_or_cut_interp(G, B)) -> - true + ( '$call_with_default_policy'(control_functor(G)) -> + '$call_with_default_policy'(call_or_cut_interp(G, B)) ; call(G) ). @@ -276,8 +284,8 @@ call_or_cut_interp((G1 -> G2), B) :- ','(M:G1, G2, B) :- !, ( nonvar(G1), - '$call_with_default_policy'(',-interp'(G1, G2, B)) -> - true + '$call_with_default_policy'(control_functor(G1)) -> + '$call_with_default_policy'(',-interp'(G1, G2, B)) ; call(M:G1), '$call_with_default_policy'(call_or_cut(G2, B, (',')/2)) ). @@ -304,8 +312,8 @@ call_or_cut_interp((G1 -> G2), B) :- ';'(M:G1, G2, B) :- !, ( nonvar(G1), - '$call_with_default_policy'(';-interp'(G1, G2, B)) -> - true + '$call_with_default_policy'(control_functor(G1)) -> + '$call_with_default_policy'(';-interp'(G1, G2, B)) ; call(M:G1) ; '$call_with_default_policy'(call_or_cut(G2, B, (;)/2)) ). @@ -337,8 +345,8 @@ call_or_cut_interp((G1 -> G2), B) :- ->(M:G1, G2, B) :- !, ( nonvar(G1), - '$call_with_default_policy'('->-interp'(G1, G2, B)) -> - true + '$call_with_default_policy'(control_functor(G1)) -> + '$call_with_default_policy'('->-interp'(G1, G2, B)) ; call(M:G1) -> '$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) ). diff --git a/src/loader.pl b/src/loader.pl index c4235eaf..01fc23f4 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -92,7 +92,7 @@ file_load(Stream, Path, Evacuable) :- catch(loader:load_loop(Stream, Evacuable), E, builtins:(loader:unload_evacuable(Evacuable), - builtins:throw(E))), + builtins:throw(E))), run_initialization_goals, '$pop_load_context'. @@ -102,7 +102,7 @@ load(Stream) :- catch(loader:load_loop(Stream, Evacuable), E, builtins:(loader:unload_evacuable(Evacuable), - builtins:throw(E))), + builtins:throw(E))), run_initialization_goals, '$pop_load_context'. From 7e208984de7695f4decb339a9d79ed79d7032dbb Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 9 Feb 2021 17:18:00 -0700 Subject: [PATCH 066/137] reset merging_ptr offset before insertion of each overlapping constant (#816) --- src/indexing.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/indexing.rs b/src/indexing.rs index 16f0ce33..14b5f356 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -479,6 +479,8 @@ pub fn merge_clause_index( merging_ptr.index_constant(constant.clone(), offset); for overlapping_constant in overlapping_constants { + merging_ptr.offset = 0; + merging_ptr.index_overlapping_constant( constant, overlapping_constant.clone(), From 2db1fac1ebb2dd2446e8c52a11e960da92557d06 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 10 Feb 2021 14:13:37 -0700 Subject: [PATCH 067/137] break out of the first inner loop if constants contains no key in remove_constant_indices (#816) --- src/indexing.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/indexing.rs b/src/indexing.rs index 14b5f356..90f1b2b3 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -561,15 +561,15 @@ pub fn remove_constant_indices( constants_index = index; match constants.get(constant).cloned() { - Some(IndexingCodePtr::External(_)) => { + Some(IndexingCodePtr::External(_)) | Some(IndexingCodePtr::Fail) => { constants.remove(constant); break; } Some(IndexingCodePtr::Internal(o)) => { index += o; } - Some(IndexingCodePtr::Fail) | None => { - unreachable!() + None => { + break; } } } From 20cd0dd77a34c3a7feaef3338b5fddcb134d5cb1 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 15:35:14 -0700 Subject: [PATCH 068/137] use IndexMap over HashMap in prolog_parser --- crates/prolog_parser/Cargo.toml | 1 + crates/prolog_parser/src/ast.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml index e022c66c..b9dab9fd 100644 --- a/crates/prolog_parser/Cargo.toml +++ b/crates/prolog_parser/Cargo.toml @@ -8,6 +8,7 @@ description = " An operator precedence parser for the Rebis development version license = "BSD-3-Clause" [dependencies] +indexmap = "1.0.2" lexical = "2.1.0" ordered-float = "0.5.0" rug = { optional = true, version = "1.4.0" } diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index fcde5b5a..3b9a9287 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -6,7 +6,6 @@ use crate::put_back_n::*; use std::cell::Cell; use std::cmp::Ordering; -use std::collections::HashMap; use std::fmt; use std::hash::{Hash, Hasher}; use std::io::{Bytes, Error as IOError, Read}; @@ -14,6 +13,7 @@ use std::ops::Deref; use std::rc::Rc; use std::vec::Vec; +use indexmap::IndexMap; use unicode_reader::CodePoints; pub type Atom = String; @@ -278,7 +278,7 @@ impl OpDirValue { } // name and fixity -> operator type and precedence. -pub type OpDir = HashMap; +pub type OpDir = IndexMap; #[derive(Debug, Clone, Copy)] pub struct MachineFlags { From 14efbb13566111fea7ac500dfbafb7e760c10168 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 15:37:43 -0700 Subject: [PATCH 069/137] roll back extent of heap when loads are complete in loader.pl --- src/loader.pl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index 01fc23f4..0abd573c 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -85,7 +85,9 @@ run_initialization_goals :- ). file_load(Stream, Path) :- - file_load(Stream, Path, _). + file_load(Stream, Path, _), + false. %% Clear the heap. +file_load(_, _). file_load(Stream, Path, Evacuable) :- create_file_load_context(Stream, Path, Evacuable), @@ -104,7 +106,9 @@ load(Stream) :- builtins:(loader:unload_evacuable(Evacuable), builtins:throw(E))), run_initialization_goals, - '$pop_load_context'. + '$pop_load_context', + false. %% Clear the heap. +load(_). load_loop(Stream, Evacuable) :- read_term(Stream, Term, [variable_names(VNs), singletons(Singletons)]), From 170a71bd029e3a21d311c0fba9a2c45fc9e29022 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 15:38:16 -0700 Subject: [PATCH 070/137] offset SwitchOnTerm's Internal indices only if the proper instructions were emitted --- src/indexing.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/indexing.rs b/src/indexing.rs index 90f1b2b3..6e1cdc85 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -848,7 +848,7 @@ fn second_level_index( } fn switch_on( - instr_fn: impl Fn(IndexMap) -> IndexingInstruction, + mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, index: IndexMap>, prelude: &mut SliceDeque, ) -> IndexingCodePtr { @@ -1083,31 +1083,40 @@ impl CodeOffsets { let mut prelude = sdeq![]; + let mut emitted_switch_on_structure = false; + let mut emitted_switch_on_constant = false; + let mut lst_loc = switch_on_list(self.lists, &mut prelude); let mut str_loc = switch_on( - IndexingInstruction::SwitchOnStructure, + |index| { + emitted_switch_on_structure = true; + IndexingInstruction::SwitchOnStructure(index) + }, self.structures, &mut prelude, ); let con_loc = switch_on( - IndexingInstruction::SwitchOnConstant, + |index| { + emitted_switch_on_constant = true; + IndexingInstruction::SwitchOnConstant(index) + }, self.constants, &mut prelude, ); match &mut str_loc { IndexingCodePtr::Internal(ref mut i) => { - *i += con_loc.is_internal() as usize; + *i += emitted_switch_on_constant as usize; // 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; + *i += emitted_switch_on_constant as usize; // con_loc.is_internal() as usize; + *i += emitted_switch_on_structure as usize; // str_loc.is_internal() as usize; } _ => {} }; From 2429971bcd19674470f4d938692c65ad4f23facc Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 15:38:30 -0700 Subject: [PATCH 071/137] update call/N indices in user-level code_dir in addition to those of pre-loaded modules --- src/machine/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 17ab0222..36e1e629 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -249,14 +249,13 @@ impl Machine { } fn configure_modules(&mut self) { - fn update_call_n_indices(loader: &Module, target_module: &mut Module) { + fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir) { for arity in 1..66 { let key = (clause_name!("call"), arity); match loader.code_dir.get(&key) { Some(src_code_index) => { - let target_code_index = target_module - .code_dir + let target_code_index = target_code_dir .entry(key.clone()) .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined)); @@ -294,9 +293,11 @@ impl Machine { } for (_, target_module) in self.indices.modules.iter_mut() { - update_call_n_indices(&loader, target_module); + update_call_n_indices(&loader, &mut target_module.code_dir); } + update_call_n_indices(&loader, &mut self.indices.code_dir); + self.indices.modules.insert(clause_name!("loader"), loader); } else { unreachable!() From e7cf5d4f3da5057a1e4040c7adafcfd734f57840 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 18:40:07 -0700 Subject: [PATCH 072/137] use machine-generated PartialEq instance for hashing Constant (#817) --- Cargo.lock | 1 + crates/prolog_parser/src/ast.rs | 42 ++++++++++++++++-------------- crates/prolog_parser/src/lexer.rs | 13 ++++++++- crates/prolog_parser/src/parser.rs | 2 +- src/machine/preprocessor.rs | 4 +-- 5 files changed, 38 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43771e59..42246954 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -881,6 +881,7 @@ dependencies = [ name = "prolog_parser" version = "0.8.68" dependencies = [ + "indexmap", "lexical", "num-rug-adapter", "ordered-float", diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index 3b9a9287..f6703d10 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -494,7 +494,7 @@ impl Hash for SharedOpDesc { } } -#[derive(Debug, Clone, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Constant { Atom(ClauseName, Option), Char(char), @@ -529,17 +529,22 @@ impl fmt::Display for Constant { } } -impl PartialEq for Constant { - fn eq(&self, other: &Constant) -> bool { - match (self, other) { - (&Constant::Atom(ref atom, _), &Constant::Char(c)) +/* + * By defining constant_eq as the PartialEq instance of Constant, we + * sometimes hash constants it considers identical to the same value, + * which can make the WAM fail erroneously. This can be avoided by + * using the machine-generated PartialEq for hashing. + */ +pub fn constant_eq(arg: &Constant, other: &Constant) -> bool { + match (arg, other) { + (&Constant::Atom(ref atom, _), &Constant::Char(c)) | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => { atom.is_char() && atom.as_str().starts_with(c) } - (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(), - (&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2, - (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => n1 == n2, - (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) + (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(), + (&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2, + (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => n1 == n2, + (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) | (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => { if let Some(n2) = n2.to_isize() { n1 == n2 @@ -547,19 +552,16 @@ impl PartialEq for Constant { false } } - (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2, - (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2, - (&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2, - (&Constant::String(ref s1), &Constant::String(ref s2)) => s1 == s2, - (&Constant::EmptyList, &Constant::EmptyList) => true, - (&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2, - _ => false, - } + (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2, + (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2, + (&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2, + (&Constant::String(ref s1), &Constant::String(ref s2)) => s1 == s2, + (&Constant::EmptyList, &Constant::EmptyList) => true, + (&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2, + _ => false, } } -impl Eq for Constant {} - impl Constant { pub fn to_atom(&self) -> Option { match self { @@ -703,7 +705,7 @@ impl AsRef for ClauseName { } } -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone)] pub enum Term { AnonVar, Clause( diff --git a/crates/prolog_parser/src/lexer.rs b/crates/prolog_parser/src/lexer.rs index 75a3a91e..b9bda1d0 100644 --- a/crates/prolog_parser/src/lexer.rs +++ b/crates/prolog_parser/src/lexer.rs @@ -33,7 +33,7 @@ macro_rules! consume_chars_with { }; } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone)] pub enum Token { Constant(Constant), Var(Rc), @@ -49,6 +49,17 @@ pub enum Token { End, } +impl Token { + #[inline] + pub(super) fn is_end(&self) -> bool { + if let Token::End = self { + true + } else { + false + } + } +} + pub struct Lexer<'a, R: Read> { pub(crate) atom_tbl: TabledData, pub(crate) reader: &'a mut ParsingStream, diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index 60cebc90..f3655232 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -200,7 +200,7 @@ fn read_tokens(lexer: &mut Lexer) -> Result, ParserError> loop { let token = lexer.next_token()?; - let at_end = Token::End == token; + let at_end = token.is_end(); tokens.push(token); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 4a8bd7b4..dc020533 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -174,7 +174,7 @@ pub(super) fn setup_module_export_list( export_list = *t2; } - if export_list.into_constant() != Some(Constant::EmptyList) { + if export_list.into_constant().map(|c| !constant_eq(&c, &Constant::EmptyList)).unwrap_or(true) { Err(CompilationError::InvalidModuleDecl) } else { Ok(exports) @@ -273,7 +273,7 @@ fn setup_qualified_import( export_list = *t2; } - if export_list.into_constant() != Some(Constant::EmptyList) { + if export_list.into_constant().map(|c| !constant_eq(&c, &Constant::EmptyList)).unwrap_or(true) { Err(CompilationError::InvalidModuleDecl) } else { Ok((module_src, exports)) From bd9708326829842c70326b7f85dabbaa3d365a2d Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 18:51:21 -0700 Subject: [PATCH 073/137] remove unused is_internal function from indexing.rs --- src/indexing.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/indexing.rs b/src/indexing.rs index 6e1cdc85..49a3afdf 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -22,17 +22,6 @@ pub enum IndexingCodePtr { Internal(usize), // the index points into the indexing instruction prelude. } -impl IndexingCodePtr { - #[inline] - fn is_internal(self) -> bool { - if let IndexingCodePtr::Internal(_) = self { - true - } else { - false - } - } -} - #[derive(Debug, Clone, Copy)] enum OptArgIndexKeyType { Structure, From 72c1a0222c7daedae5bab154b4a8c487d7dad222 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 19:21:20 -0700 Subject: [PATCH 074/137] Box LoadStatePayload when storing it in the heap --- src/machine/loader.rs | 7 ++++--- src/machine/machine_indices.rs | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 95a1f13a..07b00e20 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1098,7 +1098,7 @@ impl Machine { #[inline] pub(crate) fn push_load_state_payload(&mut self) { - let payload = LoadStatePayload::new(self); + let payload = Box::new(LoadStatePayload::new(self)); let addr = Addr::LoadStatePayload( self.machine_st .heap @@ -1171,7 +1171,8 @@ impl Machine { ) { match result { Ok(payload) => { - self.machine_st.heap[evacuable_h] = HeapCellValue::LoadStatePayload(payload); + self.machine_st.heap[evacuable_h] = + HeapCellValue::LoadStatePayload(Box::new(payload)); } Err(e) => { self.throw_session_error(e, (clause_name!("load"), 1)); @@ -1785,7 +1786,7 @@ impl<'a> Loader<'a, LiveTermStream> { pub(super) fn from_load_state_payload( wam: &'a mut Machine, - mut payload: LoadStatePayload, + mut payload: Box, ) -> Self { Loader { term_stream: mem::replace( diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index cb39fede..b72fff67 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -311,7 +311,7 @@ pub enum HeapCellValue { Atom(ClauseName, Option), DBRef(DBRef), Integer(Rc), - LoadStatePayload(LoadStatePayload), + LoadStatePayload(Box), NamedStr(usize, ClauseName, Option), // arity, name, precedence/Specifier if it has one. Rational(Rc), PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant. @@ -324,10 +324,10 @@ impl HeapCellValue { pub fn as_addr(&self, focus: usize) -> Addr { match self { HeapCellValue::Addr(ref a) => *a, - HeapCellValue::Atom(..) - | HeapCellValue::DBRef(..) - | HeapCellValue::Integer(..) - | HeapCellValue::Rational(..) => Addr::Con(focus), + HeapCellValue::Atom(..) | + HeapCellValue::DBRef(..) | + HeapCellValue::Integer(..) | + HeapCellValue::Rational(..) => Addr::Con(focus), HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(focus), HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus), HeapCellValue::PartialString(..) => Addr::PStrLocation(focus, 0), From b24f68eee74688b5af4d68861a40188bbc634d54 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 11 Feb 2021 19:22:03 -0700 Subject: [PATCH 075/137] remove vestigial uses of constant_eq --- crates/prolog_parser/src/ast.rs | 33 --------------------------------- src/machine/preprocessor.rs | 12 ++++++------ 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/crates/prolog_parser/src/ast.rs b/crates/prolog_parser/src/ast.rs index f6703d10..ac794e6e 100644 --- a/crates/prolog_parser/src/ast.rs +++ b/crates/prolog_parser/src/ast.rs @@ -529,39 +529,6 @@ impl fmt::Display for Constant { } } -/* - * By defining constant_eq as the PartialEq instance of Constant, we - * sometimes hash constants it considers identical to the same value, - * which can make the WAM fail erroneously. This can be avoided by - * using the machine-generated PartialEq for hashing. - */ -pub fn constant_eq(arg: &Constant, other: &Constant) -> bool { - match (arg, other) { - (&Constant::Atom(ref atom, _), &Constant::Char(c)) - | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => { - atom.is_char() && atom.as_str().starts_with(c) - } - (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(), - (&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2, - (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => n1 == n2, - (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) - | (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => { - if let Some(n2) = n2.to_isize() { - n1 == n2 - } else { - false - } - } - (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2, - (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2, - (&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2, - (&Constant::String(ref s1), &Constant::String(ref s2)) => s1 == s2, - (&Constant::EmptyList, &Constant::EmptyList) => true, - (&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2, - _ => false, - } -} - impl Constant { pub fn to_atom(&self) -> Option { match self { diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index dc020533..bdb9d7fb 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -174,10 +174,10 @@ pub(super) fn setup_module_export_list( export_list = *t2; } - if export_list.into_constant().map(|c| !constant_eq(&c, &Constant::EmptyList)).unwrap_or(true) { - Err(CompilationError::InvalidModuleDecl) - } else { + if let Term::Constant(_, Constant::EmptyList) = export_list { Ok(exports) + } else { + Err(CompilationError::InvalidModuleDecl) } } @@ -273,10 +273,10 @@ fn setup_qualified_import( export_list = *t2; } - if export_list.into_constant().map(|c| !constant_eq(&c, &Constant::EmptyList)).unwrap_or(true) { - Err(CompilationError::InvalidModuleDecl) - } else { + if let Term::Constant(_, Constant::EmptyList) = export_list { Ok((module_src, exports)) + } else { + Err(CompilationError::InvalidModuleDecl) } } From e2a413df786db71f257a2c6500eba12b7dab6745 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 13 Feb 2021 19:41:04 -0700 Subject: [PATCH 076/137] compile scoped clauses from loader.pl --- src/clause_types.rs | 8 +- src/forms.rs | 9 +- src/loader.pl | 27 +++-- src/machine/compile.rs | 117 ++++++++++++------- src/machine/load_state.rs | 53 ++++++--- src/machine/loader.rs | 205 +++++++++++++++++++++++---------- src/machine/machine_indices.rs | 5 +- src/machine/mod.rs | 8 +- src/machine/preprocessor.rs | 16 ++- src/machine/term_stream.rs | 4 +- src/macros.rs | 1 + src/write.rs | 2 + 12 files changed, 313 insertions(+), 142 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index a3fa0ee8..33294fa4 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -352,6 +352,9 @@ impl SystemClauseType { &SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable) => { clause_name!("$clause_to_evacuable") } + &SystemClauseType::REPL(REPLCodePtr::ScopedClauseToEvacuable) => { + clause_name!("$scoped_clause_to_evacuable") + } &SystemClauseType::REPL(REPLCodePtr::ConcludeLoad) => clause_name!("$conclude_load"), &SystemClauseType::REPL(REPLCodePtr::DeclareModule) => clause_name!("$declare_module"), &SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary) => { @@ -728,9 +731,12 @@ impl SystemClauseType { ("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory), ("$path_canonical", 2) => Some(SystemClauseType::PathCanonical), ("$file_time", 3) => Some(SystemClauseType::FileTime), - ("$clause_to_evacuable", 3) => { + ("$clause_to_evacuable", 2) => { Some(SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable)) } + ("$scoped_clause_to_evacuable", 3) => { + Some(SystemClauseType::REPL(REPLCodePtr::ScopedClauseToEvacuable)) + } ("$conclude_load", 1) => Some(SystemClauseType::REPL(REPLCodePtr::ConcludeLoad)), ("$use_module", 3) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)), ("$declare_module", 3) => Some(SystemClauseType::REPL(REPLCodePtr::DeclareModule)), diff --git a/src/forms.rs b/src/forms.rs index 408d691d..fc63e7e5 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -3,6 +3,7 @@ use prolog_parser::parser::OpDesc; use prolog_parser::{clause_name, is_infix, is_postfix}; use crate::clause_types::*; +use crate::machine::loader::PredicateQueue; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; use crate::rug::{Integer, Rational}; @@ -114,7 +115,7 @@ impl ListingSource { } pub trait ClauseInfo { - fn is_consistent(&self, clauses: &Vec) -> bool { + fn is_consistent(&self, clauses: &PredicateQueue) -> bool { match clauses.first() { Some(cl) => self.name() == cl.name() && self.arity() == cl.arity(), None => true, @@ -442,7 +443,8 @@ pub struct Module { pub code_dir: CodeDir, pub op_dir: OpDir, pub meta_predicates: MetaPredicateDir, - pub extensible_predicates: IndexMap, + pub extensible_predicates: ExtensiblePredicates, + pub local_extensible_predicates: LocalExtensiblePredicates, pub is_impromptu_module: bool, pub listing_src: ListingSource, pub clause_assert_margin: usize, @@ -457,7 +459,8 @@ impl Module { op_dir: default_op_dir(), meta_predicates: MetaPredicateDir::new(), is_impromptu_module: false, - extensible_predicates: IndexMap::new(), + extensible_predicates: ExtensiblePredicates::new(), + local_extensible_predicates: LocalExtensiblePredicates::new(), listing_src, clause_assert_margin: 0, } diff --git a/src/loader.pl b/src/loader.pl index 0abd573c..475bb4b7 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -175,11 +175,19 @@ expand_term_goals(Terms0, Terms) :- ( Terms0 = (Head1 :- Body0) -> ( var(Head1) -> instantiation_error(load/1) + ; Head1 = Module:Head2 -> + ( atom(Module) -> + prolog_load_context(module, Target), + module_expanded_head_variables(Head2, HeadVars), + expand_goal(Body0, Target, Body1, HeadVars), + Terms = (Module:Head2 :- Body1) + ; type_error(atom, Module, load/1) + ) ; prolog_load_context(module, Target), module_expanded_head_variables(Head1, HeadVars), - expand_goal(Body0, Target, Body1, HeadVars) - ), - Terms = (Head1 :- Body1) + expand_goal(Body0, Target, Body1, HeadVars), + Terms = (Head1 :- Body1) + ) ; Terms = Terms0 ). @@ -205,7 +213,7 @@ compile_dispatch_or_clause(Term, Evacuable, VNs) :- instantiation_error(load/1) ; compile_dispatch(Term, Evacuable, VNs) -> true - ; compile_clause(Term, Evacuable, VNs) + ; compile_clause(Term, Evacuable) ). @@ -257,9 +265,14 @@ compile_declaration(initialization(Goal), Evacuable) :- assertz(Module:'$initialization_goals'(Goal)). - -compile_clause(Clause, Evacuable, VNs) :- - '$clause_to_evacuable'(Clause, Evacuable, VNs). +compile_clause((Target:Head :- Body), Evacuable) :- + !, + '$scoped_clause_to_evacuable'(Target, (Head :- Body), Evacuable). +compile_clause(Target:Clause, Evacuable) :- + !, + '$scoped_clause_to_evacuable'(Target, Clause, Evacuable). +compile_clause(Clause, Evacuable) :- + '$clause_to_evacuable'(Clause, Evacuable). prolog_load_context(source, Source) :- diff --git a/src/machine/compile.rs b/src/machine/compile.rs index faac9421..e75259a6 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1010,18 +1010,22 @@ impl<'a> LoadState<'a> { fn compile( &mut self, key: PredicateKey, - predicates: &Vec, + predicates: &PredicateQueue, // &Vec, queue: &VecDeque, settings: CodeGenSettings, ) -> Result { - let code_index = self.get_or_insert_code_index(key.clone()); + let code_index = self.get_or_insert_code_index( + key.clone(), + predicates.compilation_target.clone(), + ); + let code_len = self.wam.code_repo.code.len(); let mut code_ptr = code_len; let mut cg = CodeGenerator::::new(self.wam.machine_st.atom_tbl.clone(), settings); - let mut code = cg.compile_predicate(predicates)?; + let mut code = cg.compile_predicate(&predicates.predicates)?; compile_appendix( &mut code, @@ -1047,12 +1051,12 @@ impl<'a> LoadState<'a> { match self .wam .indices - .get_predicate_skeleton_mut(&self.compilation_target, &key) + .get_predicate_skeleton_mut(&predicates.compilation_target, &key) { Some(skeleton) => { self.retraction_info .push_record(RetractionRecord::SkeletonClauseTruncateBack( - self.compilation_target.clone(), + predicates.compilation_target.clone(), key.clone(), skeleton.clauses.len(), )); @@ -1060,14 +1064,18 @@ impl<'a> LoadState<'a> { skeleton.clauses.extend(cg.skeleton.clauses.into_iter()); } None => { - self.add_extensible_predicate(key.clone(), cg.skeleton); + self.add_extensible_predicate( + key.clone(), + cg.skeleton, + predicates.compilation_target.clone(), + ); } } } set_code_index( &mut self.retraction_info, - &self.compilation_target, + &predicates.compilation_target, key, &code_index, IndexPtr::Index(code_ptr), @@ -1080,10 +1088,11 @@ impl<'a> LoadState<'a> { fn record_incremental_compile( &mut self, key: PredicateKey, + compilation_target: CompilationTarget, append_or_prepend: AppendOrPrepend, ) { self.retraction_info - .push_record(match &self.compilation_target { + .push_record(match compilation_target { CompilationTarget::User => match append_or_prepend { AppendOrPrepend::Append => { RetractionRecord::AppendedUserExtensiblePredicate(key) @@ -1092,14 +1101,14 @@ impl<'a> LoadState<'a> { RetractionRecord::PrependedUserExtensiblePredicate(key) } }, - CompilationTarget::Module(ref module_name) => match append_or_prepend { + CompilationTarget::Module(module_name) => match append_or_prepend { AppendOrPrepend::Append => RetractionRecord::AppendedModuleExtensiblePredicate( - module_name.clone(), + module_name, key, ), AppendOrPrepend::Prepend => { RetractionRecord::PrependedModuleExtensiblePredicate( - module_name.clone(), + module_name, key, ) } @@ -1112,21 +1121,30 @@ impl<'a> LoadState<'a> { key: PredicateKey, clause: PredicateClause, queue: VecDeque, + compilation_target: CompilationTarget, non_counted_bt: bool, append_or_prepend: AppendOrPrepend, ) -> Result { - self.record_incremental_compile(key.clone(), append_or_prepend); + self.record_incremental_compile( + key.clone(), + compilation_target.clone(), + append_or_prepend, + ); let skeleton = match self .wam .indices - .get_predicate_skeleton_mut(&self.compilation_target, &key) + .get_predicate_skeleton_mut(&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 predicate_queue = predicate_queue![clause]; + predicate_queue.compilation_target = compilation_target; + + return self.compile(key, &predicate_queue, &queue, settings); } }; @@ -1146,7 +1164,7 @@ impl<'a> LoadState<'a> { self.retraction_info .push_record(RetractionRecord::SkeletonClausePopBack( - self.compilation_target.clone(), + compilation_target.clone(), key.clone(), )); @@ -1157,12 +1175,15 @@ impl<'a> LoadState<'a> { &mut self.retraction_info, ); - let code_index = self.get_or_insert_code_index(key.clone()); + let code_index = self.get_or_insert_code_index( + key.clone(), + compilation_target.clone(), + ); if let Some(new_code_index) = result { set_code_index( &mut self.retraction_info, - &self.compilation_target, + &compilation_target, key, &code_index, IndexPtr::Index(new_code_index), @@ -1178,24 +1199,27 @@ impl<'a> LoadState<'a> { self.retraction_info .push_record(RetractionRecord::SkeletonClausePopFront( - self.compilation_target.clone(), + compilation_target.clone(), key.clone(), )); let threaded_choice_instr_loc = prepend_compiled_clause( &mut self.wam.code_repo.code, - self.compilation_target.clone(), + compilation_target.clone(), key.clone(), clause_code, skeleton, &mut self.retraction_info, ); - let code_index = self.get_or_insert_code_index(key.clone()); + let code_index = self.get_or_insert_code_index( + key.clone(), + compilation_target.clone(), + ); set_code_index( &mut self.retraction_info, - &self.compilation_target, + &compilation_target, key, &code_index, IndexPtr::Index(threaded_choice_instr_loc), @@ -1207,7 +1231,10 @@ impl<'a> LoadState<'a> { } 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 code_index = self.get_or_insert_code_index( + key.clone(), + self.compilation_target.clone(), + ); let skeleton = match self .wam @@ -1516,40 +1543,47 @@ impl<'a, TS: TermStream> Loader<'a, TS> { _ => compilation_target.clone(), }; - let old_compilation_target = mem::replace( - &mut self.load_state.compilation_target, - clause_clause_compilation_target, - ); - let mut clause_clause_locs = sdeq![]; for clause_predicate in clause_predicates { clause_clause_locs.push_back(self.load_state.wam.code_repo.code.len()); - let result = self.load_state.incremental_compile_clause( + self.load_state.incremental_compile_clause( (clause_name!("$clause"), 2), clause_predicate, VecDeque::new(), + clause_clause_compilation_target.clone(), false, // non_counted_bt is false. append_or_prepend, - ); - - if let Err(e) = result { - self.load_state.compilation_target = old_compilation_target; - return Err(e); - } + )?; } match self.load_state.wam.indices.get_predicate_skeleton_mut( - &self.load_state.compilation_target, + &clause_clause_compilation_target, &(clause_name!("$clause"), 2), ) { Some(skeleton) if append_or_prepend.is_append() => { + self.load_state.retraction_info.push_record( + RetractionRecord::SkeletonClauseClausesTruncateBack( + clause_clause_compilation_target.clone(), + (clause_name!("$clause"), 2), + skeleton.clause_clause_locs.len(), + ), + ); + skeleton .clause_clause_locs .extend_from_slice(&clause_clause_locs[0..]); } Some(skeleton) => { + self.load_state.retraction_info.push_record( + RetractionRecord::SkeletonClauseClausesTruncateFront( + clause_clause_compilation_target.clone(), + (clause_name!("$clause"), 2), + skeleton.clause_clause_locs.len(), + ), + ); + for loc in clause_clause_locs.iter() { skeleton.clause_clause_locs.push_front(*loc); } @@ -1589,15 +1623,16 @@ impl<'a, TS: TermStream> Loader<'a, TS> { skeleton.clause_clause_locs.push_front(*loc); } - self.load_state - .increment_clause_assert_margin(clause_clause_locs.len()); + self.load_state.increment_clause_assert_margin( + clause_clause_compilation_target, + clause_clause_locs.len(), + ); } None => { - unreachable!(); + unreachable!() } } - self.load_state.compilation_target = old_compilation_target; Ok(()) } @@ -1617,7 +1652,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { .load_state .wam .indices - .get_predicate_skeleton(&self.load_state.compilation_target, &key) + .get_predicate_skeleton(&self.predicates.compilation_target, &key) .map(|skeleton| (skeleton.is_dynamic, true)) .unwrap_or((false, false)); @@ -1629,7 +1664,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { if is_dynamic { let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter(); - let compilation_target = self.load_state.compilation_target.clone(); + let compilation_target = self.predicates.compilation_target.clone(); self.compile_clause_clauses(key, compilation_target, iter, AppendOrPrepend::Append)?; } diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 8ed61cef..81427d05 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -329,21 +329,25 @@ fn import_qualified_module_exports_into_module( impl<'a> LoadState<'a> { #[inline] - pub(super) fn increment_clause_assert_margin(&mut self, incr: usize) { - match &self.compilation_target { + pub(super) fn increment_clause_assert_margin( + &mut self, + compilation_target: CompilationTarget, + incr: usize, + ) { + match compilation_target { CompilationTarget::User => {} - CompilationTarget::Module(ref module_name) => { - self.retraction_info - .push_record(RetractionRecord::IncreasedClauseAssertMargin( - module_name.clone(), - incr, - )); - + CompilationTarget::Module(module_name) => { self.wam .indices .modules - .get_mut(module_name) + .get_mut(&module_name) .map(|module| module.clause_assert_margin += incr); + + self.retraction_info + .push_record(RetractionRecord::IncreasedClauseAssertMargin( + module_name, + incr, + )); } } } @@ -396,8 +400,12 @@ impl<'a> LoadState<'a> { } } - pub(super) fn get_or_insert_code_index(&mut self, key: PredicateKey) -> CodeIndex { - match self.compilation_target.clone() { + pub(super) fn get_or_insert_code_index( + &mut self, + key: PredicateKey, + compilation_target: CompilationTarget, + ) -> CodeIndex { + match compilation_target { CompilationTarget::User => self .wam .indices @@ -434,8 +442,9 @@ impl<'a> LoadState<'a> { &mut self, key: PredicateKey, skeleton: PredicateSkeleton, + compilation_target: CompilationTarget, ) { - match &self.compilation_target { + match compilation_target { CompilationTarget::User => { self.wam .indices @@ -445,12 +454,12 @@ impl<'a> LoadState<'a> { 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) { + CompilationTarget::Module(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), + RetractionRecord::AddedModuleExtensiblePredicate(module_name, key), ); } else { unreachable!() @@ -497,11 +506,19 @@ impl<'a> LoadState<'a> { ) -> ClauseType { match ClauseType::from(name, arity, fixity) { ClauseType::Named(name, arity, _) => { - let idx = self.get_or_insert_code_index((name.clone(), arity)); + let idx = self.get_or_insert_code_index( + (name.clone(), arity), + self.compilation_target.clone(), + ); + ClauseType::Named(name, arity, idx) } ClauseType::Op(name, fixity, _) => { - let idx = self.get_or_insert_code_index((name.clone(), arity)); + let idx = self.get_or_insert_code_index( + (name.clone(), arity), + self.compilation_target.clone(), + ); + ClauseType::Op(name, fixity, idx) } ct => ct, diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 07b00e20..7046fa1e 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -557,7 +557,7 @@ impl<'a> Drop for LoadState<'a> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum CompilationTarget { Module(ClauseName), User, @@ -587,9 +587,58 @@ impl CompilationTarget { } } +pub struct PredicateQueue { + pub(super) predicates: Vec, + pub(super) compilation_target: CompilationTarget, +} + +impl PredicateQueue { + #[inline] + pub(super) fn push(&mut self, clause: PredicateClause) { + self.predicates.push(clause); + } + + #[inline] + pub(super) fn extend(&mut self, iter: impl Iterator) { + self.predicates.extend(iter); + } + + #[inline] + pub(super) fn clear(&mut self) { + self.predicates.clear(); + } + + #[inline] + pub(crate) fn first(&self) -> Option<&PredicateClause> { + self.predicates.first() + } + + #[inline] + pub(crate) fn is_empty(&self) -> bool { + self.predicates.is_empty() + } + + #[inline] + pub(super) fn take(&mut self) -> Self { + Self { + predicates: mem::replace(&mut self.predicates, vec![]), + compilation_target: self.compilation_target.take(), + } + } +} + +macro_rules! predicate_queue { + [$($v:expr),*] => ( + PredicateQueue { + predicates: vec![$($v,)*], + compilation_target: CompilationTarget::default(), + } + ) +} + pub(crate) struct Loader<'a, TermStream> { pub(super) load_state: LoadState<'a>, - pub(super) predicates: Vec, + pub(super) predicates: PredicateQueue, pub(super) clause_clauses: Vec<(Term, Term)>, term_stream: TermStream, pub(super) non_counted_bt_preds: IndexSet, @@ -612,7 +661,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { term_stream, non_counted_bt_preds: IndexSet::new(), preprocessor: Preprocessor::new(flags), - predicates: vec![], + predicates: predicate_queue![], clause_clauses: vec![], } } @@ -643,7 +692,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { 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::Predicate(pred) => self.predicates.extend(pred.into_iter()), TopLevel::Declaration(decl) => return Ok(Some(decl)), TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact), } @@ -665,6 +714,9 @@ impl<'a, TS: TermStream> Loader<'a, TS> { self.load_state.compilation_target = CompilationTarget::Module(module_decl.name.clone()); + self.predicates.compilation_target = + self.load_state.compilation_target.clone(); + self.load_state .add_module(module_decl, self.term_stream.listing_src().clone()); } @@ -827,14 +879,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } 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()), + self.load_state.add_extensible_predicate( + key.clone(), + PredicateSkeleton::new().set_dynamic(true), + CompilationTarget::User, ); } } @@ -855,15 +903,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } 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(), - ), + self.load_state.add_extensible_predicate( + key.clone(), + PredicateSkeleton::new().set_dynamic(true), + self.load_state.compilation_target.clone(), ); } }, @@ -874,7 +917,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - let code_index = self.load_state.get_or_insert_code_index(key.clone()); + let code_index = self.load_state.get_or_insert_code_index( + key.clone(), + self.load_state.compilation_target.clone(), + ); set_code_index( &mut self.load_state.retraction_info, @@ -884,6 +930,29 @@ impl<'a, TS: TermStream> Loader<'a, TS> { IndexPtr::DynamicUndefined, ); } + + fn add_clause_clause_if_dynamic(&mut self, term: &Term) -> Result<(), SessionError> { + if let Some(predicate_name) = ClauseInfo::name(term) { + let arity = ClauseInfo::arity(term); + + let is_dynamic = self + .load_state + .wam + .indices + .get_predicate_skeleton( + &self.predicates.compilation_target, + &(predicate_name, arity), + ) + .map(|skeleton| skeleton.is_dynamic) + .unwrap_or(false); + + if is_dynamic { + self.add_clause_clause(term.clone())?; + } + } + + Ok(()) + } } impl Machine { @@ -1180,36 +1249,29 @@ impl Machine { } } - pub(crate) fn clause_to_evacuable(&mut self) { - let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2)); + pub(crate) fn scoped_clause_to_evacuable(&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 enqueue_term = || { - let term = loader.read_term_from_heap(temp_v!(1))?; + let (loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3)); - 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 compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), }; - let result = enqueue_term(); + let result = loader.read_and_enqueue_term(temp_v!(2), compilation_target); + self.restore_load_state_payload(result, evacuable_h); + } + + pub(crate) fn clause_to_evacuable(&mut self) { + let (loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2)); + let compilation_target = loader.load_state.compilation_target.clone(); + + let result = loader.read_and_enqueue_term(temp_v!(1), compilation_target); self.restore_load_state_payload(result, evacuable_h); } @@ -1470,7 +1532,11 @@ impl Machine { skeleton.clause_clause_locs.clear(); }); - let code_index = loader.load_state.get_or_insert_code_index(key); + let code_index = loader.load_state.get_or_insert_code_index( + key, + loader.load_state.compilation_target.clone(), + ); + code_index.set(IndexPtr::DynamicUndefined); loader.load_state.compilation_target = clause_clause_compilation_target; @@ -1778,7 +1844,7 @@ impl<'a> Loader<'a, LiveTermStream> { &mut self.load_state.retraction_info, RetractionInfo::new(self.load_state.wam.code_repo.code.len()), ), - predicates: mem::replace(&mut self.predicates, vec![]), + predicates: self.predicates.take(), clause_clauses: mem::replace(&mut self.clause_clauses, vec![]), module_op_exports: mem::replace(&mut self.load_state.module_op_exports, vec![]), } @@ -1799,7 +1865,7 @@ impl<'a> Loader<'a, LiveTermStream> { ), 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![]), + predicates: payload.predicates.take(), load_state: LoadState { compilation_target: payload.compilation_target.take(), module_op_exports: mem::replace(&mut payload.module_op_exports, vec![]), @@ -1819,7 +1885,11 @@ impl<'a> Loader<'a, LiveTermStream> { ) -> 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 tl = preprocessor.try_term_to_tl( + &mut self.load_state, + term, + CutContext::BlocksCuts, + )?; let queue = preprocessor.parse_queue(&mut self.load_state)?; @@ -1831,26 +1901,37 @@ impl<'a> Loader<'a, LiveTermStream> { } }; - let compilation_target = - mem::replace(&mut self.load_state.compilation_target, compilation_target); - - let result = self.load_state.incremental_compile_clause( + self.load_state.incremental_compile_clause( key, clause, queue, + compilation_target, non_counted_bt, append_or_prepend, - ); - - self.load_state.compilation_target = compilation_target; - result?; + )?; Ok(()) } - #[inline] - fn enqueue_term(&mut self, term: Term) { + fn read_and_enqueue_term( + mut self, + term_reg: RegType, + compilation_target: CompilationTarget, + ) -> Result { + if self.predicates.compilation_target != compilation_target { + if !self.predicates.is_empty() { + self.compile_and_submit()?; + } + + self.predicates.compilation_target = compilation_target; + } + + let term = self.read_term_from_heap(term_reg)?; + + self.add_clause_clause_if_dynamic(&term)?; self.term_stream.term_queue.push_back(term); + + self.load() } } diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index b72fff67..4b4a4c18 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -421,6 +421,7 @@ pub enum REPLCodePtr { AddGoalExpansionClause, AddTermExpansionClause, ClauseToEvacuable, + ScopedClauseToEvacuable, ConcludeLoad, DeclareModule, LoadCompiledLibrary, @@ -692,7 +693,6 @@ pub(crate) struct ModuleStub { pub(crate) in_situ_code_dir: InSituCodeDir, } -// pub(crate) type ModuleStubDir = IndexMap; pub(crate) type StreamAliasDir = IndexMap; pub(crate) type StreamDir = BTreeSet; @@ -700,10 +700,13 @@ pub type MetaPredicateDir = IndexMap>; pub type ExtensiblePredicates = IndexMap; +pub type LocalExtensiblePredicates = IndexMap<(CompilationTarget, PredicateKey), PredicateSkeleton>; + #[derive(Debug)] pub struct IndexStore { pub(super) code_dir: CodeDir, pub(super) extensible_predicates: ExtensiblePredicates, + pub(super) local_extensible_predicates: LocalExtensiblePredicates, pub(super) global_variables: GlobalVarDir, pub(super) meta_predicates: MetaPredicateDir, pub(super) modules: ModuleDir, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 36e1e629..38ecd285 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -15,11 +15,12 @@ use crate::read::*; mod attributed_variables; pub(super) mod code_repo; pub mod code_walker; +#[macro_use] +pub(crate) mod loader; mod compile; mod copier; pub mod heap; mod load_state; -mod loader; pub mod machine_errors; pub mod machine_indices; pub(super) mod machine_state; @@ -36,10 +37,8 @@ mod arithmetic_ops; mod machine_state_impl; mod system_calls; -//use crate::machine::attributed_variables::*; use crate::machine::code_repo::*; use crate::machine::compile::*; -// use crate::machine::loader::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; @@ -425,6 +424,9 @@ impl Machine { REPLCodePtr::ClauseToEvacuable => { self.clause_to_evacuable(); } + REPLCodePtr::ScopedClauseToEvacuable => { + self.scoped_clause_to_evacuable(); + } REPLCodePtr::ConcludeLoad => { self.conclude_load(); } diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index bdb9d7fb..6e055134 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -780,7 +780,8 @@ impl Preprocessor { query_term }) } else { - self.to_query_term(load_state, Term::Clause(r, name, subterms, fixity)) + let clause = Term::Clause(r, name, subterms, fixity); + self.to_query_term(load_state, clause) } } _ => self.to_query_term(load_state, term), @@ -831,8 +832,11 @@ impl Preprocessor { cut_context: CutContext, ) -> Result { let post_head_terms: Vec<_> = terms.drain(1..).collect(); - - let mut query_terms = self.setup_query(load_state, post_head_terms, cut_context)?; + 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(); @@ -899,7 +903,11 @@ impl Preprocessor { let mut results = VecDeque::new(); for term in terms.into_iter() { - results.push_back(self.try_term_to_tl(load_state, term, cut_context)?); + results.push_back(self.try_term_to_tl( + load_state, + term, + cut_context, + )?); } Ok(results) diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index d87f9e25..21a30e29 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -101,7 +101,7 @@ pub struct LoadStatePayload { pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>, pub(super) non_counted_bt_preds: IndexSet, pub(super) preprocessor: Preprocessor, - pub(super) predicates: Vec, + pub(super) predicates: PredicateQueue, pub(super) clause_clauses: Vec<(Term, Term)>, } @@ -120,7 +120,7 @@ impl LoadStatePayload { module_op_exports: vec![], non_counted_bt_preds: IndexSet::new(), preprocessor: Preprocessor::new(wam.machine_st.flags), - predicates: vec![], + predicates: predicate_queue![], clause_clauses: vec![], } } diff --git a/src/macros.rs b/src/macros.rs index aa043327..7e03e231 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -362,6 +362,7 @@ macro_rules! index_store { IndexStore { code_dir: $code_dir, extensible_predicates: ExtensiblePredicates::new(), + local_extensible_predicates: LocalExtensiblePredicates::new(), global_variables: GlobalVarDir::new(), meta_predicates: MetaPredicateDir::new(), modules: $modules, diff --git a/src/write.rs b/src/write.rs index 4137cf05..dacf0ed9 100644 --- a/src/write.rs +++ b/src/write.rs @@ -36,6 +36,8 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::Retract"), REPLCodePtr::ClauseToEvacuable => write!(f, "REPLCodePtr::ClauseToEvacuable"), + REPLCodePtr::ScopedClauseToEvacuable => + write!(f, "REPLCodePtr::ScopedClauseToEvacuable"), REPLCodePtr::ConcludeLoad => write!(f, "REPLCodePtr::ConcludeLoad"), REPLCodePtr::DeclareModule => From 6b6666be47e3b6f9b30fea2567e7e4da489f7b92 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 16 Feb 2021 20:54:51 -0700 Subject: [PATCH 077/137] support discontiguous and multifile declarations --- src/clause_types.rs | 14 +- src/forms.rs | 122 +++--- src/loader.pl | 35 +- src/machine/compile.rs | 456 +++++++++++++------- src/machine/load_state.rs | 266 ++++++++++-- src/machine/loader.rs | 737 ++++++++++++++++++++------------- src/machine/machine_errors.rs | 18 + src/machine/machine_indices.rs | 74 +++- src/machine/mod.rs | 6 + src/machine/preprocessor.rs | 11 +- src/machine/term_stream.rs | 3 - src/write.rs | 18 + 12 files changed, 1209 insertions(+), 551 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 33294fa4..660a74a8 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -340,9 +340,15 @@ impl SystemClauseType { &SystemClauseType::WorkingDirectory => clause_name!("$working_directory"), &SystemClauseType::PathCanonical => clause_name!("$path_canonical"), &SystemClauseType::FileTime => clause_name!("$file_time"), + &SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate) => { + clause_name!("$add_discontiguous_predicate") + } &SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) => { clause_name!("$add_dynamic_predicate") } + &SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate) => { + clause_name!("$add_multifile_predicate") + } &SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) => { clause_name!("$add_goal_expansion_clause") } @@ -582,9 +588,15 @@ impl SystemClauseType { pub fn from(name: &str, arity: usize) -> Option { match (name, arity) { ("$abolish_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)), - ("$add_dynamic_predicate", 3) => { + ("$add_dynamic_predicate", 4) => { Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate)) } + ("$add_multifile_predicate", 4) => { + Some(SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate)) + } + ("$add_discontiguous_predicate", 4) => { + Some(SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate)) + } ("$add_goal_expansion_clause", 4) => { Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause)) } diff --git a/src/forms.rs b/src/forms.rs index fc63e7e5..ad401cd4 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -28,7 +28,6 @@ pub type JumpStub = Vec; #[derive(Debug, Clone)] pub enum TopLevel { - Declaration(Declaration), Fact(Term), // Term, line_num, col_num Predicate(Predicate), Query(Vec), @@ -117,7 +116,7 @@ impl ListingSource { pub trait ClauseInfo { fn is_consistent(&self, clauses: &PredicateQueue) -> bool { match clauses.first() { - Some(cl) => self.name() == cl.name() && self.arity() == cl.arity(), + Some(cl) => self.name() == ClauseInfo::name(cl) && self.arity() == ClauseInfo::arity(cl), None => true, } } @@ -212,33 +211,6 @@ impl PredicateClause { } } } - - pub fn arity(&self) -> usize { - match self { - &PredicateClause::Fact(ref term, ..) => term.arity(), - &PredicateClause::Rule(ref rule, ..) => { - if rule.head.0.as_str() == ":" && rule.head.1.len() == 2 { - match (rule.head.1)[0].as_ref() { - &Term::Constant(_, Constant::Atom(..)) => {} - _ => { - return 2; - } - } - - (rule.head.1)[1].arity() - } else { - rule.head.1.len() - } - } - } - } - - pub fn name(&self) -> Option { - match self { - &PredicateClause::Fact(ref term, ..) => term.name(), - &PredicateClause::Rule(ref rule, ..) => Some(rule.head.0.clone()), - } - } } #[derive(Debug, Clone)] @@ -447,7 +419,6 @@ pub struct Module { pub local_extensible_predicates: LocalExtensiblePredicates, pub is_impromptu_module: bool, pub listing_src: ListingSource, - pub clause_assert_margin: usize, } // Module's and related types are defined in forms. @@ -462,7 +433,6 @@ impl Module { extensible_predicates: ExtensiblePredicates::new(), local_extensible_predicates: LocalExtensiblePredicates::new(), listing_src, - clause_assert_margin: 0, } } } @@ -643,7 +613,7 @@ impl AddAssign for OptArgIndexKey { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct ClauseIndexInfo { pub clause_start: usize, pub opt_arg_index_key: OptArgIndexKey, @@ -660,6 +630,41 @@ impl ClauseIndexInfo { } } +#[derive(Clone, Copy, Debug)] +pub struct PredicateInfo { + pub is_extensible: bool, + pub is_discontiguous: bool, + pub is_dynamic: bool, + pub is_multifile: bool, + pub has_clauses: bool, +} + +impl Default for PredicateInfo { + #[inline] + fn default() -> Self { + PredicateInfo { + is_extensible: false, + is_discontiguous: false, + is_dynamic: false, + is_multifile: false, + has_clauses: false, + } + } +} + +impl PredicateInfo { + #[inline] + pub fn compile_incrementally(&self) -> bool { + let base = self.is_extensible && self.has_clauses; + base && (self.is_discontiguous || self.is_multifile) + } + + #[inline] + pub fn must_retract_local_clauses(&self) -> bool { + self.is_extensible && !self.is_discontiguous + } +} + #[derive(Debug)] pub struct PredicateSkeleton { pub is_discontiguous: bool, @@ -667,6 +672,7 @@ pub struct PredicateSkeleton { pub is_multifile: bool, pub clauses: SliceDeque, pub clause_clause_locs: SliceDeque, + pub clause_assert_margin: usize, } impl PredicateSkeleton { @@ -678,57 +684,41 @@ impl PredicateSkeleton { is_multifile: false, clauses: sdeq![], clause_clause_locs: sdeq![], + clause_assert_margin: 0, } } - /* #[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 { + pub fn predicate_info(&self) -> PredicateInfo { + PredicateInfo { + is_extensible: true, is_discontiguous: self.is_discontiguous, - is_dynamic, + is_dynamic: self.is_dynamic, is_multifile: self.is_multifile, - clauses: self.clauses, - clause_clause_locs: self.clause_clause_locs, + has_clauses: !self.clauses.is_empty(), } } - /* #[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, - } + pub fn reset(&mut self) { + self.clauses.clear(); + self.clause_clause_locs.clear(); + self.clause_assert_margin = 0; } - */ pub fn target_pos_of_clause_clause_loc( &self, clause_clause_loc: usize, - clause_assert_margin: usize, - ) -> usize { - let search_result = self.clause_clause_locs[0..clause_assert_margin] + ) -> Option { + let search_result = self.clause_clause_locs[0..self.clause_assert_margin] .binary_search_by(|loc| clause_clause_loc.cmp(&loc)); - search_result.unwrap_or_else(|_| { - self.clause_clause_locs[clause_assert_margin..] + match search_result { + Ok(loc) => Some(loc), + Err(_) => self.clause_clause_locs[self.clause_assert_margin..] .binary_search_by(|loc| loc.cmp(&clause_clause_loc)) - .unwrap() - + clause_assert_margin - }) + .map(|loc| loc + self.clause_assert_margin) + .ok() + } } } diff --git a/src/loader.pl b/src/loader.pl index 475bb4b7..548d0e46 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -257,9 +257,38 @@ compile_declaration(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). + prolog_load_context(module, Module), + '$add_dynamic_predicate'(Module, Name, Arity, Evacuable). +compile_declaration(dynamic(Module:Name/Arity), Evacuable) :- + must_be(atom, Module), + must_be(atom, Name), + must_be(integer, Arity), + '$add_dynamic_predicate'(Module, Name, Arity, Evacuable). +compile_declaration(multifile(Name/Arity), Evacuable) :- + !, + must_be(atom, Name), + must_be(integer, Arity), + prolog_load_context(module, Module), + '$add_multifile_predicate'(Module, Name, Arity, Evacuable). +compile_declaration(multifile(Module:Name/Arity), Evacuable) :- + must_be(atom, Module), + must_be(atom, Name), + must_be(integer, Arity), + '$add_multifile_predicate'(Module, Name, Arity, Evacuable). +compile_declaration(discontiguous(Name/Arity), Evacuable) :- + !, + must_be(atom, Name), + must_be(integer, Arity), + prolog_load_context(module, Module), + '$add_discontiguous_predicate'(Module, Name, Arity, Evacuable). +compile_declaration(discontiguous(Module:Name/Arity), Evacuable) :- + must_be(atom, Module), + must_be(atom, Name), + must_be(integer, Arity), + '$add_discontiguous_predicate'(Module, Name, Arity, Evacuable). compile_declaration(initialization(Goal), Evacuable) :- prolog_load_context(module, Module), assertz(Module:'$initialization_goals'(Goal)). @@ -388,7 +417,7 @@ check_predicate_property(dynamic, Module, Name, Arity, dynamic) :- '$cpp_dynamic_property'(Module, Name, Arity). check_predicate_property(multifile, Module, Name, Arity, multifile) :- '$cpp_multifile_property'(Module, Name, Arity). -check_predicate_property(discontiguous, Module, Name, Arity, multifile) :- +check_predicate_property(discontiguous, Module, Name, Arity, discontiguous) :- '$cpp_discontiguous_property'(Module, Name, Arity). @@ -408,7 +437,7 @@ load_context(Module) :- predicate_property(Callable, Property) :- ( var(Callable) -> instantiation_error(load/1) - ; functor(Callable, (:), 2), % Callable =.. [(:), Module, Callable0], + ; functor(Callable, (:), 2), arg(1, Callable, Module), arg(2, Callable, Callable0), atom(Module) -> diff --git a/src/machine/compile.rs b/src/machine/compile.rs index e75259a6..3c7f9eb8 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -3,9 +3,9 @@ use prolog_parser::clause_name; use crate::codegen::*; use crate::debray_allocator::*; use crate::indexing::{merge_clause_index, remove_index}; -use crate::machine::load_state::set_code_index; -use crate::machine::load_state::LoadState; +use crate::machine::load_state::*; use crate::machine::loader::*; +use crate::machine::preprocessor::*; use crate::machine::term_stream::*; use crate::machine::*; @@ -45,7 +45,7 @@ pub(super) fn compile_relation( tl: &TopLevel, ) -> Result { match tl { - &TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(CompilationError::ExpectedRel), + &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), @@ -54,16 +54,15 @@ pub(super) fn compile_relation( pub(super) fn compile_appendix( code: &mut Code, - queue: &VecDeque, + mut queue: VecDeque, jmp_by_locs: Vec, non_counted_bt: bool, atom_tbl: TabledData, ) -> Result<(), CompilationError> { let mut jmp_by_locs = VecDeque::from(jmp_by_locs); - for tl in queue.iter() { + while let Some(jmp_by_offset) = jmp_by_locs.pop_front() { let code_len = code.len(); - let jmp_by_offset = jmp_by_locs.pop_front().unwrap(); match &mut code[jmp_by_offset] { &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => { @@ -76,9 +75,10 @@ pub(super) fn compile_appendix( // false because the inner predicate is a one-off, hence not extensible. let settings = CodeGenSettings::new(false, non_counted_bt); - let mut cg = CodeGenerator::::new(atom_tbl.clone(), settings); - let decl_code = compile_relation(&mut cg, tl)?; + + let tl = queue.pop_front().unwrap(); + let decl_code = compile_relation(&mut cg, &tl)?; jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len())); code.extend(decl_code.into_iter()); @@ -109,29 +109,6 @@ fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) 0 } -fn compile_standalone_clause( - clause: PredicateClause, - queue: VecDeque, - settings: CodeGenSettings, - atom_tbl: TabledData, -) -> Result { - let mut cg = CodeGenerator::::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, - }) -} - fn derelictize_try_me_else( code: &mut Code, index: usize, @@ -341,17 +318,21 @@ fn merge_indexed_subsequences( None } -fn delete_from_dynamic_skeleton( +fn delete_from_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); + let clause_clause_loc = skeleton.clause_clause_locs.remove(target_pos); - retraction_info.push_record(RetractionRecord::RemovedDynamicSkeletonClause( + if target_pos < skeleton.clause_assert_margin { + skeleton.clause_assert_margin -= 1; + } + + retraction_info.push_record(RetractionRecord::RemovedSkeletonClause( compilation_target, key, target_pos, @@ -585,7 +566,7 @@ fn finalize_retract( index_ptr_opt: Option, retraction_info: &mut RetractionInfo, ) -> usize { - let clause_clause_loc = delete_from_dynamic_skeleton( + let clause_clause_loc = delete_from_skeleton( compilation_target.clone(), key.clone(), skeleton, @@ -1007,13 +988,40 @@ fn mergeable_indexed_subsequences( } impl<'a> LoadState<'a> { + fn compile_standalone_clause( + &mut self, + term: Term, + settings: CodeGenSettings, + atom_tbl: TabledData, + ) -> Result { + let mut preprocessor = Preprocessor::new(self.wam.machine_st.flags); + let mut cg = CodeGenerator::::new(atom_tbl.clone(), settings); + + let clause = self.try_term_to_tl(term, &mut preprocessor)?; + let queue = preprocessor.parse_queue(self)?; + + 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, + }) + } + fn compile( &mut self, key: PredicateKey, - predicates: &PredicateQueue, // &Vec, - queue: &VecDeque, + predicates: &mut PredicateQueue, settings: CodeGenSettings, - ) -> Result { + ) -> Result<(), SessionError> { let code_index = self.get_or_insert_code_index( key.clone(), predicates.compilation_target.clone(), @@ -1025,7 +1033,15 @@ impl<'a> LoadState<'a> { let mut cg = CodeGenerator::::new(self.wam.machine_st.atom_tbl.clone(), settings); - let mut code = cg.compile_predicate(&predicates.predicates)?; + let mut clauses = vec![]; + let mut preprocessor = Preprocessor::new(self.wam.machine_st.flags); + + for term in predicates.predicates.drain(0 ..) { + clauses.push(self.try_term_to_tl(term, &mut preprocessor)?); + } + + let queue = preprocessor.parse_queue(self)?; + let mut code = cg.compile_predicate(&clauses)?; compile_appendix( &mut code, @@ -1036,9 +1052,13 @@ impl<'a> LoadState<'a> { )?; if settings.is_extensible { + let mut clause_clause_locs = sdeq![]; + 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; + + clause_clause_locs.push_back(clause_index_info.clause_start); } match &mut code[0] { @@ -1062,8 +1082,15 @@ impl<'a> LoadState<'a> { )); skeleton.clauses.extend(cg.skeleton.clauses.into_iter()); + skeleton.clause_clause_locs.extend_from_slice( + &clause_clause_locs[0 ..] + ); } None => { + cg.skeleton.clause_clause_locs.extend_from_slice( + &clause_clause_locs[0 ..] + ); + self.add_extensible_predicate( key.clone(), cg.skeleton, @@ -1071,6 +1098,15 @@ impl<'a> LoadState<'a> { ); } } + + let mut skeleton = PredicateSkeleton::new(); + skeleton.clause_clause_locs = clause_clause_locs; + + self.add_local_extensible_predicate( + predicates.compilation_target.clone(), + key.clone(), + skeleton, + ); } set_code_index( @@ -1082,7 +1118,7 @@ impl<'a> LoadState<'a> { ); self.wam.code_repo.code.extend(code.into_iter()); - Ok(code_index.get()) + Ok(()) } fn record_incremental_compile( @@ -1119,24 +1155,23 @@ impl<'a> LoadState<'a> { pub(super) fn incremental_compile_clause( &mut self, key: PredicateKey, - clause: PredicateClause, - queue: VecDeque, + clause: Term, compilation_target: CompilationTarget, non_counted_bt: bool, append_or_prepend: AppendOrPrepend, - ) -> Result { + ) -> Result<(), SessionError> { self.record_incremental_compile( key.clone(), compilation_target.clone(), append_or_prepend, ); - let skeleton = match self + match self .wam .indices .get_predicate_skeleton_mut(&compilation_target, &key) { - Some(skeleton) if !skeleton.clauses.is_empty() => skeleton, + Some(skeleton) if !skeleton.clauses.is_empty() => {}, _ => { // true because this predicate is extensible. let settings = CodeGenSettings::new(true, non_counted_bt); @@ -1144,7 +1179,7 @@ impl<'a> LoadState<'a> { let mut predicate_queue = predicate_queue![clause]; predicate_queue.compilation_target = compilation_target; - return self.compile(key, &predicate_queue, &queue, settings); + return self.compile(key, &mut predicate_queue, settings); } }; @@ -1154,13 +1189,25 @@ impl<'a> LoadState<'a> { let StandaloneCompileResult { clause_code, mut standalone_skeleton, - } = compile_standalone_clause(clause, queue, settings, atom_tbl)?; + } = self.compile_standalone_clause(clause, settings, atom_tbl)?; + + let code_len = self.wam.code_repo.code.len(); + + let skeleton = match self + .wam + .indices + .get_predicate_skeleton_mut(&compilation_target, &key) + { + Some(skeleton) if !skeleton.clauses.is_empty() => skeleton, + _ => unreachable!() + }; match append_or_prepend { AppendOrPrepend::Append => { - skeleton - .clauses - .push_back(standalone_skeleton.clauses.pop_back().unwrap()); + let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap(); + skeleton.clauses.push_back(clause_index_info); + + skeleton.clause_clause_locs.push_back(code_len); self.retraction_info .push_record(RetractionRecord::SkeletonClausePopBack( @@ -1175,6 +1222,38 @@ impl<'a> LoadState<'a> { &mut self.retraction_info, ); + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &self.compilation_target, + compilation_target.clone(), + key.clone(), + ) + { + Some(skeleton) => { + self.retraction_info.push_record( + RetractionRecord::SkeletonLocalClauseClausePopBack( + self.compilation_target.clone(), + compilation_target.clone(), + key.clone(), + ), + ); + + skeleton.clause_clause_locs.push_back(code_len); + } + None => { + let mut skeleton = PredicateSkeleton::new(); + skeleton.clause_clause_locs.push_back(code_len); + + self.add_local_extensible_predicate( + compilation_target.clone(), + key.clone(), + skeleton, + ); + } + } + let code_index = self.get_or_insert_code_index( key.clone(), compilation_target.clone(), @@ -1190,12 +1269,14 @@ impl<'a> LoadState<'a> { ); } - Ok(code_index.get()) + Ok(()) } AppendOrPrepend::Prepend => { - skeleton - .clauses - .push_front(standalone_skeleton.clauses.pop_back().unwrap()); + let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap(); + skeleton.clauses.push_front(clause_index_info); + + skeleton.clause_clause_locs.push_front(code_len); + skeleton.clause_assert_margin += 1; self.retraction_info .push_record(RetractionRecord::SkeletonClausePopFront( @@ -1212,6 +1293,38 @@ impl<'a> LoadState<'a> { &mut self.retraction_info, ); + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &self.compilation_target, + compilation_target.clone(), + key.clone(), + ) + { + Some(skeleton) => { + self.retraction_info.push_record( + RetractionRecord::SkeletonLocalClauseClausePopFront( + self.compilation_target.clone(), + compilation_target.clone(), + key.clone(), + ), + ); + + skeleton.clause_clause_locs.push_front(code_len); + } + None => { + let mut skeleton = PredicateSkeleton::new(); + skeleton.clause_clause_locs.push_front(code_len); + + self.add_local_extensible_predicate( + compilation_target.clone(), + key.clone(), + skeleton, + ); + } + } + let code_index = self.get_or_insert_code_index( key.clone(), compilation_target.clone(), @@ -1225,7 +1338,7 @@ impl<'a> LoadState<'a> { IndexPtr::Index(threaded_choice_instr_loc), ); - Ok(IndexPtr::Index(threaded_choice_instr_loc)) + Ok(()) } } } @@ -1309,7 +1422,7 @@ impl<'a> LoadState<'a> { skeleton.clauses[target_pos + 1].clause_start = skeleton.clauses[target_pos].clause_start; - return delete_from_dynamic_skeleton( + return delete_from_skeleton( self.compilation_target.clone(), key, skeleton, @@ -1530,12 +1643,12 @@ impl<'a, TS: TermStream> Loader<'a, TS> { append_or_prepend: AppendOrPrepend, ) -> Result<(), SessionError> { let clause_predicates = clause_clauses.map(|(head, body)| { - PredicateClause::Fact(Term::Clause( + Term::Clause( Cell::default(), clause_name!("$clause"), vec![Box::new(head), Box::new(body)], None, - )) + ) }); let clause_clause_compilation_target = match compilation_target { @@ -1543,49 +1656,64 @@ impl<'a, TS: TermStream> Loader<'a, TS> { _ => compilation_target.clone(), }; - let mut clause_clause_locs = sdeq![]; - - for clause_predicate in clause_predicates { - clause_clause_locs.push_back(self.load_state.wam.code_repo.code.len()); + let mut num_clause_predicates = 0; + for clause_term in clause_predicates { self.load_state.incremental_compile_clause( (clause_name!("$clause"), 2), - clause_predicate, - VecDeque::new(), + clause_term, clause_clause_compilation_target.clone(), false, // non_counted_bt is false. append_or_prepend, )?; + + num_clause_predicates += 1; } + let locs_vec: Vec<_> = match self + .load_state + .wam + .indices + .get_predicate_skeleton_mut(&compilation_target, &key) + { + Some(skeleton) if append_or_prepend.is_append() => { + let tail_num = skeleton.clause_clause_locs.len() - num_clause_predicates; + skeleton.clause_clause_locs[tail_num ..] + .iter() + .cloned() + .collect() + } + Some(skeleton) => { + skeleton.clause_clause_locs[0 .. num_clause_predicates] + .iter() + .cloned() + .collect() + } + None => { + unreachable!() + } + }; + match self.load_state.wam.indices.get_predicate_skeleton_mut( &clause_clause_compilation_target, &(clause_name!("$clause"), 2), ) { Some(skeleton) if append_or_prepend.is_append() => { - self.load_state.retraction_info.push_record( - RetractionRecord::SkeletonClauseClausesTruncateBack( - clause_clause_compilation_target.clone(), - (clause_name!("$clause"), 2), - skeleton.clause_clause_locs.len(), - ), - ); + for _ in 0 .. num_clause_predicates { + skeleton.clause_clause_locs.pop_back(); + } - skeleton - .clause_clause_locs - .extend_from_slice(&clause_clause_locs[0..]); + for loc in locs_vec { + skeleton.clause_clause_locs.push_back(loc); + } } Some(skeleton) => { - self.load_state.retraction_info.push_record( - RetractionRecord::SkeletonClauseClausesTruncateFront( - clause_clause_compilation_target.clone(), - (clause_name!("$clause"), 2), - skeleton.clause_clause_locs.len(), - ), - ); + for _ in 0 .. num_clause_predicates { + skeleton.clause_clause_locs.pop_front(); + } - for loc in clause_clause_locs.iter() { - skeleton.clause_clause_locs.push_front(*loc); + for loc in locs_vec.into_iter().rev() { + skeleton.clause_clause_locs.push_front(loc); } } None => { @@ -1593,82 +1721,128 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - match self - .load_state - .wam - .indices - .get_predicate_skeleton_mut(&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(), - ), - ); - - 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(), - ), - ); - - for loc in clause_clause_locs.iter() { - skeleton.clause_clause_locs.push_front(*loc); - } - - self.load_state.increment_clause_assert_margin( - clause_clause_compilation_target, - clause_clause_locs.len(), - ); - } - None => { - unreachable!() - } - } - Ok(()) } pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> { - let queue = self.preprocessor.parse_queue(&mut self.load_state)?; - let key = self .predicates .first() .and_then(|cl| { - let arity = cl.arity(); - cl.name().map(|name| (name, arity)) + let arity = ClauseInfo::arity(cl); + ClauseInfo::name(cl).map(|name| (name, arity)) }) .ok_or(SessionError::NamelessEntry)?; - let (is_dynamic, is_extensible) = self + let mut predicate_info = self .load_state .wam .indices .get_predicate_skeleton(&self.predicates.compilation_target, &key) - .map(|skeleton| (skeleton.is_dynamic, true)) - .unwrap_or((false, false)); + .map(|skeleton| skeleton.predicate_info()) + .unwrap_or_default(); - let non_counted_bt = self.non_counted_bt_preds.contains(&key); - let settings = CodeGenSettings::new(is_extensible, non_counted_bt); + let local_predicate_info = self + .load_state + .wam + .indices + .get_local_predicate_skeleton( + &self.load_state.compilation_target, + self.predicates.compilation_target.clone(), + key.clone(), + ) + .map(|skeleton| skeleton.predicate_info()) + .unwrap_or_default(); - self.load_state - .compile(key.clone(), &self.predicates, &queue, settings)?; - - if is_dynamic { - let iter = mem::replace(&mut self.clause_clauses, vec![]).into_iter(); - let compilation_target = self.predicates.compilation_target.clone(); - - self.compile_clause_clauses(key, compilation_target, iter, AppendOrPrepend::Append)?; + if predicate_info.must_retract_local_clauses() { + self.retract_local_clauses(&key, predicate_info.is_dynamic); } - Ok(self.predicates.clear()) + let do_incremental_compile = + if self.load_state.compilation_target == self.predicates.compilation_target { + predicate_info.compile_incrementally() + } else { + local_predicate_info.is_multifile && predicate_info.compile_incrementally() + }; + + let predicates_len = self.predicates.len(); + let non_counted_bt = self.non_counted_bt_preds.contains(&key); + + if do_incremental_compile { + for term in self.predicates.predicates.drain(0 ..) { + self.load_state.incremental_compile_clause( + key.clone(), + term, + self.predicates.compilation_target.clone(), + non_counted_bt, + AppendOrPrepend::Append, + )?; + } + } else { + if self.load_state.compilation_target != self.predicates.compilation_target { + if !local_predicate_info.is_extensible { + if predicate_info.is_multifile { + println!("Warning: overwriting multifile predicate {}:{}/{} because \ + it was not locally declared multifile.", + self.predicates.compilation_target, key.0, key.1); + } + + if let Some(skeleton) = self.load_state + .wam + .indices + .remove_predicate_skeleton( + &self.predicates.compilation_target, + &key, + ) + { + if predicate_info.is_dynamic { + let clause_clause_compilation_target = + match &self.predicates.compilation_target { + CompilationTarget::User => { + CompilationTarget::Module(clause_name!("builtins")) + } + module => { + module.clone() + } + }; + + self.load_state.retract_local_clauses_by_locs( + clause_clause_compilation_target, + (clause_name!("$clause"), 2), + (0 .. skeleton.clauses.len()).map(Some).collect(), + ); + + predicate_info.is_dynamic = false; + } + + self.load_state.retraction_info.push_record( + RetractionRecord::RemovedSkeleton( + self.predicates.compilation_target.clone(), + key.clone(), + skeleton, + ), + ); + } + } + } + + let settings = CodeGenSettings::new(predicate_info.is_extensible, non_counted_bt); + self.load_state.compile(key.clone(), &mut self.predicates, settings)?; + } + + if predicate_info.is_dynamic { + let clauses_vec: Vec<_> = self.clause_clauses + .drain(0 .. predicates_len) + .collect(); + + self.compile_clause_clauses( + key, + self.predicates.compilation_target.clone(), + clauses_vec.into_iter(), + AppendOrPrepend::Append, + )?; + } + + Ok(()) } } diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 81427d05..c0e22473 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -1,11 +1,13 @@ use crate::machine::machine_indices::*; +use crate::machine::preprocessor::*; use crate::machine::*; +use crate::machine::term_stream::*; + use prolog_parser::clause_name; -use crate::machine::term_stream::*; use indexmap::IndexSet; - use ref_thread_local::RefThreadLocal; +use slice_deque::{sdeq, SliceDeque}; type ModuleOpExports = Vec<(OpDecl, Option<(usize, Specifier)>)>; @@ -328,28 +330,120 @@ fn import_qualified_module_exports_into_module( } impl<'a> LoadState<'a> { - #[inline] - pub(super) fn increment_clause_assert_margin( + pub(super) fn retract_local_clauses( &mut self, compilation_target: CompilationTarget, - incr: usize, + key: PredicateKey, + clause_locs: &SliceDeque, ) { - match compilation_target { - CompilationTarget::User => {} - CompilationTarget::Module(module_name) => { - self.wam - .indices - .modules - .get_mut(&module_name) - .map(|module| module.clause_assert_margin += incr); + let clause_target_poses: Vec<_> = self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + .map(|skeleton| { + clause_locs + .iter() + .map(|clause_clause_loc| { + skeleton.target_pos_of_clause_clause_loc( + *clause_clause_loc, + ) + }) + .collect() + }).unwrap(); - self.retraction_info - .push_record(RetractionRecord::IncreasedClauseAssertMargin( - module_name, - incr, - )); + self.retract_local_clauses_by_locs( + compilation_target, + key, + clause_target_poses, + ); + } + + pub(super) fn retract_local_clauses_by_locs( + &mut self, + compilation_target: CompilationTarget, + key: PredicateKey, + mut clause_target_poses: Vec>, + ) { + let old_compilation_target = mem::replace( + &mut self.compilation_target, + compilation_target, + ); + + while let Some(target_pos_opt) = clause_target_poses.pop() { + match target_pos_opt { + Some(target_pos) => { + self.retract_clause(key.clone(), target_pos); + } + None => { + // Here because the clause was been removed + // earlier, e.g., by retract, without updating the + // local skeleton. In this case, do nothing. + } } } + + self.compilation_target = old_compilation_target; + } + + pub(super) fn retract_local_clause_clauses( + &mut self, + clause_clause_compilation_target: CompilationTarget, + clause_locs: &SliceDeque, + ) { + let key = (clause_name!("$clause"), 2); + + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &self.compilation_target, + clause_clause_compilation_target.clone(), + key.clone(), + ) + { + Some(skeleton) => { + self.retraction_info.push_record( + RetractionRecord::RemovedLocalSkeletonClauseLocations( + self.compilation_target.clone(), + clause_clause_compilation_target.clone(), + key.clone(), + mem::replace(&mut skeleton.clause_clause_locs, sdeq![]), + ), + ); + + skeleton.reset(); + } + None => { + // The local skeleton might be removed when reloading + // or redefining a module, in which case no retraction + // record is necessary. + } + }; + + self.retract_local_clauses( + clause_clause_compilation_target, + key, + &clause_locs, + ); + } + + pub(super) fn try_term_to_tl( + &mut self, + term: Term, + preprocessor: &mut Preprocessor, + ) -> Result { + let tl = preprocessor.try_term_to_tl( + self, + term, + CutContext::BlocksCuts, + )?; + + Ok(match tl { + TopLevel::Fact(fact) => PredicateClause::Fact(fact), + TopLevel::Rule(rule) => PredicateClause::Rule(rule), + TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact), + _ => unreachable!(), + }) } #[inline] @@ -451,16 +545,51 @@ impl<'a> LoadState<'a> { .extensible_predicates .insert(key.clone(), skeleton); - self.retraction_info - .push_record(RetractionRecord::AddedUserExtensiblePredicate(key)); + let record = RetractionRecord::AddedExtensiblePredicate( + CompilationTarget::User, + key, + ); + + self.retraction_info.push_record(record); } CompilationTarget::Module(module_name) => { if let Some(module) = self.wam.indices.modules.get_mut(&module_name) { - module.extensible_predicates.insert(key.clone(), skeleton); + module + .extensible_predicates + .insert(key.clone(), skeleton); - self.retraction_info.push_record( - RetractionRecord::AddedModuleExtensiblePredicate(module_name, key), + let record = RetractionRecord::AddedExtensiblePredicate( + CompilationTarget::Module(module_name), + key, ); + + self.retraction_info.push_record(record); + } else { + unreachable!() + } + } + } + } + + #[inline] + pub(super) fn add_local_extensible_predicate( + &mut self, + local_compilation_target: CompilationTarget, + key: PredicateKey, + skeleton: PredicateSkeleton, + ) { + match self.compilation_target.clone() { + CompilationTarget::User => { + self.wam + .indices + .local_extensible_predicates + .insert((local_compilation_target.clone(), key.clone()), skeleton); + } + CompilationTarget::Module(module_name) => { + if let Some(module) = self.wam.indices.modules.get_mut(&module_name) { + module + .local_extensible_predicates + .insert((local_compilation_target.clone(), key.clone()), skeleton); } else { unreachable!() } @@ -604,32 +733,40 @@ impl<'a> LoadState<'a> { } } None => { - let module_decl = ModuleDecl { - name: module_name.clone(), - exports: vec![], - }; + self.add_dynamically_generated_module(&module_name); - let listing_src = ListingSource::DynamicallyGenerated; - let mut module = Module::new(module_decl, listing_src); - - module.meta_predicates.insert(key.clone(), meta_specs); + if let Some(module) = self.wam.indices.modules.get_mut(&module_name) { + module.meta_predicates.insert(key.clone(), meta_specs); + } else { + unreachable!() + } 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); } } } } } + pub(super) fn add_dynamically_generated_module(&mut self, module_name: &ClauseName) { + let module_decl = ModuleDecl { + name: module_name.clone(), + exports: vec![], + }; + + let listing_src = ListingSource::DynamicallyGenerated; + let module = Module::new(module_decl, listing_src); + + self.retraction_info + .push_record(RetractionRecord::AddedModule(module_name.clone())); + + self.wam.indices.modules.insert(module_name.clone(), module); + } + fn import_builtins_in_module( &mut self, code_dir: &mut CodeDir, @@ -651,16 +788,57 @@ impl<'a> LoadState<'a> { pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) { let module_name = module_decl.name.clone(); + match self.wam.indices.modules.get_mut(&module_name) { + Some(module) => { + let old_module_decl = mem::replace(&mut module.module_decl, module_decl.clone()); + + let local_extensible_predicates = mem::replace( + &mut module.local_extensible_predicates, + LocalExtensiblePredicates::new(), + ); + + for ((compilation_target, key), skeleton) in local_extensible_predicates.iter() { + self.retract_local_clauses( + compilation_target.clone(), + key.clone(), + &skeleton.clause_clause_locs, + ); + + let is_dynamic = self + .wam + .indices + .get_predicate_skeleton(&compilation_target, &key) + .map(|skeleton| skeleton.is_dynamic) + .unwrap_or(false); + + if is_dynamic { + let clause_clause_compilation_target = match compilation_target { + CompilationTarget::User => { + CompilationTarget::Module(clause_name!("builtins")) + } + module => { + module.clone() + } + }; + + self.retract_local_clause_clauses( + clause_clause_compilation_target, + &skeleton.clause_clause_locs, + ); + } + } + + self.retraction_info.push_record(RetractionRecord::ReplacedModule( + old_module_decl, + listing_src.clone(), + local_extensible_predicates, + )); + } + None => {} + } + 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 } diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 7046fa1e..3ece45ba 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -9,6 +9,7 @@ use crate::machine::preprocessor::*; use crate::machine::*; use indexmap::IndexSet; +use slice_deque::{sdeq, SliceDeque}; use std::cell::Cell; use std::convert::TryFrom; @@ -28,10 +29,10 @@ use std::rc::Rc; * 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. + * structure to rebuild the loader between invocations. Preprocessor + * 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, @@ -46,19 +47,19 @@ pub(crate) enum RetractionRecord { AddedMetaPredicate(ClauseName, PredicateKey), ReplacedMetaPredicate(ClauseName, ClauseName, Vec), AddedModule(ClauseName), - ReplacedModule(ModuleDecl, ListingSource), - AddedModuleDynamicPredicate(ClauseName, PredicateKey), - AddedModuleExtensiblePredicate(ClauseName, PredicateKey), + ReplacedModule(ModuleDecl, ListingSource, LocalExtensiblePredicates), AppendedModuleExtensiblePredicate(ClauseName, PredicateKey), PrependedModuleExtensiblePredicate(ClauseName, PredicateKey), AddedModuleOp(ClauseName, OpDecl), ReplacedModuleOp(ClauseName, OpDecl, usize, Specifier), AddedModulePredicate(ClauseName, PredicateKey), ReplacedModulePredicate(ClauseName, PredicateKey, IndexPtr), - AddedUserDynamicPredicate(PredicateKey), + AddedDiscontiguousPredicate(CompilationTarget, PredicateKey), + AddedDynamicPredicate(CompilationTarget, PredicateKey), + AddedMultifilePredicate(CompilationTarget, PredicateKey), AddedUserOp(OpDecl), ReplacedUserOp(OpDecl, usize, Specifier), - AddedUserExtensiblePredicate(PredicateKey), + AddedExtensiblePredicate(CompilationTarget, PredicateKey), AppendedUserExtensiblePredicate(PredicateKey), PrependedUserExtensiblePredicate(PredicateKey), AddedUserPredicate(PredicateKey), @@ -71,14 +72,13 @@ pub(crate) enum RetractionRecord { 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), + SkeletonLocalClauseClausePopBack(CompilationTarget, CompilationTarget, PredicateKey), + SkeletonLocalClauseClausePopFront(CompilationTarget, CompilationTarget, PredicateKey), SkeletonClauseTruncateBack(CompilationTarget, PredicateKey, usize), SkeletonClauseStartReplaced(CompilationTarget, PredicateKey, usize, usize), - RemovedDynamicSkeletonClause( + RemovedSkeletonClause( CompilationTarget, PredicateKey, usize, @@ -86,6 +86,13 @@ pub(crate) enum RetractionRecord { usize, ), ReplacedIndexingLine(usize, Vec), + RemovedLocalSkeletonClauseLocations( + CompilationTarget, + CompilationTarget, + PredicateKey, + SliceDeque, + ), + RemovedSkeleton(CompilationTarget, PredicateKey, PredicateSkeleton), } /* @@ -123,7 +130,7 @@ impl RetractionInfo { Self { orig_code_extent, - records: mem::replace(&mut self.records, vec![]), //BTreeMap::new()), + records: mem::replace(&mut self.records, vec![]), } } } @@ -170,31 +177,90 @@ impl<'a> Drop for LoadState<'a> { RetractionRecord::AddedModule(module_name) => { self.wam.indices.modules.remove(&module_name); } - RetractionRecord::ReplacedModule(module_decl, listing_src) => { + RetractionRecord::ReplacedModule( + module_decl, + listing_src, + local_extensible_predicates, + ) => { match self.wam.indices.modules.get_mut(&module_decl.name) { Some(ref mut module) => { module.module_decl = module_decl; module.listing_src = listing_src; + module.local_extensible_predicates = local_extensible_predicates; } _ => { 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; - }); + RetractionRecord::AddedDiscontiguousPredicate(compilation_target, key) => { + match compilation_target { + CompilationTarget::User => { + self.wam + .indices + .extensible_predicates + .get_mut(&key) + .map(|skeleton| { + skeleton.is_discontiguous = false; + }); + } + CompilationTarget::Module(module_name) => { + match self.wam.indices.modules.get_mut(&module_name) { + Some(ref mut module) => { + module.extensible_predicates.get_mut(&key).map(|skeleton| { + skeleton.is_discontiguous = false; + }); + } + None => {} + } } - None => {} } } - RetractionRecord::AddedModuleExtensiblePredicate(module_name, key) => { - self.wam - .indices - .remove_predicate_skeleton(&CompilationTarget::Module(module_name), &key); + RetractionRecord::AddedDynamicPredicate(compilation_target, key) => { + match compilation_target { + CompilationTarget::User => { + self.wam + .indices + .extensible_predicates + .get_mut(&key) + .map(|skeleton| { + skeleton.is_dynamic = false; + }); + } + CompilationTarget::Module(module_name) => { + 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::AddedMultifilePredicate(compilation_target, key) => { + match compilation_target { + CompilationTarget::User => { + self.wam + .indices + .extensible_predicates + .get_mut(&key) + .map(|skeleton| { + skeleton.is_multifile = false; + }); + } + CompilationTarget::Module(module_name) => { + match self.wam.indices.modules.get_mut(&module_name) { + Some(ref mut module) => { + module.extensible_predicates.get_mut(&key).map(|skeleton| { + skeleton.is_multifile = false; + }); + } + None => {} + } + } + } } RetractionRecord::AppendedModuleExtensiblePredicate(module_name, key) => { self.wam @@ -249,19 +315,10 @@ impl<'a> Drop for LoadState<'a> { None => {} } } - RetractionRecord::AddedUserDynamicPredicate(key) => { + RetractionRecord::AddedExtensiblePredicate(compilation_target, 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); + .remove_predicate_skeleton(&compilation_target, &key); } RetractionRecord::AppendedUserExtensiblePredicate(key) => { self.wam @@ -399,79 +456,6 @@ impl<'a> Drop for LoadState<'a> { 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_mut(&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_mut(&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_mut(&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_mut(&compilation_target, &(clause_name!("$clause"), 2)) - { - Some(skeleton) => { - skeleton.clause_clause_locs.truncate_back(len); - } - None => {} - } - } RetractionRecord::SkeletonClausePopBack(compilation_target, key) => { match self .wam @@ -480,6 +464,7 @@ impl<'a> Drop for LoadState<'a> { { Some(skeleton) => { skeleton.clauses.pop_back(); + skeleton.clause_clause_locs.pop_back(); } None => {} } @@ -492,6 +477,44 @@ impl<'a> Drop for LoadState<'a> { { Some(skeleton) => { skeleton.clauses.pop_front(); + skeleton.clause_clause_locs.pop_front(); + skeleton.clause_assert_margin -= 1; + } + None => {} + } + } + RetractionRecord::SkeletonLocalClauseClausePopFront( + src_compilation_target, local_compilation_target, key, + ) => { + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &src_compilation_target, + local_compilation_target, + key, + ) + { + Some(skeleton) => { + skeleton.clause_clause_locs.pop_front(); + } + None => {} + } + } + RetractionRecord::SkeletonLocalClauseClausePopBack( + src_compilation_target, local_compilation_target, key, + ) => { + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &src_compilation_target, + local_compilation_target, + key, + ) + { + Some(skeleton) => { + skeleton.clause_clause_locs.pop_back(); } None => {} } @@ -504,6 +527,7 @@ impl<'a> Drop for LoadState<'a> { { Some(skeleton) => { skeleton.clauses.truncate_back(len); + skeleton.clause_clause_locs.truncate_back(len); } None => {} } @@ -525,7 +549,7 @@ impl<'a> Drop for LoadState<'a> { None => {} } } - RetractionRecord::RemovedDynamicSkeletonClause( + RetractionRecord::RemovedSkeletonClause( compilation_target, key, target_pos, @@ -549,6 +573,37 @@ impl<'a> Drop for LoadState<'a> { RetractionRecord::ReplacedIndexingLine(index_loc, indexing_code) => { self.wam.code_repo.code[index_loc] = Line::IndexingCode(indexing_code); } + RetractionRecord::RemovedLocalSkeletonClauseLocations( + compilation_target, + local_compilation_target, + key, + clause_locs, + ) => { + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &compilation_target, + local_compilation_target, + key, + ) + { + Some(skeleton) => skeleton.clause_clause_locs = clause_locs, + None => {} + } + } + RetractionRecord::RemovedSkeleton(compilation_target, key, skeleton) => { + match compilation_target { + CompilationTarget::User => { + self.wam.indices.extensible_predicates.insert(key, skeleton); + } + CompilationTarget::Module(module_name) => { + if let Some(module) = self.wam.indices.modules.get_mut(&module_name) { + module.extensible_predicates.insert(key, skeleton); + } + } + } + } } } @@ -557,7 +612,7 @@ impl<'a> Drop for LoadState<'a> { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum CompilationTarget { Module(ClauseName), User, @@ -577,7 +632,7 @@ impl CompilationTarget { } #[inline] - pub(super) fn module_name(&self) -> ClauseName { + pub fn module_name(&self) -> ClauseName { match self { CompilationTarget::User => { clause_name!("user") @@ -588,28 +643,18 @@ impl CompilationTarget { } pub struct PredicateQueue { - pub(super) predicates: Vec, + pub(super) predicates: Vec, pub(super) compilation_target: CompilationTarget, } impl PredicateQueue { #[inline] - pub(super) fn push(&mut self, clause: PredicateClause) { + pub(super) fn push(&mut self, clause: Term) { self.predicates.push(clause); } #[inline] - pub(super) fn extend(&mut self, iter: impl Iterator) { - self.predicates.extend(iter); - } - - #[inline] - pub(super) fn clear(&mut self) { - self.predicates.clear(); - } - - #[inline] - pub(crate) fn first(&self) -> Option<&PredicateClause> { + pub(crate) fn first(&self) -> Option<&Term> { self.predicates.first() } @@ -625,6 +670,11 @@ impl PredicateQueue { compilation_target: self.compilation_target.take(), } } + + #[inline] + pub(super) fn len(&self) -> usize { + self.predicates.len() + } } macro_rules! predicate_queue { @@ -642,13 +692,11 @@ pub(crate) struct Loader<'a, TermStream> { pub(super) clause_clauses: Vec<(Term, Term)>, term_stream: TermStream, pub(super) non_counted_bt_preds: IndexSet, - 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![], @@ -660,7 +708,6 @@ impl<'a, TS: TermStream> Loader<'a, TS> { load_state, term_stream, non_counted_bt_preds: IndexSet::new(), - preprocessor: Preprocessor::new(flags), predicates: predicate_queue![], clause_clauses: vec![], } @@ -683,19 +730,15 @@ impl<'a, TS: TermStream> Loader<'a, TS> { self.compile_and_submit()?; } - let tl = self.preprocessor.try_term_to_tl( - &mut self.load_state, - term, - CutContext::BlocksCuts, - )?; + let term = match term { + Term::Clause(_, name, terms, _) + if name.as_str() == ":-" && terms.len() == 1 => { + return Ok(Some(setup_declaration(&self.load_state, terms)?)); + }, + term => term, + }; - 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.into_iter()), - TopLevel::Declaration(decl) => return Ok(Some(decl)), - TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact), - } + self.predicates.push(term); } Ok(None) @@ -704,7 +747,8 @@ impl<'a, TS: TermStream> Loader<'a, TS> { pub(super) fn load_decl(&mut self, decl: Declaration) -> Result<(), SessionError> { match decl { Declaration::Dynamic(name, arity) => { - self.add_dynamic_predicate(name, arity); + let compilation_target = self.load_state.compilation_target.clone(); + self.add_dynamic_predicate(compilation_target, name, arity)?; } Declaration::MetaPredicate(module_name, name, meta_specs) => { self.load_state @@ -857,10 +901,18 @@ impl<'a, TS: TermStream> Loader<'a, TS> { Ok(()) } - fn add_dynamic_predicate(&mut self, name: ClauseName, arity: usize) { + fn add_extensible_predicate_declaration( + &mut self, + compilation_target: CompilationTarget, + name: ClauseName, + arity: usize, + flag_accessor: impl Fn(&mut PredicateSkeleton) -> &mut bool, + retraction_fn: impl Fn(CompilationTarget, PredicateKey) -> RetractionRecord, + ) -> Result<(), SessionError> { let key = (name, arity); + let mut throw_permission_error = false; - match &self.load_state.compilation_target { + match &compilation_target { CompilationTarget::User => { match self .load_state @@ -870,20 +922,27 @@ impl<'a, TS: TermStream> Loader<'a, TS> { .get_mut(&key) { Some(ref mut skeleton) => { - if !skeleton.is_dynamic { - skeleton.is_dynamic = true; + if !*flag_accessor(skeleton) { + *flag_accessor(skeleton) = true; self.load_state.retraction_info.push_record( - RetractionRecord::AddedUserDynamicPredicate(key.clone()), + retraction_fn(compilation_target.clone(), key.clone()), ); } } None => { - self.load_state.add_extensible_predicate( - key.clone(), - PredicateSkeleton::new().set_dynamic(true), - CompilationTarget::User, - ); + if self.load_state.compilation_target == compilation_target { + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; + + self.load_state.add_extensible_predicate( + key.clone(), + skeleton, + CompilationTarget::User, + ); + } else { + throw_permission_error = true; + } } } } @@ -891,44 +950,176 @@ impl<'a, TS: TermStream> Loader<'a, TS> { 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; + if !*flag_accessor(skeleton) { + *flag_accessor(skeleton) = true; self.load_state.retraction_info.push_record( - RetractionRecord::AddedModuleDynamicPredicate( - module_name.clone(), - key.clone(), - ), + retraction_fn(compilation_target.clone(), key.clone()), ); } } None => { - self.load_state.add_extensible_predicate( - key.clone(), - PredicateSkeleton::new().set_dynamic(true), - self.load_state.compilation_target.clone(), - ); + if self.load_state.compilation_target == compilation_target { + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; + + self.load_state.add_extensible_predicate( + key.clone(), + skeleton, + compilation_target.clone(), + ); + } else { + throw_permission_error = true; + } } }, None => { - unreachable!(); + self.load_state.add_dynamically_generated_module(module_name); + + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; + + self.load_state.add_extensible_predicate( + key.clone(), + skeleton, + compilation_target.clone(), + ); } } } } + if !throw_permission_error { + match self.load_state.compilation_target.clone() { + CompilationTarget::User => { + match self + .load_state + .wam + .indices + .local_extensible_predicates + .get_mut(&(compilation_target.clone(), key.clone())) + { + Some(ref mut skeleton) => { + if !*flag_accessor(skeleton) { + *flag_accessor(skeleton) = true; + } + } + None => { + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; + + self.load_state.add_local_extensible_predicate( + compilation_target.clone(), + key.clone(), + skeleton, + ); + } + } + } + CompilationTarget::Module(ref module_name) => { + match self.load_state.wam.indices.modules.get_mut(module_name) { + Some(ref mut module) => + match module.local_extensible_predicates.get_mut( + &(compilation_target.clone(), key.clone()), + ) { + Some(ref mut skeleton) => { + if !*flag_accessor(skeleton) { + *flag_accessor(skeleton) = true; + } + } + None => { + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; + + self.load_state.add_local_extensible_predicate( + compilation_target.clone(), + key.clone(), + skeleton, + ); + } + }, + None => { + self.load_state.add_dynamically_generated_module(module_name); + + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; + + self.load_state.add_local_extensible_predicate( + compilation_target.clone(), + key.clone(), + skeleton, + ); + } + } + } + } + + Ok(()) + } else { + Err(SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key)) + } + } + + fn add_discontiguous_predicate( + &mut self, + compilation_target: CompilationTarget, + name: ClauseName, + arity: usize, + ) -> Result<(), SessionError> { + self.add_extensible_predicate_declaration( + compilation_target, + name, + arity, + |skeleton| &mut skeleton.is_discontiguous, + RetractionRecord::AddedDiscontiguousPredicate, + ) + } + + fn add_dynamic_predicate( + &mut self, + compilation_target: CompilationTarget, + name: ClauseName, + arity: usize, + ) -> Result<(), SessionError> { + self.add_extensible_predicate_declaration( + compilation_target.clone(), + name.clone(), + arity, + |skeleton| &mut skeleton.is_dynamic, + RetractionRecord::AddedDynamicPredicate, + )?; + let code_index = self.load_state.get_or_insert_code_index( - key.clone(), - self.load_state.compilation_target.clone(), + (name.clone(), arity), + compilation_target.clone(), ); - set_code_index( - &mut self.load_state.retraction_info, - &self.load_state.compilation_target, - key, - &code_index, - IndexPtr::DynamicUndefined, - ); + if let IndexPtr::Undefined = code_index.get() { + set_code_index( + &mut self.load_state.retraction_info, + &compilation_target, + (name, arity), + &code_index, + IndexPtr::DynamicUndefined, + ); + } + + Ok(()) + } + + fn add_multifile_predicate( + &mut self, + compilation_target: CompilationTarget, + name: ClauseName, + arity: usize, + ) -> Result<(), SessionError> { + self.add_extensible_predicate_declaration( + compilation_target, + name, + arity, + |skeleton| &mut skeleton.is_multifile, + RetractionRecord::AddedMultifilePredicate, + ) } fn add_clause_clause_if_dynamic(&mut self, term: &Term) -> Result<(), SessionError> { @@ -953,6 +1144,51 @@ impl<'a, TS: TermStream> Loader<'a, TS> { Ok(()) } + + pub(super) fn retract_local_clauses(&mut self, key: &PredicateKey, is_dynamic: bool) { + let clause_locs = match self + .load_state + .wam + .indices + .get_local_predicate_skeleton_mut( + &self.load_state.compilation_target, + self.predicates.compilation_target.clone(), + key.clone(), + ) + { + Some(skeleton) if !skeleton.clause_clause_locs.is_empty() => + mem::replace(&mut skeleton.clause_clause_locs, sdeq![]), + _ => + return, + }; + + self.load_state.retraction_info.push_record( + RetractionRecord::RemovedLocalSkeletonClauseLocations( + self.load_state.compilation_target.clone(), + self.predicates.compilation_target.clone(), + key.clone(), + clause_locs.clone(), + ), + ); + + self.load_state.retract_local_clauses( + self.predicates.compilation_target.clone(), + key.clone(), + &clause_locs, + ); + + if is_dynamic { + let clause_clause_compilation_target = match &self.predicates.compilation_target { + CompilationTarget::User => CompilationTarget::Module(clause_name!("builtins")), + module_name => module_name.clone(), + }; + + self.load_state.retract_local_clause_clauses( + clause_clause_compilation_target, + &clause_locs, + ); + } + } } impl Machine { @@ -1052,16 +1288,52 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } + #[inline] + pub(crate) fn add_discontiguous_predicate(&mut self) { + self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| { + loader.add_discontiguous_predicate(compilation_target, clause_name, arity) + }); + } + + #[inline] pub(crate) fn add_dynamic_predicate(&mut self) { - let predicate_name = atom_from!( + self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| { + loader.add_dynamic_predicate(compilation_target, clause_name, arity) + }); + } + + #[inline] + pub(crate) fn add_multifile_predicate(&mut self) { + self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| { + loader.add_multifile_predicate(compilation_target, clause_name, arity) + }); + } + + fn add_extensible_predicate_declaration( + &mut self, + decl_adder: impl Fn(&mut Loader, CompilationTarget, ClauseName, usize) + -> Result<(), SessionError>, + ) { + let module_name = atom_from!( self.machine_st, self.machine_st .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) ); + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + let predicate_name = atom_from!( + self.machine_st, + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(2)])) + ); + let arity = self .machine_st - .store(self.machine_st.deref(self.machine_st[temp_v!(2)])); + .store(self.machine_st.deref(self.machine_st[temp_v!(3)])); 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()), @@ -1071,14 +1343,14 @@ impl Machine { _ => Err(SessionError::from(CompilationError::InvalidRuleHead)), }; - let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3)); + let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(4)); - let add_dynamic_predicate = || { - loader.add_dynamic_predicate(predicate_name, arity?); + let add_predicate_decl = || { + decl_adder(&mut loader, compilation_target, predicate_name, arity?)?; LiveTermStream::evacuate(loader) }; - let result = add_dynamic_predicate(); + let result = add_predicate_decl(); self.restore_load_state_payload(result, evacuable_h); } @@ -1088,7 +1360,7 @@ impl Machine { let add_clause = || { let term = loader.read_term_from_heap(temp_v!(1))?; - loader.incremental_compile_clause( + loader.load_state.incremental_compile_clause( (clause_name!("term_expansion"), 2), term, CompilationTarget::User, @@ -1120,7 +1392,7 @@ impl Machine { let add_clause = || { let term = loader.read_term_from_heap(temp_v!(2))?; - loader.incremental_compile_clause( + loader.load_state.incremental_compile_clause( (clause_name!("goal_expansion"), 2), term, compilation_target, @@ -1415,7 +1687,7 @@ impl Machine { fetch_op_spec(clause_name!(":-"), 2, &loader.load_state.wam.indices.op_dir), ); - loader.incremental_compile_clause( + loader.load_state.incremental_compile_clause( key.clone(), asserted_clause, compilation_target.clone(), @@ -1484,15 +1756,6 @@ impl Machine { } }; - let mut clause_assert_margin = loader - .load_state - .wam - .indices - .modules - .get(&clause_clause_compilation_target.module_name()) - .map(|module| module.clause_assert_margin) - .unwrap(); - let mut clause_clause_target_poses: Vec<_> = loader .load_state .wam @@ -1513,8 +1776,7 @@ impl Machine { .map(|clause_clause_loc| { clause_clause_skeleton.target_pos_of_clause_clause_loc( *clause_clause_loc, - clause_assert_margin, - ) + ).unwrap() }) .collect() }) @@ -1527,10 +1789,7 @@ impl Machine { .wam .indices .get_predicate_skeleton_mut(&loader.load_state.compilation_target, &key) - .map(|skeleton| { - skeleton.clauses.clear(); - skeleton.clause_clause_locs.clear(); - }); + .map(|skeleton| skeleton.reset()); let code_index = loader.load_state.get_or_insert_code_index( key, @@ -1543,20 +1802,8 @@ impl Machine { while let Some(target_pos) = clause_clause_target_poses.pop() { loader.load_state.retract_clause((clause_name!("$clause"), 2), target_pos); - - if target_pos < clause_assert_margin { - clause_assert_margin -= 1; - } } - loader - .load_state - .wam - .indices - .modules - .get_mut(&loader.load_state.compilation_target.module_name()) - .map(|module| module.clause_assert_margin = clause_assert_margin); - LiveTermStream::evacuate(loader) }; @@ -1605,36 +1852,14 @@ impl Machine { let clause_clause_loc = loader.load_state.retract_clause(key, target_pos); - let clause_assert_margin = loader - .load_state - .wam - .indices - .modules - .get(&clause_clause_compilation_target.module_name()) - .map(|module| module.clause_assert_margin) - .unwrap(); - let target_pos = match loader.load_state.wam.indices.get_predicate_skeleton( &clause_clause_compilation_target, &(clause_name!("$clause"), 2), ) { Some(skeleton) => { - let target_pos = skeleton.target_pos_of_clause_clause_loc( + skeleton.target_pos_of_clause_clause_loc( clause_clause_loc, - clause_assert_margin, - ); - - if target_pos < clause_assert_margin { - loader - .load_state - .wam - .indices - .modules - .get_mut(&clause_clause_compilation_target.module_name()) - .map(|module| module.clause_assert_margin -= 1); - } - - target_pos + ).unwrap() } None => { unreachable!(); @@ -1834,10 +2059,6 @@ impl<'a> Loader<'a, LiveTermStream> { &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( @@ -1859,10 +2080,6 @@ impl<'a> Loader<'a, LiveTermStream> { &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: payload.predicates.take(), @@ -1875,44 +2092,6 @@ impl<'a> Loader<'a, LiveTermStream> { } } - 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!() - } - }; - - self.load_state.incremental_compile_clause( - key, - clause, - queue, - compilation_target, - non_counted_bt, - append_or_prepend, - )?; - - Ok(()) - } - fn read_and_enqueue_term( mut self, term_reg: RegType, diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 2e3b5e91..c446107f 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -4,6 +4,7 @@ use prolog_parser::{clause_name, temp_v}; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; use crate::machine::PredicateKey; use crate::machine::heap::*; +use crate::machine::loader::CompilationTarget; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; use crate::rug::Integer; @@ -344,6 +345,22 @@ impl MachineError { Self::permission_error(h, Permission::Create, "operator", functor!(clause_name(op))) } SessionError::CompilationError(err) => Self::syntax_error(h, err), + SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key) => { + let functor_stub = Self::functor_stub(key.0, key.1); + let stub = functor!( + ":", + SharedOpDesc::new(600, XFY), + [clause_name(compilation_target.module_name()), aux(h + 4, 0)], + [functor_stub] + ); + + Self::permission_error( + h, + Permission::Modify, + "not_declared_multifile_or_discontiguous", + stub, + ) + } SessionError::QueryCannotBeDefinedAsFact => Self::permission_error( h, Permission::Create, @@ -808,6 +825,7 @@ pub enum SessionError { ModuleCannotImportSelf(ClauseName), NamelessEntry, OpIsInfixAndPostFix(ClauseName), + PredicateNotMultifileOrDiscontiguous(CompilationTarget, PredicateKey), QueryCannotBeDefinedAsFact, } diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 4b4a4c18..2d0556d3 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -417,7 +417,9 @@ impl Default for CodeIndex { #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] pub enum REPLCodePtr { + AddDiscontiguousPredicate, AddDynamicPredicate, + AddMultifilePredicate, AddGoalExpansionClause, AddTermExpansionClause, ClauseToEvacuable, @@ -743,6 +745,68 @@ impl IndexStore { } } + pub fn get_local_predicate_skeleton_mut( + &mut self, + src_compilation_target: &CompilationTarget, + local_compilation_target: CompilationTarget, + key: PredicateKey, + ) -> Option<&mut PredicateSkeleton> { + match (key.0.as_str(), key.1) { + ("term_expansion", 2) => { + self.local_extensible_predicates.get_mut( + &(local_compilation_target, key), + ) + } + _ => match src_compilation_target { + CompilationTarget::User => { + self.local_extensible_predicates.get_mut( + &(local_compilation_target, key), + ) + } + CompilationTarget::Module(ref module_name) => { + if let Some(module) = self.modules.get_mut(module_name) { + module.local_extensible_predicates.get_mut( + &(local_compilation_target, key), + ) + } else { + None + } + } + }, + } + } + + pub fn get_local_predicate_skeleton( + &self, + src_compilation_target: &CompilationTarget, + local_compilation_target: CompilationTarget, + key: PredicateKey, + ) -> Option<&PredicateSkeleton> { + match (key.0.as_str(), key.1) { + ("term_expansion", 2) => { + self.local_extensible_predicates.get( + &(local_compilation_target, key), + ) + } + _ => match src_compilation_target { + CompilationTarget::User => { + self.local_extensible_predicates.get( + &(local_compilation_target, key), + ) + } + CompilationTarget::Module(ref module_name) => { + if let Some(module) = self.modules.get(module_name) { + module.local_extensible_predicates.get( + &(local_compilation_target, key), + ) + } else { + None + } + } + }, + } + } + pub fn get_predicate_skeleton( &self, compilation_target: &CompilationTarget, @@ -767,18 +831,20 @@ impl IndexStore { &mut self, compilation_target: &CompilationTarget, key: &PredicateKey, - ) { + ) -> Option { match (key.0.as_str(), key.1) { ("term_expansion", 2) => { - self.extensible_predicates.remove(key); + self.extensible_predicates.remove(key) } _ => match compilation_target { CompilationTarget::User => { - self.extensible_predicates.remove(key); + 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); + module.extensible_predicates.remove(key) + } else { + None } } }, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 38ecd285..8360b3fe 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -412,9 +412,15 @@ impl Machine { fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) { match code_ptr { + REPLCodePtr::AddDiscontiguousPredicate => { + self.add_discontiguous_predicate(); + } REPLCodePtr::AddDynamicPredicate => { self.add_dynamic_predicate(); } + REPLCodePtr::AddMultifilePredicate => { + self.add_multifile_predicate(); + } REPLCodePtr::AddGoalExpansionClause => { self.add_goal_expansion_clause(); } diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 6e055134..bbc99c22 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -394,9 +394,6 @@ fn merge_clauses(tls: &mut VecDeque) -> Result { return Ok(tl); } - TopLevel::Declaration(_) if clauses.is_empty() => { - return Ok(tl); - } TopLevel::Query(_) => { return Err(CompilationError::InconsistentEntry); } @@ -409,10 +406,6 @@ fn merge_clauses(tls: &mut VecDeque) -> Result clauses.extend(predicate.into_iter()), - _ => { - tls.push_front(tl); - break; - } } } @@ -497,7 +490,7 @@ fn check_for_internal_if_then(terms: &mut Vec) { } } -fn setup_declaration<'a>( +pub(super) fn setup_declaration<'a>( load_state: &LoadState<'a>, mut terms: Vec>, ) -> Result { @@ -883,8 +876,6 @@ impl Preprocessor { 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)?)) diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index 21a30e29..6a23ff66 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -2,7 +2,6 @@ use prolog_parser::ast::*; use prolog_parser::parser::*; use crate::machine::machine_errors::CompilationError; -use crate::machine::preprocessor::*; use crate::machine::*; use indexmap::IndexSet; @@ -100,7 +99,6 @@ pub struct LoadStatePayload { pub(super) retraction_info: RetractionInfo, pub(super) module_op_exports: Vec<(OpDecl, Option<(usize, Specifier)>)>, pub(super) non_counted_bt_preds: IndexSet, - pub(super) preprocessor: Preprocessor, pub(super) predicates: PredicateQueue, pub(super) clause_clauses: Vec<(Term, Term)>, } @@ -119,7 +117,6 @@ impl LoadStatePayload { 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: predicate_queue![], clause_clauses: vec![], } diff --git a/src/write.rs b/src/write.rs index dacf0ed9..95e9160c 100644 --- a/src/write.rs +++ b/src/write.rs @@ -2,6 +2,7 @@ use crate::clause_types::*; use crate::forms::*; use crate::indexing::IndexingCodePtr; use crate::instructions::*; +use crate::machine::loader::CompilationTarget; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; @@ -20,8 +21,12 @@ impl fmt::Display for LocalCodePtr { impl fmt::Display for REPLCodePtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + REPLCodePtr::AddDiscontiguousPredicate => + write!(f, "REPLCodePtr::AddDiscontiguousPredicate"), REPLCodePtr::AddDynamicPredicate => write!(f, "REPLCodePtr::AddDynamicPredicate"), + REPLCodePtr::AddMultifilePredicate => + write!(f, "REPLCodePtr::AddMultifilePredicate"), REPLCodePtr::AddGoalExpansionClause => write!(f, "REPLCodePtr::AddGoalExpansionClause"), REPLCodePtr::AddTermExpansionClause => @@ -88,6 +93,15 @@ impl fmt::Display for IndexPtr { } } +impl fmt::Display for CompilationTarget { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + CompilationTarget::User => write!(f, "user"), + CompilationTarget::Module(ref module_name) => write!(f, "{}", module_name), + } + } +} + impl fmt::Display for FactInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -404,6 +418,10 @@ impl fmt::Display for SessionError { write!(f, "modules ({}, in this case) cannot import themselves.", module_name) } + &SessionError::PredicateNotMultifileOrDiscontiguous(ref compilation_target, ref key) => { + write!(f, "module {} does not define {}/{} as multifile or discontiguous.", + compilation_target.module_name(), key.0, key.1) + } } } } From e9ba3ad22337a5defa140a3bf10d80c285802cc1 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 01:15:29 -0700 Subject: [PATCH 078/137] handle user:goal_expansion, but not Target:goal_expansion, explicitly in loader.pl --- src/loader.pl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index 548d0e46..c34c57f4 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -231,15 +231,15 @@ compile_dispatch(user: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). + prolog_load_context(module, user), + '$add_goal_expansion_clause'(user, 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). + prolog_load_context(module, user), + '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs). +compile_dispatch(user:goal_expansion(Term, Terms), Evacuable, VNs) :- + '$add_goal_expansion_clause'(user, goal_expansion(Term, Terms), Evacuable, VNs). +compile_dispatch((user:goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :- + '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs). compile_declaration(use_module(Module), Evacuable) :- From 00bf39204d18b44b844169abe39a7f83a0dd0e12 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 11:12:19 -0700 Subject: [PATCH 079/137] add missing variable checks in various places --- src/lib/builtins.pl | 3 ++- src/loader.pl | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 1396179b..c5a9d39a 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -261,7 +261,8 @@ call_or_cut(M:G, B) :- ; call(M:G) ). call_or_cut(G, B) :- - ( '$call_with_default_policy'(control_functor(G)) -> + ( nonvar(G), + '$call_with_default_policy'(control_functor(G)) -> '$call_with_default_policy'(call_or_cut_interp(G, B)) ; call(G) ). diff --git a/src/loader.pl b/src/loader.pl index c34c57f4..20da327c 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -440,7 +440,8 @@ predicate_property(Callable, Property) :- ; functor(Callable, (:), 2), arg(1, Callable, Module), arg(2, Callable, Callable0), - atom(Module) -> + atom(Module), + nonvar(Callable0) -> functor(Callable0, Name, Arity), ( atom(Name), Name \== [] -> From f9b98f97b6dd9493a0db7702f3e7e4f2c376363f Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 11:56:58 -0700 Subject: [PATCH 080/137] remove unnecessary cause of failure in parser, qualify call to op_/3 in builtins.pl --- crates/prolog_parser/src/parser.rs | 4 ---- src/lib/builtins.pl | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index f3655232..a623f9f4 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -469,10 +469,6 @@ impl<'a, R: Read> Parser<'a, R> { return false; } } - - if arity >= 2 && is_prefix!(self.stack[idx].spec) && self.stack[idx].priority > 0 { - return false; - } } else { return false; } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index c5a9d39a..975a07c1 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -1170,7 +1170,7 @@ op(Priority, OpSpec, Op) :- ; 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(builtins:op_(Priority, OpSpec), Op), ! ; throw(error(type_error(list, Op), op/3)) % 8.14.3.3 f) ). From 7670b81633b4ca1fa5b2cfa3280bcd5e354557ff Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 13:31:58 -0700 Subject: [PATCH 081/137] remove VNs variable from loader.pl --- src/clause_types.rs | 4 ++-- src/loader.pl | 52 ++++++++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 660a74a8..b678bb7f 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -597,10 +597,10 @@ impl SystemClauseType { ("$add_discontiguous_predicate", 4) => { Some(SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate)) } - ("$add_goal_expansion_clause", 4) => { + ("$add_goal_expansion_clause", 3) => { Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause)) } - ("$add_term_expansion_clause", 3) => { + ("$add_term_expansion_clause", 2) => { Some(SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause)) } ("$atom_chars", 2) => Some(SystemClauseType::AtomChars), diff --git a/src/loader.pl b/src/loader.pl index 20da327c..4607bdbd 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -111,7 +111,7 @@ load(Stream) :- load(_). load_loop(Stream, Evacuable) :- - read_term(Stream, Term, [variable_names(VNs), singletons(Singletons)]), + read_term(Stream, Term, [singletons(Singletons)]), ( Term == end_of_file -> close(Stream), '$conclude_load'(Evacuable) @@ -122,8 +122,8 @@ load_loop(Stream, Evacuable) :- ( var(Terms) -> instantiation_error(load/1) ; Terms = [_|_] -> - compile_dispatch_or_clause_on_list(Terms, Evacuable, VNs) - ; compile_dispatch_or_clause(Terms, Evacuable, VNs) + compile_dispatch_or_clause_on_list(Terms, Evacuable) + ; compile_dispatch_or_clause(Terms, Evacuable) ), load_loop(Stream, Evacuable) ). @@ -202,44 +202,44 @@ expand_terms_and_goals(Term, Terms) :- ). -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_on_list([], Evacuable). +compile_dispatch_or_clause_on_list([Term | Terms], Evacuable) :- + compile_dispatch_or_clause(Term, Evacuable), + compile_dispatch_or_clause_on_list(Terms, Evacuable). -compile_dispatch_or_clause(Term, Evacuable, VNs) :- +compile_dispatch_or_clause(Term, Evacuable) :- ( var(Term) -> instantiation_error(load/1) - ; compile_dispatch(Term, Evacuable, VNs) -> + ; compile_dispatch(Term, Evacuable) -> true ; compile_clause(Term, Evacuable) ). -compile_dispatch((:- Declaration), Evacuable, _VNs) :- +compile_dispatch((:- Declaration), Evacuable) :- ( 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) :- +compile_dispatch(term_expansion(Term, Terms), Evacuable) :- + '$add_term_expansion_clause'(term_expansion(Term, Terms), Evacuable). +compile_dispatch((term_expansion(Term, Terms) :- Body), Evacuable) :- + '$add_term_expansion_clause'((term_expansion(Term, Terms) :- Body), Evacuable). +compile_dispatch(user:term_expansion(Term, Terms), Evacuable) :- + '$add_term_expansion_clause'(term_expansion(Term, Terms), Evacuable). +compile_dispatch((user:term_expansion(Term, Terms) :- Body), Evacuable) :- + '$add_term_expansion_clause'((term_expansion(Term, Terms) :- Body), Evacuable). +compile_dispatch(goal_expansion(Term, Terms), Evacuable) :- prolog_load_context(module, user), - '$add_goal_expansion_clause'(user, goal_expansion(Term, Terms), Evacuable, VNs). -compile_dispatch((goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :- + '$add_goal_expansion_clause'(user, goal_expansion(Term, Terms), Evacuable). +compile_dispatch((goal_expansion(Term, Terms) :- Body), Evacuable) :- prolog_load_context(module, user), - '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs). -compile_dispatch(user:goal_expansion(Term, Terms), Evacuable, VNs) :- - '$add_goal_expansion_clause'(user, goal_expansion(Term, Terms), Evacuable, VNs). -compile_dispatch((user:goal_expansion(Term, Terms) :- Body), Evacuable, VNs) :- - '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable, VNs). + '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable). +compile_dispatch(user:goal_expansion(Term, Terms), Evacuable) :- + '$add_goal_expansion_clause'(user, goal_expansion(Term, Terms), Evacuable). +compile_dispatch((user:goal_expansion(Term, Terms) :- Body), Evacuable) :- + '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable). compile_declaration(use_module(Module), Evacuable) :- From 396c589743bb51dfc79b916eaefd3aa4e03b8298 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 15:39:52 -0700 Subject: [PATCH 082/137] add second term expansion to capture the addition of hook predicates to the expansion process in loader.pl, loader.rs --- src/clause_types.rs | 13 +++++++- src/forms.rs | 12 ++++++++ src/loader.pl | 55 ++++++++++++++++++++++++++-------- src/machine/loader.rs | 42 ++++++++++++++++++++++++++ src/machine/machine_indices.rs | 2 ++ src/machine/mod.rs | 6 ++++ src/write.rs | 4 +++ 7 files changed, 120 insertions(+), 14 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index b678bb7f..c9cb0332 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -413,6 +413,12 @@ impl SystemClauseType { clause_name!("$cpp_discontiguous_property") } &SystemClauseType::REPL(REPLCodePtr::AbolishClause) => clause_name!("$abolish_clause"), + &SystemClauseType::REPL(REPLCodePtr::IsConsistentWithTermQueue) => { + clause_name!("$is_consistent_with_term_queue") + } + &SystemClauseType::REPL(REPLCodePtr::FlushTermQueue) => { + clause_name!("$flush_term_queue") + } &SystemClauseType::Close => clause_name!("$close"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), @@ -606,7 +612,6 @@ impl SystemClauseType { ("$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), ("$bind_from_register", 2) => Some(SystemClauseType::BindFromRegister), ("$call_continuation", 1) => Some(SystemClauseType::CallContinuation), ("$char_code", 2) => Some(SystemClauseType::CharCode), @@ -761,6 +766,12 @@ impl SystemClauseType { ("$asserta", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Asserta)), ("$assertz", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Assertz)), ("$retract_clause", 4) => Some(SystemClauseType::REPL(REPLCodePtr::Retract)), + ("$is_consistent_with_term_queue", 4) => { + Some(SystemClauseType::REPL(REPLCodePtr::IsConsistentWithTermQueue)) + } + ("$flush_term_queue", 1) => { + Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)) + } ("$variant", 2) => Some(SystemClauseType::Variant), ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions), ("$write_term", 7) => Some(SystemClauseType::WriteTerm), diff --git a/src/forms.rs b/src/forms.rs index ad401cd4..9956c058 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -125,6 +125,18 @@ pub trait ClauseInfo { fn arity(&self) -> usize; } +impl ClauseInfo for PredicateKey { + #[inline] + fn name(&self) -> Option { + Some(self.0.clone()) + } + + #[inline] + fn arity(&self) -> usize { + self.1 + } +} + impl ClauseInfo for Term { fn name(&self) -> Option { match self { diff --git a/src/loader.pl b/src/loader.pl index 4607bdbd..e1868a2c 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -117,18 +117,22 @@ load_loop(Stream, Evacuable) :- '$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) - ; compile_dispatch_or_clause(Terms, Evacuable) - ), + ; compile_term(Term, Evacuable), load_loop(Stream, Evacuable) ). +compile_term(Term, Evacuable) :- + expand_terms_and_goals(Term, Terms), + !, + ( var(Terms) -> + instantiation_error(load/1) + ; Terms = [_|_] -> + compile_dispatch_or_clause_on_list(Terms, Evacuable) + ; compile_dispatch_or_clause(Terms, Evacuable) + ). + + inner_meta_specs(0, HeadArg, InnerHeadArgs, InnerMetaSpecs) :- !, predicate_property(HeadArg, meta_predicate(InnerMetaSpecs)), @@ -296,12 +300,37 @@ compile_declaration(initialization(Goal), Evacuable) :- compile_clause((Target:Head :- Body), Evacuable) :- !, - '$scoped_clause_to_evacuable'(Target, (Head :- Body), Evacuable). -compile_clause(Target:Clause, Evacuable) :- + functor(Head, Name, Arity), + ( '$is_consistent_with_term_queue'(Target, Name, Arity, Evacuable) -> + '$scoped_clause_to_evacuable'(Target, (Head :- Body), Evacuable) + ; '$flush_term_queue'(Evacuable), + compile_term((Target:Head :- Body), Evacuable) + ). +compile_clause(Target:Head, Evacuable) :- !, - '$scoped_clause_to_evacuable'(Target, Clause, Evacuable). -compile_clause(Clause, Evacuable) :- - '$clause_to_evacuable'(Clause, Evacuable). + functor(Head, Name, Arity), + ( '$is_consistent_with_term_queue'(Target, Name, Arity, Evacuable) -> + '$scoped_clause_to_evacuable'(Target, Head, Evacuable) + ; '$flush_term_queue'(Evacuable), + compile_term(Target:Head, Evacuable) + ). +compile_clause((Head :- Body), Evacuable) :- + !, + prolog_load_context(module, Target), + functor(Head, Name, Arity), + ( '$is_consistent_with_term_queue'(Target, Name, Arity, Evacuable) -> + '$clause_to_evacuable'((Head :- Body), Evacuable) + ; '$flush_term_queue'(Evacuable), + compile_term((Head :- Body), Evacuable) + ). +compile_clause(Head, Evacuable) :- + prolog_load_context(module, Target), + functor(Head, Name, Arity), + ( '$is_consistent_with_term_queue'(Target, Name, Arity, Evacuable) -> + '$clause_to_evacuable'(Head, Evacuable) + ; '$flush_term_queue'(Evacuable), + compile_term(Head, Evacuable) + ). prolog_load_context(source, Source) :- diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 3ece45ba..08593238 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1882,6 +1882,48 @@ impl Machine { } } + pub(crate) fn is_consistent_with_term_queue(&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 key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]); + + let compilation_target = match module_name.as_str() { + "user" => CompilationTarget::User, + _ => CompilationTarget::Module(module_name), + }; + + let (loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(4)); + + loader.load_state.wam.machine_st.fail = + (!loader.predicates.is_empty() && + loader.predicates.compilation_target != compilation_target) || + !key.is_consistent(&loader.predicates); + + let result = LiveTermStream::evacuate(loader); + self.restore_load_state_payload(result, evacuable_h); + } + + pub(crate) fn flush_term_queue(&mut self) { + let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(1)); + + let flush_term_queue = || { + if !loader.predicates.is_empty() { + loader.compile_and_submit()?; + } + + LiveTermStream::evacuate(loader) + }; + + let result = flush_term_queue(); + self.restore_load_state_payload(result, evacuable_h); + } + pub(crate) fn meta_predicate_property(&mut self) { let module_name = atom_from!( self.machine_st, diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 2d0556d3..049cd5a0 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -446,6 +446,8 @@ pub enum REPLCodePtr { Asserta, Assertz, Retract, + IsConsistentWithTermQueue, + FlushTermQueue, } #[derive(Debug, Clone, PartialEq)] diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 8360b3fe..b0613b74 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -499,6 +499,12 @@ impl Machine { REPLCodePtr::AbolishClause => { self.abolish_clause(); } + REPLCodePtr::IsConsistentWithTermQueue => { + self.is_consistent_with_term_queue(); + } + REPLCodePtr::FlushTermQueue => { + self.flush_term_queue(); + } } self.machine_st.p = CodePtr::Local(p); diff --git a/src/write.rs b/src/write.rs index 95e9160c..49541f0b 100644 --- a/src/write.rs +++ b/src/write.rs @@ -79,6 +79,10 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::MultifileProperty"), REPLCodePtr::DiscontiguousProperty => write!(f, "REPLCodePtr::DiscontiguousProperty"), + REPLCodePtr::IsConsistentWithTermQueue => + write!(f, "REPLCodePtr::IsConsistentWithTermQueue"), + REPLCodePtr::FlushTermQueue => + write!(f, "REPLCodePtr::FlushTermQueue"), } } } From 2a70ca375c235cfed4a56ed7dfd459a1ff6bfde0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 16:18:49 -0700 Subject: [PATCH 083/137] restore support for tabling and delimited continuations (#779) --- src/forms.rs | 4 ++-- src/lib/atts.pl | 2 +- src/lib/cont.pl | 4 +++- src/lib/tabling.pl | 5 ++++- src/lib/tabling/batched_worklist.pl | 2 ++ src/lib/tabling/global_worklist.pl | 2 ++ src/lib/tabling/table_data_structure.pl | 2 ++ src/lib/tabling/table_link_manager.pl | 2 ++ src/lib/tabling/trie.pl | 2 ++ src/lib/tabling/wrapper.pl | 2 ++ src/machine/compile.rs | 2 +- 11 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/forms.rs b/src/forms.rs index 9956c058..3f0bd288 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -673,7 +673,7 @@ impl PredicateInfo { #[inline] pub fn must_retract_local_clauses(&self) -> bool { - self.is_extensible && !self.is_discontiguous + self.is_extensible && self.has_clauses && !self.is_discontiguous } } @@ -707,7 +707,7 @@ impl PredicateSkeleton { is_discontiguous: self.is_discontiguous, is_dynamic: self.is_dynamic, is_multifile: self.is_multifile, - has_clauses: !self.clauses.is_empty(), + has_clauses: !self.clause_clause_locs.is_empty(), } } diff --git a/src/lib/atts.pl b/src/lib/atts.pl index fcd5b2c1..afdebd71 100644 --- a/src/lib/atts.pl +++ b/src/lib/atts.pl @@ -108,7 +108,7 @@ get_attrs_var_check --> put_attrs(Name/Arity, Module) --> put_attr(Name, Arity, Module), - [(put_atts(Var, Attr) :- lists:maplist(put_atts(Var), Attr), !)]. + [(put_atts(Var, Attr) :- lists:maplist(Module:put_atts(Var), Attr), !)]. put_attrs((Name/Arity, Atts), Module) --> { nonvar(Atts) }, put_attr(Name, Arity, Module), diff --git a/src/lib/cont.pl b/src/lib/cont.pl index 8dccdc5e..a5125d96 100644 --- a/src/lib/cont.pl +++ b/src/lib/cont.pl @@ -1,5 +1,7 @@ :- module(cont, [reset/3, shift/1]). +:- meta_predicate reset(0, ?, ?). + reset(Goal, Ball, Cont) :- call(Goal), '$reset_cont_marker', @@ -11,7 +13,7 @@ shift(Ball) :- get_chunks(E, P, L), ( L == [] -> Cont = cont(true) - ; Cont = cont(call_continuation(L)) + ; Cont = cont(cont:call_continuation(L)) ), '$write_cont_and_term'(_, _, Cont, Ball), '$unwind_environments'. diff --git a/src/lib/tabling.pl b/src/lib/tabling.pl index 703da8e3..2163c791 100644 --- a/src/lib/tabling.pl +++ b/src/lib/tabling.pl @@ -11,9 +11,9 @@ :- use_module(library(tabling/double_linked_list)). :- use_module(library(tabling/table_data_structure)). :- use_module(library(tabling/batched_worklist)). -:- use_module(library(tabling/wrapper)). :- use_module(library(tabling/global_worklist)). :- use_module(library(tabling/table_link_manager)). +:- use_module(library(tabling/wrapper)). :- use_module(library(cont)). :- use_module(library(lists)). @@ -66,6 +66,9 @@ table_and_status_for_variant(V,T,S) :- table_for_variant(V,T), tbd_table_status(T,S). + +:- meta_predicate start_tabling(?, 0). + start_tabling(Wrapper,Worker) :- put_new_trie_table_link, put_new_global_worklist, diff --git a/src/lib/tabling/batched_worklist.pl b/src/lib/tabling/batched_worklist.pl index 99f0619b..8a8b4117 100644 --- a/src/lib/tabling/batched_worklist.pl +++ b/src/lib/tabling/batched_worklist.pl @@ -53,6 +53,8 @@ :- attribute executing_all_work/1, worklist_presence/1, wkl_answer_cluster/1, wkl_suspension_cluster/1, wkl_answer_cluster_pointer_flag/1. +verify_attributes(_, _, []). + /** Tabling Worklist management A batched worklist: a worklist that clusters suspensions and answers as diff --git a/src/lib/tabling/global_worklist.pl b/src/lib/tabling/global_worklist.pl index 19502a92..55c437f1 100644 --- a/src/lib/tabling/global_worklist.pl +++ b/src/lib/tabling/global_worklist.pl @@ -13,6 +13,8 @@ :- attribute table_global_worklist/1. +verify_attributes(_, _, []). + put_new_global_worklist :- ( bb_get(table_global_worklist_initialized, _) -> true diff --git a/src/lib/tabling/table_data_structure.pl b/src/lib/tabling/table_data_structure.pl index 0ce989da..69a057e6 100644 --- a/src/lib/tabling/table_data_structure.pl +++ b/src/lib/tabling/table_data_structure.pl @@ -61,6 +61,8 @@ :- attribute table_status/1, newly_created_table_identifiers/1. +verify_attributes(_, _, []). + % This file defines the table datastructure. % % The table datastructure contains the following sub-structures: diff --git a/src/lib/tabling/table_link_manager.pl b/src/lib/tabling/table_link_manager.pl index ec88f105..c346ea10 100644 --- a/src/lib/tabling/table_link_manager.pl +++ b/src/lib/tabling/table_link_manager.pl @@ -51,6 +51,8 @@ :- attribute trie_table_link/1. +verify_attributes(_, _, []). + % This file defines a call pattern trie. % % This data structure keeps the relation between a variant and the diff --git a/src/lib/tabling/trie.pl b/src/lib/tabling/trie.pl index 2e545524..cd855b92 100644 --- a/src/lib/tabling/trie.pl +++ b/src/lib/tabling/trie.pl @@ -47,6 +47,8 @@ :- attribute maybe_just/1, children/1. +verify_attributes(_, _, []). + % Implementation of a prefix tree, a.k.a. trie % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/lib/tabling/wrapper.pl b/src/lib/tabling/wrapper.pl index 4c902e84..d2d13901 100644 --- a/src/lib/tabling/wrapper.pl +++ b/src/lib/tabling/wrapper.pl @@ -40,6 +40,8 @@ :- use_module(library(dcgs)). :- use_module(library(error)). +:- multifile(tabled/2). + %%:- multifile %% system:term_expansion/2, %% tabled/2. diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 3c7f9eb8..9364d176 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1754,7 +1754,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { .map(|skeleton| skeleton.predicate_info()) .unwrap_or_default(); - if predicate_info.must_retract_local_clauses() { + if local_predicate_info.must_retract_local_clauses() { self.retract_local_clauses(&key, predicate_info.is_dynamic); } From f5ad845d57ff6a5d180be35d9fc5f6b766e03e53 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 17 Feb 2021 18:49:51 -0700 Subject: [PATCH 084/137] try to canonicalize to absolute path in current_dir(), use it in setting LoadContext directories (#821) --- src/machine/loader.rs | 2 -- src/machine/mod.rs | 17 +++++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 08593238..2347fcfe 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1606,8 +1606,6 @@ impl Machine { pub(crate) fn load_context_directory(&mut self) { if let Some(load_context) = self.load_contexts.last() { if let Some(directory) = load_context.path.parent() { - // canonicalize returns the absolute path of the directory. - let directory = directory.canonicalize().unwrap(); let directory_str = directory.to_str().unwrap(); let directory_atom = diff --git a/src/machine/mod.rs b/src/machine/mod.rs index b0613b74..163c82a0 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -90,8 +90,16 @@ pub(super) struct LoadContext { impl LoadContext { #[inline] fn new(path: &str, stream: Stream) -> Self { + let mut path_buf = PathBuf::from(path); + + if path_buf.is_relative() { + let mut current_dir = current_dir(); + current_dir.push(path_buf); + path_buf = current_dir; + } + LoadContext { - path: PathBuf::from(path), + path: path_buf, stream, module: clause_name!("user"), } @@ -111,11 +119,8 @@ pub struct Machine { } #[inline] -fn current_dir() -> std::path::PathBuf { - let mut path_buf = std::path::PathBuf::from(file!()); - - path_buf.pop(); - path_buf +fn current_dir() -> PathBuf { + PathBuf::from("./").canonicalize().unwrap_or(PathBuf::from("./")) } include!(concat!(env!("OUT_DIR"), "/libraries.rs")); From 71a524662dbd822db2347dd03ad9522113f11d85 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 18 Feb 2021 19:16:11 +0100 Subject: [PATCH 085/137] add appropriate meta_predicate/1 declarations --- src/lib/debug.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/debug.pl b/src/lib/debug.pl index bc9f9df8..ab84f15b 100644 --- a/src/lib/debug.pl +++ b/src/lib/debug.pl @@ -11,6 +11,10 @@ :- use_module(library(format), [portray_clause/1]). +:- meta_predicate *(0). +:- meta_predicate $(0). +:- meta_predicate $-(0). + $-(G_0) :- catch(G_0, Ex, ( portray_clause(exception:Ex:G_0), throw(Ex) ) ). From 5bec2c87cbac049f8584e3a88fcfda986fbca212 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 18 Feb 2021 20:12:15 +0100 Subject: [PATCH 086/137] add appropriate meta_predicate/1 declarations --- src/lib/freeze.pl | 2 ++ src/lib/pio.pl | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/lib/freeze.pl b/src/lib/freeze.pl index 8ab1de9b..c005672f 100644 --- a/src/lib/freeze.pl +++ b/src/lib/freeze.pl @@ -3,6 +3,8 @@ :- use_module(library(atts)). :- use_module(library(dcgs)). +:- meta_predicate freeze(?, 0). + :- attribute frozen/1. verify_attributes(Var, Other, Goals) :- diff --git a/src/lib/pio.pl b/src/lib/pio.pl index 89dfc566..1df9a796 100644 --- a/src/lib/pio.pl +++ b/src/lib/pio.pl @@ -7,6 +7,9 @@ :- use_module(library(iso_ext), [setup_call_cleanup/3, partial_string/3]). :- use_module(library(lists), [member/2]). +:- meta_predicate phrase_from_file(2, ?). +:- meta_predicate phrase_from_file(2, ?, ?). + phrase_from_file(NT, File) :- phrase_from_file(NT, File, []). From b3db8913c6587fd93ac41dffd00ce82bb6ab9d56 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 18 Feb 2021 20:19:23 +0100 Subject: [PATCH 087/137] enable meta_predicate/1 declarations --- src/lib/assoc.pl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lib/assoc.pl b/src/lib/assoc.pl index 2ebf1a8e..79e174e6 100644 --- a/src/lib/assoc.pl +++ b/src/lib/assoc.pl @@ -63,11 +63,8 @@ Assocs are Key-Value associations implemented as a balanced binary tree @author R.A.O'Keefe, L.Damas, V.S.Costa and Jan Wielemaker */ -/* -:- meta_predicate - map_assoc(1, ?), - map_assoc(2, ?, ?). -*/ +:- meta_predicate map_assoc(1, ?). +:- meta_predicate map_assoc(2, ?, ?). %! empty_assoc(?Assoc) is semidet. % From d69b7f41f210fd7544eee9ff6ea0ae7c922ebf2a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 18 Feb 2021 14:07:57 -0700 Subject: [PATCH 088/137] add '$remove_module_exports' to loader.rs --- src/clause_types.rs | 6 +++ src/loader.pl | 27 ++++++++--- src/machine/load_state.rs | 89 ++++++++++++++++++++++++++++++++++ src/machine/loader.rs | 18 +++++++ src/machine/machine_indices.rs | 1 + src/machine/mod.rs | 3 ++ src/write.rs | 2 + 7 files changed, 138 insertions(+), 8 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index c9cb0332..dc619a91 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -419,6 +419,9 @@ impl SystemClauseType { &SystemClauseType::REPL(REPLCodePtr::FlushTermQueue) => { clause_name!("$flush_term_queue") } + &SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports) => { + clause_name!("$remove_module_exports") + } &SystemClauseType::Close => clause_name!("$close"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), @@ -772,6 +775,9 @@ impl SystemClauseType { ("$flush_term_queue", 1) => { Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)) } + ("$remove_module_exports", 2) => { + Some(SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports)) + } ("$variant", 2) => Some(SystemClauseType::Variant), ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions), ("$write_term", 7) => Some(SystemClauseType::WriteTerm), diff --git a/src/loader.pl b/src/loader.pl index e1868a2c..95e0a052 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -246,19 +246,30 @@ compile_dispatch((user:goal_expansion(Term, Terms) :- Body), Evacuable) :- '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable). +remove_module(Module, Evacuable) :- + ( nonvar(Module), + Module = library(ModuleName), + atom(ModuleName), + atom \== [] -> + '$remove_module_exports'(ModuleName, Evacuable) + ; atom(Module), + atom \== [] -> + '$remove_module_exports'(Module, Evacuable) + ; domain_error(module_specifier, Module, use_module/2) + ). + + 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) + remove_module(Module, Evacuable) + ; use_module(Module, Exports, Evacuable) ). compile_declaration(module(Module, Exports), Evacuable) :- - ( atom(Module) -> - '$declare_module'(Module, Exports, Evacuable) - ; - type_error(atom, Module, load/1) + ( atom(Module) -> + '$declare_module'(Module, Exports, Evacuable) + ; type_error(atom, Module, load/1) ). compile_declaration(dynamic(Name/Arity), Evacuable) :- !, @@ -375,7 +386,7 @@ use_module(Module) :- use_module(Module, Exports) :- '$push_load_state_payload'(Evacuable), ( Exports == [] -> - '$remove_module_exports'(Module, Evacuable) + remove_module(Module, Evacuable) ; use_module(Module, Exports, Evacuable) ). diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index c0e22473..41f39248 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -459,6 +459,94 @@ impl<'a> LoadState<'a> { } } + pub(super) fn remove_module_exports(&mut self, module_name: ClauseName) { + let removed_module = match self.wam.indices.modules.remove(&module_name) { + Some(module) => module, + None => return, + }; + + fn remove_module_exports( + removed_module: &Module, + code_dir: &mut CodeDir, + op_dir: &mut OpDir, + retraction_info: &mut RetractionInfo, + predicate_retractor: impl Fn(PredicateKey, IndexPtr) -> RetractionRecord, + op_retractor: impl Fn(OpDecl, usize, Specifier) -> RetractionRecord, + ) { + for export in removed_module.module_decl.exports.iter() { + match export { + ModuleExport::PredicateKey(ref key) => { + match (removed_module.code_dir.get(key), code_dir.get(key)) { + (Some(module_code_index), Some(target_code_index)) + if module_code_index.get() == target_code_index.get() => { + let old_index_ptr = target_code_index.replace(IndexPtr::Undefined); + + retraction_info.push_record( + predicate_retractor(key.clone(), old_index_ptr), + ); + } + _ => {} + } + } + ModuleExport::OpDecl(op_decl) => { + let op_dir_value_opt = op_dir.remove(&(op_decl.name.clone(), op_decl.fixity())); + + if let Some(op_dir_value) = op_dir_value_opt { + let (prec, spec) = op_dir_value.shared_op_desc().get(); + + retraction_info.push_record( + op_retractor(op_decl.clone(), prec, spec), + ); + } + } + } + } + } + + match &self.compilation_target { + CompilationTarget::User => { + remove_module_exports( + &removed_module, + &mut self.wam.indices.code_dir, + &mut self.wam.indices.op_dir, + &mut self.retraction_info, + RetractionRecord::ReplacedUserPredicate, + RetractionRecord::ReplacedUserOp, + ); + } + CompilationTarget::Module(ref target_module_name) + if target_module_name.as_str() != module_name.as_str() => { + let predicate_retractor = |key, index_ptr| { + RetractionRecord::ReplacedModulePredicate( + module_name.clone(), key, index_ptr, + ) + }; + + let op_retractor = |op_decl, prec, spec| { + RetractionRecord::ReplacedModuleOp( + module_name.clone(), op_decl, prec, spec, + ) + }; + + if let Some(module) = self.wam.indices.modules.get_mut(target_module_name) { + remove_module_exports( + &removed_module, + &mut module.code_dir, + &mut module.op_dir, + &mut self.retraction_info, + predicate_retractor, + op_retractor, + ); + } else { + unreachable!() + } + } + CompilationTarget::Module(_) => {}, + }; + + self.wam.indices.modules.insert(module_name, removed_module); + } + fn get_or_insert_local_code_index( &mut self, module_name: ClauseName, @@ -787,6 +875,7 @@ impl<'a> LoadState<'a> { pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) { let module_name = module_decl.name.clone(); + self.remove_module_exports(module_name.clone()); match self.wam.indices.modules.get_mut(&module_name) { Some(module) => { diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 2347fcfe..38797ba8 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1922,6 +1922,24 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } + pub(crate) fn remove_module_exports(&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 (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2)); + + let remove_module_exports = || { + loader.load_state.remove_module_exports(module_name); + LiveTermStream::evacuate(loader) + }; + + let result = remove_module_exports(); + self.restore_load_state_payload(result, evacuable_h); + } + pub(crate) fn meta_predicate_property(&mut self) { let module_name = atom_from!( self.machine_st, diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 049cd5a0..43264a3f 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -448,6 +448,7 @@ pub enum REPLCodePtr { Retract, IsConsistentWithTermQueue, FlushTermQueue, + RemoveModuleExports, } #[derive(Debug, Clone, PartialEq)] diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 163c82a0..384e0daf 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -510,6 +510,9 @@ impl Machine { REPLCodePtr::FlushTermQueue => { self.flush_term_queue(); } + REPLCodePtr::RemoveModuleExports => { + self.remove_module_exports(); + } } self.machine_st.p = CodePtr::Local(p); diff --git a/src/write.rs b/src/write.rs index 49541f0b..52263c2f 100644 --- a/src/write.rs +++ b/src/write.rs @@ -83,6 +83,8 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::IsConsistentWithTermQueue"), REPLCodePtr::FlushTermQueue => write!(f, "REPLCodePtr::FlushTermQueue"), + REPLCodePtr::RemoveModuleExports => + write!(f, "REPLCodePtr::RemoveModuleExports"), } } } From c272e4d1e84ead303d7a3a93ecae6ea3c1c8af6d Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 18 Feb 2021 14:15:28 -0700 Subject: [PATCH 089/137] use add_dynamically_generated_module in get_or_insert_local_code_index --- src/machine/load_state.rs | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 41f39248..0a2fca5a 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -559,25 +559,20 @@ impl<'a> LoadState<'a> { .or_insert_with(|| CodeIndex::new(IndexPtr::Undefined)) .clone(), None => { - let mut module = Module::new( - ModuleDecl { - name: module_name.clone(), - exports: vec![], - }, - ListingSource::DynamicallyGenerated, - ); + self.add_dynamically_generated_module(&module_name); - 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 + 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 => { + unreachable!() + } + } } } } From 77ec8ebfc36b70cf5c1278d72a09e4a035145242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Thu, 18 Feb 2021 22:16:24 +0100 Subject: [PATCH 090/137] UUIDv4 generation --- README.md | 1 + src/lib/uuid.pl | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/lib/uuid.pl diff --git a/README.md b/README.md index 985ae4a0..2c86d620 100644 --- a/README.md +++ b/README.md @@ -519,6 +519,7 @@ The modules that ship with Scryer Prolog are also called public key signatures and signature verification with Ed25519, ECDH key exchange over Curve25519 (X25519), authenticated symmetric encryption with ChaCha20-Poly1305, and reasoning about elliptic curves. +* [`uuid`](src/lib/uuid.pl) UUIDv4 generation and hex representation To use predicates provided by the `lists` library, write: diff --git a/src/lib/uuid.pl b/src/lib/uuid.pl new file mode 100644 index 00000000..affa3b68 --- /dev/null +++ b/src/lib/uuid.pl @@ -0,0 +1,107 @@ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Written in February 2021 by Adrián Arroyo (adrian.arroyocalle@gmail.com) + Part of Scryer-Prolog + This library provides reasoning about UUID (only version 4 right now). + There are three predicates: + * uuidv4/1, to generate a new UUIDv4 + * uuidv4_string/1, to generate a new UUIDv4 in string hex representation + * uuid_string/2, to converte between UUID list of bytes and UUID hex representation + + Examples: + ?- uuidv4(X). + X = [42,147,248,242,117,196,79,2,129,159|...]. + ?- uuidv4_string(X). + X = "428499fc-76e3-4240- ...". + ?- uuidv4(X), uuid_string(X, S). + X = [173,12,244,152,139,118,64,139,137,4|...], S = "ad0cf498-8b76-408b- ...". + ?- uuid_string(X, "61ae692e-eaf6-4199-8dd3-9f01db70a20b"). + X = [97,174,105,46,234,246,65,153,141,211|...]. + + I place this code in the public domain. Use it in any way you want. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +:- module(uuid, [ + uuidv4/1, + uuidv4_string/1, + uuid_string/2 +]). + +:- use_module(library(crypto)). +:- use_module(library(dcgs)). +:- use_module(library(lists)). + +/* +An UUID is made of 16 bytes, composed of 5 sections: +time_low - 4 +time_mid - 2 +time_hi_and_version - 2 +clock_seq_hi_and_res_clock_seq_low - 2 +node - 6 +UUID v4 can be generated from a set of 16 random bytes: https://www.rfc-archive.org/getrfc.php?rfc=4122#gsc.tab=0 (section 4.4) +*/ +uuidv4(Uuid) :- + crypto_n_random_bytes(16, Bytes), + Bytes = [B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16], + byte_bits(B9, BitsClockSeqHi0), + BitsClockSeqHi0 = [_X7, _X6, X5, X4, X3, X2, X1, X0], + NewBitsClockSeqHi0 = [1, 0, X5, X4, X3, X2, X1, X0], + byte_bits(NewClockSeqHi0, NewBitsClockSeqHi0), + byte_bits(B7, BitsTimeHi), + BitsTimeHi = [_Y7, _Y6, _Y5, _Y4, Y3, Y2, Y1, Y0], + NewBitsTimeHi = [0, 1, 0, 0, Y3, Y2, Y1, Y0], + byte_bits(NewTimeHi, NewBitsTimeHi), + Uuid = [B1, B2, B3, B4, B5, B6, NewTimeHi, B8, NewClockSeqHi0, B10, B11, B12, B13, B14, B15, B16]. + +uuidv4_string(String) :- uuidv4(Uuid), uuid_string(Uuid, String). + +uuid_string(Uuid, String) :- + Uuid = [B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16], + phrase(uuid_([S1, S2, S3, S4, S5]), String), + hex_bytes(S1, [B1, B2, B3, B4]), + hex_bytes(S2, [B5, B6]), + hex_bytes(S3, [B7, B8]), + hex_bytes(S4, [B9, B10]), + hex_bytes(S5, [B11, B12, B13, B14, B15, B16]). + +uuid_([S1, S2, S3, S4, S5]) --> + { + length(S1, 8), + length(S2, 4), + length(S3, 4), + length(S4, 4), + length(S5, 12) + }, + S1, + "-", + S2, + "-", + S3, + "-", + S4, + "-", + S5. + +byte_bits(Byte, Bits) :- + \+ var(Byte), + byte_bits_(Byte, Bits), + length(Bits, 8),!. + +byte_bits(Byte, Bits) :- + \+ var(Bits), + length(Bits, 8), + byte_bits__(Byte, Bits),!. + +byte_bits_(0, [0]). +byte_bits_(1, [1]). +byte_bits_(Byte, Bits) :- + R is Byte // 2, + M is Byte mod 2, + byte_bits_(R, Bits0), + append(Bits0, [M], Bits). + +byte_bits__(0, []). +byte_bits__(Byte, Bits) :- + length(Bits, N), + Bits = [Bit|Bits0], + byte_bits__(Byte0, Bits0), + Byte is Byte0 + Bit*(2 ^ (N-1)). From b565eaaf5a578793ed73e24243990793ff21368e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Fri, 19 Feb 2021 00:13:00 +0100 Subject: [PATCH 091/137] Fix HTTP server to work on Rebis branch. Breaking change --- src/lib/http/http_server.pl | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/lib/http/http_server.pl b/src/lib/http/http_server.pl index 9e6d504b..1f86d438 100644 --- a/src/lib/http/http_server.pl +++ b/src/lib/http/http_server.pl @@ -10,7 +10,7 @@ Usage ========== The main predicate of the library is http_listen/2, which needs a port number - (usually 80) and a list of handlers. A handler is a compund term with the functor + (usually 80) and a list of handlers. A handler is created using the http_route/3 predicate as one HTTP method (in lowercase) and followed by a Route Match and a predicate which will handle the call. @@ -21,10 +21,13 @@ parameter_handler(User, Request, Response) :- http_body(Response, text(User)). - http_listen(7890, [ - get(echo, text_handler), % GET /echo - post(user/User, parameter_handler(User)) % POST /user/ - ]). + server :- + http_route(get(echo), text_handler, TextHandler), + http_route(post(user/User), parameter_handler(User), ParameterHandler), + http_listen(7890, [ + TextHandler, % GET /echo + ParameterHandler % POST /user/ + ]). Every handler predicate will have at least 2-arity, with Request and Response. Although you can work directly with http_request and http_response terms, it is @@ -49,6 +52,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ :- module(http_server, [ + http_route/3, http_listen/2, http_headers/2, http_status_code/2, @@ -58,6 +62,8 @@ url_decode//1 ]). +:- meta_predicate http_route(?, 2, ?). + :- use_module(library(sockets)). :- use_module(library(dcgs)). :- use_module(library(format)). @@ -68,6 +74,10 @@ :- use_module(library(time)). :- use_module(library(crypto)). +http_route(Path, Handler, MetaHandler) :- + Path =.. [Method, Pattern], + MetaHandler =.. [Method, Pattern, Handler]. + % Server initialization http_listen(Port, Handlers) :- must_be(integer, Port), @@ -99,7 +109,7 @@ accept_loop(Socket, Handlers) :- HttpResponse = http_response(_, _, _), (call(Handler, HttpRequest, HttpResponse) -> send_response(Stream, HttpResponse) - ; format(Stream, "HTTP/1.0 500 Internal Server Error\r\n\r\n") + ; format(Stream, "HTTP/1.0 500 Internal Server Error\r\n\r\n", []) ) ) ; format(Stream, "HTTP/1.0 404 Not Found\r\n\r\n", []) From eff892ccb88de1d2aae504915847fce11ae7caab Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 18 Feb 2021 17:58:05 -0700 Subject: [PATCH 092/137] add qualified imports use_module library modules --- src/clause_types.rs | 2 +- src/loader.pl | 2 +- src/machine/load_state.rs | 14 +++++++++++++- src/machine/loader.rs | 11 +++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index dc619a91..382dd6ae 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -760,7 +760,7 @@ impl SystemClauseType { ("$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) => { + ("$load_compiled_library", 3) => { Some(SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary)) } ("$push_load_state_payload", 1) => { diff --git a/src/loader.pl b/src/loader.pl index 95e0a052..09ea6dc9 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -428,7 +428,7 @@ use_module(Module, Exports, Evacuable) :- instantiation_error(load/1) ; Module = library(Library) -> ( path_atom(Library, LibraryPath) -> - ( '$load_compiled_library'(LibraryPath, Evacuable) -> %% TODO: What about Exports? + ( '$load_compiled_library'(LibraryPath, Exports, Evacuable) -> true ; '$load_library_as_stream'(LibraryPath, Stream, Path), file_load(Stream, Path, Subevacuable), diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 0a2fca5a..d652724b 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -235,6 +235,7 @@ fn import_qualified_module_exports( exports: &IndexSet, code_dir: &mut CodeDir, op_dir: &mut OpDir, + meta_predicates: &mut MetaPredicateDir, ) -> Result<(), SessionError> { for export in imported_module.module_decl.exports.iter() { if !exports.contains(export) { @@ -245,6 +246,10 @@ fn import_qualified_module_exports( 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()) @@ -281,6 +286,7 @@ fn import_qualified_module_exports_into_module( exports: &IndexSet, code_dir: &mut CodeDir, op_dir: &mut OpDir, + meta_predicates: &mut MetaPredicateDir, wam_op_dir: &mut OpDir, module_op_exports: &mut ModuleOpExports, ) -> Result<(), SessionError> { @@ -293,6 +299,10 @@ fn import_qualified_module_exports_into_module( 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()) @@ -1006,7 +1016,7 @@ impl<'a> LoadState<'a> { } } - fn import_qualified_module( + pub(super) fn import_qualified_module( &mut self, module_name: ClauseName, exports: IndexSet, @@ -1021,6 +1031,7 @@ impl<'a> LoadState<'a> { &exports, &mut self.wam.indices.code_dir, &mut self.wam.indices.op_dir, + &mut self.wam.indices.meta_predicates, )?; } CompilationTarget::Module(ref defining_module_name) => { @@ -1033,6 +1044,7 @@ impl<'a> LoadState<'a> { &exports, &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, )?; diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 38797ba8..d4b5e662 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1247,10 +1247,17 @@ impl Machine { return; } - let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2)); + let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3)); let import_module = || { - loader.load_state.import_module(library)?; + let export_list = loader.extract_module_export_list_from_heap(temp_v!(2))?; + + if export_list.is_empty() { + loader.load_state.import_module(library)?; + } else { + loader.load_state.import_qualified_module(library, export_list)?; + } + LiveTermStream::evacuate(loader) }; From a08f5c301661c2613836bca5f397fc727f765e87 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 19 Feb 2021 13:44:22 -0700 Subject: [PATCH 093/137] treat LocalCodePtr::Halt received at lookup_local_instr as an interrupt (#823) --- src/machine/code_repo.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/machine/code_repo.rs b/src/machine/code_repo.rs index 092f6407..7db42530 100644 --- a/src/machine/code_repo.rs +++ b/src/machine/code_repo.rs @@ -24,7 +24,8 @@ impl CodeRepo { ) -> RefOrOwned<'a, Line> { match p { LocalCodePtr::Halt => { - unreachable!() + // exit with the interrupt exit code. + std::process::exit(1); } LocalCodePtr::DirEntry(p) => { RefOrOwned::Borrowed(&self.code[p as usize]) From d3442bb08f133410707af49f939fdeb1fa50fd9c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 19 Feb 2021 14:12:34 -0700 Subject: [PATCH 094/137] qualify command-line specified goals with user: (#820) --- src/toplevel.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/toplevel.pl b/src/toplevel.pl index 8ff02242..36657d59 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -90,9 +90,9 @@ run_goals([g(Gs0)|Goals]) :- ), read_term_from_chars(Gs1, Goal), ( catch( - Goal, + user:Goal, Exception, - (write(Gs0), write(' causes: '), write(Exception), nl) % halt? + (write(Goal), write(' causes: '), write(Exception), nl) % halt? ) ; write('Warning: initialization failed for '), write(Gs0), nl From f6926a9642eda965f311f1df01f21dddb78129f9 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 19 Feb 2021 14:36:30 -0700 Subject: [PATCH 095/137] remove nl after top-level use_module (#818) --- src/toplevel.pl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/toplevel.pl b/src/toplevel.pl index 36657d59..b46bf49d 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -37,8 +37,7 @@ delegate_task([Arg0|Args], Goals0) :- ; member(Arg0, ["-v", "--version"]) -> print_version ; member(Arg0, ["-g", "--goal"]) -> gather_goal(g, Args, Goals0) ; atom_chars(Mod, Arg0), - catch(use_module(Mod), E, print_exception(E)), - nl + catch(use_module(Mod), E, print_exception(E)) ), delegate_task(Args, Goals0). From f2db0886dd16b60dfb8c5d54dd62c711a7f32338 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Fri, 19 Feb 2021 17:34:26 -0700 Subject: [PATCH 096/137] move to a local num-rug-adapter crate addressing #822 --- Cargo.lock | 4 +- Cargo.toml | 4 +- crates/num-rug-adapter/Cargo.toml | 18 + crates/num-rug-adapter/src/lib.rs | 883 ++++++++++++++++++++++++++++++ crates/prolog_parser/Cargo.toml | 2 +- 5 files changed, 905 insertions(+), 6 deletions(-) create mode 100644 crates/num-rug-adapter/Cargo.toml create mode 100644 crates/num-rug-adapter/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 42246954..360181de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -679,9 +679,7 @@ dependencies = [ [[package]] name = "num-rug-adapter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7470b6acf85abce0771203112db4181d03f7b8a6be49f0e842a78030192f8a58" +version = "0.1.5" dependencies = [ "libc", "num-bigint", diff --git a/Cargo.toml b/Cargo.toml index 708125ec..0d8dbee1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ categories = ["command-line-utilities"] build = "build.rs" [workspace] -members = ["crates/prolog_parser"] +members = ["crates/prolog_parser", "crates/num-rug-adapter"] [build-dependencies] indexmap = "1.0.2" @@ -33,7 +33,7 @@ indexmap = "1.0.2" lazy_static = "1.4.0" libc = "0.2.62" nix = "0.15.0" -num-rug-adapter = { optional = true, version = "0.1.4" } +num-rug-adapter = { optional = true, path = "./crates/num-rug-adapter" } ordered-float = "0.5.0" prolog_parser = { path = "./crates/prolog_parser", default-features = false } ref_thread_local = "0.0.0" diff --git a/crates/num-rug-adapter/Cargo.toml b/crates/num-rug-adapter/Cargo.toml new file mode 100644 index 00000000..8693ac47 --- /dev/null +++ b/crates/num-rug-adapter/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "num-rug-adapter" +version = "0.1.5" +authors = ["Marco A L Barbosa "] +edition = "2018" +description = "An adapter to use num crate where rug is needed." +license = "MIT/Apache-2.0" +repository = "https://github.com/malbarbo/num-rug-adapter" +keywords = ["mathematics", "numerics", "bignum"] +categories = ["api-bindings", "science"] +readme = "README.md" + +[dependencies] +libc = "0.2" +num-bigint = "0.2" +num-integer = "0.1.41" +num-rational = "0.2" +num-traits = "0.2" diff --git a/crates/num-rug-adapter/src/lib.rs b/crates/num-rug-adapter/src/lib.rs new file mode 100644 index 00000000..a95d42c8 --- /dev/null +++ b/crates/num-rug-adapter/src/lib.rs @@ -0,0 +1,883 @@ +use num_bigint::{BigInt, ParseBigIntError}; +use num_integer::Integer as _; +use num_rational::BigRational; +use num_traits::{FromPrimitive, Num, Signed, ToPrimitive}; +use num_traits::identities::One; + +use std::cmp::Ordering; +use std::fmt::{self, Display, Formatter}; +use std::ops::*; + +use std::str::FromStr; + +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Integer(BigInt); + +impl Integer { + #[inline] + pub fn new() -> Self { + Integer(BigInt::default()) + } + + #[inline] + pub fn from_str_radix(s: &str, radix: u32) -> Result { + BigInt::from_str_radix(s, radix).map(Integer) + } + + #[inline] + pub fn to_u8(&self) -> Option { + self.0.to_u8() + } + + #[inline] + pub fn to_u32(&self) -> Option { + self.0.to_u32() + } + + #[inline] + pub fn to_u64(&self) -> Option { + self.0.to_u64() + } + + #[inline] + pub fn to_usize(&self) -> Option { + self.0.to_usize() + } + + #[inline] + pub fn to_i32(&self) -> Option { + self.0.to_i32() + } + + #[inline] + pub fn to_isize(&self) -> Option { + self.0.to_isize() + } + + #[inline] + pub fn to_f64(&self) -> f64 { + self.0.to_f64().unwrap() + } + + #[inline] + pub fn abs(&self) -> Self { + Integer(self.0.abs()) + } + + #[inline] + pub fn abs_ref(&self) -> Self { + Integer(self.0.abs()) + } + + #[inline] + pub fn div_rem(&self, other: Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_rem(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn div_rem_ref(&self, other: &Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_rem(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn div_rem_floor(&self, other: Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn div_rem_floor_ref(&self, other: &Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn mod_u(&self, modulo: u32) -> u32 { + (self.0.abs() % modulo).to_u32().unwrap() + } + + #[inline] + pub fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + #[inline] + pub fn from_f64(v: f64) -> Option { + BigInt::from_f64(v).map(Integer) + } + + #[inline] + pub fn gcd_ref(&self, other: &Self) -> Self { + Integer(num_integer::Integer::gcd(&self.0, &other.0)) + } + + #[inline] + pub fn gcd(&self, other: &Self) -> Self { + Integer(num_integer::Integer::gcd(&self.0, &other.0)) + } +} + +impl From<&Integer> for Integer { + #[inline] + fn from(s: &Integer) -> Self { + s.clone() + } +} + +impl From for Integer { + #[inline] + fn from(s: i32) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: isize) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: u8) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: u32) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: u64) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: usize) -> Self { + Integer(BigInt::from(s)) + } +} + +impl Mul for Integer { + type Output = Integer; + + #[inline] + fn mul(self, other: Integer) -> Self::Output { + Integer(self.0 * other.0) + } +} + +impl Mul for Integer { + type Output = Integer; + + #[inline] + fn mul(self, other: u32) -> Self::Output { + Integer(self.0 * other) + } +} + +impl Mul<&Integer> for Integer { + type Output = Integer; + + fn mul(self, other: &Integer) -> Self::Output { + Integer(self.0 * &other.0) + } +} + +impl MulAssign<&Integer> for Integer { + #[inline] + fn mul_assign(&mut self, other: &Integer) { + self.0 *= &other.0; + } +} + +impl Add for Integer { + type Output = Integer; + + #[inline] + fn add(self, other: Integer) -> Self::Output { + Integer(self.0 + other.0) + } +} + +impl Add for &Integer { + type Output = Integer; + + #[inline] + fn add(self, other: Integer) -> Self::Output { + Integer(&self.0 + other.0) + } +} + +impl Add<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn add(self, other: &Integer) -> Self::Output { + Integer(self.0 + &other.0) + } +} + +impl Add<&Integer> for &Integer { + type Output = Integer; + + #[inline] + fn add(self, other: &Integer) -> Self::Output { + Integer(&self.0 + &other.0) + } +} + +impl AddAssign for Integer { + #[inline] + fn add_assign(&mut self, other: i64) { + self.0 += other; + } +} + +impl AddAssign<&Integer> for Integer { + #[inline] + fn add_assign(&mut self, other: &Integer) { + self.0 += &other.0; + } +} + +impl Div for Integer { + type Output = Integer; + + #[inline] + fn div(self, other: Integer) -> Integer { + Integer(self.0 / other.0) + } +} + +impl Div<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn div(self, other: &Integer) -> Integer { + Integer(self.0 / &other.0) + } +} + +impl Div for &Integer { + type Output = Integer; + + #[inline] + fn div(self, other: Integer) -> Integer { + Integer(&self.0 / &other.0) + } +} + +impl Shr for Integer { + type Output = Integer; + + #[inline] + fn shr(self, rhs: u32) -> Self::Output { + Integer(self.0 >> rhs as usize) + } +} + +impl Shr for &Integer { + type Output = Integer; + + #[inline] + fn shr(self, rhs: u32) -> Self::Output { + Integer(&self.0 >> rhs as usize) + } +} + +impl ShrAssign for Integer { + #[inline] + fn shr_assign(&mut self, rhs: u32) { + self.0 >>= rhs as usize; + } +} + +impl Shl for Integer { + type Output = Integer; + + #[inline] + fn shl(self, rhs: u32) -> Self::Output { + Integer(self.0 << rhs as usize) + } +} + +impl Shl for &Integer { + type Output = Integer; + + #[inline] + fn shl(self, rhs: u32) -> Self::Output { + Integer(&self.0 << rhs as usize) + } +} + +impl Not for Integer { + type Output = Integer; + + #[inline] + fn not(self) -> Self::Output { + Integer(!self.0) + } +} + +impl Not for &Integer { + type Output = Integer; + + #[inline] + fn not(self) -> Self::Output { + Integer(!&self.0) + } +} + +impl Rem for Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl Rem<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: &Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl Rem<&Integer> for &Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: &Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl Rem for &Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl BitAnd for Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: Integer) -> Self::Output { + Integer(self.0 & &other.0) + } +} + +impl BitAnd<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: &Integer) -> Self::Output { + Integer(self.0 & &other.0) + } +} + +impl BitAnd for &Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: Integer) -> Self::Output { + Integer(&self.0 & other.0) + } +} + +impl BitAnd for &Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: &Integer) -> Self::Output { + Integer(&self.0 & &other.0) + } +} + +impl BitOr for Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: Integer) -> Self::Output { + Integer(self.0 | other.0) + } +} + +impl BitOr<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: &Integer) -> Self::Output { + Integer(self.0 | &other.0) + } +} + +impl BitOr for &Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: Integer) -> Self::Output { + Integer(&self.0 | other.0) + } +} + +impl BitOr for &Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: &Integer) -> Self::Output { + Integer(&self.0 | &other.0) + } +} + +impl BitXor for Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: Integer) -> Self::Output { + Integer(self.0 ^ other.0) + } +} + +impl BitXor<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: &Integer) -> Self::Output { + Integer(self.0 ^ &other.0) + } +} + +impl BitXor for &Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: Integer) -> Self::Output { + Integer(&self.0 ^ other.0) + } +} + +impl BitXor<&Integer> for &Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: &Integer) -> Self::Output { + Integer(&self.0 ^ &other.0) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &i32) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &i64) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &isize) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &usize) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for isize { + #[inline] + fn eq(&self, other: &Integer) -> bool { + other.0 == BigInt::from(*self) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &i32) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &i64) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &isize) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &usize) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl FromStr for Integer { + type Err = ::Err; + + #[inline] + fn from_str(s: &str) -> Result { + Ok(Integer(s.parse()?)) + } +} + +impl Neg for Integer { + type Output = Integer; + + #[inline] + fn neg(self) -> Self { + Integer(-self.0) + } +} + +impl Display for Integer { + #[inline] + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +// Rational + +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Rational(BigRational); + +impl Rational { + #[inline] + pub fn new() -> Self { + Rational(BigRational::from(BigInt::default())) + } + + #[inline] + pub fn from_f64(v: f64) -> Option { + BigRational::from_f64(v).map(Rational) + } + + #[inline] + pub fn to_f64(&self) -> f64 { + self.0.numer().to_f64().unwrap() / self.0.denom().to_f64().unwrap() + } + + #[inline] + pub fn numer(&self) -> &Integer { + unsafe { ::std::mem::transmute(self.0.numer()) } + } + + #[inline] + pub fn denom(&self) -> &Integer { + unsafe { ::std::mem::transmute(self.0.denom()) } + } + + #[inline] + pub fn abs(self) -> Self { + Rational(self.0.abs()) + } + + #[inline] + pub fn abs_ref(&self) -> Self { + Rational(self.0.abs()) + } + + #[inline] + pub fn fract_floor_ref(&self) -> &Self { + panic!() + } +} + +impl From for Rational { + #[inline] + fn from(s: isize) -> Self { + Rational(BigRational::new_raw(BigInt::from(s), One::one())) + } +} + +impl From<&Integer> for Rational { + #[inline] + fn from(s: &Integer) -> Self { + Rational::from(s.clone()) + } +} + +impl From<&Rational> for Rational { + #[inline] + fn from(s: &Rational) -> Self { + s.clone() + } +} + +impl From for Rational { + #[inline] + fn from(i: Integer) -> Self { + Rational(BigRational::from(i.0)) + } +} + +impl Add for Rational { + type Output = Rational; + + #[inline] + fn add(self, other: Rational) -> Self::Output { + Rational(self.0 + other.0) + } +} + +impl Add<&Rational> for Rational { + type Output = Rational; + + #[inline] + fn add(self, other: &Rational) -> Self::Output { + Rational(self.0 + &other.0) + } +} + +impl PartialEq for Rational { + #[inline] + fn eq(&self, other: &i32) -> bool { + self.0 == BigRational::from(BigInt::from(*other)) + } +} + +impl PartialEq for Rational { + #[inline] + fn eq(&self, other: &i64) -> bool { + self.0 == BigRational::from(BigInt::from(*other)) + } +} + +impl PartialEq for Rational { + #[inline] + fn eq(&self, other: &isize) -> bool { + self == &Rational::from(*other) + } +} + +impl PartialEq for isize { + #[inline] + fn eq(&self, other: &Rational) -> bool { + other == &Rational::from(*self) + } +} + +impl PartialOrd for Rational { + #[inline] + fn partial_cmp(&self, other: &isize) -> Option { + self.0.partial_cmp(&BigRational::from(BigInt::from(*other))) + } +} + +impl PartialOrd for Rational { + #[inline] + fn partial_cmp(&self, other: &i64) -> Option { + self.0.partial_cmp(&BigRational::from(BigInt::from(*other))) + } +} + +impl PartialOrd for Rational { + #[inline] + fn partial_cmp(&self, other: &i32) -> Option { + self.0.partial_cmp(&BigRational::from(BigInt::from(*other))) + } +} + +impl Neg for Rational { + type Output = Rational; + + #[inline] + fn neg(self) -> Self { + Rational(-self.0) + } +} + +impl Mul for Rational { + type Output = Rational; + + #[inline] + fn mul(self, other: Rational) -> Self::Output { + Rational(self.0 * other.0) + } +} + +impl Mul<&Rational> for Rational { + type Output = Rational; + + fn mul(self, other: &Rational) -> Self::Output { + Rational(self.0 * &other.0) + } +} + +impl Div for Rational { + type Output = Rational; + + #[inline] + fn div(self, other: Rational) -> Self::Output { + Rational(self.0 / other.0) + } +} + +impl Div<&Rational> for &Rational { + type Output = Rational; + + #[inline] + fn div(self, other: &Rational) -> Self::Output { + Rational(&self.0 / &other.0) + } +} + +impl Display for Rational { + #[inline] + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +pub trait Assign { + fn assign(&mut self, src: Src); +} + +impl Assign<&Rational> for (&mut Rational, &mut Integer) { + fn assign(&mut self, _src: &Rational) { + panic!() + } +} + +pub mod ops { + use super::{Integer, Rational}; + + pub trait Pow { + type Output; + fn pow(self, rhs: Rhs) -> Self::Output; + } + + impl Pow for Integer { + type Output = Integer; + + fn pow(self, rhs: u32) -> Self::Output { + Integer(num_traits::Pow::pow(&self.0, rhs)) + } + } + + pub trait PowAssign { + fn pow_assign(&mut self, rhs: Rhs); + } + + impl PowAssign for Integer { + fn pow_assign(&mut self, rhs: u32) { + // FIXME: make it efficient + self.0 = num_traits::Pow::pow(&self.0, rhs); + } + } + + pub trait NegAssign { + fn neg_assign(&mut self); + } + + impl NegAssign for Integer { + fn neg_assign(&mut self) { + self.0 = -std::mem::replace(self, Integer::new()).0; + } + } + + impl NegAssign for Rational { + #[inline] + fn neg_assign(&mut self) { + self.0 = -std::mem::replace(self, Rational::new()).0; + } + } +} + +pub mod rand { + use super::Integer; + use std::marker::PhantomData; + + pub struct RandState<'a>{ + _marker: PhantomData<&'a ()>, + } + + impl<'a> RandState<'a> { + pub fn new() -> Self { + unsafe { libc::srand(libc::time(std::ptr::null_mut()) as _) }; + RandState { _marker: PhantomData } + } + + pub fn borrow_mut(&self) -> &Self { + self + } + + pub fn bits(&mut self, bits: u32) -> u32 { + assert!(bits <= 32); + (unsafe { libc::rand() } as u32) & (u32::max_value() >> (32 - bits)) + } + + pub fn seed(&mut self, seed: &Integer) { + unsafe { libc::srand(seed.to_f64() as _)} + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::ops::NegAssign; + + #[test] + fn bits() { + let mut rand = rand::RandState::new(); + for bits in 1..32 { + for _ in 0..100 { + let r = rand.bits(bits); + let max = 1 << bits; + assert!(max > r, "{} > {}", max, r); + } + } + } + + #[test] + fn neg_rational() { + let mut x = Rational::from_f64(5.0).unwrap(); + let x_neg = Rational::from_f64(-5.0).unwrap(); + x.neg_assign(); + assert_eq!(x, x_neg); + } + + #[test] + fn neg_integer() { + let mut x = Integer::from(5); + let x_neg = Integer::from(-5); + x.neg_assign(); + assert_eq!(x, x_neg); + } +} diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml index b9dab9fd..8946bf27 100644 --- a/crates/prolog_parser/Cargo.toml +++ b/crates/prolog_parser/Cargo.toml @@ -12,7 +12,7 @@ indexmap = "1.0.2" lexical = "2.1.0" ordered-float = "0.5.0" rug = { optional = true, version = "1.4.0" } -num-rug-adapter = { optional = true, version = "0.1.3" } +num-rug-adapter = { optional = true, path = "../num-rug-adapter" } unicode_reader = "1.0.0" [lib] From a9fe2ab5c465811b69824e06af47a246a593c05a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 20 Feb 2021 18:25:34 -0700 Subject: [PATCH 097/137] use env::current_dir in Machine::current_dir (#833) --- src/machine/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 384e0daf..a919f3c4 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -120,7 +120,7 @@ pub struct Machine { #[inline] fn current_dir() -> PathBuf { - PathBuf::from("./").canonicalize().unwrap_or(PathBuf::from("./")) + std::env::current_dir().unwrap_or(PathBuf::from("./")) } include!(concat!(env!("OUT_DIR"), "/libraries.rs")); From eb5ea28bcde8674d6505c7cfe0cdbda0527e3e6a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 20 Feb 2021 18:31:47 -0700 Subject: [PATCH 098/137] add 'e' as evaluable functor for Euler's constant (#832) --- src/arithmetic.rs | 6 ++++++ src/machine/arithmetic_ops.rs | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 7941ed3b..bcaf239f 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -278,6 +278,12 @@ impl<'a> ArithmeticEvaluator<'a> { &Constant::Rational(ref n) => self .interm .push(ArithmeticTerm::Number(Number::Rational(n.clone()))), + &Constant::Atom(ref name, _) if name.as_str() == "e" => { + self.interm + .push(ArithmeticTerm::Number(Number::Float(OrderedFloat( + f64::consts::E, + )))) + } &Constant::Atom(ref name, _) if name.as_str() == "pi" => { self.interm .push(ArithmeticTerm::Number(Number::Float(OrderedFloat( diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 63ec2d6d..9ce4eac0 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -224,6 +224,9 @@ impl MachineState { &HeapCellValue::Atom(ref name, _) if name.as_str() == "pi" => { interms.push(Number::Float(OrderedFloat(f64::consts::PI))) } + &HeapCellValue::Atom(ref name, _) if name.as_str() == "e" => { + interms.push(Number::Float(OrderedFloat(f64::consts::E))) + } &HeapCellValue::NamedStr(arity, ref name, _) => { let evaluable_stub = MachineError::functor_stub(name.clone(), arity); From fec790e10859575509b0f788140dd2453c0b2669 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 20 Feb 2021 19:10:34 -0700 Subject: [PATCH 099/137] correct comment before call meta_predicate declarations --- src/lib/ops_and_meta_predicates.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ops_and_meta_predicates.pl b/src/lib/ops_and_meta_predicates.pl index 59a324d4..f84d0fd6 100644 --- a/src/lib/ops_and_meta_predicates.pl +++ b/src/lib/ops_and_meta_predicates.pl @@ -59,7 +59,7 @@ :- op(1200, xfx, -->). -% meta_predicate declarations for call/{0, 64}. +% meta_predicate declarations for call/{1, 66}. :- meta_predicate call(0). :- meta_predicate call(1, ?). :- meta_predicate call(2, ?, ?). From 5225587ff5d5b31920ef556c3780d8fe302bc718 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 21 Feb 2021 12:08:14 -0700 Subject: [PATCH 100/137] add set_prolog_flag to declarations recognized by loader.pl --- src/loader.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index 09ea6dc9..5f5a1031 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -245,7 +245,6 @@ compile_dispatch(user:goal_expansion(Term, Terms), Evacuable) :- compile_dispatch((user:goal_expansion(Term, Terms) :- Body), Evacuable) :- '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable). - remove_module(Module, Evacuable) :- ( nonvar(Module), Module = library(ModuleName), @@ -307,6 +306,8 @@ compile_declaration(discontiguous(Module:Name/Arity), Evacuable) :- compile_declaration(initialization(Goal), Evacuable) :- prolog_load_context(module, Module), assertz(Module:'$initialization_goals'(Goal)). +compile_declaration(set_prolog_flag(Flag, Value), _) :- + set_prolog_flag(Flag, Value). compile_clause((Target:Head :- Body), Evacuable) :- @@ -543,7 +544,7 @@ expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars ) -> ( var(SG), pairs:same_key(SG, HeadVars, [_|_], _) -> - expand_subgoal(SG, MS, M, ESG, HeadVars) + expand_subgoal(SG, MS, M, ESG, HeadVars) %%TODO: Shortcut this.. set SG = ESG. Or wrap it in '$call', ie. ESG = '$call'(SG). ; expand_subgoal(SG, MS, M, ESG0, HeadVars), expand_module_name(ESG0, M, ESG) ), From d60bfef924199d51238ba26a36e19b5849dcd109 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 21 Feb 2021 12:08:36 -0700 Subject: [PATCH 101/137] tweak bimetatrans_tests.pl --- src/examples/bimetatrans/bimetatrans_tests.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/bimetatrans/bimetatrans_tests.pl b/src/examples/bimetatrans/bimetatrans_tests.pl index 8675dcde..eab6f294 100644 --- a/src/examples/bimetatrans/bimetatrans_tests.pl +++ b/src/examples/bimetatrans/bimetatrans_tests.pl @@ -1,6 +1,6 @@ :- module(bimetatran_tests, [test_bimetatrans/0]). -:- use_module('bimetatrans'). +:- use_module(bimetatrans). :- use_module(library(dcgs)). :- use_module(library(iso_ext)). From 265a5955d764b1ba613a7b0e9e20b90b9c2dfa4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Sun, 21 Feb 2021 20:22:08 +0100 Subject: [PATCH 102/137] Use notoria's comment --- src/lib/http/http_server.pl | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/lib/http/http_server.pl b/src/lib/http/http_server.pl index 1f86d438..f39b2226 100644 --- a/src/lib/http/http_server.pl +++ b/src/lib/http/http_server.pl @@ -10,7 +10,7 @@ Usage ========== The main predicate of the library is http_listen/2, which needs a port number - (usually 80) and a list of handlers. A handler is created using the http_route/3 predicate + (usually 80) and a list of handlers. A handler is a compund term with the functor as one HTTP method (in lowercase) and followed by a Route Match and a predicate which will handle the call. @@ -21,13 +21,10 @@ parameter_handler(User, Request, Response) :- http_body(Response, text(User)). - server :- - http_route(get(echo), text_handler, TextHandler), - http_route(post(user/User), parameter_handler(User), ParameterHandler), - http_listen(7890, [ - TextHandler, % GET /echo - ParameterHandler % POST /user/ - ]). + http_listen(7890, [ + get(echo, text_handler), % GET /echo + post(user/User, parameter_handler(User)) % POST /user/ + ]). Every handler predicate will have at least 2-arity, with Request and Response. Although you can work directly with http_request and http_response terms, it is @@ -52,7 +49,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ :- module(http_server, [ - http_route/3, http_listen/2, http_headers/2, http_status_code/2, @@ -62,7 +58,7 @@ url_decode//1 ]). -:- meta_predicate http_route(?, 2, ?). +:- meta_predicate http_listen(?, 2). :- use_module(library(sockets)). :- use_module(library(dcgs)). @@ -74,12 +70,17 @@ :- use_module(library(time)). :- use_module(library(crypto)). -http_route(Path, Handler, MetaHandler) :- - Path =.. [Method, Pattern], - MetaHandler =.. [Method, Pattern, Handler]. +% Module prefix workaround with meta_predicate +http_listen(Port, Module:Handlers0) :- + maplist(module_qualification(Module), Handlers0, Handlers), + http_listen_(Port, Handlers). + +module_qualification(M, H0, H) :- + H0 =.. [Method, Path, Goal], + H =.. [Method, Path, M:Goal]. % Server initialization -http_listen(Port, Handlers) :- +http_listen_(Port, Handlers) :- must_be(integer, Port), must_be(list, Handlers), once(socket_server_open(Port, Socket)), From 77968ab33a08d9392445b6b5bd416defc9c79172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Sun, 21 Feb 2021 21:08:03 +0100 Subject: [PATCH 103/137] Fix typo --- src/lib/http/http_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/http/http_server.pl b/src/lib/http/http_server.pl index f39b2226..72657c35 100644 --- a/src/lib/http/http_server.pl +++ b/src/lib/http/http_server.pl @@ -10,7 +10,7 @@ Usage ========== The main predicate of the library is http_listen/2, which needs a port number - (usually 80) and a list of handlers. A handler is a compund term with the functor + (usually 80) and a list of handlers. A handler is a compound term with the functor as one HTTP method (in lowercase) and followed by a Route Match and a predicate which will handle the call. From a323a4dd8e0c18ea6be8f83334575f0acb5685e9 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 21 Feb 2021 16:28:30 -0700 Subject: [PATCH 104/137] wrap stream instances in one Rc>, use Ref/RefMut to access stream options --- src/heap_print.rs | 2 +- src/machine/machine_state.rs | 4 +- src/machine/mod.rs | 4 +- src/machine/streams.rs | 164 +++++++++++++++++++++-------------- src/machine/system_calls.rs | 56 ++++++------ 5 files changed, 132 insertions(+), 98 deletions(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index aadd2e0f..a7250c2f 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1363,7 +1363,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } fn print_stream(&mut self, iter: &mut HCPreOrderIterator, stream: &Stream, max_depth: usize) { - if let Some(alias) = &stream.options.alias { + if let Some(alias) = &stream.options().alias { self.print_atom(alias); } else { if self.format_struct(iter, max_depth, 1, clause_name!("$stream")) { diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 96964b1e..ab372549 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -308,7 +308,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -402,7 +402,7 @@ impl MachineState { 3, )?; - if orig_stream.options.eof_action == EOFAction::Reset { + if orig_stream.options().eof_action == EOFAction::Reset { if self.fail == false { continue; } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index a919f3c4..b9247176 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -387,7 +387,7 @@ impl Machine { } pub fn configure_streams(&mut self) { - self.user_input.options.alias = Some(clause_name!("user_input")); + self.user_input.options_mut().alias = Some(clause_name!("user_input")); self.indices .stream_aliases @@ -395,7 +395,7 @@ impl Machine { self.indices.streams.insert(self.user_input.clone()); - self.user_output.options.alias = Some(clause_name!("user_output")); + self.user_output.options_mut().alias = Some(clause_name!("user_output")); self.indices .stream_aliases diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 21ffbbda..f4c182ce 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -197,13 +197,25 @@ impl fmt::Debug for StreamInstance { } } +#[derive(Debug)] +struct InnerStream { + options: StreamOptions, + stream_inst: StreamInstance, + past_end_of_stream: bool, +} + #[derive(Debug, Clone)] -struct WrappedStreamInstance(Rc>); +struct WrappedStreamInstance(Rc>); impl WrappedStreamInstance { #[inline] - fn new(stream_inst: StreamInstance) -> Self { - WrappedStreamInstance(Rc::new(RefCell::new((false, stream_inst)))) + fn new(stream_inst: StreamInstance, past_end_of_stream: bool) -> Self { + WrappedStreamInstance(Rc::new(RefCell::new( + InnerStream { + options: StreamOptions::default(), + stream_inst, + past_end_of_stream } + ))) } } @@ -293,7 +305,6 @@ impl Default for StreamOptions { #[derive(Debug, Clone, Hash)] pub struct Stream { - pub options: StreamOptions, stream_inst: WrappedStreamInstance, } @@ -352,9 +363,25 @@ impl Stream { ptr as *const u8 } + #[inline] + pub(crate) fn options(&self) -> std::cell::Ref<'_, StreamOptions> { + std::cell::Ref::map( + self.stream_inst.0.borrow(), + |inner_stream| &inner_stream.options, + ) + } + + #[inline] + pub(crate) fn options_mut(&mut self) -> std::cell::RefMut<'_, StreamOptions> { + std::cell::RefMut::map( + self.stream_inst.0.borrow_mut(), + |inner_stream| &mut inner_stream.options, + ) + } + #[inline] pub(crate) fn position(&mut self) -> Option { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::InputFile(_, ref mut file) => file.seek(SeekFrom::Current(0)).ok(), _ => None, } @@ -363,7 +390,9 @@ impl Stream { #[inline] pub(crate) fn set_position(&mut self, position: u64) { match self.stream_inst.0.borrow_mut().deref_mut() { - (past_end_of_stream, StreamInstance::InputFile(_, ref mut file)) => { + InnerStream { past_end_of_stream, + stream_inst: StreamInstance::InputFile(_, ref mut file), + .. } => { file.seek(SeekFrom::Start(position)).unwrap(); if let Ok(metadata) = file.metadata() { @@ -376,7 +405,7 @@ impl Stream { #[inline] pub(crate) fn past_end_of_stream(&self) -> bool { - self.stream_inst.0.borrow_mut().0 + self.stream_inst.0.borrow_mut().past_end_of_stream } #[inline] @@ -386,7 +415,7 @@ impl Stream { #[inline] pub(crate) fn set_past_end_of_stream(&mut self) { - self.stream_inst.0.borrow_mut().0 = true; + self.stream_inst.0.borrow_mut().past_end_of_stream = true; } #[inline] @@ -396,7 +425,9 @@ impl Stream { } match self.stream_inst.0.borrow_mut().deref_mut() { - (past_end_of_stream, StreamInstance::InputFile(_, ref mut file)) => { + InnerStream { past_end_of_stream, + stream_inst: StreamInstance::InputFile(_, ref mut file), + .. } => { match file.metadata() { Ok(metadata) => { if let Ok(position) = file.seek(SeekFrom::Current(0)) { @@ -404,17 +435,17 @@ impl Stream { Ordering::Equal => AtEndOfStream::At, Ordering::Less => AtEndOfStream::Not, Ordering::Greater => { - *past_end_of_stream = true; //self.set_past_end_of_stream(); + *past_end_of_stream = true; AtEndOfStream::Past } }; } else { - *past_end_of_stream = true; //self.set_past_end_of_stream(); + *past_end_of_stream = true; AtEndOfStream::Past } } _ => { - *past_end_of_stream = true; //self.set_past_end_of_stream(); + *past_end_of_stream = true; AtEndOfStream::Past } } @@ -425,7 +456,7 @@ impl Stream { #[inline] pub(crate) fn file_name(&self) -> Option { - match self.stream_inst.0.borrow().1 { + match self.stream_inst.0.borrow().stream_inst { StreamInstance::InputFile(ref name, _) => Some(name.clone()), StreamInstance::OutputFile(ref name, ..) => Some(name.clone()), StreamInstance::TcpStream(ref name, _) => Some(name.clone()), @@ -435,12 +466,12 @@ impl Stream { #[inline] pub(crate) fn mode(&self) -> &'static str { - match self.stream_inst.0.borrow().1 { - StreamInstance::Bytes(_) - | StreamInstance::PausedPrologStream(..) - | StreamInstance::ReadlineStream(_) - | StreamInstance::StaticStr(_) - | StreamInstance::InputFile(..) => "read", + match self.stream_inst.0.borrow().stream_inst { + StreamInstance::Bytes(_) | + StreamInstance::PausedPrologStream(..) | + StreamInstance::ReadlineStream(_) | + StreamInstance::StaticStr(_) | + StreamInstance::InputFile(..) => "read", StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append", StreamInstance::OutputFile(_, _, true) => "append", StreamInstance::Stdout | StreamInstance::OutputFile(_, _, false) => "write", @@ -451,8 +482,7 @@ impl Stream { #[inline] fn from_inst(stream_inst: StreamInstance) -> Self { Stream { - options: StreamOptions::default(), - stream_inst: WrappedStreamInstance::new(stream_inst), + stream_inst: WrappedStreamInstance::new(stream_inst, false), } } @@ -486,7 +516,7 @@ impl Stream { #[inline] pub(crate) fn is_stdout(&self) -> bool { - match self.stream_inst.0.borrow().1 { + match self.stream_inst.0.borrow().stream_inst { StreamInstance::Stdout => true, _ => false, } @@ -494,7 +524,7 @@ impl Stream { #[inline] pub(crate) fn is_stdin(&self) -> bool { - match self.stream_inst.0.borrow().1 { + match self.stream_inst.0.borrow().stream_inst { StreamInstance::ReadlineStream(_) => true, _ => false, } @@ -502,12 +532,12 @@ impl Stream { #[inline] pub(crate) fn close(&mut self) { - self.stream_inst.0.borrow_mut().1 = StreamInstance::Null; + self.stream_inst.0.borrow_mut().stream_inst = StreamInstance::Null; } #[inline] pub(crate) fn is_null_stream(&self) -> bool { - if let StreamInstance::Null = self.stream_inst.0.borrow().1 { + if let StreamInstance::Null = self.stream_inst.0.borrow().stream_inst { true } else { false @@ -516,32 +546,32 @@ impl Stream { #[inline] pub(crate) fn is_input_stream(&self) -> bool { - match self.stream_inst.0.borrow().1 { - StreamInstance::TcpStream(..) - | StreamInstance::TlsStream(..) - | StreamInstance::Bytes(_) - | StreamInstance::PausedPrologStream(..) - | StreamInstance::ReadlineStream(_) - | StreamInstance::StaticStr(_) - | StreamInstance::InputFile(..) => true, + match self.stream_inst.0.borrow().stream_inst { + StreamInstance::TcpStream(..) | + StreamInstance::TlsStream(..) | + StreamInstance::Bytes(_) | + StreamInstance::PausedPrologStream(..) | + StreamInstance::ReadlineStream(_) | + StreamInstance::StaticStr(_) | + StreamInstance::InputFile(..) => true, _ => false, } } #[inline] pub(crate) fn is_output_stream(&self) -> bool { - match self.stream_inst.0.borrow().1 { - StreamInstance::Stdout - | StreamInstance::TcpStream(..) - | StreamInstance::TlsStream(..) - | StreamInstance::Bytes(_) - | StreamInstance::OutputFile(..) => true, + match self.stream_inst.0.borrow().stream_inst { + StreamInstance::Stdout | + StreamInstance::TcpStream(..) | + StreamInstance::TlsStream(..) | + StreamInstance::Bytes(_) | + StreamInstance::OutputFile(..) => true, _ => false, } } fn unpause_stream(&mut self) { - let stream_inst = match self.stream_inst.0.borrow_mut().1 { + let stream_inst = match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::PausedPrologStream(ref put_back, ref mut stream_inst) if put_back.is_empty() => { @@ -552,16 +582,16 @@ impl Stream { } }; - self.stream_inst.0.borrow_mut().1 = stream_inst; + self.stream_inst.0.borrow_mut().stream_inst = stream_inst; } // returns true on success. #[inline] pub(super) fn reset(&mut self) -> bool { - self.stream_inst.0.borrow_mut().0 = false; + self.stream_inst.0.borrow_mut().past_end_of_stream = false; loop { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::Bytes(ref mut cursor) => { cursor.set_position(0); return true; @@ -587,7 +617,7 @@ impl Stream { #[inline] pub(crate) fn peek_byte(&mut self) -> std::io::Result { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::Bytes(ref mut cursor) => { let mut b = [0u8; 1]; let pos = cursor.position(); @@ -631,7 +661,7 @@ impl Stream { pub(crate) fn peek_char(&mut self) -> std::io::Result { use unicode_reader::CodePoints; - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::InputFile(_, ref mut file) => { let c = { let mut iter = CodePoints::from(&*file); @@ -679,7 +709,7 @@ impl Stream { #[inline] pub(crate) fn pause_stream(&mut self, buf: Vec>) -> io::Result<()> { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::PausedPrologStream(ref mut inner_buf, _) => { inner_buf.extend(parser_top_to_bytes(buf)?.into_iter()); return Ok(()); @@ -688,10 +718,12 @@ impl Stream { } if !buf.is_empty() { - let stream_inst = - mem::replace(&mut self.stream_inst.0.borrow_mut().1, StreamInstance::Null); + let stream_inst = mem::replace( + &mut self.stream_inst.0.borrow_mut().stream_inst, + StreamInstance::Null, + ); - self.stream_inst.0.borrow_mut().1 = StreamInstance::PausedPrologStream( + self.stream_inst.0.borrow_mut().stream_inst = StreamInstance::PausedPrologStream( parser_top_to_bytes(buf)?, Box::new(stream_inst), ); @@ -710,13 +742,15 @@ impl MachineState { caller: ClauseName, arity: usize, ) -> CallResult { - match stream.options.eof_action { + let eof_action = stream.options().eof_action; + + match eof_action { EOFAction::Error => { stream.set_past_end_of_stream(); return Err(self.open_past_eos_error(stream.clone(), caller, arity)); } EOFAction::EOFCode => { - let end_of_stream = if stream.options.stream_type == StreamType::Binary { + let end_of_stream = if stream.options().stream_type == StreamType::Binary { Addr::Fixnum(-1) } else { self.heap @@ -979,7 +1013,7 @@ impl MachineState { Some("stream") // 8.14.2.3 g) } else if input.is_none() && !stream.is_output_stream() { Some("stream") // 8.14.2.3 g) - } else if stream.options.stream_type != expected_type { + } else if stream.options().stream_type != expected_type { Some(expected_type.other().as_str()) // 8.14.2.3 h) } else { None @@ -1014,7 +1048,7 @@ impl MachineState { impl Read for Stream { #[inline] fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - let bytes_read = self.stream_inst.0.borrow_mut().1.read(buf)?; + let bytes_read = self.stream_inst.0.borrow_mut().stream_inst.read(buf)?; self.unpause_stream(); Ok(bytes_read) } @@ -1022,17 +1056,17 @@ impl Read for Stream { impl Write for Stream { fn write(&mut self, buf: &[u8]) -> std::io::Result { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::OutputFile(_, ref mut file, _) => file.write(buf), StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.write(buf), StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf), StreamInstance::Bytes(ref mut cursor) => cursor.write(buf), StreamInstance::Stdout => stdout().write(buf), - StreamInstance::PausedPrologStream(..) - | StreamInstance::StaticStr(_) - | StreamInstance::ReadlineStream(_) - | StreamInstance::InputFile(..) - | StreamInstance::Null => Err(std::io::Error::new( + StreamInstance::PausedPrologStream(..) | + StreamInstance::StaticStr(_) | + StreamInstance::ReadlineStream(_) | + StreamInstance::InputFile(..) | + StreamInstance::Null => Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::WriteToInputStream, )), @@ -1040,17 +1074,17 @@ impl Write for Stream { } fn flush(&mut self) -> std::io::Result<()> { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::OutputFile(_, ref mut file, _) => file.flush(), StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.flush(), StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(), StreamInstance::Bytes(ref mut cursor) => cursor.flush(), StreamInstance::Stdout => stdout().flush(), - StreamInstance::PausedPrologStream(..) - | StreamInstance::StaticStr(_) - | StreamInstance::ReadlineStream(_) - | StreamInstance::InputFile(..) - | StreamInstance::Null => Err(std::io::Error::new( + StreamInstance::PausedPrologStream(..) | + StreamInstance::StaticStr(_) | + StreamInstance::ReadlineStream(_) | + StreamInstance::InputFile(..) | + StreamInstance::Null => Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::FlushToInputStream, )), diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 8251c3fe..12039b02 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -467,7 +467,7 @@ impl MachineState { } else { self.p.local() + 1 }; - + Ok(self.p = CodePtr::REPL(repl_code_ptr, p)) } @@ -1319,7 +1319,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1395,7 +1395,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1417,7 +1417,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1491,7 +1491,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1520,7 +1520,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1610,7 +1610,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2027,7 +2027,7 @@ impl MachineState { let mut bytes = Vec::new(); let string = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); - if stream.options.stream_type == StreamType::Binary { + if stream.options().stream_type == StreamType::Binary { for c in string.chars() { if c as u32 > 255 { let stub = MachineError::functor_stub(clause_name!("$put_chars"), 2); @@ -2172,7 +2172,7 @@ impl MachineState { if stream.past_end_of_stream() { self.eof_action(self[temp_v!(2)], &mut stream, clause_name!("get_byte"), 2)?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2253,7 +2253,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2327,7 +2327,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2363,7 +2363,7 @@ impl MachineState { let mut string = String::new(); - if stream.options.stream_type == StreamType::Binary { + if stream.options().stream_type == StreamType::Binary { let mut buf = vec![]; let mut chunk = stream.take(num as u64); chunk.read_to_end(&mut buf).ok(); @@ -2402,7 +2402,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2490,7 +2490,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2664,8 +2664,8 @@ impl MachineState { if !stream.is_stdin() && !stream.is_stdout() { stream.close(); - if let Some(alias) = stream.options.alias { - indices.stream_aliases.remove(&alias); + if let Some(ref alias) = stream.options().alias { + indices.stream_aliases.remove(alias); } } } @@ -3153,11 +3153,11 @@ impl MachineState { _ => self.stream_from_file_spec(clause_name!(""), indices, &options)?, }; - stream.options = options; + *stream.options_mut() = options; indices.streams.insert(stream.clone()); - if let Some(ref alias) = &stream.options.alias { + if let Some(ref alias) = &stream.options().alias { indices.stream_aliases.insert(alias.clone(), stream.clone()); } @@ -4261,9 +4261,9 @@ impl MachineState { } }; - stream.options = options; + *stream.options_mut() = options; - if let Some(ref alias) = &stream.options.alias { + if let Some(ref alias) = &stream.options().alias { indices.stream_aliases.insert(alias.clone(), stream.clone()); } @@ -4398,9 +4398,9 @@ impl MachineState { let mut tcp_stream = Stream::from_tcp_stream(client.clone(), tcp_stream); - tcp_stream.options = options; + *tcp_stream.options_mut() = options; - if let Some(ref alias) = &tcp_stream.options.alias { + if let Some(ref alias) = &tcp_stream.options().alias { indices .stream_aliases .insert(alias.clone(), tcp_stream.clone()); @@ -4467,7 +4467,7 @@ impl MachineState { let mut stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "set_stream_position", 2)?; - if !stream.options.reposition { + if !stream.options().reposition { let stub = MachineError::functor_stub(clause_name!("set_stream_position"), 2); let err = MachineError::permission_error( @@ -4526,7 +4526,7 @@ impl MachineState { None, ), "alias" => { - if let Some(alias) = &stream.options.alias { + if let Some(alias) = &stream.options().alias { HeapCellValue::Atom(alias.clone(), None) } else { self.fail = true; @@ -4547,11 +4547,11 @@ impl MachineState { HeapCellValue::Atom(clause_name!(end_of_stream_pos.as_str()), None) } "eof_action" => HeapCellValue::Atom( - clause_name!(stream.options.eof_action.as_str()), + clause_name!(stream.options().eof_action.as_str()), None, ), "reposition" => HeapCellValue::Atom( - clause_name!(if stream.options.reposition { + clause_name!(if stream.options().reposition { "true" } else { "false" @@ -4559,7 +4559,7 @@ impl MachineState { None, ), "type" => HeapCellValue::Atom( - clause_name!(stream.options.stream_type.as_property_str()), + clause_name!(stream.options().stream_type.as_property_str()), None, ), _ => { @@ -4815,7 +4815,7 @@ impl MachineState { let opt_err = if !stream.is_output_stream() { Some("stream") // 8.14.2.3 g) - } else if stream.options.stream_type == StreamType::Binary { + } else if stream.options().stream_type == StreamType::Binary { Some("binary_stream") // 8.14.2.3 h) } else { None From 0ef5f7f9b1ef7ebbf6622b8830ec970d644159b3 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 21 Feb 2021 19:18:06 -0700 Subject: [PATCH 105/137] issue singleton variable warnings from loader.pl (#812) --- crates/prolog_parser/src/parser.rs | 20 +++----- src/clause_types.rs | 6 +++ src/lib/builtins.pl | 19 ++++--- src/loader.pl | 50 +++++++++++++++++- src/machine/loader.rs | 12 +++++ src/machine/machine_indices.rs | 1 + src/machine/machine_state.rs | 82 ++++++++++++++++++------------ src/machine/mod.rs | 3 ++ src/machine/streams.rs | 24 +++++++-- src/machine/system_calls.rs | 14 +++-- src/read.rs | 8 ++- src/write.rs | 2 + 12 files changed, 178 insertions(+), 63 deletions(-) diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index a623f9f4..0fa142f6 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -965,6 +965,12 @@ impl<'a, R: Read> Parser<'a, R> { self.lexer.eof() } + #[inline] + pub fn num_lines_read(&self) -> usize { + self.lexer.line_num + } + + // on success, returns the parsed term and the number of lines read. pub fn read_term(&mut self, op_dir: &CompositeOpDir) -> Result { self.tokens = read_tokens(&mut self.lexer)?; @@ -998,18 +1004,4 @@ impl<'a, R: Read> Parser<'a, R> { )), } } - - pub fn read(&mut self, op_dir: &CompositeOpDir) -> Result, ParserError> { - let mut terms = Vec::new(); - - loop { - terms.push(self.read_term(op_dir)?); - - if self.lexer.eof()? { - break; - } - } - - Ok(terms) - } } diff --git a/src/clause_types.rs b/src/clause_types.rs index 382dd6ae..70736282 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -422,6 +422,9 @@ impl SystemClauseType { &SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports) => { clause_name!("$remove_module_exports") } + &SystemClauseType::REPL(REPLCodePtr::AddNonCountedBacktracking) => { + clause_name!("$add_non_counted_backtracking") + } &SystemClauseType::Close => clause_name!("$close"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), @@ -778,6 +781,9 @@ impl SystemClauseType { ("$remove_module_exports", 2) => { Some(SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports)) } + ("$add_non_counted_backtracking", 3) => { + Some(SystemClauseType::REPL(REPLCodePtr::AddNonCountedBacktracking)) + } ("$variant", 2) => Some(SystemClauseType::Variant), ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions), ("$write_term", 7) => Some(SystemClauseType::WriteTerm), diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 975a07c1..abf650c2 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -1516,16 +1516,21 @@ peek_char(S, C) :- '$peek_char'(S, C). +is_stream_position(position_and_lines_read(P, L)) :- + ( var(P) ; integer(P), P >= 0 ), + ( var(L) ; integer(L), L >= 0 ), + !. + +check_stream_property(D, direction, D) :- + ( var(D) -> true ; lists:member(D, [input, output, input_output]), ! ). check_stream_property(file_name(F), file_name, F) :- ( var(F) -> true ; atom(F) ). check_stream_property(mode(M), mode, M) :- ( var(M) -> true ; lists:member(M, [read, write, append]) ). -check_stream_property(D, direction, D) :- - ( var(D) -> true ; lists:member(D, [input, output, input_output]), ! ). check_stream_property(alias(A), alias, A) :- ( var(A) -> true ; atom(A) ). check_stream_property(position(P), position, P) :- - ( var(P) -> true ; integer(P), P >= 0 ). + ( var(P) -> true ; is_stream_position(P)). check_stream_property(end_of_stream(E), end_of_stream, E) :- ( var(E) -> true ; lists:member(E, [not, at, past]) ). check_stream_property(eof_action(A), eof_action, A) :- @@ -1576,8 +1581,8 @@ at_end_of_stream :- set_stream_position(S_or_a, Position) :- ( var(Position) -> throw(error(instantiation_error, set_stream_position/2)) - ; integer(Position), Position >= 0 -> - true + ; Position = position_and_lines_read(P, _), + is_stream_position(Position) -> + '$set_stream_position'(S_or_a, P) ; throw(error(domain_error(stream_position, Position))) - ), - '$set_stream_position'(S_or_a, Position). + ). diff --git a/src/loader.pl b/src/loader.pl index 5f5a1031..5975dddd 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -110,14 +110,55 @@ load(Stream) :- false. %% Clear the heap. load(_). + +print_comma_separated_list([VN=_]) :- + write(VN), + !. +print_comma_separated_list([VN=_, VNEq | VNEqs]) :- + write(VN), + write(', '), + print_comma_separated_list([VNEq | VNEqs]). + + +filter_anonymous_vars([], []). +filter_anonymous_vars([VN=V | VNEqs0], VNEqs) :- + ( atom_concat('_', _, VN) -> + filter_anonymous_vars(VNEqs0, VNEqs) + ; VNEqs = [VN=V | VNEqs1], + filter_anonymous_vars(VNEqs0, VNEqs1) + ). + +warn_about_singletons([], _). +warn_about_singletons([Singleton|Singletons], LinesRead) :- + ( LinesRead =:= -1 -> + true + ; filter_anonymous_vars([Singleton|Singletons], VarEqs), + VarEqs \== [] -> + write('Warning: singleton variables '), + print_comma_separated_list(VarEqs), + write(' at line '), + write(LinesRead), + write(' of '), + load_context(Module), + write(Module), + nl + ; true + ). + + load_loop(Stream, Evacuable) :- + ( stream_property(Stream, position(position_and_lines_read(_, LinesRead))) -> + true + ; LinesRead = -1 + ), read_term(Stream, Term, [singletons(Singletons)]), ( Term == end_of_file -> close(Stream), '$conclude_load'(Evacuable) ; var(Term) -> instantiation_error(load/1) - ; compile_term(Term, Evacuable), + ; warn_about_singletons(Singletons, LinesRead), + compile_term(Term, Evacuable), load_loop(Stream, Evacuable) ). @@ -308,6 +349,13 @@ compile_declaration(initialization(Goal), Evacuable) :- assertz(Module:'$initialization_goals'(Goal)). compile_declaration(set_prolog_flag(Flag, Value), _) :- set_prolog_flag(Flag, Value). +compile_declaration(non_counted_backtracking(Name/Arity), Evacuable) :- + must_be(atom, Name), + must_be(integer, Arity), + ( Arity >= 0 -> + '$add_non_counted_backtracking'(Name, Arity, Evacuable) + ; domain_error(not_less_than_zero, Arity, load/1) + ). compile_clause((Target:Head :- Body), Evacuable) :- diff --git a/src/machine/loader.rs b/src/machine/loader.rs index d4b5e662..afa193d3 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1947,6 +1947,18 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } + pub(crate) fn add_non_counted_backtracking(&mut self) { + let key = self + .machine_st + .read_predicate_key(self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)]); + + let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(3)); + loader.non_counted_bt_preds.insert(key); + + let result = LiveTermStream::evacuate(loader); + self.restore_load_state_payload(result, evacuable_h); + } + pub(crate) fn meta_predicate_property(&mut self) { let module_name = atom_from!( self.machine_st, diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 43264a3f..336ab16c 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -449,6 +449,7 @@ pub enum REPLCodePtr { IsConsistentWithTermQueue, FlushTermQueue, RemoveModuleExports, + AddNonCountedBacktracking, } #[derive(Debug, Clone, PartialEq)] diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index ab372549..b7ac7499 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -27,6 +27,7 @@ use std::fmt; use std::io::Write; use std::mem; use std::ops::{Index, IndexMut}; +use std::rc::Rc; #[derive(Debug)] pub struct Ball { @@ -299,6 +300,30 @@ pub struct MachineState { impl MachineState { pub(crate) fn read_term(&mut self, mut stream: Stream, indices: &mut IndexStore) -> CallResult { + fn push_var_eq_functors<'a>( + heap: &mut Heap, + iter: impl Iterator, &'a Addr)>, + op_dir: &OpDir, + atom_tbl: TabledData, + ) -> Vec { + let mut list_of_var_eqs = vec![]; + + for (var, binding) in iter { + let var_atom = clause_name!(var.to_string(), atom_tbl); + + let h = heap.h(); + let spec = fetch_atom_op_spec(clause_name!("="), None, op_dir); + + heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec)); + heap.push(HeapCellValue::Atom(var_atom, None)); + heap.push(HeapCellValue::Addr(*binding)); + + list_of_var_eqs.push(Addr::Str(h)); + } + + list_of_var_eqs + } + self.check_stream_properties( &mut stream, StreamType::Text, @@ -327,47 +352,40 @@ impl MachineState { return Ok(()); } - 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(), self.atom_tbl); - - let h = self.heap.h(); - let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir); - - self.heap - .push(HeapCellValue::NamedStr(2, clause_name!("="), spec)); - self.heap.push(HeapCellValue::Atom(var_atom, None)); - self.heap.push(HeapCellValue::Addr(binding)); - - list_of_var_eqs.push(Addr::Str(h)); - } - - let mut var_set: IndexMap = IndexMap::new(); - - for addr in self.acyclic_pre_order_iter(term) { - if let Some(var) = addr.as_var() { - if !var_set.contains_key(&var) { - var_set.insert(var, true); - } else { - var_set.insert(var, false); - } - } - } + let list_of_var_eqs = push_var_eq_functors( + &mut self.heap, + term_write_result.var_dict.iter(), + &indices.op_dir, + self.atom_tbl.clone(), + ); + let mut singleton_var_set: IndexMap = IndexMap::new(); let mut var_list = vec![]; - let mut singleton_var_list = vec![]; for addr in self.acyclic_pre_order_iter(term) { if let Some(var) = addr.as_var() { - if var_set.get(&var) == Some(&true) { - singleton_var_list.push(var.as_addr()); + if !singleton_var_set.contains_key(&var) { + singleton_var_set.insert(var, true); + var_list.push(addr); + } else { + singleton_var_set.insert(var, false); } - - var_list.push(var.as_addr()); } } + let singleton_var_list = push_var_eq_functors( + &mut self.heap, + term_write_result.var_dict.iter().filter(|(_, binding)| { + if let Some(r) = binding.as_var() { + *singleton_var_set.get(&r).unwrap_or(&false) + } else { + false + } + }), + &indices.op_dir, + self.atom_tbl.clone(), + ); + let singleton_addr = self[temp_v!(3)]; let singletons_offset = Addr::HeapCell(self.heap.to_list(singleton_var_list.into_iter())); diff --git a/src/machine/mod.rs b/src/machine/mod.rs index b9247176..6e3bd4eb 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -513,6 +513,9 @@ impl Machine { REPLCodePtr::RemoveModuleExports => { self.remove_module_exports(); } + REPLCodePtr::AddNonCountedBacktracking => { + self.add_non_counted_backtracking(); + } } self.machine_st.p = CodePtr::Local(p); diff --git a/src/machine/streams.rs b/src/machine/streams.rs index f4c182ce..4c138a49 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -202,6 +202,7 @@ struct InnerStream { options: StreamOptions, stream_inst: StreamInstance, past_end_of_stream: bool, + lines_read: usize, } #[derive(Debug, Clone)] @@ -214,7 +215,9 @@ impl WrappedStreamInstance { InnerStream { options: StreamOptions::default(), stream_inst, - past_end_of_stream } + past_end_of_stream, + lines_read: 0, + } ))) } } @@ -363,6 +366,11 @@ impl Stream { ptr as *const u8 } + #[inline] + pub(crate) fn add_lines_read(&mut self, incr_num_lines_read: usize) { + self.stream_inst.0.borrow_mut().lines_read += incr_num_lines_read; + } + #[inline] pub(crate) fn options(&self) -> std::cell::Ref<'_, StreamOptions> { std::cell::Ref::map( @@ -380,11 +388,18 @@ impl Stream { } #[inline] - pub(crate) fn position(&mut self) -> Option { - match self.stream_inst.0.borrow_mut().stream_inst { + pub(crate) fn position(&mut self) -> Option<(u64, usize)> { // returns lines_read, position. + let result = match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::InputFile(_, ref mut file) => file.seek(SeekFrom::Current(0)).ok(), + StreamInstance::TcpStream(..) | + StreamInstance::TlsStream(..) | + StreamInstance::ReadlineStream(..) | + StreamInstance::StaticStr(..) | + StreamInstance::Bytes(..) => Some(0), _ => None, - } + }; + + result.map(|position| (position, self.stream_inst.0.borrow().lines_read)) } #[inline] @@ -588,6 +603,7 @@ impl Stream { // returns true on success. #[inline] pub(super) fn reset(&mut self) -> bool { + self.stream_inst.0.borrow_mut().lines_read = 0; self.stream_inst.0.borrow_mut().past_end_of_stream = false; loop { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 12039b02..3c30de06 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -4534,8 +4534,17 @@ impl MachineState { } } "position" => { - if let Some(position) = stream.position() { - HeapCellValue::Addr(Addr::Usize(position as usize)) + if let Some((position, lines_read)) = stream.position() { + let h = self.heap.h(); + + let position_term = functor!( + "position_and_lines_read", + [integer(position), integer(lines_read)] + ); + + self.heap.extend(position_term.into_iter()); + + HeapCellValue::Addr(Addr::HeapCell(h)) } else { self.fail = true; return Ok(()); @@ -4543,7 +4552,6 @@ impl MachineState { } "end_of_stream" => { let end_of_stream_pos = stream.position_relative_to_end(); - HeapCellValue::Atom(clause_name!(end_of_stream_pos.as_str()), None) } "eof_action" => HeapCellValue::Atom( diff --git a/src/read.rs b/src/read.rs index b55849a9..4cb8e779 100644 --- a/src/read.rs +++ b/src/read.rs @@ -184,15 +184,19 @@ impl MachineState { ) -> Result { let mut stream = parsing_stream(inner.clone())?; - let term = { + let (term, num_lines_read) = { let mut parser = Parser::new(&mut stream, atom_tbl, self.flags); - parser.read_term(&CompositeOpDir::new(op_dir, None))? + let term = parser.read_term(&CompositeOpDir::new(op_dir, None))?; + + (term, parser.num_lines_read()) }; // 'pausing' the stream saves the pending top buffer // created by the parsing stream, which was created in this // scope and is about to be destroyed in it. + inner.add_lines_read(num_lines_read); + let buf = stream.take_buf(); inner.pause_stream(buf)?; diff --git a/src/write.rs b/src/write.rs index 52263c2f..e98b550f 100644 --- a/src/write.rs +++ b/src/write.rs @@ -85,6 +85,8 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::FlushTermQueue"), REPLCodePtr::RemoveModuleExports => write!(f, "REPLCodePtr::RemoveModuleExports"), + REPLCodePtr::AddNonCountedBacktracking => + write!(f, "REPLCodePtr::AddNonCountedBacktracking"), } } } From f6498f2a7bfcdc8299c16a0151bbcd2677fb646b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 21 Feb 2021 19:19:43 -0700 Subject: [PATCH 106/137] anonymize singleton variables in iso_ext.pl, charsio.pl --- src/lib/charsio.pl | 2 +- src/lib/iso_ext.pl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/charsio.pl b/src/lib/charsio.pl index 05681bc3..3f30ec17 100644 --- a/src/lib/charsio.pl +++ b/src/lib/charsio.pl @@ -53,7 +53,7 @@ extend_var_list(Vars, VarList, NewVarList, VarType) :- extend_var_list_(Vars, 0, VarList, NewVarList0, VarType), append(VarList, NewVarList0, NewVarList). -extend_var_list_([], _, VarList, [], _). +extend_var_list_([], _, _, [], _). extend_var_list_([V|Vs], N, VarList, NewVarList, VarType) :- ( var_list_contains_variable(VarList, V) -> extend_var_list_(Vs, N, VarList, NewVarList, VarType) diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index c7c3d6c3..fe5d4baf 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -110,10 +110,10 @@ run_cleaners_without_handling(Cp) :- % call_with_inference_limit :- non_counted_backtracking end_block/4. -end_block(_, Bb, NBb, L) :- +end_block(_, Bb, NBb, _L) :- '$clean_up_block'(NBb), '$reset_block'(Bb). -end_block(B, Bb, NBb, L) :- +end_block(B, _Bb, NBb, L) :- '$install_inference_counter'(B, L, _), '$reset_block'(NBb), '$fail'. From 5f8bdc564b7319c692a7923ed60661d4f7b9d1a6 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 22 Feb 2021 02:00:25 -0700 Subject: [PATCH 107/137] extend existing local predicate skeletons in LoadState::compile --- src/machine/compile.rs | 39 ++++++++++++++++++++++++++++++++------- src/machine/loader.rs | 22 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 9364d176..ebdcb134 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1099,14 +1099,39 @@ impl<'a> LoadState<'a> { } } - let mut skeleton = PredicateSkeleton::new(); - skeleton.clause_clause_locs = clause_clause_locs; + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &self.compilation_target, + predicates.compilation_target.clone(), + key.clone(), + ) + { + Some(skeleton) => { + self.retraction_info + .push_record(RetractionRecord::SkeletonLocalClauseTruncateBack( + self.compilation_target.clone(), + predicates.compilation_target.clone(), + key.clone(), + skeleton.clause_clause_locs.len(), + )); - self.add_local_extensible_predicate( - predicates.compilation_target.clone(), - key.clone(), - skeleton, - ); + skeleton.clause_clause_locs.extend_from_slice( + &clause_clause_locs[0 ..] + ); + } + None => { + let mut skeleton = PredicateSkeleton::new(); + skeleton.clause_clause_locs = clause_clause_locs; + + self.add_local_extensible_predicate( + predicates.compilation_target.clone(), + key.clone(), + skeleton, + ); + } + } } set_code_index( diff --git a/src/machine/loader.rs b/src/machine/loader.rs index afa193d3..a9d45bcc 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -76,6 +76,7 @@ pub(crate) enum RetractionRecord { SkeletonClausePopFront(CompilationTarget, PredicateKey), SkeletonLocalClauseClausePopBack(CompilationTarget, CompilationTarget, PredicateKey), SkeletonLocalClauseClausePopFront(CompilationTarget, CompilationTarget, PredicateKey), + SkeletonLocalClauseTruncateBack(CompilationTarget, CompilationTarget, PredicateKey, usize), SkeletonClauseTruncateBack(CompilationTarget, PredicateKey, usize), SkeletonClauseStartReplaced(CompilationTarget, PredicateKey, usize, usize), RemovedSkeletonClause( @@ -519,6 +520,27 @@ impl<'a> Drop for LoadState<'a> { None => {} } } + RetractionRecord::SkeletonLocalClauseTruncateBack( + src_compilation_target, + local_compilation_target, + key, + len, + ) => { + match self + .wam + .indices + .get_local_predicate_skeleton_mut( + &src_compilation_target, + local_compilation_target, + key, + ) + { + Some(skeleton) => { + skeleton.clause_clause_locs.truncate_back(len); + } + None => {} + } + } RetractionRecord::SkeletonClauseTruncateBack(compilation_target, key, len) => { match self .wam From 1a9f6f06dfa704ee96b4b2e7af1dd3de150f3139 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 22 Feb 2021 13:23:22 -0700 Subject: [PATCH 108/137] consume whitespace before reading a term in loader.pl, modify prolog_load_context at file key to better reflect loading context, use it when reporting singleton variables (#812) --- src/clause_types.rs | 5 ++++ src/loader.pl | 16 +++++----- src/machine/loader.rs | 28 ++++++++++------- src/machine/streams.rs | 1 + src/machine/system_calls.rs | 60 ++++++++----------------------------- src/read.rs | 22 ++++++++++++-- 6 files changed, 62 insertions(+), 70 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 70736282..ecfd0cbf 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -306,6 +306,7 @@ pub enum SystemClauseType { SetEnv, UnsetEnv, CharsBase64, + DevourWhitespace, } impl SystemClauseType { @@ -594,6 +595,7 @@ impl SystemClauseType { &SystemClauseType::UnsetEnv => clause_name!("$unsetenv"), &SystemClauseType::CharsBase64 => clause_name!("$chars_base64"), &SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"), + &SystemClauseType::DevourWhitespace => clause_name!("$devour_whitespace"), } } @@ -841,6 +843,9 @@ impl SystemClauseType { ("$cpp_discontiguous_property", 3) => { Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty)) } + ("$devour_whitespace", 1) => { + Some(SystemClauseType::DevourWhitespace) + } _ => None, } } diff --git a/src/loader.pl b/src/loader.pl index 5975dddd..bf6efc26 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -130,28 +130,26 @@ filter_anonymous_vars([VN=V | VNEqs0], VNEqs) :- warn_about_singletons([], _). warn_about_singletons([Singleton|Singletons], LinesRead) :- - ( LinesRead =:= -1 -> - true - ; filter_anonymous_vars([Singleton|Singletons], VarEqs), + ( filter_anonymous_vars([Singleton|Singletons], VarEqs), VarEqs \== [] -> write('Warning: singleton variables '), print_comma_separated_list(VarEqs), write(' at line '), write(LinesRead), write(' of '), - load_context(Module), - write(Module), + prolog_load_context(file, File), + write(File), nl ; true ). load_loop(Stream, Evacuable) :- - ( stream_property(Stream, position(position_and_lines_read(_, LinesRead))) -> - true - ; LinesRead = -1 + ( '$devour_whitespace'(Stream) -> + stream_property(Stream, position(position_and_lines_read(_, LinesRead))), + read_term(Stream, Term, [singletons(Singletons)]) + ; Term = end_of_file ), - read_term(Stream, Term, [singletons(Singletons)]), ( Term == end_of_file -> close(Stream), '$conclude_load'(Evacuable) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index a9d45bcc..96c449dc 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1612,20 +1612,26 @@ impl Machine { 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); + match load_context.path.file_name() { + Some(file_name) if load_context.path.is_file() => { + let file_name_str = file_name.to_str().unwrap(); + let file_name_atom = + 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)), + ); - let file_name_addr = Addr::Con( self.machine_st - .heap - .push(HeapCellValue::Atom(file_name_atom, None)), - ); + .unify(file_name_addr, self.machine_st[temp_v!(1)]); - self.machine_st - .unify(file_name_addr, self.machine_st[temp_v!(1)]); - return; + return; + } + _ => { + return self.load_context_module(); + } } } diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 4c138a49..c08a6ae5 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -395,6 +395,7 @@ impl Stream { StreamInstance::TlsStream(..) | StreamInstance::ReadlineStream(..) | StreamInstance::StaticStr(..) | + StreamInstance::PausedPrologStream(..) | StreamInstance::Bytes(..) => Some(0), _ => None, }; diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 3c30de06..0d94fd1c 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -3888,54 +3888,6 @@ impl MachineState { self.unify(a1, a2); } - /* - &SystemClauseType::GetClause => { - let head = self[temp_v!(1)]; - - let subsection = match self.store(self.deref(head)) { - Addr::Str(s) => match &self.heap[s] { - &HeapCellValue::NamedStr(arity, ref name, ..) => { - indices.get_clause_subsection( - name.owning_module(), - name.clone(), - arity, - ) - } - _ => { - unreachable!() - } - }, - Addr::Con(h) if self.heap.atom_at(h) => { - if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] { - indices.get_clause_subsection( - name.owning_module(), - name.clone(), - 0, - ) - } else { - unreachable!() - } - } - _ => { - unreachable!() - } - }; - - match subsection { - Some(dynamic_predicate_info) => { - self.execute_at_index( - 2, - dir_entry!(dynamic_predicate_info.clauses_subsection_p), - ); - - return Ok(()); - } - _ => { - unreachable!() - } - } - } - */ &SystemClauseType::GetCutPoint => { let a1 = self[temp_v!(1)]; let a2 = Addr::CutPoint(self.b0); @@ -5496,6 +5448,18 @@ impl MachineState { } } } + &SystemClauseType::DevourWhitespace => { + let stream = + self.get_stream_or_alias(self[temp_v!(1)], indices, "$devour_whitespace", 1)?; + + match self.devour_whitespace(stream, self.atom_tbl.clone()) { + Ok(false) => {} // not at EOF. + _ => { + self.fail = true; + return Ok(()); + } + } + } }; return_from_clause!(self.last_call, self) diff --git a/src/read.rs b/src/read.rs index 4cb8e779..fa158414 100644 --- a/src/read.rs +++ b/src/read.rs @@ -176,6 +176,24 @@ pub mod readline { } impl MachineState { + pub fn devour_whitespace( + &mut self, + mut inner: Stream, + atom_tbl: TabledData, + ) -> Result { + let mut stream = parsing_stream(inner.clone())?; + let mut parser = Parser::new(&mut stream, atom_tbl, self.flags); + + parser.devour_whitespace()?; + inner.add_lines_read(parser.num_lines_read()); + + let result = parser.eof(); + let buf = stream.take_buf(); + + inner.pause_stream(buf)?; + result + } + pub fn read( &mut self, mut inner: Stream, @@ -191,12 +209,12 @@ impl MachineState { (term, parser.num_lines_read()) }; + inner.add_lines_read(num_lines_read); + // 'pausing' the stream saves the pending top buffer // created by the parsing stream, which was created in this // scope and is about to be destroyed in it. - inner.add_lines_read(num_lines_read); - let buf = stream.take_buf(); inner.pause_stream(buf)?; From 6c447da730e476f8bce3774ed4a9edf7567b92fc Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 22 Feb 2021 18:27:30 -0700 Subject: [PATCH 109/137] no longer generate a choice point in bb_b_put/2 (#742) --- src/clause_types.rs | 28 ++----- src/lib/iso_ext.pl | 39 ++++------ src/machine/heap.rs | 5 ++ src/machine/machine_indices.rs | 11 +-- src/machine/machine_state.rs | 70 ++++++++++++++---- src/machine/machine_state_impl.rs | 61 ++++++++++++++-- src/machine/mod.rs | 18 ++++- src/machine/system_calls.rs | 117 +++++++++++------------------- 8 files changed, 195 insertions(+), 154 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index ecfd0cbf..1804040a 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -186,7 +186,6 @@ pub enum SystemClauseType { EnqueueAttributeGoal, EnqueueAttributedVar, FetchGlobalVar, - FetchGlobalVarWithOffset, FirstStream, FlushOutput, GetByte, @@ -240,14 +239,12 @@ pub enum SystemClauseType { RemoveCallPolicyCheck, RemoveInferenceCounter, ResetContinuationMarker, - ResetGlobalVarAtKey, - ResetGlobalVarAtOffset, RestoreCutPolicy, SetCutPoint(RegType), SetInput, SetOutput, + StoreBacktrackableGlobalVar, StoreGlobalVar, - StoreGlobalVarWithOffset, StreamProperty, SetStreamPosition, InferenceLevel, @@ -434,9 +431,6 @@ impl SystemClauseType { &SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"), &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"), - &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"), @@ -527,10 +521,10 @@ impl SystemClauseType { &SystemClauseType::SetSeed => clause_name!("$set_seed"), &SystemClauseType::StreamProperty => clause_name!("$stream_property"), &SystemClauseType::SetStreamPosition => clause_name!("$set_stream_position"), - &SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"), - &SystemClauseType::StoreGlobalVarWithOffset => { - clause_name!("$store_global_var_with_offset") + &SystemClauseType::StoreBacktrackableGlobalVar => { + clause_name!("$store_back_trackable_global_var") } + &SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"), &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), &SystemClauseType::EraseBall => clause_name!("$erase_ball"), @@ -539,15 +533,10 @@ impl SystemClauseType { &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::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::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::ResetContinuationMarker => clause_name!("$reset_cont_marker"), &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), @@ -654,9 +643,6 @@ impl SystemClauseType { ("$peek_code", 2) => Some(SystemClauseType::PeekCode), ("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), - ("$fetch_global_var_with_offset", 3) => { - Some(SystemClauseType::FetchGlobalVarWithOffset) - } ("$get_byte", 2) => Some(SystemClauseType::GetByte), ("$get_char", 2) => Some(SystemClauseType::GetChar), ("$get_n_chars", 3) => Some(SystemClauseType::GetNChars), @@ -723,8 +709,6 @@ impl SystemClauseType { ("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$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), ("$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))), @@ -737,8 +721,8 @@ impl SystemClauseType { ("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept), ("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), - ("$store_global_var_with_offset", 2) => { - Some(SystemClauseType::StoreGlobalVarWithOffset) + ("$store_backtrackable_global_var", 2) => { + Some(SystemClauseType::StoreBacktrackableGlobalVar) } ("$term_attributed_variables", 2) => Some(SystemClauseType::TermAttributedVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables), diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index fe5d4baf..61a3fa29 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -9,7 +9,7 @@ partial_string_tail/2, setup_call_cleanup/3, call_nth/2, variant/2]). -:- use_module(library(error), [can_be/2,domain_error/3]). +:- use_module(library(error), [can_be/2, domain_error/3, type_error/3]). :- meta_predicate call_cleanup(0, 0). @@ -22,34 +22,25 @@ forall(Generate, Test) :- %% (non-)backtrackable global variables. -bb_put(Key, Value) :- atom(Key), !, '$store_global_var'(Key, Value). -bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)). +bb_put(Key, Value) :- + ( atom(Key) -> + '$store_global_var'(Key, Value) + ; type_error(atom, Key, bb_put/2) + ). %% backtrackable global variables. -bb_b_put(Key, NewValue) :- - ( '$bb_get_with_offset'(Key, OldValue, OldOffset) -> - call_cleanup((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), - reset_global_var_at_key(Key)) +bb_b_put(Key, Value) :- + ( atom(Key) -> + '$store_backtrackable_global_var'(Key, Value) + ; type_error(atom, Key, bb_b_put/2) ). -store_global_var_with_offset(Key, Value) :- '$store_global_var_with_offset'(Key, Value). - -store_global_var(Key, Value) :- '$store_global_var'(Key, Value). - -reset_global_var_at_key(Key) :- '$reset_global_var_at_key'(Key). - -reset_global_var_at_offset(Key, Value, Offset) :- '$reset_global_var_at_offset'(Key, Value, Offset). - -'$bb_get_with_offset'(Key, OldValue, Offset) :- - atom(Key), !, '$fetch_global_var_with_offset'(Key, OldValue, Offset). -'$bb_get_with_offset'(Key, _, _) :- - throw(error(type_error(atom, Key), bb_b_put/2)). - -bb_get(Key, Value) :- atom(Key), !, '$fetch_global_var'(Key, Value). -bb_get(Key, _) :- throw(error(type_error(atom, Key), bb_get/2)). +bb_get(Key, Value) :- + ( atom(Key) -> + '$fetch_global_var'(Key, Value) + ; type_error(atom, Key, bb_get/2) + ). call_cleanup(G, C) :- setup_call_cleanup(true, G, C). diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 7f9323c1..935bad8b 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -206,6 +206,11 @@ impl HeapTemplate { } } + #[inline] + pub(crate) fn is_empty(&self) -> bool { + self.h() == 0 + } + #[inline] pub(crate) fn pop(&mut self) { let h = self.h(); diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 336ab16c..04a60feb 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -12,7 +12,6 @@ use crate::machine::partial_string::*; use crate::machine::raw_block::RawBlockTraits; use crate::machine::streams::Stream; use crate::machine::term_stream::LoadStatePayload; -use crate::machine::Ball; use crate::machine::CompilationTarget; use crate::rug::{Integer, Rational}; use ordered_float::OrderedFloat; @@ -297,6 +296,8 @@ pub enum TrailRef { Ref(Ref), AttrVarHeapLink(usize), AttrVarListLink(usize, usize), + BlackboardEntry(usize), + BlackboardOffset(usize, usize), // key atom heap location, key value heap location } impl From for TrailRef { @@ -691,13 +692,7 @@ impl SubAssign for CodePtr { pub type HeapVarDict = IndexMap, Addr>; pub type AllocVarDict = IndexMap, VarData>; -pub type InSituCodeDir = IndexMap; -pub type GlobalVarDir = IndexMap)>; - -#[derive(Debug)] -pub(crate) struct ModuleStub { - pub(crate) in_situ_code_dir: InSituCodeDir, -} +pub type GlobalVarDir = IndexMap)>; pub(crate) type StreamAliasDir = IndexMap; pub(crate) type StreamDir = BTreeSet; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index b7ac7499..26686fd8 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -657,7 +657,12 @@ impl MachineState { pub(crate) type CallResult = Result<(), Vec>; pub(crate) trait CallPolicy: Any + fmt::Debug { - fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { + fn retry_me_else( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -679,7 +684,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -708,7 +713,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Ok(()) } - fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { + fn retry( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -730,7 +740,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -759,7 +769,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Ok(()) } - fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { + fn trust( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -779,7 +794,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -811,7 +826,11 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { Ok(()) } - fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult { + fn trust_me( + &mut self, + machine_st: &mut MachineState, + global_variables: &mut GlobalVarDir, + ) -> CallResult { let b = machine_st.b; let n = machine_st .stack @@ -831,7 +850,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let curr_tr = machine_st.tr; - machine_st.unwind_trail(old_tr, curr_tr); + machine_st.unwind_trail(old_tr, curr_tr, global_variables); machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); @@ -1225,23 +1244,42 @@ impl CallPolicy for CWILCallPolicy { self.increment(machine_st) } - fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { - self.prev_policy.retry_me_else(machine_st, offset)?; + fn retry_me_else( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.retry_me_else(machine_st, offset, global_variables)?; self.increment(machine_st) } - fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { - self.prev_policy.retry(machine_st, offset)?; + fn retry( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.retry(machine_st, offset, global_variables)?; self.increment(machine_st) } - fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult { - self.prev_policy.trust_me(machine_st)?; + fn trust_me( + &mut self, + machine_st: &mut MachineState, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.trust_me(machine_st, global_variables)?; self.increment(machine_st) } - fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { - self.prev_policy.trust(machine_st, offset)?; + fn trust( + &mut self, + machine_st: &mut MachineState, + offset: usize, + global_variables: &mut GlobalVarDir, + ) -> CallResult { + self.prev_policy.trust(machine_st, offset, global_variables)?; self.increment(machine_st) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index d92a4f6f..5b946b0d 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -621,6 +621,14 @@ impl MachineState { self.tr += 1; } } + TrailRef::BlackboardOffset(key_h, value_h) => { + self.trail.push(TrailRef::BlackboardOffset(key_h, value_h)); + self.tr += 1; + } + TrailRef::BlackboardEntry(key_h) => { + self.trail.push(TrailRef::BlackboardEntry(key_h)); + self.tr += 1; + } } } @@ -644,7 +652,12 @@ impl MachineState { } } - pub(super) fn unwind_trail(&mut self, a1: usize, a2: usize) { + pub(super) fn unwind_trail( + &mut self, + a1: usize, + a2: usize, + global_variables: &mut GlobalVarDir, + ) { // the sequence is reversed to respect the chronology of trail // additions, now that deleted attributes can be undeleted by // backtracking. @@ -665,6 +678,30 @@ impl MachineState { TrailRef::AttrVarListLink(h, l) => { self.heap[h] = HeapCellValue::Addr(Addr::Lis(l)); } + TrailRef::BlackboardOffset(key_h, value_h) => { + let key = atom_from!( + self, + self.store(self.deref(self.heap[key_h].as_addr(key_h))) + ); + + let value_addr = self.heap[value_h].as_addr(value_h); + + match global_variables.get_mut(&key) { + Some((_, ref mut loc)) => *loc = Some(value_addr), + None => unreachable!(), + } + } + TrailRef::BlackboardEntry(key_h) => { + let key = atom_from!( + self, + self.store(self.deref(self.heap[key_h].as_addr(key_h))) + ); + + match global_variables.get_mut(&key) { + Some((_, ref mut loc)) => *loc = None, + None => unreachable!(), + } + } } } } @@ -1266,6 +1303,7 @@ impl MachineState { &mut self, indexing_lines: &Vec, call_policy: &mut Box, + global_variables: &mut GlobalVarDir, ) { let mut index = 0; let addr = match &indexing_lines[0] { @@ -1372,7 +1410,12 @@ impl MachineState { unreachable!() } - self.execute_indexed_choice_instr(instrs.first().unwrap(), call_policy); + self.execute_indexed_choice_instr( + instrs.first().unwrap(), + call_policy, + global_variables, + ); + break; } } @@ -2989,6 +3032,7 @@ impl MachineState { &mut self, instr: &IndexedChoiceInstruction, call_policy: &mut Box, + global_variables: &mut GlobalVarDir, ) { match instr { &IndexedChoiceInstruction::Try(offset) => { @@ -3018,10 +3062,10 @@ impl MachineState { self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset)); } &IndexedChoiceInstruction::Retry(l) => { - try_or_fail!(self, call_policy.retry(self, l)); + try_or_fail!(self, call_policy.retry(self, l, global_variables)); } &IndexedChoiceInstruction::Trust(l) => { - try_or_fail!(self, call_policy.trust(self, l)); + try_or_fail!(self, call_policy.trust(self, l, global_variables)); } }; } @@ -3030,6 +3074,7 @@ impl MachineState { &mut self, instr: &ChoiceInstruction, call_policy: &mut Box, + global_variables: &mut GlobalVarDir, ) { match instr { &ChoiceInstruction::TryMeElse(offset) => { @@ -3059,17 +3104,17 @@ impl MachineState { } &ChoiceInstruction::DefaultRetryMeElse(offset) => { let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.retry_me_else(self, offset)) + try_or_fail!(self, call_policy.retry_me_else(self, offset, global_variables)) } &ChoiceInstruction::DefaultTrustMe(_) => { let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.trust_me(self)) + try_or_fail!(self, call_policy.trust_me(self, global_variables)) } &ChoiceInstruction::RetryMeElse(offset) => { - try_or_fail!(self, call_policy.retry_me_else(self, offset)) + try_or_fail!(self, call_policy.retry_me_else(self, offset, global_variables)) } &ChoiceInstruction::TrustMe(_) => { - try_or_fail!(self, call_policy.trust_me(self)) + try_or_fail!(self, call_policy.trust_me(self, global_variables)) } } } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 6e3bd4eb..d23580ba 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -560,7 +560,11 @@ impl MachineState { match instr { &Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr), &Line::Choice(ref choice_instr) => { - self.execute_choice_instr(choice_instr, &mut policies.call_policy) + self.execute_choice_instr( + choice_instr, + &mut policies.call_policy, + &mut indices.global_variables, + ) } &Line::Cut(ref cut_instr) => { self.execute_cut_instr(cut_instr, &mut policies.cut_policy) @@ -579,10 +583,18 @@ impl MachineState { self.p += 1; } &Line::IndexingCode(ref indexing_lines) => { - self.execute_indexing_instr(indexing_lines, &mut policies.call_policy) + self.execute_indexing_instr( + indexing_lines, + &mut policies.call_policy, + &mut indices.global_variables, + ) } &Line::IndexedChoice(ref choice_instr) => { - self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy) + self.execute_indexed_choice_instr( + choice_instr, + &mut policies.call_policy, + &mut indices.global_variables, + ) } &Line::Query(ref query_instr) => { self.execute_query_instr(&query_instr); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 0d94fd1c..72e6b3a9 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1850,12 +1850,10 @@ impl MachineState { self.copy_term(AttrVarPolicy::StripAttributes); } &SystemClauseType::FetchGlobalVar => { - let key = self[temp_v!(1)]; - - let key = match self.store(self.deref(key)) { + let (key_h, key) = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - atom.clone() + (h, atom.clone()) } else { unreachable!() } @@ -1868,52 +1866,24 @@ impl MachineState { let addr = self[temp_v!(2)]; match indices.global_variables.get_mut(&key) { - Some((ref mut ball, None)) => { - let h = self.heap.h(); - let stub = ball.copy_and_align(h); + Some((ref ball, ref mut loc)) => { + match loc { + Some(ref value_addr) => { + self.unify(addr, *value_addr); + } + loc @ None if !ball.stub.is_empty() => { + let h = self.heap.h(); + let stub = ball.copy_and_align(h); - self.heap.extend(stub.into_iter()); - self.unify(addr, Addr::HeapCell(h)); - } - Some((_, Some(h))) => self.unify(addr, Addr::HeapCell(*h)), - None => self.fail = true, - }; - } - &SystemClauseType::FetchGlobalVarWithOffset => { - let key = self[temp_v!(1)]; + self.heap.extend(stub.into_iter()); + self.unify(addr, Addr::HeapCell(h)); - let key = match self.store(self.deref(key)) { - Addr::Con(h) if self.heap.atom_at(h) => { - if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - atom.clone() - } else { - unreachable!() - } - } - _ => { - unreachable!() - } - }; - - let addr = self[temp_v!(2)]; - - match indices.global_variables.get_mut(&key) { - Some((ref mut ball, ref mut offset @ None)) => { - let h = self.heap.h(); - let stub = ball.copy_and_align(h); - - self.heap.extend(stub.into_iter()); - self.unify(addr, Addr::HeapCell(h)); - - *offset = Some(h); - } - Some((_, Some(h))) => { - let offset = self[temp_v!(3)]; - - self.unify(offset, Addr::Usize(*h)); - - if !self.fail { - self.unify(addr, Addr::HeapCell(*h)); + if !self.fail { + *loc = Some(Addr::HeapCell(h)); + self.trail(TrailRef::BlackboardEntry(key_h)); + } + } + _ => self.fail = true, } } None => self.fail = true, @@ -3572,6 +3542,7 @@ impl MachineState { } } } + /* &SystemClauseType::ResetGlobalVarAtKey => { let key = self[temp_v!(1)]; @@ -3626,6 +3597,7 @@ impl MachineState { } } } + */ &SystemClauseType::ResetAttrVarState => { self.attr_var_init.reset(); } @@ -4539,9 +4511,7 @@ impl MachineState { self.unify(self[temp_v!(3)], property); } &SystemClauseType::StoreGlobalVar => { - let key = self[temp_v!(1)]; - - let key = match self.store(self.deref(key)) { + let key = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { atom.clone() @@ -4567,13 +4537,11 @@ impl MachineState { indices.global_variables.insert(key, (ball, None)); } - &SystemClauseType::StoreGlobalVarWithOffset => { - let key = self[temp_v!(1)]; - - let key = match self.store(self.deref(key)) { + &SystemClauseType::StoreBacktrackableGlobalVar => { + let (key_h, key) = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { - atom.clone() + (h, atom.clone()) } else { unreachable!() } @@ -4583,24 +4551,27 @@ impl MachineState { } }; - let value = self[temp_v!(2)]; - let mut ball = Ball::new(); - let h = self.heap.h(); + let new_value = self.store(self.deref(self[temp_v!(2)])); - ball.boundary = h; - - copy_term( - CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub), - value, - AttrVarPolicy::DeepCopy, - ); - - let stub = ball.copy_and_align(h); - self.heap.extend(stub.into_iter()); - - indices.global_variables.insert(key, (ball, Some(h))); - - self.unify(value, Addr::HeapCell(h)); + match indices.global_variables.get_mut(&key) { + Some((_, ref mut loc)) => { + match loc { + Some(ref mut value) => { + let old_value_loc = self.heap.push(HeapCellValue::Addr(*value)); + self.trail(TrailRef::BlackboardOffset(key_h, old_value_loc)); + *value = new_value; + } + loc @ None => { + self.trail(TrailRef::BlackboardEntry(key_h)); + *loc = Some(new_value); + } + } + } + None => { + self.trail(TrailRef::BlackboardEntry(key_h)); + indices.global_variables.insert(key, (Ball::new(), Some(new_value))); + } + } } &SystemClauseType::Succeed => {} &SystemClauseType::TermAttributedVariables => { From 9067f76bd63f1405d725115bec885cdc94152509 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 22 Feb 2021 18:33:35 -0700 Subject: [PATCH 110/137] no longer delay verify_attributes for cut instructions (#807) --- src/instructions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/instructions.rs b/src/instructions.rs index 98002bce..5cdf472d 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -175,7 +175,6 @@ impl Line { #[inline] pub fn is_head_instr(&self) -> bool { match self { - &Line::Cut(_) => true, &Line::Fact(_) => true, &Line::Query(_) => true, _ => false, From 4d72845c588a5ec1b184f5d77e99bdf3c5445aa2 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 22 Feb 2021 22:39:34 -0700 Subject: [PATCH 111/137] add copy_term_nat/2 (#795) --- src/lib/iso_ext.pl | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/lib/iso_ext.pl b/src/lib/iso_ext.pl index 61a3fa29..7d580497 100644 --- a/src/lib/iso_ext.pl +++ b/src/lib/iso_ext.pl @@ -3,11 +3,19 @@ %% ?- use_module(library(iso_ext)). -:- module(iso_ext, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2, - call_with_inference_limit/3, forall/2, - partial_string/1, partial_string/3, - partial_string_tail/2, setup_call_cleanup/3, - call_nth/2, variant/2]). +:- module(iso_ext, [bb_b_put/2, + bb_get/2, + bb_put/2, + call_cleanup/2, + call_with_inference_limit/3, + forall/2, + partial_string/1, + partial_string/3, + partial_string_tail/2, + setup_call_cleanup/3, + call_nth/2, + variant/2, + copy_term_nat/2]). :- use_module(library(error), [can_be/2, domain_error/3, type_error/3]). @@ -195,3 +203,7 @@ call_nth_nesting(ID) :- ), asserta(i_call_nth_nesting(ID, 0)), asserta(i_call_nth_counter(ID)). + + +copy_term_nat(Source, Dest) :- + '$copy_term_without_attr_vars'(Source, Dest). From b85e260b92b1a9b2e9fdbccb7126a1524e0eb66d Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 25 Feb 2021 22:00:44 +0100 Subject: [PATCH 112/137] ADDED: library(lambda) by Ulrich Neumerkel. Source: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl More information: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord --- src/lib/lambda.pl | 231 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 src/lib/lambda.pl diff --git a/src/lib/lambda.pl b/src/lib/lambda.pl new file mode 100644 index 00000000..d59a5125 --- /dev/null +++ b/src/lib/lambda.pl @@ -0,0 +1,231 @@ +/* + Author: Ulrich Neumerkel + E-mail: ulrich@complang.tuwien.ac.at + Copyright (C): 2009 Ulrich Neumerkel. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Ulrich Neumerkel ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ulrich Neumerkel OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of Ulrich Neumerkel. + + + +*/ + +:- module(lambda, [ + (^)/3, (^)/4, (^)/5, (^)/6, (^)/7, (^)/8, (^)/9, (^)/10, + (\)/1, (\)/2, (\)/3, (\)/4, (\)/5, (\)/6, (\)/7, (\)/8, + (+\)/2, (+\)/3, (+\)/4, (+\)/5, (+\)/6, (+\)/7, (+\)/8, + (+\)/9, op(201,xfx,+\)]). + +/** Lambda expressions + +This library provides lambda expressions to simplify higher order +programming based on call/N. + +Lambda expressions are represented by ordinary Prolog terms. +There are two kinds of lambda expressions: + + Free+\X1^X2^ ..^XN^Goal + + \X1^X2^ ..^XN^Goal + +The second is a shorthand for t+\X1^X2^..^XN^Goal. + +Xi are the parameters. + +Goal is a goal or continuation. Syntax note: Operators within Goal +require parentheses due to the low precedence of the ^ operator. + +Free contains variables that are valid outside the scope of the lambda +expression. They are thus free variables within. + +All other variables of Goal are considered local variables. They must +not appear outside the lambda expression. This restriction is +currently not checked. Violations may lead to unexpected bindings. + +In the following example the parentheses around X>3 are necessary. + +== +?- use_module(library(lambda)). +?- use_module(library(apply)). + +?- maplist(\X^(X>3),[4,5,9]). +true. +== + +In the following X is a variable that is shared by both instances of +the lambda expression. The second query illustrates the cooperation of +continuations and lambdas. The lambda expression is in this case a +continuation expecting a further argument. + +== +?- Xs = [A,B], maplist(X+\Y^dif(X,Y), Xs). +Xs = [A, B], +dif(X, A), +dif(X, B). + +?- Xs = [A,B], maplist(X+\dif(X), Xs). +Xs = [A, B], +dif(X, A), +dif(X, B). +== + +The following queries are all equivalent. To see this, use +the fact f(x,y). +== +?- call(f,A1,A2). +?- call(\X^f(X),A1,A2). +?- call(\X^Y^f(X,Y), A1,A2). +?- call(\X^(X+\Y^f(X,Y)), A1,A2). +?- call(call(f, A1),A2). +?- call(f(A1),A2). +?- f(A1,A2). +A1 = x, +A2 = y. +== + +Further discussions +http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord + +@tbd Static expansion similar to apply_macros. +@author Ulrich Neumerkel +*/ + +:- meta_predicate + ^(?,0,?), + ^(?,1,?,?), + ^(?,2,?,?,?), + ^(?,3,?,?,?,?), + ^(?,4,?,?,?,?,?), + ^(?,5,?,?,?,?,?,?), + ^(?,6,?,?,?,?,?,?,?), + ^(?,7,?,?,?,?,?,?,?,?), + \(0), + \(1,?), + \(2,?,?), + \(3,?,?,?), + \(4,?,?,?,?), + \(5,?,?,?,?,?), + \(6,?,?,?,?,?,?), + \(7,?,?,?,?,?,?,?), + +\(?,0), + +\(?,1,?), + +\(?,2,?,?), + +\(?,3,?,?,?), + +\(?,4,?,?,?,?), + +\(?,5,?,?,?,?,?), + +\(?,6,?,?,?,?,?,?), + +\(?,7,?,?,?,?,?,?,?). + +:- meta_predicate no_hat_call(0). + +^(V1,C_0,V1) :- + no_hat_call(C_0). +^(V1,C_1,V1,V2) :- + call(C_1,V2). +^(V1,C_2,V1,V2,V3) :- + call(C_2,V2,V3). +^(V1,C_3,V1,V2,V3,V4) :- + call(C_3,V2,V3,V4). +^(V1,C_4,V1,V2,V3,V4,V5) :- + call(C_4,V2,V3,V4,V5). +^(V1,C_5,V1,V2,V3,V4,V5,V6) :- + call(C_5,V2,V3,V4,V5,V6). +^(V1,C_6,V1,V2,V3,V4,V5,V6,V7) :- + call(C_6,V2,V3,V4,V5,V6,V7). +^(V1,C_7,V1,V2,V3,V4,V5,V6,V7,V8) :- + call(C_7,V2,V3,V4,V5,V6,V7,V8). + +\(FC_0) :- + copy_term_nat(FC_0,C_0), + no_hat_call(C_0). +\(FC_1,V1) :- + copy_term_nat(FC_1,C_1), + call(C_1,V1). +\(FC_2,V1,V2) :- + copy_term_nat(FC_2,C_2), + call(C_2,V1,V2). +\(FC_3,V1,V2,V3) :- + copy_term_nat(FC_3,C_3), + call(C_3,V1,V2,V3). +\(FC_4,V1,V2,V3,V4) :- + copy_term_nat(FC_4,C_4), + call(C_4,V1,V2,V3,V4). +\(FC_5,V1,V2,V3,V4,V5) :- + copy_term_nat(FC_5,C_5), + call(C_5,V1,V2,V3,V4,V5). +\(FC_6,V1,V2,V3,V4,V5,V6) :- + copy_term_nat(FC_6,C_6), + call(C_6,V1,V2,V3,V4,V5,V6). +\(FC_7,V1,V2,V3,V4,V5,V6,V7) :- + copy_term_nat(FC_7,C_7), + call(C_7,V1,V2,V3,V4,V5,V6,V7). + + ++\(GV,FC_0) :- + copy_term_nat(GV+FC_0,GV+C_0), + no_hat_call(C_0). ++\(GV,FC_1,V1) :- + copy_term_nat(GV+FC_1,GV+C_1), + call(C_1,V1). ++\(GV,FC_2,V1,V2) :- + copy_term_nat(GV+FC_2,GV+C_2), + call(C_2,V1,V2). ++\(GV,FC_3,V1,V2,V3) :- + copy_term_nat(GV+FC_3,GV+C_3), + call(C_3,V1,V2,V3). ++\(GV,FC_4,V1,V2,V3,V4) :- + copy_term_nat(GV+FC_4,GV+C_4), + call(C_4,V1,V2,V3,V4). ++\(GV,FC_5,V1,V2,V3,V4,V5) :- + copy_term_nat(GV+FC_5,GV+C_5), + call(C_5,V1,V2,V3,V4,V5). ++\(GV,FC_6,V1,V2,V3,V4,V5,V6) :- + copy_term_nat(GV+FC_6,GV+C_6), + call(C_6,V1,V2,V3,V4,V5,V6). ++\(GV,FC_7,V1,V2,V3,V4,V5,V6,V7) :- + copy_term_nat(GV+FC_7,GV+C_7), + call(C_7,V1,V2,V3,V4,V5,V6,V7). + + +%% no_hat_call(:Goal_0) +% +% Like call, but issues an error for a goal (^)/2. Such goals are +% likely the result of an insufficient number of arguments. + +no_hat_call(MGoal_0) :- + strip_module(MGoal_0, _, Goal_0), + ( nonvar(Goal_0), + Goal_0 = (_^_) + -> throw( + error( + existence_error(lambda_parameter,MGoal_0), + _)) + ; call(MGoal_0) + ). + +% I would like to replace this by: +% V1^Goal :- throw(error(existence_error(lambda_parameter,V1^Goal),_)). From dfb60ec2ed3675ab0d54ad2ebcea4c51abce81e5 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 25 Feb 2021 22:02:51 +0100 Subject: [PATCH 113/137] use individual meta_predicate/1 declarations --- src/lib/lambda.pl | 49 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/lib/lambda.pl b/src/lib/lambda.pl index d59a5125..03d9db89 100644 --- a/src/lib/lambda.pl +++ b/src/lib/lambda.pl @@ -114,31 +114,30 @@ http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord @author Ulrich Neumerkel */ -:- meta_predicate - ^(?,0,?), - ^(?,1,?,?), - ^(?,2,?,?,?), - ^(?,3,?,?,?,?), - ^(?,4,?,?,?,?,?), - ^(?,5,?,?,?,?,?,?), - ^(?,6,?,?,?,?,?,?,?), - ^(?,7,?,?,?,?,?,?,?,?), - \(0), - \(1,?), - \(2,?,?), - \(3,?,?,?), - \(4,?,?,?,?), - \(5,?,?,?,?,?), - \(6,?,?,?,?,?,?), - \(7,?,?,?,?,?,?,?), - +\(?,0), - +\(?,1,?), - +\(?,2,?,?), - +\(?,3,?,?,?), - +\(?,4,?,?,?,?), - +\(?,5,?,?,?,?,?), - +\(?,6,?,?,?,?,?,?), - +\(?,7,?,?,?,?,?,?,?). +:- meta_predicate ^(?,0,?). +:- meta_predicate ^(?,1,?,?). +:- meta_predicate ^(?,2,?,?,?). +:- meta_predicate ^(?,3,?,?,?,?). +:- meta_predicate ^(?,4,?,?,?,?,?). +:- meta_predicate ^(?,5,?,?,?,?,?,?). +:- meta_predicate ^(?,6,?,?,?,?,?,?,?). +:- meta_predicate ^(?,7,?,?,?,?,?,?,?,?). +:- meta_predicate \(0). +:- meta_predicate \(1,?). +:- meta_predicate \(2,?,?). +:- meta_predicate \(3,?,?,?). +:- meta_predicate \(4,?,?,?,?). +:- meta_predicate \(5,?,?,?,?,?). +:- meta_predicate \(6,?,?,?,?,?,?). +:- meta_predicate \(7,?,?,?,?,?,?,?). +:- meta_predicate +\(?,0). +:- meta_predicate +\(?,1,?). +:- meta_predicate +\(?,2,?,?). +:- meta_predicate +\(?,3,?,?,?). +:- meta_predicate +\(?,4,?,?,?,?). +:- meta_predicate +\(?,5,?,?,?,?,?). +:- meta_predicate +\(?,6,?,?,?,?,?,?). +:- meta_predicate +\(?,7,?,?,?,?,?,?,?). :- meta_predicate no_hat_call(0). From e0c98a5c7920f2d858cc6ed218a24bc39b5f47b6 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 25 Feb 2021 22:06:09 +0100 Subject: [PATCH 114/137] adapt libraries and toplevel output to Scryer Prolog --- src/lib/lambda.pl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/lib/lambda.pl b/src/lib/lambda.pl index 03d9db89..56332255 100644 --- a/src/lib/lambda.pl +++ b/src/lib/lambda.pl @@ -40,6 +40,8 @@ official policies, either expressed or implied, of Ulrich Neumerkel. (+\)/2, (+\)/3, (+\)/4, (+\)/5, (+\)/6, (+\)/7, (+\)/8, (+\)/9, op(201,xfx,+\)]). +:- use_module(library(iso_ext)). + /** Lambda expressions This library provides lambda expressions to simplify higher order @@ -70,10 +72,10 @@ In the following example the parentheses around X>3 are necessary. == ?- use_module(library(lambda)). -?- use_module(library(apply)). +?- use_module(library(lists)). ?- maplist(\X^(X>3),[4,5,9]). -true. + true. == In the following X is a variable that is shared by both instances of @@ -82,15 +84,14 @@ continuations and lambdas. The lambda expression is in this case a continuation expecting a further argument. == +?- use_module(library(dif)). + true. + ?- Xs = [A,B], maplist(X+\Y^dif(X,Y), Xs). -Xs = [A, B], -dif(X, A), -dif(X, B). + Xs = [A,B], dif:dif(X,A), dif:dif(X,B). ?- Xs = [A,B], maplist(X+\dif(X), Xs). -Xs = [A, B], -dif(X, A), -dif(X, B). + Xs = [A,B], dif:dif(X,A), dif:dif(X,B). == The following queries are all equivalent. To see this, use @@ -103,8 +104,7 @@ the fact f(x,y). ?- call(call(f, A1),A2). ?- call(f(A1),A2). ?- f(A1,A2). -A1 = x, -A2 = y. + A1 = x, A2 = y. == Further discussions From 2c1b7e3b14bb4f9473f517856d4e14fece21124c Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 18 Feb 2021 20:33:27 +0100 Subject: [PATCH 115/137] remove unused attribute_goal/2 --- src/lib/clpz.pl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index ead80546..797aace8 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -7590,10 +7590,6 @@ clpz_gcc_occurred:attribute_goals(_) --> []. clpz_relation:attribute_goals(_) --> []. -attribute_goal(Var, Goal) :- - phrase(attribute_goals(Var), Goals), - list_goal(Goals, Goal). - attributes_goals([]) --> []. attributes_goals([propagator(P, State)|As]) --> ( { ground(State) } -> [] From aecbd0eda3adf90c0c5009ef6f7a5dab69a4ac28 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 25 Feb 2021 21:45:06 +0100 Subject: [PATCH 116/137] omit internal residual goals for global_cardinality/2 --- src/lib/clpz.pl | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/lib/clpz.pl b/src/lib/clpz.pl index 797aace8..3012af78 100644 --- a/src/lib/clpz.pl +++ b/src/lib/clpz.pl @@ -7580,16 +7580,6 @@ attribute_goals(X) --> attributes_goals(Ps), { del_attr(X, clpz) }. -clpz_aux:attribute_goals(_) --> []. - -clpz_gcc_vs:attribute_goals(_) --> []. - -clpz_gcc_num:attribute_goals(_) --> []. - -clpz_gcc_occurred:attribute_goals(_) --> []. - -clpz_relation:attribute_goals(_) --> []. - attributes_goals([]) --> []. attributes_goals([propagator(P, State)|As]) --> ( { ground(State) } -> [] @@ -7652,7 +7642,9 @@ attribute_goal_(pelement(N,Is,V)) --> [element(N, Is, V)]. attribute_goal_(pgcc(Vs, Pairs, _)) --> [global_cardinality(Vs, Pairs)]. attribute_goal_(pgcc_single(_,_)) --> []. attribute_goal_(pgcc_check_single(_)) --> []. -attribute_goal_(pgcc_check(_)) --> []. +attribute_goal_(pgcc_check(Pairs)) --> + { pairs_values(Pairs, Nums), + maplist(gcc_done, Nums) }. attribute_goal_(pcircuit(Vs)) --> [circuit(Vs)]. attribute_goal_(pserialized(_,_,_,_,O)) --> original_goal(O). attribute_goal_(rel_tuple(R, Tuple)) --> From dd64268bc721f33e03271ddc76862639705208b1 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 25 Feb 2021 22:40:31 +0100 Subject: [PATCH 117/137] add entry for library(lambda) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2c86d620..c15c6b8b 100644 --- a/README.md +++ b/README.md @@ -447,6 +447,8 @@ The modules that ship with Scryer Prolog are also called file, reading lazily only as much as is needed. Due to the compact internal string representation, also extremely large files can be efficiently processed with Scryer Prolog in this way. +* [`lambda`](src/lib/lambda.pl) + Lambda expressions to simplify higher order programming. * [`charsio`](src/lib/charsio.pl) Various predicates that are useful for parsing and reasoning about characters, notably `char_type/2` to classify characters according to their type, and conversion From 064d261357f7aa27c96be561b8b0eb22b57074ae Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 27 Feb 2021 22:51:32 -0700 Subject: [PATCH 118/137] implement logical update semantics for dynamic database predicates --- src/codegen.rs | 181 ++++--- src/indexing.rs | 795 +++++++++++++++++++++++------- src/instructions.rs | 113 ++++- src/lib/builtins.pl | 58 +-- src/machine/code_repo.rs | 98 +++- src/machine/code_walker.rs | 8 + src/machine/compile.rs | 515 ++++++++++++++++--- src/machine/load_state.rs | 12 +- src/machine/loader.rs | 51 +- src/machine/machine_indices.rs | 34 +- src/machine/machine_state.rs | 20 +- src/machine/machine_state_impl.rs | 376 +++++++++++++- src/machine/mod.rs | 11 +- src/machine/system_calls.rs | 12 +- src/macros.rs | 1 + src/write.rs | 37 +- 16 files changed, 1904 insertions(+), 418 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index cb9c4a97..7a5d8ba3 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -21,24 +21,6 @@ use std::cell::Cell; use std::collections::VecDeque; use std::rc::Rc; -#[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)] pub struct ConjunctInfo<'a> { pub perm_vs: VariableFixtures<'a>, @@ -109,16 +91,93 @@ impl<'a> ConjunctInfo<'a> { #[derive(Clone, Copy, Debug)] pub struct CodeGenSettings { + pub global_clock_tick: Option, 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, + pub fn is_dynamic(&self) -> bool { + self.global_clock_tick.is_some() + } + + #[inline] + pub fn internal_try_me_else(&self, offset: usize) -> ChoiceInstruction { + if let Some(global_clock_time) = self.global_clock_tick { + ChoiceInstruction::DynamicInternalElse( + global_clock_time, + Death::Infinity, + if offset == 0 { NextOrFail::Next(0) } else { NextOrFail::Next(offset) }, + ) + } else { + ChoiceInstruction::TryMeElse(offset) + } + } + + pub fn try_me_else(&self, offset: usize) -> ChoiceInstruction { + if let Some(global_clock_tick) = self.global_clock_tick { + ChoiceInstruction::DynamicElse( + global_clock_tick, + Death::Infinity, + if offset == 0 { NextOrFail::Next(0) } else { NextOrFail::Next(offset) }, + ) + } else { + ChoiceInstruction::TryMeElse(offset) + } + } + + pub fn internal_retry_me_else(&self, offset: usize) -> ChoiceInstruction { + if let Some(global_clock_tick) = self.global_clock_tick { + ChoiceInstruction::DynamicInternalElse( + global_clock_tick, + Death::Infinity, + if offset == 0 { NextOrFail::Next(0) } else { NextOrFail::Next(offset) }, + ) + } else { + ChoiceInstruction::RetryMeElse(offset) + } + } + + pub fn retry_me_else(&self, offset: usize) -> ChoiceInstruction { + if let Some(global_clock_tick) = self.global_clock_tick { + ChoiceInstruction::DynamicElse( + global_clock_tick, + Death::Infinity, + if offset == 0 { NextOrFail::Next(0) } else { NextOrFail::Next(offset) }, + ) + } else if self.non_counted_bt { + ChoiceInstruction::DefaultRetryMeElse(offset) + } else { + ChoiceInstruction::RetryMeElse(offset) + } + } + + pub fn internal_trust_me(&self) -> ChoiceInstruction { + if let Some(global_clock_tick) = self.global_clock_tick { + ChoiceInstruction::DynamicInternalElse( + global_clock_tick, + Death::Infinity, + NextOrFail::Fail(0), + ) + } else if self.non_counted_bt { + ChoiceInstruction::DefaultTrustMe(0) + } else { + ChoiceInstruction::TrustMe(0) + } + } + + pub fn trust_me(&self) -> ChoiceInstruction { + if let Some(global_clock_tick) = self.global_clock_tick { + ChoiceInstruction::DynamicElse( + global_clock_tick, + Death::Infinity, + NextOrFail::Fail(0), + ) + } else if self.non_counted_bt { + ChoiceInstruction::DefaultTrustMe(0) + } else { + ChoiceInstruction::TrustMe(0) } } } @@ -128,8 +187,7 @@ pub struct CodeGenerator { atom_tbl: TabledData, marker: TermMarker, pub var_count: IndexMap, usize>, - non_counted_bt: bool, - is_extensible: bool, + settings: CodeGenSettings, pub skeleton: PredicateSkeleton, pub jmp_by_locs: Vec, global_jmp_by_locs_offset: usize, @@ -141,8 +199,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { atom_tbl, marker: Allocator::new(), var_count: IndexMap::new(), - non_counted_bt: settings.non_counted_bt, - is_extensible: settings.is_extensible, + settings, skeleton: PredicateSkeleton::new(), jmp_by_locs: vec![], global_jmp_by_locs_offset: 0, @@ -889,27 +946,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { self.add_conditional_call(code, term, num_perm_vars_left); } - /* - pub fn compile_query(&mut self, query: &'a Vec) -> Result { - let iter = ChunkedIterator::from_term_sequence(query); - let conjunct_info = self.collect_var_data(iter); - - let mut code = Vec::new(); - self.compile_seq_prelude(&conjunct_info, &mut code); - - let iter = ChunkedIterator::from_term_sequence(query); - self.compile_seq(iter, &conjunct_info, &mut code, true)?; - - conjunct_info.mark_unsafe_vars(UnsafeVarMarker::new(), &mut code); - - if let Some(query_term) = query.last() { - Self::compile_cleanup(&mut code, &conjunct_info, query_term); - } - - Ok(code) - } - */ - #[inline] fn increment_jmp_by_locs_by(&mut self, incr: usize) { let offset = self.global_jmp_by_locs_offset; @@ -986,15 +1022,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { subseqs } - fn compile_pred_subseq<'b: 'a>( + fn compile_pred_subseq<'b: 'a, I: Indexer>( &mut self, clauses: &'b [PredicateClause], optimal_index: usize, ) -> Result { 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 mut code_offsets = CodeOffsets::new( + self.atom_tbl.clone(), + I::new(), + optimal_index + 1, + ); + let mut skip_stub_try_me_else = false; let jmp_by_locs_len = self.jmp_by_locs.len(); for (i, clause) in clauses.iter().enumerate() { @@ -1010,13 +1050,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { if clauses.len() > 1 { let choice = match i { - 0 => ChoiceInstruction::TryMeElse(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), + 0 => self.settings.internal_try_me_else(clause_code.len() + 1), + //ChoiceInstruction::TryMeElse(clause_code.len() + 1), + _ if i == clauses.len() - 1 => self.settings.internal_trust_me(), + _ => self.settings.internal_retry_me_else(clause_code.len() + 1), }; code.push_back(Line::Choice(choice)); - } else if self.is_extensible { + } else if self.settings.is_extensible { /* generate stub choice instructions for extensible predicates. if predicates are added to either the @@ -1028,8 +1069,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { over them. */ - code.push_front(Line::Choice(ChoiceInstruction::TryMeElse(0))); - skip_stub_try_me_else = true; + code.push_front(Line::Choice(self.settings.internal_try_me_else(0))); + //Line::Choice(ChoiceInstruction::TryMeElse(0))); + skip_stub_try_me_else = !self.settings.is_dynamic(); //true; } let arg = match clause.args() { @@ -1045,7 +1087,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { code_offsets.index_term(arg, index, &mut clause_index_info); } - if !skip_stub_try_me_else { + if !(clauses.len() == 1 && self.settings.is_extensible) { self.increment_jmp_by_locs_by(code.len()); } @@ -1065,7 +1107,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } else { self.increment_jmp_by_locs_by(1); } - } else if skip_stub_try_me_else { + } else if clauses.len() == 1 && self.settings.is_extensible { + // the condition is the value of skip_stub_try_me_else, which is + // true if the predicate is not dynamic. This operation must apply + // to dynamic predicates also, though. + // remove the TryMeElse(0). code.pop_front(); } @@ -1089,22 +1135,27 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { for (l, r) in split_pred { let skel_lower_bound = self.skeleton.clauses.len(); - let code_segment = self.compile_pred_subseq(&clauses[l..r], optimal_index)?; + let code_segment = if self.settings.is_dynamic() { + self.compile_pred_subseq::(&clauses[l..r], optimal_index)? + } else { + 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() => trust_me(self.non_counted_bt), - _ => retry_me_else(code_segment.len() + 1, self.non_counted_bt), + 0 => self.settings.try_me_else(code_segment.len() + 1), + _ if r == clauses.len() => self.settings.trust_me(), + _ => self.settings.retry_me_else(code_segment.len() + 1), }; code.push(Line::Choice(choice)); - } else if self.is_extensible { - code.push(Line::Choice(ChoiceInstruction::TryMeElse(0))); + } else if self.settings.is_extensible { + code.push(Line::Choice(self.settings.try_me_else(0))); } - if self.is_extensible { + if self.settings.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() { diff --git a/src/indexing.rs b/src/indexing.rs index 49a3afdf..754cc57d 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -13,11 +13,13 @@ use slice_deque::{sdeq, SliceDeque}; use std::convert::TryFrom; use std::hash::Hash; use std::iter::once; +use std::mem; use std::rc::Rc; #[derive(Debug, Clone, Copy)] pub enum IndexingCodePtr { External(usize), // the index points past the indexing instruction prelude. + DynamicExternal(usize), // an External index of a dynamic predicate, potentially invalidated by retraction. Fail, Internal(usize), // the index points into the indexing instruction prelude. } @@ -66,10 +68,10 @@ fn search_skeleton_for_first_key_type( struct IndexingCodeMergingPtr<'a> { skeleton: &'a mut [ClauseIndexInfo], - // merged_clause_index: usize, indexing_code: &'a mut Vec, offset: usize, append_or_prepend: AppendOrPrepend, + is_dynamic: bool, } impl<'a> IndexingCodeMergingPtr<'a> { @@ -79,11 +81,23 @@ impl<'a> IndexingCodeMergingPtr<'a> { indexing_code: &'a mut Vec, append_or_prepend: AppendOrPrepend, ) -> Self { + let is_dynamic = match &indexing_code[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => { + match v { + IndexingCodePtr::External(_) => false, + IndexingCodePtr::DynamicExternal(_) => true, + _ => unreachable!() + } + } + _ => unreachable!() + }; + Self { skeleton, indexing_code, offset: 0, append_or_prepend, + is_dynamic, } } @@ -106,11 +120,12 @@ impl<'a> IndexingCodeMergingPtr<'a> { } if let IndexingCodePtr::Internal(_) = constant_ptr { + let last_index = self.indexing_code.len(); + 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 { self.offset = self.indexing_code.len(); @@ -121,7 +136,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } - fn add_indexed_choice_for_constant( + fn add_static_indexed_choice_for_constant( &mut self, external: usize, constant: Constant, @@ -140,8 +155,35 @@ impl<'a> IndexingCodeMergingPtr<'a> { }; let indexing_code_len = self.indexing_code.len(); - self.indexing_code - .push(IndexingLine::IndexedChoice(third_level_index)); + self.indexing_code.push(IndexingLine::IndexedChoice(third_level_index)); + + match &mut self.indexing_code[self.offset] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => { + constants.insert( + constant, + IndexingCodePtr::Internal(indexing_code_len - self.offset), + ); + } + _ => { + unreachable!() + } + } + } + + fn add_dynamic_indexed_choice_for_constant( + &mut self, + external: usize, + constant: Constant, + index: usize, + ) { + let third_level_index = if self.append_or_prepend.is_append() { + sdeq![external, index] + } else { + sdeq![index, external] + }; + + let indexing_code_len = self.indexing_code.len(); + self.indexing_code.push(IndexingLine::DynamicIndexedChoice(third_level_index)); match &mut self.indexing_code[self.offset] { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref mut constants)) => { @@ -168,6 +210,14 @@ impl<'a> IndexingCodeMergingPtr<'a> { uncap_choice_seq_with_try(indexed_choice_instrs); indexed_choice_instrs.push_front(IndexedChoiceInstruction::Try(index)); } + IndexingLine::DynamicIndexedChoice(ref mut indexed_choice_instrs) + if self.append_or_prepend.is_append() => + { + indexed_choice_instrs.push_back(index); + } + IndexingLine::DynamicIndexedChoice(ref mut indexed_choice_instrs) => { + indexed_choice_instrs.push_front(index); + } _ => { unreachable!() } @@ -186,11 +236,15 @@ impl<'a> IndexingCodeMergingPtr<'a> { match &mut self.indexing_code[self.offset] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { match *c { + IndexingCodePtr::Fail if self.is_dynamic => { + *c = IndexingCodePtr::DynamicExternal(index); + break; + } IndexingCodePtr::Fail => { *c = IndexingCodePtr::External(index); break; } - IndexingCodePtr::External(_) => { + IndexingCodePtr::DynamicExternal(_) | IndexingCodePtr::External(_) => { let mut constants = IndexMap::new(); constants.insert(orig_constant.clone(), *c); @@ -209,12 +263,23 @@ impl<'a> IndexingCodeMergingPtr<'a> { } IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => { match constants.get(&overlapping_constant).cloned() { + None | Some(IndexingCodePtr::Fail) if self.is_dynamic => { + constants.insert( + overlapping_constant, + IndexingCodePtr::DynamicExternal(index), + ); + } None | Some(IndexingCodePtr::Fail) => { - constants - .insert(overlapping_constant, IndexingCodePtr::External(index)); + constants.insert( + overlapping_constant, + IndexingCodePtr::External(index), + ); + } + Some(IndexingCodePtr::DynamicExternal(o)) => { + self.add_dynamic_indexed_choice_for_constant(o, overlapping_constant, index); } Some(IndexingCodePtr::External(o)) => { - self.add_indexed_choice_for_constant(o, overlapping_constant, index); + self.add_static_indexed_choice_for_constant(o, overlapping_constant, index); } Some(IndexingCodePtr::Internal(o)) => { self.offset += o; @@ -224,7 +289,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { break; } - IndexingLine::IndexedChoice(_) => { + IndexingLine::IndexedChoice(_) | IndexingLine::DynamicIndexedChoice(_) => { self.internalize_constant(IndexingCodePtr::Internal( indexing_code_len - self.offset, )); @@ -243,6 +308,10 @@ impl<'a> IndexingCodeMergingPtr<'a> { match &mut self.indexing_code[self.offset] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { match *c { + IndexingCodePtr::Fail if self.is_dynamic => { + *c = IndexingCodePtr::DynamicExternal(index); + break; + } IndexingCodePtr::Fail => { *c = IndexingCodePtr::External(index); break; @@ -251,6 +320,10 @@ impl<'a> IndexingCodeMergingPtr<'a> { *c = IndexingCodePtr::Internal(indexing_code_len - self.offset); self.internalize_constant(IndexingCodePtr::External(o)); } + IndexingCodePtr::DynamicExternal(o) => { + *c = IndexingCodePtr::Internal(indexing_code_len - self.offset); + self.internalize_constant(IndexingCodePtr::DynamicExternal(o)); + } IndexingCodePtr::Internal(o) => { self.offset += o; } @@ -258,11 +331,17 @@ impl<'a> IndexingCodeMergingPtr<'a> { } IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(constants)) => { match constants.get(&constant).cloned() { + None | Some(IndexingCodePtr::Fail) if self.is_dynamic => { + constants.insert(constant, IndexingCodePtr::DynamicExternal(index)); + } None | Some(IndexingCodePtr::Fail) => { constants.insert(constant, IndexingCodePtr::External(index)); } + Some(IndexingCodePtr::DynamicExternal(o)) => { + self.add_dynamic_indexed_choice_for_constant(o, constant, index); + } Some(IndexingCodePtr::External(o)) => { - self.add_indexed_choice_for_constant(o, constant, index); + self.add_static_indexed_choice_for_constant(o, constant, index); } Some(IndexingCodePtr::Internal(o)) => { self.offset += o; @@ -272,7 +351,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { break; } - IndexingLine::IndexedChoice(_) => { + IndexingLine::IndexedChoice(_) | IndexingLine::DynamicIndexedChoice(_) => { self.internalize_constant(IndexingCodePtr::Internal( indexing_code_len - self.offset, )); @@ -303,11 +382,12 @@ impl<'a> IndexingCodeMergingPtr<'a> { } if let IndexingCodePtr::Internal(_) = structure_ptr { + let last_index = self.indexing_code.len(); + 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(); @@ -318,7 +398,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } - fn add_indexed_choice_for_structure( + fn add_static_indexed_choice_for_structure( &mut self, external: usize, key: PredicateKey, @@ -353,6 +433,34 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } + fn add_dynamic_indexed_choice_for_structure( + &mut self, + external: usize, + key: PredicateKey, + index: usize, + ) { + let third_level_index = if self.append_or_prepend.is_append() { + sdeq![external, index] + } else { + sdeq![index, external] + }; + + let indexing_code_len = self.indexing_code.len(); + self.indexing_code.push(IndexingLine::DynamicIndexedChoice(third_level_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), + ); + } + _ => { + unreachable!() + } + } + } + fn index_structure(&mut self, key: PredicateKey, index: usize) { loop { let indexing_code_len = self.indexing_code.len(); @@ -365,10 +473,18 @@ impl<'a> IndexingCodeMergingPtr<'a> { _, ref mut s, )) => match *s { + IndexingCodePtr::Fail if self.is_dynamic => { + *s = IndexingCodePtr::DynamicExternal(index); + break; + } IndexingCodePtr::Fail => { *s = IndexingCodePtr::External(index); break; } + IndexingCodePtr::DynamicExternal(o) => { + *s = IndexingCodePtr::Internal(indexing_code_len - self.offset); + self.internalize_structure(IndexingCodePtr::DynamicExternal(o)); + } IndexingCodePtr::External(o) => { *s = IndexingCodePtr::Internal(indexing_code_len - self.offset); self.internalize_structure(IndexingCodePtr::External(o)); @@ -379,11 +495,17 @@ impl<'a> IndexingCodeMergingPtr<'a> { }, IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(structures)) => { match structures.get(&key).cloned() { + None | Some(IndexingCodePtr::Fail) if self.is_dynamic => { + structures.insert(key, IndexingCodePtr::DynamicExternal(index)); + } None | Some(IndexingCodePtr::Fail) => { structures.insert(key, IndexingCodePtr::External(index)); } + Some(IndexingCodePtr::DynamicExternal(o)) => { + self.add_dynamic_indexed_choice_for_structure(o, key, index); + } Some(IndexingCodePtr::External(o)) => { - self.add_indexed_choice_for_structure(o, key, index); + self.add_static_indexed_choice_for_structure(o, key, index); } Some(IndexingCodePtr::Internal(o)) => { self.offset += o; @@ -393,7 +515,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { break; } - IndexingLine::IndexedChoice(_) => { + IndexingLine::IndexedChoice(_) | IndexingLine::DynamicIndexedChoice(_) => { // replace this value, at self.offset, with // SwitchOnStructures, and swap this IndexedChoice // vector to the end of self.indexing_code. @@ -414,9 +536,24 @@ impl<'a> IndexingCodeMergingPtr<'a> { match &mut self.indexing_code[self.offset] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)) => { match *l { + IndexingCodePtr::Fail if self.is_dynamic => { + *l = IndexingCodePtr::DynamicExternal(index); + } IndexingCodePtr::Fail => { *l = IndexingCodePtr::External(index); } + IndexingCodePtr::DynamicExternal(o) => { + *l = IndexingCodePtr::Internal(indexing_code_len - self.offset); + + let third_level_index = if self.append_or_prepend.is_append() { + sdeq![o, index] + } else { + sdeq![index, o] + }; + + self.indexing_code + .push(IndexingLine::DynamicIndexedChoice(third_level_index)); + } IndexingCodePtr::External(o) => { *l = IndexingCodePtr::Internal(indexing_code_len - self.offset); @@ -459,8 +596,11 @@ pub fn merge_clause_index( AppendOrPrepend::Prepend => skeleton.first_mut().unwrap().opt_arg_index_key.take(), }; - let mut merging_ptr = - IndexingCodeMergingPtr::new(skeleton, target_indexing_code, append_or_prepend); + 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) => { @@ -498,17 +638,6 @@ pub fn merge_clause_index( } } -#[inline] -fn remove_instruction_with_offset(code: &mut SliceDeque, 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], @@ -521,7 +650,7 @@ pub fn remove_constant_indices( match &mut indexing_code[index] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, ref mut c, ..)) => { match *c { - IndexingCodePtr::External(_) => { + IndexingCodePtr::DynamicExternal(_) | IndexingCodePtr::External(_) => { *c = IndexingCodePtr::Fail; return; } @@ -541,7 +670,6 @@ pub fn remove_constant_indices( 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( @@ -550,7 +678,9 @@ pub fn remove_constant_indices( constants_index = index; match constants.get(constant).cloned() { - Some(IndexingCodePtr::External(_)) | Some(IndexingCodePtr::Fail) => { + Some(IndexingCodePtr::DynamicExternal(_)) | + Some(IndexingCodePtr::External(_)) | + Some(IndexingCodePtr::Fail) => { constants.remove(constant); break; } @@ -563,29 +693,61 @@ pub fn remove_constant_indices( } } IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => { - remove_instruction_with_offset(indexed_choice_instrs, offset); + StaticCodeIndices::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(), - ); + if let Some(indexed_choice_instr) = indexed_choice_instrs.pop_back() { + let ext = IndexingCodePtr::External( + indexed_choice_instr.offset() + ); - match &mut indexing_code[constants_index] { - IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( - _, - _, - ref mut c, - .., - )) => { - *c = ext; + 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!() + } } - IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant( - ref mut constants, - )) => { - constants.insert(constant.clone(), ext); - } - _ => { - unreachable!() + } + } + + break; + } + IndexingLine::DynamicIndexedChoice(ref mut indexed_choice_instrs) => { + DynamicCodeIndices::remove_instruction_with_offset(indexed_choice_instrs, offset); + + if indexed_choice_instrs.len() == 1 { + if let Some(indexed_choice_instr) = indexed_choice_instrs.pop_back() { + let ext = IndexingCodePtr::DynamicExternal(indexed_choice_instr); + + 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!() + } } } } @@ -627,7 +789,7 @@ pub fn remove_structure_index( match &mut indexing_code[index] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, _, _, ref mut s)) => { match *s { - IndexingCodePtr::External(_) => { + IndexingCodePtr::DynamicExternal(_) | IndexingCodePtr::External(_) => { *s = IndexingCodePtr::Fail; return; } @@ -652,7 +814,7 @@ pub fn remove_structure_index( structures_index = index; match structures.get(&(name.clone(), arity)).cloned() { - Some(IndexingCodePtr::External(_)) => { + Some(IndexingCodePtr::DynamicExternal(_)) | Some(IndexingCodePtr::External(_)) => { structures.remove(&(name.clone(), arity)); break; } @@ -665,30 +827,61 @@ pub fn remove_structure_index( } } IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => { - remove_instruction_with_offset(indexed_choice_instrs, offset); + StaticCodeIndices::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(), - ); + if let Some(indexed_choice_instr) = indexed_choice_instrs.pop_back() { + let ext = IndexingCodePtr::External(indexed_choice_instr.offset()); - match &mut indexing_code[structures_index] { - IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( - _, - _, - _, - _, - ref mut s, - )) => { - *s = ext; + 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!() + } } - IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure( - ref mut structures, - )) => { - structures.insert((name.clone(), arity), ext); - } - _ => { - unreachable!() + } + } + + break; + } + IndexingLine::DynamicIndexedChoice(ref mut indexed_choice_instrs) => { + DynamicCodeIndices::remove_instruction_with_offset(indexed_choice_instrs, offset); + + if indexed_choice_instrs.len() == 1 { + if let Some(indexed_choice_instr) = indexed_choice_instrs.pop_back() { + let ext = IndexingCodePtr::DynamicExternal(indexed_choice_instr); + + 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!() + } } } } @@ -730,7 +923,7 @@ pub fn remove_list_index(indexing_code: &mut Vec, offset: usize) { match &mut indexing_code[index] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, _, ref mut l, _)) => { match *l { - IndexingCodePtr::External(_) => { + IndexingCodePtr::DynamicExternal(_) | IndexingCodePtr::External(_) => { *l = IndexingCodePtr::Fail; return; } @@ -749,24 +942,49 @@ pub fn remove_list_index(indexing_code: &mut Vec, offset: usize) { match &mut indexing_code[index] { IndexingLine::IndexedChoice(ref mut indexed_choice_instrs) => { - remove_instruction_with_offset(indexed_choice_instrs, offset); + StaticCodeIndices::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()); + if let Some(indexed_choice_instr) = indexed_choice_instrs.pop_back() { + let ext = IndexingCodePtr::External(indexed_choice_instr.offset()); - match &mut indexing_code[0] { - IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( - _, - _, - _, - ref mut l, - _, - )) => { - *l = ext; + match &mut indexing_code[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( + _, + _, + _, + ref mut l, + _, + )) => { + *l = ext; + } + _ => { + unreachable!() + } } - _ => { - unreachable!() + } + } + } + IndexingLine::DynamicIndexedChoice(ref mut indexed_choice_instrs) => { + DynamicCodeIndices::remove_instruction_with_offset(indexed_choice_instrs, offset); + + if indexed_choice_instrs.len() == 1 { + if let Some(indexed_choice_instr) = indexed_choice_instrs.pop_back() { + let ext = IndexingCodePtr::DynamicExternal(indexed_choice_instr); + + match &mut indexing_code[0] { + IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm( + _, + _, + _, + ref mut l, + _, + )) => { + *l = ext; + } + _ => { + unreachable!() + } } } } @@ -778,7 +996,6 @@ pub fn remove_list_index(indexing_code: &mut Vec, offset: usize) { } pub fn remove_index( - //skeleton: &[ClauseIndexInfo], opt_arg_index_key: &OptArgIndexKey, indexing_code: &mut Vec, clause_loc: usize, @@ -790,7 +1007,6 @@ pub fn remove_index( overlapping_constants, indexing_code, clause_loc, - //&skeleton[index].index_locs, ); } OptArgIndexKey::Structure(_, _, ref name, ref arity) => { @@ -799,14 +1015,12 @@ pub fn remove_index( *arity, indexing_code, clause_loc, - //&skeleton[index].index_locs, ); } OptArgIndexKey::List(..) => { remove_list_index( indexing_code, clause_loc, - //&skeleton[index].index_locs, ); } OptArgIndexKey::None => { @@ -815,64 +1029,6 @@ pub fn remove_index( } } -fn second_level_index( - indices: IndexMap>, - prelude: &mut SliceDeque, -) -> IndexMap { - let mut index_locs = IndexMap::new(); - - 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 { - code.first().map(|i| { - index_locs.insert(key, IndexingCodePtr::External(i.offset())); - }); - } - } - - index_locs -} - -fn switch_on( - mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, - index: IndexMap>, - prelude: &mut SliceDeque, -) -> 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, - prelude: &mut SliceDeque, -) -> 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| { @@ -909,15 +1065,6 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) { }); } -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) -> Vec { let mut constants = vec![]; @@ -968,43 +1115,311 @@ pub fn constant_key_alternatives(constant: &Constant, atom_tbl: TabledData } #[derive(Debug)] -pub struct CodeOffsets { - atom_tbl: TabledData, - pub constants: IndexMap>, - pub lists: SliceDeque, - pub structures: IndexMap<(ClauseName, usize), SliceDeque>, - optimal_index: usize, +pub(crate) struct StaticCodeIndices { + constants: IndexMap>, + lists: SliceDeque, + structures: IndexMap<(ClauseName, usize), SliceDeque>, } -impl CodeOffsets { - pub fn new(atom_tbl: TabledData, optimal_index: usize) -> Self { - CodeOffsets { - atom_tbl, +#[derive(Debug)] +pub(crate) struct DynamicCodeIndices { + constants: IndexMap>, + lists: SliceDeque, + structures: IndexMap<(ClauseName, usize), SliceDeque>, +} + +pub trait Indexer { + type ThirdLevelIndex; + + fn new() -> Self; + + fn constants(&mut self) -> &mut IndexMap>; + fn lists(&mut self) -> &mut SliceDeque; + fn structures(&mut self) -> &mut IndexMap<(ClauseName, usize), SliceDeque>; + + fn compute_index(is_initial_index: bool, index: usize) -> Self::ThirdLevelIndex; + + fn second_level_index( + indices: IndexMap>, + prelude: &mut SliceDeque, + ) -> IndexMap; + + fn switch_on( + instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, + index: &mut IndexMap>, + prelude: &mut SliceDeque, + ) -> IndexingCodePtr; + + fn switch_on_list( + lists: &mut SliceDeque, + prelude: &mut SliceDeque, + ) -> IndexingCodePtr; + + fn remove_instruction_with_offset( + code: &mut SliceDeque, + offset: usize, + ); + + fn var_offset_wrapper(var_offset: usize) -> IndexingCodePtr; +} + +impl Indexer for StaticCodeIndices { + type ThirdLevelIndex = IndexedChoiceInstruction; + + #[inline] + fn new() -> Self { + Self { constants: IndexMap::new(), lists: sdeq![], structures: IndexMap::new(), + } + } + + #[inline] + fn constants(&mut self) -> &mut IndexMap> { + &mut self.constants + } + + #[inline] + fn lists(&mut self) -> &mut SliceDeque { + &mut self.lists + } + + #[inline] + fn structures(&mut self) -> &mut IndexMap<(ClauseName, usize), SliceDeque> { + &mut self.structures + } + + fn compute_index(is_initial_index: bool, index: usize) -> IndexedChoiceInstruction { + if is_initial_index { + IndexedChoiceInstruction::Try(index + 1) + } else { + IndexedChoiceInstruction::Retry(index + 1) + } + } + + fn second_level_index( + indices: IndexMap>, + prelude: &mut SliceDeque, + ) -> IndexMap { + let mut index_locs = IndexMap::new(); + + 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 { + code.first().map(|i| { + index_locs.insert(key, IndexingCodePtr::External(i.offset())); + }); + } + } + + index_locs + } + + fn switch_on( + mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, + index: &mut IndexMap>, + prelude: &mut SliceDeque, + ) -> IndexingCodePtr { + let index = mem::replace(index, IndexMap::new()); + let index = Self::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( + lists: &mut SliceDeque, + prelude: &mut SliceDeque, + ) -> IndexingCodePtr { + if lists.len() > 1 { + cap_choice_seq_with_trust(lists); + let lists = mem::replace(lists, sdeq![]); + prelude.push_back(IndexingLine::from(lists)); + + IndexingCodePtr::Internal(1) + } else { + lists + .first() + .map(|i| IndexingCodePtr::External(i.offset())) + .unwrap_or(IndexingCodePtr::Fail) + } + } + + #[inline] + fn remove_instruction_with_offset(code: &mut SliceDeque, offset: usize) { + for (index, line) in code.iter().enumerate() { + if offset == line.offset() { + code.remove(index); + cap_choice_seq(code); + return; + } + } + } + + #[inline] + fn var_offset_wrapper(var_offset: usize) -> IndexingCodePtr { + IndexingCodePtr::External(var_offset) + } +} + +impl Indexer for DynamicCodeIndices { + type ThirdLevelIndex = usize; + + #[inline] + fn new() -> Self { + Self { + constants: IndexMap::new(), + lists: sdeq![], + structures: IndexMap::new(), + } + } + + #[inline] + fn constants(&mut self) -> &mut IndexMap> { + &mut self.constants + } + + #[inline] + fn lists(&mut self) -> &mut SliceDeque { + &mut self.lists + } + + #[inline] + fn structures(&mut self) -> &mut IndexMap<(ClauseName, usize), SliceDeque> { + &mut self.structures + } + + #[inline] + fn compute_index(_: bool, index: usize) -> usize { + index + 1 + } + + fn second_level_index( + indices: IndexMap>, + prelude: &mut SliceDeque, + ) -> IndexMap { + let mut index_locs = IndexMap::new(); + + for (key, code) in indices.into_iter() { + if code.len() > 1 { + index_locs.insert(key, IndexingCodePtr::Internal(prelude.len() + 1)); + prelude.push_back(IndexingLine::DynamicIndexedChoice(code)); + } else { + code.first().map(|i| { + index_locs.insert(key, IndexingCodePtr::DynamicExternal(*i)); + }); + } + } + + index_locs + } + + fn switch_on( + mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, + index: &mut IndexMap>, + prelude: &mut SliceDeque, + ) -> IndexingCodePtr { + let index = mem::replace(index, IndexMap::new()); + let index = Self::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( + lists: &mut SliceDeque, + prelude: &mut SliceDeque, + ) -> IndexingCodePtr { + if lists.len() > 1 { + let lists = mem::replace(lists, sdeq![]); + prelude.push_back(IndexingLine::DynamicIndexedChoice(lists)); + IndexingCodePtr::Internal(1) + } else { + lists + .first() + .map(|i| IndexingCodePtr::DynamicExternal(*i)) + .unwrap_or(IndexingCodePtr::Fail) + } + } + + #[inline] + fn remove_instruction_with_offset(code: &mut SliceDeque, offset: usize) { + for (index, line) in code.iter().enumerate() { + if offset == *line { + code.remove(index); + return; + } + } + } + + #[inline] + fn var_offset_wrapper(var_offset: usize) -> IndexingCodePtr { + IndexingCodePtr::DynamicExternal(var_offset) + } +} + +#[derive(Debug)] +pub struct CodeOffsets { + atom_tbl: TabledData, + indices: I, + optimal_index: usize, +} + +impl CodeOffsets { + pub fn new( + atom_tbl: TabledData, + indices: I, + optimal_index: usize, + ) -> Self { + CodeOffsets { + atom_tbl, + indices, optimal_index, } } 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)); + let is_initial_index = self.indices.lists().is_empty(); + let index = I::compute_index(is_initial_index, index); + self.indices.lists().push_back(index); } fn index_constant(&mut self, constant: &Constant, index: usize) -> Vec { let overlapping_constants = constant_key_alternatives(constant, self.atom_tbl.clone()); - - let code = self.constants.entry(constant.clone()).or_insert(sdeq![]); + let code = self.indices.constants().entry(constant.clone()).or_insert(sdeq![]); let is_initial_index = code.is_empty(); - code.push_back(compute_index(is_initial_index, index)); + code.push_back(I::compute_index(is_initial_index, index)); for constant in &overlapping_constants { - let code = self.constants.entry(constant.clone()).or_insert(sdeq![]); + let code = self.indices.constants().entry(constant.clone()).or_insert(sdeq![]); let is_initial_index = code.is_empty(); - let index = compute_index(is_initial_index, index); + let index = I::compute_index(is_initial_index, index); code.push_back(index); } @@ -1013,15 +1428,15 @@ impl CodeOffsets { } fn index_structure(&mut self, name: &ClauseName, arity: usize, index: usize) -> usize { - let code = self - .structures + let code = self.indices + .structures() .entry((name.clone(), arity)) .or_insert(sdeq![]); let code_len = code.len(); let is_initial_index = code.is_empty(); - code.push_back(compute_index(is_initial_index, index)); + code.push_back(I::compute_index(is_initial_index, index)); code_len } @@ -1057,15 +1472,15 @@ impl CodeOffsets { } } - 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(); + pub fn no_indices(&mut self) -> bool { + let no_constants = self.indices.constants().is_empty(); + let no_structures = self.indices.structures().is_empty(); + let no_lists = self.indices.lists().is_empty(); no_constants && no_structures && no_lists } - pub fn compute_indices(self, skip_stub_try_me_else: bool) -> Vec { + pub fn compute_indices(mut self, skip_stub_try_me_else: bool) -> Vec { if self.no_indices() { return vec![]; } @@ -1075,23 +1490,23 @@ impl CodeOffsets { let mut emitted_switch_on_structure = false; let mut emitted_switch_on_constant = false; - let mut lst_loc = switch_on_list(self.lists, &mut prelude); + let mut lst_loc = I::switch_on_list(self.indices.lists(), &mut prelude); - let mut str_loc = switch_on( + let mut str_loc = I::switch_on( |index| { emitted_switch_on_structure = true; IndexingInstruction::SwitchOnStructure(index) }, - self.structures, + self.indices.structures(), &mut prelude, ); - let con_loc = switch_on( + let con_loc = I::switch_on( |index| { emitted_switch_on_constant = true; IndexingInstruction::SwitchOnConstant(index) }, - self.constants, + self.indices.constants(), &mut prelude, ); @@ -1114,7 +1529,7 @@ impl CodeOffsets { prelude.push_front(IndexingLine::from(IndexingInstruction::SwitchOnTerm( self.optimal_index, - var_offset, + I::var_offset_wrapper(var_offset), con_loc, lst_loc, str_loc, diff --git a/src/instructions.rs b/src/instructions.rs index 5cdf472d..e552c8e3 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -46,8 +46,33 @@ impl ArithmeticTerm { } } +#[derive(Debug, Clone, Copy)] +pub enum NextOrFail { + Next(usize), + Fail(usize), +} + +impl NextOrFail { + #[inline] + pub fn is_next(&self) -> bool { + if let NextOrFail::Next(_) = self { + true + } else { + false + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum Death { + Finite(usize), + Infinity, +} + #[derive(Debug)] pub enum ChoiceInstruction { + DynamicElse(usize, Death, NextOrFail), + DynamicInternalElse(usize, Death, NextOrFail), DefaultRetryMeElse(usize), DefaultTrustMe(usize), RetryMeElse(usize), @@ -56,8 +81,76 @@ pub enum ChoiceInstruction { } impl ChoiceInstruction { - pub fn to_functor(&self) -> MachineStub { + pub fn to_functor(&self, h: usize) -> MachineStub { match self { + &ChoiceInstruction::DynamicElse(birth, death, next_or_fail) => { + match (death, next_or_fail) { + (Death::Infinity, NextOrFail::Next(i)) => { + functor!( + "dynamic_else", + [integer(birth), atom("inf"), integer(i)] + ) + } + (Death::Infinity, NextOrFail::Fail(i)) => { + let next_functor = functor!("fail", [integer(i)]); + + functor!( + "dynamic_else", + [integer(birth), atom("inf"), aux(h, 0)], + [next_functor] + ) + } + (Death::Finite(d), NextOrFail::Fail(i)) => { + let next_functor = functor!("fail", [integer(i)]); + + functor!( + "dynamic_else", + [integer(birth), integer(d), aux(h, 0)], + [next_functor] + ) + } + (Death::Finite(d), NextOrFail::Next(i)) => { + functor!( + "dynamic_else", + [integer(birth), integer(d), integer(i)] + ) + } + } + } + &ChoiceInstruction::DynamicInternalElse(birth, death, next_or_fail) => { + match (death, next_or_fail) { + (Death::Infinity, NextOrFail::Next(i)) => { + functor!( + "dynamic_internal_else", + [integer(birth), atom("inf"), integer(i)] + ) + } + (Death::Infinity, NextOrFail::Fail(i)) => { + let next_functor = functor!("fail", [integer(i)]); + + functor!( + "dynamic_internal_else", + [integer(birth), atom("inf"), aux(h, 0)], + [next_functor] + ) + } + (Death::Finite(d), NextOrFail::Fail(i)) => { + let next_functor = functor!("fail", [integer(i)]); + + functor!( + "dynamic_internal_else", + [integer(birth), integer(d), aux(h, 0)], + [next_functor] + ) + } + (Death::Finite(d), NextOrFail::Next(i)) => { + functor!( + "dynamic_internal_else", + [integer(birth), integer(d), integer(i)] + ) + } + } + } &ChoiceInstruction::TryMeElse(offset) => { functor!("try_me_else", [integer(offset)]) } @@ -143,6 +236,7 @@ impl IndexedChoiceInstruction { pub enum IndexingLine { Indexing(IndexingInstruction), IndexedChoice(SliceDeque), + DynamicIndexedChoice(SliceDeque), } impl From for IndexingLine { @@ -168,6 +262,7 @@ pub enum Line { Fact(FactInstruction), IndexingCode(Vec), IndexedChoice(IndexedChoiceInstruction), + DynamicIndexedChoice(usize), Query(QueryInstruction), } @@ -184,7 +279,7 @@ impl Line { pub fn enqueue_functors(&self, mut h: usize, functors: &mut Vec) { match self { &Line::Arithmetic(ref arith_instr) => functors.push(arith_instr.to_functor(h)), - &Line::Choice(ref choice_instr) => functors.push(choice_instr.to_functor()), + &Line::Choice(ref choice_instr) => functors.push(choice_instr.to_functor(h)), &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)), @@ -203,12 +298,22 @@ impl Line { functors.push(section); } } + IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => { + for indexed_choice_instr in indexed_choice_instrs { + let section = functor!("dynamic", [integer(*indexed_choice_instr)]); + h += section.len(); + functors.push(section); + } + } } } } &Line::IndexedChoice(ref indexed_choice_instr) => { functors.push(indexed_choice_instr.to_functor()) } + &Line::DynamicIndexedChoice(ref indexed_choice_instr) => { + functors.push(functor!("dynamic", [integer(*indexed_choice_instr)])); + } &Line::Query(ref query_instr) => functors.push(query_instr.to_functor(h)), } } @@ -454,7 +559,7 @@ pub enum IndexingInstruction { // The first index is the optimal argument being indexed. SwitchOnTerm( usize, - usize, + IndexingCodePtr, IndexingCodePtr, IndexingCodePtr, IndexingCodePtr, @@ -471,7 +576,7 @@ impl IndexingInstruction { "switch_on_term", [ integer(arg), - integer(vars), + indexing_code_ptr(h, vars), indexing_code_ptr(h, constants), indexing_code_ptr(h, lists), indexing_code_ptr(h, structures) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index abf650c2..bc393c40 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -802,11 +802,11 @@ setof(Template, Goal, Solution) :- ; functor(H, Name, Arity) -> ( Name == '.' -> throw(error(type_error(callable, H), clause/2)) - ; '$no_such_predicate'(Module, H) -> - '$fail' ; '$head_is_dynamic'(Module, H) -> '$clause_body_is_valid'(B), Module:'$clause'(H, B) + ; '$no_such_predicate'(Module, H) -> + '$fail' ; throw(error(permission_error(access, private_procedure, Name/Arity), clause/2)) ) @@ -825,12 +825,12 @@ clause(H, B) :- arg(1, H, Module), arg(2, H, F), '$module_clause'(F, B, Module) - ; '$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) + ; '$no_such_predicate'(user, H) -> %% '$no_such_predicate' fails if + %% H is not callable. + '$fail' ; throw(error(permission_error(access, private_procedure, Name/Arity), clause/2)) ) @@ -865,10 +865,10 @@ asserta_clause(Head, Body) :- 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, user) ; '$head_is_dynamic'(user, Head) -> call_asserta(Head, Body, Name, Arity, user) + ; '$no_such_predicate'(user, Head) -> + call_asserta(Head, Body, Name, Arity, user) ; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1)) ) ; throw(error(type_error(callable, Head), asserta/1)) @@ -889,10 +889,10 @@ module_assertz_clause(Head, Body, Module) :- ; functor(Head, Name, Arity), atom(Name), Name \== '.' -> - ( '$no_such_predicate'(Module, Head) -> - call_assertz(Head, Body, Name, Arity, Module) - ; '$head_is_dynamic'(Module, Head) -> + ( '$head_is_dynamic'(Module, Head) -> call_assertz(Head, Body, Name, Arity, Module) + ; '$no_such_predicate'(Module, Head) -> + call_assertz(Head, Body, Name, Arity, Module) ; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1)) ) @@ -916,10 +916,10 @@ assertz_clause(Head, Body) :- 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, user) ; '$head_is_dynamic'(user, Head) -> call_assertz(Head, Body, Name, Arity, user) + ; '$no_such_predicate'(user, Head) -> + call_assertz(Head, Body, Name, Arity, user) ; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1)) ) @@ -939,11 +939,13 @@ assertz(Clause) :- module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :- functor(VarHead, Name, Arity), findall((VarHead :- VarBody), Module:'$clause'(VarHead, VarBody), Clauses1), - first_match_index(Clauses1, (Head :- Body), 0, N), + ( first_match_index(Clauses1, (Head :- Body), 0, N) -> + '$retract_clause'(Name, Arity, N, Module) + ; Clause = (Head :- Body) + ), ( Clauses0 == [] -> ! ; true - ), - '$retract_clause'(Name, Arity, N, Module). + ). module_retract_clauses([_|Clauses0], Head, Body, Name, Arity, Module) :- module_retract_clauses(Clauses0, Head, Body, Name, Arity, Module). @@ -969,22 +971,22 @@ retract_module_clause(Head, Body, Module) :- ). -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 - ). +first_match_index([Clause | Clauses], Clause, N, N) :- + !. +first_match_index([_ | Clauses], Clause, N0, N) :- + N1 is N0 + 1, + first_match_index(Clauses, Clause, N1, N). 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), + ( first_match_index(Clauses1, (Head :- Body), 0, N) -> + '$retract_clause'(Name, Arity, N, user) + ; Clause = (Head :- Body) + ), ( Clauses0 == [] -> ! ; true - ), - '$retract_clause'(Name, Arity, N, user). + ). retract_clauses([_ | Clauses0], Head, Body, Name, Arity) :- retract_clauses(Clauses0, Head, Body, Name, Arity). @@ -1065,10 +1067,10 @@ abolish(Pred) :- ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1)) ; functor(Head, Name, Arity) -> - ( '$no_such_predicate'(user, Head) -> - true - ; '$head_is_dynamic'(user, Head) -> + ( '$head_is_dynamic'(user, Head) -> '$abolish_clause'(user, Name, Arity) + ; '$no_such_predicate'(user, Head) -> + true ; throw(error(permission_error(modify, static_procedure, Pred), abolish/1)) ) ) diff --git a/src/machine/code_repo.rs b/src/machine/code_repo.rs index 7db42530..1a812b58 100644 --- a/src/machine/code_repo.rs +++ b/src/machine/code_repo.rs @@ -37,6 +37,9 @@ impl CodeRepo { &IndexingLine::IndexedChoice(ref indexed_choice_instrs) => { RefOrOwned::Owned(Line::IndexedChoice(indexed_choice_instrs[i])) } + &IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { + RefOrOwned::Owned(Line::DynamicIndexedChoice(indexed_choice_instrs[i])) + } _ => { unreachable!() } @@ -86,11 +89,98 @@ impl CodeRepo { &CodePtr::VerifyAttrInterrupt(p) => { Some(RefOrOwned::Borrowed(&self.code[p])) } -/* - &CodePtr::DynamicTransaction(..) => { - None + } + } + + pub(super) + fn find_living_dynamic_else(&self, mut p: usize, cc: usize) -> Option<(usize, usize)> { + loop { + match &self.code[p] { + &Line::Choice(ChoiceInstruction::DynamicElse(birth, death, NextOrFail::Next(i))) => { + if birth < cc && Death::Finite(cc) <= death { + return Some((p, i)); + } else if i > 0 { + p += i; + } else { + return None; + } + } + &Line::Choice(ChoiceInstruction::DynamicElse(birth, death, NextOrFail::Fail(_))) => { + if birth < cc && Death::Finite(cc) <= death { + return Some((p, 0)); + } else { + return None; + } + } + &Line::Choice(ChoiceInstruction::DynamicInternalElse( + birth, + death, + NextOrFail::Next(i), + )) => { + if birth < cc && Death::Finite(cc) <= death { + return Some((p, i)); + } else if i > 0 { + p += i; + } else { + return None; + } + } + &Line::Choice(ChoiceInstruction::DynamicInternalElse( + birth, + death, + NextOrFail::Fail(_)), + ) => { + if birth < cc && Death::Finite(cc) <= death { + return Some((p, 0)); + } else { + return None; + } + } + &Line::Control(ControlInstruction::RevJmpBy(i)) => { + p -= i; + } + _ => { + unreachable!(); + } + } + } + } + + pub(super) + fn find_living_dynamic(&self, p: LocalCodePtr, cc: usize) -> Option<(usize, usize, usize, bool)> { + let (p, oi, mut ii) = match p { + LocalCodePtr::IndexingBuf(p, oi, ii) => (p, oi, ii), + _ => unreachable!(), + }; + + let indexed_choice_instrs = match &self.code[p] { + Line::IndexingCode(ref indexing_code) => match &indexing_code[oi] { + IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { + indexed_choice_instrs + } + _ => unreachable!() + } + _ => unreachable!() + }; + + loop { + match &indexed_choice_instrs.get(ii) { + Some(&offset) => { + match &self.code[p + offset - 1] { + &Line::Choice(ChoiceInstruction::DynamicInternalElse( + birth, death, next_or_fail, + )) => { + if birth < cc && Death::Finite(cc) <= death { + return Some((offset, oi, ii, next_or_fail.is_next())); + } else { + ii += 1; + } + } + _ => unreachable!(), + } + } + None => return None, } -*/ } } } diff --git a/src/machine/code_walker.rs b/src/machine/code_walker.rs index 94944889..2d199fd6 100644 --- a/src/machine/code_walker.rs +++ b/src/machine/code_walker.rs @@ -11,6 +11,14 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec) -> bool { &Line::Choice(ChoiceInstruction::RetryMeElse(offset)) if offset > 0 => { stack.push(index + offset); } + &Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset))) + if offset > 0 => { + stack.push(index + offset); + } + &Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(offset))) + if offset > 0 => { + stack.push(index + offset); + } &Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => { stack.push(index + offset); } diff --git a/src/machine/compile.rs b/src/machine/compile.rs index ebdcb134..bfea3f2f 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -2,7 +2,7 @@ use prolog_parser::clause_name; use crate::codegen::*; use crate::debray_allocator::*; -use crate::indexing::{merge_clause_index, remove_index}; +use crate::indexing::{IndexingCodePtr, merge_clause_index, remove_index}; use crate::machine::load_state::*; use crate::machine::loader::*; use crate::machine::preprocessor::*; @@ -74,7 +74,12 @@ pub(super) fn compile_appendix( } // false because the inner predicate is a one-off, hence not extensible. - let settings = CodeGenSettings::new(false, non_counted_bt); + let settings = CodeGenSettings { + global_clock_tick: None, + is_extensible: false, + non_counted_bt, + }; + let mut cg = CodeGenerator::::new(atom_tbl.clone(), settings); let tl = queue.pop_front().unwrap(); @@ -115,11 +120,22 @@ fn derelictize_try_me_else( retraction_info: &mut RetractionInfo, ) -> Option { match &mut code[index] { + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(0))) => None, + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))) => { + retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o)); + Some(mem::replace(o, 0)) + } + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(0))) => None, + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))) => { + retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o)); + Some(mem::replace(o, 0)) + } + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(_))) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(_))) => None, Line::Choice(ChoiceInstruction::TryMeElse(0)) => None, - Line::Choice(ChoiceInstruction::TryMeElse(ref mut offset)) => { - retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *offset)); - - Some(mem::replace(offset, 0)) + Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => { + retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *o)); + Some(mem::replace(o, 0)) } _ => { unreachable!() @@ -165,23 +181,80 @@ fn merge_indices( } } -fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> usize { +fn find_outer_choice_instr( + code: &Code, + mut index: usize, +) -> usize { loop { match &code[index] { - Line::Choice(ChoiceInstruction::TryMeElse(o)) - | Line::Choice(ChoiceInstruction::RetryMeElse(o)) => { + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(i))) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(i))) + if *i > 0 => + { + index += i; + } + _ => { + return index; + } + } + } +} + +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::DynamicElse(_, _, next_or_fail)) | + &Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, next_or_fail)) => { + match next_or_fail { + NextOrFail::Next(i) => { + if i == 0 { + index = index_loc; + } else { + return index; + } + } + NextOrFail::Fail(_) => { + return index; + } + } + } Line::Choice(ChoiceInstruction::TrustMe(_)) => { return index; } Line::IndexingCode(indexing_code) => match &indexing_code[0] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => { - index += v; + match v { + IndexingCodePtr::External(v) => { + index += v; + } + IndexingCodePtr::DynamicExternal(v) => { + match &code[index + v] { + &Line::Choice(ChoiceInstruction::DynamicInternalElse( + _, + _, + NextOrFail::Next(0), + )) => { + return index + v; + } + _ => { + index += v; + } + } + } + _ => unreachable!() + } } _ => { unreachable!(); @@ -253,7 +326,7 @@ fn merge_indexed_subsequences( 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, + inner_try_me_else_loc, *o, )); @@ -357,9 +430,35 @@ fn blunt_leading_choice_instr( return instr_loc; } - Line::Choice(ChoiceInstruction::TrustMe(offset)) => { + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(_))) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(_))) => { + return instr_loc; + } + &mut Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Fail(o))) => { + retraction_info.push_record( + RetractionRecord::AppendedNextOrFail(instr_loc, NextOrFail::Fail(o)), + ); + + code[instr_loc] = Line::Choice( + ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(0)), + ); + + return instr_loc; + } + &mut Line::Choice(ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Fail(o))) => { + retraction_info.push_record( + RetractionRecord::AppendedNextOrFail(instr_loc, NextOrFail::Fail(o)), + ); + + code[instr_loc] = Line::Choice( + ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Next(0)), + ); + + return instr_loc; + } + Line::Choice(ChoiceInstruction::TrustMe(o)) => { retraction_info - .push_record(RetractionRecord::AppendedTrustMe(instr_loc, *offset, false)); + .push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false)); code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(0)); return instr_loc + 1; @@ -388,15 +487,22 @@ fn set_switch_var_offset_to_choice_instr( ) { let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap(); - let v = match &mut target_indexing_line[0] { - IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => *v, + let v = match &target_indexing_line[0] { + &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => { + match v { + IndexingCodePtr::External(v) | IndexingCodePtr::DynamicExternal(v) => v, + _ => unreachable!() + } + } _ => { unreachable!(); } }; match &code[index_loc + v] { - Line::Choice(ChoiceInstruction::TryMeElse(_)) => {} + Line::Choice(ChoiceInstruction::TryMeElse(_)) | + Line::Choice(ChoiceInstruction::DynamicElse(..)) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(..)) => {} _ => { set_switch_var_offset(code, index_loc, offset, retraction_info); } @@ -414,7 +520,15 @@ fn set_switch_var_offset( let old_v = match &mut target_indexing_line[0] { IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => { - mem::replace(v, offset) + match *v { + IndexingCodePtr::DynamicExternal(_) => { + mem::replace(v, IndexingCodePtr::DynamicExternal(offset)) + } + IndexingCodePtr::External(_) => { + mem::replace(v, IndexingCodePtr::External(offset)) + } + _ => unreachable!() + } } _ => { unreachable!() @@ -432,6 +546,53 @@ fn internalize_choice_instr_at( retraction_info: &mut RetractionInfo, ) { match &mut code[instr_loc] { + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(_))) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(_))) => { + } + Line::Choice(ChoiceInstruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0))) => { + retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0)); + *o = NextOrFail::Fail(0); + } + &mut Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(o))) => { + retraction_info.push_record( + RetractionRecord::AppendedNextOrFail(instr_loc, NextOrFail::Next(o)), + ); + + match &mut code[instr_loc + o] { + Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => { + code[instr_loc] = Line::Choice( + ChoiceInstruction::DynamicElse(b, d, NextOrFail::Fail(o)), + ); + } + _ => { + code[instr_loc] = Line::Choice( + ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(o)), + ); + } + } + } + Line::Choice(ChoiceInstruction::DynamicInternalElse( + _, _, ref mut o @ NextOrFail::Next(0), + )) => { + retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0)); + *o = NextOrFail::Fail(0); + } + &mut Line::Choice(ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Next(o))) => { + retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, o)); + + match &mut code[instr_loc + o] { + Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => { + code[instr_loc] = Line::Choice( + ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Fail(o)), + ); + } + _ => { + code[instr_loc] = Line::Choice( + ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Next(o)), + ); + } + } + } Line::Choice(ChoiceInstruction::TryMeElse(0)) => { retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(instr_loc, 0)); @@ -465,8 +626,8 @@ fn thread_choice_instr_at_to( ) { loop { match &mut code[instr_loc] { - Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) - | Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) + 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)); @@ -474,8 +635,20 @@ fn thread_choice_instr_at_to( *o = target_loc - instr_loc; return; } - Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) - | Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) => { + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))) + if target_loc >= instr_loc => + { + retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, *o)); + *o = target_loc - instr_loc; + return; + } + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))) => { + instr_loc += *o; + } + 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 => { @@ -484,6 +657,44 @@ fn thread_choice_instr_at_to( *o = instr_loc - target_loc; return; } + &mut Line::Choice(ChoiceInstruction::DynamicElse(birth, death, ref mut fail)) + if target_loc >= instr_loc => + { + retraction_info.push_record( + RetractionRecord::AppendedNextOrFail(instr_loc, *fail), + ); + + code[instr_loc] = + Line::Choice(ChoiceInstruction::DynamicElse( + birth, death, NextOrFail::Next(target_loc - instr_loc), + )); + + return; + } + Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(o))) + if *o > 0 => + { + instr_loc += *o; + } + &mut Line::Choice(ChoiceInstruction::DynamicInternalElse(birth, death, ref mut fail)) + if target_loc >= instr_loc => + { + retraction_info.push_record( + RetractionRecord::AppendedNextOrFail(instr_loc, *fail), + ); + + code[instr_loc] = + Line::Choice(ChoiceInstruction::DynamicInternalElse( + birth, death, NextOrFail::Next(target_loc - instr_loc), + )); + + return; + } + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(o))) + if *o > 0 => + { + instr_loc += *o; + } Line::Choice(ChoiceInstruction::TrustMe(ref mut o)) if target_loc >= instr_loc => { retraction_info.push_record( RetractionRecord::AppendedTrustMe(instr_loc, *o, false), @@ -619,6 +830,29 @@ fn remove_leading_unindexed_clause( } } +fn find_dynamic_outer_choice_instr( + code: &Code, + index_loc: usize, +) -> usize { + match &code[index_loc] { + Line::IndexingCode(indexing_code) => { + match &indexing_code[0] { + &IndexingLine::Indexing( + IndexingInstruction::SwitchOnTerm( + _, + IndexingCodePtr::DynamicExternal(v), + .., + ) + ) => { + index_loc + v - 2 + } + _ => unreachable!() + } + } + _ => unreachable!() + } +} + fn prepend_compiled_clause( code: &mut Code, compilation_target: CompilationTarget, @@ -626,14 +860,25 @@ fn prepend_compiled_clause( mut clause_code: Code, skeleton: &mut PredicateSkeleton, retraction_info: &mut RetractionInfo, -) -> usize { + global_clock_tick: usize, +) -> IndexPtr { 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(); + + let settings = CodeGenSettings { + global_clock_tick: if skeleton.is_dynamic { + Some(global_clock_tick) + } else { + None + }, + is_extensible: true, + non_counted_bt: false, + }; - if skeleton.clauses[0] + let clause_loc = if skeleton.clauses[0] .opt_arg_index_key .switch_on_term_loc() .is_some() @@ -650,7 +895,11 @@ fn prepend_compiled_clause( skeleton.clauses[0].clause_start, )); - let outer_thread_choice_loc = skeleton.clauses[1].clause_start - 2; + let outer_thread_choice_loc = if skeleton.is_dynamic { + find_dynamic_outer_choice_instr(code, index_loc) + } else { + skeleton.clauses[1].clause_start - 2 + }; retraction_info.push_record(RetractionRecord::SkeletonClauseStartReplaced( compilation_target, @@ -669,9 +918,9 @@ fn prepend_compiled_clause( inner_thread_rev_offset, ))); - prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( - prepend_queue.len(), - ))); + prepend_queue.push_front(Line::Choice( + settings.internal_try_me_else(prepend_queue.len()), + )); // prepend_queue is now: // | TryMeElse N_2 @@ -716,9 +965,9 @@ fn prepend_compiled_clause( } }; - prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( - outer_thread_choice_offset, - ))); + prepend_queue.push_front(Line::Choice( + settings.try_me_else(outer_thread_choice_offset), + )); // prepend_queue is now: // | TryMeElse N_3 @@ -747,7 +996,11 @@ fn prepend_compiled_clause( code.extend(prepend_queue.into_iter()); - clause_loc + (outer_thread_choice_offset == 0) as usize + if skeleton.is_dynamic { + clause_loc + } else { + clause_loc + (outer_thread_choice_offset == 0) as usize + } } _ => { prepend_queue.extend(clause_code.drain(1..)); @@ -755,7 +1008,18 @@ fn prepend_compiled_clause( 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 old_clause_start = + match skeleton.clauses[1].opt_arg_index_key.switch_on_term_loc() { + Some(index_loc) if skeleton.is_dynamic => { + find_dynamic_outer_choice_instr(code, index_loc) + } + Some(_) => { + skeleton.clauses[1].clause_start - 2 + } + None => { + skeleton.clauses[1].clause_start + } + }; let inner_thread_rev_offset = 2 + prepend_queue.len() + clause_loc - old_clause_start; @@ -770,6 +1034,11 @@ fn prepend_compiled_clause( Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) if *o == 0 => { *o = prepend_queue_len - 2; } + Line::Choice(ChoiceInstruction::DynamicInternalElse( + _, _, ref mut o @ NextOrFail::Next(0), + )) => { + *o = NextOrFail::Fail(prepend_queue_len - 2); + } _ => { unreachable!(); } @@ -779,9 +1048,9 @@ fn prepend_compiled_clause( inner_thread_rev_offset, ))); - prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( - prepend_queue.len(), - ))); + prepend_queue.push_front(Line::Choice( + settings.try_me_else(prepend_queue.len()), + )); // prepend_queue is now: // | TryMeElse(N_2) @@ -799,10 +1068,14 @@ fn prepend_compiled_clause( } } else { match skeleton.clauses[1].opt_arg_index_key.switch_on_term_loc() { - Some(_) => { + Some(index_loc) => { prepend_queue.extend(clause_code.drain(1..)); - let old_clause_start = skeleton.clauses[1].clause_start - 2; + let old_clause_start = if skeleton.is_dynamic { + find_dynamic_outer_choice_instr(code, index_loc) + } else { + skeleton.clauses[1].clause_start - 2 + }; let inner_thread_rev_offset = 1 + prepend_queue.len() + clause_loc - old_clause_start; @@ -811,9 +1084,9 @@ fn prepend_compiled_clause( inner_thread_rev_offset, ))); - prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( - prepend_queue.len(), - ))); + prepend_queue.push_front(Line::Choice( + settings.try_me_else(prepend_queue.len()), + )); // prepend_queue is now: // | TryMeElse(N_2) @@ -841,9 +1114,9 @@ fn prepend_compiled_clause( inner_thread_rev_offset, ))); - prepend_queue.push_front(Line::Choice(ChoiceInstruction::TryMeElse( - prepend_queue.len(), - ))); + prepend_queue.push_front(Line::Choice( + settings.try_me_else(prepend_queue.len()), + )); // prepend_queue is now: // | TryMeElse(N_2) @@ -857,9 +1130,15 @@ fn prepend_compiled_clause( // 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) + clause_loc } } + }; + + if skeleton.is_dynamic { + IndexPtr::DynamicIndex(clause_loc) + } else { + IndexPtr::Index(clause_loc) } } @@ -868,12 +1147,22 @@ fn append_compiled_clause( mut clause_code: Code, skeleton: &mut PredicateSkeleton, retraction_info: &mut RetractionInfo, -) -> Option { + global_clock_tick: usize, +) -> Option { 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))); + let settings = CodeGenSettings { + global_clock_tick: if skeleton.is_dynamic { + Some(global_clock_tick) + } else { + None + }, + is_extensible: true, + non_counted_bt: false, + }; + skeleton.clauses[target_pos].clause_start = clause_loc; let mut code_ptr_opt = None; @@ -886,6 +1175,8 @@ fn append_compiled_clause( .switch_on_term_loc() { Some(index_loc) if lower_bound_arg_num == target_arg_num => { + code.push(Line::Choice(settings.internal_trust_me())); + code.extend(clause_code.drain(3..)); // skip the indexing code // set skeleton[target_pos].opt_arg_index_key to @@ -912,8 +1203,13 @@ fn append_compiled_clause( index_loc, ); + let target_pos_clause_start = find_outer_choice_instr( + code, + target_pos_clause_start, + ); + if lower_bound + 1 == target_pos { - set_switch_var_offset( + set_switch_var_offset_to_choice_instr( code, index_loc, target_pos_clause_start - index_loc, @@ -924,6 +1220,8 @@ fn append_compiled_clause( target_pos_clause_start // skeleton.clauses[target_pos - 1].clause_start } _ => { + code.push(Line::Choice(settings.trust_me())); + skeleton.clauses[target_pos].opt_arg_index_key += clause_loc; code.extend(clause_code.drain(1..)); @@ -936,7 +1234,7 @@ fn append_compiled_clause( code_ptr_opt = Some(skeleton.clauses[lower_bound].clause_start - 2); } - skeleton.clauses[lower_bound].clause_start - 2 + find_outer_choice_instr(code, skeleton.clauses[lower_bound].clause_start - 2) } None => { if lower_bound == 0 { @@ -953,12 +1251,14 @@ fn append_compiled_clause( // its variable offset. skeleton.clauses[target_pos].clause_start += 2; - set_switch_var_offset(code, index_loc, 2, retraction_info); + if !skeleton.is_dynamic { + set_switch_var_offset(code, index_loc, 2, retraction_info); + } } None => {} } - skeleton.clauses[lower_bound].clause_start + find_outer_choice_instr(code, skeleton.clauses[lower_bound].clause_start) } } } @@ -966,7 +1266,13 @@ fn append_compiled_clause( thread_choice_instr_at_to(code, threaded_choice_instr_loc, clause_loc, retraction_info); - code_ptr_opt + code_ptr_opt.map(|p| { + if skeleton.is_dynamic { + IndexPtr::DynamicIndex(p) + } else { + IndexPtr::Index(p) + } + }) } #[inline] @@ -1139,7 +1445,11 @@ impl<'a> LoadState<'a> { &predicates.compilation_target, key, &code_index, - IndexPtr::Index(code_ptr), + if settings.is_dynamic() { + IndexPtr::DynamicIndex(code_ptr) + } else { + IndexPtr::Index(code_ptr) + }, ); self.wam.code_repo.code.extend(code.into_iter()); @@ -1191,15 +1501,36 @@ impl<'a> LoadState<'a> { append_or_prepend, ); - match self + let settings = match self .wam .indices .get_predicate_skeleton_mut(&compilation_target, &key) { - Some(skeleton) if !skeleton.clauses.is_empty() => {}, - _ => { - // true because this predicate is extensible. - let settings = CodeGenSettings::new(true, non_counted_bt); + Some(skeleton) if !skeleton.clauses.is_empty() => { + CodeGenSettings { + global_clock_tick: if skeleton.is_dynamic { + Some(self.wam.machine_st.global_clock) + } else { + None + }, + is_extensible: true, + non_counted_bt, + } + }, + skeleton_opt => { + let settings = CodeGenSettings { + global_clock_tick: if let Some(skeleton) = skeleton_opt { + if skeleton.is_dynamic { + Some(self.wam.machine_st.global_clock) + } else { + None + } + } else { + None + }, + is_extensible: true, + non_counted_bt, + }; let mut predicate_queue = predicate_queue![clause]; predicate_queue.compilation_target = compilation_target; @@ -1208,7 +1539,6 @@ impl<'a> LoadState<'a> { } }; - let settings = CodeGenSettings::new(true, non_counted_bt); let atom_tbl = self.wam.machine_st.atom_tbl.clone(); let StandaloneCompileResult { @@ -1245,6 +1575,7 @@ impl<'a> LoadState<'a> { clause_code, skeleton, &mut self.retraction_info, + self.wam.machine_st.global_clock, ); match self @@ -1284,13 +1615,13 @@ impl<'a> LoadState<'a> { compilation_target.clone(), ); - if let Some(new_code_index) = result { + if let Some(new_code_ptr) = result { set_code_index( &mut self.retraction_info, &compilation_target, key, &code_index, - IndexPtr::Index(new_code_index), + new_code_ptr, ); } @@ -1309,13 +1640,14 @@ impl<'a> LoadState<'a> { key.clone(), )); - let threaded_choice_instr_loc = prepend_compiled_clause( + let new_code_ptr = prepend_compiled_clause( &mut self.wam.code_repo.code, compilation_target.clone(), key.clone(), clause_code, skeleton, &mut self.retraction_info, + self.wam.machine_st.global_clock, ); match self @@ -1360,7 +1692,7 @@ impl<'a> LoadState<'a> { &compilation_target, key, &code_index, - IndexPtr::Index(threaded_choice_instr_loc), + new_code_ptr, ); Ok(()) @@ -1368,6 +1700,51 @@ impl<'a> LoadState<'a> { } } + pub(super) fn retract_dynamic_clause(&mut self, key: PredicateKey, target_pos: usize) -> usize { + let skeleton = match self + .wam + .indices + .get_predicate_skeleton_mut(&self.compilation_target, &key) + { + Some(skeleton) => skeleton, + None => { + unreachable!(); + } + }; + + let clause_loc = match skeleton.clauses[target_pos] + .opt_arg_index_key + .switch_on_term_loc() + { + Some(index_loc) => { + find_inner_choice_instr( + &self.wam.code_repo.code, + skeleton.clauses[target_pos].clause_start, + index_loc, + ) + } + None => { + skeleton.clauses[target_pos].clause_start + } + }; + + match &mut self.wam.code_repo.code[clause_loc] { + Line::Choice(ChoiceInstruction::DynamicElse(_, ref mut d, _)) | + Line::Choice(ChoiceInstruction::DynamicInternalElse(_, ref mut d, _)) => { + *d = Death::Finite(self.wam.machine_st.global_clock); + } + _ => unreachable!() + } + + delete_from_skeleton( + self.compilation_target.clone(), + key, + skeleton, + target_pos, + &mut self.retraction_info, + ) + } + pub(super) fn retract_clause(&mut self, key: PredicateKey, target_pos: usize) -> usize { let code_index = self.get_or_insert_code_index( key.clone(), @@ -1835,6 +2212,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { clause_clause_compilation_target, (clause_name!("$clause"), 2), (0 .. skeleton.clauses.len()).map(Some).collect(), + false, // the builtin M:'$clause'/2 is never dynamic. ); predicate_info.is_dynamic = false; @@ -1851,11 +2229,22 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } } - let settings = CodeGenSettings::new(predicate_info.is_extensible, non_counted_bt); + let settings = CodeGenSettings { + global_clock_tick: if predicate_info.is_dynamic { + Some(self.load_state.wam.machine_st.global_clock) + } else { + None + }, + is_extensible: predicate_info.is_extensible, + non_counted_bt, + }; + self.load_state.compile(key.clone(), &mut self.predicates, settings)?; } if predicate_info.is_dynamic { + self.load_state.wam.machine_st.global_clock += 1; + let clauses_vec: Vec<_> = self.clause_clauses .drain(0 .. predicates_len) .collect(); diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index d652724b..b2567725 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -346,25 +346,27 @@ impl<'a> LoadState<'a> { key: PredicateKey, clause_locs: &SliceDeque, ) { - let clause_target_poses: Vec<_> = self + let (clause_target_poses, is_dynamic) = self .wam .indices .get_predicate_skeleton(&compilation_target, &key) .map(|skeleton| { - clause_locs + (clause_locs .iter() .map(|clause_clause_loc| { skeleton.target_pos_of_clause_clause_loc( *clause_clause_loc, ) }) - .collect() + .collect(), + skeleton.is_dynamic) }).unwrap(); self.retract_local_clauses_by_locs( compilation_target, key, clause_target_poses, + is_dynamic, ); } @@ -373,6 +375,7 @@ impl<'a> LoadState<'a> { compilation_target: CompilationTarget, key: PredicateKey, mut clause_target_poses: Vec>, + is_dynamic: bool, ) { let old_compilation_target = mem::replace( &mut self.compilation_target, @@ -381,6 +384,9 @@ impl<'a> LoadState<'a> { while let Some(target_pos_opt) = clause_target_poses.pop() { match target_pos_opt { + Some(target_pos) if is_dynamic => { + self.retract_dynamic_clause(key.clone(), target_pos); + } Some(target_pos) => { self.retract_clause(key.clone(), target_pos); } diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 96c449dc..691871c6 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -68,7 +68,7 @@ pub(crate) enum RetractionRecord { RemovedIndex(usize, OptArgIndexKey, usize), ReplacedChoiceOffset(usize, usize), AppendedTrustMe(usize, usize, bool), - ReplacedSwitchOnTermVarIndex(usize, usize), + ReplacedSwitchOnTermVarIndex(usize, IndexingCodePtr), ModifiedTryMeElse(usize, usize), ModifiedRetryMeElse(usize, usize), ModifiedRevJmpBy(usize, usize), @@ -94,6 +94,8 @@ pub(crate) enum RetractionRecord { SliceDeque, ), RemovedSkeleton(CompilationTarget, PredicateKey, PredicateSkeleton), + ReplacedDynamicElseOffset(usize, usize), + AppendedNextOrFail(usize, NextOrFail), } /* @@ -626,6 +628,32 @@ impl<'a> Drop for LoadState<'a> { } } } + RetractionRecord::ReplacedDynamicElseOffset(instr_loc, next) => { + match &mut self.wam.code_repo.code[instr_loc] { + Line::Choice(ChoiceInstruction::DynamicElse( + _, _, NextOrFail::Next(ref mut o), + )) | + Line::Choice(ChoiceInstruction::DynamicInternalElse( + _, _, NextOrFail::Next(ref mut o), + )) => { + *o = next; + } + _ => {} + } + } + RetractionRecord::AppendedNextOrFail(instr_loc, fail) => { + match &mut self.wam.code_repo.code[instr_loc] { + Line::Choice(ChoiceInstruction::DynamicElse( + _, _, ref mut next_or_fail, + )) | + Line::Choice(ChoiceInstruction::DynamicInternalElse( + _, _, ref mut next_or_fail, + )) => { + *next_or_fail = fail; + } + _ => {} + } + } } } @@ -1720,6 +1748,13 @@ impl Machine { fetch_op_spec(clause_name!(":-"), 2, &loader.load_state.wam.indices.op_dir), ); + // if a new predicate was just created, make it dynamic. + loader.add_dynamic_predicate( + compilation_target.clone(), + key.0.clone(), + key.1, + )?; + loader.load_state.incremental_compile_clause( key.clone(), asserted_clause, @@ -1728,13 +1763,8 @@ impl Machine { append_or_prepend, )?; - // if a new predicate was just created, make it dynamic. - loader - .load_state - .wam - .indices - .get_predicate_skeleton_mut(&compilation_target, &key) - .map(|skeleton| skeleton.is_dynamic = true); + // the global clock is incremented after each assertion. + loader.load_state.wam.machine_st.global_clock += 1; loader.compile_clause_clauses( key, @@ -1883,7 +1913,10 @@ impl Machine { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); loader.load_state.compilation_target = compilation_target; - let clause_clause_loc = loader.load_state.retract_clause(key, target_pos); + let clause_clause_loc = loader.load_state.retract_dynamic_clause(key, target_pos); + + // the global clock is incremented after each retraction. + loader.load_state.wam.machine_st.global_clock += 1; let target_pos = match loader.load_state.wam.indices.get_predicate_skeleton( &clause_clause_compilation_target, diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 04a60feb..17bfa4a6 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -372,6 +372,7 @@ impl From for HeapCellValue { #[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. + DynamicIndex(usize), Index(usize), Undefined, } @@ -405,6 +406,7 @@ impl CodeIndex { pub fn local(&self) -> Option { match self.0.get() { IndexPtr::Index(i) => Some(i), + IndexPtr::DynamicIndex(i) => Some(i), _ => None, } } @@ -555,38 +557,6 @@ impl LocalCodePtr { } } -/* -impl PartialOrd for CodePtr { - fn partial_cmp(&self, other: &CodePtr) -> Option { - match (self, other) { - (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => { - l1.partial_cmp(l2) - } - _ => { - Some(Ordering::Greater) - } - } - } -} - -impl PartialOrd for LocalCodePtr { - fn partial_cmp(&self, other: &LocalCodePtr) -> Option { - match (self, other) { - (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2)) | - (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => { - p1.partial_cmp(p2) - } - (_, &LocalCodePtr::TopLevel(_, _)) => { - Some(Ordering::Less) - } - _ => { - Some(Ordering::Greater) - } - } - } -} -*/ - impl Default for CodePtr { #[inline] fn default() -> Self { diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 26686fd8..71801f3b 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -269,6 +269,12 @@ impl Default for HeapPtr { } } +#[derive(Debug)] +pub enum FirstOrNext { + First, + Next, +} + #[derive(Debug)] pub struct MachineState { pub(crate) atom_tbl: TabledData, @@ -295,7 +301,9 @@ pub struct MachineState { pub(super) last_call: bool, pub(crate) heap_locs: HeapVarDict, pub(crate) flags: MachineFlags, - pub(crate) at_end_of_expansion: bool, + pub(crate) cc: usize, + pub(crate) global_clock: usize, + pub(crate) dynamic_mode: FirstOrNext, } impl MachineState { @@ -911,8 +919,12 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { IndexPtr::Undefined => { return Err(machine_st.throw_undefined_error(name, arity)); } + IndexPtr::DynamicIndex(compiled_tl_index) => { + machine_st.dynamic_mode = FirstOrNext::First; + machine_st.call_at_index(arity, dir_entry!(compiled_tl_index)); + } IndexPtr::Index(compiled_tl_index) => { - machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index)); + machine_st.call_at_index(arity, dir_entry!(compiled_tl_index)); } } @@ -934,6 +946,10 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { IndexPtr::Undefined => { return Err(machine_st.throw_undefined_error(name, arity)); } + IndexPtr::DynamicIndex(compiled_tl_index) => { + machine_st.dynamic_mode = FirstOrNext::First; + machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index)); + } IndexPtr::Index(compiled_tl_index) => { machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index)) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 5b946b0d..3262daa5 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -54,7 +54,9 @@ impl MachineState { last_call: false, heap_locs: HeapVarDict::new(), flags: MachineFlags::default(), - at_end_of_expansion: false, + cc: 0, + global_clock: 0, + dynamic_mode: FirstOrNext::First, } } @@ -1302,9 +1304,35 @@ impl MachineState { pub(super) fn execute_indexing_instr( &mut self, indexing_lines: &Vec, - call_policy: &mut Box, - global_variables: &mut GlobalVarDir, + code_repo: &CodeRepo, ) { + fn dynamic_external_of_clause_is_valid( + machine_st: &mut MachineState, + code: &Code, + p: usize, + ) -> bool { + match &code[p] { + Line::Choice(ChoiceInstruction::DynamicInternalElse(..)) => { + machine_st.dynamic_mode = FirstOrNext::First; + return true; + } + _ => {} + } + + match &code[p-1] { + &Line::Choice(ChoiceInstruction::DynamicInternalElse(birth, death, _)) => { + if birth < machine_st.cc && Death::Finite(machine_st.cc) <= death { + return true; + } else { + return false; + } + } + _ => {} + } + + true + } + let mut index = 0; let addr = match &indexing_lines[0] { &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => { @@ -1323,7 +1351,7 @@ impl MachineState { IndexingCodePtr::Fail } Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => { - IndexingCodePtr::External(v) + v } Addr::PStrLocation(..) => l, Addr::Char(_) @@ -1342,6 +1370,20 @@ impl MachineState { self.fail = true; break; } + IndexingCodePtr::DynamicExternal(o) => { + // either points directly to a + // DynamicInternalElse, or just ahead of + // one. Or neither! + let p = self.p.local().abs_loc(); + + if !dynamic_external_of_clause_is_valid(self, &code_repo.code, p + o) { + self.fail = true; + } else { + self.p += o; + } + + break; + } IndexingCodePtr::External(o) => { self.p += o; break; @@ -1365,6 +1407,20 @@ impl MachineState { self.fail = true; break; } + IndexingCodePtr::DynamicExternal(o) => { + // either points directly to a + // DynamicInternalElse, or just ahead of + // one. Or neither! + let p = self.p.local().abs_loc(); + + if !dynamic_external_of_clause_is_valid(self, &code_repo.code, p + o) { + self.fail = true; + } else { + self.p += o; + } + + break; + } IndexingCodePtr::External(o) => { self.p += o; break; @@ -1394,6 +1450,17 @@ impl MachineState { self.fail = true; break; } + IndexingCodePtr::DynamicExternal(o) => { + let p = self.p.local().abs_loc(); + + if !dynamic_external_of_clause_is_valid(self, &code_repo.code, p + o) { + self.fail = true; + } else { + self.p += o; + } + + break; + } IndexingCodePtr::External(o) => { self.p += o; break; @@ -1403,18 +1470,23 @@ impl MachineState { } } } - &IndexingLine::IndexedChoice(ref instrs) => { + &IndexingLine::IndexedChoice(_) => { if let LocalCodePtr::DirEntry(p) = self.p.local() { self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(p, index, 0)); } else { unreachable!() } - self.execute_indexed_choice_instr( - instrs.first().unwrap(), - call_policy, - global_variables, - ); + break; + } + &IndexingLine::DynamicIndexedChoice(_) => { + self.dynamic_mode = FirstOrNext::First; + + if let LocalCodePtr::DirEntry(p) = self.p.local() { + self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(p, index, 0)); + } else { + unreachable!() + } break; } @@ -3028,6 +3100,113 @@ impl MachineState { }; } + pub(super) fn execute_dynamic_indexed_choice_instr( + &mut self, + code_repo: &CodeRepo, + call_policy: &mut Box, + global_variables: &mut GlobalVarDir, + ) { + let p = self.p.local(); + + match code_repo.find_living_dynamic(p, self.cc) { + Some((offset, oi, ii, is_next_clause)) => { + self.p = CodePtr::Local(LocalCodePtr::IndexingBuf( + p.abs_loc(), oi, ii, + )); + + match self.dynamic_mode { + FirstOrNext::First if !is_next_clause => { + self.p = CodePtr::Local(LocalCodePtr::DirEntry( + p.abs_loc() + offset, + )); + } + FirstOrNext::First => { + // there's a leading DynamicElse that sets self.cc. + // self.cc = self.global_clock; + + match code_repo.find_living_dynamic( + LocalCodePtr::IndexingBuf(p.abs_loc(), oi, ii + 1), + self.cc, + ) { + Some(_) => { + self.registers[self.num_of_args + 1] = Addr::Usize(self.cc); + self.num_of_args += 1; + + self.execute_indexed_choice_instr( + &IndexedChoiceInstruction::Try(offset), + call_policy, + global_variables, + ); + + self.num_of_args -= 1; + } + None => { + self.p = CodePtr::Local(LocalCodePtr::DirEntry( + p.abs_loc() + offset, + )); + } + } + } + FirstOrNext::Next => { + let n = self + .stack + .index_or_frame(self.b) + .prelude + .univ_prelude + .num_cells; + + self.cc = match self.stack.index_or_frame(self.b)[n - 1] { + Addr::Usize(cc) => cc, + _ => unreachable!(), + }; + + if is_next_clause { + match code_repo.find_living_dynamic( + LocalCodePtr::IndexingBuf(p.abs_loc(), oi, ii + 1), + self.cc, + ) { + Some(_) => { + try_or_fail!( + self, + call_policy.retry( + self, + offset, + global_variables, + ) + ) + } + None => { + try_or_fail!( + self, + call_policy.trust( + self, + offset, + global_variables, + ) + ) + } + } + } else { + try_or_fail!( + self, + call_policy.trust( + self, + offset, + global_variables, + ) + ) + } + } + } + + self.dynamic_mode = FirstOrNext::Next; + } + None => { + self.fail = true; + } + } + } + pub(super) fn execute_indexed_choice_instr( &mut self, instr: &IndexedChoiceInstruction, @@ -3073,10 +3252,187 @@ impl MachineState { pub(super) fn execute_choice_instr( &mut self, instr: &ChoiceInstruction, + code_repo: &CodeRepo, call_policy: &mut Box, global_variables: &mut GlobalVarDir, ) { match instr { + &ChoiceInstruction::DynamicElse(..) => { + if let FirstOrNext::First = self.dynamic_mode { + self.cc = self.global_clock; + } + + let p = self.p.local().abs_loc(); + + match code_repo.find_living_dynamic_else(p, self.cc) { + Some((p, next_i)) => { + self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); + + match self.dynamic_mode { + FirstOrNext::First if next_i == 0 => { + self.p = CodePtr::Local(LocalCodePtr::DirEntry(p + 1)); + } + FirstOrNext::First => { + self.cc = self.global_clock; + + match code_repo.find_living_dynamic_else(p + next_i, self.cc) { + Some(_) => { + self.registers[self.num_of_args + 1] = Addr::Usize(self.cc); + self.num_of_args += 1; + + self.execute_choice_instr( + &ChoiceInstruction::TryMeElse(next_i), + code_repo, + call_policy, + global_variables, + ); + + self.num_of_args -= 1; + } + None => { + self.p += 1; + } + } + } + FirstOrNext::Next => { + let n = self + .stack + .index_or_frame(self.b) + .prelude + .univ_prelude + .num_cells; + + self.cc = match self.stack.index_or_frame(self.b)[n - 1] { + Addr::Usize(cc) => cc, + _ => unreachable!(), + }; + + if next_i > 0 { + match code_repo.find_living_dynamic_else(p + next_i, self.cc) { + Some(_) => { + try_or_fail!( + self, + call_policy.retry_me_else( + self, + next_i, + global_variables, + ) + ) + } + None => { + try_or_fail!( + self, + call_policy.trust_me( + self, + global_variables, + ) + ) + } + } + } else { + try_or_fail!( + self, + call_policy.trust_me( + self, + global_variables, + ) + ) + } + } + } + } + None => { + self.fail = true; + } + } + + self.dynamic_mode = FirstOrNext::Next; + } + &ChoiceInstruction::DynamicInternalElse(..) => { + let p = self.p.local().abs_loc(); + + match code_repo.find_living_dynamic_else(p, self.cc) { + Some((p, next_i)) => { + self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); + + match self.dynamic_mode { + FirstOrNext::First if next_i == 0 => { + self.p = CodePtr::Local(LocalCodePtr::DirEntry(p + 1)); + } + FirstOrNext::First => { + match code_repo.find_living_dynamic_else(p + next_i, self.cc) { + Some(_) => { + self.registers[self.num_of_args + 1] = Addr::Usize(self.cc); + self.num_of_args += 1; + + self.execute_choice_instr( + &ChoiceInstruction::TryMeElse(next_i), + code_repo, + call_policy, + global_variables, + ); + + self.num_of_args -= 1; + } + None => { + self.p += 1; + } + } + } + FirstOrNext::Next => { + let n = self + .stack + .index_or_frame(self.b) + .prelude + .univ_prelude + .num_cells; + + self.cc = match self.stack.index_or_frame(self.b)[n - 1] { + Addr::Usize(cc) => cc, + _ => unreachable!(), + }; + + if next_i > 0 { + match code_repo.find_living_dynamic_else(p + next_i, self.cc) { + Some(_) => { + try_or_fail!( + self, + call_policy.retry_me_else( + self, + next_i, + global_variables, + ) + ) + } + None => { + try_or_fail!( + self, + call_policy.trust_me( + self, + global_variables, + ) + ) + } + } + } else { + try_or_fail!( + self, + call_policy.trust_me( + self, + global_variables, + ) + ) + } + } + } + } + None => { + self.fail = true; + } + } + + self.dynamic_mode = FirstOrNext::Next; + } &ChoiceInstruction::TryMeElse(offset) => { let n = self.num_of_args; let b = self.stack.allocate_or_frame(n); diff --git a/src/machine/mod.rs b/src/machine/mod.rs index d23580ba..b0f607f2 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -562,6 +562,7 @@ impl MachineState { &Line::Choice(ref choice_instr) => { self.execute_choice_instr( choice_instr, + code_repo, &mut policies.call_policy, &mut indices.global_variables, ) @@ -585,8 +586,7 @@ impl MachineState { &Line::IndexingCode(ref indexing_lines) => { self.execute_indexing_instr( indexing_lines, - &mut policies.call_policy, - &mut indices.global_variables, + code_repo, ) } &Line::IndexedChoice(ref choice_instr) => { @@ -596,6 +596,13 @@ impl MachineState { &mut indices.global_variables, ) } + &Line::DynamicIndexedChoice(_) => { + self.execute_dynamic_indexed_choice_instr( + code_repo, + &mut policies.call_policy, + &mut indices.global_variables, + ) + } &Line::Query(ref query_instr) => { self.execute_query_instr(&query_instr); self.p += 1; diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 72e6b3a9..a2307ed2 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -3496,14 +3496,16 @@ impl MachineState { 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) => indices - .get_predicate_code_index( + &HeapCellValue::NamedStr(arity, ref name, ref spec) => { + CLAUSE_TYPE_FORMS.borrow().get(&(name.as_str(), arity)).is_some() || + indices.get_predicate_code_index( name.clone(), arity, module_name, spec.clone(), ) - .is_some(), + .is_some() + } _ => { unreachable!() } @@ -3513,8 +3515,8 @@ impl MachineState { let spec = fetch_atom_op_spec(name.clone(), spec.clone(), &indices.op_dir); - indices - .get_predicate_code_index(name.clone(), 0, module_name, spec) + CLAUSE_TYPE_FORMS.borrow().get(&(name.as_str(), 0)).is_some() || + indices.get_predicate_code_index(name.clone(), 0, module_name, spec) .is_some() } else { unreachable!() diff --git a/src/macros.rs b/src/macros.rs index 7e03e231..b8b6d802 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -126,6 +126,7 @@ macro_rules! functor_term { (indexing_code_ptr($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({ let stub = match $e { + IndexingCodePtr::DynamicExternal(o) => functor!("dynamic_external", [integer(o)]), IndexingCodePtr::External(o) => functor!("external", [integer(o)]), IndexingCodePtr::Internal(o) => functor!("internal", [integer(o)]), IndexingCodePtr::Fail => vec![HeapCellValue::Atom(clause_name!("fail"), None)], diff --git a/src/write.rs b/src/write.rs index e98b550f..4aa84e99 100644 --- a/src/write.rs +++ b/src/write.rs @@ -96,7 +96,7 @@ impl fmt::Display for IndexPtr { match self { &IndexPtr::DynamicUndefined => write!(f, "undefined"), &IndexPtr::Undefined => write!(f, "undefined"), - &IndexPtr::Index(i) => write!(f, "{}", i), + &IndexPtr::DynamicIndex(i) | &IndexPtr::Index(i) => write!(f, "{}", i), } } } @@ -339,6 +339,30 @@ impl fmt::Display for IndexedChoiceInstruction { impl fmt::Display for ChoiceInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + &ChoiceInstruction::DynamicElse(offset, Death::Infinity, NextOrFail::Next(i)) => { + write!(f, "dynamic_else {}, {}, {}", offset, "inf", i) + } + &ChoiceInstruction::DynamicElse(offset, Death::Infinity, NextOrFail::Fail(i)) => { + write!(f, "dynamic_else {}, {}, fail({})", offset, "inf", i) + } + &ChoiceInstruction::DynamicElse(offset, Death::Finite(d), NextOrFail::Next(i)) => { + write!(f, "dynamic_else {}, {}, {}", offset, d, i) + } + &ChoiceInstruction::DynamicElse(offset, Death::Finite(d), NextOrFail::Fail(i)) => { + write!(f, "dynamic_else {}, {}, fail({})", offset, d, i) + } + &ChoiceInstruction::DynamicInternalElse(offset, Death::Infinity, NextOrFail::Next(i)) => { + write!(f, "dynamic_internal_else {}, {}, {}", offset, "inf", i) + } + &ChoiceInstruction::DynamicInternalElse(offset, Death::Infinity, NextOrFail::Fail(i)) => { + write!(f, "dynamic_internal_else {}, {}, fail({})", offset, "inf", i) + } + &ChoiceInstruction::DynamicInternalElse(offset, Death::Finite(d), NextOrFail::Next(i)) => { + write!(f, "dynamic_internal_else {}, {}, {}", offset, d, i) + } + &ChoiceInstruction::DynamicInternalElse(offset, Death::Finite(d), NextOrFail::Fail(i)) => { + write!(f, "dynamic_internal_else {}, {}, fail({})", offset, d, i) + } &ChoiceInstruction::TryMeElse(offset) => write!(f, "try_me_else {}", offset), &ChoiceInstruction::DefaultRetryMeElse(offset) => { @@ -357,6 +381,9 @@ impl fmt::Display for ChoiceInstruction { impl fmt::Display for IndexingCodePtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + &IndexingCodePtr::DynamicExternal(o) => { + write!(f, "IndexingCodePtr::DynamicExternal({})", o) + } &IndexingCodePtr::External(o) => { write!(f, "IndexingCodePtr::External({})", o) } @@ -480,6 +507,13 @@ impl fmt::Display for IndexingLine { write!(f, "{}", indexed_choice_instr)?; } + Ok(()) + } + &IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { + for indexed_choice_instr in indexed_choice_instrs { + write!(f, "dynamic({})", indexed_choice_instr)?; + } + Ok(()) } } @@ -502,6 +536,7 @@ impl fmt::Display for Line { Ok(()) } &Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr), + &Line::DynamicIndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr), &Line::Query(ref query_instr) => write!(f, "{}", query_instr), } } From 590a0b807787a4561966e70a1b9cdffdbc8bf80c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 27 Feb 2021 23:56:58 -0700 Subject: [PATCH 119/137] update the parser with the number of lines already read by the underlying stream (#836) --- crates/prolog_parser/src/parser.rs | 5 +++++ src/machine/streams.rs | 5 +++++ src/read.rs | 8 +++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/crates/prolog_parser/src/parser.rs b/crates/prolog_parser/src/parser.rs index 0fa142f6..c72d6453 100644 --- a/crates/prolog_parser/src/parser.rs +++ b/crates/prolog_parser/src/parser.rs @@ -965,6 +965,11 @@ impl<'a, R: Read> Parser<'a, R> { self.lexer.eof() } + #[inline] + pub fn add_lines_read(&mut self, lines_read: usize) { + self.lexer.line_num += lines_read; + } + #[inline] pub fn num_lines_read(&self) -> usize { self.lexer.line_num diff --git a/src/machine/streams.rs b/src/machine/streams.rs index c08a6ae5..56bb3836 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -366,6 +366,11 @@ impl Stream { ptr as *const u8 } + #[inline] + pub(crate) fn lines_read(&mut self) -> usize { + self.stream_inst.0.borrow_mut().lines_read + } + #[inline] pub(crate) fn add_lines_read(&mut self, incr_num_lines_read: usize) { self.stream_inst.0.borrow_mut().lines_read += incr_num_lines_read; diff --git a/src/read.rs b/src/read.rs index fa158414..5d7d85c0 100644 --- a/src/read.rs +++ b/src/read.rs @@ -185,7 +185,6 @@ impl MachineState { let mut parser = Parser::new(&mut stream, atom_tbl, self.flags); parser.devour_whitespace()?; - inner.add_lines_read(parser.num_lines_read()); let result = parser.eof(); let buf = stream.take_buf(); @@ -203,10 +202,13 @@ impl MachineState { let mut stream = parsing_stream(inner.clone())?; let (term, num_lines_read) = { + let prior_num_lines_read = inner.lines_read(); let mut parser = Parser::new(&mut stream, atom_tbl, self.flags); - let term = parser.read_term(&CompositeOpDir::new(op_dir, None))?; - (term, parser.num_lines_read()) + parser.add_lines_read(prior_num_lines_read); + + let term = parser.read_term(&CompositeOpDir::new(op_dir, None))?; + (term, parser.num_lines_read() - prior_num_lines_read) }; inner.add_lines_read(num_lines_read); From 8c7494885fd9104f762c5905747ea2b4a16bc945 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 00:27:50 -0700 Subject: [PATCH 120/137] set compilation_target of assert loader to match that of predicate qualifier --- src/machine/loader.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 691871c6..8b09a46c 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1738,6 +1738,8 @@ impl Machine { let compile_assert = || { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); + loader.load_state.compilation_target = compilation_target.clone(); + let head = loader.read_term_from_heap(temp_v!(1))?; let body = loader.read_term_from_heap(temp_v!(2))?; From 0747697d1080b4236fa6625e4728704600ca386a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 02:09:53 -0700 Subject: [PATCH 121/137] add lines read from devour_whitespace (#836) --- src/read.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/read.rs b/src/read.rs index 5d7d85c0..78de8e30 100644 --- a/src/read.rs +++ b/src/read.rs @@ -186,10 +186,13 @@ impl MachineState { parser.devour_whitespace()?; + inner.add_lines_read(parser.num_lines_read()); + let result = parser.eof(); let buf = stream.take_buf(); inner.pause_stream(buf)?; + result } From 8e6a89b2792bd03c6ef09c16d08185dffd964a6e Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 09:15:03 -0700 Subject: [PATCH 122/137] enable op declarations with lists of operands using term expansion (#839) --- src/toplevel.pl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/toplevel.pl b/src/toplevel.pl index b46bf49d..4a861259 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -108,6 +108,17 @@ repl :- repl :- repl. +%% Enable op declarations with lists of operands, i.e., +%% :- op(900, fy, [$,@]). + +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). + + read_and_match :- '$read_query_term'(_, Term, _, _, VarList), instruction_match(Term, VarList). From a36781234890f26085d8fa79a9a541ad2a49ace4 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 10:41:32 -0700 Subject: [PATCH 123/137] add occurs_check flag (#309) --- src/clause_types.rs | 9 ++ src/lib/builtins.pl | 8 ++ src/machine/loader.rs | 20 +-- src/machine/machine_state.rs | 61 ++++++-- src/machine/machine_state_impl.rs | 30 ++-- src/machine/system_calls.rs | 223 ++++++++++++++++-------------- 6 files changed, 210 insertions(+), 141 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 1804040a..dc2d0150 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -304,6 +304,9 @@ pub enum SystemClauseType { UnsetEnv, CharsBase64, DevourWhitespace, + IsSTOEnabled, + SetSTOAsUnify, + SetNSTOAsUnify, } impl SystemClauseType { @@ -585,6 +588,9 @@ impl SystemClauseType { &SystemClauseType::CharsBase64 => clause_name!("$chars_base64"), &SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"), &SystemClauseType::DevourWhitespace => clause_name!("$devour_whitespace"), + &SystemClauseType::IsSTOEnabled => clause_name!("$is_sto_enabled"), + &SystemClauseType::SetSTOAsUnify => clause_name!("$set_sto_as_unify"), + &SystemClauseType::SetNSTOAsUnify => clause_name!("$set_nsto_as_unify"), } } @@ -830,6 +836,9 @@ impl SystemClauseType { ("$devour_whitespace", 1) => { Some(SystemClauseType::DevourWhitespace) } + ("$is_sto_enabled", 1) => Some(SystemClauseType::IsSTOEnabled), + ("$set_sto_as_unify", 0) => Some(SystemClauseType::SetSTOAsUnify), + ("$set_nsto_as_unify", 0) => Some(SystemClauseType::SetNSTOAsUnify), _ => None, } } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index bc393c40..3c9a380e 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -133,6 +133,10 @@ current_prolog_flag(Flag, Value) :- Flag == double_quotes, !, '$get_double_quote current_prolog_flag(double_quotes, Value) :- '$get_double_quotes'(Value). current_prolog_flag(Flag, _) :- Flag == max_integer, !, '$fail'. current_prolog_flag(Flag, _) :- Flag == min_integer, !, '$fail'. +current_prolog_flag(Flag, OccursCheckEnabled) :- + Flag == occurs_check, + !, + '$is_sto_enabled'(OccursCheckEnabled). current_prolog_flag(Flag, _) :- atom(Flag), throw(error(domain_error(prolog_flag, Flag), current_prolog_flag/2)). % 8.17.2.3 b @@ -163,6 +167,10 @@ set_prolog_flag(double_quotes, atom) :- !, '$set_double_quotes'(atom). % 7.11.2.5, list of char codes (UTF8). set_prolog_flag(double_quotes, codes) :- !, '$set_double_quotes'(codes). +set_prolog_flag(occurs_check, true) :- + !, '$set_sto_as_unify'. +set_prolog_flag(occurs_check, false) :- + !, '$set_nsto_as_unify'. set_prolog_flag(double_quotes, Value) :- throw(error(domain_error(flag_value, double_quotes + Value), set_prolog_flag/2)). % 8.17.1.3 e diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 8b09a46c..a98c8fc0 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1631,8 +1631,7 @@ impl Machine { .push(HeapCellValue::Atom(path_atom, None)), ); - self.machine_st - .unify(path_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(path_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } @@ -1652,9 +1651,7 @@ impl Machine { .push(HeapCellValue::Atom(file_name_atom, None)), ); - self.machine_st - .unify(file_name_addr, self.machine_st[temp_v!(1)]); - + self.machine_st.unify(file_name_addr, self.machine_st[temp_v!(1)]); return; } _ => { @@ -1680,8 +1677,7 @@ impl Machine { .push(HeapCellValue::Atom(directory_atom, None)), ); - self.machine_st - .unify(directory_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(directory_addr, self.machine_st[temp_v!(1)]); return; } } @@ -1697,8 +1693,7 @@ impl Machine { .push(HeapCellValue::Atom(load_context.module.clone(), None)), ); - self.machine_st - .unify(module_name_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(module_name_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } @@ -1712,8 +1707,7 @@ impl Machine { .push(HeapCellValue::Stream(load_context.stream.clone())), ); - self.machine_st - .unify(stream_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(stream_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } @@ -2064,8 +2058,8 @@ impl Machine { self.machine_st .heap .push(HeapCellValue::Addr(Addr::HeapCell(list_loc))); - self.machine_st - .unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(4)]); + + self.machine_st.unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(4)]); } None => { self.machine_st.fail = true; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 71801f3b..87af5a41 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -275,7 +275,7 @@ pub enum FirstOrNext { Next, } -#[derive(Debug)] +// #[derive(Debug)] pub struct MachineState { pub(crate) atom_tbl: TabledData, pub(super) s: HeapPtr, @@ -299,11 +299,48 @@ pub struct MachineState { pub(super) lifted_heap: Heap, pub(super) interms: Vec, // intermediate numbers. pub(super) last_call: bool, - pub(crate) heap_locs: HeapVarDict, pub(crate) flags: MachineFlags, pub(crate) cc: usize, pub(crate) global_clock: usize, pub(crate) dynamic_mode: FirstOrNext, + pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr), +} + +impl fmt::Debug for MachineState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("MachineState") + .field("atom_tbl", &self.atom_tbl) + .field("s", &self.s) + .field("p", &self.p) + .field("b", &self.b) + .field("b0", &self.b0) + .field("e", &self.e) + .field("num_of_args", &self.num_of_args) + .field("cp", &self.cp) + .field("attr_var_init", &self.attr_var_init) + .field("fail", &self.fail) + .field("heap", &self.heap) + .field("mode", &self.mode) + .field("stack", &self.stack) + .field("registers", &self.registers) + .field("trail", &self.trail) + .field("tr", &self.tr) + .field("hb", &self.hb) + .field("block", &self.block) + .field("ball", &self.ball) + .field("lifted_heap", &self.lifted_heap) + .field("interms", &self.interms) + .field("last_call", &self.last_call) + .field("flags", &self.flags) + .field("cc", &self.cc) + .field("global_clock", &self.global_clock) + .field("dynamic_mode", &self.dynamic_mode) + .field("unify_fn", + if self.unify_fn as usize == MachineState::unify as usize + { &"MachineState::unify" } + else { &"MachineState::unify_with_occurs_check" }) + .finish() + } } impl MachineState { @@ -354,7 +391,7 @@ impl MachineState { match self.read(stream.clone(), self.atom_tbl.clone(), &indices.op_dir) { Ok(term_write_result) => { let term = self[temp_v!(2)]; - self.unify(Addr::HeapCell(term_write_result.heap_loc), term); + (self.unify_fn)(self, Addr::HeapCell(term_write_result.heap_loc), term); if self.fail { return Ok(()); @@ -398,7 +435,7 @@ impl MachineState { let singletons_offset = Addr::HeapCell(self.heap.to_list(singleton_var_list.into_iter())); - self.unify(singletons_offset, singleton_addr); + (self.unify_fn)(self, singletons_offset, singleton_addr); if self.fail { return Ok(()); @@ -407,7 +444,7 @@ impl MachineState { let vars_addr = self[temp_v!(4)]; let vars_offset = Addr::HeapCell(self.heap.to_list(var_list.into_iter())); - self.unify(vars_offset, vars_addr); + (self.unify_fn)(self, vars_offset, vars_addr); if self.fail { return Ok(()); @@ -417,7 +454,7 @@ impl MachineState { let var_names_offset = Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter())); - return Ok(self.unify(var_names_offset, var_names_addr)); + return Ok((self.unify_fn)(self, var_names_offset, var_names_addr)); } Err(err) => { if let ParserError::UnexpectedEOF = err { @@ -1027,7 +1064,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let h = machine_st.heap.h(); machine_st.heap.push(atom); - machine_st.unify(a1, Addr::Con(h)); + (machine_st.unify_fn)(machine_st, a1, Addr::Con(h)); return_from_clause!(machine_st.last_call, machine_st) } @@ -1049,7 +1086,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { ) { Ok(offset) => { let addr = machine_st[temp_v!(1)]; - machine_st.unify(addr, Addr::HeapCell(offset.heap_loc)); + (machine_st.unify_fn)(machine_st, addr, Addr::HeapCell(offset.heap_loc)); } Err(ParserError::UnexpectedEOF) => { let addr = machine_st[temp_v!(1)]; @@ -1057,7 +1094,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let atom = machine_st.heap.to_unifiable(HeapCellValue::Atom(eof, None)); - machine_st.unify(addr, atom); + (machine_st.unify_fn)(machine_st, addr, atom); } Err(e) => { let h = machine_st.heap.h(); @@ -1121,7 +1158,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter())); let r2 = machine_st[temp_v!(2)]; - machine_st.unify(r2, heap_addr); + (machine_st.unify_fn)(machine_st, r2, heap_addr); return_from_clause!(machine_st.last_call, machine_st) } @@ -1147,7 +1184,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs)); let r2 = machine_st[temp_v!(2)]; - machine_st.unify(r2, heap_addr); + (machine_st.unify_fn)(machine_st, r2, heap_addr); return_from_clause!(machine_st.last_call, machine_st) } @@ -1156,7 +1193,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let n2 = machine_st.get_number(at)?; let n2 = machine_st.heap.put_constant(n2.into()); - machine_st.unify(a1, n2); + (machine_st.unify_fn)(machine_st, a1, n2); return_from_clause!(machine_st.last_call, machine_st) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 3262daa5..5ae448f9 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -52,11 +52,11 @@ impl MachineState { lifted_heap: Heap::new(), interms: vec![Number::default(); 256], last_call: false, - heap_locs: HeapVarDict::new(), flags: MachineFlags::default(), cc: 0, global_clock: 0, dynamic_mode: FirstOrNext::First, + unify_fn: MachineState::unify, } } @@ -770,7 +770,7 @@ impl MachineState { self.heap.put_complete_string(&string[prefix_len..]) }; - self.unify(Addr::Lis(l), pstr_addr); + (self.unify_fn)(self, Addr::Lis(l), pstr_addr); } _ => { self.fail = true; @@ -839,7 +839,7 @@ impl MachineState { } Addr::Lis(l) => { let addr = self.heap.put_constant(c.clone()); - self.unify(Addr::Lis(l), addr); + (self.unify_fn)(self, Addr::Lis(l), addr); } Addr::PStrLocation(h, n) => { if let Constant::String(ref s2) = c { @@ -857,7 +857,7 @@ impl MachineState { if let Some(r) = addr.as_var() { self.bind(r, c); } else { - self.unify(addr, c); + (self.unify_fn)(self, addr, c); } } }; @@ -1209,7 +1209,7 @@ impl MachineState { let norm_addr = self[norm]; let reg_addr = self.registers[arg]; - self.unify(norm_addr, reg_addr); + (self.unify_fn)(self, norm_addr, reg_addr); } &FactInstruction::UnifyConstant(ref c) => { match self.mode { @@ -1247,7 +1247,7 @@ impl MachineState { MachineMode::Read => { let reg_addr = self[reg]; - self.unify(reg_addr, self.s.read(&self.heap)); + (self.unify_fn)(self, reg_addr, self.s.read(&self.heap)); self.increment_s_ptr(1); } MachineMode::Write => { @@ -1275,7 +1275,7 @@ impl MachineState { MachineMode::Read => { let reg_addr = self[reg]; - self.unify(reg_addr, self.s.read(&self.heap)); + (self.unify_fn)(self, reg_addr, self.s.read(&self.heap)); self.increment_s_ptr(1); } MachineMode::Write => { @@ -1778,7 +1778,7 @@ impl MachineState { let a3 = self[temp_v!(3)]; let h_a = Addr::HeapCell(o + n); - self.unify(a3, h_a); + (self.unify_fn)(self, a3, h_a); } _ => { self.fail = true; @@ -1789,7 +1789,7 @@ impl MachineState { let a3 = self[temp_v!(3)]; let h_a = Addr::HeapCell(l + n - 1); - self.unify(a3, h_a); + (self.unify_fn)(self, a3, h_a); } else { self.fail = true; } @@ -1812,7 +1812,7 @@ impl MachineState { unreachable!() }; - self.unify(a3, h_a); + (self.unify_fn)(self, a3, h_a); } else { self.fail = true; } @@ -2396,10 +2396,10 @@ impl MachineState { let a2 = self[temp_v!(2)]; let a3 = self[temp_v!(3)]; - self.unify(a2, name); + (self.unify_fn)(self, a2, name); if !self.fail { - self.unify(a3, Addr::Usize(arity)); + (self.unify_fn)(self, a3, Addr::Usize(arity)); } } @@ -2520,7 +2520,7 @@ impl MachineState { | Addr::Usize(_) if arity == 0 => { - self.unify(a1, name); + (self.unify_fn)(self, a1, name); } Addr::Con(h) => { if let HeapCellValue::Atom(name, spec) = self.heap.clone(h) { @@ -2763,7 +2763,7 @@ impl MachineState { copy_term(CopyTerm::new(self), a1, attr_var_policy); - self.unify(Addr::HeapCell(old_h), a2); + (self.unify_fn)(self, Addr::HeapCell(old_h), a2); } // returns true on failure. @@ -3505,7 +3505,7 @@ impl MachineState { let b0 = self[perm_v!(1)]; let a = self[r]; - self.unify(a, b0); + (self.unify_fn)(self, a, b0); self.p += 1; } &CutInstruction::Cut(r) => { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index a2307ed2..0dacd2aa 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -253,11 +253,11 @@ impl MachineState { fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) { let target_n = self[temp_v!(1)]; - self.unify(Addr::Usize(n), target_n); + (self.unify_fn)(self, Addr::Usize(n), target_n); if !self.fail { let xs = self[temp_v!(4)]; - self.unify(addr, xs); + (self.unify_fn)(self, addr, xs); } } @@ -313,7 +313,7 @@ impl MachineState { let xs0 = self[temp_v!(3)]; let xs = self[temp_v!(4)]; - self.unify(xs0, xs); + (self.unify_fn)(self, xs0, xs); } else { self.skip_max_list_result(max_steps_n); } @@ -323,7 +323,7 @@ impl MachineState { let xs0 = self[temp_v!(3)]; let xs = self[temp_v!(4)]; - self.unify(xs0, xs); + (self.unify_fn)(self, xs0, xs); } else { self.skip_max_list_result(max_steps_n); } @@ -630,19 +630,19 @@ impl MachineState { } Ok(Term::Constant(_, Constant::Rational(n))) => { let addr = self.heap.put_constant(Constant::Rational(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } Ok(Term::Constant(_, Constant::Float(n))) => { let addr = self.heap.put_constant(Constant::Float(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } Ok(Term::Constant(_, Constant::Integer(n))) => { let addr = self.heap.put_constant(Constant::Integer(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } Ok(Term::Constant(_, Constant::Fixnum(n))) => { let addr = self.heap.put_constant(Constant::Fixnum(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } _ => { let err = ParserError::ParseBigInt(0, 0); @@ -668,7 +668,7 @@ impl MachineState { let attr_goals = Addr::HeapCell(self.heap.to_list(attr_goals.into_iter())); let target = self[temp_v!(1)]; - self.unify(attr_goals, target); + (self.unify_fn)(self, attr_goals, target); } fn call_continuation_chunk(&mut self, chunk: Addr, return_p: LocalCodePtr) -> LocalCodePtr { @@ -742,7 +742,7 @@ impl MachineState { let target = self[temp_v!(n)]; let addr = self[temp_v!(1)]; - self.unify(addr, target); + (self.unify_fn)(self, addr, target); return return_from_clause!(self.last_call, self); } } @@ -758,7 +758,7 @@ impl MachineState { None, )); - self.unify(self[temp_v!(1)], hostname); + (self.unify_fn)(self, self[temp_v!(1)], hostname); return return_from_clause!(self.last_call, self); } None => {} @@ -777,7 +777,7 @@ impl MachineState { match addr { addr if addr.is_ref() => { let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream)); - self.unify(stream, addr); + (self.unify_fn)(self, stream, addr); } Addr::Stream(other_stream) => { if let HeapCellValue::Stream(ref other_stream) = &self.heap[other_stream] { @@ -802,7 +802,7 @@ impl MachineState { match addr { addr if addr.is_ref() => { let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream)); - self.unify(stream, addr); + (self.unify_fn)(self, stream, addr); } Addr::Stream(other_stream) => { if let HeapCellValue::Stream(ref other_stream) = &self.heap[other_stream] { @@ -849,7 +849,7 @@ impl MachineState { } let files_list = Addr::HeapCell(self.heap.to_list(files.into_iter())); - self.unify(self[temp_v!(2)], files_list); + (self.unify_fn)(self, self[temp_v!(2)], files_list); } &SystemClauseType::FileSize => { let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); @@ -857,7 +857,7 @@ impl MachineState { let len = self.heap.to_unifiable(HeapCellValue::Integer(Rc::new(len))); - self.unify(self[temp_v!(2)], len); + (self.unify_fn)(self, self[temp_v!(2)], len); } &SystemClauseType::FileExists => { let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); @@ -880,7 +880,7 @@ impl MachineState { let addr = self .heap .put_constant(Constant::Char(std::path::MAIN_SEPARATOR)); - self.unify(self[temp_v!(1)], addr); + (self.unify_fn)(self, self[temp_v!(1)], addr); } &SystemClauseType::MakeDirectory => { let directory = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); @@ -919,7 +919,7 @@ impl MachineState { }; let chars = self.heap.put_complete_string(current); - self.unify(self[temp_v!(1)], chars); + (self.unify_fn)(self, self[temp_v!(1)], chars); let next = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); @@ -952,7 +952,7 @@ impl MachineState { } }; let chars = self.heap.put_complete_string(cs); - self.unify(self[temp_v!(2)], chars); + (self.unify_fn)(self, self[temp_v!(2)], chars); } _ => { self.fail = true; @@ -986,7 +986,7 @@ impl MachineState { } } { let chars = self.systemtime_to_timestamp(time); - self.unify(self[temp_v!(3)], chars); + (self.unify_fn)(self, self[temp_v!(3)], chars); } else { self.fail = true; return Ok(()); @@ -1005,14 +1005,14 @@ impl MachineState { let list_of_chars = Addr::HeapCell(self.heap.to_list(iter)); let a2 = self[temp_v!(2)]; - self.unify(a2, list_of_chars); + (self.unify_fn)(self, a2, list_of_chars); } Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(name, _) = self.heap.clone(h) { let s = self.heap.put_complete_string(name.as_str()); let a2 = self[temp_v!(2)]; - self.unify(s, a2); + (self.unify_fn)(self, s, a2); } else { unreachable!() } @@ -1023,7 +1023,7 @@ impl MachineState { let list_of_chars = Addr::HeapCell(self.heap.to_list(chars.into_iter())); - self.unify(a2, list_of_chars); + (self.unify_fn)(self, a2, list_of_chars); } addr if addr.is_ref() => { let mut iter = self.heap_pstr_iter(self[temp_v!(2)]); @@ -1032,13 +1032,13 @@ impl MachineState { match iter.focus() { Addr::EmptyList => { if &string == "[]" { - self.unify(addr, Addr::EmptyList); + (self.unify_fn)(self, addr, Addr::EmptyList); } else { let chars = clause_name!(string, self.atom_tbl); let atom = self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); - self.unify(addr, atom); + (self.unify_fn)(self, addr, atom); } } focus => { @@ -1071,7 +1071,7 @@ impl MachineState { let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); let a2 = self[temp_v!(2)]; - self.unify(a2, list_of_codes); + (self.unify_fn)(self, a2, list_of_codes); } Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(name, _) = self.heap.clone(h) { @@ -1081,7 +1081,7 @@ impl MachineState { let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); - self.unify(a2, list_of_codes); + (self.unify_fn)(self, a2, list_of_codes); } else { unreachable!() } @@ -1092,7 +1092,7 @@ impl MachineState { let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter())); let a2 = self[temp_v!(2)]; - self.unify(a2, list_of_codes); + (self.unify_fn)(self, a2, list_of_codes); } addr if addr.is_ref() => { let stub = MachineError::functor_stub(clause_name!("atom_codes"), 2); @@ -1180,7 +1180,7 @@ impl MachineState { let a2 = self[temp_v!(2)]; - self.unify(a2, len); + (self.unify_fn)(self, a2, len); } &SystemClauseType::CallContinuation => { let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1); @@ -1244,13 +1244,13 @@ impl MachineState { } let pstr = self.heap.allocate_pstr(atom.as_str()); - self.unify(self[temp_v!(2)], pstr); + (self.unify_fn)(self, self[temp_v!(2)], pstr); if !self.fail { let h = self.heap.h(); let pstr_tail = self.heap[h - 1].as_addr(h - 1); - self.unify(self[temp_v!(3)], pstr_tail); + (self.unify_fn)(self, self[temp_v!(3)], pstr_tail); } } &SystemClauseType::IsPartialString => { @@ -1288,14 +1288,14 @@ impl MachineState { let tail = self.heap[h + 1].as_addr(h + 1); let target = self[temp_v!(2)]; - self.unify(tail, target); + (self.unify_fn)(self, tail, target); } else { self.fail = true; return Ok(()); } } Addr::Lis(h) => { - self.unify(Addr::HeapCell(h + 1), self[temp_v!(2)]); + (self.unify_fn)(self, Addr::HeapCell(h + 1), self[temp_v!(2)]); } Addr::EmptyList => { self.fail = true; @@ -1328,7 +1328,7 @@ impl MachineState { if stream.at_end_of_stream() { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], Addr::Fixnum(-1)); + (self.unify_fn)(self, self[temp_v!(2)], Addr::Fixnum(-1)); return return_from_clause!(self.last_call, self); } @@ -1432,7 +1432,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -1535,7 +1535,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -1645,7 +1645,7 @@ impl MachineState { let chars = string.trim().chars().map(|c| Addr::Char(c)); let char_list = Addr::HeapCell(self.heap.to_list(chars)); - self.unify(char_list, chs); + (self.unify_fn)(self, char_list, chs); } &SystemClauseType::NumberToCodes => { let n = self[temp_v!(1)]; @@ -1672,7 +1672,7 @@ impl MachineState { let codes_list = Addr::HeapCell(self.heap.to_list(codes)); - self.unify(codes_list, chs); + (self.unify_fn)(self, codes_list, chs); } &SystemClauseType::CodesToNumber => { let stub = MachineError::functor_stub(clause_name!("number_codes"), 2); @@ -1698,7 +1698,7 @@ impl MachineState { let a1 = self[temp_v!(1)]; let lh_len = Addr::Usize(self.lifted_heap.h()); - self.unify(a1, lh_len); + (self.unify_fn)(self, a1, lh_len); } &SystemClauseType::CharCode => { let a1 = self[temp_v!(1)]; @@ -1717,11 +1717,11 @@ impl MachineState { }; let a2 = self[temp_v!(2)]; - self.unify(Addr::Fixnum(c as isize), a2); + (self.unify_fn)(self, Addr::Fixnum(c as isize), a2); } Addr::Char(c) => { let a2 = self[temp_v!(2)]; - self.unify(Addr::Fixnum(c as isize), a2); + (self.unify_fn)(self, Addr::Fixnum(c as isize), a2); } addr if addr.is_ref() => { let a2 = self[temp_v!(2)]; @@ -1738,7 +1738,7 @@ impl MachineState { } }; - self.unify(Addr::Char(c), addr); + (self.unify_fn)(self, Addr::Char(c), addr); } _ => { unreachable!(); @@ -1869,14 +1869,14 @@ impl MachineState { Some((ref ball, ref mut loc)) => { match loc { Some(ref value_addr) => { - self.unify(addr, *value_addr); + (self.unify_fn)(self, addr, *value_addr); } loc @ None if !ball.stub.is_empty() => { let h = self.heap.h(); let stub = ball.copy_and_align(h); self.heap.extend(stub.into_iter()); - self.unify(addr, Addr::HeapCell(h)); + (self.unify_fn)(self, addr, Addr::HeapCell(h)); if !self.fail { *loc = Some(Addr::HeapCell(h)); @@ -2204,7 +2204,7 @@ impl MachineState { } _ => { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], Addr::Fixnum(-1)); + (self.unify_fn)(self, self[temp_v!(2)], Addr::Fixnum(-1)); return return_from_clause!(self.last_call, self); } } @@ -2238,7 +2238,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -2357,7 +2357,7 @@ impl MachineState { } }; let string = self.heap.put_complete_string(&string); - self.unify(self[temp_v!(3)], string); + (self.unify_fn)(self, self[temp_v!(3)], string); } &SystemClauseType::GetCode => { let mut stream = @@ -2387,7 +2387,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -2580,7 +2580,7 @@ impl MachineState { let a1 = self[temp_v!(1)]; - self.unify(Addr::Char(c), a1); + (self.unify_fn)(self, Addr::Char(c), a1); } &SystemClauseType::HeadIsDynamic => { let module_name = atom_from!(self, self.store(self.deref(self[temp_v!(1)]))); @@ -2933,10 +2933,10 @@ impl MachineState { let atom = self.heap.to_unifiable(HeapCellValue::Atom(name, spec)); - self.unify(a2, atom); + (self.unify_fn)(self, a2, atom); if !self.fail { - self.unify(a3, Addr::Usize(arity)); + (self.unify_fn)(self, a3, Addr::Usize(arity)); } } _ => { @@ -2986,14 +2986,14 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Atom(name, Some(shared_op_desc))); - self.unify(Addr::Usize(priority), prec); + (self.unify_fn)(self, Addr::Usize(priority), prec); if !self.fail { - self.unify(a3, specifier); + (self.unify_fn)(self, a3, specifier); } if !self.fail { - self.unify(a4, op); + (self.unify_fn)(self, a4, op); } } _ => { @@ -3018,11 +3018,11 @@ impl MachineState { let a2 = ProcessTime::now().as_duration().as_secs_f64(); let addr = self.heap.put_constant(Constant::Float(OrderedFloat(a2))); - self.unify(a1, addr); + (self.unify_fn)(self, a1, addr); } &SystemClauseType::CurrentTime => { let str = self.systemtime_to_timestamp(SystemTime::now()); - self.unify(self[temp_v!(1)], str); + (self.unify_fn)(self, self[temp_v!(1)], str); } &SystemClauseType::OpDeclaration => { let priority = self[temp_v!(1)]; @@ -3176,7 +3176,7 @@ impl MachineState { let addr = self[temp_v!(1)]; let value = Addr::Usize(self.attr_var_init.attr_var_queue.len()); - self.unify(addr, value); + (self.unify_fn)(self, addr, value); } &SystemClauseType::GetAttrVarQueueBeyond => { let addr = self[temp_v!(1)]; @@ -3200,7 +3200,7 @@ impl MachineState { let var_list_addr = Addr::HeapCell(self.heap.to_list(iter)); let list_addr = self[temp_v!(2)]; - self.unify(var_list_addr, list_addr); + (self.unify_fn)(self, var_list_addr, list_addr); } } &SystemClauseType::GetContinuationChunk => { @@ -3245,7 +3245,7 @@ impl MachineState { self.heap.push(HeapCellValue::Addr(p_functor)); self.heap.extend(addrs.into_iter().map(HeapCellValue::Addr)); - self.unify(self[temp_v!(3)], chunk); + (self.unify_fn)(self, self[temp_v!(3)], chunk); } &SystemClauseType::GetLiftedHeapFromOffsetDiff => { let lh_offset = self[temp_v!(1)]; @@ -3256,8 +3256,8 @@ impl MachineState { let solutions = self[temp_v!(2)]; let diff = self[temp_v!(3)]; - self.unify(solutions, Addr::EmptyList); - self.unify(diff, Addr::EmptyList); + (self.unify_fn)(self, solutions, Addr::EmptyList); + (self.unify_fn)(self, diff, Addr::EmptyList); } else { let h = self.heap.h(); let mut last_index = h; @@ -3285,14 +3285,14 @@ impl MachineState { addr_opt.map(|addr| { let diff = self[temp_v!(3)]; - self.unify(diff, addr); + (self.unify_fn)(self, diff, addr); }); } self.lifted_heap.truncate(lh_offset); let solutions = self[temp_v!(2)]; - self.unify(Addr::HeapCell(h), solutions); + (self.unify_fn)(self, Addr::HeapCell(h), solutions); } } _ => { @@ -3307,7 +3307,7 @@ impl MachineState { Addr::Usize(lh_offset) => { if lh_offset >= self.lifted_heap.h() { let solutions = self[temp_v!(2)]; - self.unify(solutions, Addr::EmptyList); + (self.unify_fn)(self, solutions, Addr::EmptyList); } else { let h = self.heap.h(); @@ -3325,7 +3325,7 @@ impl MachineState { self.lifted_heap.truncate(lh_offset); let solutions = self[temp_v!(2)]; - self.unify(Addr::HeapCell(h), solutions); + (self.unify_fn)(self, Addr::HeapCell(h), solutions); } } _ => { @@ -3342,21 +3342,21 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Atom(clause_name!("chars"), None)); - self.unify(a1, atom); + (self.unify_fn)(self, a1, atom); } DoubleQuotes::Atom => { let atom = self .heap .to_unifiable(HeapCellValue::Atom(clause_name!("atom"), None)); - self.unify(a1, atom); + (self.unify_fn)(self, a1, atom); } DoubleQuotes::Codes => { let atom = self .heap .to_unifiable(HeapCellValue::Atom(clause_name!("codes"), None)); - self.unify(a1, atom); + (self.unify_fn)(self, a1, atom); } } } @@ -3460,7 +3460,7 @@ impl MachineState { .to_unifiable(HeapCellValue::Integer(Rc::new(count))); let a3 = self[temp_v!(3)]; - self.unify(a3, count); + (self.unify_fn)(self, a3, count); } None => { panic!( @@ -3645,7 +3645,7 @@ impl MachineState { let a2 = self[temp_v!(2)]; - self.unify(a2, count); + (self.unify_fn)(self, a2, count); } _ => { panic!("remove_inference_counter: expected Usize in A1."); @@ -3795,13 +3795,13 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Atom(clause_name!("!"), None)); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } else { let a2 = self .heap .to_unifiable(HeapCellValue::Atom(clause_name!("true"), None)); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } } _ => { @@ -3860,13 +3860,13 @@ impl MachineState { let a1 = self[temp_v!(1)]; let a2 = Addr::Usize(self.b); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } &SystemClauseType::GetCutPoint => { let a1 = self[temp_v!(1)]; let a2 = Addr::CutPoint(self.b0); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } &SystemClauseType::InstallNewBlock => { self.install_new_block(temp_v!(1)); @@ -3891,10 +3891,10 @@ impl MachineState { let p = cp.as_functor(&mut self.heap); - self.unify(self[temp_v!(2)], e); + (self.unify_fn)(self, self[temp_v!(2)], e); if !self.fail { - self.unify(self[temp_v!(3)], p); + (self.unify_fn)(self, self[temp_v!(3)], p); } } else { unreachable!() @@ -3918,10 +3918,10 @@ impl MachineState { let e = Addr::Usize(e); - self.unify(self[temp_v!(2)], e); + (self.unify_fn)(self, self[temp_v!(2)], e); if !self.fail { - self.unify(self[temp_v!(3)], p); + (self.unify_fn)(self, self[temp_v!(3)], p); } } _ => { @@ -4288,7 +4288,7 @@ impl MachineState { self.bind(addr.as_var().unwrap(), tcp_listener); if had_zero_port { - self.unify(self[temp_v!(2)], Addr::Usize(port)); + (self.unify_fn)(self, self[temp_v!(2)], Addr::Usize(port)); } } &SystemClauseType::SocketServerAccept => { @@ -4510,7 +4510,7 @@ impl MachineState { }; let property = self.heap.to_unifiable(property); - self.unify(self[temp_v!(3)], property); + (self.unify_fn)(self, self[temp_v!(3)], property); } &SystemClauseType::StoreGlobalVar => { let key = match self.store(self.deref(self[temp_v!(1)])) { @@ -4580,7 +4580,7 @@ impl MachineState { let seen_vars = self.attr_vars_of_term(self[temp_v!(1)]); let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); - self.unify(self[temp_v!(2)], outcome); + (self.unify_fn)(self, self[temp_v!(2)], outcome); } &SystemClauseType::TermVariables => { let a1 = self[temp_v!(1)]; @@ -4595,7 +4595,7 @@ impl MachineState { } let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); - self.unify(self[temp_v!(2)], outcome); + (self.unify_fn)(self, self[temp_v!(2)], outcome); } &SystemClauseType::TruncateLiftedHeapTo => { match self.store(self.deref(self[temp_v!(1)])) { @@ -4732,7 +4732,7 @@ impl MachineState { 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_fn)(self, listing, listing_var); } &SystemClauseType::WriteTerm => { let mut stream = @@ -4819,7 +4819,7 @@ impl MachineState { let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown"); let chars = buffer.chars().map(|c| Addr::Char(c)); let result = Addr::HeapCell(self.heap.to_list(chars)); - self.unify(version, result); + (self.unify_fn)(self, version, result); } &SystemClauseType::CryptoRandomByte => { let arg = self[temp_v!(1)]; @@ -4840,7 +4840,7 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Integer(Rc::new(Integer::from(bytes[0])))); - self.unify(arg, byte); + (self.unify_fn)(self, arg, byte); } &SystemClauseType::CryptoDataHash => { let encoding = self.atom_argument_to_string(2); @@ -4963,7 +4963,7 @@ impl MachineState { } }; - self.unify(self[temp_v!(3)], ints_list); + (self.unify_fn)(self, self[temp_v!(3)], ints_list); } &SystemClauseType::CryptoDataHKDF => { let encoding = self.atom_argument_to_string(2); @@ -5023,7 +5023,7 @@ impl MachineState { ) }; - self.unify(self[temp_v!(7)], ints_list); + (self.unify_fn)(self, self[temp_v!(7)], ints_list); } &SystemClauseType::CryptoPasswordHash => { let stub1 = MachineError::functor_stub(clause_name!("crypto_password_hash"), 3); @@ -5066,7 +5066,7 @@ impl MachineState { ) }; - self.unify(self[temp_v!(4)], ints_list); + (self.unify_fn)(self, self[temp_v!(4)], ints_list); } &SystemClauseType::CryptoDataEncrypt => { let encoding = self.atom_argument_to_string(3); @@ -5107,8 +5107,8 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(6)], tag_list); - self.unify(self[temp_v!(7)], complete_string); + (self.unify_fn)(self, self[temp_v!(6)], tag_list); + (self.unify_fn)(self, self[temp_v!(7)], complete_string); } &SystemClauseType::CryptoDataDecrypt => { let data = self.string_encoding_bytes(1, "octet"); @@ -5152,7 +5152,7 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(6)], complete_string); + (self.unify_fn)(self, self[temp_v!(6)], complete_string); } &SystemClauseType::CryptoCurveScalarMult => { let curve = self.atom_argument_to_string(1); @@ -5196,8 +5196,8 @@ impl MachineState { .heap .put_complete_string(&ry.to_dec_str().unwrap().to_string()); - self.unify(self[temp_v!(4)], sx); - self.unify(self[temp_v!(5)], sy); + (self.unify_fn)(self, self[temp_v!(4)], sx); + (self.unify_fn)(self, self[temp_v!(5)], sy); } &SystemClauseType::Ed25519NewKeyPair => { let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap(); @@ -5206,7 +5206,7 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(1)], complete_string); + (self.unify_fn)(self, self[temp_v!(1)], complete_string); } &SystemClauseType::Ed25519KeyPairPublicKey => { let bytes = self.string_encoding_bytes(1, "octet"); @@ -5226,7 +5226,7 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(2)], complete_string); + (self.unify_fn)(self, self[temp_v!(2)], complete_string); } &SystemClauseType::Ed25519Sign => { let key = self.string_encoding_bytes(1, "octet"); @@ -5251,7 +5251,7 @@ impl MachineState { ), ); - self.unify(self[temp_v!(4)], sig_list); + (self.unify_fn)(self, self[temp_v!(4)], sig_list); } &SystemClauseType::Ed25519Verify => { let key = self.string_encoding_bytes(1, "octet"); @@ -5282,21 +5282,21 @@ impl MachineState { let string = String::from_iter(result[..].iter().map(|b| *b as char)); let cstr = self.heap.put_complete_string(&string); - self.unify(self[temp_v!(3)], cstr); + (self.unify_fn)(self, self[temp_v!(3)], cstr); } &SystemClauseType::LoadHTML => { let string = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); let doc = select::document::Document::from_read(string.as_bytes()).unwrap(); let result = self.html_node_to_term(indices, doc.nth(0).unwrap()); - self.unify(self[temp_v!(2)], result); + (self.unify_fn)(self, self[temp_v!(2)], result); } &SystemClauseType::LoadXML => { let string = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); match roxmltree::Document::parse(&string) { Ok(doc) => { let result = self.xml_node_to_term(indices, doc.root_element()); - self.unify(self[temp_v!(2)], result); + (self.unify_fn)(self, self[temp_v!(2)], result); } _ => { self.fail = true; @@ -5309,7 +5309,7 @@ impl MachineState { match env::var(key) { Ok(value) => { let cstr = self.heap.put_complete_string(&value); - self.unify(self[temp_v!(2)], cstr); + (self.unify_fn)(self, self[temp_v!(2)], cstr); } _ => { self.fail = true; @@ -5352,7 +5352,7 @@ impl MachineState { Ok(bs) => { let string = String::from_iter(bs.iter().map(|b| *b as char)); let cstr = self.heap.put_complete_string(&string); - self.unify(self[temp_v!(1)], cstr); + (self.unify_fn)(self, self[temp_v!(1)], cstr); } _ => { self.fail = true; @@ -5379,7 +5379,7 @@ impl MachineState { let b64 = base64::encode_config(bytes, config); let cstr = self.heap.put_complete_string(&b64); - self.unify(self[temp_v!(2)], cstr); + (self.unify_fn)(self, self[temp_v!(2)], cstr); } } &SystemClauseType::LoadLibraryAsStream => { @@ -5433,6 +5433,27 @@ impl MachineState { } } } + &SystemClauseType::IsSTOEnabled => { + if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize { + let value = self.heap.to_unifiable( + HeapCellValue::Atom(clause_name!("true"), None), + ); + + (self.unify_fn)(self, self[temp_v!(1)], value); + } else { + let value = self.heap.to_unifiable( + HeapCellValue::Atom(clause_name!("false"), None), + ); + + (self.unify_fn)(self, self[temp_v!(1)], value); + } + } + &SystemClauseType::SetSTOAsUnify => { + self.unify_fn = MachineState::unify_with_occurs_check; + } + &SystemClauseType::SetNSTOAsUnify => { + self.unify_fn = MachineState::unify; + } }; return_from_clause!(self.last_call, self) From f935060b2b9393c28e62c7f2b6918a9b85618f9b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 11:03:55 -0700 Subject: [PATCH 124/137] restore .scryerrc loading --- src/clause_types.rs | 3 +++ src/machine/mod.rs | 28 ---------------------------- src/machine/system_calls.rs | 22 ++++++++++++++++++++++ src/toplevel.pl | 9 +++++++++ 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index dc2d0150..abbacbf5 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -307,6 +307,7 @@ pub enum SystemClauseType { IsSTOEnabled, SetSTOAsUnify, SetNSTOAsUnify, + HomeDirectory, } impl SystemClauseType { @@ -591,6 +592,7 @@ impl SystemClauseType { &SystemClauseType::IsSTOEnabled => clause_name!("$is_sto_enabled"), &SystemClauseType::SetSTOAsUnify => clause_name!("$set_sto_as_unify"), &SystemClauseType::SetNSTOAsUnify => clause_name!("$set_nsto_as_unify"), + &SystemClauseType::HomeDirectory => clause_name!("$home_directory"), } } @@ -839,6 +841,7 @@ impl SystemClauseType { ("$is_sto_enabled", 1) => Some(SystemClauseType::IsSTOEnabled), ("$set_sto_as_unify", 0) => Some(SystemClauseType::SetSTOAsUnify), ("$set_nsto_as_unify", 0) => Some(SystemClauseType::SetNSTOAsUnify), + ("$home_directory", 1) => Some(SystemClauseType::HomeDirectory), _ => None, } } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index b0f607f2..41940154 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -126,34 +126,6 @@ fn current_dir() -> PathBuf { include!(concat!(env!("OUT_DIR"), "/libraries.rs")); impl Machine { - /* - fn compile_scryerrc(&mut self) { - let mut path = match dirs_next::home_dir() { - Some(path) => path, - None => return, - }; - - path.push(".scryerrc"); - - if path.is_file() { - let file_src = match File::open(&path) { - Ok(file_handle) => Stream::from_file_as_input( - clause_name!(".scryerrc"), - file_handle, - ), - Err(_) => return, - }; - - let rc_src = ListingSource::from_file_and_path( - clause_name!(".scryerrc"), - path.to_path_buf(), - ); - - compile_user_module(self, file_src, rc_src); - } - } - */ - 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) { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 0dacd2aa..bc6724a5 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -5454,6 +5454,28 @@ impl MachineState { &SystemClauseType::SetNSTOAsUnify => { self.unify_fn = MachineState::unify; } + &SystemClauseType::HomeDirectory => { + let path = match dirs_next::home_dir() { + Some(path) => path, + None => { + self.fail = true; + return Ok(()); + } + }; + + if path.is_dir() { + if let Some(path) = path.to_str() { + let path_atom = self.heap.to_unifiable( + HeapCellValue::Atom(clause_name!(path.to_string(), self.atom_tbl), None), + ); + + (self.unify_fn)(self, self[temp_v!(1)], path_atom); + return return_from_clause!(self.last_call, self); + } + } + + self.fail = true; + } }; return_from_clause!(self.last_call, self) diff --git a/src/toplevel.pl b/src/toplevel.pl index 4a861259..daf03525 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -9,6 +9,13 @@ :- use_module(library('$project_atts')). :- use_module(library('$atts')). +load_scryerrc :- + ( '$home_directory'(HomeDir) -> + atom_concat(HomeDir, '/.scryerrc', ScryerrcFile), + catch(use_module(ScryerrcFile), E, print_exception(E)) + ; true + ). + :- dynamic(argv/1). '$repl'([_|Args0]) :- @@ -19,12 +26,14 @@ ; asserta('$toplevel':argv([])), Args = Args0 ), + load_scryerrc, delegate_task(Args, []), repl. '$repl'(_) :- ( \+ argv(_) -> asserta('$toplevel':argv([])) ; true ), + load_scryerrc, repl. delegate_task([], []). From 2f428b72618aeb421485950ffb91ff9dba2f0b0c Mon Sep 17 00:00:00 2001 From: Skgland Date: Thu, 25 Feb 2021 23:24:20 +0100 Subject: [PATCH 125/137] split into lib and bin * makes most pub things in src/ pub(crate) as not to expose things accidentally * only those things needed by src/bin/scryer-prolog.rs and tests/scryer.rs should be pub * split src/main.rs into src/lib.rs and src/bin/scryer-prolog.rs * add tests folder and run most of the files in src/tests with cargo test added bytes method to Stream in src/machine/streams.rs to check if stdout is as expected --- build.rs | 2 +- src/allocator.rs | 2 +- src/arithmetic.rs | 22 +-- src/bin/scryer-prolog.rs | 11 ++ src/clause_types.rs | 58 +++---- src/codegen.rs | 43 ++--- src/debray_allocator.rs | 2 +- src/fixtures.rs | 60 +++---- src/forms.rs | 186 ++++++++++---------- src/heap_iter.rs | 34 ++-- src/heap_print.rs | 22 +-- src/indexing.rs | 28 +-- src/instructions.rs | 56 +++--- src/iterators.rs | 38 ++--- src/{main.rs => lib.rs} | 16 +- src/machine/code_repo.rs | 123 +++++++------- src/machine/code_walker.rs | 20 +-- src/machine/copier.rs | 153 ++++++++--------- src/machine/heap.rs | 2 +- src/machine/loader.rs | 272 +++++++++++++++--------------- src/machine/machine_errors.rs | 48 +++--- src/machine/machine_indices.rs | 149 ++++++++-------- src/machine/machine_state.rs | 17 +- src/machine/machine_state_impl.rs | 15 +- src/machine/mod.rs | 24 +-- src/machine/partial_string.rs | 154 +++++++---------- src/machine/preprocessor.rs | 20 +-- src/machine/stack.rs | 83 ++++----- src/machine/streams.rs | 184 +++++++++++--------- src/machine/system_calls.rs | 2 +- src/machine/term_stream.rs | 4 +- src/read.rs | 22 ++- src/targets.rs | 2 +- src/tests/hello_world.pl | 6 + tests/scryer.rs | 65 +++++++ 35 files changed, 981 insertions(+), 964 deletions(-) create mode 100644 src/bin/scryer-prolog.rs rename src/{main.rs => lib.rs} (61%) create mode 100644 src/tests/hello_world.pl create mode 100644 tests/scryer.rs diff --git a/build.rs b/build.rs index c0865b52..0133c93e 100644 --- a/build.rs +++ b/build.rs @@ -44,7 +44,7 @@ fn main() { libraries .write_all( b"ref_thread_local::ref_thread_local! { - pub static managed LIBRARIES: IndexMap<&'static str, &'static str> = { + pub(crate) static managed LIBRARIES: IndexMap<&'static str, &'static str> = { let mut m = IndexMap::new();\n", ) .unwrap(); diff --git a/src/allocator.rs b/src/allocator.rs index 73d281cd..cc8de305 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -9,7 +9,7 @@ use crate::targets::*; use std::cell::Cell; use std::rc::Rc; -pub trait Allocator<'a> { +pub(crate) trait Allocator<'a> { fn new() -> Self; fn mark_anon_var(&mut self, _: Level, _: GenContext, _: &mut Vec) diff --git a/src/arithmetic.rs b/src/arithmetic.rs index bcaf239f..87e72d45 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -25,11 +25,11 @@ use std::rc::Rc; use std::vec::Vec; #[derive(Debug)] -pub struct ArithInstructionIterator<'a> { +pub(crate) struct ArithInstructionIterator<'a> { state_stack: Vec>, } -pub type ArithCont = (Code, Option); +pub(crate) type ArithCont = (Code, Option); impl<'a> ArithInstructionIterator<'a> { fn push_subterm(&mut self, lvl: Level, term: &'a Term) { @@ -71,7 +71,7 @@ impl<'a> ArithInstructionIterator<'a> { } #[derive(Debug)] -pub enum ArithTermRef<'a> { +pub(crate) enum ArithTermRef<'a> { Constant(&'a Constant), Op(ClauseName, usize), // name, arity. Var(&'a Cell, Rc), @@ -113,13 +113,13 @@ impl<'a> Iterator for ArithInstructionIterator<'a> { } #[derive(Debug)] -pub struct ArithmeticEvaluator<'a> { +pub(crate) struct ArithmeticEvaluator<'a> { bindings: &'a AllocVarDict, interm: Vec, interm_c: usize, } -pub trait ArithmeticTermIter<'a> { +pub(crate) trait ArithmeticTermIter<'a> { type Iter: Iterator, ArithmeticError>>; fn iter(self) -> Result; @@ -134,7 +134,7 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term { } impl<'a> ArithmeticEvaluator<'a> { - pub fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self { + pub(crate) fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self { ArithmeticEvaluator { bindings, interm: Vec::new(), @@ -296,7 +296,7 @@ impl<'a> ArithmeticEvaluator<'a> { Ok(()) } - pub fn eval(&mut self, src: Iter) -> Result + pub(crate) fn eval(&mut self, src: Iter) -> Result where Iter: ArithmeticTermIter<'a>, { @@ -329,7 +329,7 @@ impl<'a> ArithmeticEvaluator<'a> { } // integer division rounding function -- 9.1.3.1. -pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Number> { +pub(crate) fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Number> { match n { &Number::Integer(_) => RefOrOwned::Borrowed(n), &Number::Float(OrderedFloat(f)) => RefOrOwned::Owned(Number::from( @@ -347,7 +347,7 @@ pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Number> { } // floating point rounding function -- 9.1.4.1. -pub fn rnd_f(n: &Number) -> f64 { +pub(crate) fn rnd_f(n: &Number) -> f64 { match n { &Number::Fixnum(n) => n as f64, &Number::Integer(ref n) => n.to_f64(), @@ -357,7 +357,7 @@ pub fn rnd_f(n: &Number) -> f64 { } // floating point result function -- 9.1.4.2. -pub fn result_f(n: &Number, round: Round) -> Result +pub(crate) fn result_f(n: &Number, round: Round) -> Result where Round: Fn(&Number) -> f64, { @@ -752,7 +752,7 @@ impl<'a> From<&'a Integer> for Number { } // Computes n ^ power. Ignores the sign of power. -pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer { +pub(crate) fn binary_pow(mut n: Integer, power: &Integer) -> Integer { let mut power = Integer::from(power.abs_ref()); if power == 0 { diff --git a/src/bin/scryer-prolog.rs b/src/bin/scryer-prolog.rs new file mode 100644 index 00000000..e3330c0a --- /dev/null +++ b/src/bin/scryer-prolog.rs @@ -0,0 +1,11 @@ +fn main() { + use nix::sys::signal; + use scryer_prolog::read::readline; + use scryer_prolog::*; + + let handler = signal::SigHandler::Handler(handle_sigint); + unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap(); + + let mut wam = machine::Machine::new(readline::input_stream(), machine::Stream::stdout()); + wam.run_top_level(); +} diff --git a/src/clause_types.rs b/src/clause_types.rs index abbacbf5..67b3b101 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -10,7 +10,7 @@ use ref_thread_local::{ref_thread_local, RefThreadLocal}; use std::collections::BTreeMap; #[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub enum CompareNumberQT { +pub(crate) enum CompareNumberQT { GreaterThan, LessThan, GreaterThanOrEqual, @@ -33,7 +33,7 @@ impl CompareNumberQT { } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum CompareTermQT { +pub(crate) enum CompareTermQT { LessThan, LessThanOrEqual, GreaterThanOrEqual, @@ -52,14 +52,14 @@ impl CompareTermQT { } #[derive(Debug, Clone, PartialEq, Eq)] -pub enum ArithmeticTerm { +pub(crate) enum ArithmeticTerm { Reg(RegType), Interm(usize), Number(Number), } impl ArithmeticTerm { - pub fn interm_or(&self, interm: usize) -> usize { + pub(crate) fn interm_or(&self, interm: usize) -> usize { if let &ArithmeticTerm::Interm(interm) = self { interm } else { @@ -69,7 +69,7 @@ impl ArithmeticTerm { } #[derive(Debug, Clone, Eq, PartialEq)] -pub enum InlinedClauseType { +pub(crate) enum InlinedClauseType { CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), IsAtom(RegType), IsAtomic(RegType), @@ -83,11 +83,11 @@ pub enum InlinedClauseType { } ref_thread_local! { - pub static managed RANDOM_STATE: RandState<'static> = RandState::new(); + pub(crate)static managed RANDOM_STATE: RandState<'static> = RandState::new(); } ref_thread_local! { - pub static managed CLAUSE_TYPE_FORMS: BTreeMap<(&'static str, usize), ClauseType> = { + pub(crate)static managed CLAUSE_TYPE_FORMS: BTreeMap<(&'static str, usize), ClauseType> = { let mut m = BTreeMap::new(); let r1 = temp_v!(1); @@ -133,7 +133,7 @@ ref_thread_local! { } impl InlinedClauseType { - pub fn name(&self) -> &'static str { + pub(crate) fn name(&self) -> &'static str { match self { &InlinedClauseType::CompareNumber(qt, ..) => qt.name(), &InlinedClauseType::IsAtom(..) => "atom", @@ -150,7 +150,7 @@ impl InlinedClauseType { } #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum SystemClauseType { +pub(crate) enum SystemClauseType { AtomChars, AtomCodes, AtomLength, @@ -311,7 +311,7 @@ pub enum SystemClauseType { } impl SystemClauseType { - pub fn name(&self) -> ClauseName { + pub(crate) fn name(&self) -> ClauseName { match self { &SystemClauseType::AtomChars => clause_name!("$atom_chars"), &SystemClauseType::AtomCodes => clause_name!("$atom_codes"), @@ -596,7 +596,7 @@ impl SystemClauseType { } } - pub fn from(name: &str, arity: usize) -> Option { + pub(crate) fn from(name: &str, arity: usize) -> Option { match (name, arity) { ("$abolish_clause", 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)), ("$add_dynamic_predicate", 4) => { @@ -605,9 +605,9 @@ impl SystemClauseType { ("$add_multifile_predicate", 4) => { Some(SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate)) } - ("$add_discontiguous_predicate", 4) => { - Some(SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate)) - } + ("$add_discontiguous_predicate", 4) => Some(SystemClauseType::REPL( + REPLCodePtr::AddDiscontiguousPredicate, + )), ("$add_goal_expansion_clause", 3) => { Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause)) } @@ -766,18 +766,16 @@ impl SystemClauseType { ("$asserta", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Asserta)), ("$assertz", 5) => Some(SystemClauseType::REPL(REPLCodePtr::Assertz)), ("$retract_clause", 4) => Some(SystemClauseType::REPL(REPLCodePtr::Retract)), - ("$is_consistent_with_term_queue", 4) => { - Some(SystemClauseType::REPL(REPLCodePtr::IsConsistentWithTermQueue)) - } - ("$flush_term_queue", 1) => { - Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)) - } + ("$is_consistent_with_term_queue", 4) => Some(SystemClauseType::REPL( + REPLCodePtr::IsConsistentWithTermQueue, + )), + ("$flush_term_queue", 1) => Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)), ("$remove_module_exports", 2) => { Some(SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports)) } - ("$add_non_counted_backtracking", 3) => { - Some(SystemClauseType::REPL(REPLCodePtr::AddNonCountedBacktracking)) - } + ("$add_non_counted_backtracking", 3) => Some(SystemClauseType::REPL( + REPLCodePtr::AddNonCountedBacktracking, + )), ("$variant", 2) => Some(SystemClauseType::Variant), ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions), ("$write_term", 7) => Some(SystemClauseType::WriteTerm), @@ -848,7 +846,7 @@ impl SystemClauseType { } #[derive(Debug, Clone, Eq, PartialEq)] -pub enum BuiltInClauseType { +pub(crate) enum BuiltInClauseType { AcyclicTerm, Arg, Compare, @@ -866,7 +864,7 @@ pub enum BuiltInClauseType { } #[derive(Debug, Clone, PartialEq, Eq)] -pub enum ClauseType { +pub(crate) enum ClauseType { BuiltIn(BuiltInClauseType), CallN, Inlined(InlinedClauseType), @@ -876,7 +874,7 @@ pub enum ClauseType { } impl BuiltInClauseType { - pub fn name(&self) -> ClauseName { + pub(crate) fn name(&self) -> ClauseName { match self { &BuiltInClauseType::AcyclicTerm => clause_name!("acyclic_term"), &BuiltInClauseType::Arg => clause_name!("arg"), @@ -895,7 +893,7 @@ impl BuiltInClauseType { } } - pub fn arity(&self) -> usize { + pub(crate) fn arity(&self) -> usize { match self { &BuiltInClauseType::AcyclicTerm => 1, &BuiltInClauseType::Arg => 3, @@ -916,7 +914,7 @@ impl BuiltInClauseType { } impl ClauseType { - pub fn spec(&self) -> Option { + pub(crate) fn spec(&self) -> Option { match self { &ClauseType::Op(_, ref spec, _) => Some(spec.clone()), &ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) @@ -928,7 +926,7 @@ impl ClauseType { } } - pub fn name(&self) -> ClauseName { + pub(crate) fn name(&self) -> ClauseName { match self { &ClauseType::BuiltIn(ref built_in) => built_in.name(), &ClauseType::CallN => clause_name!("$call"), @@ -939,7 +937,7 @@ impl ClauseType { } } - pub fn from(name: ClauseName, arity: usize, spec: Option) -> Self { + pub(crate) fn from(name: ClauseName, arity: usize, spec: Option) -> Self { CLAUSE_TYPE_FORMS .borrow() .get(&(name.as_str(), arity)) diff --git a/src/codegen.rs b/src/codegen.rs index 7a5d8ba3..a678549b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -22,10 +22,10 @@ use std::collections::VecDeque; use std::rc::Rc; #[derive(Debug)] -pub struct ConjunctInfo<'a> { - pub perm_vs: VariableFixtures<'a>, - pub num_of_chunks: usize, - pub has_deep_cut: bool, +pub(crate) struct ConjunctInfo<'a> { + pub(crate) perm_vs: VariableFixtures<'a>, + pub(crate) num_of_chunks: usize, + pub(crate) has_deep_cut: bool, } impl<'a> ConjunctInfo<'a> { @@ -90,7 +90,7 @@ impl<'a> ConjunctInfo<'a> { } #[derive(Clone, Copy, Debug)] -pub struct CodeGenSettings { +pub(crate) struct CodeGenSettings { pub global_clock_tick: Option, pub is_extensible: bool, pub non_counted_bt: bool, @@ -98,12 +98,12 @@ pub struct CodeGenSettings { impl CodeGenSettings { #[inline] - pub fn is_dynamic(&self) -> bool { + pub(crate) fn is_dynamic(&self) -> bool { self.global_clock_tick.is_some() } #[inline] - pub fn internal_try_me_else(&self, offset: usize) -> ChoiceInstruction { + pub(crate) fn internal_try_me_else(&self, offset: usize) -> ChoiceInstruction { if let Some(global_clock_time) = self.global_clock_tick { ChoiceInstruction::DynamicInternalElse( global_clock_time, @@ -115,7 +115,7 @@ impl CodeGenSettings { } } - pub fn try_me_else(&self, offset: usize) -> ChoiceInstruction { + pub(crate) fn try_me_else(&self, offset: usize) -> ChoiceInstruction { if let Some(global_clock_tick) = self.global_clock_tick { ChoiceInstruction::DynamicElse( global_clock_tick, @@ -127,7 +127,7 @@ impl CodeGenSettings { } } - pub fn internal_retry_me_else(&self, offset: usize) -> ChoiceInstruction { + pub(crate) fn internal_retry_me_else(&self, offset: usize) -> ChoiceInstruction { if let Some(global_clock_tick) = self.global_clock_tick { ChoiceInstruction::DynamicInternalElse( global_clock_tick, @@ -139,7 +139,7 @@ impl CodeGenSettings { } } - pub fn retry_me_else(&self, offset: usize) -> ChoiceInstruction { + pub(crate) fn retry_me_else(&self, offset: usize) -> ChoiceInstruction { if let Some(global_clock_tick) = self.global_clock_tick { ChoiceInstruction::DynamicElse( global_clock_tick, @@ -153,7 +153,7 @@ impl CodeGenSettings { } } - pub fn internal_trust_me(&self) -> ChoiceInstruction { + pub(crate) fn internal_trust_me(&self) -> ChoiceInstruction { if let Some(global_clock_tick) = self.global_clock_tick { ChoiceInstruction::DynamicInternalElse( global_clock_tick, @@ -167,7 +167,7 @@ impl CodeGenSettings { } } - pub fn trust_me(&self) -> ChoiceInstruction { + pub(crate) fn trust_me(&self) -> ChoiceInstruction { if let Some(global_clock_tick) = self.global_clock_tick { ChoiceInstruction::DynamicElse( global_clock_tick, @@ -183,18 +183,18 @@ impl CodeGenSettings { } #[derive(Debug)] -pub struct CodeGenerator { +pub(crate) struct CodeGenerator { atom_tbl: TabledData, marker: TermMarker, - pub var_count: IndexMap, usize>, + pub(crate) var_count: IndexMap, usize>, settings: CodeGenSettings, - pub skeleton: PredicateSkeleton, - pub jmp_by_locs: Vec, + pub(crate) skeleton: PredicateSkeleton, + pub(crate) jmp_by_locs: Vec, global_jmp_by_locs_offset: usize, } impl<'a, TermMarker: Allocator<'a>> CodeGenerator { - pub fn new(atom_tbl: TabledData, settings: CodeGenSettings) -> Self { + pub(crate) fn new(atom_tbl: TabledData, settings: CodeGenSettings) -> Self { CodeGenerator { atom_tbl, marker: Allocator::new(), @@ -837,7 +837,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } } - pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result { + pub(crate) fn compile_rule<'b: 'a>( + &mut self, + rule: &'b Rule, + ) -> Result { let iter = ChunkedIterator::from_rule(rule); let conjunct_info = self.collect_var_data(iter); @@ -894,7 +897,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { UnsafeVarMarker::from_safe_vars(safe_vars) } - pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code { + pub(crate) fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code { self.update_var_count(post_order_iter(term)); let mut vs = VariableFixtures::new(); @@ -1119,7 +1122,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { Ok(Vec::from(code)) } - pub fn compile_predicate<'b: 'a>( + pub(crate) fn compile_predicate<'b: 'a>( &mut self, clauses: &'b Vec, ) -> Result { diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 4d69a344..7525a79a 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -14,7 +14,7 @@ use std::collections::BTreeSet; use std::rc::Rc; #[derive(Debug)] -pub struct DebrayAllocator { +pub(crate) struct DebrayAllocator { bindings: IndexMap, VarData>, arg_c: usize, temp_lb: usize, diff --git a/src/fixtures.rs b/src/fixtures.rs index 94d10c25..0ecdd9e8 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -14,23 +14,23 @@ use std::vec::Vec; // labeled with chunk numbers. #[derive(Debug)] -pub enum VarStatus { +pub(crate) enum VarStatus { Perm(usize), Temp(usize, TempVarData), // Perm(chunk_num) | Temp(chunk_num, _) } -pub type OccurrenceSet = BTreeSet<(GenContext, usize)>; +pub(crate) type OccurrenceSet = BTreeSet<(GenContext, usize)>; // Perm: 0 initially, a stack register once processed. // Temp: labeled with chunk_num and temp offset (unassigned if 0). #[derive(Debug)] -pub enum VarData { +pub(crate) enum VarData { Perm(usize), Temp(usize, usize, TempVarData), } impl VarData { - pub fn as_reg_type(&self) -> RegType { + pub(crate) fn as_reg_type(&self) -> RegType { match self { &VarData::Temp(_, r, _) => RegType::Temp(r), &VarData::Perm(r) => RegType::Perm(r), @@ -39,15 +39,15 @@ impl VarData { } #[derive(Debug)] -pub struct TempVarData { - pub last_term_arity: usize, - pub use_set: OccurrenceSet, - pub no_use_set: BTreeSet, - pub conflict_set: BTreeSet, +pub(crate) struct TempVarData { + pub(crate) last_term_arity: usize, + pub(crate) use_set: OccurrenceSet, + pub(crate) no_use_set: BTreeSet, + pub(crate) conflict_set: BTreeSet, } impl TempVarData { - pub fn new(last_term_arity: usize) -> Self { + pub(crate) fn new(last_term_arity: usize) -> Self { TempVarData { last_term_arity: last_term_arity, use_set: BTreeSet::new(), @@ -56,7 +56,7 @@ impl TempVarData { } } - pub fn uses_reg(&self, reg: usize) -> bool { + pub(crate) fn uses_reg(&self, reg: usize) -> bool { for &(_, nreg) in self.use_set.iter() { if reg == nreg { return true; @@ -66,7 +66,7 @@ impl TempVarData { return false; } - pub fn populate_conflict_set(&mut self) { + pub(crate) fn populate_conflict_set(&mut self) { if self.last_term_arity > 0 { let arity = self.last_term_arity; let mut conflict_set: BTreeSet = (1..arity).collect(); @@ -83,29 +83,29 @@ impl TempVarData { type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); #[derive(Debug)] -pub struct VariableFixtures<'a> { +pub(crate) struct VariableFixtures<'a> { perm_vars: IndexMap, VariableFixture<'a>>, last_chunk_temp_vars: IndexSet>, } impl<'a> VariableFixtures<'a> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { VariableFixtures { perm_vars: IndexMap::new(), last_chunk_temp_vars: IndexSet::new(), } } - pub fn insert(&mut self, var: Rc, vs: VariableFixture<'a>) { + pub(crate) fn insert(&mut self, var: Rc, vs: VariableFixture<'a>) { self.perm_vars.insert(var, vs); } - pub fn insert_last_chunk_temp_var(&mut self, var: Rc) { + pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Rc) { self.last_chunk_temp_vars.insert(var); } // computes no_use and conflict sets for all temp vars. - pub fn populate_restricting_sets(&mut self) { + pub(crate) fn populate_restricting_sets(&mut self) { // three stages: // 1. move the use sets of each variable to a local IndexMap, use_set // (iterate mutably, swap mutable refs). @@ -170,7 +170,7 @@ impl<'a> VariableFixtures<'a> { }; } - pub fn vars_above_threshold(&self, index: usize) -> usize { + pub(crate) fn vars_above_threshold(&self, index: usize) -> usize { let mut var_count = 0; for &(ref var_status, _) in self.values() { @@ -184,7 +184,7 @@ impl<'a> VariableFixtures<'a> { var_count } - pub fn mark_vars_in_chunk(&mut self, iter: I, lt_arity: usize, term_loc: GenContext) + pub(crate) fn mark_vars_in_chunk(&mut self, iter: I, lt_arity: usize, term_loc: GenContext) where I: Iterator>, { @@ -218,7 +218,7 @@ impl<'a> VariableFixtures<'a> { } } - pub fn into_iter(self) -> indexmap::map::IntoIter, VariableFixture<'a>> { + pub(crate) fn into_iter(self) -> indexmap::map::IntoIter, VariableFixture<'a>> { self.perm_vars.into_iter() } @@ -226,11 +226,11 @@ impl<'a> VariableFixtures<'a> { self.perm_vars.values() } - pub fn size(&self) -> usize { + pub(crate) fn size(&self) -> usize { self.perm_vars.len() } - pub fn set_perm_vals(&self, has_deep_cuts: bool) { + pub(crate) fn set_perm_vals(&self, has_deep_cuts: bool) { let mut values_vec: Vec<_> = self .values() .filter_map(|ref v| match &v.0 { @@ -252,27 +252,27 @@ impl<'a> VariableFixtures<'a> { } #[derive(Debug)] -pub struct UnsafeVarMarker { - pub unsafe_vars: IndexMap, - pub safe_vars: IndexSet, +pub(crate) struct UnsafeVarMarker { + pub(crate) unsafe_vars: IndexMap, + pub(crate) safe_vars: IndexSet, } impl UnsafeVarMarker { - pub fn new() -> Self { + pub(crate) fn new() -> Self { UnsafeVarMarker { unsafe_vars: IndexMap::new(), safe_vars: IndexSet::new(), } } - pub fn from_safe_vars(safe_vars: IndexSet) -> Self { + pub(crate) fn from_safe_vars(safe_vars: IndexSet) -> Self { UnsafeVarMarker { unsafe_vars: IndexMap::new(), safe_vars, } } - pub fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) -> bool { + pub(crate) fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) -> bool { match query_instr { &QueryInstruction::PutVariable(r @ RegType::Temp(_), _) | &QueryInstruction::SetVariable(r) => { @@ -283,7 +283,7 @@ impl UnsafeVarMarker { } } - pub fn mark_phase(&mut self, query_instr: &QueryInstruction, phase: usize) { + pub(crate) fn mark_phase(&mut self, query_instr: &QueryInstruction, phase: usize) { match query_instr { &QueryInstruction::PutValue(r @ RegType::Perm(_), _) | &QueryInstruction::SetValue(r) => { @@ -294,7 +294,7 @@ impl UnsafeVarMarker { } } - pub fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction, phase: usize) { + pub(crate) fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction, phase: usize) { match query_instr { &mut QueryInstruction::PutValue(RegType::Perm(i), arg) => { if let Some(p) = self.unsafe_vars.swap_remove(&RegType::Perm(i)) { diff --git a/src/forms.rs b/src/forms.rs index 3f0bd288..3d07ec8a 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -18,16 +18,16 @@ use std::ops::AddAssign; use std::path::PathBuf; use std::rc::Rc; -pub type PredicateKey = (ClauseName, usize); // name, arity. +pub(crate) type PredicateKey = (ClauseName, usize); // name, arity. -pub type Predicate = Vec; +pub(crate) type Predicate = Vec; // vars of predicate, toplevel offset. Vec is always a vector // of vars (we get their adjoining cells this way). -pub type JumpStub = Vec; +pub(crate) type JumpStub = Vec; #[derive(Debug, Clone)] -pub enum TopLevel { +pub(crate) enum TopLevel { Fact(Term), // Term, line_num, col_num Predicate(Predicate), Query(Vec), @@ -35,14 +35,14 @@ pub enum TopLevel { } #[derive(Debug, Clone, Copy)] -pub enum AppendOrPrepend { +pub(crate) enum AppendOrPrepend { Append, Prepend, } impl AppendOrPrepend { #[inline] - pub fn is_append(self) -> bool { + pub(crate) fn is_append(self) -> bool { match self { AppendOrPrepend::Append => true, AppendOrPrepend::Prepend => false, @@ -51,14 +51,14 @@ impl AppendOrPrepend { } #[derive(Debug, Clone, Copy)] -pub enum Level { +pub(crate) enum Level { Deep, Root, Shallow, } impl Level { - pub fn child_level(self) -> Level { + pub(crate) fn child_level(self) -> Level { match self { Level::Root => Level::Shallow, _ => Level::Deep, @@ -67,7 +67,7 @@ impl Level { } #[derive(Debug, Clone)] -pub enum QueryTerm { +pub(crate) enum QueryTerm { // register, clause type, subterms, use default call policy. Clause(Cell, ClauseType, Vec>, bool), BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. @@ -77,14 +77,14 @@ pub enum QueryTerm { } impl QueryTerm { - pub fn set_default_caller(&mut self) { + pub(crate) fn set_default_caller(&mut self) { match self { &mut QueryTerm::Clause(_, _, _, ref mut use_default_cp) => *use_default_cp = true, _ => {} } } - pub fn arity(&self) -> usize { + pub(crate) fn arity(&self) -> usize { match self { &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, @@ -95,28 +95,30 @@ impl QueryTerm { } #[derive(Debug, Clone)] -pub struct Rule { - pub head: (ClauseName, Vec>, QueryTerm), - pub clauses: Vec, +pub(crate) struct Rule { + pub(crate) head: (ClauseName, Vec>, QueryTerm), + pub(crate) clauses: Vec, } #[derive(Clone, Debug, Hash)] -pub enum ListingSource { +pub(crate) enum ListingSource { DynamicallyGenerated, File(ClauseName, PathBuf), // filename, path User, } impl ListingSource { - pub fn from_file_and_path(filename: ClauseName, path_buf: PathBuf) -> Self { + pub(crate) fn from_file_and_path(filename: ClauseName, path_buf: PathBuf) -> Self { ListingSource::File(filename, path_buf) } } -pub trait ClauseInfo { +pub(crate) trait ClauseInfo { fn is_consistent(&self, clauses: &PredicateQueue) -> bool { match clauses.first() { - Some(cl) => self.name() == ClauseInfo::name(cl) && self.arity() == ClauseInfo::arity(cl), + Some(cl) => { + self.name() == ClauseInfo::name(cl) && self.arity() == ClauseInfo::arity(cl) + } None => true, } } @@ -198,17 +200,17 @@ impl ClauseInfo for PredicateClause { } } -// pub type CompiledResult = (Predicate, VecDeque); +// pub(crate) type CompiledResult = (Predicate, VecDeque); #[derive(Debug, Clone)] -pub enum PredicateClause { +pub(crate) enum PredicateClause { Fact(Term), Rule(Rule), } impl PredicateClause { // TODO: add this to `Term` in `prolog_parser` like `first_arg`. - pub fn args(&self) -> Option<&[Box]> { + pub(crate) fn args(&self) -> Option<&[Box]> { match *self { PredicateClause::Fact(ref term, ..) => match term { Term::Clause(_, _, args, _) => Some(&args), @@ -226,13 +228,13 @@ impl PredicateClause { } #[derive(Debug, Clone)] -pub enum ModuleSource { +pub(crate) enum ModuleSource { Library(ClauseName), File(ClauseName), } impl ModuleSource { - pub fn as_functor_stub(&self) -> MachineStub { + pub(crate) fn as_functor_stub(&self) -> MachineStub { match self { ModuleSource::Library(ref name) => { functor!("library", [clause_name(name.clone())]) @@ -244,18 +246,18 @@ impl ModuleSource { } } -// pub type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator. +// pub(crate) type ScopedPredicateKey = (ClauseName, PredicateKey); // module name, predicate indicator. /* #[derive(Debug, Clone)] -pub enum MultiFileIndicator { +pub(crate) enum MultiFileIndicator { LocalScoped(ClauseName, usize), // name, arity ModuleScoped(ScopedPredicateKey), } */ #[derive(Clone, Copy, Hash, Debug)] -pub enum MetaSpec { +pub(crate) enum MetaSpec { Minus, Plus, Either, @@ -263,7 +265,7 @@ pub enum MetaSpec { } #[derive(Debug, Clone)] -pub enum Declaration { +pub(crate) enum Declaration { Dynamic(ClauseName, usize), MetaPredicate(ClauseName, ClauseName, Vec), // module name, name, meta-specs Module(ModuleDecl), @@ -274,20 +276,20 @@ pub enum Declaration { } #[derive(Debug, Clone, Eq, Hash, PartialEq, Ord, PartialOrd)] -pub struct OpDecl { - pub prec: usize, - pub spec: Specifier, - pub name: ClauseName, +pub(crate) struct OpDecl { + pub(crate) prec: usize, + pub(crate) spec: Specifier, + pub(crate) name: ClauseName, } impl OpDecl { #[inline] - pub fn new(prec: usize, spec: Specifier, name: ClauseName) -> Self { + pub(crate) fn new(prec: usize, spec: Specifier, name: ClauseName) -> Self { Self { prec, spec, name } } #[inline] - pub fn remove(&mut self, op_dir: &mut OpDir) { + pub(crate) fn remove(&mut self, op_dir: &mut OpDir) { let prec = self.prec; self.prec = 0; @@ -296,7 +298,7 @@ impl OpDecl { } #[inline] - pub fn fixity(&self) -> Fixity { + pub(crate) fn fixity(&self) -> Fixity { match self.spec { XFY | XFX | YFX => Fixity::In, XF | YF => Fixity::Post, @@ -305,7 +307,7 @@ impl OpDecl { } } - pub fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<(usize, Specifier)> { + pub(crate) fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<(usize, Specifier)> { let key = (self.name.clone(), self.fixity()); match op_dir.get(&key) { @@ -320,7 +322,7 @@ impl OpDecl { .map(|op_dir_value| op_dir_value.shared_op_desc().get()) } - pub fn submit( + pub(crate) fn submit( &self, existing_desc: Option, op_dir: &mut OpDir, @@ -348,7 +350,7 @@ impl OpDecl { } } -pub fn fetch_atom_op_spec( +pub(crate) fn fetch_atom_op_spec( name: ClauseName, spec: Option, op_dir: &OpDir, @@ -357,7 +359,7 @@ pub fn fetch_atom_op_spec( .or_else(|| fetch_op_spec_from_existing(name, 2, spec, op_dir)) } -pub fn fetch_op_spec_from_existing( +pub(crate) fn fetch_op_spec_from_existing( name: ClauseName, arity: usize, spec: Option, @@ -375,7 +377,11 @@ pub fn fetch_op_spec_from_existing( spec.or_else(|| fetch_op_spec(name, arity, op_dir)) } -pub fn fetch_op_spec(name: ClauseName, arity: usize, op_dir: &OpDir) -> Option { +pub(crate) fn fetch_op_spec( + name: ClauseName, + arity: usize, + op_dir: &OpDir, +) -> Option { match arity { 2 => op_dir .get(&(name, Fixity::In)) @@ -407,35 +413,35 @@ pub fn fetch_op_spec(name: ClauseName, arity: usize, op_dir: &OpDir) -> Option; +pub(crate) type ModuleDir = IndexMap; #[derive(Debug, Clone, Eq, Hash, PartialEq)] -pub enum ModuleExport { +pub(crate) enum ModuleExport { OpDecl(OpDecl), PredicateKey(PredicateKey), } #[derive(Debug, Clone)] -pub struct ModuleDecl { - pub name: ClauseName, - pub exports: Vec, +pub(crate) struct ModuleDecl { + pub(crate) name: ClauseName, + pub(crate) exports: Vec, } #[derive(Debug)] -pub struct Module { - pub module_decl: ModuleDecl, - pub code_dir: CodeDir, - pub op_dir: OpDir, - pub meta_predicates: MetaPredicateDir, - pub extensible_predicates: ExtensiblePredicates, - pub local_extensible_predicates: LocalExtensiblePredicates, - pub is_impromptu_module: bool, - pub listing_src: ListingSource, +pub(crate) struct Module { + pub(crate) module_decl: ModuleDecl, + pub(crate) code_dir: CodeDir, + pub(crate) op_dir: OpDir, + pub(crate) meta_predicates: MetaPredicateDir, + pub(crate) extensible_predicates: ExtensiblePredicates, + pub(crate) local_extensible_predicates: LocalExtensiblePredicates, + pub(crate) is_impromptu_module: bool, + pub(crate) listing_src: ListingSource, } // Module's and related types are defined in forms. impl Module { - pub fn new(module_decl: ModuleDecl, listing_src: ListingSource) -> Self { + pub(crate) fn new(module_decl: ModuleDecl, listing_src: ListingSource) -> Self { Module { module_decl, code_dir: CodeDir::new(), @@ -450,7 +456,7 @@ impl Module { } #[derive(Debug, Clone)] -pub enum Number { +pub(crate) enum Number { Float(OrderedFloat), Integer(Rc), Rational(Rc), @@ -510,7 +516,7 @@ impl Into for Number { impl Number { #[inline] - pub fn is_positive(&self) -> bool { + pub(crate) fn is_positive(&self) -> bool { match self { &Number::Fixnum(n) => n > 0, &Number::Integer(ref n) => &**n > &0, @@ -520,7 +526,7 @@ impl Number { } #[inline] - pub fn is_negative(&self) -> bool { + pub(crate) fn is_negative(&self) -> bool { match self { &Number::Fixnum(n) => n < 0, &Number::Integer(ref n) => &**n < &0, @@ -530,7 +536,7 @@ impl Number { } #[inline] - pub fn is_zero(&self) -> bool { + pub(crate) fn is_zero(&self) -> bool { match self { &Number::Fixnum(n) => n == 0, &Number::Integer(ref n) => &**n == &0, @@ -540,7 +546,7 @@ impl Number { } #[inline] - pub fn abs(self) -> Self { + pub(crate) fn abs(self) -> Self { match self { Number::Fixnum(n) => { if let Some(n) = n.checked_abs() { @@ -557,7 +563,7 @@ impl Number { } #[derive(Debug, Clone)] -pub enum OptArgIndexKey { +pub(crate) enum OptArgIndexKey { Constant(usize, usize, Constant, Vec), // index, IndexingCode location, opt arg, alternatives List(usize, usize), // index, IndexingCode location None, @@ -566,12 +572,12 @@ pub enum OptArgIndexKey { impl OptArgIndexKey { #[inline] - pub fn take(&mut self) -> OptArgIndexKey { + pub(crate) fn take(&mut self) -> OptArgIndexKey { std::mem::replace(self, OptArgIndexKey::None) } #[inline] - pub fn arg_num(&self) -> usize { + pub(crate) fn arg_num(&self) -> usize { match &self { OptArgIndexKey::Constant(arg_num, ..) | OptArgIndexKey::Structure(arg_num, ..) @@ -584,12 +590,12 @@ impl OptArgIndexKey { } #[inline] - pub fn is_some(&self) -> bool { + pub(crate) fn is_some(&self) -> bool { self.switch_on_term_loc().is_some() } #[inline] - pub fn switch_on_term_loc(&self) -> Option { + pub(crate) fn switch_on_term_loc(&self) -> Option { match &self { OptArgIndexKey::Constant(_, loc, ..) | OptArgIndexKey::Structure(_, loc, ..) @@ -599,7 +605,7 @@ impl OptArgIndexKey { } #[inline] - pub fn set_switch_on_term_loc(&mut self, value: usize) { + pub(crate) fn set_switch_on_term_loc(&mut self, value: usize) { match self { OptArgIndexKey::Constant(_, ref mut loc, ..) | OptArgIndexKey::Structure(_, ref mut loc, ..) @@ -626,14 +632,14 @@ impl AddAssign for OptArgIndexKey { } #[derive(Clone, Debug)] -pub struct ClauseIndexInfo { - pub clause_start: usize, - pub opt_arg_index_key: OptArgIndexKey, +pub(crate) struct ClauseIndexInfo { + pub(crate) clause_start: usize, + pub(crate) opt_arg_index_key: OptArgIndexKey, } impl ClauseIndexInfo { #[inline] - pub fn new(clause_start: usize) -> Self { + pub(crate) fn new(clause_start: usize) -> Self { Self { clause_start, opt_arg_index_key: OptArgIndexKey::None, @@ -643,12 +649,12 @@ impl ClauseIndexInfo { } #[derive(Clone, Copy, Debug)] -pub struct PredicateInfo { - pub is_extensible: bool, - pub is_discontiguous: bool, - pub is_dynamic: bool, - pub is_multifile: bool, - pub has_clauses: bool, +pub(crate) struct PredicateInfo { + pub(crate) is_extensible: bool, + pub(crate) is_discontiguous: bool, + pub(crate) is_dynamic: bool, + pub(crate) is_multifile: bool, + pub(crate) has_clauses: bool, } impl Default for PredicateInfo { @@ -666,30 +672,30 @@ impl Default for PredicateInfo { impl PredicateInfo { #[inline] - pub fn compile_incrementally(&self) -> bool { + pub(crate) fn compile_incrementally(&self) -> bool { let base = self.is_extensible && self.has_clauses; base && (self.is_discontiguous || self.is_multifile) } #[inline] - pub fn must_retract_local_clauses(&self) -> bool { + pub(crate) fn must_retract_local_clauses(&self) -> bool { self.is_extensible && self.has_clauses && !self.is_discontiguous } } #[derive(Debug)] -pub struct PredicateSkeleton { - pub is_discontiguous: bool, - pub is_dynamic: bool, - pub is_multifile: bool, - pub clauses: SliceDeque, - pub clause_clause_locs: SliceDeque, - pub clause_assert_margin: usize, +pub(crate) struct PredicateSkeleton { + pub(crate) is_discontiguous: bool, + pub(crate) is_dynamic: bool, + pub(crate) is_multifile: bool, + pub(crate) clauses: SliceDeque, + pub(crate) clause_clause_locs: SliceDeque, + pub(crate) clause_assert_margin: usize, } impl PredicateSkeleton { #[inline] - pub fn new() -> Self { + pub(crate) fn new() -> Self { PredicateSkeleton { is_discontiguous: false, is_dynamic: false, @@ -701,7 +707,7 @@ impl PredicateSkeleton { } #[inline] - pub fn predicate_info(&self) -> PredicateInfo { + pub(crate) fn predicate_info(&self) -> PredicateInfo { PredicateInfo { is_extensible: true, is_discontiguous: self.is_discontiguous, @@ -712,13 +718,13 @@ impl PredicateSkeleton { } #[inline] - pub fn reset(&mut self) { + pub(crate) fn reset(&mut self) { self.clauses.clear(); self.clause_clause_locs.clear(); self.clause_assert_margin = 0; } - pub fn target_pos_of_clause_clause_loc( + pub(crate) fn target_pos_of_clause_clause_loc( &self, clause_clause_loc: usize, ) -> Option { @@ -727,10 +733,10 @@ impl PredicateSkeleton { match search_result { Ok(loc) => Some(loc), - Err(_) => self.clause_clause_locs[self.clause_assert_margin..] + Err(_) => self.clause_clause_locs[self.clause_assert_margin..] .binary_search_by(|loc| loc.cmp(&clause_clause_loc)) .map(|loc| loc + self.clause_assert_margin) - .ok() + .ok(), } } } diff --git a/src/heap_iter.rs b/src/heap_iter.rs index a6d2e5fa..fd057ac3 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -8,13 +8,13 @@ use std::ops::Deref; use std::vec::Vec; #[derive(Debug)] -pub struct HCPreOrderIterator<'a> { - pub machine_st: &'a MachineState, - pub state_stack: Vec, +pub(crate) struct HCPreOrderIterator<'a> { + pub(crate) machine_st: &'a MachineState, + pub(crate) state_stack: Vec, } impl<'a> HCPreOrderIterator<'a> { - pub fn new(machine_st: &'a MachineState, a: Addr) -> Self { + pub(crate) fn new(machine_st: &'a MachineState, a: Addr) -> Self { HCPreOrderIterator { machine_st, state_stack: vec![a], @@ -22,7 +22,7 @@ impl<'a> HCPreOrderIterator<'a> { } #[inline] - pub fn machine_st(&self) -> &MachineState { + pub(crate) fn machine_st(&self) -> &MachineState { &self.machine_st } @@ -116,7 +116,7 @@ impl<'a> Iterator for HCPreOrderIterator<'a> { } } -pub trait MutStackHCIterator<'b> +pub(crate) trait MutStackHCIterator<'b> where Self: Iterator, { @@ -126,7 +126,7 @@ where } #[derive(Debug)] -pub struct HCPostOrderIterator<'a> { +pub(crate) struct HCPostOrderIterator<'a> { base_iter: HCPreOrderIterator<'a>, parent_stack: Vec<(usize, Addr)>, // number of children, parent node. } @@ -140,7 +140,7 @@ impl<'a> Deref for HCPostOrderIterator<'a> { } impl<'a> HCPostOrderIterator<'a> { - pub fn new(base_iter: HCPreOrderIterator<'a>) -> Self { + pub(crate) fn new(base_iter: HCPreOrderIterator<'a>) -> Self { HCPostOrderIterator { base_iter, parent_stack: vec![], @@ -201,19 +201,19 @@ impl<'a> Iterator for HCPostOrderIterator<'a> { } impl MachineState { - pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> { + pub(crate) fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> { HCPreOrderIterator::new(self, a) } - pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCPostOrderIterator<'a> { + pub(crate) fn post_order_iter<'a>(&'a self, a: Addr) -> HCPostOrderIterator<'a> { HCPostOrderIterator::new(HCPreOrderIterator::new(self, a)) } - pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr) -> HCAcyclicIterator<'a> { + pub(crate) fn acyclic_pre_order_iter<'a>(&'a self, a: Addr) -> HCAcyclicIterator<'a> { HCAcyclicIterator::new(HCPreOrderIterator::new(self, a)) } - pub fn zipped_acyclic_pre_order_iter<'a>( + pub(crate) fn zipped_acyclic_pre_order_iter<'a>( &'a self, a1: Addr, a2: Addr, @@ -234,13 +234,13 @@ impl<'b, 'a: 'b> MutStackHCIterator<'b> for HCPreOrderIterator<'a> { } #[derive(Debug)] -pub struct HCAcyclicIterator<'a> { +pub(crate) struct HCAcyclicIterator<'a> { iter: HCPreOrderIterator<'a>, seen: IndexSet, } impl<'a> HCAcyclicIterator<'a> { - pub fn new(iter: HCPreOrderIterator<'a>) -> Self { + pub(crate) fn new(iter: HCPreOrderIterator<'a>) -> Self { HCAcyclicIterator { iter, seen: IndexSet::new(), @@ -282,11 +282,11 @@ impl<'a> Iterator for HCAcyclicIterator<'a> { } #[derive(Debug)] -pub struct HCZippedAcyclicIterator<'a> { +pub(crate) struct HCZippedAcyclicIterator<'a> { i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>, seen: IndexSet<(Addr, Addr)>, - pub first_to_expire: Ordering, + pub(crate) first_to_expire: Ordering, } impl<'b, 'a: 'b> MutStackHCIterator<'b> for HCZippedAcyclicIterator<'a> { @@ -298,7 +298,7 @@ impl<'b, 'a: 'b> MutStackHCIterator<'b> for HCZippedAcyclicIterator<'a> { } impl<'a> HCZippedAcyclicIterator<'a> { - pub fn new(i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>) -> Self { + pub(crate) fn new(i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>) -> Self { HCZippedAcyclicIterator { i1, i2, diff --git a/src/heap_print.rs b/src/heap_print.rs index a7250c2f..5e05d5b5 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -27,7 +27,7 @@ use std::rc::Rc; /* contains the location, name, precision and Specifier of the parent op. */ #[derive(Debug, Clone)] -pub enum DirectedOp { +pub(crate) enum DirectedOp { Left(ClauseName, SharedOpDesc), Right(ClauseName, SharedOpDesc), } @@ -190,7 +190,7 @@ enum TokenOrRedirect { HeadTailSeparator, } -pub trait HCValueOutputter { +pub(crate) trait HCValueOutputter { type Output; fn new() -> Self; @@ -207,7 +207,7 @@ pub trait HCValueOutputter { } #[derive(Debug)] -pub struct PrinterOutputter { +pub(crate) struct PrinterOutputter { contents: String, } @@ -306,7 +306,7 @@ fn numbervar(n: Integer) -> Var { } impl MachineState { - pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option { + pub(crate) fn numbervar(&self, offset: &Integer, addr: Addr) -> Option { let addr = self.store(self.deref(addr)); match Number::try_from((addr, &self.heap)) { @@ -332,7 +332,7 @@ impl MachineState { type ReverseHeapVarDict = IndexMap>; #[derive(Debug)] -pub struct HCPrinter<'a, Outputter> { +pub(crate) struct HCPrinter<'a, Outputter> { outputter: Outputter, machine_st: &'a MachineState, op_dir: &'a OpDir, @@ -363,7 +363,7 @@ macro_rules! push_space_if_amb { }; } -pub fn requires_space(atom: &str, op: &str) -> bool { +pub(crate) fn requires_space(atom: &str, op: &str) -> bool { match atom.chars().last() { Some(ac) => op .chars() @@ -473,7 +473,7 @@ fn functor_location(addr: &Addr) -> Option { } impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { - pub fn new(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) -> Self { + pub(crate) fn new(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) -> Self { HCPrinter { outputter: output, machine_st, @@ -495,7 +495,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } /* - pub fn from_heap_locs( + pub(crate) fn from_heap_locs( machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter, @@ -513,13 +513,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } */ /* - pub fn drop_toplevel_spec(&mut self) { + pub(crate) fn drop_toplevel_spec(&mut self) { self.toplevel_spec = None; } */ /* #[inline] - pub fn see_all_locs(&mut self) { + pub(crate) fn see_all_locs(&mut self) { for key in self.heap_locs.keys().cloned() { self.printed_vars.insert(key); } @@ -1517,7 +1517,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - pub fn print(mut self, addr: Addr) -> Outputter { + pub(crate) fn print(mut self, addr: Addr) -> Outputter { let mut iter = self.machine_st.pre_order_iter(addr); loop { diff --git a/src/indexing.rs b/src/indexing.rs index 754cc57d..be6d7260 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -17,7 +17,7 @@ use std::mem; use std::rc::Rc; #[derive(Debug, Clone, Copy)] -pub enum IndexingCodePtr { +pub(crate) enum IndexingCodePtr { External(usize), // the index points past the indexing instruction prelude. DynamicExternal(usize), // an External index of a dynamic predicate, potentially invalidated by retraction. Fail, @@ -585,7 +585,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { } } -pub fn merge_clause_index( +pub(crate) fn merge_clause_index( target_indexing_code: &mut Vec, 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. @@ -638,7 +638,7 @@ pub fn merge_clause_index( } } -pub fn remove_constant_indices( +pub(crate) fn remove_constant_indices( constant: &Constant, overlapping_constants: &[Constant], indexing_code: &mut Vec, @@ -778,7 +778,7 @@ pub fn remove_constant_indices( } } -pub fn remove_structure_index( +pub(crate) fn remove_structure_index( name: &ClauseName, arity: usize, indexing_code: &mut Vec, @@ -917,7 +917,7 @@ pub fn remove_structure_index( } } -pub fn remove_list_index(indexing_code: &mut Vec, offset: usize) { +pub(crate) fn remove_list_index(indexing_code: &mut Vec, offset: usize) { let mut index = 0; match &mut indexing_code[index] { @@ -995,7 +995,7 @@ pub fn remove_list_index(indexing_code: &mut Vec, offset: usize) { } } -pub fn remove_index( +pub(crate) fn remove_index( opt_arg_index_key: &OptArgIndexKey, indexing_code: &mut Vec, clause_loc: usize, @@ -1065,7 +1065,7 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) { }); } -pub fn constant_key_alternatives(constant: &Constant, atom_tbl: TabledData) -> Vec { +pub(crate) fn constant_key_alternatives(constant: &Constant, atom_tbl: TabledData) -> Vec { let mut constants = vec![]; match constant { @@ -1128,7 +1128,7 @@ pub(crate) struct DynamicCodeIndices { structures: IndexMap<(ClauseName, usize), SliceDeque>, } -pub trait Indexer { +pub(crate) trait Indexer { type ThirdLevelIndex; fn new() -> Self; @@ -1383,14 +1383,14 @@ impl Indexer for DynamicCodeIndices { } #[derive(Debug)] -pub struct CodeOffsets { +pub(crate) struct CodeOffsets { atom_tbl: TabledData, indices: I, optimal_index: usize, } impl CodeOffsets { - pub fn new( + pub(crate) fn new( atom_tbl: TabledData, indices: I, optimal_index: usize, @@ -1440,7 +1440,7 @@ impl CodeOffsets { code_len } - pub fn index_term( + pub(crate) fn index_term( &mut self, optimal_arg: &Term, index: usize, @@ -1472,7 +1472,7 @@ impl CodeOffsets { } } - pub fn no_indices(&mut self) -> bool { + pub(crate) fn no_indices(&mut self) -> bool { let no_constants = self.indices.constants().is_empty(); let no_structures = self.indices.structures().is_empty(); let no_lists = self.indices.lists().is_empty(); @@ -1480,7 +1480,7 @@ impl CodeOffsets { no_constants && no_structures && no_lists } - pub fn compute_indices(mut self, skip_stub_try_me_else: bool) -> Vec { + pub(crate) fn compute_indices(mut self, skip_stub_try_me_else: bool) -> Vec { if self.no_indices() { return vec![]; } @@ -1488,7 +1488,7 @@ impl CodeOffsets { let mut prelude = sdeq![]; let mut emitted_switch_on_structure = false; - let mut emitted_switch_on_constant = false; + let mut emitted_switch_on_constant = false; let mut lst_loc = I::switch_on_list(self.indices.lists(), &mut prelude); diff --git a/src/instructions.rs b/src/instructions.rs index e552c8e3..90cbeeab 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -47,7 +47,7 @@ impl ArithmeticTerm { } #[derive(Debug, Clone, Copy)] -pub enum NextOrFail { +pub(crate) enum NextOrFail { Next(usize), Fail(usize), } @@ -64,13 +64,13 @@ impl NextOrFail { } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Death { +pub(crate) enum Death { Finite(usize), Infinity, } #[derive(Debug)] -pub enum ChoiceInstruction { +pub(crate) enum ChoiceInstruction { DynamicElse(usize, Death, NextOrFail), DynamicInternalElse(usize, Death, NextOrFail), DefaultRetryMeElse(usize), @@ -81,7 +81,7 @@ pub enum ChoiceInstruction { } impl ChoiceInstruction { - pub fn to_functor(&self, h: usize) -> MachineStub { + pub(crate) fn to_functor(&self, h: usize) -> MachineStub { match self { &ChoiceInstruction::DynamicElse(birth, death, next_or_fail) => { match (death, next_or_fail) { @@ -171,7 +171,7 @@ impl ChoiceInstruction { } #[derive(Debug)] -pub enum CutInstruction { +pub(crate) enum CutInstruction { Cut(RegType), GetLevel(RegType), GetLevelAndUnify(RegType), @@ -179,7 +179,7 @@ pub enum CutInstruction { } impl CutInstruction { - pub fn to_functor(&self, h: usize) -> MachineStub { + pub(crate) fn to_functor(&self, h: usize) -> MachineStub { match self { &CutInstruction::Cut(r) => { let rt_stub = reg_type_into_functor(r); @@ -201,14 +201,14 @@ impl CutInstruction { } #[derive(Clone, Copy, Debug)] -pub enum IndexedChoiceInstruction { +pub(crate) enum IndexedChoiceInstruction { Retry(usize), Trust(usize), Try(usize), } impl IndexedChoiceInstruction { - pub fn offset(&self) -> usize { + pub(crate) fn offset(&self) -> usize { match self { &IndexedChoiceInstruction::Retry(offset) => offset, &IndexedChoiceInstruction::Trust(offset) => offset, @@ -216,7 +216,7 @@ impl IndexedChoiceInstruction { } } - pub fn to_functor(&self) -> MachineStub { + pub(crate) fn to_functor(&self) -> MachineStub { match self { &IndexedChoiceInstruction::Try(offset) => { functor!("try", [integer(offset)]) @@ -233,7 +233,7 @@ impl IndexedChoiceInstruction { /// A `Line` is an instruction (cf. page 98 of wambook). #[derive(Debug)] -pub enum IndexingLine { +pub(crate) enum IndexingLine { Indexing(IndexingInstruction), IndexedChoice(SliceDeque), DynamicIndexedChoice(SliceDeque), @@ -254,7 +254,7 @@ impl From> for IndexingLine { } #[derive(Debug)] -pub enum Line { +pub(crate) enum Line { Arithmetic(ArithmeticInstruction), Choice(ChoiceInstruction), Control(ControlInstruction), @@ -268,7 +268,7 @@ pub enum Line { impl Line { #[inline] - pub fn is_head_instr(&self) -> bool { + pub(crate) fn is_head_instr(&self) -> bool { match self { &Line::Fact(_) => true, &Line::Query(_) => true, @@ -276,7 +276,7 @@ impl Line { } } - pub fn enqueue_functors(&self, mut h: usize, functors: &mut Vec) { + pub(crate) fn enqueue_functors(&self, mut h: usize, functors: &mut Vec) { match self { &Line::Arithmetic(ref arith_instr) => functors.push(arith_instr.to_functor(h)), &Line::Choice(ref choice_instr) => functors.push(choice_instr.to_functor(h)), @@ -320,7 +320,7 @@ impl Line { } #[inline] -pub fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec> { +pub(crate) fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec> { match line { Line::IndexingCode(ref mut indexing_code) => Some(indexing_code), _ => None, @@ -328,7 +328,7 @@ pub fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec> { } #[inline] -pub fn to_indexing_line(line: &Line) -> Option<&Vec> { +pub(crate) fn to_indexing_line(line: &Line) -> Option<&Vec> { match line { Line::IndexingCode(ref indexing_code) => Some(indexing_code), _ => None, @@ -336,7 +336,7 @@ pub fn to_indexing_line(line: &Line) -> Option<&Vec> { } #[derive(Debug, Clone)] -pub enum ArithmeticInstruction { +pub(crate) enum ArithmeticInstruction { Add(ArithmeticTerm, ArithmeticTerm, usize), Sub(ArithmeticTerm, ArithmeticTerm, usize), Mul(ArithmeticTerm, ArithmeticTerm, usize), @@ -407,7 +407,7 @@ fn arith_instr_bin_functor( } impl ArithmeticInstruction { - pub fn to_functor(&self, h: usize) -> MachineStub { + pub(crate) fn to_functor(&self, h: usize) -> MachineStub { match self { &ArithmeticInstruction::Add(ref at_1, ref at_2, t) => { arith_instr_bin_functor(h, "add", at_1, at_2, t) @@ -505,7 +505,7 @@ impl ArithmeticInstruction { } #[derive(Debug)] -pub enum ControlInstruction { +pub(crate) enum ControlInstruction { Allocate(usize), // num_frames. // name, arity, perm_vars after threshold, last call, use default call policy. CallClause(ClauseType, usize, usize, bool, bool), @@ -518,7 +518,7 @@ pub enum ControlInstruction { } impl ControlInstruction { - pub fn perm_vars(&self) -> Option { + pub(crate) fn perm_vars(&self) -> Option { match self { ControlInstruction::CallClause(_, _, num_cells, ..) => Some(*num_cells), ControlInstruction::JmpBy(_, _, num_cells, ..) => Some(*num_cells), @@ -526,7 +526,7 @@ impl ControlInstruction { } } - pub fn to_functor(&self) -> MachineStub { + pub(crate) fn to_functor(&self) -> MachineStub { match self { &ControlInstruction::Allocate(num_frames) => { functor!("allocate", [integer(num_frames)]) @@ -555,7 +555,7 @@ impl ControlInstruction { /// `IndexingInstruction` cf. page 110 of wambook. #[derive(Debug)] -pub enum IndexingInstruction { +pub(crate) enum IndexingInstruction { // The first index is the optimal argument being indexed. SwitchOnTerm( usize, @@ -569,7 +569,7 @@ pub enum IndexingInstruction { } impl IndexingInstruction { - pub fn to_functor(&self, mut h: usize) -> MachineStub { + pub(crate) fn to_functor(&self, mut h: usize) -> MachineStub { match self { &IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => { functor!( @@ -657,7 +657,7 @@ impl IndexingInstruction { } #[derive(Debug, Clone)] -pub enum FactInstruction { +pub(crate) enum FactInstruction { GetConstant(Level, Constant, RegType), GetList(Level, RegType), GetPartialString(Level, String, RegType, bool), @@ -672,7 +672,7 @@ pub enum FactInstruction { } impl FactInstruction { - pub fn to_functor(&self, h: usize) -> MachineStub { + pub(crate) fn to_functor(&self, h: usize) -> MachineStub { match self { &FactInstruction::GetConstant(lvl, ref c, r) => { let lvl_stub = lvl.into_functor(); @@ -745,7 +745,7 @@ impl FactInstruction { } #[derive(Debug, Clone)] -pub enum QueryInstruction { +pub(crate) enum QueryInstruction { GetVariable(RegType, usize), PutConstant(Level, Constant, RegType), PutList(Level, RegType), @@ -762,7 +762,7 @@ pub enum QueryInstruction { } impl QueryInstruction { - pub fn to_functor(&self, h: usize) -> MachineStub { + pub(crate) fn to_functor(&self, h: usize) -> MachineStub { match self { &QueryInstruction::PutUnsafeValue(norm, arg) => { functor!("put_unsafe_value", [integer(norm), integer(arg)]) @@ -842,6 +842,6 @@ impl QueryInstruction { } } -pub type CompiledFact = Vec; +pub(crate) type CompiledFact = Vec; -pub type Code = Vec; +pub(crate) type Code = Vec; diff --git a/src/iterators.rs b/src/iterators.rs index fc4fbdc3..a83c5796 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -13,7 +13,7 @@ use std::rc::Rc; use std::vec::Vec; #[derive(Debug, Clone)] -pub enum TermRef<'a> { +pub(crate) enum TermRef<'a> { AnonVar(Level), Cons(Level, &'a Cell, &'a Term, &'a Term), Constant(Level, &'a Cell, &'a Constant), @@ -23,7 +23,7 @@ pub enum TermRef<'a> { } impl<'a> TermRef<'a> { - pub fn level(self) -> Level { + pub(crate) fn level(self) -> Level { match self { TermRef::AnonVar(lvl) | TermRef::Cons(lvl, ..) @@ -36,7 +36,7 @@ impl<'a> TermRef<'a> { } #[derive(Debug)] -pub enum TermIterState<'a> { +pub(crate) enum TermIterState<'a> { AnonVar(Level), Constant(Level, &'a Cell, &'a Constant), Clause( @@ -97,7 +97,7 @@ fn is_partial_string<'a>(head: &'a Term, mut tail: &'a Term) -> Option<(String, } impl<'a> TermIterState<'a> { - pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { + pub(crate) fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { match term { &Term::AnonVar => TermIterState::AnonVar(lvl), &Term::Clause(ref cell, ref name, ref subterms, ref spec) => { @@ -119,7 +119,7 @@ impl<'a> TermIterState<'a> { } #[derive(Debug)] -pub struct QueryIterator<'a> { +pub(crate) struct QueryIterator<'a> { state_stack: Vec>, } @@ -286,7 +286,7 @@ impl<'a> Iterator for QueryIterator<'a> { } #[derive(Debug)] -pub struct FactIterator<'a> { +pub(crate) struct FactIterator<'a> { state_queue: VecDeque>, iterable_root: bool, } @@ -297,7 +297,7 @@ impl<'a> FactIterator<'a> { .push_back(TermIterState::subterm_to_state(lvl, term)); } - pub fn from_rule_head_clause(terms: &'a Vec>) -> Self { + pub(crate) fn from_rule_head_clause(terms: &'a Vec>) -> Self { let state_queue = terms .iter() .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref())) @@ -386,26 +386,26 @@ impl<'a> Iterator for FactIterator<'a> { } } -pub fn post_order_iter(term: &Term) -> QueryIterator { +pub(crate) fn post_order_iter(term: &Term) -> QueryIterator { QueryIterator::from_term(term) } -pub fn breadth_first_iter(term: &Term, iterable_root: bool) -> FactIterator { +pub(crate) fn breadth_first_iter(term: &Term, iterable_root: bool) -> FactIterator { FactIterator::new(term, iterable_root) } #[derive(Debug)] -pub enum ChunkedTerm<'a> { +pub(crate) enum ChunkedTerm<'a> { HeadClause(ClauseName, &'a Vec>), BodyTerm(&'a QueryTerm), } -pub fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> { +pub(crate) fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> { QueryIterator::new(query_term) } impl<'a> ChunkedTerm<'a> { - pub fn post_order_iter(&self) -> QueryIterator<'a> { + pub(crate) fn post_order_iter(&self) -> QueryIterator<'a> { match self { &ChunkedTerm::BodyTerm(ref qt) => QueryIterator::new(qt), &ChunkedTerm::HeadClause(_, terms) => QueryIterator::from_rule_head_clause(terms), @@ -425,8 +425,8 @@ fn contains_cut_var<'a, Iter: Iterator>(terms: Iter) -> bool { false } -pub struct ChunkedIterator<'a> { - pub chunk_num: usize, +pub(crate) struct ChunkedIterator<'a> { + pub(crate) chunk_num: usize, iter: Box> + 'a>, deep_cut_encountered: bool, cut_var_in_head: bool, @@ -448,7 +448,7 @@ type ChunkedIteratorItem<'a> = (usize, usize, Vec>); type RuleBodyIteratorItem<'a> = (usize, usize, Vec<&'a QueryTerm>); impl<'a> ChunkedIterator<'a> { - pub fn rule_body_iter(self) -> Box> + 'a> { + pub(crate) fn rule_body_iter(self) -> Box> + 'a> { Box::new(self.filter_map(|(cn, lt_arity, terms)| { let filtered_terms: Vec<_> = terms .into_iter() @@ -466,7 +466,7 @@ impl<'a> ChunkedIterator<'a> { })) } /* - pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self { + pub(crate) fn from_term_sequence(terms: &'a [QueryTerm]) -> Self { ChunkedIterator { chunk_num: 0, iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))), @@ -475,7 +475,7 @@ impl<'a> ChunkedIterator<'a> { } } */ - pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec) -> Self { + pub(crate) fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec) -> Self { let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))); @@ -487,7 +487,7 @@ impl<'a> ChunkedIterator<'a> { } } - pub fn from_rule(rule: &'a Rule) -> Self { + pub(crate) fn from_rule(rule: &'a Rule) -> Self { let &Rule { head: (ref name, ref args, ref p1), ref clauses, @@ -505,7 +505,7 @@ impl<'a> ChunkedIterator<'a> { } } - pub fn encountered_deep_cut(&self) -> bool { + pub(crate) fn encountered_deep_cut(&self) -> bool { self.deep_cut_encountered } diff --git a/src/main.rs b/src/lib.rs similarity index 61% rename from src/main.rs rename to src/lib.rs index a79563b6..06fead04 100644 --- a/src/main.rs +++ b/src/lib.rs @@ -17,29 +17,19 @@ mod heap_print; mod indexing; mod instructions; mod iterators; -mod machine; -mod read; +pub mod machine; +pub mod read; mod targets; mod write; -use machine::streams::*; use machine::*; -use read::*; use nix::sys::signal; use std::sync::atomic::Ordering; -extern "C" fn handle_sigint(signal: libc::c_int) { +pub extern "C" fn handle_sigint(signal: libc::c_int) { let signal = signal::Signal::from_c_int(signal).unwrap(); if signal == signal::Signal::SIGINT { INTERRUPT.store(true, Ordering::Relaxed); } } - -fn main() { - let handler = signal::SigHandler::Handler(handle_sigint); - unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap(); - - let mut wam = Machine::new(readline::input_stream(), Stream::stdout()); - wam.run_top_level(); -} diff --git a/src/machine/code_repo.rs b/src/machine/code_repo.rs index 1a812b58..bb21462e 100644 --- a/src/machine/code_repo.rs +++ b/src/machine/code_repo.rs @@ -3,58 +3,44 @@ use crate::instructions::*; use crate::machine::machine_indices::*; #[derive(Debug)] -pub struct CodeRepo { +pub(crate) struct CodeRepo { pub(super) code: Code, } impl CodeRepo { #[inline] - pub(super) - fn new() -> Self { - CodeRepo { - code: Code::new(), - } + pub(super) fn new() -> Self { + CodeRepo { code: Code::new() } } #[inline] - pub(super) - fn lookup_local_instr<'a>( - &'a self, - p: LocalCodePtr, - ) -> RefOrOwned<'a, Line> { + pub(super) fn lookup_local_instr<'a>(&'a self, p: LocalCodePtr) -> RefOrOwned<'a, Line> { match p { LocalCodePtr::Halt => { // exit with the interrupt exit code. std::process::exit(1); } - 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])) - } - &IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { - RefOrOwned::Owned(Line::DynamicIndexedChoice(indexed_choice_instrs[i])) - } - _ => { - unreachable!() - } - } + 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])) + } + &IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { + RefOrOwned::Owned(Line::DynamicIndexedChoice(indexed_choice_instrs[i])) } _ => { unreachable!() } + }, + _ => { + unreachable!() } - } + }, } } - pub(super) - fn lookup_instr<'a>( + pub(super) fn lookup_instr<'a>( &'a self, last_call: bool, p: &CodePtr, @@ -63,9 +49,7 @@ impl CodeRepo { &CodePtr::Local(local) => { return Some(self.lookup_local_instr(local)); } - &CodePtr::REPL(..) => { - None - } + &CodePtr::REPL(..) => None, &CodePtr::BuiltInClause(ref built_in, _) => { let call_clause = call_clause!( ClauseType::BuiltIn(built_in.clone()), @@ -77,26 +61,26 @@ impl CodeRepo { 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::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])), } } - pub(super) - fn find_living_dynamic_else(&self, mut p: usize, cc: usize) -> Option<(usize, usize)> { + pub(super) fn find_living_dynamic_else( + &self, + mut p: usize, + cc: usize, + ) -> Option<(usize, usize)> { loop { match &self.code[p] { - &Line::Choice(ChoiceInstruction::DynamicElse(birth, death, NextOrFail::Next(i))) => { + &Line::Choice(ChoiceInstruction::DynamicElse( + birth, + death, + NextOrFail::Next(i), + )) => { if birth < cc && Death::Finite(cc) <= death { return Some((p, i)); } else if i > 0 { @@ -105,7 +89,11 @@ impl CodeRepo { return None; } } - &Line::Choice(ChoiceInstruction::DynamicElse(birth, death, NextOrFail::Fail(_))) => { + &Line::Choice(ChoiceInstruction::DynamicElse( + birth, + death, + NextOrFail::Fail(_), + )) => { if birth < cc && Death::Finite(cc) <= death { return Some((p, 0)); } else { @@ -128,8 +116,8 @@ impl CodeRepo { &Line::Choice(ChoiceInstruction::DynamicInternalElse( birth, death, - NextOrFail::Fail(_)), - ) => { + NextOrFail::Fail(_), + )) => { if birth < cc && Death::Finite(cc) <= death { return Some((p, 0)); } else { @@ -146,8 +134,11 @@ impl CodeRepo { } } - pub(super) - fn find_living_dynamic(&self, p: LocalCodePtr, cc: usize) -> Option<(usize, usize, usize, bool)> { + pub(super) fn find_living_dynamic( + &self, + p: LocalCodePtr, + cc: usize, + ) -> Option<(usize, usize, usize, bool)> { let (p, oi, mut ii) = match p { LocalCodePtr::IndexingBuf(p, oi, ii) => (p, oi, ii), _ => unreachable!(), @@ -158,27 +149,27 @@ impl CodeRepo { IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { indexed_choice_instrs } - _ => unreachable!() - } - _ => unreachable!() + _ => unreachable!(), + }, + _ => unreachable!(), }; loop { match &indexed_choice_instrs.get(ii) { - Some(&offset) => { - match &self.code[p + offset - 1] { - &Line::Choice(ChoiceInstruction::DynamicInternalElse( - birth, death, next_or_fail, - )) => { - if birth < cc && Death::Finite(cc) <= death { - return Some((offset, oi, ii, next_or_fail.is_next())); - } else { - ii += 1; - } + Some(&offset) => match &self.code[p + offset - 1] { + &Line::Choice(ChoiceInstruction::DynamicInternalElse( + birth, + death, + next_or_fail, + )) => { + if birth < cc && Death::Finite(cc) <= death { + return Some((offset, oi, ii, next_or_fail.is_next())); + } else { + ii += 1; } - _ => unreachable!(), } - } + _ => unreachable!(), + }, None => return None, } } diff --git a/src/machine/code_walker.rs b/src/machine/code_walker.rs index 2d199fd6..9bde8a36 100644 --- a/src/machine/code_walker.rs +++ b/src/machine/code_walker.rs @@ -7,8 +7,10 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec) -> bool { &Line::Choice(ChoiceInstruction::TryMeElse(offset)) if offset > 0 => { stack.push(index + offset); } - &Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) | - &Line::Choice(ChoiceInstruction::RetryMeElse(offset)) if offset > 0 => { + &Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) + | &Line::Choice(ChoiceInstruction::RetryMeElse(offset)) + if offset > 0 => + { stack.push(index + offset); } &Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset))) @@ -26,8 +28,8 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec) -> bool { stack.push(index + offset); return true; } - &Line::Control(ControlInstruction::Proceed) | - &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) => { + &Line::Control(ControlInstruction::Proceed) + | &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) => { return true; } &Line::Control(ControlInstruction::RevJmpBy(offset)) => { @@ -37,8 +39,7 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec) -> bool { return true; } } - _ => { - } + _ => {} }; false @@ -48,8 +49,7 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec) -> bool { * begin in code at the offset p. Each instruction is passed to the * walker function. */ -pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) -{ +pub(crate) fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) { let mut stack = vec![p]; let mut visited_indices = IndexSet::new(); @@ -60,7 +60,7 @@ pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) visited_indices.insert(first_index); } - for (index, instr) in code[first_index ..].iter().enumerate() { + for (index, instr) in code[first_index..].iter().enumerate() { walker(instr); if capture_offset(instr, first_index + index, &mut stack) { @@ -74,7 +74,7 @@ pub fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) * the code. Otherwise identical to walk_code. */ /* -pub fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line)) +pub(crate) fn walk_code_mut(code: &mut Code, p: usize, mut walker: impl FnMut(&mut Line)) { let mut queue = VecDeque::from(vec![p]); diff --git a/src/machine/copier.rs b/src/machine/copier.rs index ba2eff53..fdd52c96 100644 --- a/src/machine/copier.rs +++ b/src/machine/copier.rs @@ -7,13 +7,12 @@ use std::ops::IndexMut; type Trail = Vec<(Ref, HeapCellValue)>; #[derive(Debug, Clone, Copy)] -pub enum AttrVarPolicy { +pub(crate) enum AttrVarPolicy { DeepCopy, - StripAttributes + StripAttributes, } -pub(crate) -trait CopierTarget: IndexMut { +pub(crate) trait CopierTarget: IndexMut { fn deref(&self, val: Addr) -> Addr; fn push(&mut self, val: HeapCellValue); fn stack(&mut self) -> &mut Stack; @@ -21,8 +20,7 @@ trait CopierTarget: IndexMut { fn threshold(&self) -> usize; } -pub(crate) -fn copy_term(target: T, addr: Addr, attr_var_policy: AttrVarPolicy) { +pub(crate) fn copy_term(target: T, addr: Addr, attr_var_policy: AttrVarPolicy) { let mut copy_term_state = CopyTermState::new(target, attr_var_policy); copy_term_state.copy_term_impl(addr); } @@ -43,7 +41,7 @@ impl CopyTermState { scan: 0, old_h: target.threshold(), target, - attr_var_policy + attr_var_policy, } } @@ -59,14 +57,11 @@ impl CopyTermState { HeapCellValue::Addr(Addr::Lis(threshold)), ); - self.trail.push(( - Ref::HeapCell(addr), - trail_item, - )); + self.trail.push((Ref::HeapCell(addr), trail_item)); } fn copy_list(&mut self, addr: usize) { - for offset in 0 .. 2 { + for offset in 0..2 { if let Addr::Lis(h) = self.target[addr + offset].as_addr(addr + offset) { if h >= self.old_h { *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h)); @@ -81,12 +76,14 @@ impl CopyTermState { *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold)); - for i in 0 .. 2 { + for i in 0..2 { let hcv = self.target[addr + i].context_free_clone(); self.target.push(hcv); } - let cdr = self.target.store(self.target.deref(Addr::HeapCell(addr + 1))); + let cdr = self + .target + .store(self.target.deref(Addr::HeapCell(addr + 1))); if !cdr.is_ref() { self.trail_list_cell(addr + 1, threshold); @@ -113,34 +110,27 @@ impl CopyTermState { let threshold = self.target.threshold(); - *self.value_at_scan() = - HeapCellValue::Addr(Addr::PStrLocation(threshold, n)); + *self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(threshold, n)); self.scan += 1; - let (pstr, has_tail) = - match &self.target[addr] { - &HeapCellValue::PartialString(ref pstr, has_tail) => { - (pstr.clone_from_offset(0), has_tail) - } - _ => { - unreachable!() - } - }; + let (pstr, has_tail) = match &self.target[addr] { + &HeapCellValue::PartialString(ref pstr, has_tail) => { + (pstr.clone_from_offset(0), has_tail) + } + _ => { + unreachable!() + } + }; - self.target.push(HeapCellValue::PartialString(pstr, has_tail)); + self.target + .push(HeapCellValue::PartialString(pstr, has_tail)); let replacement = HeapCellValue::Addr(Addr::PStrLocation(threshold, n)); - let trail_item = mem::replace( - &mut self.target[addr], - replacement, - ); + let trail_item = mem::replace(&mut self.target[addr], replacement); - self.trail.push(( - Ref::HeapCell(addr), - trail_item, - )); + self.trail.push((Ref::HeapCell(addr), trail_item)); if has_tail { let tail_addr = self.target[addr + 1].as_addr(addr + 1); @@ -154,10 +144,8 @@ impl CopyTermState { self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier)); self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier)); - self.trail.push(( - Ref::HeapCell(h), - HeapCellValue::Addr(Addr::HeapCell(h)), - )); + self.trail + .push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h)))); } Addr::StackCell(fr, sc) => { self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier)); @@ -178,13 +166,12 @@ impl CopyTermState { self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold)); self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold)); - self.trail.push(( - Ref::AttrVar(h), - HeapCellValue::Addr(Addr::AttrVar(h)), - )); + self.trail + .push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h)))); if let AttrVarPolicy::DeepCopy = self.attr_var_policy { - self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold))); + self.target + .push(HeapCellValue::Addr(Addr::AttrVar(threshold))); let list_val = self.target[h + 1].context_free_clone(); self.target.push(list_val); @@ -226,12 +213,10 @@ impl CopyTermState { HeapCellValue::Addr(Addr::Str(threshold)), ); - self.trail.push(( - Ref::HeapCell(addr), - trail_item, - )); + self.trail.push((Ref::HeapCell(addr), trail_item)); - self.target.push(HeapCellValue::NamedStr(arity, name, fixity)); + self.target + .push(HeapCellValue::NamedStr(arity, name, fixity)); for i in 0..arity { let hcv = self.target[addr + 1 + i].context_free_clone(); @@ -255,43 +240,41 @@ impl CopyTermState { while self.scan < self.target.threshold() { match self.value_at_scan() { - &mut HeapCellValue::Addr(addr) => { - match addr { - Addr::Con(h) => { - let addr = self.target[h].as_addr(h); + &mut HeapCellValue::Addr(addr) => match addr { + Addr::Con(h) => { + let addr = self.target[h].as_addr(h); - if addr == Addr::Con(h) { - *self.value_at_scan() = self.target[h].context_free_clone(); - } else { - *self.value_at_scan() = HeapCellValue::Addr(addr); - } - } - Addr::Lis(h) => { - if h >= self.old_h { - self.scan += 1; - } else { - self.copy_list(h); - } - } - addr @ Addr::AttrVar(_) | - addr @ Addr::HeapCell(_) | - addr @ Addr::StackCell(..) => { - self.copy_var(addr); - } - Addr::Str(addr) => { - self.copy_structure(addr); - } - Addr::PStrLocation(addr, n) => { - self.copy_partial_string(addr, n); - } - Addr::Stream(h) => { + if addr == Addr::Con(h) { *self.value_at_scan() = self.target[h].context_free_clone(); - } - _ => { - self.scan += 1; + } else { + *self.value_at_scan() = HeapCellValue::Addr(addr); } } - } + Addr::Lis(h) => { + if h >= self.old_h { + self.scan += 1; + } else { + self.copy_list(h); + } + } + addr @ Addr::AttrVar(_) + | addr @ Addr::HeapCell(_) + | addr @ Addr::StackCell(..) => { + self.copy_var(addr); + } + Addr::Str(addr) => { + self.copy_structure(addr); + } + Addr::PStrLocation(addr, n) => { + self.copy_partial_string(addr, n); + } + Addr::Stream(h) => { + *self.value_at_scan() = self.target[h].context_free_clone(); + } + _ => { + self.scan += 1; + } + }, _ => { self.scan += 1; } @@ -304,10 +287,10 @@ impl CopyTermState { fn unwind_trail(&mut self) { for (r, value) in self.trail.drain(0..) { match r { - Ref::AttrVar(h) | Ref::HeapCell(h) => - self.target[h] = value, - Ref::StackCell(fr, sc) => - self.target.stack().index_and_frame_mut(fr)[sc] = value.as_addr(0), + Ref::AttrVar(h) | Ref::HeapCell(h) => self.target[h] = value, + Ref::StackCell(fr, sc) => { + self.target.stack().index_and_frame_mut(fr)[sc] = value.as_addr(0) + } } } } diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 935bad8b..067bfa93 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -429,7 +429,7 @@ impl HeapTemplate { } #[inline] - pub fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> { + pub(crate) 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]) diff --git a/src/machine/loader.rs b/src/machine/loader.rs index a98c8fc0..c5c5e2e8 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -184,18 +184,16 @@ impl<'a> Drop for LoadState<'a> { module_decl, listing_src, local_extensible_predicates, - ) => { - match self.wam.indices.modules.get_mut(&module_decl.name) { - Some(ref mut module) => { - module.module_decl = module_decl; - module.listing_src = listing_src; - module.local_extensible_predicates = local_extensible_predicates; - } - _ => { - unreachable!() - } + ) => match self.wam.indices.modules.get_mut(&module_decl.name) { + Some(ref mut module) => { + module.module_decl = module_decl; + module.listing_src = listing_src; + module.local_extensible_predicates = local_extensible_predicates; } - } + _ => { + unreachable!() + } + }, RetractionRecord::AddedDiscontiguousPredicate(compilation_target, key) => { match compilation_target { CompilationTarget::User => { @@ -487,17 +485,15 @@ impl<'a> Drop for LoadState<'a> { } } RetractionRecord::SkeletonLocalClauseClausePopFront( - src_compilation_target, local_compilation_target, key, + src_compilation_target, + local_compilation_target, + key, ) => { - match self - .wam - .indices - .get_local_predicate_skeleton_mut( - &src_compilation_target, - local_compilation_target, - key, - ) - { + match self.wam.indices.get_local_predicate_skeleton_mut( + &src_compilation_target, + local_compilation_target, + key, + ) { Some(skeleton) => { skeleton.clause_clause_locs.pop_front(); } @@ -505,17 +501,15 @@ impl<'a> Drop for LoadState<'a> { } } RetractionRecord::SkeletonLocalClauseClausePopBack( - src_compilation_target, local_compilation_target, key, + src_compilation_target, + local_compilation_target, + key, ) => { - match self - .wam - .indices - .get_local_predicate_skeleton_mut( - &src_compilation_target, - local_compilation_target, - key, - ) - { + match self.wam.indices.get_local_predicate_skeleton_mut( + &src_compilation_target, + local_compilation_target, + key, + ) { Some(skeleton) => { skeleton.clause_clause_locs.pop_back(); } @@ -528,15 +522,11 @@ impl<'a> Drop for LoadState<'a> { key, len, ) => { - match self - .wam - .indices - .get_local_predicate_skeleton_mut( - &src_compilation_target, - local_compilation_target, - key, - ) - { + match self.wam.indices.get_local_predicate_skeleton_mut( + &src_compilation_target, + local_compilation_target, + key, + ) { Some(skeleton) => { skeleton.clause_clause_locs.truncate_back(len); } @@ -603,15 +593,11 @@ impl<'a> Drop for LoadState<'a> { key, clause_locs, ) => { - match self - .wam - .indices - .get_local_predicate_skeleton_mut( - &compilation_target, - local_compilation_target, - key, - ) - { + match self.wam.indices.get_local_predicate_skeleton_mut( + &compilation_target, + local_compilation_target, + key, + ) { Some(skeleton) => skeleton.clause_clause_locs = clause_locs, None => {} } @@ -663,7 +649,7 @@ impl<'a> Drop for LoadState<'a> { } #[derive(Debug, Clone, Hash, PartialEq, Eq)] -pub enum CompilationTarget { +pub(crate) enum CompilationTarget { Module(ClauseName), User, } @@ -682,7 +668,7 @@ impl CompilationTarget { } #[inline] - pub fn module_name(&self) -> ClauseName { + pub(crate) fn module_name(&self) -> ClauseName { match self { CompilationTarget::User => { clause_name!("user") @@ -692,7 +678,7 @@ impl CompilationTarget { } } -pub struct PredicateQueue { +pub(crate) struct PredicateQueue { pub(super) predicates: Vec, pub(super) compilation_target: CompilationTarget, } @@ -781,10 +767,9 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } let term = match term { - Term::Clause(_, name, terms, _) - if name.as_str() == ":-" && terms.len() == 1 => { - return Ok(Some(setup_declaration(&self.load_state, terms)?)); - }, + Term::Clause(_, name, terms, _) if name.as_str() == ":-" && terms.len() == 1 => { + return Ok(Some(setup_declaration(&self.load_state, terms)?)); + } term => term, }; @@ -808,8 +793,7 @@ impl<'a, TS: TermStream> Loader<'a, TS> { self.load_state.compilation_target = CompilationTarget::Module(module_decl.name.clone()); - self.predicates.compilation_target = - self.load_state.compilation_target.clone(); + self.predicates.compilation_target = self.load_state.compilation_target.clone(); self.load_state .add_module(module_decl, self.term_stream.listing_src().clone()); @@ -975,9 +959,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { if !*flag_accessor(skeleton) { *flag_accessor(skeleton) = true; - self.load_state.retraction_info.push_record( - retraction_fn(compilation_target.clone(), key.clone()), - ); + self.load_state.retraction_info.push_record(retraction_fn( + compilation_target.clone(), + key.clone(), + )); } } None => { @@ -1003,9 +988,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { if !*flag_accessor(skeleton) { *flag_accessor(skeleton) = true; - self.load_state.retraction_info.push_record( - retraction_fn(compilation_target.clone(), key.clone()), - ); + self.load_state.retraction_info.push_record(retraction_fn( + compilation_target.clone(), + key.clone(), + )); } } None => { @@ -1024,7 +1010,8 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } }, None => { - self.load_state.add_dynamically_generated_module(module_name); + self.load_state + .add_dynamically_generated_module(module_name); let mut skeleton = PredicateSkeleton::new(); *flag_accessor(&mut skeleton) = true; @@ -1068,28 +1055,29 @@ impl<'a, TS: TermStream> Loader<'a, TS> { } CompilationTarget::Module(ref module_name) => { match self.load_state.wam.indices.modules.get_mut(module_name) { - Some(ref mut module) => - match module.local_extensible_predicates.get_mut( - &(compilation_target.clone(), key.clone()), - ) { - Some(ref mut skeleton) => { - if !*flag_accessor(skeleton) { - *flag_accessor(skeleton) = true; - } + Some(ref mut module) => match module + .local_extensible_predicates + .get_mut(&(compilation_target.clone(), key.clone())) + { + Some(ref mut skeleton) => { + if !*flag_accessor(skeleton) { + *flag_accessor(skeleton) = true; } - None => { - let mut skeleton = PredicateSkeleton::new(); - *flag_accessor(&mut skeleton) = true; + } + None => { + let mut skeleton = PredicateSkeleton::new(); + *flag_accessor(&mut skeleton) = true; - self.load_state.add_local_extensible_predicate( - compilation_target.clone(), - key.clone(), - skeleton, - ); - } - }, + self.load_state.add_local_extensible_predicate( + compilation_target.clone(), + key.clone(), + skeleton, + ); + } + }, None => { - self.load_state.add_dynamically_generated_module(module_name); + self.load_state + .add_dynamically_generated_module(module_name); let mut skeleton = PredicateSkeleton::new(); *flag_accessor(&mut skeleton) = true; @@ -1106,7 +1094,10 @@ impl<'a, TS: TermStream> Loader<'a, TS> { Ok(()) } else { - Err(SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key)) + Err(SessionError::PredicateNotMultifileOrDiscontiguous( + compilation_target, + key, + )) } } @@ -1139,10 +1130,9 @@ impl<'a, TS: TermStream> Loader<'a, TS> { RetractionRecord::AddedDynamicPredicate, )?; - let code_index = self.load_state.get_or_insert_code_index( - (name.clone(), arity), - compilation_target.clone(), - ); + let code_index = self + .load_state + .get_or_insert_code_index((name.clone(), arity), compilation_target.clone()); if let IndexPtr::Undefined = code_index.get() { set_code_index( @@ -1204,12 +1194,11 @@ impl<'a, TS: TermStream> Loader<'a, TS> { &self.load_state.compilation_target, self.predicates.compilation_target.clone(), key.clone(), - ) - { - Some(skeleton) if !skeleton.clause_clause_locs.is_empty() => - mem::replace(&mut skeleton.clause_clause_locs, sdeq![]), - _ => - return, + ) { + Some(skeleton) if !skeleton.clause_clause_locs.is_empty() => { + mem::replace(&mut skeleton.clause_clause_locs, sdeq![]) + } + _ => return, }; self.load_state.retraction_info.push_record( @@ -1233,10 +1222,8 @@ impl<'a, TS: TermStream> Loader<'a, TS> { module_name => module_name.clone(), }; - self.load_state.retract_local_clause_clauses( - clause_clause_compilation_target, - &clause_locs, - ); + self.load_state + .retract_local_clause_clauses(clause_clause_compilation_target, &clause_locs); } } } @@ -1305,7 +1292,9 @@ impl Machine { if export_list.is_empty() { loader.load_state.import_module(library)?; } else { - loader.load_state.import_qualified_module(library, export_list)?; + loader + .load_state + .import_qualified_module(library, export_list)?; } LiveTermStream::evacuate(loader) @@ -1347,29 +1336,39 @@ impl Machine { #[inline] pub(crate) fn add_discontiguous_predicate(&mut self) { - self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| { - loader.add_discontiguous_predicate(compilation_target, clause_name, arity) - }); + self.add_extensible_predicate_declaration( + |loader, compilation_target, clause_name, arity| { + loader.add_discontiguous_predicate(compilation_target, clause_name, arity) + }, + ); } #[inline] pub(crate) fn add_dynamic_predicate(&mut self) { - self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| { - loader.add_dynamic_predicate(compilation_target, clause_name, arity) - }); + self.add_extensible_predicate_declaration( + |loader, compilation_target, clause_name, arity| { + loader.add_dynamic_predicate(compilation_target, clause_name, arity) + }, + ); } #[inline] pub(crate) fn add_multifile_predicate(&mut self) { - self.add_extensible_predicate_declaration(|loader, compilation_target, clause_name, arity| { - loader.add_multifile_predicate(compilation_target, clause_name, arity) - }); + self.add_extensible_predicate_declaration( + |loader, compilation_target, clause_name, arity| { + loader.add_multifile_predicate(compilation_target, clause_name, arity) + }, + ); } fn add_extensible_predicate_declaration( &mut self, - decl_adder: impl Fn(&mut Loader, CompilationTarget, ClauseName, usize) - -> Result<(), SessionError>, + decl_adder: impl Fn( + &mut Loader, + CompilationTarget, + ClauseName, + usize, + ) -> Result<(), SessionError>, ) { let module_name = atom_from!( self.machine_st, @@ -1805,15 +1804,10 @@ impl Machine { let mut loader = Loader::new(LiveTermStream::new(ListingSource::User), self); loader.load_state.compilation_target = compilation_target; - let clause_clause_compilation_target = - match &loader.load_state.compilation_target { - CompilationTarget::User => { - CompilationTarget::Module(clause_name!("builtins")) - } - module => { - module.clone() - } - }; + let clause_clause_compilation_target = match &loader.load_state.compilation_target { + CompilationTarget::User => CompilationTarget::Module(clause_name!("builtins")), + module => module.clone(), + }; let mut clause_clause_target_poses: Vec<_> = loader .load_state @@ -1830,12 +1824,13 @@ impl Machine { &(clause_name!("$clause"), 2), ) .map(|clause_clause_skeleton| { - skeleton.clause_clause_locs + skeleton + .clause_clause_locs .iter() .map(|clause_clause_loc| { - clause_clause_skeleton.target_pos_of_clause_clause_loc( - *clause_clause_loc, - ).unwrap() + clause_clause_skeleton + .target_pos_of_clause_clause_loc(*clause_clause_loc) + .unwrap() }) .collect() }) @@ -1850,17 +1845,18 @@ impl Machine { .get_predicate_skeleton_mut(&loader.load_state.compilation_target, &key) .map(|skeleton| skeleton.reset()); - let code_index = loader.load_state.get_or_insert_code_index( - key, - loader.load_state.compilation_target.clone(), - ); + let code_index = loader + .load_state + .get_or_insert_code_index(key, loader.load_state.compilation_target.clone()); code_index.set(IndexPtr::DynamicUndefined); loader.load_state.compilation_target = clause_clause_compilation_target; while let Some(target_pos) = clause_clause_target_poses.pop() { - loader.load_state.retract_clause((clause_name!("$clause"), 2), target_pos); + loader + .load_state + .retract_clause((clause_name!("$clause"), 2), target_pos); } LiveTermStream::evacuate(loader) @@ -1918,11 +1914,9 @@ impl Machine { &clause_clause_compilation_target, &(clause_name!("$clause"), 2), ) { - Some(skeleton) => { - skeleton.target_pos_of_clause_clause_loc( - clause_clause_loc, - ).unwrap() - } + Some(skeleton) => skeleton + .target_pos_of_clause_clause_loc(clause_clause_loc) + .unwrap(), None => { unreachable!(); } @@ -1962,10 +1956,9 @@ impl Machine { let (loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(4)); - loader.load_state.wam.machine_st.fail = - (!loader.predicates.is_empty() && - loader.predicates.compilation_target != compilation_target) || - !key.is_consistent(&loader.predicates); + loader.load_state.wam.machine_st.fail = (!loader.predicates.is_empty() + && loader.predicates.compilation_target != compilation_target) + || !key.is_consistent(&loader.predicates); let result = LiveTermStream::evacuate(loader); self.restore_load_state_payload(result, evacuable_h); @@ -2263,5 +2256,6 @@ pub(super) fn load_module( code_dir, op_dir, meta_predicate_dir, - ).unwrap(); + ) + .unwrap(); } diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index c446107f..8175d261 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -2,11 +2,11 @@ use prolog_parser::ast::*; use prolog_parser::{clause_name, temp_v}; use crate::forms::{ModuleSource, Number}; //, PredicateKey}; -use crate::machine::PredicateKey; use crate::machine::heap::*; use crate::machine::loader::CompilationTarget; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; +use crate::machine::PredicateKey; use crate::rug::Integer; use std::rc::Rc; @@ -321,14 +321,12 @@ impl MachineError { // SessionError::InvalidFileName(filename) => { // Self::existence_error(h, ExistenceError::Module(filename)) // } - SessionError::ModuleDoesNotContainExport(..) => { - Self::permission_error( - h, - Permission::Access, - "private_procedure", - functor!("module_does_not_contain_claimed_export"), - ) - } + SessionError::ModuleDoesNotContainExport(..) => Self::permission_error( + h, + Permission::Access, + "private_procedure", + functor!("module_does_not_contain_claimed_export"), + ), SessionError::ModuleCannotImportSelf(module_name) => Self::permission_error( h, Permission::Modify, @@ -417,7 +415,7 @@ impl MachineError { } #[derive(Debug)] -pub enum CompilationError { +pub(crate) enum CompilationError { Arithmetic(ArithmeticError), ParserError(ParserError), // BadPendingByte, @@ -454,14 +452,14 @@ impl From for CompilationError { } impl CompilationError { - pub fn line_and_col_num(&self) -> Option<(usize, usize)> { + pub(crate) 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 { + pub(crate) fn as_functor(&self, _h: usize) -> MachineStub { match self { &CompilationError::Arithmetic(..) => functor!("arithmetic_error"), // &CompilationError::BadPendingByte => @@ -494,7 +492,7 @@ impl CompilationError { } #[derive(Debug, Clone, Copy)] -pub enum Permission { +pub(crate) enum Permission { Access, Create, InputStream, @@ -506,7 +504,7 @@ pub enum Permission { impl Permission { #[inline] - pub fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { Permission::Access => "access", Permission::Create => "create", @@ -521,7 +519,7 @@ impl Permission { // from 7.12.2 b) of 13211-1:1995 #[derive(Debug, Clone, Copy)] -pub enum ValidType { +pub(crate) enum ValidType { Atom, Atomic, // Boolean, @@ -543,7 +541,7 @@ pub enum ValidType { } impl ValidType { - pub fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { ValidType::Atom => "atom", ValidType::Atomic => "atomic", @@ -568,7 +566,7 @@ impl ValidType { } #[derive(Debug, Clone, Copy)] -pub enum DomainErrorType { +pub(crate) enum DomainErrorType { IOMode, NotLessThanZero, Order, @@ -578,7 +576,7 @@ pub enum DomainErrorType { } impl DomainErrorType { - pub fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { DomainErrorType::IOMode => "io_mode", DomainErrorType::NotLessThanZero => "not_less_than_zero", @@ -592,7 +590,7 @@ impl DomainErrorType { // from 7.12.2 f) of 13211-1:1995 #[derive(Debug, Clone, Copy)] -pub enum RepFlag { +pub(crate) enum RepFlag { Character, CharacterCode, InCharacterCode, @@ -602,7 +600,7 @@ pub enum RepFlag { } impl RepFlag { - pub fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { RepFlag::Character => "character", RepFlag::CharacterCode => "character_code", @@ -616,7 +614,7 @@ impl RepFlag { // from 7.12.2 g) of 13211-1:1995 #[derive(Debug, Clone, Copy)] -pub enum EvalError { +pub(crate) enum EvalError { FloatOverflow, Undefined, // Underflow, @@ -624,7 +622,7 @@ pub enum EvalError { } impl EvalError { - pub fn as_str(self) -> &'static str { + pub(crate) fn as_str(self) -> &'static str { match self { EvalError::FloatOverflow => "float_overflow", EvalError::Undefined => "undefined", @@ -806,7 +804,7 @@ impl MachineState { } #[derive(Debug)] -pub enum ExistenceError { +pub(crate) enum ExistenceError { Module(ClauseName), ModuleSource(ModuleSource), Procedure(ClauseName, usize), @@ -815,7 +813,7 @@ pub enum ExistenceError { } #[derive(Debug)] -pub enum SessionError { +pub(crate) enum SessionError { CompilationError(CompilationError), // CannotOverwriteBuiltIn(ClauseName), // CannotOverwriteImport(ClauseName), @@ -830,7 +828,7 @@ pub enum SessionError { } #[derive(Debug)] -pub enum EvalSession { +pub(crate) enum EvalSession { // EntrySuccess, Error(SessionError), } diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 17bfa4a6..ab2f332d 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -29,12 +29,12 @@ use std::ops::{Add, AddAssign, Deref, Sub, SubAssign}; use std::rc::Rc; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct OrderedOpDirKey(pub ClauseName, pub Fixity); +pub(crate) struct OrderedOpDirKey(pub(crate) ClauseName, pub(crate) Fixity); -pub type OssifiedOpDir = BTreeMap; +pub(crate) type OssifiedOpDir = BTreeMap; #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum DBRef { +pub(crate) enum DBRef { NamedPred(ClauseName, usize, Option), Op( usize, @@ -47,7 +47,7 @@ pub enum DBRef { // 7.2 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum TermOrderCategory { +pub(crate) enum TermOrderCategory { Variable, FloatingPoint, Integer, @@ -56,7 +56,7 @@ pub enum TermOrderCategory { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum Addr { +pub(crate) enum Addr { AttrVar(usize), Char(char), Con(usize), @@ -76,14 +76,14 @@ pub enum Addr { } #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd)] -pub enum Ref { +pub(crate) enum Ref { AttrVar(usize), HeapCell(usize), StackCell(usize, usize), } impl Ref { - pub fn as_addr(self) -> Addr { + pub(crate) fn as_addr(self) -> Addr { match self { Ref::AttrVar(h) => Addr::AttrVar(h), Ref::HeapCell(h) => Addr::HeapCell(h), @@ -141,7 +141,7 @@ impl PartialOrd for Addr { impl Addr { #[inline] - pub fn is_heap_bound(&self) -> bool { + pub(crate) fn is_heap_bound(&self) -> bool { match self { Addr::Char(_) | Addr::EmptyList @@ -154,7 +154,7 @@ impl Addr { } #[inline] - pub fn is_ref(&self) -> bool { + pub(crate) fn is_ref(&self) -> bool { match self { Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => true, _ => false, @@ -162,7 +162,7 @@ impl Addr { } #[inline] - pub fn as_var(&self) -> Option { + pub(crate) fn as_var(&self) -> Option { match self { &Addr::AttrVar(h) => Some(Ref::AttrVar(h)), &Addr::HeapCell(h) => Some(Ref::HeapCell(h)), @@ -202,7 +202,7 @@ impl Addr { } } - pub fn as_constant_index(&self, machine_st: &MachineState) -> Option { + pub(crate) fn as_constant_index(&self, machine_st: &MachineState) -> Option { match self { &Addr::Char(c) => Some(Constant::Char(c)), &Addr::Con(h) => match &machine_st.heap[h] { @@ -222,7 +222,7 @@ impl Addr { } } - pub fn is_protected(&self, e: usize) -> bool { + pub(crate) fn is_protected(&self, e: usize) -> bool { match self { &Addr::StackCell(addr, _) if addr >= e => false, _ => true, @@ -292,7 +292,7 @@ impl SubAssign for Addr { } #[derive(Debug, Clone, Copy)] -pub enum TrailRef { +pub(crate) enum TrailRef { Ref(Ref), AttrVarHeapLink(usize), AttrVarListLink(usize, usize), @@ -307,7 +307,7 @@ impl From for TrailRef { } #[derive(Debug)] -pub enum HeapCellValue { +pub(crate) enum HeapCellValue { Addr(Addr), Atom(ClauseName, Option), DBRef(DBRef), @@ -322,13 +322,13 @@ pub enum HeapCellValue { impl HeapCellValue { #[inline] - pub fn as_addr(&self, focus: usize) -> Addr { + pub(crate) fn as_addr(&self, focus: usize) -> Addr { match self { HeapCellValue::Addr(ref a) => *a, - HeapCellValue::Atom(..) | - HeapCellValue::DBRef(..) | - HeapCellValue::Integer(..) | - HeapCellValue::Rational(..) => Addr::Con(focus), + HeapCellValue::Atom(..) + | HeapCellValue::DBRef(..) + | HeapCellValue::Integer(..) + | HeapCellValue::Rational(..) => Addr::Con(focus), HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(focus), HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus), HeapCellValue::PartialString(..) => Addr::PStrLocation(focus, 0), @@ -338,7 +338,7 @@ impl HeapCellValue { } #[inline] - pub fn context_free_clone(&self) -> HeapCellValue { + pub(crate) fn context_free_clone(&self) -> HeapCellValue { match self { &HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr), &HeapCellValue::Atom(ref name, ref op) => HeapCellValue::Atom(name.clone(), op.clone()), @@ -370,7 +370,7 @@ impl From for HeapCellValue { } #[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub enum IndexPtr { +pub(crate) enum IndexPtr { DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined. DynamicIndex(usize), Index(usize), @@ -378,7 +378,7 @@ pub enum IndexPtr { } #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)] -pub struct CodeIndex(pub Rc>); +pub(crate) struct CodeIndex(pub(crate) Rc>); impl Deref for CodeIndex { type Target = Cell; @@ -396,14 +396,14 @@ impl CodeIndex { } #[inline] - pub fn is_undefined(&self) -> bool { + pub(crate) fn is_undefined(&self) -> bool { match self.0.get() { IndexPtr::Undefined => true, // | &IndexPtr::DynamicUndefined => true, _ => false, } } - pub fn local(&self) -> Option { + pub(crate) fn local(&self) -> Option { match self.0.get() { IndexPtr::Index(i) => Some(i), IndexPtr::DynamicIndex(i) => Some(i), @@ -419,7 +419,7 @@ impl Default for CodeIndex { } #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] -pub enum REPLCodePtr { +pub(crate) enum REPLCodePtr { AddDiscontiguousPredicate, AddDynamicPredicate, AddMultifilePredicate, @@ -456,7 +456,7 @@ pub enum REPLCodePtr { } #[derive(Debug, Clone, PartialEq)] -pub enum CodePtr { +pub(crate) enum CodePtr { BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call. CallN(usize, LocalCodePtr, bool), // arity, local, last call. Local(LocalCodePtr), @@ -466,7 +466,7 @@ pub enum CodePtr { } impl CodePtr { - pub fn local(&self) -> LocalCodePtr { + pub(crate) fn local(&self) -> LocalCodePtr { match self { &CodePtr::BuiltInClause(_, ref local) | &CodePtr::CallN(_, ref local, _) @@ -477,7 +477,7 @@ impl CodePtr { } #[inline] - pub fn is_halt(&self) -> bool { + pub(crate) fn is_halt(&self) -> bool { if let CodePtr::Local(LocalCodePtr::Halt) = self { true } else { @@ -487,7 +487,7 @@ impl CodePtr { } #[derive(Copy, Clone, Debug, PartialEq)] -pub enum LocalCodePtr { +pub(crate) enum LocalCodePtr { DirEntry(usize), // offset Halt, IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset @@ -659,22 +659,23 @@ impl SubAssign for CodePtr { } } -pub type HeapVarDict = IndexMap, Addr>; -pub type AllocVarDict = IndexMap, VarData>; +pub(crate) type HeapVarDict = IndexMap, Addr>; +pub(crate) type AllocVarDict = IndexMap, VarData>; -pub type GlobalVarDir = IndexMap)>; +pub(crate) type GlobalVarDir = IndexMap)>; pub(crate) type StreamAliasDir = IndexMap; pub(crate) type StreamDir = BTreeSet; -pub type MetaPredicateDir = IndexMap>; +pub(crate) type MetaPredicateDir = IndexMap>; -pub type ExtensiblePredicates = IndexMap; +pub(crate) type ExtensiblePredicates = IndexMap; -pub type LocalExtensiblePredicates = IndexMap<(CompilationTarget, PredicateKey), PredicateSkeleton>; +pub(crate) type LocalExtensiblePredicates = + IndexMap<(CompilationTarget, PredicateKey), PredicateSkeleton>; #[derive(Debug)] -pub struct IndexStore { +pub(crate) struct IndexStore { pub(super) code_dir: CodeDir, pub(super) extensible_predicates: ExtensiblePredicates, pub(super) local_extensible_predicates: LocalExtensiblePredicates, @@ -694,7 +695,7 @@ impl Default for IndexStore { } impl IndexStore { - pub fn get_predicate_skeleton_mut( + pub(crate) fn get_predicate_skeleton_mut( &mut self, compilation_target: &CompilationTarget, key: &PredicateKey, @@ -714,29 +715,25 @@ impl IndexStore { } } - pub fn get_local_predicate_skeleton_mut( + pub(crate) fn get_local_predicate_skeleton_mut( &mut self, src_compilation_target: &CompilationTarget, local_compilation_target: CompilationTarget, key: PredicateKey, ) -> Option<&mut PredicateSkeleton> { match (key.0.as_str(), key.1) { - ("term_expansion", 2) => { - self.local_extensible_predicates.get_mut( - &(local_compilation_target, key), - ) - } + ("term_expansion", 2) => self + .local_extensible_predicates + .get_mut(&(local_compilation_target, key)), _ => match src_compilation_target { - CompilationTarget::User => { - self.local_extensible_predicates.get_mut( - &(local_compilation_target, key), - ) - } + CompilationTarget::User => self + .local_extensible_predicates + .get_mut(&(local_compilation_target, key)), CompilationTarget::Module(ref module_name) => { if let Some(module) = self.modules.get_mut(module_name) { - module.local_extensible_predicates.get_mut( - &(local_compilation_target, key), - ) + module + .local_extensible_predicates + .get_mut(&(local_compilation_target, key)) } else { None } @@ -745,29 +742,25 @@ impl IndexStore { } } - pub fn get_local_predicate_skeleton( + pub(crate) fn get_local_predicate_skeleton( &self, src_compilation_target: &CompilationTarget, local_compilation_target: CompilationTarget, key: PredicateKey, ) -> Option<&PredicateSkeleton> { match (key.0.as_str(), key.1) { - ("term_expansion", 2) => { - self.local_extensible_predicates.get( - &(local_compilation_target, key), - ) - } + ("term_expansion", 2) => self + .local_extensible_predicates + .get(&(local_compilation_target, key)), _ => match src_compilation_target { - CompilationTarget::User => { - self.local_extensible_predicates.get( - &(local_compilation_target, key), - ) - } + CompilationTarget::User => self + .local_extensible_predicates + .get(&(local_compilation_target, key)), CompilationTarget::Module(ref module_name) => { if let Some(module) = self.modules.get(module_name) { - module.local_extensible_predicates.get( - &(local_compilation_target, key), - ) + module + .local_extensible_predicates + .get(&(local_compilation_target, key)) } else { None } @@ -776,7 +769,7 @@ impl IndexStore { } } - pub fn get_predicate_skeleton( + pub(crate) fn get_predicate_skeleton( &self, compilation_target: &CompilationTarget, key: &PredicateKey, @@ -796,19 +789,15 @@ impl IndexStore { } } - pub fn remove_predicate_skeleton( + pub(crate) fn remove_predicate_skeleton( &mut self, compilation_target: &CompilationTarget, key: &PredicateKey, ) -> Option { match (key.0.as_str(), key.1) { - ("term_expansion", 2) => { - self.extensible_predicates.remove(key) - } + ("term_expansion", 2) => self.extensible_predicates.remove(key), _ => match compilation_target { - CompilationTarget::User => { - self.extensible_predicates.remove(key) - } + 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) @@ -820,7 +809,7 @@ impl IndexStore { } } - pub fn get_predicate_code_index( + pub(crate) fn get_predicate_code_index( &self, name: ClauseName, arity: usize, @@ -848,7 +837,7 @@ impl IndexStore { } } - pub fn get_meta_predicate_spec( + pub(crate) fn get_meta_predicate_spec( &self, name: ClauseName, arity: usize, @@ -866,7 +855,7 @@ impl IndexStore { } } - pub fn is_dynamic_predicate(&self, module_name: ClauseName, key: PredicateKey) -> bool { + pub(crate) fn is_dynamic_predicate(&self, module_name: ClauseName, key: PredicateKey) -> bool { match module_name.as_str() { "user" => self .extensible_predicates @@ -911,9 +900,9 @@ impl IndexStore { } } -pub type CodeDir = BTreeMap; +pub(crate) type CodeDir = BTreeMap; -pub enum RefOrOwned<'a, T: 'a> { +pub(crate) enum RefOrOwned<'a, T: 'a> { Borrowed(&'a T), Owned(T), } @@ -928,14 +917,14 @@ impl<'a, T: 'a + fmt::Debug> fmt::Debug for RefOrOwned<'a, T> { } impl<'a, T> RefOrOwned<'a, T> { - pub fn as_ref(&'a self) -> &'a T { + pub(crate) fn as_ref(&'a self) -> &'a T { match self { &RefOrOwned::Borrowed(r) => r, &RefOrOwned::Owned(ref r) => r, } } - pub fn to_owned(self) -> T + pub(crate) fn to_owned(self) -> T where T: Clone, { diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 87af5a41..b94de736 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -30,7 +30,7 @@ use std::ops::{Index, IndexMut}; use std::rc::Rc; #[derive(Debug)] -pub struct Ball { +pub(crate) struct Ball { pub(super) boundary: usize, pub(super) stub: Heap, } @@ -225,7 +225,7 @@ impl IndexMut for MachineState { } } -pub type Registers = Vec; +pub(crate) type Registers = Vec; #[derive(Debug, Clone, Copy)] pub(super) enum MachineMode { @@ -276,7 +276,7 @@ pub enum FirstOrNext { } // #[derive(Debug)] -pub struct MachineState { +pub(crate) struct MachineState { pub(crate) atom_tbl: TabledData, pub(super) s: HeapPtr, pub(super) p: CodePtr, @@ -347,7 +347,7 @@ impl MachineState { pub(crate) fn read_term(&mut self, mut stream: Stream, indices: &mut IndexStore) -> CallResult { fn push_var_eq_functors<'a>( heap: &mut Heap, - iter: impl Iterator, &'a Addr)>, + iter: impl Iterator, &'a Addr)>, op_dir: &OpDir, atom_tbl: TabledData, ) -> Vec { @@ -1303,7 +1303,8 @@ impl CallPolicy for CWILCallPolicy { offset: usize, global_variables: &mut GlobalVarDir, ) -> CallResult { - self.prev_policy.retry_me_else(machine_st, offset, global_variables)?; + self.prev_policy + .retry_me_else(machine_st, offset, global_variables)?; self.increment(machine_st) } @@ -1313,7 +1314,8 @@ impl CallPolicy for CWILCallPolicy { offset: usize, global_variables: &mut GlobalVarDir, ) -> CallResult { - self.prev_policy.retry(machine_st, offset, global_variables)?; + self.prev_policy + .retry(machine_st, offset, global_variables)?; self.increment(machine_st) } @@ -1332,7 +1334,8 @@ impl CallPolicy for CWILCallPolicy { offset: usize, global_variables: &mut GlobalVarDir, ) -> CallResult { - self.prev_policy.trust(machine_st, offset, global_variables)?; + self.prev_policy + .trust(machine_st, offset, global_variables)?; self.increment(machine_st) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 5ae448f9..efb0e6a9 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -61,7 +61,7 @@ impl MachineState { } #[inline] - pub fn machine_flags(&self) -> MachineFlags { + pub(crate) fn machine_flags(&self) -> MachineFlags { self.flags } @@ -590,8 +590,7 @@ impl MachineState { } } - pub(super) - fn trail(&mut self, r: TrailRef) { + pub(super) fn trail(&mut self, r: TrailRef) { match r { TrailRef::Ref(Ref::HeapCell(h)) => { if h < self.hb { @@ -3460,14 +3459,20 @@ impl MachineState { } &ChoiceInstruction::DefaultRetryMeElse(offset) => { let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.retry_me_else(self, offset, global_variables)) + try_or_fail!( + self, + call_policy.retry_me_else(self, offset, global_variables) + ) } &ChoiceInstruction::DefaultTrustMe(_) => { let mut call_policy = DefaultCallPolicy {}; try_or_fail!(self, call_policy.trust_me(self, global_variables)) } &ChoiceInstruction::RetryMeElse(offset) => { - try_or_fail!(self, call_policy.retry_me_else(self, offset, global_variables)) + try_or_fail!( + self, + call_policy.retry_me_else(self, offset, global_variables) + ) } &ChoiceInstruction::TrustMe(_) => { try_or_fail!(self, call_policy.trust_me(self, global_variables)) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 41940154..51a88762 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -14,17 +14,17 @@ use crate::read::*; mod attributed_variables; pub(super) mod code_repo; -pub mod code_walker; +pub(crate) mod code_walker; #[macro_use] pub(crate) mod loader; mod compile; mod copier; -pub mod heap; +pub(crate) mod heap; mod load_state; -pub mod machine_errors; -pub mod machine_indices; +pub(crate) mod machine_errors; +pub(crate) mod machine_indices; pub(super) mod machine_state; -pub mod partial_string; +pub(crate) mod partial_string; mod preprocessor; mod raw_block; mod stack; @@ -42,7 +42,7 @@ use crate::machine::compile::*; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; use crate::machine::machine_state::*; -use crate::machine::streams::*; +pub use crate::machine::streams::Stream; use indexmap::IndexMap; @@ -54,13 +54,13 @@ use std::path::PathBuf; use std::sync::atomic::AtomicBool; #[derive(Debug)] -pub struct MachinePolicies { +pub(crate) struct MachinePolicies { call_policy: Box, cut_policy: Box, } lazy_static! { - pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false); + pub(crate) static ref INTERRUPT: AtomicBool = AtomicBool::new(false); } impl MachinePolicies { @@ -141,7 +141,7 @@ impl Machine { unreachable!(); } - fn load_file(&mut self, path: String, stream: Stream) { + pub 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))); @@ -224,7 +224,7 @@ impl Machine { self.run_module_predicate(clause_name!("$toplevel"), (clause_name!("$repl"), 1)); } - fn configure_modules(&mut self) { + pub(crate) fn configure_modules(&mut self) { fn update_call_n_indices(loader: &Module, target_code_dir: &mut CodeDir) { for arity in 1..66 { let key = (clause_name!("call"), arity); @@ -358,7 +358,7 @@ impl Machine { wam } - pub fn configure_streams(&mut self) { + pub(crate) fn configure_streams(&mut self) { self.user_input.options_mut().alias = Some(clause_name!("user_input")); self.indices @@ -493,7 +493,7 @@ impl Machine { self.machine_st.p = CodePtr::Local(p); } - pub(super) fn run_query(&mut self) { + pub(crate) fn run_query(&mut self) { while !self.machine_st.p.is_halt() { self.machine_st.query_stepper( &mut self.indices, diff --git a/src/machine/partial_string.rs b/src/machine/partial_string.rs index 7d865d49..bdaacc78 100644 --- a/src/machine/partial_string.rs +++ b/src/machine/partial_string.rs @@ -1,20 +1,20 @@ -use crate::machine::*; use crate::machine::machine_indices::*; +use crate::machine::*; use core::marker::PhantomData; use std::alloc; use std::cmp::Ordering; use std::mem; -use std::ptr; use std::ops::RangeFrom; +use std::ptr; use std::slice; use std::str; use indexmap::IndexSet; #[derive(Debug)] -pub struct PartialString { +pub(crate) struct PartialString { buf: *const u8, len: usize, _marker: PhantomData<[u8]>, @@ -54,7 +54,7 @@ fn scan_for_terminator>(iter: Iter) -> usize { } #[derive(Debug)] -pub struct PStrIter { +pub(crate) struct PStrIter { buf: *const u8, len: usize, } @@ -91,17 +91,14 @@ impl Iterator for PStrIter { impl PartialString { #[inline] - pub(super) - fn new(src: &str) -> Option<(Self, &str)> { + pub(super) fn new(src: &str) -> Option<(Self, &str)> { let pstr = PartialString { buf: ptr::null_mut(), len: 0, _marker: PhantomData, }; - unsafe { - pstr.append_chars(src) - } + unsafe { pstr.append_chars(src) } } unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> { @@ -115,29 +112,23 @@ impl PartialString { self.buf = alloc::alloc(layout) as *const _; self.len = terminator_idx + '\u{0}'.len_utf8(); - ptr::copy( - src.as_ptr(), - self.buf as *mut _, - terminator_idx, - ); + ptr::copy(src.as_ptr(), self.buf as *mut _, terminator_idx); self.write_terminator_at(terminator_idx); Some(if terminator_idx != src.as_bytes().len() { - (self, &src[terminator_idx ..]) + (self, &src[terminator_idx..]) } else { (self, "") }) } - pub(super) - fn clone_from_offset(&self, n: usize) -> Self { - let len = - if self.len - '\u{0}'.len_utf8() > n { - self.len - n - '\u{0}'.len_utf8() - } else { - 0 - }; + pub(super) fn clone_from_offset(&self, n: usize) -> Self { + let len = if self.len - '\u{0}'.len_utf8() > n { + self.len - n - '\u{0}'.len_utf8() + } else { + 0 + }; let mut pstr = PartialString { buf: ptr::null_mut(), @@ -168,18 +159,14 @@ impl PartialString { } #[inline] - pub(super) - fn write_terminator_at(&mut self, index: usize) { + pub(super) fn write_terminator_at(&mut self, index: usize) { unsafe { - ptr::write( - (self.buf as usize + index) as *mut u8, - 0u8, - ); + ptr::write((self.buf as usize + index) as *mut u8, 0u8); } } #[inline] - pub fn range_from(&self, index: RangeFrom) -> PStrIter { + pub(crate) fn range_from(&self, index: RangeFrom) -> PStrIter { if self.len >= '\u{0}'.len_utf8() { PStrIter::from(self.buf, self.len - '\u{0}'.len_utf8(), index.start) } else { @@ -188,21 +175,18 @@ impl PartialString { } #[inline] - pub fn at_end(&self, end_n: usize) -> bool { + pub(crate) fn at_end(&self, end_n: usize) -> bool { end_n + 1 == self.len } #[inline] - pub fn as_str_from(&self, n: usize) -> &str { + pub(crate) fn as_str_from(&self, n: usize) -> &str { unsafe { - let slice = slice::from_raw_parts( - self.buf, - self.len - '\u{0}'.len_utf8(), - ); + let slice = slice::from_raw_parts(self.buf, self.len - '\u{0}'.len_utf8()); let s = str::from_utf8(slice).unwrap(); - &s[n ..] + &s[n..] } } } @@ -216,8 +200,7 @@ pub(crate) struct HeapPStrIter<'a> { impl<'a> HeapPStrIter<'a> { #[inline] - pub(super) - fn new(machine_st: &'a MachineState, focus: Addr) -> Self { + pub(super) fn new(machine_st: &'a MachineState, focus: Addr) -> Self { HeapPStrIter { focus, machine_st, @@ -226,14 +209,12 @@ impl<'a> HeapPStrIter<'a> { } #[inline] - pub(crate) - fn focus(&self) -> Addr { + 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 { + pub(crate) fn to_string(&mut self) -> String { let mut buf = String::new(); while let Some(iteratee) = self.next() { @@ -241,16 +222,14 @@ impl<'a> HeapPStrIter<'a> { 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!() - } + PStrIteratee::PStrSegment(h, n) => match &self.machine_st.heap[h] { + HeapCellValue::PartialString(ref pstr, _) => { + buf += pstr.as_str_from(n); } - } + _ => { + unreachable!() + } + }, } } @@ -291,7 +270,9 @@ impl<'a> Iterator for HeapPStrIter<'a> { } } Addr::Lis(l) => { - let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(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) => { @@ -305,12 +286,8 @@ impl<'a> Iterator for HeapPStrIter<'a> { unreachable!() } } - Addr::Char(c) => { - Some(c) - } - _ => { - None - } + Addr::Char(c) => Some(c), + _ => None, }; if let Some(c) = opt_c { @@ -332,8 +309,7 @@ impl<'a> Iterator for HeapPStrIter<'a> { } #[inline] -pub(super) -fn compare_pstr_prefixes<'a>( +pub(super) fn compare_pstr_prefixes<'a>( i1: &mut HeapPStrIter<'a>, i2: &mut HeapPStrIter<'a>, ) -> Option { @@ -425,25 +401,16 @@ fn compare_pstr_prefixes<'a>( } return match (i1.focus(), i2.focus()) { - (Addr::EmptyList, Addr::EmptyList) => { - Some(Ordering::Equal) - } - (Addr::EmptyList, _) => { - Some(Ordering::Less) - } - (_, Addr::EmptyList) => { - Some(Ordering::Greater) - } - _ => { - None - } + (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>( +pub(super) fn compare_pstr_to_string<'a>( heap_pstr_iter: &mut HeapPStrIter<'a>, s: &String, ) -> Option { @@ -452,7 +419,7 @@ fn compare_pstr_to_string<'a>( while let Some(iteratee) = heap_pstr_iter.next() { match iteratee { PStrIteratee::Char(c1) => { - if let Some(c2) = s[s_offset ..].chars().next() { + if let Some(c2) = s[s_offset..].chars().next() { if c1 != c2 { return None; } else { @@ -462,31 +429,28 @@ fn compare_pstr_to_string<'a>( 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); + 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()); + 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!() + s_offset += s[s_offset..].len(); + return Some(s_offset); + } else { + return None; } } - } + _ => { + unreachable!() + } + }, } - if s[s_offset ..].is_empty() { + if s[s_offset..].is_empty() { return Some(s_offset); } } diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index bbc99c22..62a446f8 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -30,7 +30,7 @@ pub(crate) enum CutContext { HasCutVariable, } -pub fn fold_by_str(terms: I, mut term: Term, sym: ClauseName) -> Term +pub(crate) fn fold_by_str(terms: I, mut term: Term, sym: ClauseName) -> Term where I: DoubleEndedIterator, { @@ -46,7 +46,11 @@ where term } -pub fn to_op_decl(prec: usize, spec: &str, name: ClauseName) -> Result { +pub(crate) fn to_op_decl( + prec: usize, + spec: &str, + name: ClauseName, +) -> Result { match spec { "xfx" => Ok(OpDecl::new(prec, XFX, name)), "xfy" => Ok(OpDecl::new(prec, XFY, name)), @@ -825,11 +829,7 @@ impl Preprocessor { cut_context: CutContext, ) -> Result { let post_head_terms: Vec<_> = terms.drain(1..).collect(); - let mut query_terms = self.setup_query( - load_state, - post_head_terms, - cut_context, - )?; + 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(); @@ -894,11 +894,7 @@ impl Preprocessor { let mut results = VecDeque::new(); for term in terms.into_iter() { - results.push_back(self.try_term_to_tl( - load_state, - term, - cut_context, - )?); + results.push_back(self.try_term_to_tl(load_state, term, cut_context)?); } Ok(results) diff --git a/src/machine/stack.rs b/src/machine/stack.rs index ab7d48e2..8240d2a8 100644 --- a/src/machine/stack.rs +++ b/src/machine/stack.rs @@ -23,9 +23,7 @@ impl RawBlockTraits for StackTraits { #[inline] fn base_offset(base: *const u8) -> *const u8 { - unsafe { - base.offset(Self::align() as isize) - } + unsafe { base.offset(Self::align() as isize) } } } @@ -37,7 +35,7 @@ const fn prelude_size() -> usize { } #[derive(Debug)] -pub struct Stack { +pub(crate) struct Stack { buf: RawBlock, _marker: PhantomData, } @@ -50,25 +48,25 @@ impl Drop for Stack { } #[derive(Debug, Clone, Copy)] -pub struct FramePrelude { - pub num_cells: usize, +pub(crate) struct FramePrelude { + pub(crate) num_cells: usize, } #[derive(Debug)] -pub struct AndFramePrelude { - pub univ_prelude: FramePrelude, - pub e: usize, - pub cp: LocalCodePtr, - pub interrupt_cp: LocalCodePtr, +pub(crate) struct AndFramePrelude { + pub(crate) univ_prelude: FramePrelude, + pub(crate) e: usize, + pub(crate) cp: LocalCodePtr, + pub(crate) interrupt_cp: LocalCodePtr, } #[derive(Debug)] -pub struct AndFrame { - pub prelude: AndFramePrelude, +pub(crate) struct AndFrame { + pub(crate) prelude: AndFramePrelude, } impl AndFrame { - pub fn size_of(num_cells: usize) -> usize { + pub(crate) fn size_of(num_cells: usize) -> usize { prelude_size::() + num_cells * mem::size_of::() } } @@ -104,23 +102,23 @@ impl IndexMut for AndFrame { } #[derive(Debug)] -pub struct OrFramePrelude { - pub univ_prelude: FramePrelude, - pub e: usize, - pub cp: LocalCodePtr, - pub b: usize, - pub bp: LocalCodePtr, - pub tr: usize, - pub pstr_tr: usize, - pub h: usize, - pub b0: usize, - pub attr_var_init_queue_b: usize, - pub attr_var_init_bindings_b: usize, +pub(crate) struct OrFramePrelude { + pub(crate) univ_prelude: FramePrelude, + pub(crate) e: usize, + pub(crate) cp: LocalCodePtr, + pub(crate) b: usize, + pub(crate) bp: LocalCodePtr, + pub(crate) tr: usize, + pub(crate) pstr_tr: usize, + pub(crate) h: usize, + pub(crate) b0: usize, + pub(crate) attr_var_init_queue_b: usize, + pub(crate) attr_var_init_bindings_b: usize, } #[derive(Debug)] -pub struct OrFrame { - pub prelude: OrFramePrelude, +pub(crate) struct OrFrame { + pub(crate) prelude: OrFramePrelude, } impl Index for OrFrame { @@ -156,24 +154,27 @@ impl IndexMut for OrFrame { } impl OrFrame { - pub fn size_of(num_cells: usize) -> usize { + pub(crate) fn size_of(num_cells: usize) -> usize { prelude_size::() + num_cells * mem::size_of::() } } impl Stack { - pub fn new() -> Self { - Stack { buf: RawBlock::new(), _marker: PhantomData } + pub(crate) fn new() -> Self { + Stack { + buf: RawBlock::new(), + _marker: PhantomData, + } } - pub fn allocate_and_frame(&mut self, num_cells: usize) -> usize { + pub(crate) fn allocate_and_frame(&mut self, num_cells: usize) -> usize { let frame_size = AndFrame::size_of(num_cells); unsafe { let new_top = self.buf.new_block(frame_size); let e = self.buf.top as usize - self.buf.base as usize; - for idx in 0 .. num_cells { + for idx in 0..num_cells { let offset = prelude_size::() + idx * mem::size_of::(); ptr::write( (self.buf.top as usize + offset) as *mut Addr, @@ -190,14 +191,14 @@ impl Stack { } } - pub fn allocate_or_frame(&mut self, num_cells: usize) -> usize { + pub(crate) fn allocate_or_frame(&mut self, num_cells: usize) -> usize { let frame_size = OrFrame::size_of(num_cells); unsafe { let new_top = self.buf.new_block(frame_size); let b = self.buf.top as usize - self.buf.base as usize; - for idx in 0 .. num_cells { + for idx in 0..num_cells { let offset = prelude_size::() + idx * mem::size_of::(); ptr::write( (self.buf.top as usize + offset) as *mut Addr, @@ -215,7 +216,7 @@ impl Stack { } #[inline] - pub fn index_and_frame(&self, e: usize) -> &AndFrame { + pub(crate) fn index_and_frame(&self, e: usize) -> &AndFrame { unsafe { let ptr = self.buf.base as usize + e; &*(ptr as *const AndFrame) @@ -223,7 +224,7 @@ impl Stack { } #[inline] - pub fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame { + pub(crate) fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame { unsafe { let ptr = self.buf.base as usize + e; &mut *(ptr as *mut AndFrame) @@ -231,7 +232,7 @@ impl Stack { } #[inline] - pub fn index_or_frame(&self, b: usize) -> &OrFrame { + pub(crate) fn index_or_frame(&self, b: usize) -> &OrFrame { unsafe { let ptr = self.buf.base as usize + b; &*(ptr as *const OrFrame) @@ -239,7 +240,7 @@ impl Stack { } #[inline] - pub fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame { + pub(crate) fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame { unsafe { let ptr = self.buf.base as usize + b; &mut *(ptr as *mut OrFrame) @@ -247,7 +248,7 @@ impl Stack { } #[inline] - pub fn truncate(&mut self, b: usize) { + pub(crate) fn truncate(&mut self, b: usize) { if b == 0 { self.inner_truncate(mem::align_of::()); } else { @@ -264,7 +265,7 @@ impl Stack { } } - pub fn drop_in_place(&mut self) { + pub(crate) fn drop_in_place(&mut self) { self.truncate(mem::align_of::()); debug_assert!(if self.buf.top.is_null() { diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 56bb3836..e1401b0e 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -23,7 +23,7 @@ use std::rc::Rc; use native_tls::TlsStream; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum StreamType { +pub(crate) enum StreamType { Binary, Text, } @@ -55,14 +55,14 @@ impl StreamType { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum EOFAction { +pub(crate) enum EOFAction { EOFCode, Error, Reset, } #[derive(Debug, PartialEq)] -pub enum AtEndOfStream { +pub(crate) enum AtEndOfStream { Not, At, Past, @@ -198,7 +198,7 @@ impl fmt::Debug for StreamInstance { } #[derive(Debug)] -struct InnerStream { +pub(crate) struct InnerStream { options: StreamOptions, stream_inst: StreamInstance, past_end_of_stream: bool, @@ -211,14 +211,12 @@ struct WrappedStreamInstance(Rc>); impl WrappedStreamInstance { #[inline] fn new(stream_inst: StreamInstance, past_end_of_stream: bool) -> Self { - WrappedStreamInstance(Rc::new(RefCell::new( - InnerStream { - options: StreamOptions::default(), - stream_inst, - past_end_of_stream, - lines_read: 0, - } - ))) + WrappedStreamInstance(Rc::new(RefCell::new(InnerStream { + options: StreamOptions::default(), + stream_inst, + past_end_of_stream, + lines_read: 0, + }))) } } @@ -287,11 +285,11 @@ impl fmt::Display for StreamError { impl Error for StreamError {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StreamOptions { - pub stream_type: StreamType, - pub reposition: bool, - pub alias: Option, - pub eof_action: EOFAction, +pub(crate) struct StreamOptions { + pub(crate) stream_type: StreamType, + pub(crate) reposition: bool, + pub(crate) alias: Option, + pub(crate) eof_action: EOFAction, } impl Default for StreamOptions { @@ -366,6 +364,23 @@ impl Stream { ptr as *const u8 } + pub fn bytes(&self) -> Option>> { + // if Ref had an and_then function this could be simplified + let val = std::cell::Ref::map(self.stream_inst.0.borrow(), |inner_stream| { + &inner_stream.stream_inst + }); + match std::ops::Deref::deref(&val) { + StreamInstance::Bytes(_) => Some(std::cell::Ref::map( + std::cell::Ref::clone(&val), + |instance| match instance { + StreamInstance::Bytes(cursor) => cursor.get_ref(), + _ => unreachable!(), + }, + )), + _ => None, + } + } + #[inline] pub(crate) fn lines_read(&mut self) -> usize { self.stream_inst.0.borrow_mut().lines_read @@ -378,30 +393,29 @@ impl Stream { #[inline] pub(crate) fn options(&self) -> std::cell::Ref<'_, StreamOptions> { - std::cell::Ref::map( - self.stream_inst.0.borrow(), - |inner_stream| &inner_stream.options, - ) + std::cell::Ref::map(self.stream_inst.0.borrow(), |inner_stream| { + &inner_stream.options + }) } #[inline] pub(crate) fn options_mut(&mut self) -> std::cell::RefMut<'_, StreamOptions> { - std::cell::RefMut::map( - self.stream_inst.0.borrow_mut(), - |inner_stream| &mut inner_stream.options, - ) + std::cell::RefMut::map(self.stream_inst.0.borrow_mut(), |inner_stream| { + &mut inner_stream.options + }) } #[inline] - pub(crate) fn position(&mut self) -> Option<(u64, usize)> { // returns lines_read, position. + pub(crate) fn position(&mut self) -> Option<(u64, usize)> { + // returns lines_read, position. let result = match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::InputFile(_, ref mut file) => file.seek(SeekFrom::Current(0)).ok(), - StreamInstance::TcpStream(..) | - StreamInstance::TlsStream(..) | - StreamInstance::ReadlineStream(..) | - StreamInstance::StaticStr(..) | - StreamInstance::PausedPrologStream(..) | - StreamInstance::Bytes(..) => Some(0), + StreamInstance::TcpStream(..) + | StreamInstance::TlsStream(..) + | StreamInstance::ReadlineStream(..) + | StreamInstance::StaticStr(..) + | StreamInstance::PausedPrologStream(..) + | StreamInstance::Bytes(..) => Some(0), _ => None, }; @@ -411,9 +425,11 @@ impl Stream { #[inline] pub(crate) fn set_position(&mut self, position: u64) { match self.stream_inst.0.borrow_mut().deref_mut() { - InnerStream { past_end_of_stream, - stream_inst: StreamInstance::InputFile(_, ref mut file), - .. } => { + InnerStream { + past_end_of_stream, + stream_inst: StreamInstance::InputFile(_, ref mut file), + .. + } => { file.seek(SeekFrom::Start(position)).unwrap(); if let Ok(metadata) = file.metadata() { @@ -446,31 +462,31 @@ impl Stream { } match self.stream_inst.0.borrow_mut().deref_mut() { - InnerStream { past_end_of_stream, - stream_inst: StreamInstance::InputFile(_, ref mut file), - .. } => { - match file.metadata() { - Ok(metadata) => { - if let Ok(position) = file.seek(SeekFrom::Current(0)) { - return match position.cmp(&metadata.len()) { - Ordering::Equal => AtEndOfStream::At, - Ordering::Less => AtEndOfStream::Not, - Ordering::Greater => { - *past_end_of_stream = true; - AtEndOfStream::Past - } - }; - } else { - *past_end_of_stream = true; - AtEndOfStream::Past - } - } - _ => { + InnerStream { + past_end_of_stream, + stream_inst: StreamInstance::InputFile(_, ref mut file), + .. + } => match file.metadata() { + Ok(metadata) => { + if let Ok(position) = file.seek(SeekFrom::Current(0)) { + return match position.cmp(&metadata.len()) { + Ordering::Equal => AtEndOfStream::At, + Ordering::Less => AtEndOfStream::Not, + Ordering::Greater => { + *past_end_of_stream = true; + AtEndOfStream::Past + } + }; + } else { *past_end_of_stream = true; AtEndOfStream::Past } } - } + _ => { + *past_end_of_stream = true; + AtEndOfStream::Past + } + }, _ => AtEndOfStream::Not, } } @@ -488,11 +504,11 @@ impl Stream { #[inline] pub(crate) fn mode(&self) -> &'static str { match self.stream_inst.0.borrow().stream_inst { - StreamInstance::Bytes(_) | - StreamInstance::PausedPrologStream(..) | - StreamInstance::ReadlineStream(_) | - StreamInstance::StaticStr(_) | - StreamInstance::InputFile(..) => "read", + StreamInstance::Bytes(_) + | StreamInstance::PausedPrologStream(..) + | StreamInstance::ReadlineStream(_) + | StreamInstance::StaticStr(_) + | StreamInstance::InputFile(..) => "read", StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append", StreamInstance::OutputFile(_, _, true) => "append", StreamInstance::Stdout | StreamInstance::OutputFile(_, _, false) => "write", @@ -508,7 +524,7 @@ impl Stream { } #[inline] - pub(crate) fn stdout() -> Self { + pub fn stdout() -> Self { Stream::from_inst(StreamInstance::Stdout) } @@ -568,13 +584,13 @@ impl Stream { #[inline] pub(crate) fn is_input_stream(&self) -> bool { match self.stream_inst.0.borrow().stream_inst { - StreamInstance::TcpStream(..) | - StreamInstance::TlsStream(..) | - StreamInstance::Bytes(_) | - StreamInstance::PausedPrologStream(..) | - StreamInstance::ReadlineStream(_) | - StreamInstance::StaticStr(_) | - StreamInstance::InputFile(..) => true, + StreamInstance::TcpStream(..) + | StreamInstance::TlsStream(..) + | StreamInstance::Bytes(_) + | StreamInstance::PausedPrologStream(..) + | StreamInstance::ReadlineStream(_) + | StreamInstance::StaticStr(_) + | StreamInstance::InputFile(..) => true, _ => false, } } @@ -582,11 +598,11 @@ impl Stream { #[inline] pub(crate) fn is_output_stream(&self) -> bool { match self.stream_inst.0.borrow().stream_inst { - StreamInstance::Stdout | - StreamInstance::TcpStream(..) | - StreamInstance::TlsStream(..) | - StreamInstance::Bytes(_) | - StreamInstance::OutputFile(..) => true, + StreamInstance::Stdout + | StreamInstance::TcpStream(..) + | StreamInstance::TlsStream(..) + | StreamInstance::Bytes(_) + | StreamInstance::OutputFile(..) => true, _ => false, } } @@ -1084,11 +1100,11 @@ impl Write for Stream { StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf), StreamInstance::Bytes(ref mut cursor) => cursor.write(buf), StreamInstance::Stdout => stdout().write(buf), - StreamInstance::PausedPrologStream(..) | - StreamInstance::StaticStr(_) | - StreamInstance::ReadlineStream(_) | - StreamInstance::InputFile(..) | - StreamInstance::Null => Err(std::io::Error::new( + StreamInstance::PausedPrologStream(..) + | StreamInstance::StaticStr(_) + | StreamInstance::ReadlineStream(_) + | StreamInstance::InputFile(..) + | StreamInstance::Null => Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::WriteToInputStream, )), @@ -1102,11 +1118,11 @@ impl Write for Stream { StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(), StreamInstance::Bytes(ref mut cursor) => cursor.flush(), StreamInstance::Stdout => stdout().flush(), - StreamInstance::PausedPrologStream(..) | - StreamInstance::StaticStr(_) | - StreamInstance::ReadlineStream(_) | - StreamInstance::InputFile(..) | - StreamInstance::Null => Err(std::io::Error::new( + StreamInstance::PausedPrologStream(..) + | StreamInstance::StaticStr(_) + | StreamInstance::ReadlineStream(_) + | StreamInstance::InputFile(..) + | StreamInstance::Null => Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::FlushToInputStream, )), diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index bc6724a5..a37e4efe 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -71,7 +71,7 @@ use base64; use roxmltree; use select; -pub fn get_key() -> KeyEvent { +pub(crate) fn get_key() -> KeyEvent { let key; enable_raw_mode().expect("failed to enable raw mode"); loop { diff --git a/src/machine/term_stream.rs b/src/machine/term_stream.rs index 6a23ff66..e55a5499 100644 --- a/src/machine/term_stream.rs +++ b/src/machine/term_stream.rs @@ -78,7 +78,7 @@ impl<'a> TermStream for BootstrappingTermStream<'a> { } } -pub struct LiveTermStream { +pub(crate) struct LiveTermStream { pub(super) term_queue: VecDeque, pub(super) listing_src: ListingSource, } @@ -93,7 +93,7 @@ impl LiveTermStream { } } -pub struct LoadStatePayload { +pub(crate) struct LoadStatePayload { pub(super) term_stream: LiveTermStream, pub(super) compilation_target: CompilationTarget, pub(super) retraction_info: RetractionInfo, diff --git a/src/read.rs b/src/read.rs index 78de8e30..366962cb 100644 --- a/src/read.rs +++ b/src/read.rs @@ -12,7 +12,7 @@ use std::collections::VecDeque; type SubtermDeque = VecDeque<(usize, usize)>; -pub type PrologStream = ParsingStream; +pub(crate) type PrologStream = ParsingStream; pub mod readline { use crate::machine::streams::Stream; @@ -24,7 +24,7 @@ pub mod readline { const HISTORY_FILE: &'static str = ".scryer_history"; - pub fn set_prompt(value: bool) { + pub(crate) fn set_prompt(value: bool) { unsafe { PROMPT = value; } @@ -49,10 +49,8 @@ pub mod readline { impl ReadlineStream { #[inline] - pub fn new(pending_input: String) -> Self { - let config = Config::builder() - .check_cursor_position(true) - .build(); + pub(crate) fn new(pending_input: String) -> Self { + let config = Config::builder().check_cursor_position(true).build(); let mut rl = Editor::<()>::with_config(config); //Editor::<()>::new(); if let Some(mut path) = dirs_next::home_dir() { @@ -72,7 +70,7 @@ pub mod readline { } #[inline] - pub fn input_stream(pending_input: String) -> Stream { + pub(crate) fn input_stream(pending_input: String) -> Stream { Stream::from(Self::new(pending_input)) } @@ -116,7 +114,7 @@ pub mod readline { } } - pub fn peek_byte(&mut self) -> std::io::Result { + pub(crate) fn peek_byte(&mut self) -> std::io::Result { set_prompt(false); loop { @@ -137,7 +135,7 @@ pub mod readline { } } - pub fn peek_char(&mut self) -> std::io::Result { + pub(crate) fn peek_char(&mut self) -> std::io::Result { set_prompt(false); loop { @@ -176,7 +174,7 @@ pub mod readline { } impl MachineState { - pub fn devour_whitespace( + pub(crate) fn devour_whitespace( &mut self, mut inner: Stream, atom_tbl: TabledData, @@ -196,7 +194,7 @@ impl MachineState { result } - pub fn read( + pub(crate) fn read( &mut self, mut inner: Stream, atom_tbl: TabledData, @@ -241,7 +239,7 @@ struct TermWriter<'a> { } #[derive(Debug)] -pub struct TermWriteResult { +pub(crate) struct TermWriteResult { pub(crate) heap_loc: usize, pub(crate) var_dict: HeapVarDict, } diff --git a/src/targets.rs b/src/targets.rs index 956da22a..78e988e5 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -5,7 +5,7 @@ use crate::forms::*; use crate::instructions::*; use crate::iterators::*; -pub trait CompilationTarget<'a> { +pub(crate) trait CompilationTarget<'a> { type Iterator: Iterator>; fn iter(_: &'a Term) -> Self::Iterator; diff --git a/src/tests/hello_world.pl b/src/tests/hello_world.pl new file mode 100644 index 00000000..e7fd4e20 --- /dev/null +++ b/src/tests/hello_world.pl @@ -0,0 +1,6 @@ +:- use_module(library(debug)). +:- use_module(library(format)). + +hello_world :- write('Hello World!'), nl. + +:- initialization(hello_world). \ No newline at end of file diff --git a/tests/scryer.rs b/tests/scryer.rs new file mode 100644 index 00000000..55d67a73 --- /dev/null +++ b/tests/scryer.rs @@ -0,0 +1,65 @@ +/// Loads the file and if some expected output is given checks that it matches +fn test_file(file: &str, expected: Option<&[u8]>) { + use scryer_prolog::*; + + let input = machine::Stream::from(""); + let output = machine::Stream::from(String::new()); + + let mut wam = machine::Machine::new(input, output.clone()); + + wam.load_file( + file.into(), + machine::Stream::from( + std::fs::read_to_string(AsRef::::as_ref(file)).unwrap(), + ), + ); + + if let Some(expected) = expected { + let output = output.bytes().unwrap(); + assert_eq!(output.as_slice(), expected); + } +} + +#[test] +fn builtins() { + test_file("src/tests/builtins.pl", Some(b"")); +} + +#[test] +fn call_with_inference_limit() { + test_file("src/tests/call_with_inference_limit.pl", Some(b"")); +} + +#[test] +fn facts() { + test_file("src/tests/facts.pl", Some(b"")); +} + +#[test] +fn hello_world() { + test_file( + "src/tests/hello_world.pl", + Some("Hello World!\n".as_bytes()), + ); +} + +#[test] +fn predicates() { + test_file("src/tests/predicates.pl", Some(b"")); +} + +#[test] +fn rules() { + test_file("src/tests/rules.pl", Some(b"")); +} + +#[test] +#[ignore] // ignored as this does not appear to terminate +fn setup_call_cleanup() { + test_file("src/tests/setup_call_cleanup.pl", Some(b"")); +} + +#[test] +fn clpz() { + test_file("src/tests/clpz/test_clpz.pl", Some(b"")); +} From 90aefd35f0b7f80dd9bcfb8056624dcd378a1709 Mon Sep 17 00:00:00 2001 From: Skgland Date: Thu, 25 Feb 2021 23:42:41 +0100 Subject: [PATCH 126/137] adjust ci --- .github/workflows/test.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 94ebc690..ddb8e61d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,11 +17,16 @@ jobs: profile: minimal toolchain: ${{ matrix.rust-version }} override: true - - name: Build + - name: Build lib uses: actions-rs/cargo@v1 with: command: rustc - args: --verbose -- -D warnings + args: --verbose --lib -- -D warnings + - name: Build bin + uses: actions-rs/cargo@v1 + with: + command: rustc + args: --verbose --bin scryer-prolog -- -D warnings - name: Test uses: actions-rs/cargo@v1 with: From 90256ea2f53add821e115c7f8fb70b32b6353474 Mon Sep 17 00:00:00 2001 From: Skgland Date: Fri, 26 Feb 2021 01:03:05 +0100 Subject: [PATCH 127/137] fix CI lib build with beta compiler --- src/indexing.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/indexing.rs b/src/indexing.rs index be6d7260..286f618a 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -28,6 +28,7 @@ pub(crate) enum IndexingCodePtr { enum OptArgIndexKeyType { Structure, Constant, + #[allow(dead_code)] List, } From a638d42d92efbfa481f167b9a86b7c7c2f2ccda0 Mon Sep 17 00:00:00 2001 From: Skgland Date: Fri, 26 Feb 2021 17:19:38 +0100 Subject: [PATCH 128/137] remove #[allow(dead_code)] only commenting out the unused variant as `OptArgIndexKeyType` as it appears to mirror `OptArgIndexKey` and there List is not unused so this appears to be not yet used rather than obsolete --- src/indexing.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/indexing.rs b/src/indexing.rs index 286f618a..0f368356 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -28,8 +28,7 @@ pub(crate) enum IndexingCodePtr { enum OptArgIndexKeyType { Structure, Constant, - #[allow(dead_code)] - List, + // List, } impl OptArgIndexKey { @@ -38,7 +37,8 @@ impl OptArgIndexKey { match (self, key_type) { (OptArgIndexKey::Constant(..), OptArgIndexKeyType::Constant) | (OptArgIndexKey::Structure(..), OptArgIndexKeyType::Structure) - | (OptArgIndexKey::List(..), OptArgIndexKeyType::List) => true, + // | (OptArgIndexKey::List(..), OptArgIndexKeyType::List) + => true, _ => false, } } From 0a08464d4fab151da73203642c8cd5150d1ad077 Mon Sep 17 00:00:00 2001 From: Skgland Date: Fri, 26 Feb 2021 17:24:31 +0100 Subject: [PATCH 129/137] move the signal handler to the binary --- src/bin/scryer-prolog.rs | 9 +++++++++ src/lib.rs | 10 ---------- src/machine/mod.rs | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/bin/scryer-prolog.rs b/src/bin/scryer-prolog.rs index e3330c0a..4260bdd5 100644 --- a/src/bin/scryer-prolog.rs +++ b/src/bin/scryer-prolog.rs @@ -9,3 +9,12 @@ fn main() { let mut wam = machine::Machine::new(readline::input_stream(), machine::Stream::stdout()); wam.run_top_level(); } + +pub extern "C" fn handle_sigint(signal: libc::c_int) { + use nix::sys::signal; + use std::sync::atomic::Ordering; + let signal = signal::Signal::from_c_int(signal).unwrap(); + if signal == signal::Signal::SIGINT { + scryer_prolog::machine::INTERRUPT.store(true, Ordering::Relaxed); + } +} diff --git a/src/lib.rs b/src/lib.rs index 06fead04..1fd4a4fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,13 +23,3 @@ mod targets; mod write; use machine::*; - -use nix::sys::signal; -use std::sync::atomic::Ordering; - -pub extern "C" fn handle_sigint(signal: libc::c_int) { - let signal = signal::Signal::from_c_int(signal).unwrap(); - if signal == signal::Signal::SIGINT { - INTERRUPT.store(true, Ordering::Relaxed); - } -} diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 51a88762..3deee1bb 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -60,7 +60,7 @@ pub(crate) struct MachinePolicies { } lazy_static! { - pub(crate) static ref INTERRUPT: AtomicBool = AtomicBool::new(false); + pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false); } impl MachinePolicies { From 5a78f02dcb9c2ecf8833f31ecd6a9d83130dd737 Mon Sep 17 00:00:00 2001 From: Skgland Date: Fri, 26 Feb 2021 19:58:55 +0100 Subject: [PATCH 130/137] revert removal of PartialEq --- crates/prolog_parser/src/lexer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/prolog_parser/src/lexer.rs b/crates/prolog_parser/src/lexer.rs index b9bda1d0..02053035 100644 --- a/crates/prolog_parser/src/lexer.rs +++ b/crates/prolog_parser/src/lexer.rs @@ -33,7 +33,7 @@ macro_rules! consume_chars_with { }; } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Token { Constant(Constant), Var(Rc), From 101ed9a633e51356ff808a50a9f1497be1af3d2b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 11:44:07 -0700 Subject: [PATCH 131/137] add error value to occurs_check prolog flag (#783) --- src/clause_types.rs | 3 ++ src/lib/builtins.pl | 2 ++ src/machine/machine_errors.rs | 4 ++- src/machine/machine_state.rs | 10 +++++-- src/machine/machine_state_impl.rs | 49 ++++++++++++++++++++++++++----- src/machine/system_calls.rs | 9 ++++++ 6 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index 67b3b101..4d7e35d6 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -307,6 +307,7 @@ pub(crate) enum SystemClauseType { IsSTOEnabled, SetSTOAsUnify, SetNSTOAsUnify, + SetSTOWithErrorAsUnify, HomeDirectory, } @@ -593,6 +594,7 @@ impl SystemClauseType { &SystemClauseType::SetSTOAsUnify => clause_name!("$set_sto_as_unify"), &SystemClauseType::SetNSTOAsUnify => clause_name!("$set_nsto_as_unify"), &SystemClauseType::HomeDirectory => clause_name!("$home_directory"), + &SystemClauseType::SetSTOWithErrorAsUnify => clause_name!("$set_sto_with_error_as_unify"), } } @@ -839,6 +841,7 @@ impl SystemClauseType { ("$is_sto_enabled", 1) => Some(SystemClauseType::IsSTOEnabled), ("$set_sto_as_unify", 0) => Some(SystemClauseType::SetSTOAsUnify), ("$set_nsto_as_unify", 0) => Some(SystemClauseType::SetNSTOAsUnify), + ("$set_sto_with_error_as_unify", 0) => Some(SystemClauseType::SetSTOWithErrorAsUnify), ("$home_directory", 1) => Some(SystemClauseType::HomeDirectory), _ => None, } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 3c9a380e..ae727d4b 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -171,6 +171,8 @@ set_prolog_flag(occurs_check, true) :- !, '$set_sto_as_unify'. set_prolog_flag(occurs_check, false) :- !, '$set_nsto_as_unify'. +set_prolog_flag(occurs_check, error) :- + !, '$set_sto_with_error_as_unify'. set_prolog_flag(double_quotes, Value) :- throw(error(domain_error(flag_value, double_quotes + Value), set_prolog_flag/2)). % 8.17.1.3 e diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 8175d261..fbfb1bcf 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -596,7 +596,8 @@ pub(crate) enum RepFlag { InCharacterCode, MaxArity, // MaxInteger, - // MinInteger + // MinInteger, + Term, } impl RepFlag { @@ -606,6 +607,7 @@ impl RepFlag { RepFlag::CharacterCode => "character_code", RepFlag::InCharacterCode => "in_character_code", RepFlag::MaxArity => "max_arity", + RepFlag::Term => "term", // RepFlag::MaxInteger => "max_integer", // RepFlag::MinInteger => "min_integer" } diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index b94de736..77a0d368 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -336,9 +336,13 @@ impl fmt::Debug for MachineState { .field("global_clock", &self.global_clock) .field("dynamic_mode", &self.dynamic_mode) .field("unify_fn", - if self.unify_fn as usize == MachineState::unify as usize - { &"MachineState::unify" } - else { &"MachineState::unify_with_occurs_check" }) + if self.unify_fn as usize == MachineState::unify as usize { + &"MachineState::unify" + } else if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize { + &"MachineState::unify_with_occurs_check" + } else { + &"MachineState::unify_with_occurs_check_with_error" + }) .finish() } } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index efb0e6a9..b4486366 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -153,31 +153,58 @@ impl MachineState { } } - fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) { + #[inline] + fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool { if let Ref::StackCell(..) = r { // local variable optimization -- r cannot occur in the // data structure bound to addr, so don't bother // traversing it. self.bind(r, addr); - return; + return false; } - let mut fail = false; + let mut occurs_triggered = false; for addr in self.acyclic_pre_order_iter(addr) { if let Some(inner_r) = addr.as_var() { if r == inner_r { - fail = true; + occurs_triggered = true; break; } } } - self.fail = fail; + self.fail = occurs_triggered; self.bind(r, addr); + + return occurs_triggered; + } + + pub(super) fn unify_with_occurs_check_with_error(&mut self, a1: Addr, a2: Addr) { + let mut throw_error = false; + self.unify_with_occurs_check_loop(a1, a2, || throw_error = true); + + if throw_error { + let err = self.representation_error( + RepFlag::Term, + clause_name!("unify_with_occurs_check"), + 2, + ); + + self.throw_exception(err); + } } pub(super) fn unify_with_occurs_check(&mut self, a1: Addr, a2: Addr) { + self.unify_with_occurs_check_loop(a1, a2, || {}) + } + + pub(super) fn unify_with_occurs_check_loop( + &mut self, + a1: Addr, + a2: Addr, + mut occurs_trigger: impl FnMut() + ) { let mut pdl = vec![a1, a2]; let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new(); @@ -199,13 +226,19 @@ impl MachineState { match (d1, d2) { (Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => { - self.bind_with_occurs_check(Ref::AttrVar(h), addr) + if self.bind_with_occurs_check(Ref::AttrVar(h), addr) { + occurs_trigger(); + } } (Addr::HeapCell(h), addr) | (addr, Addr::HeapCell(h)) => { - self.bind_with_occurs_check(Ref::HeapCell(h), addr) + if self.bind_with_occurs_check(Ref::HeapCell(h), addr) { + occurs_trigger(); + } } (Addr::StackCell(fr, sc), addr) | (addr, Addr::StackCell(fr, sc)) => { - self.bind_with_occurs_check(Ref::StackCell(fr, sc), addr) + if self.bind_with_occurs_check(Ref::StackCell(fr, sc), addr) { + occurs_trigger(); + } } (Addr::Lis(a1), Addr::Str(a2)) | (Addr::Str(a2), Addr::Lis(a1)) => { if let &HeapCellValue::NamedStr(n2, ref f2, _) = &self.heap[a2] { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index a37e4efe..6793c085 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -5439,6 +5439,12 @@ impl MachineState { HeapCellValue::Atom(clause_name!("true"), None), ); + (self.unify_fn)(self, self[temp_v!(1)], value); + } else if self.unify_fn as usize == MachineState::unify_with_occurs_check_with_error as usize { + let value = self.heap.to_unifiable( + HeapCellValue::Atom(clause_name!("error"), None), + ); + (self.unify_fn)(self, self[temp_v!(1)], value); } else { let value = self.heap.to_unifiable( @@ -5454,6 +5460,9 @@ impl MachineState { &SystemClauseType::SetNSTOAsUnify => { self.unify_fn = MachineState::unify; } + &SystemClauseType::SetSTOWithErrorAsUnify => { + self.unify_fn = MachineState::unify_with_occurs_check_with_error; + } &SystemClauseType::HomeDirectory => { let path = match dirs_next::home_dir() { Some(path) => path, From 08e2b601f1575e3e38b8c2f0a09115398a0b243a Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 12:28:19 -0700 Subject: [PATCH 132/137] pop non-composite terms from iter stack in is_cyclic_term --- src/heap_print.rs | 46 ------------------------------- src/machine/machine_state_impl.rs | 2 ++ 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/src/heap_print.rs b/src/heap_print.rs index 5e05d5b5..950b3ecd 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -392,21 +392,6 @@ pub(crate) fn requires_space(atom: &str, op: &str) -> bool { } } -/* -fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict { - machine_st - .heap_locs - .iter() - .map(|(var, var_addr)| { - ( - machine_st.store(machine_st.deref(var_addr.clone())), - var.clone(), - ) - }) - .collect() -} -*/ - fn non_quoted_graphic_token>(mut iter: Iter, c: char) -> bool { if c == '/' { return match iter.next() { @@ -494,37 +479,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { max_depth: 0, } } - /* - pub(crate) fn from_heap_locs( - machine_st: &'a MachineState, - op_dir: &'a OpDir, - output: Outputter, - ) -> Self { - let mut printer = Self::new(machine_st, op_dir, output); - - printer.toplevel_spec = Some(DirectedOp::Right( - clause_name!("="), - SharedOpDesc::new(700, XFX), - )); - - printer.heap_locs = reverse_heap_locs(machine_st); - - printer - } - */ - /* - pub(crate) fn drop_toplevel_spec(&mut self) { - self.toplevel_spec = None; - } - */ - /* - #[inline] - pub(crate) 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 { diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index b4486366..6ca1341a 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1749,6 +1749,8 @@ impl MachineState { fail = true; break; } + } else { + iter.stack().pop(); } } From 3f1cfd29957dc0b71e404b9eadca0c9aa476f748 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 16:19:06 -0700 Subject: [PATCH 133/137] introduce bind_fn, use in applicable Fact/Query instructions (#841) --- src/machine/machine_state.rs | 9 ++++++ src/machine/machine_state_impl.rs | 48 ++++++++++++++++++++----------- src/machine/system_calls.rs | 11 ++++--- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 77a0d368..ee48340a 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -304,6 +304,7 @@ pub(crate) struct MachineState { pub(crate) global_clock: usize, pub(crate) dynamic_mode: FirstOrNext, pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr), + pub(crate) bind_fn: fn(&mut MachineState, Ref, Addr), } impl fmt::Debug for MachineState { @@ -343,6 +344,14 @@ impl fmt::Debug for MachineState { } else { &"MachineState::unify_with_occurs_check_with_error" }) + .field("bind_fn", + if self.bind_fn as usize == MachineState::bind as usize { + &"MachineState::bind" + } else if self.bind_fn as usize == MachineState::bind_with_occurs_check_wrapper as usize { + &"MachineState::bind_with_occurs_check" + } else { + &"MachineState::bind_with_occurs_check_with_error_wrapper" + }) .finish() } } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 6ca1341a..b1d8dde7 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -57,6 +57,7 @@ impl MachineState { global_clock: 0, dynamic_mode: FirstOrNext::First, unify_fn: MachineState::unify, + bind_fn: MachineState::bind, } } @@ -154,7 +155,25 @@ impl MachineState { } #[inline] - fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool { + pub(super) fn bind_with_occurs_check_with_error_wrapper(&mut self, r: Ref, addr: Addr) { + if self.bind_with_occurs_check(r, addr) { + let err = self.representation_error( + RepFlag::Term, + clause_name!("unify_with_occurs_check"), + 2, + ); + + self.throw_exception(err); + } + } + + #[inline] + pub(super) fn bind_with_occurs_check_wrapper(&mut self, r: Ref, addr: Addr) { + self.bind_with_occurs_check(r, addr); + } + + #[inline] + pub(super) fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool { if let Ref::StackCell(..) = r { // local variable optimization -- r cannot occur in the // data structure bound to addr, so don't bother @@ -871,7 +890,7 @@ impl MachineState { } Addr::Lis(l) => { let addr = self.heap.put_constant(c.clone()); - (self.unify_fn)(self, Addr::Lis(l), addr); + self.unify(Addr::Lis(l), addr); } Addr::PStrLocation(h, n) => { if let Constant::String(ref s2) = c { @@ -889,7 +908,7 @@ impl MachineState { if let Some(r) = addr.as_var() { self.bind(r, c); } else { - (self.unify_fn)(self, addr, c); + self.unify(addr, c); } } }; @@ -1222,8 +1241,7 @@ impl MachineState { let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1))); - self.heap - .push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); + self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); self.bind(addr.as_var().unwrap(), Addr::HeapCell(h)); @@ -1283,22 +1301,20 @@ impl MachineState { self.increment_s_ptr(1); } MachineMode::Write => { - let addr = self.deref(self[reg]); + let addr = self.store(self.deref(self[reg])); let h = self.heap.h(); if let Addr::HeapCell(hc) = addr { - if hc < h { - let val = self.heap.clone(hc); + let val = self.heap.clone(hc); - self.heap.push(val); - self.increment_s_ptr(1); + self.heap.push(val); + self.increment_s_ptr(1); - return; - } + return; } self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); - self.bind(Ref::HeapCell(h), addr); + (self.bind_fn)(self, Ref::HeapCell(h), addr); } }; } @@ -1569,7 +1585,7 @@ impl MachineState { let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); - self.bind(Ref::HeapCell(h), addr); + (self.bind_fn)(self, Ref::HeapCell(h), addr); self.registers[arg] = self.heap[h].as_addr(h); } @@ -1611,7 +1627,7 @@ impl MachineState { } self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); - self.bind(Ref::HeapCell(h), addr); + (self.bind_fn)(self, Ref::HeapCell(h), addr); } &QueryInstruction::SetVariable(reg) => { let h = self.heap.h(); @@ -2466,7 +2482,7 @@ impl MachineState { self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + i))); } - self.bind(r, f_a); + (self.bind_fn)(self, r, f_a); } pub(super) fn try_functor(&mut self, op_dir: &OpDir) -> CallResult { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 6793c085..dfe0411f 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -253,11 +253,11 @@ impl MachineState { fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) { let target_n = self[temp_v!(1)]; - (self.unify_fn)(self, Addr::Usize(n), target_n); + self.unify(Addr::Usize(n), target_n); if !self.fail { let xs = self[temp_v!(4)]; - (self.unify_fn)(self, addr, xs); + self.unify(addr, xs); } } @@ -313,7 +313,7 @@ impl MachineState { let xs0 = self[temp_v!(3)]; let xs = self[temp_v!(4)]; - (self.unify_fn)(self, xs0, xs); + self.unify(xs0, xs); } else { self.skip_max_list_result(max_steps_n); } @@ -323,7 +323,7 @@ impl MachineState { let xs0 = self[temp_v!(3)]; let xs = self[temp_v!(4)]; - (self.unify_fn)(self, xs0, xs); + self.unify(xs0, xs); } else { self.skip_max_list_result(max_steps_n); } @@ -5456,12 +5456,15 @@ impl MachineState { } &SystemClauseType::SetSTOAsUnify => { self.unify_fn = MachineState::unify_with_occurs_check; + self.bind_fn = MachineState::bind_with_occurs_check_wrapper; } &SystemClauseType::SetNSTOAsUnify => { self.unify_fn = MachineState::unify; + self.bind_fn = MachineState::bind; } &SystemClauseType::SetSTOWithErrorAsUnify => { self.unify_fn = MachineState::unify_with_occurs_check_with_error; + self.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper; } &SystemClauseType::HomeDirectory => { let path = match dirs_next::home_dir() { From 360485d830d0281763783e7def1f638b573c2bdb Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 16:19:37 -0700 Subject: [PATCH 134/137] print errors arising from term and goal expansion calls from loader.pl --- src/loader.pl | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index bf6efc26..d1db274b 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -17,15 +17,26 @@ :- use_module(library(pairs)). -'$print_message_and_fail'(Error, Culprit) :- - % writeq(error(Error, Culprit)), - % nl, +'$print_message_and_fail'(Error) :- + ( Error = error(existence_error(procedure, Expansion), Expansion) -> + ( ( Expansion = goal_expansion/2 + ; Expansion = term_expansion/2 + ) -> + true + ; write('caught: '), + writeq(Error), + nl + ) + ; write('caught: '), + writeq(Error), + nl + ), '$fail'. expand_term(Term, ExpandedTerm) :- ( catch('$call'(user:term_expansion(Term, ExpandedTerm0)), E, - '$call'(loader:'$print_message_and_fail'(E, user:term_expansion/2))) -> + '$call'(loader:'$print_message_and_fail'(E))) -> ( var(ExpandedTerm0) -> error:instantiation_error(term_expansion/2) ; ExpandedTerm0 = [_|_] -> @@ -51,7 +62,7 @@ term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- goal_expansion(Goal, Module, ExpandedGoal) :- ( catch('$call'(Module:goal_expansion(Goal, ExpandedGoal0)), E, - '$call'(loader:'$print_message_and_fail'(E, Module:goal_expansion/2))) -> + '$call'(loader:'$print_message_and_fail'(E))) -> ( var(ExpandedGoal0) -> error:instantiation_error(goal_expansion/2) ; goal_expansion(ExpandedGoal0, Module, ExpandedGoal) @@ -94,6 +105,7 @@ file_load(Stream, Path, Evacuable) :- catch(loader:load_loop(Stream, Evacuable), E, builtins:(loader:unload_evacuable(Evacuable), + loader:'$print_message_and_fail'(E), builtins:throw(E))), run_initialization_goals, '$pop_load_context'. @@ -104,6 +116,7 @@ load(Stream) :- catch(loader:load_loop(Stream, Evacuable), E, builtins:(loader:unload_evacuable(Evacuable), + loader:'$print_message_and_fail'(E), builtins:throw(E))), run_initialization_goals, '$pop_load_context', @@ -523,7 +536,7 @@ load_context(Module) :- predicate_property(Callable, Property) :- ( var(Callable) -> - instantiation_error(load/1) + instantiation_error(predicate_property/2) ; functor(Callable, (:), 2), arg(1, Callable, Module), arg(2, Callable, Callable0), From a03f00628b771767c08e5b1e2c2e150ca68976ed Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 17:57:35 -0700 Subject: [PATCH 135/137] do not print error messages if .scryerrc[.pl] does not exist (#842) --- src/machine/system_calls.rs | 6 ++---- src/toplevel.pl | 11 +++++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index dfe0411f..1ffa227e 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -5477,11 +5477,9 @@ impl MachineState { if path.is_dir() { if let Some(path) = path.to_str() { - let path_atom = self.heap.to_unifiable( - HeapCellValue::Atom(clause_name!(path.to_string(), self.atom_tbl), None), - ); + let path_string = self.heap.put_complete_string(path); - (self.unify_fn)(self, self[temp_v!(1)], path_atom); + self.unify(self[temp_v!(1)], path_string); return return_from_clause!(self.last_call, self); } } diff --git a/src/toplevel.pl b/src/toplevel.pl index daf03525..e0f1bcc1 100644 --- a/src/toplevel.pl +++ b/src/toplevel.pl @@ -2,6 +2,7 @@ copy_term/3]). :- use_module(library(charsio)). +:- use_module(library(files)). :- use_module(library(iso_ext)). :- use_module(library(lists)). :- use_module(library(si)). @@ -11,8 +12,14 @@ load_scryerrc :- ( '$home_directory'(HomeDir) -> - atom_concat(HomeDir, '/.scryerrc', ScryerrcFile), - catch(use_module(ScryerrcFile), E, print_exception(E)) + append(HomeDir, "/.scryerrc", ScryerrcFile), + ( file_exists(ScryerrcFile) -> + % convert ScryerrcFile to atom. somehow, I dunno how. + append(ScryerrcFile, "'.", ScryerrcFile0), + read_term_from_chars(['\'' | ScryerrcFile0], ScryerrcFileAtom), + catch(use_module(ScryerrcFileAtom), E, print_exception(E)) + ; true + ) ; true ). From 9a225e624458cf6ab5bd31638a800f8ccbad7747 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 18:15:33 -0700 Subject: [PATCH 136/137] wrap variable goals in module-expanded call/1 --- src/loader.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/loader.pl b/src/loader.pl index d1db274b..e5304812 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -603,7 +603,7 @@ expand_meta_predicate_subgoals([SG | SGs], [MS | MSs], M, [ESG | ESGs], HeadVars ) -> ( var(SG), pairs:same_key(SG, HeadVars, [_|_], _) -> - expand_subgoal(SG, MS, M, ESG, HeadVars) %%TODO: Shortcut this.. set SG = ESG. Or wrap it in '$call', ie. ESG = '$call'(SG). + expand_subgoal(SG, MS, M, ESG, HeadVars) ; expand_subgoal(SG, MS, M, ESG0, HeadVars), expand_module_name(ESG0, M, ESG) ), @@ -654,7 +654,7 @@ expand_goal_cases((Module:Goals0), _, ExpandedGoals, HeadVars) :- expand_goal(UnexpandedGoals, Module, ExpandedGoals, HeadVars) :- ( var(UnexpandedGoals) -> - UnexpandedGoals = ExpandedGoals + call(Module:UnexpandedGoals) = ExpandedGoals ; goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1), ( Module \== user -> goal_expansion(UnexpandedGoals1, user, Goals) From d6e04beb95a6751004dea7d6f8a7ea58dc10ba3d Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 28 Feb 2021 18:28:12 -0700 Subject: [PATCH 137/137] check that Module is an atom before calling Module:goal_expansion/2 --- src/loader.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/loader.pl b/src/loader.pl index e5304812..8a409ce2 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -60,7 +60,8 @@ term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :- goal_expansion(Goal, Module, ExpandedGoal) :- - ( catch('$call'(Module:goal_expansion(Goal, ExpandedGoal0)), + ( atom(Module), + catch('$call'(Module:goal_expansion(Goal, ExpandedGoal0)), E, '$call'(loader:'$print_message_and_fail'(E))) -> ( var(ExpandedGoal0) ->