diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 38d3fb57..d7e8a2df 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,6 @@ name: Main -on: +on: pull_request: branches: - master @@ -20,7 +20,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: nightly-2024-07-07 components: rustfmt - name: Install cargo-make diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 72d68c49..54e3a07a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,8 +20,8 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: stable - + toolchain: 1.81.0 + - name: Release zia run: cargo package && cargo publish --token ${{secrets.CRATES_TOKEN}} working-directory: ./zia @@ -29,7 +29,7 @@ jobs: - name: Sleep for 30 seconds uses: jakejarvis/wait-action@master with: - time: '30s' + time: "30s" - name: Release izia run: cargo package && cargo publish --token ${{secrets.CRATES_TOKEN}} diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 078620d9..1933e625 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -12,35 +12,35 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v1 - - name: Install node v16 + - name: Install node v18 uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 18 - - name: Install nightly Rust and rustfmt + - name: Install stable Rust uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly - components: rustfmt + toolchain: 1.81.0 - name: Install cargo-make uses: davidB/rust-cargo-make@v1 with: - version: '0.35.1' + version: "0.35.1" - name: Install wasm-pack uses: jetli/wasm-pack-action@v0.3.0 with: - # Optional version of wasm-pack to install(eg. 'v0.9.1', 'latest') - version: 'latest' + version: "v0.13.0" - name: Install Node dependencies run: yarn working-directory: ./zia-lang.org - - name: Build & prerender - run: yarn build:prerender + - name: Build + run: yarn build:release + env: + NODE_OPTIONS: --openssl-legacy-provider working-directory: ./zia-lang.org - name: Install Netlify CLI @@ -53,6 +53,3 @@ jobs: NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} NETLIFY_ACCESS_TOKEN: ${{ secrets.NETLIFY_ACCESS_TOKEN }} run: sudo netlify deploy -s $NETLIFY_SITE_ID --auth $NETLIFY_ACCESS_TOKEN -p --dir ./zia-lang.org/dist - - - diff --git a/Cargo.lock b/Cargo.lock index 201613fb..9002e141 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "atty" version = "0.2.14" @@ -46,12 +52,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base-x" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" - [[package]] name = "base64" version = "0.13.0" @@ -172,18 +172,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.15", "lazy_static", "proc-macro-hack", "tiny-keccak", ] -[[package]] -name = "const_fn" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7" - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -192,13 +186,13 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cookie" -version = "0.14.4" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.2.27", - "version_check 0.9.3", + "time", + "version_check 0.9.5", ] [[package]] @@ -288,12 +282,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "either" version = "1.6.1" @@ -320,9 +308,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -335,9 +323,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -345,15 +333,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -362,38 +350,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", ] [[package]] name = "futures-sink" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -407,15 +395,6 @@ dependencies = [ "slab", ] -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - [[package]] name = "getrandom" version = "0.1.16" @@ -423,22 +402,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", - "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "js-sys", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -454,9 +431,9 @@ dependencies = [ [[package]] name = "gloo-file" -version = "0.1.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f9fecfe46b5dc3cc46f58e98ba580cc714f2c93860796d002eb3527a465ef49" +checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" dependencies = [ "futures-channel", "gloo-events", @@ -467,22 +444,34 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", "web-sys", ] [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hermit-abi" @@ -495,9 +484,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg 1.0.1", "hashbrown", @@ -509,6 +498,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + [[package]] name = "izia" version = "0.5.0" @@ -519,10 +514,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -534,9 +530,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.108" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linefeed" @@ -610,8 +606,8 @@ dependencies = [ "bitflags 0.4.0", "cfg-if 0.1.10", "libc", - "rustc_version 0.1.7", - "semver 0.1.20", + "rustc_version", + "semver", "void", ] @@ -644,6 +640,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -731,11 +733,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -758,18 +760,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "pulldown-cmark" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" -dependencies = [ - "bitflags 1.3.2", - "getopts", - "memchr", - "unicase", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -778,9 +768,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.10" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -795,39 +785,24 @@ dependencies = [ "libc", "rand_chacha 0.1.1", "rand_core 0.4.2", - "rand_hc 0.1.0", + "rand_hc", "rand_isaac", "rand_jitter", "rand_os", - "rand_pcg 0.1.2", + "rand_pcg", "rand_xorshift", "winapi", ] [[package]] name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", - "rand_pcg 0.2.1", -] - -[[package]] -name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -840,16 +815,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -875,22 +840,13 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - [[package]] name = "rand_core" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.15", ] [[package]] @@ -902,24 +858,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_isaac" version = "0.1.1" @@ -964,15 +902,6 @@ dependencies = [ "rand_core 0.4.2", ] -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rand_xorshift" version = "0.1.1" @@ -1075,17 +1004,14 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" dependencies = [ - "semver 0.1.20", + "semver", ] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "rustversion" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "rusty-fork" @@ -1107,9 +1033,9 @@ checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568" [[package]] name = "scoped-tls" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -1119,25 +1045,26 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "seed" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b599be9cc57456f4b7fc99b8abfb154d4819f7b6c147e80be5580663dad4536" +checksum = "9352d75dd253803ce05722fe3acaafffc461d4faeaf0ebe0d8bf831059482e21" dependencies = [ "console_error_panic_hook", "cookie", "dbg", "enclose", "futures", + "getrandom 0.2.15", "gloo-file", "gloo-timers", + "gloo-utils", "indexmap", "js-sys", - "pulldown-cmark", - "rand 0.7.3", + "rand 0.8.5", "serde", "serde_json", "uuid", - "version_check 0.9.3", + "version_check 0.9.5", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1149,58 +1076,38 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" -[[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 = "serde" -version = "1.0.130" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.72" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ - "itoa", + "itoa 1.0.14", + "memchr", "ryu", "serde", ] -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" - [[package]] name = "simple_logger" version = "1.15.0" @@ -1210,7 +1117,7 @@ dependencies = [ "atty", "colored", "log", - "time 0.3.5", + "time", "winapi", ] @@ -1232,7 +1139,7 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" dependencies = [ - "version_check 0.9.3", + "version_check 0.9.5", ] [[package]] @@ -1254,72 +1161,25 @@ dependencies = [ ] [[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check 0.9.3", -] - -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" +name = "syn" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ - "base-x", "proc-macro2", "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", + "unicode-xid", ] -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "syn" -version = "1.0.82" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1330,7 +1190,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", "libc", - "rand 0.8.4", + "rand 0.8.5", "redox_syscall 0.2.10", "remove_dir_all", "winapi", @@ -1365,22 +1225,7 @@ checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" -dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", - "time-macros 0.1.1", - "version_check 0.9.3", - "winapi", + "syn 1.0.82", ] [[package]] @@ -1389,19 +1234,9 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" dependencies = [ - "itoa", + "itoa 0.4.8", "libc", - "time-macros 0.2.3", -] - -[[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", + "time-macros", ] [[package]] @@ -1410,19 +1245,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1448,13 +1270,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] -name = "unicase" -version = "2.6.0" +name = "unicode-ident" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check 0.9.3", -] +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-normalization" @@ -1479,11 +1298,11 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "uuid" -version = "0.8.2" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.15", ] [[package]] @@ -1494,9 +1313,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -1521,17 +1340,19 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if 1.0.0", + "once_cell", + "rustversion", "serde", "serde_json", "wasm-bindgen-macro", @@ -1539,36 +1360,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", - "lazy_static", "log", "proc-macro2", "quote", - "syn", + "syn 2.0.98", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if 1.0.0", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1576,28 +1397,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-bindgen-test" -version = "0.3.28" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96f1aa7971fdf61ef0f353602102dbea75a56e225ed036c1e3740564b91e6b7e" +checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" dependencies = [ "console_error_panic_hook", "js-sys", @@ -1609,9 +1433,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.28" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6006f79628dfeb96a86d4db51fbf1344cd7fd8408f06fc9aa3c84913a4789688" +checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" dependencies = [ "proc-macro2", "quote", @@ -1619,9 +1443,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -1670,6 +1494,7 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" name = "zia" version = "0.5.0" dependencies = [ + "assert_matches", "bimap", "dashmap", "lazy_static", diff --git a/Makefile.toml b/Makefile.toml index 024fed26..7fce199c 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -2,12 +2,12 @@ # ---- GENERAL ---- [tasks.verify] -toolchain = "nightly" +toolchain = "nightly-2024-07-07" description = "Format, lint with Clippy and run tests" dependencies = ["fmt", "clippy_fix", "test"] [tasks.verify_only] -toolchain = "nightly" +toolchain = "nightly-2024-07-07" description = "Like `verify`, but fails if the code isn't formatted. Primarily for CI." dependencies = ["fmt_check", "clippy", "test"] @@ -15,28 +15,28 @@ dependencies = ["fmt_check", "clippy", "test"] [tasks.test] description = "Run tests. i.e.: 'cargo make test'." -toolchain = "nightly" +toolchain = "nightly-2024-07-07" command = "cargo" args = ["test"] # ---- LINT ---- [tasks.fmt] -description = "Format with nightly rustfmt" -toolchain = "nightly" +description = "Format with nightly-2024-07-07 rustfmt" +toolchain = "nightly-2024-07-07" command = "cargo" args = ["fmt", "--all"] [tasks.fmt_check] extend = "fmt" -toolchain = "nightly" -description = "Check format with nightly rustfmt" +toolchain = "nightly-2024-07-07" +description = "Check format with nightly-2024-07-07 rustfmt" args = ["fmt", "--all", "--", "--check"] [tasks.clippy] description = "Lint with Clippy" clear = true -toolchain = "nightly" +toolchain = "nightly-2024-07-07" install_crate = { rustup_component_name = "clippy", binary = "cargo-clippy", test_arg = "--help" } command = "cargo" args = ["clippy", "--all-features", "--", "--deny", "warnings", "--deny", "clippy::pedantic", "--deny", "clippy::nursery", "--allow", "clippy::manual_filter_map"] @@ -45,7 +45,7 @@ args = ["clippy", "--all-features", "--", "--deny", "warnings", "--deny", "clipp [tasks.clippy_fix] description = "Lint and fix with Clippy" clear = true -toolchain = "nightly" +toolchain = "nightly-2024-07-07" install_crate = { rustup_component_name = "clippy", binary = "cargo-clippy", test_arg = "--help" } command = "cargo" args = ["clippy", "--all-features", "--fix", "--allow-dirty", "--", "--deny", "warnings", "--deny", "clippy::pedantic", "--deny", "clippy::nursery", "--allow", "clippy::manual_filter_map"] diff --git a/docker-compose.nvim.yml b/docker-compose.nvim.yml index f05abce7..4af371ac 100644 --- a/docker-compose.nvim.yml +++ b/docker-compose.nvim.yml @@ -3,10 +3,12 @@ services: environment: - CARGO_HOME=/usr/src/.cargo - DISPLAY - build: ./nvim + image: devimage + pull_policy: never volumes: - .:/usr/src - /tmp/.X11-unix:/tmp/.X11-unix + - /home/charles/SideProjects/zia_programming/target:/usr/src/target command: [ "sh", @@ -19,26 +21,30 @@ services: environment: - CARGO_HOME=/usr/src/.cargo - DISPLAY - build: ./nvim + image: devimage + pull_policy: never volumes: - .:/usr/src - /tmp/.X11-unix:/tmp/.X11-unix + - /home/charles/SideProjects/zia_programming/target:/usr/src/target command: [ "sh", "-c", - "rsync -avzh /home/node/.cargo /usr/src/.cargo && cargo make --no-workspace test", + "rsync -avzh /home/node/.cargo /usr/src/.cargo && ls -al target && cargo make --no-workspace test", ] - working_dir: /usr/src user: ${UID:-1000}:${GID:-1000} + working_dir: /usr/src verify: environment: - CARGO_HOME=/usr/src/.cargo - DISPLAY - build: ./nvim + image: devimage + pull_policy: never volumes: - .:/usr/src - /tmp/.X11-unix:/tmp/.X11-unix + - /home/charles/SideProjects/zia_programming/target:/usr/src/target command: [ "sh", @@ -51,10 +57,12 @@ services: environment: - CARGO_HOME=/usr/src/.cargo - DISPLAY - build: ./nvim + image: devimage + pull_policy: never volumes: - .:/usr/src - /tmp/.X11-unix:/tmp/.X11-unix + - /home/charles/SideProjects/zia_programming/target:/usr/src/target command: [ "sh", @@ -65,3 +73,25 @@ services: user: ${UID:-1000}:${GID:-1000} ports: - 8000:8000 + web-release: + environment: + - CARGO_HOME=/usr/src/.cargo + - DISPLAY + - NODE_OPTIONS=--openssl-legacy-provider + build: ./nvim + image: devimage + pull_policy: never + volumes: + - .:/usr/src + - /tmp/.X11-unix:/tmp/.X11-unix + - /home/charles/SideProjects/zia_programming/target:/usr/src/target + command: + [ + "sh", + "-c", + "rsync -avzh /home/node/.cargo /usr/src/.cargo && cd zia-lang.org && yarn && yarn build:prerender", + ] + working_dir: /usr/src + user: ${UID:-1000}:${GID:-1000} + ports: + - 8000:8000 diff --git a/nvim/Dockerfile b/nvim/Dockerfile index 6e3b7c74..eb5304be 100644 --- a/nvim/Dockerfile +++ b/nvim/Dockerfile @@ -3,7 +3,7 @@ RUN apt update RUN apt install -y curl RUN apt-get install ripgrep USER node -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain=1.75 -y +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain=1.81 -y ENV PATH="/home/node/.cargo/bin:$PATH" RUN rustup component add rust-analyzer RUN mkdir -p /home/node/.local/share/nvim/site/autoload @@ -18,8 +18,12 @@ RUN git clone https://tpope.io/vim/fugitive.git RUN mkdir -p /home/node/.config/nvim COPY init.vim /home/node/.config/nvim/init.vim USER root -RUN apt update && apt install -y neovim +RUN curl -o /home/node/nvim.tar.gz -L https://github.com/neovim/neovim/releases/download/v0.8.3/nvim-linux64.tar.gz +RUN tar -xzvf /home/node/nvim.tar.gz +RUN mv nvim-linux64 /home/node/nvim +RUN chown -R node:node /home/node/nvim USER node +ENV PATH=$PATH:/home/node/nvim/bin RUN nvim -c "helptags fugitive/doc" -c ":PlugInstall | :q | :q" RUN git config --global --add safe.directory /usr/src # install coc.nvim extensions @@ -41,10 +45,11 @@ USER root RUN apt install -y build-essential RUN apt install -y rsync USER node -RUN cargo install --force wasm-pack -RUN cargo install --force cargo-make -RUN rustup toolchain install nightly -RUN rustup component add rustfmt --toolchain nightly +RUN cargo install --force wasm-pack --version 0.13.0 +RUN cargo install --force cargo-make --version "0.35.1" +RUN rustup toolchain install nightly-2024-07-07 +RUN rustup component add rustfmt --toolchain nightly-2024-07-07 RUN cargo install --force cargo-readme RUN git config --global user.email "charlesthomasjohnson0@gmail.com" RUN git config --global user.name "Charle Johnson" + diff --git a/zia-lang.org/crate/Cargo.toml b/zia-lang.org/crate/Cargo.toml index b29c7a26..875b645b 100644 --- a/zia-lang.org/crate/Cargo.toml +++ b/zia-lang.org/crate/Cargo.toml @@ -13,11 +13,11 @@ edition = "2018" crate-type = ["cdylib"] [dev-dependencies] -wasm-bindgen-test = "^0.3.18" +wasm-bindgen-test = "=0.3.18" [dependencies] zia = { path = "../../zia", version = "0.5.0"} -seed = "0.8.0" +seed = "0.9.0" console_error_panic_hook = "0.1.7" [dependencies.web-sys] @@ -30,3 +30,4 @@ features = [ [profile.release] lto = true opt-level = 's' +strip = true diff --git a/zia-lang.org/crate/src/page/home/command_input.rs b/zia-lang.org/crate/src/page/home/command_input.rs index d6fa5aa7..bcc11053 100644 --- a/zia-lang.org/crate/src/page/home/command_input.rs +++ b/zia-lang.org/crate/src/page/home/command_input.rs @@ -90,12 +90,12 @@ pub fn view(model: &HomeModel) -> impl IntoNodes { LexemeCategory::Concept(ConceptKind::Variable) => { Some(C.text_variable_concept) }, - LexemeCategory::Concept(ConceptKind::Concrete) => { - Some(C.text_concrete_concept) - }, - LexemeCategory::Concept(ConceptKind::Abstract) => { - Some(C.text_abstract_concept) - }, + LexemeCategory::Concept(ConceptKind::Concrete { + .. + }) => Some(C.text_concrete_concept), + LexemeCategory::Concept(ConceptKind::Abstract { + .. + }) => Some(C.text_abstract_concept), LexemeCategory::OpeningParenthesis { closing_position: None, } diff --git a/zia/Cargo.toml b/zia/Cargo.toml index 3fce6316..daeac354 100755 --- a/zia/Cargo.toml +++ b/zia/Cargo.toml @@ -36,3 +36,4 @@ simple_logger = "1.15.0" [dev-dependencies] proptest = "0.9.1" pretty_assertions = "1.4.0" +assert_matches = "*" diff --git a/zia/src/associativity.rs b/zia/src/associativity.rs index 88a7e871..e6325d3e 100644 --- a/zia/src/associativity.rs +++ b/zia/src/associativity.rs @@ -30,12 +30,12 @@ impl Associativity { } #[must_use] - pub fn slice_tokens<'a>( + pub fn slice_tokens<'a, T>( &self, - tokens: &'a [String], + tokens: &'a [T], prev_lp_index: Option, lp_index: usize, - ) -> &'a [String] { + ) -> &'a [T] { match &self { Self::Left => prev_lp_index .map_or_else(|| &tokens[..lp_index], |i| &tokens[i..lp_index]), diff --git a/zia/src/ast/macro.rs b/zia/src/ast/macro.rs index 5719df1c..f16e33f1 100644 --- a/zia/src/ast/macro.rs +++ b/zia/src/ast/macro.rs @@ -1,232 +1,252 @@ #![allow(clippy::single_component_path_imports)] -macro_rules! impl_syntax_tree { - ($refcounter:tt, $syntax_tree:tt) => { - use maplit::hashmap; - use std::{ - collections::HashMap, - fmt, - hash::{Hash, Hasher} - }; - use crate::{ - and_also::AndAlso, - ast::{is_variable, SyntaxLeaf, SyntaxNode}, - consistent_merge::ConsistentMerge - }; - #[derive(Clone, Debug)] - pub struct $syntax_tree { - /// The root of this syntax tree, represented as a `String`. - syntax: Option, - /// Index of the concept that the syntax may represent. - concept: Option, - node: SyntaxNode<$refcounter>, - } +use crate::{ + and_also::AndAlso, + ast::{is_variable, SyntaxLeaf, SyntaxNode}, + consistent_merge::ConsistentMerge, + mixed_concept::ConceptId, + nester::SharedReference, +}; +use maplit::hashmap; +use std::{ + fmt, + hash::{Hash, Hasher}, +}; +#[derive(Clone)] +pub struct GenericSyntaxTree { + /// The root of this syntax tree, represented as a `String`. + pub syntax: Option, + /// Index of the concept that the syntax may represent. + concept: Option, + pub node: SyntaxNode, +} - impl PartialEq for $syntax_tree { - /// `SyntaxTree`s are equal if the syntax they represent is the same. - fn eq(&self, other: &Self) -> bool { - if let (Some(ss), Some(os)) = (&self.syntax, &other.syntax) { - ss == os - } else if let (Some(sc), Some(oc)) = (&self.concept, &other.concept) { - sc == oc - } else { - self.node == other.node - } - } - } +impl std::fmt::Debug + for GenericSyntaxTree +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("GenericSyntaxTree") + .field("syntax", &self.syntax) + .field("concept", &self.concept) + .field("node", &self.node) + .finish() + } +} - impl PartialEq<$refcounter> for $syntax_tree { - /// `SyntaxTree`s are equal if the syntax they represent is the same. - fn eq(&self, other: &$refcounter) -> bool { - if let (Some(ss), Some(os)) = (&self.syntax, &other.syntax) { - ss == os - } else { - self.concept == other.concept - } - } +impl GenericSyntaxTree { + pub fn key(&self) -> SyntaxKey { + SyntaxKey { + syntax: self.syntax.clone(), + concept: self.concept, } + } +} - impl Eq for $syntax_tree {} +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct SyntaxKey { + syntax: Option, + concept: Option, +} - impl Hash for $syntax_tree { - fn hash(&self, state: &mut H) { - self.syntax.hash(state); - self.concept.hash(state); - } +impl PartialEq + for GenericSyntaxTree +{ + /// `SyntaxTree`s are equal if the syntax they represent is the same. + fn eq(&self, other: &Self) -> bool { + if let (Some(ss), Some(os)) = (&self.syntax, &other.syntax) { + ss == os + } else if let (Some(sc), Some(oc)) = (&self.concept, &other.concept) { + sc == oc + } else { + self.node == other.node } + } +} - impl fmt::Display for $syntax_tree - { - /// Displays the same as the inside of an `SyntaxTree` variant. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - self.syntax.clone().unwrap_or_else(|| self - .get_expansion() - .map( - |(left, right)| left.to_string() + " " + &right.to_string() - ) - .expect(&format!("Tried to display syntax ({:?}) without symbols", self)) - ) - ) - } - } +impl Eq for GenericSyntaxTree {} - impl From for $syntax_tree - where - S: Into, - { - fn from(syntax: S) -> Self { - let syntax = syntax.into(); - let node = if is_variable(&syntax) { - SyntaxNode::Leaf(SyntaxLeaf::Variable) - } else { - SyntaxNode::Leaf(SyntaxLeaf::Constant) - }; - Self { - syntax: Some(syntax), - concept: None, - node, - } - } - } +impl Hash for GenericSyntaxTree { + fn hash(&self, state: &mut H) { + self.syntax.hash(state); + self.concept.hash(state); + } +} + +impl fmt::Display + for GenericSyntaxTree +{ + /// Displays the same as the inside of an `SyntaxTree` variant. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}", + self.syntax.clone().unwrap_or_else(|| self + .get_expansion() + .map_or_else( + || panic!( + "Tried to display syntax ({self:?}) without symbols" + ), + |(left, right)| left.to_string() + " " + &right.to_string() + )) + ) + } +} - impl<'a, ConceptId> From<&'a $refcounter<$syntax_tree>> for &'a SyntaxNode<$refcounter<$syntax_tree>> { - fn from(syntax_tree: &'a $refcounter<$syntax_tree>) -> Self { - &syntax_tree.node - } +impl From + for GenericSyntaxTree +where + S: Into, +{ + fn from(syntax: S) -> Self { + let syntax = syntax.into(); + let node = if is_variable(&syntax) { + SyntaxNode::Leaf(SyntaxLeaf::Variable) + } else { + SyntaxNode::Leaf(SyntaxLeaf::Constant) + }; + Self { + syntax: Some(syntax), + concept: None, + node, } - use crate::ast::ExampleSubstitutions; - impl SyntaxTree for $syntax_tree { - type SharedSyntax = $refcounter; - type ConceptId = ConceptId; + } +} - fn make_mut(refcounter: &mut Self::SharedSyntax) -> &mut Self { - $refcounter::make_mut(refcounter) - } +use crate::ast::ExampleSubstitutions; - fn share(self) -> Self::SharedSyntax { - $refcounter::new(self) - } +impl GenericSyntaxTree { + pub fn make_mut(refcounter: &mut SR::Share) -> &mut Self { + SR::make_mut(refcounter) + } - fn is_leaf_variable(&self) -> bool { - matches!(self.node, SyntaxNode::Leaf(SyntaxLeaf::Variable)) - } + pub fn share(self) -> SR::Share { + SR::share(self) + } - fn new_constant_concept(concept_id: impl Into) -> Self { - let concept_id = concept_id.into(); - Self { - syntax: Some(format!("constant {concept_id}")), - concept: Some(concept_id), - node: SyntaxNode::Leaf(SyntaxLeaf::Constant), - } - } + pub const fn is_leaf_variable(&self) -> bool { + matches!(self.node, SyntaxNode::Leaf(SyntaxLeaf::Variable)) + } - fn new_quantifier_concept(concept_id: Self::ConceptId) -> Self { - Self { - syntax: Some(format!("quantifier {concept_id}")), - concept: Some(concept_id), - node: SyntaxNode::Leaf(SyntaxLeaf::Quantifier), - } - } + pub fn new_constant_concept(concept_id: impl Into) -> Self { + let concept_id = concept_id.into(); + Self { + syntax: Some(format!("constant {concept_id}")), + concept: Some(concept_id), + node: SyntaxNode::Leaf(SyntaxLeaf::Constant), + } + } - fn new_pair(left: Self::SharedSyntax, right: Self::SharedSyntax) -> Self { - Self { - syntax: None, - concept: None, - node: SyntaxNode::new_pair(left, right), - } - } + pub fn new_quantifier_concept(concept_id: CI) -> Self { + Self { + syntax: Some(format!("quantifier {concept_id}")), + concept: Some(concept_id), + node: SyntaxNode::Leaf(SyntaxLeaf::Quantifier), + } + } - fn new_leaf_variable(concept_id: Self::ConceptId) -> Self { - Self { - syntax: Some(format!("variable {concept_id}")), - concept: Some(concept_id), - node: SyntaxNode::Leaf(SyntaxLeaf::Variable), - } - } + pub fn new_pair(left: SR::Share, right: SR::Share) -> Self { + Self { + syntax: None, + concept: None, + node: SyntaxNode::new_pair(left, right), + } + } - fn bind_nonquantifier_concept(mut self, concept: impl Into) -> Self { - self.concept = Some(concept.into()); - self - } + pub fn new_leaf_variable(concept_id: CI) -> Self { + Self { + syntax: Some(format!("variable {concept_id}")), + concept: Some(concept_id), + node: SyntaxNode::Leaf(SyntaxLeaf::Variable), + } + } - fn bind_nonquantifier_concept_as_ref(&mut self, concept: Self::ConceptId) { - self.concept = Some(concept); - } + pub fn bind_nonquantifier_concept( + mut self, + concept: impl Into, + ) -> Self { + self.concept = Some(concept.into()); + self + } - fn bind_quantifier_concept(mut self, concept: Self::ConceptId) -> Self { - debug_assert_eq!(self.node, SyntaxNode::Leaf(SyntaxLeaf::Constant)); - self.concept = Some(concept); - self.node = SyntaxNode::Leaf(SyntaxLeaf::Quantifier); - self - } + pub fn bind_nonquantifier_concept_as_ref(&mut self, concept: CI) { + self.concept = Some(concept); + } - fn contains(&self, other: &Self) -> bool { - if let Some((ref left, ref right)) = self.get_expansion() { - other == left - || other == right - || left.contains(other) - || right.contains(other) - } else { - false - } - } + pub fn bind_quantifier_concept(mut self, concept: CI) -> Self { + debug_assert_eq!(self.node, SyntaxNode::Leaf(SyntaxLeaf::Constant)); + self.concept = Some(concept); + self.node = SyntaxNode::Leaf(SyntaxLeaf::Quantifier); + self + } - /// An expression does have an expansion while a symbol does not. - fn get_expansion(&self) -> Option<(Self::SharedSyntax, Self::SharedSyntax)> { - if let SyntaxNode::Branch { - left, - right, - .. - } = &self.node - { - Some((left.clone(), right.clone())) - } else { - None - } - } + pub fn contains(&self, other: &Self) -> bool { + if let Some((ref left, ref right)) = self.get_expansion() { + other.key() == left.key() + || other.key() == right.key() + || left.contains(other) + || right.contains(other) + } else { + false + } + } - fn get_expansion_mut(&mut self) -> Option<(&mut Self, &mut Self)> { - if let SyntaxNode::Branch { - left, - right, - .. - } = &mut self.node - { - Some(($refcounter::make_mut(left), $refcounter::make_mut(right))) - } else { - None - } - } + /// An expression does have an expansion while a symbol does not. + pub fn get_expansion(&self) -> Option<(SR::Share, SR::Share)> { + if let SyntaxNode::Branch { + left, + right, + .. + } = &self.node + { + Some((left.clone(), right.clone())) + } else { + None + } + } + + pub fn get_expansion_mut(&mut self) -> Option<(&mut Self, &mut Self)> { + if let SyntaxNode::Branch { + left, + right, + .. + } = &mut self.node + { + Some((SR::make_mut(left), SR::make_mut(right))) + } else { + None + } + } - fn bind_pair(mut self, left: Self::SharedSyntax, right: Self::SharedSyntax) -> Self { - self.node = SyntaxNode::new_pair(left, right); - self - } + pub fn bind_pair( + mut self, + left: SR::Share, + right: SR::Share, + ) -> Self { + self.node = SyntaxNode::new_pair(left, right); + self + } - fn get_concept(&self) -> Option { - self.concept - } + pub const fn get_concept(&self) -> Option { + self.concept + } - fn is_variable(&self) -> bool { - match &self.node { - SyntaxNode::Branch { - free_variables, - binding_variables, - .. - } => !free_variables.is_empty() || !binding_variables.is_empty(), - SyntaxNode::Leaf(SyntaxLeaf::Variable) => true, - SyntaxNode::Leaf(_) => false, - } - } + pub fn is_variable(&self) -> bool { + match &self.node { + SyntaxNode::Branch { + free_variables, + binding_variables, + .. + } => !free_variables.is_empty() || !binding_variables.is_empty(), + SyntaxNode::Leaf(SyntaxLeaf::Variable) => true, + SyntaxNode::Leaf(_) => false, + } + } - fn check_example( - example: &Self::SharedSyntax, - generalisation: &Self::SharedSyntax, - ) -> Option> { - match (example.get_expansion(), generalisation.get_expansion()) { + pub fn check_example( + example: &SR::Share, + generalisation: &SR::Share, + ) -> Option> { + match (example.get_expansion(), generalisation.get_expansion()) { ( Some((left_example, right_example)), Some((left_gen, right_gen)), @@ -238,25 +258,21 @@ macro_rules! impl_syntax_tree { (Some(_), None) => generalisation .is_variable() .then(|| ExampleSubstitutions{ - generalisation: hashmap! {generalisation.clone() => example.clone()}, + generalisation: hashmap! {generalisation.key() => example.clone()}, example: hashmap!{} }), (None, Some(_)) => None, (None, None) => generalisation .is_variable() .then(|| ExampleSubstitutions{ - generalisation: hashmap! {generalisation.clone() => example.clone()}, + generalisation: hashmap! {generalisation.key() => example.clone()}, example: hashmap!{} }) .or_else(|| example.get_concept().and_then(|id| example.is_variable().then(|| ExampleSubstitutions{ generalisation: hashmap! {}, example: hashmap!{id => generalisation.clone()} }))) - .or_else(|| (example == generalisation).then(|| ExampleSubstitutions::default())), + .or_else(|| (example.key() == generalisation.key()).then(ExampleSubstitutions::default)), } - } - } - }; + } } - -pub(crate) use impl_syntax_tree; diff --git a/zia/src/ast/mod.rs b/zia/src/ast/mod.rs index 14ec6d79..7ff68fa7 100644 --- a/zia/src/ast/mod.rs +++ b/zia/src/ast/mod.rs @@ -20,9 +20,8 @@ mod node; mod r#trait; pub use node::{Node as SyntaxNode, SyntaxLeaf}; -pub(crate) use r#macro::impl_syntax_tree; -pub use r#trait::{ExampleSubstitutions, SyntaxTree}; - +pub use r#macro::{GenericSyntaxTree, SyntaxKey}; +pub use r#trait::ExampleSubstitutions; pub fn is_variable(string: &str) -> bool { string.starts_with('_') && string.ends_with('_') && !string.contains(' ') } diff --git a/zia/src/ast/node.rs b/zia/src/ast/node.rs index c7782f69..ef0271c5 100644 --- a/zia/src/ast/node.rs +++ b/zia/src/ast/node.rs @@ -1,18 +1,42 @@ -use std::{collections::HashSet, fmt::Debug, hash::Hash}; +use std::{collections::HashSet, fmt::Debug}; -#[derive(Clone, Debug)] -pub enum Node { +use crate::{mixed_concept::ConceptId, nester::SharedReference}; + +use super::{GenericSyntaxTree, SyntaxKey}; + +#[derive(Clone)] +pub enum Node { /// This syntax tree may branch to two subtrees Branch { - left: SharedSyntax, - right: SharedSyntax, - free_variables: HashSet, - binding_variables: HashSet, + left: SR::Share>, + right: SR::Share>, + free_variables: HashSet>, + binding_variables: HashSet>, }, /// or have no descendants Leaf(SyntaxLeaf), } +impl Debug for Node { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Branch { + left, + right, + free_variables, + binding_variables, + } => f + .debug_struct("Branch") + .field("left", &left.as_ref()) + .field("right", &right.as_ref()) + .field("free_variables", free_variables) + .field("binding_variables", binding_variables) + .finish(), + Self::Leaf(arg0) => f.debug_tuple("Leaf").field(arg0).finish(), + } + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SyntaxLeaf { Variable, @@ -21,7 +45,7 @@ pub enum SyntaxLeaf { } // the variables fields can be derived from left and right so no need to check them for equality -impl PartialEq for Node { +impl PartialEq for Node { fn eq(&self, other: &Self) -> bool { match (self, other) { ( @@ -35,7 +59,10 @@ impl PartialEq for Node { right: other_right, .. }, - ) => left == other_left && right == other_right, + ) => { + left.key() == other_left.key() + && right.key() == other_right.key() + }, (Self::Leaf(leaf), Self::Leaf(other_leaf)) => leaf == other_leaf, ( Self::Leaf(_), @@ -53,15 +80,14 @@ impl PartialEq for Node { } } -impl Node -where - SharedSyntax: Clone + Eq + Hash, - for<'a> &'a Self: From<&'a SharedSyntax>, -{ - pub fn new_pair(left: SharedSyntax, right: SharedSyntax) -> Self { - let mut free_variables = HashSet::::new(); - let mut binding_variables = HashSet::::new(); - let right_node: &Self = (&right).into(); +impl Node { + pub fn new_pair( + left: SR::Share>, + right: SR::Share>, + ) -> Self { + let mut free_variables = HashSet::>::new(); + let mut binding_variables = HashSet::>::new(); + let right_node: &Self = &right.node; let right_is_quantifier = match right_node { Self::Branch { free_variables: fv, @@ -73,13 +99,13 @@ where false }, Self::Leaf(SyntaxLeaf::Variable) => { - free_variables.insert(right.clone()); + free_variables.insert(right.key()); false }, Self::Leaf(SyntaxLeaf::Constant) => false, Self::Leaf(SyntaxLeaf::Quantifier) => true, }; - let left_node: &Self = (&left).into(); + let left_node: &Self = &left.node; match left_node { Self::Branch { free_variables: fv, @@ -93,9 +119,9 @@ where }, Self::Leaf(SyntaxLeaf::Variable) => { if right_is_quantifier { - binding_variables.insert(left.clone()); + binding_variables.insert(left.key()); } else { - free_variables.insert(left.clone()); + free_variables.insert(left.key()); } }, Self::Leaf(_) => {}, diff --git a/zia/src/ast/trait.rs b/zia/src/ast/trait.rs index 7f3460bd..e3369d5b 100644 --- a/zia/src/ast/trait.rs +++ b/zia/src/ast/trait.rs @@ -1,91 +1,20 @@ -use std::{ - borrow::Borrow, - fmt::{Debug, Display}, - hash::Hash, - ops::Deref, -}; - use maplit::hashmap; use crate::{ and_also::AndAlso, consistent_merge::ConsistentMerge, + mixed_concept::ConceptId, nester::SharedReference, substitute::Substitutions, variable_mask_list::VariableMask, }; -pub trait SyntaxTree -where - Self: Clone - + Debug - + Display - + Eq - + for<'a> From<&'a str> - + From - + Hash - + PartialEq, -{ - type SharedSyntax: AsRef - + Borrow - + Clone - + Debug - + Deref - + Display - + Eq - + Hash; - type ConceptId: Copy + Debug + Display + Eq + Hash; - fn share(self) -> Self::SharedSyntax; - - fn make_mut(refcounter: &mut Self::SharedSyntax) -> &mut Self; - - fn is_leaf_variable(&self) -> bool; - - fn new_constant_concept(concept_id: impl Into) -> Self; - - fn new_quantifier_concept(concept_id: Self::ConceptId) -> Self; - - fn new_pair(left: Self::SharedSyntax, right: Self::SharedSyntax) -> Self; - - fn new_leaf_variable(concept_id: Self::ConceptId) -> Self; - - fn bind_nonquantifier_concept( - self, - concept: impl Into, - ) -> Self; - - fn bind_nonquantifier_concept_as_ref(&mut self, concept: Self::ConceptId); - - fn bind_quantifier_concept(self, concept: Self::ConceptId) -> Self; - - fn contains(&self, other: &Self) -> bool; - - /// An expression does have an expansion while a symbol does not. - fn get_expansion(&self) - -> Option<(Self::SharedSyntax, Self::SharedSyntax)>; - - fn get_expansion_mut(&mut self) -> Option<(&mut Self, &mut Self)>; - - fn bind_pair( - self, - left: Self::SharedSyntax, - right: Self::SharedSyntax, - ) -> Self; - - fn get_concept(&self) -> Option; - - fn is_variable(&self) -> bool; - - fn check_example( - example: &Self::SharedSyntax, - generalisation: &Self::SharedSyntax, - ) -> Option>; -} - -#[derive(Clone, Debug)] -pub struct ExampleSubstitutions { - pub generalisation: Substitutions, - pub example: VariableMask, +#[derive(Clone)] +pub struct ExampleSubstitutions { + pub generalisation: Substitutions, + pub example: VariableMask, } -impl Default for ExampleSubstitutions { +impl Default + for ExampleSubstitutions +{ fn default() -> Self { Self { generalisation: hashmap! {}, @@ -94,16 +23,25 @@ impl Default for ExampleSubstitutions { } } -impl ConsistentMerge for ExampleSubstitutions { +impl ConsistentMerge + for ExampleSubstitutions +{ type Output = Self; fn consistent_merge(self, other: Self) -> Option { - self.generalisation - .consistent_merge(other.generalisation) - .and_also_move(self.example.consistent_merge(other.example)) - .map(|(generalisation, example)| Self { - generalisation, - example, - }) + as ConsistentMerge>::consistent_merge( + self.generalisation, + other.generalisation, + ) + .and_also_move( + as ConsistentMerge>::consistent_merge( + self.example, + other.example, + ), + ) + .map(|(generalisation, example)| Self { + generalisation, + example, + }) } } diff --git a/zia/src/concepts/mod.rs b/zia/src/concepts/mod.rs index da4dba27..d5ad0c88 100755 --- a/zia/src/concepts/mod.rs +++ b/zia/src/concepts/mod.rs @@ -208,7 +208,7 @@ impl Concept { { binding_variables.clone_from(&cp.binding_variables); free_variables.clone_from(&cp.free_variables); - }; + } ap.composition = MaybeComposition::Composition(CompositePart { binding_variables, free_variables, @@ -273,7 +273,7 @@ impl Concept { { binding_variables.clone_from(&cp.binding_variables); free_variables.clone_from(&cp.free_variables); - }; + } ap.composition = MaybeComposition::Composition(CompositePart { binding_variables, free_variables, @@ -736,11 +736,10 @@ pub enum ConcreteConceptType { Associativity, Right, Left, - Precedence, - Default, GreaterThan, Implication, ExistsSuchThat, + Preceeds, } impl From for SpecificPart { @@ -960,7 +959,7 @@ impl MaybeComposition { c.righthand = righthand; }, (Self::Leaf(_), None) => {}, - }; + } self } @@ -995,7 +994,7 @@ impl MaybeComposition { }, Self::Leaf(LeafCharacter::Constant) => {}, } - }; + } if let SpecificPart::Abstract(ap) = &left.specific_part { match &ap.composition { Self::Composition(cp) => { diff --git a/zia/src/concepts/trait.rs b/zia/src/concepts/trait.rs index 20fd6fed..87429b44 100644 --- a/zia/src/concepts/trait.rs +++ b/zia/src/concepts/trait.rs @@ -87,7 +87,11 @@ pub trait Concept: Sized { fn anonymous_variable(&self) -> bool; fn remove_reduction(&self) -> ZiaResult { - self.get_reduction().ok_or(ZiaError::RedundantReduction) + self.get_reduction().ok_or(ZiaError::RedundantReduction { + syntax: self + .get_string() + .unwrap_or_else(|| "anonymous".to_string()), + }) } fn find_what_reduces_to_it(&self) -> Self::IdIterator<'_>; diff --git a/zia/src/consistent_merge.rs b/zia/src/consistent_merge.rs index 4a4e304b..1bdcf275 100644 --- a/zia/src/consistent_merge.rs +++ b/zia/src/consistent_merge.rs @@ -1,18 +1,21 @@ -use std::{ - collections::{hash_map::Entry, HashMap}, - hash::Hash, - mem::swap, +use std::{collections::hash_map::Entry, mem::swap}; + +use crate::{ + mixed_concept::ConceptId, nester::SharedReference, + substitute::Substitutions, variable_mask_list::VariableMask, }; -pub trait ConsistentMerge: Sized { +pub trait ConsistentMerge: Sized { type Output; fn consistent_merge(self, other: Self) -> Option; } -impl ConsistentMerge for HashMap { +impl ConsistentMerge + for Substitutions +{ type Output = Self; - fn consistent_merge(self, other: Self) -> Option { + fn consistent_merge(self, other: Self) -> Option { let mut small = self; let mut large = other; if small.len() > large.len() { @@ -21,7 +24,7 @@ impl ConsistentMerge for HashMap { for (key, value) in small { match large.entry(key) { Entry::Occupied(e) => { - if e.get() != &value { + if e.get().key() != value.key() { // inconsistent return None; } @@ -34,28 +37,27 @@ impl ConsistentMerge for HashMap { Some(large) } } - -impl ConsistentMerge - for &HashMap +impl ConsistentMerge + for VariableMask { - type Output = HashMap; + type Output = Self; - fn consistent_merge(self, other: Self) -> Option { - let (small, mut large) = if self.len() > other.len() { - (other, self.clone()) - } else { - (self, other.clone()) - }; + fn consistent_merge(self, other: Self) -> Option { + let mut small = self; + let mut large = other; + if small.len() > large.len() { + swap(&mut small, &mut large); + } for (key, value) in small { - match large.entry(key.clone()) { + match large.entry(key) { Entry::Occupied(e) => { - if e.get() != value { + if e.get().key() != value.key() { // inconsistent return None; } }, Entry::Vacant(e) => { - e.insert(value.clone()); + e.insert(value); }, } } diff --git a/zia/src/context.rs b/zia/src/context.rs index f593fe00..439de73b 100755 --- a/zia/src/context.rs +++ b/zia/src/context.rs @@ -15,25 +15,22 @@ // along with this program. If not, see . use crate::{ - and_also::AndAlso, associativity::Associativity, - ast::SyntaxTree, + ast::{GenericSyntaxTree, SyntaxKey, SyntaxLeaf}, concepts::{ConceptTrait, ConcreteConceptType}, - context_cache::{self, ContextCache}, + context_cache::{GenericCache, SharedSyntax}, context_delta::{ DirectConceptDelta, NestedDelta, NewConceptDelta, SharedDelta, }, - context_search::{Comparison, ContextReferences, ContextSearch}, + context_search::{ContextReferences, ContextSearch}, context_updater::ContextUpdater, delta::Apply, errors::{ZiaError, ZiaResult}, lexer::{Category as LexemeCategory, ConceptKind, Lexeme}, map_err_variant::MapErrVariant, - mixed_concept::MixedConcept, - parser::parse_line, - reduction_reason::{ReductionReason, SharedSyntax, Syntax}, + mixed_concept::{ConceptId, MixedConcept}, + nester::{NestedSyntaxTree, Node, SharedReference}, snap_shot::Reader as SnapShotReader, - variable_mask_list::VariableMaskList, }; use std::{ collections::{HashMap, HashSet}, @@ -42,26 +39,25 @@ use std::{ marker::PhantomData, }; -pub struct Context +pub struct Context where - S: SnapShotReader + Default + Sync + Apply + Debug, - Syntax: SyntaxTree, - C: Default + ContextCache, - for<'a> <::RR as ReductionReason>::Syntax: std::convert::From<&'a std::string::String>, + S: SnapShotReader + + Default + + Sync + + Apply + + Debug, SDCD: Clone + Debug - + AsRef> - + From>, - VML: VariableMaskList>, - D: SharedDelta>, + + AsRef> + + From>, + D: SharedDelta>, { snap_shot: S, delta: D, - cache: C, - new_variable_concepts_by_label: HashMap, - bounded_variable_syntax: HashSet>, - phantom2: PhantomData, - phantom: PhantomData + cache: GenericCache, + new_variable_concepts_by_label: HashMap, + bounded_variable_syntax: HashSet>, + phantom: PhantomData, } #[derive(Debug, PartialEq, Eq)] @@ -69,44 +65,48 @@ pub struct TokenSubsequence { pub syntax: Vec, pub positions: Vec, } -impl Clone for Context +impl Clone + for Context where - S: SnapShotReader + Default + Sync + Apply + Debug + Clone, - Syntax: SyntaxTree, - C: Default + ContextCache, - for<'a> <::RR as ReductionReason>::Syntax: std::convert::From<&'a std::string::String>, + S: SnapShotReader + + Default + + Sync + + Apply + + Debug + + Clone, SDCD: Clone + Debug - + AsRef> - + From>, - VML: VariableMaskList>, - D: SharedDelta>, + + AsRef> + + From>, + D: SharedDelta>, { fn clone(&self) -> Self { Self { delta: D::default(), - phantom2: self.phantom2, phantom: self.phantom, bounded_variable_syntax: self.bounded_variable_syntax.clone(), cache: self.cache.clone(), - new_variable_concepts_by_label: self.new_variable_concepts_by_label.clone(), - snap_shot: self.snap_shot.clone() + new_variable_concepts_by_label: self + .new_variable_concepts_by_label + .clone(), + snap_shot: self.snap_shot.clone(), } } } -impl Context +impl + Context where - S: SnapShotReader + Default + Sync + Apply + Debug, - Syntax: SyntaxTree, - C: Default + ContextCache, - for<'a> <::RR as ReductionReason>::Syntax: std::convert::From<&'a std::string::String>, + S: SnapShotReader + + Default + + Sync + + Apply + + Debug, SDCD: Clone + Debug - + AsRef> - + From>, - VML: VariableMaskList>, - D: SharedDelta>, + + AsRef> + + From>, + D: SharedDelta>, { pub fn new() -> ZiaResult { let mut cont = Self::default(); @@ -114,7 +114,7 @@ where Ok(cont) } - pub fn lex(&self, command: &str) -> Vec { + pub fn lex(&self, command: &str) -> Vec> { let mut lexemes = vec![]; let mut opening_parentheses_positions = vec![]; for character in command.chars() { @@ -186,22 +186,84 @@ where lexemes } - fn concept_kind_from_symbol(&self, symbol: &str) -> ConceptKind { + pub(crate) fn nest( + lexemes: Vec>, + ) -> ZiaResult> { + let mut nested_syntax_at_depth = + HashMap::>::new(); + let mut nest_depth = 0; + for lexeme in lexemes { + match lexeme.category { + LexemeCategory::Whitespace => continue, + LexemeCategory::Concept(c) => { + let new_nested_syntax = + NestedSyntaxTree::from_concept_kind(&c, lexeme.text); + let nested_syntax = + match nested_syntax_at_depth.remove(&nest_depth) { + None => new_nested_syntax, + Some(ns) => ns.append_node(new_nested_syntax), + }; + let existing_value = nested_syntax_at_depth + .insert(nest_depth, nested_syntax); + assert!(existing_value.is_none(), "A value for the nested_syntax at depth {nest_depth} previously exists"); + }, + LexemeCategory::OpeningParenthesis { + .. + } => { + nest_depth += 1; + }, + LexemeCategory::ClosingParenthesis { + .. + } => { + let Some(mut nested_syntax) = + nested_syntax_at_depth.remove(&nest_depth) + else { + return Err(ZiaError::EmptyParentheses); + }; + if nest_depth == 0 { + return Err(ZiaError::UnmatchedParentheses); + } + nest_depth -= 1; + if let Some(ns) = nested_syntax_at_depth.remove(&nest_depth) + { + nested_syntax = ns.append_node(nested_syntax.nest()); + } else { + nested_syntax = nested_syntax.nest(); + }; + + nested_syntax_at_depth.insert(nest_depth, nested_syntax); + }, + } + } + if nest_depth != 0 { + return Err(ZiaError::UnmatchedParentheses); + } + let Some(nested_syntax) = nested_syntax_at_depth.remove(&0) else { + return Err(ZiaError::EmptyExpression); + }; + Ok(nested_syntax) + } + + fn concept_kind_from_symbol(&self, symbol: &str) -> ConceptKind { if symbol.starts_with('_') && symbol.ends_with('_') { return ConceptKind::Variable; } self.snap_shot.concept_from_label(self.delta.as_ref(), symbol).map_or( ConceptKind::New, |id| { - if self + if let Some(concrete_type) = self .snap_shot .read_concept(self.delta.as_ref(), id) .get_concrete_concept_type() - .is_some() { - ConceptKind::Concrete + ConceptKind::Concrete { + id, + concrete_type, + } } else { - ConceptKind::Abstract + ConceptKind::Abstract { + id, + } } }, ) @@ -214,12 +276,18 @@ where string.unwrap() } - fn execute_without_closing_scope(&mut self, command: &str) -> ZiaResult { + fn execute_without_closing_scope( + &mut self, + command: &str, + ) -> ZiaResult { let string = self .ast_from_expression(command) .and_then(|mut a| { a = self.context_search().expand(&a); - self.create_variable_concepts(Syntax::::make_mut(&mut a)).unwrap(); + self.create_variable_concepts( + GenericSyntaxTree::::make_mut(&mut a), + ) + .unwrap(); self.call(&a) }) .unwrap_or_else(|e| e.to_string()); @@ -227,7 +295,10 @@ where Ok(string) } - pub fn create_variable_concepts(&mut self, ast: &mut Syntax) -> ZiaResult<()> { + pub fn create_variable_concepts( + &mut self, + ast: &mut GenericSyntaxTree, + ) -> ZiaResult<()> { if let Some((left, right)) = ast.get_expansion_mut() { self.create_variable_concepts(left)?; self.create_variable_concepts(right)?; @@ -238,7 +309,7 @@ where .copied() .or_else(|| { let direct_delta = DirectConceptDelta::New( - if self.bounded_variable_syntax.contains(ast) { + if self.bounded_variable_syntax.contains(&ast.key()) { NewConceptDelta::BoundVariable } else { NewConceptDelta::FreeVariable @@ -262,33 +333,63 @@ where pub fn ast_from_expression( &mut self, s: &str, - ) -> ZiaResult> { - let tokens: Vec = parse_line(s)?; - self.ast_from_tokens(&tokens) + ) -> ZiaResult> { + let lexemes = self.lex(s); + let nested_syntax = Self::nest(lexemes)?; + let syntax_list = self.syntax_list_for_nested_syntax(&nested_syntax)?; + self.ast_from_syntax_list(&syntax_list) } - fn ast_from_tokens( + pub fn syntax_list_for_nested_syntax( &mut self, - tokens: &[String], - ) -> ZiaResult> { - match tokens.len() { - 0 => Err(ZiaError::EmptyParentheses), - 1 => self.ast_from_token(&tokens[0]), - 2 => self - .ast_from_pair(&tokens[0], &tokens[1]) - .map(Syntax::::share), - _ => { - let TokenSubsequence { - syntax: lp_syntax, - positions: lp_indices, - } = self.lowest_precedence_info(tokens)?; - if lp_indices.is_empty() { - return Err(ZiaError::LowestPrecendenceNotFound { - tokens: tokens.to_vec(), - }); - } - // TODO: redesign how opposing associativity is handled. Refer to this issue #69 - let assoc = + NestedSyntaxTree { + node, + syntax, + concept, + .. + }: &NestedSyntaxTree, + ) -> ZiaResult>> { + match node { + Node::Parent { + children, + } => children + .iter() + .map(|n| self.ast_from_nested_syntax(n)) + .collect(), + Node::Leaf(leaf) => { + Ok(vec![self.ast_from_syntax_leaf(*leaf, syntax, concept)?]) + }, + } + } + + /// Panics if `syntax_list.is_empty()` + pub fn ast_from_syntax_list( + &mut self, + syntax_list: &[SharedSyntax], + ) -> ZiaResult> { + match syntax_list { + [] => panic!("ast_from_syntax_list called with empty list!"), + [s] => return Ok(s.clone()), + [l, r] => { + return Ok(GenericSyntaxTree::::new_pair( + l.clone(), + r.clone(), + ) + .share()) + }, + _ => {}, + }; + let TokenSubsequence { + syntax: lp_syntax, + positions: lp_indices, + } = self.lowest_precedence_info(syntax_list)?; + if lp_indices.is_empty() { + return Err(ZiaError::LowestPrecendenceNotFound { + tokens: syntax_list.iter().map(|s| s.to_string()).collect(), + }); + } + // TODO: redesign how opposing associativity is handled. Refer to this issue #69 + let assoc = lp_syntax.iter().try_fold(None, |assoc, syntax| match ( self.context_search().get_associativity(syntax), assoc, @@ -302,51 +403,119 @@ where }, (x, None) => Ok(Some(x)), })?; - match assoc { - Some(Associativity::Right) => { - let tail = lp_indices - .iter() - .rev() - .try_fold( - Err(ZiaError::AmbiguousExpression), - |state, lp_index| { - Ok(Ok(self - .associativity_try_fold_handler( - tokens, - state.ok(), - *lp_index, - Associativity::Right, - )?)) - }, - )?? - .0; - if lp_indices[0] == 0 { - Ok(tail) - } else { - let head = - self.ast_from_tokens(&tokens[..lp_indices[0]])?; - Ok(self - .context_search() - .combine(&head, &tail) - .share()) - } - }, - Some(Associativity::Left) => lp_indices - .iter() - .try_fold(None, |state, lp_index| { - Some(self.associativity_try_fold_handler( - tokens, - state, + match assoc { + Some(Associativity::Right) => { + let tail = lp_indices + .iter() + .rev() + .try_fold( + Err(ZiaError::AmbiguousExpression), + |state, lp_index| { + Ok(Ok(self.associativity_try_fold_handler( + syntax_list, + state.ok(), *lp_index, - Associativity::Left, - )) - .transpose() - })? - .map_or( - Err(ZiaError::AmbiguousExpression), - |(syntax, _)| Ok(syntax), - ), - None => Err(ZiaError::AmbiguousExpression), + Associativity::Right, + )?)) + }, + )?? + .0; + if lp_indices[0] == 0 { + Ok(tail) + } else { + let head = self + .ast_from_syntax_list(&syntax_list[..lp_indices[0]])?; + Ok(self.context_search().combine(&head, &tail).share()) + } + }, + Some(Associativity::Left) => lp_indices + .iter() + .try_fold(None, |state, lp_index| { + Some(self.associativity_try_fold_handler( + syntax_list, + state, + *lp_index, + Associativity::Left, + )) + .transpose() + })? + .map_or(Err(ZiaError::AmbiguousExpression), |(syntax, _)| { + Ok(syntax) + }), + None => Err(ZiaError::AmbiguousExpression), + } + } + + fn ast_from_syntax_leaf( + &mut self, + l: SyntaxLeaf, + syntax: &str, + concept: &Option, + ) -> ZiaResult> { + let concept_id = concept.map_or_else( + || { + let maybe_inner_delta = self.delta.get_mut(); + let Some(delta) = maybe_inner_delta else { + return Err(ZiaError::MultiplePointersToDelta); + }; + if let Some(id) = + self.snap_shot.concept_from_label(delta, syntax) + { + return Ok(id); + } + let label_id = { + self.snap_shot + .concrete_concept_id(delta, ConcreteConceptType::Label) + }; + let mut updater = ContextUpdater { + snap_shot: &self.snap_shot, + delta, + cache: &mut self.cache, + phantom: PhantomData, + phantom2: PhantomData, + }; + Ok(updater.new_labelled_concept(syntax, None, label_id)) + }, + Ok, + )?; + let mut gst = match l { + crate::ast::SyntaxLeaf::Variable => { + GenericSyntaxTree::::new_leaf_variable(concept_id) + }, + crate::ast::SyntaxLeaf::Constant => { + GenericSyntaxTree::::new_constant_concept(concept_id) + }, + crate::ast::SyntaxLeaf::Quantifier => { + GenericSyntaxTree::::new_quantifier_concept(concept_id) + }, + }; + gst.syntax = Some(syntax.to_string()); + Ok(gst.share()) + } + + fn ast_from_nested_syntax( + &mut self, + nested_syntax: &NestedSyntaxTree, + ) -> ZiaResult> { + match &nested_syntax.node { + crate::nester::Node::Leaf(l) => self.ast_from_syntax_leaf( + *l, + &nested_syntax.syntax, + &nested_syntax.concept, + ), + crate::nester::Node::Parent { + children: nodes, + } => { + if let [left, right] = &nodes[..] { + let left_syntax = + self.ast_from_nested_syntax(left.as_ref())?; + let right_syntax = + self.ast_from_nested_syntax(right.as_ref())?; + Ok(self.ast_from_pair(&left_syntax, &right_syntax).share()) + } else { + let syntax_list = + self.syntax_list_for_nested_syntax(nested_syntax)?; + self.ast_from_syntax_list(&syntax_list) } }, } @@ -354,11 +523,11 @@ where fn associativity_try_fold_handler( &mut self, - tokens: &[String], - state: Option<(SharedSyntax, usize)>, + tokens: &[SharedSyntax], + state: Option<(SharedSyntax, usize)>, lp_index: usize, assoc: Associativity, - ) -> ZiaResult<(SharedSyntax, usize)> { + ) -> ZiaResult<(SharedSyntax, usize)> { let mut prev_lp_index = None; let mut edge = None; if let Some((e, pli)) = state { @@ -366,7 +535,7 @@ where prev_lp_index = Some(pli); } let slice = assoc.slice_tokens(tokens, prev_lp_index, lp_index); - // Required otherwise self.ast_from_tokens will return Err(ZiaError::EmprtyParentheses) + // Required otherwise self.ast_from_tokens will return Err(ZiaError::EmptyParentheses) if slice.is_empty() { return Err(ZiaError::AmbiguousExpression); } @@ -375,34 +544,36 @@ where Associativity::Right => 0, }; let lp_with_the_rest = if lp_index == edge_index { - let edge_syntax = self.ast_from_token(&slice[edge_index])?; + let edge_syntax = slice[edge_index].clone(); if slice.len() == 1 { edge_syntax } else { match assoc { Associativity::Left => { let rest_of_syntax = if slice.len() < 3 { - self.ast_from_token(&slice[slice.len() - 1])? + &slice[slice.len() - 1] } else { - self.ast_from_tokens(&slice[..slice.len() - 1])? + &self.ast_from_syntax_list( + &slice[..slice.len() - 1], + )? }; self.context_search() - .combine(&rest_of_syntax, &edge_syntax) + .combine(rest_of_syntax, &edge_syntax) }, Associativity::Right => { let rest_of_syntax = if slice.len() < 3 { - self.ast_from_token(&slice[1])? + &slice[1] } else { - self.ast_from_tokens(&slice[1..])? + &self.ast_from_syntax_list(&slice[1..])? }; self.context_search() - .combine(&edge_syntax, &rest_of_syntax) + .combine(&edge_syntax, rest_of_syntax) }, } .share() } } else { - self.ast_from_tokens(slice)? + self.ast_from_syntax_list(slice)? }; Ok(( match edge { @@ -424,112 +595,156 @@ where /// Determine the syntax and the positions in the token sequence of the concepts with the lowest precedence #[allow(clippy::too_many_lines)] pub fn lowest_precedence_info( - &self, - tokens: &[String], - ) -> ZiaResult>> { - let context_search = self.context_search(); - let (syntax, positions, _number_of_tokens) = tokens.iter().try_fold( - // Initially assume no concepts have the lowest precedence - (Vec::>::new(), Vec::::new(), None), - |(mut lowest_precedence_syntax, mut lp_indices, prev_index), - token| { - // Increment index - let this_index = prev_index.map(|x| x + 1).or(Some(0)); - let raw_syntax_of_token = Syntax::::from(token).share(); - let (precedence_of_token, syntax_of_token) = self - .snap_shot - .concept_from_label(self.delta.as_ref(), token) - .map_or_else( - || { - ( - context_search - .concrete_ast(ConcreteConceptType::Default), - raw_syntax_of_token.clone(), - ) - }, - |c| { - let syntax_of_token = self - .snap_shot - .bind_concept_to_syntax( - self.delta.as_ref(), - raw_syntax_of_token.as_ref().clone(), - c, - ) - .share(); - ( - context_search - .concrete_ast( - ConcreteConceptType::Precedence, - ) - .map(|ast| { - context_search - .combine(&ast, &syntax_of_token) - .share() - }), - syntax_of_token, - ) - }, - ); - // Compare current token's precedence with each currently assumed lowest syntax - for syntax in &lowest_precedence_syntax { - let precedence_of_syntax = if syntax.get_concept().is_some() - { - context_search - .concrete_ast(ConcreteConceptType::Precedence) - .map(|ast| { - context_search.combine(&ast, syntax).share() - }) - } else { - context_search - .concrete_ast(ConcreteConceptType::Default) - }; - match precedence_of_syntax - .and_also(&precedence_of_token) - .map_or(Comparison::Incomparable, |(pos, pot)| { - context_search.compare(pos, pot).0 - }) { - // syntax of token has an even lower precedence than some previous lowest precendence syntax - // reset lowest precedence syntax with just this one - Comparison::GreaterThan => { - return Ok(( - vec![syntax_of_token], - vec![this_index.unwrap()], - this_index, - )) - }, - // syntax of token has a higher precedence than some previous lowest precendence syntax - // keep existing lowest precedence syntax as-is - Comparison::LessThan => { - return Ok(( - lowest_precedence_syntax, - lp_indices, - this_index, - )) - }, - // syntax of token has at least an equal precedence as the previous lowest precedence syntax - // include syntax is lowest precedence syntax list - Comparison::EqualTo - | Comparison::GreaterThanOrEqualTo => { - lowest_precedence_syntax.push(syntax_of_token); - lp_indices.push(this_index.unwrap()); - return Ok(( - lowest_precedence_syntax, - lp_indices, - this_index, - )); - }, - // Cannot determine if token has higher or lower precedence than this syntax - // Check other syntax with lowest precedence - Comparison::Incomparable - | Comparison::LessThanOrEqualTo => (), + &mut self, + syntax_children: &[SR::Share>], + ) -> ZiaResult>> { + let (syntax, positions, _number_of_tokens) = + syntax_children.iter().try_fold( + // Initially assume no concepts have the lowest precedence + ( + Vec::>::new(), + Vec::::new(), + None, + ), + |(mut lowest_precedence_syntax, mut lp_indices, prev_index), + child| { + // Increment index + let this_index = prev_index.map(|x| x + 1).or(Some(0)); + let preceeds = |a, b| { + let context_search = self.context_search(); + let preceeds_syntax = context_search.concrete_ast(ConcreteConceptType::Preceeds).unwrap(); + self.concrete_type_of_ast(&context_search.recursively_reduce( + &context_search.combine( + a, + &context_search.combine( + &preceeds_syntax, + b + ).share() + ).share() + ).0) }; - } - // syntax of token has neither higher or lower precedence than the lowest precedence syntax - lowest_precedence_syntax.push(syntax_of_token); - lp_indices.push(this_index.unwrap()); - Ok((lowest_precedence_syntax, lp_indices, this_index)) - }, - )?; + // Compare current token's precedence with each currently assumed lowest syntax + if let Some(syntax) = lowest_precedence_syntax.first() { + match preceeds(syntax, child) { + Some(ConcreteConceptType::True) => { + return Ok(( + vec![child.clone()], + vec![this_index.unwrap()], + this_index, + )) + }, + Some(ConcreteConceptType::False) => { + match preceeds(child, syntax) { + Some(ConcreteConceptType::True) => { + return Ok(( + lowest_precedence_syntax, + lp_indices, + this_index, + )) + }, + Some(ConcreteConceptType::False) => { + lowest_precedence_syntax + .push(child.clone()); + lp_indices.push(this_index.unwrap()); + return Ok(( + lowest_precedence_syntax, + lp_indices, + this_index, + )); + }, + Some(cc) => panic!("_x_ preceeds _y_ evaluates to a non boolean concrete concept: {cc:?}"), + None => { + let context_search = self.context_search(); + let preceeds_syntax = context_search.concrete_ast(ConcreteConceptType::Preceeds).unwrap(); + let child_precedes_syntax = context_search.combine( + child, + &context_search.combine( + &preceeds_syntax, + syntax + ).share() + ).share(); + let true_syntax = context_search.concrete_ast(ConcreteConceptType::True).expect("true concept needs to exist"); + drop(context_search); + self.execute_reduction(&child_precedes_syntax, &true_syntax)?; + lowest_precedence_syntax + .push(child.clone()); + lp_indices.push(this_index.unwrap()); + return Ok(( + lowest_precedence_syntax, + lp_indices, + this_index, + )); + } + } + }, + // TODO: remove the need to default (assoc _x_) to right + Some(ConcreteConceptType::Right) | None => { + match preceeds(child, syntax) { + Some(ConcreteConceptType::True) => { + return Ok(( + lowest_precedence_syntax, + lp_indices, + this_index, + )) + }, + Some(ConcreteConceptType::False) => { + let context_search = self.context_search(); + let preceeds_syntax = context_search.concrete_ast(ConcreteConceptType::Preceeds).unwrap(); + let syntax_precedes_child = context_search.combine( + syntax, + &context_search.combine( + &preceeds_syntax, + child + ).share() + ).share(); + let true_syntax = context_search.concrete_ast(ConcreteConceptType::True).expect("true concept needs to exist"); + drop(context_search); + self.execute_reduction(&syntax_precedes_child, &true_syntax)?; + lowest_precedence_syntax + .push(child.clone()); + lp_indices.push(this_index.unwrap()); + return Ok(( + lowest_precedence_syntax, + lp_indices, + this_index, + )); + }, + // TODO: remove the need to default (assoc _x_) to right + Some(ConcreteConceptType::Right) | None => { + let context_search = self.context_search(); + let preceeds_syntax = context_search.concrete_ast(ConcreteConceptType::Preceeds).unwrap(); + let child_precedes_syntax = context_search.combine( + child, + &context_search.combine( + &preceeds_syntax, + syntax + ).share() + ).share(); + let true_syntax = context_search.concrete_ast(ConcreteConceptType::True).expect("true concept needs to exist"); + drop(context_search); + self.execute_reduction(&child_precedes_syntax, &true_syntax)?; + lowest_precedence_syntax + .push(child.clone()); + lp_indices.push(this_index.unwrap()); + return Ok(( + lowest_precedence_syntax, + lp_indices, + this_index, + )); + + } + Some(cc) => panic!("_x_ preceeds _y_ evaluates to a non boolean concrete concept: {cc:?}"), + } + } + Some(cc) => panic!("_x_ preceeds _y_ evaluates to a non boolean concrete concept: {cc:?}"), + } + } + // child has the lowest precendence syntax so far because the vector is empty + lowest_precedence_syntax.push(child.clone()); + lp_indices.push(this_index.unwrap()); + Ok((lowest_precedence_syntax, lp_indices, this_index)) + }, + )?; Ok(TokenSubsequence { syntax, positions, @@ -538,28 +753,16 @@ where fn ast_from_pair( &mut self, - left: &str, - right: &str, - ) -> ZiaResult> { - let lefthand = self.ast_from_token(left)?; - let righthand = self.ast_from_token(right)?; + left: &SharedSyntax, + right: &SharedSyntax, + ) -> GenericSyntaxTree { if Some(ConcreteConceptType::ExistsSuchThat) - == self.concrete_type_of_ast(&righthand) - && lefthand.is_leaf_variable() + == self.concrete_type_of_ast(right) + && left.is_leaf_variable() { - self.bounded_variable_syntax.insert(lefthand.clone()); - } - Ok(self.context_search().combine(&lefthand, &righthand)) - } - - fn ast_from_token(&mut self, t: &str) -> ZiaResult> { - if t.contains(' ') || t.contains('(') || t.contains(')') { - self.ast_from_expression(t) - } else { - let ast = - self.snap_shot.ast_from_symbol::, D>(self.delta.as_ref(), t); - Ok(ast.share()) + self.bounded_variable_syntax.insert(left.key()); } + self.context_search().combine(left, right) } fn commit(&mut self) -> ZiaResult<()> { @@ -579,11 +782,10 @@ where ("assoc", ConcreteConceptType::Associativity), ("right", ConcreteConceptType::Right), ("left", ConcreteConceptType::Left), - ("prec", ConcreteConceptType::Precedence), - ("default", ConcreteConceptType::Default), (">", ConcreteConceptType::GreaterThan), ("=>", ConcreteConceptType::Implication), ("exists_such_that", ConcreteConceptType::ExistsSuchThat), + ("preceeds", ConcreteConceptType::Preceeds), ]; let maybe_inner_delta = self.delta.get_mut(); let Some(delta) = maybe_inner_delta else { @@ -593,7 +795,8 @@ where snap_shot: &self.snap_shot, delta, cache: &mut self.cache, - phantom: PhantomData + phantom: PhantomData, + phantom2: PhantomData, }; let label_id = updater.new_labelled_concept( "label_of", @@ -617,18 +820,17 @@ where self.execute("let (false and _y_) -> false"); self.execute("let (_x_ and false) -> false"); self.execute( - "let ((_y_ exists_such_that) (_x_ > _y_) and _y_ > _z_) => _x_ > _z_", + "let ((_y_ exists_such_that) (_x_ preceeds _y_) and _y_ preceeds _z_) => _x_ preceeds _z_", ); - self.execute("let default > prec ->"); - self.execute("let (prec ->) > prec :="); - self.execute("let (prec :=) > prec let"); + self.execute("let -> preceeds :="); + self.execute("let := preceeds let"); Ok(()) } fn reduce_and_call_pair( &mut self, - left: &SharedSyntax, - right: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, ) -> ZiaResult { let reduced_left = self.context_search().reduce(left); let reduced_right = self.context_search().reduce(right); @@ -643,12 +845,13 @@ where /// If the abstract syntax tree can be reduced, then `call` is called with this reduction. If not then an `Err(ZiaError::CannotReduceFurther)` is returned fn try_reducing_then_call( &mut self, - ast: &SharedSyntax, + ast: &SharedSyntax, ) -> ZiaResult { let context_search = self.context_search(); let (normal_form, _) = &context_search.recursively_reduce(ast); - if normal_form == ast { - context_search.find_examples_of_inferred_reduction(ast) + if normal_form.key() == ast.key() { + context_search + .find_examples_of_inferred_reduction(ast) .map(|(normal_form, _)| normal_form.to_string()) .ok_or(ZiaError::CannotReduceFurther) } else { @@ -657,7 +860,7 @@ where } /// If the associated concept of the syntax tree is a string concept that that associated string is returned. If not, the function tries to expand the syntax tree. If that's possible, `call_pair` is called with the lefthand and righthand syntax parts. If not `try_expanding_then_call` is called on the tree. If a program cannot be found this way, `Err(ZiaError::NotAProgram)` is returned. - fn call(&mut self, ast: &SharedSyntax) -> ZiaResult { + fn call(&mut self, ast: &SharedSyntax) -> ZiaResult { ast.get_concept() .and_then(|c| { self.snap_shot.read_concept(self.delta.as_ref(), c).get_string() @@ -695,16 +898,13 @@ where ) } - fn concrete_type( - &self, - concept_id: &S::ConceptId, - ) -> Option { + fn concrete_type(&self, concept_id: &CCI) -> Option { self.snap_shot.concrete_concept_type(self.delta.as_ref(), *concept_id) } fn concrete_type_of_ast( &self, - ast: &SharedSyntax, + ast: &SharedSyntax, ) -> Option { ast.get_concept().and_then(|c| self.concrete_type(&c)) } @@ -712,8 +912,8 @@ where /// If the associated concept of the lefthand part of the syntax tree is LET then `call_as_righthand` is called with the left and right of the lefthand syntax. Tries to get the concept associated with the righthand part of the syntax. If the associated concept is `->` then `call` is called with the reduction of the lefthand part of the syntax. Otherwise `Err(ZiaError::NotAProgram)` is returned. fn call_pair( &mut self, - left: &SharedSyntax, - right: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, ) -> ZiaResult { self.concrete_type_of_ast(left) .and_then(|cct| match cct { @@ -730,19 +930,18 @@ where }) .or_else(|| { let cs = self.context_search(); - let maybe_ast = cs - .concrete_ast(ConcreteConceptType::True); + let maybe_ast = + cs.concrete_ast(ConcreteConceptType::True); drop(cs); - maybe_ast - .map(|ast| { - self.execute_reduction(right, &ast) - }) + maybe_ast.map(|ast| self.execute_reduction(right, &ast)) }) .map(|r| r.map(|()| String::new())), ConcreteConceptType::Label => Some(Ok("'".to_string() + &right .get_concept() - .and_then(|c| self.snap_shot.get_label(self.delta.as_ref(), c)) + .and_then(|c| { + self.snap_shot.get_label(self.delta.as_ref(), c) + }) .unwrap_or_else(|| right.to_string()) + "'")), _ => None, @@ -761,8 +960,8 @@ where /// If the righthand part of the syntax can be expanded, then `match_righthand_pair` is called. If not, `Err(ZiaError::CannotExpandFurther)` is returned. fn execute_let( &mut self, - left: &SharedSyntax, - right: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, ) -> Option> { right.get_expansion().map(|(ref rightleft, ref rightright)| { self.match_righthand_pair(left, rightleft, rightright) @@ -774,9 +973,9 @@ where /// with a concept which isn't `->` or `:=` then if this concept reduces, `match_righthand_pair` is called with this reduced concept as an abstract syntax tree. fn match_righthand_pair( &mut self, - left: &SharedSyntax, - rightleft: &SharedSyntax, - rightright: &SharedSyntax, + left: &SharedSyntax, + rightleft: &SharedSyntax, + rightright: &SharedSyntax, ) -> ZiaResult<()> { rightleft.get_concept().map_or(Err(ZiaError::UnusedSymbol), |c| { match self.concrete_type(&c) { @@ -806,8 +1005,8 @@ where /// If the new syntax is contained within the old syntax then this returns `Err(ZiaError::InfiniteComposition)`. Otherwise `define` is called. fn execute_composition( &mut self, - new: &SharedSyntax, - old: &SharedSyntax, + new: &SharedSyntax, + old: &SharedSyntax, ) -> ZiaResult<()> { if old.contains(new) { Err(ZiaError::InfiniteComposition) @@ -819,8 +1018,8 @@ where /// If the new syntax is an expanded expression then this returns `Err(ZiaError::BadComposition)`. Otherwise the result depends on whether the new or old syntax is associated with a concept and whether the old syntax is an expanded expression. fn define( &mut self, - new: &SharedSyntax, - old: &SharedSyntax, + new: &SharedSyntax, + old: &SharedSyntax, ) -> ZiaResult<()> { let maybe_inner_delta = self.delta.get_mut(); let Some(delta) = maybe_inner_delta else { @@ -830,7 +1029,8 @@ where snap_shot: &self.snap_shot, delta, cache: &mut self.cache, - phantom: PhantomData + phantom: PhantomData, + phantom2: PhantomData, }; match ( new.get_concept(), @@ -838,7 +1038,7 @@ where old.get_concept(), old.get_expansion(), ) { - (_, Some(_), None, None) => Err(ZiaError::BadComposition), + (_, Some(_), _, None) => Err(ZiaError::BadComposition), (_, None, None, None) => Err(ZiaError::RedundantRefactor), (None, _, Some(b), None) => updater.relabel(b, &new.to_string()), (None, _, Some(b), Some(_)) => { @@ -855,9 +1055,16 @@ where (None, _, None, Some((ref left, ref right))) => { updater.define_new_syntax(&new.to_string(), left, right) }, - (Some(a), _, Some(b), None) => { + (Some(a), a_comp, Some(b), None) => { if a == b { updater.cleanly_delete_composition(&a) + } else if a_comp.is_none() { + if self.snap_shot.get_concept(b).is_some() { + updater.unlabel(a)?; + updater.relabel(b, &new.to_string()) + } else { + Err(ZiaError::RedundantRefactor) + } } else { Err(ZiaError::CompositionCollision) } @@ -877,12 +1084,12 @@ where fn execute_reduction( &mut self, - syntax: &Syntax, - normal_form: &Syntax, + syntax: &SharedSyntax, + normal_form: &SharedSyntax, ) -> ZiaResult<()> { if normal_form.contains(syntax) { Err(ZiaError::ExpandingReduction) - } else if syntax == normal_form { + } else if syntax.key() == normal_form.key() { self.try_removing_reduction(syntax) } else { let maybe_inner_delta = self.delta.get_mut(); @@ -893,7 +1100,8 @@ where snap_shot: &self.snap_shot, delta, cache: &mut self.cache, - phantom: PhantomData + phantom: PhantomData, + phantom2: PhantomData, }; let syntax_concept = updater.concept_from_ast(syntax)?; let normal_form_concept = updater.concept_from_ast(normal_form)?; @@ -901,25 +1109,34 @@ where } } - fn try_removing_reduction(&mut self, syntax: &Syntax) -> ZiaResult<()> { + fn try_removing_reduction( + &mut self, + syntax: &GenericSyntaxTree, + ) -> ZiaResult<()> { let maybe_inner_delta = self.delta.get_mut(); let Some(delta) = maybe_inner_delta else { return Err(ZiaError::MultiplePointersToDelta); }; let snap_shot = &self.snap_shot; let cache = &mut self.cache; - syntax.get_concept().map_or(Err(ZiaError::RedundantReduction), |c| { - ContextUpdater { - cache, - delta, - snap_shot, - phantom: PhantomData - } - .delete_reduction(c) - }) + syntax.get_concept().map_or( + Err(ZiaError::RedundantReduction { + syntax: syntax.to_string(), + }), + |c| { + ContextUpdater { + cache, + delta, + snap_shot, + phantom: PhantomData, + phantom2: PhantomData, + } + .delete_reduction(c) + }, + ) } - fn context_search(&self) -> ContextSearch { + fn context_search(&self) -> ContextSearch { ContextSearch::from(ContextReferences { snap_shot: &self.snap_shot, delta: self.delta.clone(), @@ -929,45 +1146,46 @@ where } } -impl Default for Context +impl Default + for Context where - S: SnapShotReader + Default + Sync + Apply + Debug, - Syntax: SyntaxTree, - C: Default + ContextCache, - for<'a> <::RR as ReductionReason>::Syntax: std::convert::From<&'a std::string::String>, + S: SnapShotReader + + Default + + Sync + + Apply + + Debug, SDCD: Clone + Debug + AsRef> + From>, - VML: VariableMaskList>, - D: SharedDelta>, + D: SharedDelta>, { #[must_use] fn default() -> Self { Self { snap_shot: S::default(), delta: D::default(), - cache: C::default(), + cache: GenericCache::::default(), new_variable_concepts_by_label: HashMap::new(), bounded_variable_syntax: HashSet::new(), - phantom2: PhantomData, - phantom: PhantomData + phantom: PhantomData, } } } -impl From for Context +impl From + for Context where - S: SnapShotReader + Default + Sync + Apply + Debug, - Syntax: SyntaxTree, - C: Default + ContextCache, - for<'a> <::RR as ReductionReason>::Syntax: std::convert::From<&'a std::string::String>, + S: SnapShotReader + + Default + + Sync + + Apply + + Debug, SDCD: Clone + Debug + AsRef> + From>, - VML: VariableMaskList>, - D: SharedDelta>, + D: SharedDelta>, { fn from(snap_shot: S) -> Self { Self { diff --git a/zia/src/context_cache/macro.rs b/zia/src/context_cache/macro.rs index 9f4a939a..50f0e19f 100644 --- a/zia/src/context_cache/macro.rs +++ b/zia/src/context_cache/macro.rs @@ -1,234 +1,214 @@ #![allow(clippy::single_component_path_imports)] -macro_rules! impl_cache { - ($refcounter:tt, $cache:tt) => { - use crate::{ - ast::SyntaxTree, - concepts::ConceptTrait, - context_cache::{ContextCache, ReductionCache, InferenceCache, ConceptId, SharedSyntax}, - reduction_reason::{ReductionReason, ReductionResult} - }; - use dashmap::DashMap; - use log::debug; - #[derive(Debug, Clone)] - pub struct $cache { - pub reductions: $refcounter>, - syntax_trees: $refcounter, SharedSyntax>>, - contains_bound_variable_syntax: $refcounter, bool>>, - inferences: $refcounter> - } +use crate::{ + ast::SyntaxKey, + concepts::ConceptTrait, + context_cache::{InferenceCache, ReductionCache}, + mixed_concept::ConceptId, + nester::SharedReference, + reduction_reason::{ReductionResult, SharedSyntax}, +}; +use dashmap::DashMap; +use log::debug; +#[derive(Debug, Clone)] +pub struct GenericCache { + pub reductions: SR::Share>, + syntax_trees: SR::Share>>, + contains_bound_variable_syntax: SR::Share, bool>>, + inferences: SR::Share>, +} - impl Default for $cache { - fn default() -> Self { - Self { - reductions: $refcounter::new(ReductionCacheList::default()), - syntax_trees: $refcounter::new(DashMap::default()), - contains_bound_variable_syntax: $refcounter::new(DashMap::default()), - inferences: $refcounter::new(InferenceCacheList::default()) - } - } +impl Default for GenericCache { + fn default() -> Self { + Self { + reductions: SR::share(ReductionCacheList::default()), + syntax_trees: SR::share(DashMap::default()), + contains_bound_variable_syntax: SR::share(DashMap::default()), + inferences: SR::share(InferenceCacheList::default()), } + } +} - impl ContextCache for $cache - { - type RR = RR; - type SharedReductionCache = $refcounter>; - fn invalidate(&mut self) { - std::mem::take(self); - debug!("Cache invalidated"); - } - - fn spawn( - &self, - cache: &Self::SharedReductionCache, - ) -> Self { - Self { - reductions: self.reductions.spawn(cache.clone()), - inferences: self.inferences.clone(), - ..Self::default() - } - } - - fn remember_if_contains_bound_variable_syntax_or_else( - &self, - syntax: &SharedSyntax, - f: impl Fn() -> bool, - ) -> bool { - self.contains_bound_variable_syntax.get(syntax).map_or_else(f, |v| *v) - } - - fn get_syntax_tree_or_else( - &self, - concept_id: ConceptId, - build_syntax: impl Fn() -> SharedSyntax + Copy, - ) -> <::Syntax as SyntaxTree>::SharedSyntax { - self.syntax_trees - .get(&concept_id) - .map_or_else(build_syntax, |v| v.clone()) - } - - fn insert_syntax_tree( - &self, - concept: &impl ConceptTrait>, - syntax_tree: &SharedSyntax, - ) - { - if !concept.anonymous_variable() { - self.syntax_trees.insert(concept.id(), syntax_tree.clone()); - } - } - - fn get_reduction_or_else( - &self, - ast: &SharedSyntax, - reduce: impl Fn() -> ReductionResult - + Copy, - ) -> ReductionResult { - self.reductions.get_reduction_or_else(ast, reduce) - } - - fn insert_reduction(&self, - ast: &SharedSyntax, - reduction_result: &ReductionResult,) { - self.reductions.insert_reduction(ast, reduction_result); - } - - fn get_inference_or_else(&self, concept: ConceptId, infer: impl Fn() -> ReductionResult + Copy) -> ReductionResult { - self.inferences.get_inference_or_else(concept, infer) - } - - fn insert_inference(&self, concept: ConceptId, rr: &ReductionResult) { - self.inferences.insert_inference(concept, rr) - } - } +impl GenericCache { + pub fn invalidate(&mut self) { + std::mem::take(self); + debug!("Cache invalidated"); + } - #[derive(Debug, Clone)] - pub struct InferenceCacheList { - head: $refcounter>, - tail: Option<$refcounter>, + pub fn spawn(&self, cache: &SR::Share>) -> Self { + Self { + reductions: ReductionCacheList::::spawn( + &self.reductions, + cache.clone(), + ), + inferences: self.inferences.clone(), + ..Self::default() } + } - impl Default for InferenceCacheList - { - fn default() -> Self { - Self { - head: $refcounter::new(InferenceCache::::default()), - tail: None, - } - } - } + pub fn remember_if_contains_bound_variable_syntax_or_else( + &self, + syntax: &SharedSyntax, + f: impl Fn() -> bool, + ) -> bool { + self.contains_bound_variable_syntax + .get(&syntax.key()) + .map_or_else(f, |v| *v) + } - impl<'a, RR: ReductionReason> - From<$refcounter>> - for InferenceCacheList - { - fn from( - head: $refcounter>, - ) -> Self { - Self { - head, - tail: None, - } - } - } + pub fn get_syntax_tree_or_else( + &self, + concept_id: CI, + build_syntax: impl Fn() -> SharedSyntax + Copy, + ) -> SharedSyntax { + self.syntax_trees + .get(&concept_id) + .map_or_else(build_syntax, |v| v.clone()) + } - impl InferenceCacheList { - pub fn get_inference_or_else( - &self, - concept: ConceptId, - reduce: impl Fn() -> ReductionResult - + Copy, - ) -> ReductionResult { - self.head.get(&concept).map_or_else( - || { - self.tail.as_ref().map_or_else(reduce, |ccl| { - ccl.get_inference_or_else(concept, reduce) - }) - }, - |r| r.as_ref().cloned(), - ) - } - - pub fn insert_inference( - &self, - concept: ConceptId, - reduction_result: &ReductionResult, - ) { - self.head.insert(concept, reduction_result.clone()); - } + pub fn insert_syntax_tree( + &self, + concept: &impl ConceptTrait, + syntax_tree: &SharedSyntax, + ) { + if !concept.anonymous_variable() { + self.syntax_trees.insert(concept.id(), syntax_tree.clone()); } + } + + pub fn get_reduction_or_else( + &self, + ast: &SharedSyntax, + reduce: impl Fn() -> ReductionResult + Copy, + ) -> ReductionResult { + self.reductions.get_reduction_or_else(ast, reduce) + } + + pub fn insert_reduction( + &self, + ast: &SharedSyntax, + reduction_result: &ReductionResult, + ) { + self.reductions.insert_reduction(ast, reduction_result); + } + + pub fn get_inference_or_else( + &self, + concept: CI, + infer: impl Fn() -> ReductionResult + Copy, + ) -> ReductionResult { + self.inferences.get_inference_or_else(concept, infer) + } + + pub fn insert_inference(&self, concept: CI, rr: &ReductionResult) { + self.inferences.insert_inference(concept, rr); + } +} - #[derive(Debug, Clone)] - pub struct ReductionCacheList { - head: $refcounter>, - tail: Option<$refcounter>, +#[derive(Debug, Clone)] +pub struct InferenceCacheList { + head: SR::Share>, + tail: Option>, +} + +impl Default + for InferenceCacheList +{ + fn default() -> Self { + Self { + head: SR::share(InferenceCache::::default()), + tail: None, } + } +} - impl Default for ReductionCacheList - { - fn default() -> Self { - Self { - head: $refcounter::new(ReductionCache::::default()), - tail: None, - } - } +impl InferenceCacheList { + pub fn get_inference_or_else( + &self, + concept: CI, + reduce: impl Fn() -> ReductionResult + Copy, + ) -> ReductionResult { + self.head.get(&concept).map_or_else( + || { + self.tail.as_ref().map_or_else(reduce, |ccl| { + ccl.get_inference_or_else(concept, reduce) + }) + }, + |r| r.as_ref().cloned(), + ) + } + + pub fn insert_inference( + &self, + concept: CI, + reduction_result: &ReductionResult, + ) { + self.head.insert(concept, reduction_result.clone()); + } +} + +#[derive(Debug, Clone)] +pub struct ReductionCacheList { + head: SR::Share>, + tail: Option>, +} + +impl Default + for ReductionCacheList +{ + fn default() -> Self { + Self { + head: SR::share(ReductionCache::::default()), + tail: None, } + } +} - impl<'a, RR: ReductionReason> - From<$refcounter>> - for ReductionCacheList - { - fn from( - head: $refcounter>, - ) -> Self { - Self { - head, - tail: None, - } - } +impl ReductionCacheList { + #[must_use] + pub fn spawn( + shared_ref: &SR::Share, + cache: SR::Share>, + ) -> SR::Share { + SR::share(Self { + head: cache, + tail: Some(shared_ref.clone()), + }) + } + + pub const fn start_list(head: SR::Share>) -> Self { + Self { + head, + tail: None, } + } - impl ReductionCacheList { - #[must_use] - pub fn spawn( - self: &$refcounter, - cache: $refcounter>, - ) -> $refcounter { - $refcounter::new(Self { - head: cache, - tail: Some(self.clone()), + pub fn get_reduction_or_else( + &self, + ast: &SharedSyntax, + reduce: impl Fn() -> ReductionResult + Copy, + ) -> ReductionResult { + self.head.get(&ast.key()).map_or_else( + || { + self.tail.as_ref().map_or_else(reduce, |ccl| { + ccl.get_reduction_or_else(ast, reduce) }) - } - - pub fn get_reduction_or_else( - &self, - ast: &SharedSyntax, - reduce: impl Fn() -> ReductionResult - + Copy, - ) -> ReductionResult { - self.head.get(ast).map_or_else( - || { - self.tail.as_ref().map_or_else(reduce, |ccl| { - ccl.get_reduction_or_else(ast, reduce) - }) - }, - |r| r.as_ref().cloned(), - ) - } - - pub fn insert_reduction( - &self, - ast: &SharedSyntax, - reduction_result: &ReductionResult, - ) { - if !ast.is_variable() - && reduction_result.as_ref().map_or(true, |(r, _)| r != ast) - { - self.head.insert(ast.clone(), reduction_result.clone()); - } - } + }, + |r| r.as_ref().cloned(), + ) + } + + pub fn insert_reduction( + &self, + ast: &SharedSyntax, + reduction_result: &ReductionResult, + ) { + if !ast.is_variable() + && reduction_result + .as_ref() + .map_or(true, |(r, _)| r.key() != ast.key()) + { + self.head.insert(ast.key(), reduction_result.clone()); } } } - -pub(crate) use impl_cache; diff --git a/zia/src/context_cache/mod.rs b/zia/src/context_cache/mod.rs index 5ec34993..0c57a92b 100644 --- a/zia/src/context_cache/mod.rs +++ b/zia/src/context_cache/mod.rs @@ -1,24 +1,19 @@ #![allow(clippy::redundant_pub_crate)] mod r#macro; -pub(crate) mod r#trait; use crate::{ - ast::SyntaxTree, - reduction_reason::{ReductionReason, ReductionResult}, + ast::{GenericSyntaxTree, SyntaxKey}, + nester::SharedReference, + reduction_reason::ReductionResult, }; use dashmap::DashMap; -pub(crate) use r#macro::impl_cache; -pub use r#trait::ContextCache; +pub(crate) use r#macro::GenericCache; -pub type ReductionCache = DashMap< - <::Syntax as SyntaxTree>::SharedSyntax, - ReductionResult, ->; +pub type ReductionCache = + DashMap, ReductionResult>; -pub type InferenceCache = DashMap, ReductionResult>; +pub type InferenceCache = DashMap>; -pub type ConceptId = - <::Syntax as SyntaxTree>::ConceptId; -pub type SharedSyntax = - <::Syntax as SyntaxTree>::SharedSyntax; +pub type SharedSyntax = + ::Share>; diff --git a/zia/src/context_cache/trait.rs b/zia/src/context_cache/trait.rs deleted file mode 100644 index 97a84120..00000000 --- a/zia/src/context_cache/trait.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::{ - ast::SyntaxTree, - concepts::ConceptTrait, - reduction_reason::{ReductionReason, ReductionResult}, -}; -use std::fmt::Debug; - -use super::{ConceptId, SharedSyntax}; - -pub trait ContextCache -where - Self: Clone + Debug + Default, -{ - type SharedReductionCache: Default; - type RR: ReductionReason; - fn invalidate(&mut self); - - fn spawn(&self, cache: &Self::SharedReductionCache) -> Self; - - fn remember_if_contains_bound_variable_syntax_or_else( - &self, - syntax: &SharedSyntax, - f: impl Fn() -> bool, - ) -> bool; - - fn get_syntax_tree_or_else( - &self, - concept_id: ConceptId, - build_syntax: impl Fn() -> SharedSyntax + Copy, - ) -> <::Syntax as SyntaxTree>::SharedSyntax; - - fn insert_syntax_tree( - &self, - concept: &impl ConceptTrait>, - syntax_tree: &SharedSyntax, - ); - - fn get_reduction_or_else( - &self, - ast: &SharedSyntax, - reduce: impl Fn() -> ReductionResult + Copy, - ) -> ReductionResult; - - fn insert_reduction( - &self, - ast: &SharedSyntax, - reduction_result: &ReductionResult, - ); - - fn get_inference_or_else( - &self, - concept: ConceptId, - infer: impl Fn() -> ReductionResult + Copy, - ) -> ReductionResult; - - fn insert_inference( - &self, - concept: ConceptId, - rr: &ReductionResult, - ); -} diff --git a/zia/src/context_delta.rs b/zia/src/context_delta.rs index d279a4b6..4427d111 100644 --- a/zia/src/context_delta.rs +++ b/zia/src/context_delta.rs @@ -15,22 +15,25 @@ // along with this program. If not, see . use crate::{ - ast::SyntaxTree, concepts::{ConcreteConceptType, LefthandOf, RighthandOf}, - context_cache::ContextCache, + context_cache::GenericCache, errors::ZiaResult, - mixed_concept::MixedConcept, - reduction_reason::{ReductionReason, Syntax}, + mixed_concept::{self, ConceptId, MixedConcept}, + nester::SharedReference, }; use std::{ collections::{hash_map::Entry, HashMap}, fmt::{self, Debug, Display, Formatter}, - hash::Hash, + marker::PhantomData, slice::Iter, }; #[derive(Clone)] -pub struct ContextDelta { +pub struct ContextDelta< + ConceptId: mixed_concept::ConceptId, + SharedDirectConceptDelta, + SR: SharedReference, +> { string: HashMap>, number_of_uncommitted_concepts: usize, concepts_to_apply_in_order: Vec<(ConceptId, SharedDirectConceptDelta)>, @@ -38,6 +41,7 @@ pub struct ContextDelta { ConceptId, Vec>, >, + phantom: PhantomData, } pub trait SharedDelta: @@ -50,8 +54,11 @@ pub trait SharedDelta: fn strong_count(&self) -> usize; } -impl - ContextDelta +impl< + ConceptId: mixed_concept::ConceptId, + SharedDirectConceptDelta, + SR: SharedReference, + > ContextDelta { fn new(number_of_uncommitted_concepts: usize) -> Self { Self { @@ -59,32 +66,28 @@ impl concepts_to_apply_in_order: vec![], concept: HashMap::new(), number_of_uncommitted_concepts, + phantom: PhantomData, } } } -impl - ContextDelta +impl + ContextDelta where - ConceptId: MixedConcept, - SharedDirectConceptDelta: Clone - + AsRef> - + From>, + CI: MixedConcept, + SharedDirectConceptDelta: + Clone + AsRef> + From>, { - pub fn update_concept_delta( + pub fn update_concept_delta( &mut self, - concept_delta: DirectConceptDelta, - cache_to_invalidate: &mut C, - ) -> ConceptId - where - C: ContextCache, - ::Syntax: SyntaxTree, - { + concept_delta: DirectConceptDelta, + cache_to_invalidate: &mut GenericCache, + ) -> CI { let concept_delta: SharedDirectConceptDelta = concept_delta.into(); let dcd = ConceptDelta::Direct(concept_delta.clone()); let concept_id = match concept_delta.as_ref() { DirectConceptDelta::New(delta) => { - self.update_new_concept_delta::>(delta) + self.update_new_concept_delta(delta) }, DirectConceptDelta::Compose { composition_id, @@ -179,41 +182,30 @@ where pub const fn concepts_to_apply_in_order( &self, - ) -> &Vec<(ConceptId, SharedDirectConceptDelta)> { + ) -> &Vec<(CI, SharedDirectConceptDelta)> { &self.concepts_to_apply_in_order } - pub fn get_string(&self, key: &str) -> Option<&ValueChange> { + pub fn get_string(&self, key: &str) -> Option<&ValueChange> { self.string.get(key) } pub fn get_concept( &self, - key: &ConceptId, - ) -> Option< - impl Iterator>, - > { + key: &CI, + ) -> Option>> + { self.concept.get(key).map(|v| v.iter()) } pub fn iter_concepts( &self, - ) -> impl Iterator< - Item = ( - &ConceptId, - Iter>, - ), - > { + ) -> impl Iterator>)> + { self.concept.iter().map(|(c, v)| (c, v.iter())) } - fn update_new_concept_delta( - &mut self, - delta: &NewConceptDelta, - ) -> ConceptId - where - Syntax: SyntaxTree, - { + fn update_new_concept_delta(&mut self, delta: &NewConceptDelta) -> CI { let new_concept_id = self.insert_delta_for_new_concept(delta.clone()); match delta { NewConceptDelta::FreeVariable | NewConceptDelta::BoundVariable => { @@ -307,54 +299,49 @@ where IndirectConceptDelta::ReducesFrom(new_concept_id).into(); self.insert_delta_for_existing_concept(*reduction, cd); }, - }; + } new_concept_id } fn insert_delta_for_existing_concept( &mut self, - concept_id: ConceptId, - cd: ConceptDelta, + concept_id: CI, + cd: ConceptDelta, ) { self.insert_delta_for_concept( concept_id, cd, - |last_delta, concept_id: ConceptId| { - match last_delta { - ConceptDelta::Direct(dcd) - if matches!( - dcd.as_ref(), - &DirectConceptDelta::Remove(_) - ) => - { - panic!("Concept {concept_id} already removed"); - }, - _ => (), - }; + |last_delta, concept_id: CI| match last_delta { + ConceptDelta::Direct(dcd) + if matches!( + dcd.as_ref(), + &DirectConceptDelta::Remove(_) + ) => + { + panic!("Concept {concept_id} already removed"); + }, + _ => (), }, ); } pub fn insert_delta_for_new_concept( &mut self, - cd: NewConceptDelta, - ) -> ConceptId { - // TODO: Explicitly convert to uncommitted concept - let concept_id: ConceptId = - ConceptId::uncommitted(self.number_of_uncommitted_concepts); + cd: NewConceptDelta, + ) -> CI { + let concept_id: CI = + CI::uncommitted(self.number_of_uncommitted_concepts); self.number_of_uncommitted_concepts += 1; self.insert_delta_for_concept( concept_id, ConceptDelta::Direct(DirectConceptDelta::New(cd).into()), - |last_delta, concept_id: ConceptId| { - match last_delta { - ConceptDelta::Direct(dcd) - if matches!( - dcd.as_ref(), - &DirectConceptDelta::Remove(_) - ) => {}, - _ => panic!("Concept {concept_id} already exists"), - }; + |last_delta, concept_id: CI| match last_delta { + ConceptDelta::Direct(dcd) + if matches!( + dcd.as_ref(), + &DirectConceptDelta::Remove(_) + ) => {}, + _ => panic!("Concept {concept_id} already exists"), }, ); concept_id @@ -362,12 +349,9 @@ where fn insert_delta_for_concept( &mut self, - concept_id: ConceptId, - cd: ConceptDelta, - sanity_check: impl Fn( - &ConceptDelta, - ConceptId, - ), + concept_id: CI, + cd: ConceptDelta, + sanity_check: impl Fn(&ConceptDelta, CI), ) { match self.concept.entry(concept_id) { Entry::Occupied(mut e) => { @@ -381,14 +365,14 @@ where Entry::Vacant(e) => { e.insert(vec![cd]); }, - }; + } } } -impl Debug - for ContextDelta +impl Debug + for ContextDelta where - ConceptId: Clone + Debug + Display + Eq + Hash, + CI: ConceptId, SharedDirectConceptDelta: Debug, { fn fmt( @@ -421,23 +405,24 @@ where } #[derive(Debug)] -pub struct NestedDelta +pub struct NestedDelta where - ConceptId: MixedConcept, + CI: ConceptId, SharedDirectConceptDelta: Debug, D: SharedDelta, { inner_delta: Option, - overlay_delta: ContextDelta, + overlay_delta: ContextDelta, } impl< - ConceptId, + CI, SharedDirectConceptDelta, D: SharedDelta, - > Default for NestedDelta + SR: SharedReference, + > Default for NestedDelta where - ConceptId: MixedConcept + Clone, + CI: ConceptId + Clone, SharedDirectConceptDelta: Debug, { fn default() -> Self { @@ -462,13 +447,13 @@ type BoxedTupleIterator<'a, ConceptId, SharedDirectConceptDelta> = Box< ), > + 'a, >; -impl - NestedDelta +impl + NestedDelta where - ConceptId: MixedConcept, + CI: MixedConcept, SharedDirectConceptDelta: Clone - + AsRef> - + From> + + AsRef> + + From> + Debug, D: SharedDelta, { @@ -484,7 +469,7 @@ where } } - pub fn get_string(&self, key: &str) -> Option> { + pub fn get_string(&self, key: &str) -> Option> { match ( self.inner_delta.as_ref().and_then(|d| d.as_ref().get_string(key)), self.overlay_delta.get_string(key), @@ -560,7 +545,7 @@ where pub fn iter_string( &self, - ) -> impl Iterator)> { + ) -> impl Iterator)> { // need to combine values for same key let maybe_inner_strings = self.inner_delta.as_ref().map(|d| d.as_ref().iter_string()); @@ -569,13 +554,13 @@ where .map_or_else( || { let new_box: Box< - dyn Iterator)>, + dyn Iterator)>, > = Box::new(std::iter::empty()); new_box }, |inner_strings| { let new_box: Box< - dyn Iterator)>, + dyn Iterator)>, > = Box::new(inner_strings.filter(move |(s, _)| { !self.overlay_delta.string.contains_key(*s) })); @@ -590,9 +575,9 @@ where pub fn get_concept<'a>( &'a self, - key: &'a ConceptId, + key: &'a CI, ) -> Option< - impl Iterator>, + impl Iterator>, > { let maybe_inner_concept_deltas = self.inner_delta.as_ref().and_then(|d| d.as_ref().get_concept(key)); @@ -602,10 +587,7 @@ where (Some(cd), None) => { let new_box: Box< dyn Iterator< - Item = &ConceptDelta< - ConceptId, - SharedDirectConceptDelta, - >, + Item = &ConceptDelta, >, > = Box::new(cd); Some(new_box) @@ -613,10 +595,7 @@ where (None, Some(cd)) => { let new_box: Box< dyn Iterator< - Item = &ConceptDelta< - ConceptId, - SharedDirectConceptDelta, - >, + Item = &ConceptDelta, >, > = Box::new(cd); Some(new_box) @@ -624,10 +603,7 @@ where (Some(inner_cd), Some(outer_cd)) => { let new_box: Box< dyn Iterator< - Item = &ConceptDelta< - ConceptId, - SharedDirectConceptDelta, - >, + Item = &ConceptDelta, >, > = Box::new(inner_cd.chain(outer_cd)); Some(new_box) @@ -639,52 +615,46 @@ where &'a self, ) -> impl Iterator< Item = ( - &'a ConceptId, + &'a CI, Box< dyn Iterator< - Item = &'a ConceptDelta< - ConceptId, - SharedDirectConceptDelta, - >, + Item = &'a ConceptDelta, > + 'a, >, ), > + 'a { let inner_delta = self.inner_delta.as_ref(); - let new_box: BoxedTupleIterator< - 'a, - ConceptId, - SharedDirectConceptDelta, - > = Box::new(self.overlay_delta.iter_concepts().map(move |(k, v)| { - (k, { - let inner_concept_iter = - inner_delta.and_then(|d| d.as_ref().get_concept(k)); - match inner_concept_iter { - None => { - let new_box: Box< - dyn Iterator< - Item = &ConceptDelta< - ConceptId, - SharedDirectConceptDelta, + let new_box: BoxedTupleIterator<'a, CI, SharedDirectConceptDelta> = + Box::new(self.overlay_delta.iter_concepts().map(move |(k, v)| { + (k, { + let inner_concept_iter = + inner_delta.and_then(|d| d.as_ref().get_concept(k)); + match inner_concept_iter { + None => { + let new_box: Box< + dyn Iterator< + Item = &ConceptDelta< + CI, + SharedDirectConceptDelta, + >, >, - >, - > = Box::new(v); - new_box - }, - Some(inner_concept_iter) => { - let new_box: Box< - dyn Iterator< - Item = &ConceptDelta< - ConceptId, - SharedDirectConceptDelta, + > = Box::new(v); + new_box + }, + Some(inner_concept_iter) => { + let new_box: Box< + dyn Iterator< + Item = &ConceptDelta< + CI, + SharedDirectConceptDelta, + >, >, - >, - > = Box::new(inner_concept_iter.chain(v)); - new_box - }, - } - }) - })); + > = Box::new(inner_concept_iter.chain(v)); + new_box + }, + } + }) + })); let concepts = &self.overlay_delta.concept; self.inner_delta .as_ref() @@ -692,7 +662,7 @@ where || { let new_box: BoxedTupleIterator< 'a, - ConceptId, + CI, SharedDirectConceptDelta, > = Box::new(std::iter::empty()); new_box @@ -700,7 +670,7 @@ where |d| { let new_box: BoxedTupleIterator< 'a, - ConceptId, + CI, SharedDirectConceptDelta, > = Box::new( d.as_ref() @@ -713,22 +683,18 @@ where .chain(new_box) } - pub fn update_concept_delta( + pub fn update_concept_delta( &mut self, - concept_delta: DirectConceptDelta, - cache_to_invalidate: &mut C, - ) -> ConceptId - where - C: ContextCache, - ::Syntax: SyntaxTree, - { + concept_delta: DirectConceptDelta, + cache_to_invalidate: &mut GenericCache, + ) -> CI { self.overlay_delta .update_concept_delta(concept_delta, cache_to_invalidate) } pub fn concepts_to_apply_in_order( &self, - ) -> Vec<(ConceptId, SharedDirectConceptDelta)> { + ) -> Vec<(CI, SharedDirectConceptDelta)> { let mut concepts = self .inner_delta .as_ref() @@ -740,8 +706,8 @@ where pub fn insert_delta_for_new_concept( &mut self, - cd: NewConceptDelta, - ) -> ConceptId { + cd: NewConceptDelta, + ) -> CI { self.overlay_delta.insert_delta_for_new_concept(cd) } } diff --git a/zia/src/context_search.rs b/zia/src/context_search.rs index 80fca0ab..b6ad15b5 100644 --- a/zia/src/context_search.rs +++ b/zia/src/context_search.rs @@ -17,17 +17,16 @@ use crate::{ and_also::AndAlso, associativity::Associativity, - ast::{ExampleSubstitutions, SyntaxTree}, + ast::{ExampleSubstitutions, GenericSyntaxTree, SyntaxKey}, concepts::{format_string, ConceptTrait, ConcreteConceptType, Hand}, consistent_merge::ConsistentMerge, - context_cache::ContextCache, + context_cache::{GenericCache, ReductionCache}, context_delta::{ DirectConceptDelta, NestedDelta, NewConceptDelta, SharedDelta, }, - mixed_concept::MixedConcept, - reduction_reason::{ - RRSharedSyntax, ReductionReason, ReductionResult, SharedSyntax, Syntax, - }, + mixed_concept::{ConceptId, MixedConcept}, + nester::SharedReference, + reduction_reason::{ReductionReason, ReductionResult, SharedSyntax}, snap_shot::Reader as SnapShotReader, substitute::substitute, variable_mask_list::{VariableMask, VariableMaskList}, @@ -36,48 +35,73 @@ use log::debug; use maplit::{hashmap, hashset}; use std::{collections::HashSet, fmt::Debug, iter, marker::PhantomData}; -#[derive(Debug)] -pub struct ContextSearch<'s, 'v, S, C, VML, SDCD, D, CCI: MixedConcept> -where - S: SnapShotReader + Sync + std::fmt::Debug, - C: ContextCache, - Syntax: SyntaxTree, +pub struct ContextSearch< + 's, + 'v, + S, + SDCD, + D, + CCI: ConceptId, + SR: SharedReference, +> where + S: SnapShotReader + Sync + std::fmt::Debug, SDCD: Clone + AsRef> + From> + Debug, - VML: VariableMaskList>, - D: SharedDelta>, + D: SharedDelta>, { snap_shot: &'s S, - variable_mask: VML::Shared, + variable_mask: SR::Share>, delta: D, - caches: C, - syntax_evaluating: HashSet>, + caches: GenericCache, + syntax_evaluating: HashSet>, concept_inferring: HashSet, - bound_variable_syntax: &'v HashSet>, + bound_variable_syntax: &'v HashSet>, phantom: PhantomData, phantom2: PhantomData, } +impl Debug + for ContextSearch<'_, '_, S, SDCD, D, CCI, SR> +where + S: SnapShotReader + Sync + std::fmt::Debug, + SDCD: Clone + + AsRef> + + From> + + Debug, + D: AsRef> + + SharedDelta>, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ContextSearch") + .field("snap_shot", &self.snap_shot) + .field("variable_mask", &"[variable_mask]") + .field("delta", &self.delta) + .field("caches", &"[caches]") + .field("syntax_evaluating", &self.syntax_evaluating) + .field("concept_inferring", &self.concept_inferring) + .field("bound_variable_syntax", &self.bound_variable_syntax) + .field("phantom", &self.phantom) + .field("phantom2", &self.phantom2) + .finish() + } +} -impl<'s, 'v, S, C, SDCD, VML, D, CCI: MixedConcept> - ContextSearch<'s, 'v, S, C, VML, SDCD, D, CCI> +impl<'s, 'v, S, SDCD, D, CCI: MixedConcept, SR: SharedReference> + ContextSearch<'s, 'v, S, SDCD, D, CCI, SR> where - S: SnapShotReader + Sync + std::fmt::Debug, - C: ContextCache, - Syntax: SyntaxTree, + S: SnapShotReader + Sync + std::fmt::Debug, SDCD: Clone + AsRef> + From> + Debug, - VML: VariableMaskList>, - D: AsRef> - + SharedDelta>, + D: AsRef> + + SharedDelta>, { fn infer_reduction( &self, concept: &S::MixedConcept<'_>, - ) -> ReductionResult { + ) -> ReductionResult { debug!("infer_reduction({:#?})", concept); let implication_id = self.concrete_concept_id(ConcreteConceptType::Implication)?; @@ -101,7 +125,7 @@ where ( // TODO: this should be the "true" concept only if the implication result is equivalent to the `concept` self.to_ast(&x), - C::RR::inference( + ReductionReason::::inference( self.to_ast(&implication_rule_id), reason, ), @@ -123,12 +147,12 @@ where pub fn concrete_ast( &self, cct: ConcreteConceptType, - ) -> Option> { + ) -> Option> { self.concrete_concept_id(cct).map(|id| self.to_ast(&id)) } /// Returns the syntax for the reduction of a concept. - fn reduce_concept(&self, id: &S::ConceptId) -> ReductionResult { + fn reduce_concept(&self, id: &S::ConceptId) -> ReductionResult { debug!("reduce_concept({})", id); let concept = self.snap_shot.read_concept(self.delta.as_ref(), *id); if self.concept_inferring.contains(id) { @@ -143,24 +167,24 @@ where } else { Some(self.to_ast(&n)) } - .map(|r| (r, C::RR::explicit())) + .map(|r| (r, ReductionReason::::explicit())) }) } // If (operator right) cannot by trying be reduced by other means, then it should reduce to default_concept fn reduce_otherwise_default( &self, - ast: &SharedSyntax, - left: &SharedSyntax, - right: &SharedSyntax, + ast: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, operator_id: &S::ConceptId, default_concept_id: &S::ConceptId, - ) -> ReductionResult { - let mut reduced_pair: ReductionResult = None; + ) -> ReductionResult { + let mut reduced_pair: ReductionResult = None; let mut operator_composition_check = || { - let cache = ::SharedReductionCache::default(); + let cache = SR::share(ReductionCache::::default()); let mut context_search = self.spawn(&cache, self.delta.clone()); - context_search.syntax_evaluating.insert(ast.clone()); + context_search.syntax_evaluating.insert(ast.key()); reduced_pair = context_search.reduce_pair(left, right); let operator_concept = self.snap_shot.read_concept(self.delta.as_ref(), *operator_id); @@ -170,11 +194,12 @@ where reduced_pair.is_none() && right.get_concept().and_then(find).is_none() }; - if self.syntax_evaluating.contains(ast) || operator_composition_check() + if self.syntax_evaluating.contains(&ast.key()) + || operator_composition_check() { Some(( self.to_ast(default_concept_id), - C::RR::default(*operator_id), + ReductionReason::::default(*operator_id), )) } else { reduced_pair @@ -182,7 +207,10 @@ where } /// Reduces the syntax by using the reduction rules of associated concepts. - pub fn reduce(&self, ast: &SharedSyntax) -> ReductionResult { + pub fn reduce( + &self, + ast: &SharedSyntax, + ) -> ReductionResult { debug!("reduce({})", ast.to_string()); self.caches.get_reduction_or_else(ast, || { let maybe_concept: Option = ast.get_concept(); @@ -197,19 +225,6 @@ where let (ref left, ref right) = ast.get_expansion()?; left.get_concept() .and_then(|lc| match self.concrete_type(&lc) { - Some(ConcreteConceptType::Precedence) => { - let default_concept_id = self - .concrete_concept_id( - ConcreteConceptType::Default, - )?; - self.reduce_otherwise_default( - ast, - left, - right, - &lc, - &default_concept_id, - ) - }, Some(ConcreteConceptType::Associativity) => { let default_concept_id = self .concrete_concept_id( @@ -235,9 +250,9 @@ where // Reduces a syntax tree based on the properties of the left and right branches fn reduce_pair( &self, - left: &SharedSyntax, - right: &SharedSyntax, - ) -> ReductionResult { + left: &SharedSyntax, + right: &SharedSyntax, + ) -> ReductionResult { debug!("reduce_pair({}, {})", left.to_string(), right.to_string()); right .get_expansion() @@ -257,17 +272,21 @@ where fn recursively_reduce_pair( &self, - left: &SharedSyntax, - right: &SharedSyntax, - ) -> ReductionResult { - debug!("recursively_reduce_pair({}, {})", left, right); + left: &SharedSyntax, + right: &SharedSyntax, + ) -> ReductionResult { + debug!( + "recursively_reduce_pair({}, {})", + left.as_ref(), + right.as_ref() + ); let left_result = self.reduce(left); let right_result = self.reduce(right); let maybe_subbed_r = right.get_concept().and_then(|r| self.variable_mask.get(r)); let maybe_subbed_l = left.get_concept().and_then(|l| self.variable_mask.get(l)); - let cache = ::SharedReductionCache::default(); + let cache = SR::share(ReductionCache::::default()); match (left_result, right_result) { (None, None) => { let ast = self.contract_pair(left, right); @@ -296,7 +315,7 @@ where ( context_search .substitute(&ast, &variable_mask), - C::RR::rule( + ReductionReason::::rule( self.to_ast(&generalisation), variable_mask.clone(), reason, @@ -309,15 +328,15 @@ where (Some((left_ast, left_reason)), None) => Some(( self.contract_pair(&left_ast, maybe_subbed_r.unwrap_or(right)) .share(), - C::RR::partial( - hashmap! {left.clone() => (left_ast, left_reason)}, + ReductionReason::::partial( + hashmap! {left.key() => (left_ast, left_reason)}, ), )), (None, Some((right_ast, right_reason))) => Some(( self.contract_pair(maybe_subbed_l.unwrap_or(left), &right_ast) .share(), - C::RR::partial( - hashmap! {right.clone() => (right_ast, right_reason)}, + ReductionReason::::partial( + hashmap! {right.key() => (right_ast, right_reason)}, ), )), ( @@ -325,9 +344,9 @@ where Some((right_ast, right_reason)), ) => Some(( self.contract_pair(&left_ast, &right_ast).share(), - C::RR::partial(hashmap! { - left.clone() => (left_ast, left_reason), - right.clone() => (right_ast, right_reason) + ReductionReason::::partial(hashmap! { + left.key() => (left_ast, left_reason), + right.key() => (right_ast, right_reason) }), )), } @@ -335,9 +354,9 @@ where pub fn substitute( &self, - ast: &SharedSyntax, - variable_mask: &VariableMask>, - ) -> SharedSyntax { + ast: &SharedSyntax, + variable_mask: &VariableMask, + ) -> SharedSyntax { ast.get_concept() .and_then(|c| variable_mask.get(&c).cloned()) .unwrap_or_else(|| { @@ -357,9 +376,9 @@ where /// Returns the abstract syntax from two syntax parts, using the label and concept of the composition of associated concepts if it exists. pub fn contract_pair( &self, - lefthand: &SharedSyntax, - righthand: &SharedSyntax, - ) -> Syntax { + lefthand: &SharedSyntax, + righthand: &SharedSyntax, + ) -> GenericSyntaxTree { lefthand .get_concept() .and_also(&righthand.get_concept()) @@ -369,7 +388,7 @@ where left_concept .find_as_hand_in_composition_with(*rc, Hand::Left) .map(|def| { - let syntax = Syntax::::from( + let syntax = GenericSyntaxTree::::from( self.snap_shot .get_label(self.delta.as_ref(), def) .unwrap_or_else(|| { @@ -387,7 +406,10 @@ where .bind_pair(lefthand.clone(), righthand.clone()) } - fn find_generalisations(&self, ast: &Syntax) -> HashSet { + fn find_generalisations( + &self, + ast: &GenericSyntaxTree, + ) -> HashSet { let mut generalisations = HashSet::::new(); if let Some((l, r)) = ast.get_expansion() { if let Some(c) = l.get_concept() { @@ -425,13 +447,13 @@ where /// Reduces the syntax as much as possible (returns the normal form syntax). pub fn recursively_reduce( &self, - ast: &SharedSyntax, - ) -> MaybeReducedSyntaxWithReason { - debug!("recursively_reduce({})", ast); - let mut maybe_reason: Option = None; + ast: &SharedSyntax, + ) -> (SharedSyntax, Option>) { + debug!("recursively_reduce({})", ast.as_ref()); + let mut maybe_reason: Option> = None; let mut reduced_ast = ast.clone(); while let Some((a, reason)) = self.reduce(&reduced_ast) { - maybe_reason = Some(C::RR::recursive_reason( + maybe_reason = Some(ReductionReason::::recursive_reason( maybe_reason, reason, &reduced_ast, @@ -443,10 +465,10 @@ where fn reduce_by_expanded_left_branch( &self, - leftleft: &SharedSyntax, - leftright: &SharedSyntax, - right: &SharedSyntax, - ) -> ReductionResult { + leftleft: &SharedSyntax, + leftright: &SharedSyntax, + right: &SharedSyntax, + ) -> ReductionResult { let cct = self.concrete_type_of_ast(leftright)?; match cct { ConcreteConceptType::ExistsSuchThat @@ -463,7 +485,7 @@ where let true_syntax = self.to_ast(&true_id); ( true_syntax, - C::RR::existence( + ReductionReason::::existence( substitutions.generalisation, right.clone(), ), @@ -476,17 +498,17 @@ where fn find_example( &self, - generalisation: &SharedSyntax, + generalisation: &SharedSyntax, truths: impl Iterator, - ) -> Option>> { + ) -> Option> { self.find_examples(generalisation.clone(), truths).next() } #[allow(clippy::too_many_lines)] pub fn find_examples_of_inferred_reduction( &self, - ast_to_reduce: &SharedSyntax, - ) -> ReductionResult { + ast_to_reduce: &SharedSyntax, + ) -> ReductionResult { let implication_id = self.concrete_concept_id(ConcreteConceptType::Implication)?; let reduction_operator = @@ -495,16 +517,23 @@ where let variable_reduction_id = spawned_delta .insert_delta_for_new_concept(NewConceptDelta::BoundVariable); let variable_reduction_syntax = - Syntax::::new_leaf_variable(variable_reduction_id).share(); + GenericSyntaxTree::::new_leaf_variable( + variable_reduction_id, + ) + .share(); let variable_condition_id = spawned_delta .insert_delta_for_new_concept(NewConceptDelta::BoundVariable); let variable_condition_syntax = - Syntax::::new_leaf_variable(variable_condition_id).share(); + GenericSyntaxTree::::new_leaf_variable( + variable_condition_id, + ) + .share(); let variable_result_id = spawned_delta .insert_delta_for_new_concept(NewConceptDelta::BoundVariable); let _variable_result_syntax = - Syntax::::new_leaf_variable(variable_result_id).share(); - let cache = ::SharedReductionCache::default(); + GenericSyntaxTree::::new_leaf_variable(variable_result_id) + .share(); + let cache = SR::share(ReductionCache::::default()); let mut spawned_context_search = self.spawn(&cache, D::from_nested(spawned_delta)); if let Some(concept) = ast_to_reduce.get_concept() { @@ -512,16 +541,16 @@ where } let implication_syntax = spawned_context_search.to_ast(&implication_id); let implication_rule_fn = - |condition: &SharedSyntax, - prereduction: &SharedSyntax, - reduction: &SharedSyntax| { - Syntax::::new_pair( + |condition: &SharedSyntax, + prereduction: &SharedSyntax, + reduction: &SharedSyntax| { + GenericSyntaxTree::::new_pair( condition.clone(), - Syntax::::new_pair( + GenericSyntaxTree::::new_pair( implication_syntax.clone(), - Syntax::::new_pair( + GenericSyntaxTree::::new_pair( prereduction.clone(), - Syntax::::new_pair( + GenericSyntaxTree::::new_pair( reduction_operator.clone(), reduction.clone(), ) @@ -553,7 +582,7 @@ where .find_map(|substitutions| { substitutions .generalisation - .get(&variable_condition_syntax) + .get(&variable_condition_syntax.key()) .and_then(|condition_syntax| { let substituted_condition = self.substitute( condition_syntax, @@ -568,14 +597,14 @@ where )?; substitutions .generalisation - .get(&variable_reduction_syntax) + .get(&variable_reduction_syntax.key()) .map(|result| { ( self.substitute( result, &substitutions.example, ), - C::RR::inference( + ReductionReason::::inference( implication_rule_fn( condition_syntax, ast_to_reduce, @@ -595,12 +624,10 @@ where fn find_examples<'a>( &'a self, - generalisation: SharedSyntax, + generalisation: SharedSyntax, equivalence_set: impl Iterator + 'a, /* All concepts that are equal to generalisation */ - ) -> impl Iterator>> + 'a { - let iterator: Box< - dyn Iterator>>, - >; + ) -> impl Iterator> + 'a { + let iterator: Box>>; if let Some((left, right)) = generalisation.get_expansion() { iterator = Box::new(self.find_examples_of_branched_generalisation( left, @@ -610,16 +637,16 @@ where } else { debug_assert!( self.contains_bound_variable_syntax(&generalisation), - "Generalisation ({generalisation}) doesn't contain bound variables" + "Generalisation ({}) doesn't contain bound variables", + generalisation.as_ref() ); - iterator = Box::new(equivalence_set - .map(move |c| { - let example = self.to_ast(&c); - ExampleSubstitutions { - generalisation: hashmap! {generalisation.clone() => example}, - example: hashmap!{} - } - })); + iterator = Box::new(equivalence_set.map(move |c| { + let example = self.to_ast(&c); + ExampleSubstitutions { + generalisation: hashmap! {generalisation.key() => example}, + example: hashmap! {}, + } + })); } iterator } @@ -627,47 +654,55 @@ where #[allow(clippy::too_many_lines)] fn find_examples_of_branched_generalisation<'a>( &'a self, - left: SharedSyntax, - right: SharedSyntax, + left: SharedSyntax, + right: SharedSyntax, equivalence_set: impl Iterator + 'a, - ) -> impl Iterator>> + 'a { - let iterator: Box< - dyn Iterator>>, - > = match ( - self.contains_bound_variable_syntax(&left), - self.contains_bound_variable_syntax(&right), - ) { - (true, true) => { - Box::new( - equivalence_set - .filter_map(|equivalent_concept_id| { - self.composition_of_concept(&equivalent_concept_id) - }) - .filter_map( - move |(equivalent_left_id, equivalent_right_id)| { - let equivalent_concept = - self.snap_shot.read_concept( - self.delta.as_ref(), - equivalent_left_id, - ); - // TODO handle case when a concept implicitly reduces to `equivalent_concept` - let equivalent_left_equivalence_set = - equivalent_concept - .find_what_reduces_to_it() - .chain(iter::once(equivalent_left_id)); - // TODO try to find a case where this needs to be a flat_map method call - let maybe_example = self + ) -> impl Iterator> + 'a { + let iterator: Box>> = + match ( + self.contains_bound_variable_syntax(&left), + self.contains_bound_variable_syntax(&right), + ) { + (true, true) => { + Box::new( + equivalence_set + .filter_map(|equivalent_concept_id| { + self.composition_of_concept( + &equivalent_concept_id, + ) + }) + .filter_map( + move |( + equivalent_left_id, + equivalent_right_id, + )| { + let equivalent_concept = + self.snap_shot.read_concept( + self.delta.as_ref(), + equivalent_left_id, + ); + // TODO handle case when a concept implicitly reduces to `equivalent_concept` + let equivalent_left_equivalence_set = + equivalent_concept + .find_what_reduces_to_it() + .chain(iter::once( + equivalent_left_id, + )); + // TODO try to find a case where this needs to be a flat_map method call + let maybe_example = self .find_examples( left.clone(), equivalent_left_equivalence_set, ) .find_map(|left_example| { let mut right_clone = right.clone(); - let mutable_right = - Syntax::::make_mut( - &mut right_clone, - ); - substitute::>( + let mutable_right = GenericSyntaxTree::< + CCI, + SR, + >::make_mut( + &mut right_clone + ); + substitute::( mutable_right, &left_example.generalisation, ); @@ -709,7 +744,7 @@ where ) .0 .get_concept() - .map_or(false, |id| { + .is_some_and(|id| { equivalent_right_equivalence_set .any( |equivalent_right_id| { @@ -724,41 +759,41 @@ where None } }); - maybe_example - }, - ), - ) - }, - (true, false) => Box::new( - self.find_examples_of_half_generalisation( - left.clone(), - right.clone(), - equivalence_set, - Hand::Right, - ) - .into_iter(), - ), - (false, true) => Box::new( - self.find_examples_of_half_generalisation( - right.clone(), - left.clone(), - equivalence_set, - Hand::Left, - ) - .into_iter(), - ), - (false, false) => Box::new(iter::empty()), - }; + maybe_example + }, + ), + ) + }, + (true, false) => Box::new( + self.find_examples_of_half_generalisation( + left.clone(), + right.clone(), + equivalence_set, + Hand::Right, + ) + .into_iter(), + ), + (false, true) => Box::new( + self.find_examples_of_half_generalisation( + right.clone(), + left.clone(), + equivalence_set, + Hand::Left, + ) + .into_iter(), + ), + (false, false) => Box::new(iter::empty()), + }; iterator } fn find_examples_of_half_generalisation<'a>( &'a self, - generalised_part: SharedSyntax, - non_generalised_part: SharedSyntax, + generalised_part: SharedSyntax, + non_generalised_part: SharedSyntax, mut equivalence_set_of_composition: impl Iterator + 'a, non_generalised_hand: Hand, - ) -> Option>> { + ) -> Option> { let non_generalised_part_clone = non_generalised_part.clone(); let generalised_part_clone = generalised_part; // TODO try to test if this needs to be a flat_map call @@ -787,7 +822,7 @@ where Hand::Right => (right == non_generalised_id).then_some(left)?, }; let example_hand_syntax = self.to_ast(&example_hand); - Syntax::::check_example( + GenericSyntaxTree::::check_example( &example_hand_syntax, &generalised_part_clone, ) @@ -807,10 +842,10 @@ where // Reduces a syntax tree based on the properties of the left branch and the branches of the right branch fn reduce_by_expanded_right_branch( &self, - left: &SharedSyntax, - rightleft: &SharedSyntax, - rightright: &SharedSyntax, - ) -> ReductionResult { + left: &SharedSyntax, + rightleft: &SharedSyntax, + rightright: &SharedSyntax, + ) -> ReductionResult { let cct = self.concrete_type_of_ast(rightleft)?; match cct { ConcreteConceptType::GreaterThan => { @@ -831,11 +866,12 @@ where .map(|ast| (ast, comparison_reason.into())) }, ConcreteConceptType::Reduction => { - let (x, reason) = C::RR::determine_reduction_truth( - left, - rightright, - |syntax| self.reduce(syntax), - )?; + let (x, reason) = + ReductionReason::::determine_reduction_truth( + left, + rightright, + |syntax| self.reduce(syntax), + )?; self.concrete_ast(if x { ConcreteConceptType::True } else { @@ -851,7 +887,7 @@ where pub fn to_ast( &self, concept_id: &(impl Into + Copy), - ) -> SharedSyntax { + ) -> SharedSyntax { let concept_id = (*concept_id).into(); self.variable_mask.get(concept_id).cloned().unwrap_or_else(|| { self.caches.get_syntax_tree_or_else(concept_id, || { @@ -871,7 +907,7 @@ where self.snap_shot .bind_concept_to_syntax( self.delta.as_ref(), - Syntax::::from(s), + GenericSyntaxTree::::from(s), concept_id, ) }).share(); @@ -883,9 +919,9 @@ where pub fn combine( &self, - ast: &SharedSyntax, - other: &SharedSyntax, - ) -> Syntax { + ast: &SharedSyntax, + other: &SharedSyntax, + ) -> GenericSyntaxTree { ast.get_concept() .and_also(&other.get_concept()) .and_then(|(l, r)| { @@ -907,37 +943,44 @@ where fn join( &self, - left: &SharedSyntax, - right: &SharedSyntax, - ) -> Syntax { - Syntax::::from(self.display_joint(left, right)) + left: &SharedSyntax, + right: &SharedSyntax, + ) -> GenericSyntaxTree { + GenericSyntaxTree::::from(self.display_joint(left, right)) .bind_pair(left.clone(), right.clone()) } fn display_joint( &self, - left: &SharedSyntax, - right: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, ) -> String { // TODO: find a better way of checking that a syntax tree does not a have a labeled root concept let mut left_string = left.to_string(); if left_string.chars().any(char::is_whitespace) { left_string = left.get_expansion().map_or_else( || left.to_string(), - |(l, r)| self.get_associativity(&r).display_joint_left(l, r), + |(l, r)| { + self.get_associativity(&r) + .display_joint_left(l.as_ref(), r.as_ref()) + }, ); } let mut right_string = right.to_string(); if right_string.chars().any(char::is_whitespace) { right_string = right.get_expansion().map_or(right_string, |(l, r)| { - self.get_associativity(&l).display_joint_right(l, r) + self.get_associativity(&l) + .display_joint_right(l.as_ref(), r.as_ref()) }); } left_string + " " + &right_string } - pub fn get_associativity(&self, ast: &SharedSyntax) -> Associativity { + pub fn get_associativity( + &self, + ast: &SharedSyntax, + ) -> Associativity { self.concrete_concept_id(ConcreteConceptType::Associativity).map_or( Associativity::Right, |associativity_concept_id| { @@ -959,7 +1002,7 @@ where } /// Expands syntax by definition of its associated concept. - pub fn expand(&self, ast: &SharedSyntax) -> SharedSyntax { + pub fn expand(&self, ast: &SharedSyntax) -> SharedSyntax { ast.get_concept().map_or_else( || { if let Some((ref left, ref right)) = ast.get_expansion() { @@ -986,10 +1029,10 @@ where #[allow(clippy::too_many_lines)] pub fn compare( &self, - some_syntax: &SharedSyntax, - another_syntax: &SharedSyntax, - ) -> (Comparison, ComparisonReason) { - if some_syntax == another_syntax { + some_syntax: &SharedSyntax, + another_syntax: &SharedSyntax, + ) -> (Comparison, ComparisonReason) { + if some_syntax.key() == another_syntax.key() { return (Comparison::EqualTo, ComparisonReason::SameSyntax); } @@ -1014,10 +1057,10 @@ where reason = local_reason; self.concrete_type_of_ast(&syntax_comparison) }; - let cache = ::SharedReductionCache::default(); + let cache = SR::share(ReductionCache::::default()); ( match ( - if self.syntax_evaluating.contains(&comparing_syntax) { + if self.syntax_evaluating.contains(&comparing_syntax.key()) { self.caches .get_reduction_or_else( &comparing_syntax.share(), @@ -1029,7 +1072,7 @@ where let comparing_syntax = comparing_syntax.share(); context_search .syntax_evaluating - .insert(comparing_syntax.clone()); + .insert(comparing_syntax.key()); Some( context_search .recursively_reduce(&comparing_syntax), @@ -1040,7 +1083,7 @@ where ), if self .syntax_evaluating - .contains(&comparing_reversed_syntax) + .contains(&comparing_reversed_syntax.key()) { self.caches .get_reduction_or_else( @@ -1054,7 +1097,7 @@ where comparing_reversed_syntax.share(); context_search .syntax_evaluating - .insert(comparing_reversed_syntax.clone()); + .insert(comparing_reversed_syntax.key()); Some( context_search .recursively_reduce(&comparing_reversed_syntax), @@ -1072,7 +1115,7 @@ where Some(ConcreteConceptType::True), Some(ConcreteConceptType::True), ) => { - panic!("{some_syntax:#?} is both greater than and less than {another_syntax:#?}!\nReason: {reason:#?}\n Reversed reason: {reversed_reason:#?}"); + panic!("{:#?} is both greater than and less than {:#?}!\nReason: {reason:#?}\n Reversed reason: {reversed_reason:#?}", some_syntax.as_ref(), another_syntax.as_ref()); }, (Some(ConcreteConceptType::True), _) => { Comparison::GreaterThan @@ -1088,19 +1131,16 @@ where }, _ => Comparison::Incomparable, }, - C::RR::simplify_reasoning(reason, reversed_reason), + ReductionReason::::simplify_reasoning(reason, reversed_reason), ) }) } pub fn spawn<'b, 'c>( &'b self, - cache: &'c ::SharedReductionCache, + cache: &'c SR::Share>, delta: D, - ) -> Self - where - VML: VariableMaskList, - { + ) -> Self { ContextSearch::<'s, 'v> { concept_inferring: self.concept_inferring.clone(), bound_variable_syntax: self.bound_variable_syntax, @@ -1119,12 +1159,12 @@ where /// TODO: refactor into method on struct with `self.snap_shot`, self.delta, `self.bound_variable_syntax` and `self.variable_mask` pub fn check_generalisation( &self, - ast: &SharedSyntax, + ast: &SharedSyntax, generalisation: &S::ConceptId, - ) -> Option>> { + ) -> Option> { (self.is_free_variable(generalisation) - && !self.bound_variable_syntax.contains(ast) - && !ast.get_concept().map_or(false, |c| { + && !self.bound_variable_syntax.contains(&ast.key()) + && !ast.get_concept().is_some_and(|c| { self.snap_shot .read_concept(self.delta.as_ref(), c) .bounded_variable() @@ -1140,7 +1180,7 @@ where .and_then(|(lm, mut rm)| { for (lmk, lmv) in lm { if let Some(rmv) = rm.get(&lmk) { - if rmv != &lmv { + if rmv.key() != lmv.key() { return None; } } else { @@ -1181,7 +1221,8 @@ where && self .variable_mask .tail() - .map_or(true, |vml| vml.get(*v).is_none()) // A hack required to prevent stack overflow + .map_or(true, |vml| vml.get(*v).is_none()) + // A hack required to prevent stack overflow } // TODO: move to separate struct that just has self.delta and self.snap_shot @@ -1223,7 +1264,7 @@ where // TODO: refactor into method of struct with access to self.snap_shot and self.delta fn concrete_type_of_ast( &self, - ast: &SharedSyntax, + ast: &SharedSyntax, ) -> Option { ast.get_concept().and_then(|c| self.concrete_type(&c)) } @@ -1240,15 +1281,20 @@ where /// TODO: refactor as method on `VariableMaskList` fn insert_variable_mask( &mut self, - variable_mask: VariableMask>, + variable_mask: VariableMask, ) -> Result<(), ()> { - self.variable_mask = - VML::push(&self.variable_mask, variable_mask).ok_or(())?.into(); + self.variable_mask = SR::share( + VariableMaskList::push(&self.variable_mask, variable_mask) + .ok_or(())?, + ); Ok(()) } // TODO: move to separate struct with access to self.snap_shot, self.bound_variable_syntax, self.delta and self.caches - fn contains_bound_variable_syntax(&self, syntax: &SharedSyntax) -> bool { + fn contains_bound_variable_syntax( + &self, + syntax: &SharedSyntax, + ) -> bool { self.caches.remember_if_contains_bound_variable_syntax_or_else( syntax, || { @@ -1259,8 +1305,8 @@ where return true; } } - self.bound_variable_syntax.contains(syntax) - || syntax.get_concept().map_or(false, |c| { + self.bound_variable_syntax.contains(&syntax.key()) + || syntax.get_concept().is_some_and(|c| { self.snap_shot .read_concept(self.delta.as_ref(), c) .bounded_variable() @@ -1270,8 +1316,6 @@ where } } -type MaybeReducedSyntaxWithReason = (RRSharedSyntax, Option); - #[derive(PartialEq, Debug, Eq)] pub enum Comparison { GreaterThan, @@ -1282,30 +1326,29 @@ pub enum Comparison { LessThanOrEqualTo, } -#[derive(PartialEq, Eq, Debug)] -pub enum ComparisonReason { +#[derive(PartialEq, Debug)] +pub enum ComparisonReason { SameSyntax, Reduction { - reason: Option, - reversed_reason: Option, + reason: Option>, + reversed_reason: Option>, }, NoGreaterThanConcept, } -impl<'c, 's, 'v, S, C, SDCD, VML, D, CCI: MixedConcept> - From> - for ContextSearch<'s, 'v, S, C, VML, SDCD, D, CCI> +impl Eq for ComparisonReason {} + +impl<'c, 's, 'v, S, SDCD, D, CCI: ConceptId, SR: SharedReference> + From> + for ContextSearch<'s, 'v, S, SDCD, D, CCI, SR> where - S: SnapShotReader + Sync + std::fmt::Debug, - C: ContextCache, - Syntax: SyntaxTree, + S: SnapShotReader + Sync + std::fmt::Debug, SDCD: Clone + AsRef> + From> + Debug, - VML: VariableMaskList>, - D: AsRef> - + SharedDelta>, + D: AsRef> + + SharedDelta>, { fn from( ContextReferences { @@ -1313,13 +1356,13 @@ where delta, cache, bound_variable_syntax, - }: ContextReferences<'c, 's, 'v, S, C, D>, + }: ContextReferences<'c, 's, 'v, S, D, SR, CCI>, ) -> Self { Self { concept_inferring: HashSet::default(), bound_variable_syntax, snap_shot, - variable_mask: VML::from(hashmap! {}).into(), + variable_mask: SR::share(VariableMaskList::from(hashmap! {})), delta, caches: cache.clone(), syntax_evaluating: hashset! {}, @@ -1329,11 +1372,19 @@ where } } -pub struct ContextReferences<'c, 's, 'v, S, C: ContextCache, D> { +pub struct ContextReferences< + 'c, + 's, + 'v, + S, + D, + SR: SharedReference, + CCI: ConceptId, +> { pub snap_shot: &'s S, pub delta: D, - pub cache: &'c C, - pub bound_variable_syntax: &'v HashSet>, + pub cache: &'c GenericCache, + pub bound_variable_syntax: &'v HashSet>, } pub type ReductionTruthResult = Option<(bool, RR)>; diff --git a/zia/src/context_search_test/basic_comparison.rs b/zia/src/context_search_test/basic_comparison.rs index 69611c7f..2cf3385a 100644 --- a/zia/src/context_search_test/basic_comparison.rs +++ b/zia/src/context_search_test/basic_comparison.rs @@ -5,7 +5,7 @@ use crate::{ context_search_test::ReductionReason, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -19,8 +19,9 @@ fn basic_comparison() { ConceptId, SharedDirectConceptDelta, SharedContextDelta, + _, >::default(); - let cache = MultiThreadedContextCache::default(); + let cache = MTContextCache::default(); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, diff --git a/zia/src/context_search_test/basic_composition.rs b/zia/src/context_search_test/basic_composition.rs index 64dc3c06..90580e43 100644 --- a/zia/src/context_search_test/basic_composition.rs +++ b/zia/src/context_search_test/basic_composition.rs @@ -1,12 +1,11 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -20,8 +19,9 @@ fn basic_composition() { ConceptId, SharedDirectConceptDelta, SharedContextDelta, + _, >::default(); - let cache = MultiThreadedContextCache::default(); + let cache = MTContextCache::default(); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, @@ -37,8 +37,8 @@ fn basic_composition() { .share(); assert_eq!( - context_search.contract_pair(&left_syntax, &right_syntax), - composite_syntax + context_search.contract_pair(&left_syntax, &right_syntax).key(), + composite_syntax.key() ); assert_eq!( diff --git a/zia/src/context_search_test/basic_existence.rs b/zia/src/context_search_test/basic_existence.rs index 6380a476..f6eaa50d 100644 --- a/zia/src/context_search_test/basic_existence.rs +++ b/zia/src/context_search_test/basic_existence.rs @@ -1,13 +1,12 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, context_search_test::ReductionReason, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -21,10 +20,11 @@ fn basic_existence() { ConceptId, SharedDirectConceptDelta, SharedContextDelta, + _, >::default(); - let cache = MultiThreadedContextCache::default(); + let cache = MTContextCache::default(); let variable_syntax = Syntax::from("_x_").share(); - let bound_variables = hashset! {variable_syntax.clone()}; + let bound_variables = hashset! {variable_syntax.key()}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, delta: SharedContextDelta(delta.into()), @@ -48,7 +48,7 @@ fn basic_existence() { true_syntax, ReductionReason::Existence { generalisation: variable_syntax.clone(), - substitutions: hashmap! {variable_syntax => context_search.to_ast(&2)}, + substitutions: hashmap! {variable_syntax.key() => context_search.to_ast(&2)}, } )) ); diff --git a/zia/src/context_search_test/basic_inference.rs b/zia/src/context_search_test/basic_inference.rs index 08daa8e9..a40084a7 100644 --- a/zia/src/context_search_test/basic_inference.rs +++ b/zia/src/context_search_test/basic_inference.rs @@ -1,13 +1,12 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, context_search_test::ReductionReason, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -21,8 +20,9 @@ fn basic_inference() { ConceptId, SharedDirectConceptDelta, SharedContextDelta, + _, >::default(); - let cache = MultiThreadedContextCache::default(); + let cache = MTContextCache::default(); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, @@ -83,7 +83,7 @@ fn concepts() -> [Concept; 10] { condition_implies_result_concept, (ConcreteConceptType::Associativity, 6).into(), (ConcreteConceptType::Left, 7).into(), - (ConcreteConceptType::Precedence, 8).into(), + (ConcreteConceptType::Preceeds, 8).into(), (ConcreteConceptType::Right, 9).into(), ] } diff --git a/zia/src/context_search_test/basic_reduction.rs b/zia/src/context_search_test/basic_reduction.rs index c9ebe404..4e0fcc71 100644 --- a/zia/src/context_search_test/basic_reduction.rs +++ b/zia/src/context_search_test/basic_reduction.rs @@ -1,13 +1,12 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, context_search_test::ReductionReason, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -21,8 +20,9 @@ fn basic_reduction() { ConceptId, SharedDirectConceptDelta, SharedContextDelta, + _, >::default(); - let cache = MultiThreadedContextCache::default(); + let cache = MTContextCache::default(); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, diff --git a/zia/src/context_search_test/basic_rule.rs b/zia/src/context_search_test/basic_rule.rs index 9b0bce1d..ea5823bd 100644 --- a/zia/src/context_search_test/basic_rule.rs +++ b/zia/src/context_search_test/basic_rule.rs @@ -1,13 +1,12 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, context_search_test::ReductionReason, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -21,8 +20,9 @@ fn basic_rule() { ConceptId, SharedDirectConceptDelta, SharedContextDelta, + _, >::default(); - let cache = MultiThreadedContextCache::default(); + let cache = MTContextCache::default(); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, diff --git a/zia/src/context_search_test/comparison_existence_implication_rule.rs b/zia/src/context_search_test/comparison_existence_implication_rule.rs index d0d4f35e..d185c8ec 100644 --- a/zia/src/context_search_test/comparison_existence_implication_rule.rs +++ b/zia/src/context_search_test/comparison_existence_implication_rule.rs @@ -5,7 +5,7 @@ use crate::{ context_search_test::ReductionReason, mock_snap_shot::MockSnapShot, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -14,9 +14,9 @@ use std::collections::HashMap; #[test] fn comparison_existence_implication_rule_test() { - let context_cache = MultiThreadedContextCache::default(); + let context_cache = MTContextCache::default(); let context_delta = - NestedDelta::<_, SharedDirectConceptDelta<_>, _>::default(); + NestedDelta::<_, SharedDirectConceptDelta<_>, _, _>::default(); let context_snap_shot = MockSnapShot::new_test_case(&concepts(), &labels()); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { @@ -39,7 +39,7 @@ fn comparison_existence_implication_rule_test() { &context_search.to_ast(&20), &variable_mask ), reason: ReductionReason::Existence{ - substitutions: hashmap!{context_search.to_ast(&5) => context_search.to_ast(&22)}, + substitutions: hashmap!{context_search.to_ast(&5).key() => context_search.to_ast(&22)}, generalisation: context_search.substitute(&context_search.to_ast(&15), &variable_mask), }.into() }.into() diff --git a/zia/src/context_search_test/existence_inference_rule.rs b/zia/src/context_search_test/existence_inference_rule.rs index 798f6c7e..58350694 100644 --- a/zia/src/context_search_test/existence_inference_rule.rs +++ b/zia/src/context_search_test/existence_inference_rule.rs @@ -1,12 +1,11 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, mock_snap_shot::MockSnapShot, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -29,9 +28,9 @@ fn labels() -> HashMap { #[test] fn existence_inference_rule() { - let context_cache = MultiThreadedContextCache::default(); + let context_cache = MTContextCache::default(); let context_delta = - NestedDelta::<_, SharedDirectConceptDelta<_>, _>::default(); + NestedDelta::<_, SharedDirectConceptDelta<_>, _, _>::default(); let context_snap_shot = MockSnapShot::new_test_case(&concepts(), &labels()); let bound_variables = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { diff --git a/zia/src/context_search_test/implied_reduction_via_implication_chain.rs b/zia/src/context_search_test/implied_reduction_via_implication_chain.rs index aa573cf1..458ff870 100644 --- a/zia/src/context_search_test/implied_reduction_via_implication_chain.rs +++ b/zia/src/context_search_test/implied_reduction_via_implication_chain.rs @@ -4,7 +4,7 @@ use crate::{ context_search::ContextReferences, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -80,7 +80,7 @@ fn concepts() -> [Concept; 26] { example_composition, variable_concept, concept_b, - (ConcreteConceptType::Precedence, 11).into(), + (ConcreteConceptType::Preceeds, 11).into(), (ConcreteConceptType::Associativity, 12).into(), (ConcreteConceptType::Left, 13).into(), (ConcreteConceptType::Right, 14).into(), @@ -119,9 +119,9 @@ fn labels() -> HashMap { #[test] fn inference_rule() { - let context_cache = MultiThreadedContextCache::default(); + let context_cache = MTContextCache::default(); let context_delta = - NestedDelta::<_, SharedDirectConceptDelta, _>::default(); + NestedDelta::<_, SharedDirectConceptDelta, _, _>::default(); let context_snap_shot = MockSnapShot::new_test_case(&concepts(), &labels()); let bound_variable_syntax = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { diff --git a/zia/src/context_search_test/inference_rule.rs b/zia/src/context_search_test/inference_rule.rs index 15a69c62..1059c51d 100644 --- a/zia/src/context_search_test/inference_rule.rs +++ b/zia/src/context_search_test/inference_rule.rs @@ -1,12 +1,11 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -51,7 +50,7 @@ fn concepts() -> [Concept; 15] { example_composition, variable_concept, concept_b, - (ConcreteConceptType::Precedence, 11).into(), + (ConcreteConceptType::Preceeds, 11).into(), (ConcreteConceptType::Associativity, 12).into(), (ConcreteConceptType::Left, 13).into(), (ConcreteConceptType::Right, 14).into(), @@ -66,7 +65,7 @@ fn labels() -> HashMap { 7 => "example", 9 => "_x_", 10 => "b", - 11 => "prec", + 11 => "preceeds", 12 => "assoc", 13 => "left", 14 => "right" @@ -75,9 +74,9 @@ fn labels() -> HashMap { #[test] fn inference_rule() { - let context_cache = MultiThreadedContextCache::default(); + let context_cache = MTContextCache::default(); let context_delta = - NestedDelta::<_, SharedDirectConceptDelta, _>::default(); + NestedDelta::<_, SharedDirectConceptDelta, _, _>::default(); let context_snap_shot = MockSnapShot::new_test_case(&concepts(), &labels()); let bound_variable_syntax = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { diff --git a/zia/src/context_search_test/inferred_negation.rs b/zia/src/context_search_test/inferred_negation.rs index 7aa92892..005d733e 100644 --- a/zia/src/context_search_test/inferred_negation.rs +++ b/zia/src/context_search_test/inferred_negation.rs @@ -1,11 +1,10 @@ use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -41,7 +40,7 @@ fn concepts() -> [Concept; 14] { implies_result_concept, cause_implies_result_concept, concept_b, - (ConcreteConceptType::Precedence, 8).into(), + (ConcreteConceptType::Preceeds, 8).into(), (ConcreteConceptType::Associativity, 9).into(), (ConcreteConceptType::Left, 10).into(), (ConcreteConceptType::Right, 11).into(), @@ -56,9 +55,9 @@ fn labels() -> HashMap { #[test] fn inferred_negation() { - let context_cache = MultiThreadedContextCache::default(); + let context_cache = MTContextCache::default(); let context_delta = - NestedDelta::<_, SharedDirectConceptDelta, _>::default(); + NestedDelta::<_, SharedDirectConceptDelta, _, _>::default(); let context_snap_shot = MockSnapShot::new_test_case(&concepts(), &labels()); let bound_variable_syntax = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { diff --git a/zia/src/context_search_test/mod.rs b/zia/src/context_search_test/mod.rs index e7270b4d..6a538feb 100644 --- a/zia/src/context_search_test/mod.rs +++ b/zia/src/context_search_test/mod.rs @@ -15,7 +15,7 @@ mod not; use crate::{ concepts::{Concept, ConceptTrait}, mock_snap_shot::ConceptId, - multi_threaded::{MultiThreadedReductionReason, MultiThreadedSyntaxTree}, + multi_threaded::{MTReductionReason, MTSyntaxTree}, }; pub fn check_order(concepts: &[Concept]) -> Vec> { @@ -29,5 +29,5 @@ pub fn check_order(concepts: &[Concept]) -> Vec> { .collect::>>() } -type Syntax = MultiThreadedSyntaxTree; -type ReductionReason = MultiThreadedReductionReason; +type Syntax = MTSyntaxTree; +type ReductionReason = MTReductionReason; diff --git a/zia/src/context_search_test/nested_composition_rule.rs b/zia/src/context_search_test/nested_composition_rule.rs index 03202a09..66aa64a9 100644 --- a/zia/src/context_search_test/nested_composition_rule.rs +++ b/zia/src/context_search_test/nested_composition_rule.rs @@ -1,16 +1,16 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, context_search_test::ReductionReason, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; +use assert_matches::assert_matches; use maplit::{hashmap, hashset}; use std::collections::HashMap; @@ -58,8 +58,8 @@ fn labels() -> HashMap { fn basic_rule() { let snapshot = MockSnapShot::new_test_case(&concepts(), &labels()); let delta = - NestedDelta::<_, SharedDirectConceptDelta, _>::default(); - let cache = MultiThreadedContextCache::default(); + NestedDelta::<_, SharedDirectConceptDelta, _, _>::default(); + let cache = MTContextCache::default(); let bound_variable_syntax = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { snap_shot: &snapshot, @@ -92,9 +92,12 @@ fn basic_rule() { reason: ReductionReason::Explicit.into(), }; - assert_eq!( + assert_matches!( context_search.reduce(&left_and_right_left_and_random_syntax), - Some((concrete_syntax().into(), reduction_reason.clone())) + Some((syntax, reason)) => { + assert_eq!(syntax.key(), concrete_syntax().key()); + assert_eq!(reason, reduction_reason); + } ); assert_eq!( diff --git a/zia/src/context_search_test/not.rs b/zia/src/context_search_test/not.rs index a1198277..2a0e665d 100644 --- a/zia/src/context_search_test/not.rs +++ b/zia/src/context_search_test/not.rs @@ -1,11 +1,10 @@ use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_delta::NestedDelta, context_search::ContextReferences, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MTContextSearch, MultiThreadedContextCache, SharedContextDelta, + MTContextCache, MTContextSearch, SharedContextDelta, SharedDirectConceptDelta, }, }; @@ -48,7 +47,7 @@ fn concepts() -> [Concept; 17] { implies_result_concept, cause_implies_result_concept, not, - (ConcreteConceptType::Precedence, 8).into(), + (ConcreteConceptType::Preceeds, 8).into(), (ConcreteConceptType::Associativity, 9).into(), (ConcreteConceptType::Left, 10).into(), (ConcreteConceptType::Right, 11).into(), @@ -74,9 +73,9 @@ fn labels() -> HashMap { #[test] fn not() { - let context_cache = MultiThreadedContextCache::default(); + let context_cache = MTContextCache::default(); let context_delta = - NestedDelta::<_, SharedDirectConceptDelta, _>::default(); + NestedDelta::<_, SharedDirectConceptDelta, _, _>::default(); let context_snap_shot = MockSnapShot::new_test_case(&concepts(), &labels()); let bound_variable_syntax = hashset! {}; let context_search = MTContextSearch::from(ContextReferences { diff --git a/zia/src/context_snap_shot/concept.rs b/zia/src/context_snap_shot/concept.rs index 23538187..506fcfa0 100644 --- a/zia/src/context_snap_shot/concept.rs +++ b/zia/src/context_snap_shot/concept.rs @@ -51,18 +51,22 @@ impl<'a> From<&'a Concept> for Mixed<'a> { } } -impl<'a, 'b> From<&'a NewDirectConceptDelta> - for Mixed<'b> -{ +impl<'a> From<&'a NewDirectConceptDelta> for Mixed<'_> { fn from(delta: &'a NewDirectConceptDelta) -> Self { Mixed::Uncommitted(Box::new(delta.into())) } } -impl<'a> ConceptTrait for Mixed<'a> { +impl ConceptTrait for Mixed<'_> { type Id = ConceptId; - type IdIterator<'b> = Box + 'b> where Self: 'b; - type IdPairIterator<'b> = Box + 'b> where Self: 'b; + type IdIterator<'b> + = Box + 'b> + where + Self: 'b; + type IdPairIterator<'b> + = Box + 'b> + where + Self: 'b; fn id(&self) -> Self::Id { match self { @@ -296,7 +300,7 @@ impl<'a> ConceptTrait for Mixed<'a> { Some(None) => return None, Some(Some(c)) => return Some(*c), None => (), - }; + } other_id.try_into().map_or(None, |other_id| { original_concept .find_as_hand_in_composition_with(other_id, hand) diff --git a/zia/src/context_snap_shot/concept_id.rs b/zia/src/context_snap_shot/concept_id.rs index 73ef78cb..ff87313a 100644 --- a/zia/src/context_snap_shot/concept_id.rs +++ b/zia/src/context_snap_shot/concept_id.rs @@ -3,7 +3,7 @@ use std::{ fmt::{Debug, Display}, }; -use crate::mixed_concept::MixedConcept; +use crate::mixed_concept::{self, MixedConcept}; use slotmap::new_key_type; @@ -23,6 +23,8 @@ pub enum ConceptId { Uncommitted(Uncommitted), } +impl mixed_concept::ConceptId for ConceptId {} + impl MixedConcept for ConceptId { fn uncommitted(id: usize) -> Self { Self::Uncommitted(id) diff --git a/zia/src/context_snap_shot/mod.rs b/zia/src/context_snap_shot/mod.rs index 1568f4e1..c44c872b 100644 --- a/zia/src/context_snap_shot/mod.rs +++ b/zia/src/context_snap_shot/mod.rs @@ -30,6 +30,7 @@ use crate::{ NewConceptDelta, NewDirectConceptDelta, SharedDelta, ValueChange, }, delta::Apply, + nester::SharedReference, snap_shot::Reader as SnapShotReader, }; use bimap::BiMap; @@ -38,20 +39,22 @@ use std::{ collections::{HashMap, VecDeque}, convert::{TryFrom, TryInto}, fmt::Debug, + marker::PhantomData, }; /// A container for adding, reading, writing and removing concepts of generic type `T`. #[derive(Default, Debug, Clone)] -pub struct ContextSnapShot { +pub struct ContextSnapShot { /// Relates a String value to the index where the concept corresponding to the String is stored /// in the `concepts` field. string_map: HashMap, concepts: SlotMap>, concrete_concepts: BiMap, previously_uncommitted_concepts: HashMap, + phantom: PhantomData, } -impl ContextSnapShot { +impl ContextSnapShot { fn commit_new_concept( &mut self, id: Uncommitted, @@ -250,10 +253,12 @@ impl ContextSnapShot { + AsRef> + From> + Debug, - D: SharedDelta>, + D: SharedDelta< + NestedDelta = NestedDelta, + >, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, s: &str, ) -> Option { delta.get_string(s).map_or_else( @@ -292,10 +297,10 @@ impl ContextSnapShot { + AsRef> + From> + Debug, - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, c: ConceptId, ) -> Option { let concept = self.read_concept(delta, c); @@ -321,7 +326,7 @@ impl ContextSnapShot { } } -impl SnapShotReader for ContextSnapShot +impl SnapShotReader for ContextSnapShot where SDCD: Clone + AsRef> @@ -330,13 +335,16 @@ where { type CommittedConceptId = Committed; type ConceptId = ConceptId; - type MixedConcept<'a> = Mixed<'a>; + type MixedConcept<'a> + = Mixed<'a> + where + SR: 'a; fn concept_from_label< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, s: &str, ) -> Option { self.get_string_concept(delta, s) @@ -352,10 +360,10 @@ where } fn get_label< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept: Self::ConceptId, ) -> Option { self.get_concept_of_label(delta, concept).map_or_else( @@ -372,16 +380,19 @@ where } fn concrete_concept_id< - D: SharedDelta>, + D: SharedDelta< + NestedDelta = NestedDelta, + >, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, cc: ConcreteConceptType, ) -> Option { let mut id = None; for (concept_id, cdv) in delta.iter_concepts().filter(|(concept_id, _)| { - self.concrete_concept_type(delta, **concept_id) == Some(cc) + self.maybe_concrete_concept_type(delta, **concept_id) + == Some(cc) }) { for dcd in cdv.filter_map(ConceptDelta::try_direct) { @@ -402,19 +413,9 @@ where .map(Self::ConceptId::from) }) } - - fn concrete_concept_type< - D: SharedDelta>, - >( - &self, - delta: &NestedDelta, - concept_id: Self::ConceptId, - ) -> Option { - self.read_concept(delta, concept_id).get_concrete_concept_type() - } } -impl Apply for ContextSnapShot +impl Apply for ContextSnapShot where SDCD: Clone + AsRef> @@ -424,10 +425,12 @@ where { #[allow(clippy::too_many_lines)] fn apply< - D: SharedDelta>, + D: SharedDelta< + NestedDelta = NestedDelta, + >, >( &mut self, - delta: NestedDelta, + delta: NestedDelta, ) { debug_assert!(self.previously_uncommitted_concepts.is_empty()); for (concept_id, concept_delta) in delta.concepts_to_apply_in_order() { diff --git a/zia/src/context_test/basic_precedence.rs b/zia/src/context_test/basic_precedence.rs index b571abac..b3847233 100644 --- a/zia/src/context_test/basic_precedence.rs +++ b/zia/src/context_test/basic_precedence.rs @@ -1,6 +1,5 @@ use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_test::Context, mock_snap_shot::MockSnapShot, @@ -8,52 +7,46 @@ use crate::{ use maplit::hashmap; use std::collections::HashMap; -fn concepts() -> [Concept; 11] { - let mut precedence_concept = (ConcreteConceptType::Precedence, 0).into(); - let mut greater_than_concept = (ConcreteConceptType::GreaterThan, 1).into(); - let mut default_concept = (ConcreteConceptType::Default, 2).into(); +fn concepts() -> [Concept; 13] { + let mut c_concept = (SpecificPart::default(), 0).into(); + let mut preceeds_concept = (ConcreteConceptType::Preceeds, 1).into(); + let mut b_concept = (SpecificPart::default(), 2).into(); let mut true_concept = (ConcreteConceptType::True, 3).into(); - let mut abstract_concept = (SpecificPart::default(), 4).into(); - let mut precedence_of_abstract_concept = Concept::composition_of( - 5, - &mut precedence_concept, - &mut abstract_concept, - ); - let mut greater_than_precedence_of_abstract_concept = - Concept::composition_of( - 6, - &mut greater_than_concept, - &mut precedence_of_abstract_concept, - ); - let mut precedence_of_abstract_concept_is_below_default = - Concept::composition_of( - 7, - &mut default_concept, - &mut greater_than_precedence_of_abstract_concept, - ); - precedence_of_abstract_concept_is_below_default - .make_reduce_to(&mut true_concept); + let mut a_concept = (SpecificPart::default(), 4).into(); + let mut preceeds_a_concept = + Concept::composition_of(5, &mut preceeds_concept, &mut a_concept); + let mut c_preceeds_a_concept = + Concept::composition_of(6, &mut c_concept, &mut preceeds_a_concept); + c_preceeds_a_concept.make_reduce_to(&mut true_concept); let assoc_concept: Concept<_> = - (ConcreteConceptType::Associativity, 8).into(); - let left_concept: Concept<_> = (ConcreteConceptType::Left, 9).into(); - let right_concept: Concept<_> = (ConcreteConceptType::Right, 10).into(); + (ConcreteConceptType::Associativity, 7).into(); + let left_concept: Concept<_> = (ConcreteConceptType::Left, 8).into(); + let right_concept: Concept<_> = (ConcreteConceptType::Right, 9).into(); + let label_of_concept: Concept<_> = (ConcreteConceptType::Label, 10).into(); + let mut preceeds_b_concept = + Concept::composition_of(11, &mut preceeds_concept, &mut b_concept); + let mut c_preceeds_b_concept = + Concept::composition_of(12, &mut c_concept, &mut preceeds_b_concept); + c_preceeds_b_concept.make_reduce_to(&mut true_concept); [ - precedence_concept, - greater_than_concept, - default_concept, + c_concept, + preceeds_concept, + b_concept, true_concept, - abstract_concept, - precedence_of_abstract_concept, - greater_than_precedence_of_abstract_concept, - precedence_of_abstract_concept_is_below_default, + a_concept, + preceeds_a_concept, + c_preceeds_a_concept, assoc_concept, left_concept, right_concept, + label_of_concept, + preceeds_b_concept, + c_preceeds_b_concept, ] } fn labels() -> HashMap { - hashmap! {4 => "a"} + hashmap! {0 => "c", 2 => "b", 4 => "a"} } #[test] diff --git a/zia/src/context_test/infered_precedence.rs b/zia/src/context_test/infered_precedence.rs index 231e2096..2939177e 100644 --- a/zia/src/context_test/infered_precedence.rs +++ b/zia/src/context_test/infered_precedence.rs @@ -1,6 +1,4 @@ -use super::Syntax; use crate::{ - ast::SyntaxTree, concepts::{Concept, ConcreteConceptType, SpecificPart}, context_test::Context, mock_snap_shot::MockSnapShot, @@ -9,138 +7,116 @@ use maplit::hashmap; use std::collections::HashMap; #[allow(clippy::too_many_lines)] -fn concepts() -> [Concept; 36] { +fn concepts() -> [Concept; 33] { let mut true_concept = (ConcreteConceptType::True, 0).into(); - let mut greater_than_concept = (ConcreteConceptType::GreaterThan, 1).into(); + let mut preceeds_concept = (ConcreteConceptType::Preceeds, 1).into(); let mut exists_such_that_concept = (ConcreteConceptType::ExistsSuchThat, 2).into(); let mut implication_concept = (ConcreteConceptType::Implication, 3).into(); let mut x = (SpecificPart::free_variable(), 4).into(); let mut y = (SpecificPart::bound_variable(), 5).into(); let mut z = (SpecificPart::free_variable(), 6).into(); - let mut greater_than_z = - Concept::composition_of(7, &mut greater_than_concept, &mut z); - let mut y_greater_than_z = - Concept::composition_of(8, &mut y, &mut greater_than_z); + let mut preceeds_z = + Concept::composition_of(7, &mut preceeds_concept, &mut z); + let mut y_preceeds_z = Concept::composition_of(8, &mut y, &mut preceeds_z); let mut and_concept = (SpecificPart::default(), 9).into(); let mut and_true = Concept::composition_of(10, &mut and_concept, &mut true_concept); let mut true_and_true = Concept::composition_of(11, &mut true_concept, &mut and_true); true_and_true.make_reduce_to(&mut true_concept); - let mut and_y_greater_than_z = - Concept::composition_of(12, &mut and_concept, &mut y_greater_than_z); - let mut greater_than_y = - Concept::composition_of(13, &mut greater_than_concept, &mut y); - let mut x_greater_than_y = - Concept::composition_of(14, &mut x, &mut greater_than_y); - let mut x_greater_than_y_and_y_greater_than_z = Concept::composition_of( - 15, - &mut x_greater_than_y, - &mut and_y_greater_than_z, - ); + let mut and_y_preceeds_z = + Concept::composition_of(12, &mut and_concept, &mut y_preceeds_z); + let mut preceeds_y = + Concept::composition_of(13, &mut preceeds_concept, &mut y); + let mut x_preceeds_y = Concept::composition_of(14, &mut x, &mut preceeds_y); + let mut x_preceeds_y_and_y_preceeds_z = + Concept::composition_of(15, &mut x_preceeds_y, &mut and_y_preceeds_z); let mut y_exists_such_that = Concept::composition_of(16, &mut y, &mut exists_such_that_concept); - let mut y_exists_such_that_x_greater_than_y_and_y_greater_than_z = + let mut y_exists_such_that_x_preceeds_y_and_y_preceeds_z = Concept::composition_of( 17, &mut y_exists_such_that, - &mut x_greater_than_y_and_y_greater_than_z, + &mut x_preceeds_y_and_y_preceeds_z, ); - let mut x_greater_than_z = - Concept::composition_of(18, &mut x, &mut greater_than_z); - let mut implies_x_greater_than_z = Concept::composition_of( + let mut x_preceeds_z = Concept::composition_of(18, &mut x, &mut preceeds_z); + let mut implies_x_preceeds_z = Concept::composition_of( 19, &mut implication_concept, - &mut x_greater_than_z, + &mut x_preceeds_z, ); let mut - y_exists_such_that_x_greater_than_y_and_y_greater_than_z_implies_x_greater_than_z = + y_exists_such_that_x_preceeds_y_and_y_preceeds_z_implies_x_preceeds_z = Concept::composition_of( 20, - &mut y_exists_such_that_x_greater_than_y_and_y_greater_than_z, - &mut implies_x_greater_than_z, + &mut y_exists_such_that_x_preceeds_y_and_y_preceeds_z, + &mut implies_x_preceeds_z, ); - y_exists_such_that_x_greater_than_y_and_y_greater_than_z_implies_x_greater_than_z.make_reduce_to(&mut true_concept); + y_exists_such_that_x_preceeds_y_and_y_preceeds_z_implies_x_preceeds_z + .make_reduce_to(&mut true_concept); let mut let_concept = (ConcreteConceptType::Let, 21).into(); let mut reduction_concept = (ConcreteConceptType::Reduction, 22).into(); - let mut precedence_concept = (ConcreteConceptType::Precedence, 23).into(); - let mut default_concept = (ConcreteConceptType::Default, 24).into(); - let mut let_precedence = - Concept::composition_of(25, &mut precedence_concept, &mut let_concept); - let mut reduction_precedence = Concept::composition_of( - 26, - &mut precedence_concept, - &mut reduction_concept, - ); - let mut greater_than_let_precedence = Concept::composition_of( - 27, - &mut greater_than_concept, - &mut let_precedence, - ); - let assoc_concept = (ConcreteConceptType::Associativity, 28).into(); - let right_id_concept = (ConcreteConceptType::Right, 29).into(); - let mut greater_than_reduction_precedence = Concept::composition_of( - 30, - &mut greater_than_concept, - &mut reduction_precedence, + let mut definition_concept = (ConcreteConceptType::Define, 23).into(); + let mut preceeds_let = + Concept::composition_of(24, &mut preceeds_concept, &mut let_concept); + let mut definition_preceeds_let = + Concept::composition_of(25, &mut definition_concept, &mut preceeds_let); + definition_preceeds_let.make_reduce_to(&mut true_concept); + let assoc_concept = (ConcreteConceptType::Associativity, 26).into(); + let right_id_concept = (ConcreteConceptType::Right, 27).into(); + let mut preceeds_definition = Concept::composition_of( + 28, + &mut preceeds_concept, + &mut definition_concept, ); - let mut default_greater_than_reduction_precedence = Concept::composition_of( - 31, - &mut default_concept, - &mut greater_than_reduction_precedence, - ); - default_greater_than_reduction_precedence.make_reduce_to(&mut true_concept); - let mut reduction_preceeds_let = Concept::composition_of( - 32, - &mut reduction_precedence, - &mut greater_than_let_precedence, + let mut reduction_preceeds_definition = Concept::composition_of( + 29, + &mut reduction_concept, + &mut preceeds_definition, ); - reduction_preceeds_let.make_reduce_to(&mut true_concept); + reduction_preceeds_definition.make_reduce_to(&mut true_concept); [ true_concept, - greater_than_concept, + preceeds_concept, exists_such_that_concept, implication_concept, x, y, z, - greater_than_z, - y_greater_than_z, + preceeds_z, + y_preceeds_z, and_concept, and_true, true_and_true, - and_y_greater_than_z, - greater_than_y, - x_greater_than_y, - x_greater_than_y_and_y_greater_than_z, + and_y_preceeds_z, + preceeds_y, + x_preceeds_y, + x_preceeds_y_and_y_preceeds_z, y_exists_such_that, - y_exists_such_that_x_greater_than_y_and_y_greater_than_z, - x_greater_than_z, - implies_x_greater_than_z, - y_exists_such_that_x_greater_than_y_and_y_greater_than_z_implies_x_greater_than_z, + y_exists_such_that_x_preceeds_y_and_y_preceeds_z, + x_preceeds_z, + implies_x_preceeds_z, + y_exists_such_that_x_preceeds_y_and_y_preceeds_z_implies_x_preceeds_z, let_concept, reduction_concept, - precedence_concept, - default_concept, - let_precedence, - reduction_precedence, - greater_than_let_precedence, + definition_concept, + preceeds_let, + definition_preceeds_let, assoc_concept, right_id_concept, - greater_than_reduction_precedence, - default_greater_than_reduction_precedence, - reduction_preceeds_let, - (ConcreteConceptType::False, 33).into(), // false - (ConcreteConceptType::Left, 34).into(), // left - (ConcreteConceptType::Label, 35).into() // label_of + preceeds_definition, + reduction_preceeds_definition, + (ConcreteConceptType::False, 30).into(), // false + (ConcreteConceptType::Left, 31).into(), // left + (ConcreteConceptType::Label, 32).into(), // label_of ] } fn concept_labels() -> HashMap { hashmap! { 0 => "true", - 1 => ">", + 1 => "preceeds", 2 => ":", 3 => "=>", 4 => "_x_", @@ -149,36 +125,14 @@ fn concept_labels() -> HashMap { 9 => "and", 21 => "let", 22 => "->", - 23 => "prec", - 24 => "default", - 28 => "assoc", - 29 => "right", - 33 => "false", + 26 => "assoc", + 27 => "right", + 30 => "false", } } #[test] fn infered_precedence_test() { let snapshot = MockSnapShot::new_test_case(&concepts(), &concept_labels()); let mut context: Context = snapshot.into(); - assert_eq!( - context.ast_from_expression("let a b -> c"), - Ok(Syntax::new_pair( - Syntax::from("let").bind_nonquantifier_concept(21).share(), - Syntax::new_pair( - Syntax::new_pair( - Syntax::from("a").share(), - Syntax::from("b").into() - ) - .share(), - Syntax::new_pair( - Syntax::from("->").bind_nonquantifier_concept(22).share(), - Syntax::from("c").into() - ) - .into() - ) - .into() - ) - .into()) - ); - assert_eq!(context.execute("default > (prec let)"), "true"); + assert_eq!(context.execute("-> (preceeds let)"), "true"); } diff --git a/zia/src/context_test/mod.rs b/zia/src/context_test/mod.rs index 3c35a25e..4c45bdec 100644 --- a/zia/src/context_test/mod.rs +++ b/zia/src/context_test/mod.rs @@ -5,21 +5,16 @@ use crate::{ context::Context as GenericContext, mock_snap_shot::{ConceptId, MockSnapShot}, multi_threaded::{ - MultiThreadedContextCache, MultiThreadedReductionReason, - MultiThreadedSyntaxTree, MultiThreadedVariableMaskList, - SharedContextDelta, SharedDirectConceptDelta, + ArcFamily, MTSyntaxTree, SharedContextDelta, SharedDirectConceptDelta, }, }; pub type Context = GenericContext< MockSnapShot, - MultiThreadedContextCache< - MultiThreadedReductionReason>, - >, SharedDirectConceptDelta, - MultiThreadedVariableMaskList>, SharedContextDelta, ConceptId, + ArcFamily, >; -type Syntax = MultiThreadedSyntaxTree; +type Syntax = MTSyntaxTree; diff --git a/zia/src/context_updater.rs b/zia/src/context_updater.rs index 9ced84d9..ef001f33 100644 --- a/zia/src/context_updater.rs +++ b/zia/src/context_updater.rs @@ -1,14 +1,15 @@ use crate::{ and_also::AndAlso, - ast::SyntaxTree, + ast::GenericSyntaxTree, concepts::{ConceptTrait, ConcreteConceptType, Hand}, - context_cache::ContextCache, + context_cache::GenericCache, context_delta::{ Composition, DirectConceptDelta, NestedDelta, NewConceptDelta, - SharedDelta, ValueChange, + SharedDelta, ValueAndTypeChange, ValueChange, }, errors::ZiaResult, - reduction_reason::{ReductionReason, SharedSyntax, Syntax}, + nester::SharedReference, + reduction_reason::SharedSyntax, snap_shot::Reader, ZiaError, }; @@ -17,39 +18,36 @@ use std::{fmt::Debug, marker::PhantomData}; pub struct ContextUpdater< 'a, - S: Reader, - C: ContextCache, + S: Reader, SDCD: Clone + AsRef> + From> + Debug, - D: SharedDelta>, + D: SharedDelta>, + SR: SharedReference, > { - pub cache: &'a mut C, - pub delta: &'a mut NestedDelta, + pub cache: &'a mut GenericCache, + pub delta: &'a mut NestedDelta, pub snap_shot: &'a S, pub phantom: PhantomData, + pub phantom2: PhantomData, } impl< - 'a, - S: Reader, - C: ContextCache, + S: Reader, SDCD: Clone + AsRef> + From> + Debug, - D: SharedDelta>, - > ContextUpdater<'a, S, C, SDCD, D> -where - <::RR as ReductionReason>::Syntax: - SyntaxTree, + D: SharedDelta>, + SR: SharedReference, + > ContextUpdater<'_, S, SDCD, D, SR> { pub fn redefine( &mut self, concept: &S::ConceptId, - left: &SharedSyntax, - right: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, ) -> ZiaResult<()> { if let Some((left_concept, right_concept)) = self.snap_shot.read_concept(self.delta, *concept).get_composition() @@ -85,8 +83,8 @@ where pub fn define_new_syntax( &mut self, syntax: &str, - left: &SharedSyntax, - right: &SharedSyntax, + left: &SharedSyntax, + right: &SharedSyntax, ) -> ZiaResult<()> { let new_syntax_tree = left .get_concept() @@ -96,7 +94,8 @@ where .read_concept(self.delta, *l) .find_as_hand_in_composition_with(*r, Hand::Left) .map(|concept| { - let syntax = Syntax::::from(syntax); + let syntax = + GenericSyntaxTree::::from(syntax); self.snap_shot .bind_concept_to_syntax(self.delta, syntax, concept) }) @@ -109,7 +108,7 @@ where pub fn concept_from_ast( &mut self, - ast: &Syntax, + ast: &GenericSyntaxTree, ) -> ZiaResult { if let Some(c) = ast.get_concept() { Ok(c) @@ -196,7 +195,8 @@ where .snap_shot .get_concept_of_label(self.delta, concept) .expect("No label to remove"); - self.delete_reduction(concept_of_label) + self.delete_reduction(concept_of_label)?; + Ok(()) } pub fn delete_reduction( @@ -229,7 +229,15 @@ where .concrete_concept_id(self.delta, ConcreteConceptType::Label) .ok_or(ZiaError::NoLabelConcept)?; let composition = self.find_or_insert_composition(label_id, concept); - let string_id = self.new_string(string); + + let string_id = self + .delta + .get_string(string) + .and_then(|v| match v { + ValueAndTypeChange::Create(id) => Some(id), + _ => None, + }) + .unwrap_or_else(|| self.new_string(string)); self.update_reduction(composition, string_id) } @@ -247,14 +255,18 @@ where .read_concept(self.delta, concept) .get_reduction() .and_then(|r| { - (r == reduction).then_some(Err(ZiaError::RedundantReduction)) + (r == reduction).then_some(Err(ZiaError::RedundantReduction { + syntax: concept.to_string(), + })) }) { result } else if reduction == self.snap_shot.get_reduction_of_composition(self.delta, concept) { - Err(ZiaError::RedundantReduction) + Err(ZiaError::RedundantReduction { + syntax: concept.to_string(), + }) } else { let change = maybe_normal_form.map_or_else( || ValueChange::Create(reduction), diff --git a/zia/src/delta.rs b/zia/src/delta.rs index 4f63e5f4..2161f336 100644 --- a/zia/src/delta.rs +++ b/zia/src/delta.rs @@ -1,5 +1,6 @@ use crate::{ context_delta::{DirectConceptDelta, NestedDelta, SharedDelta}, + nester::SharedReference, snap_shot::Reader, }; use std::fmt::Debug; @@ -19,7 +20,7 @@ use std::fmt::Debug; // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pub trait Apply: Reader +pub trait Apply: Reader where SDCD: Clone + AsRef> @@ -27,9 +28,9 @@ where + Debug, { fn apply< - D: SharedDelta>, + D: SharedDelta>, >( &mut self, - _: NestedDelta, + _: NestedDelta, ); } diff --git a/zia/src/errors.rs b/zia/src/errors.rs index cfdd59e6..d57d6432 100755 --- a/zia/src/errors.rs +++ b/zia/src/errors.rs @@ -23,9 +23,17 @@ pub type ZiaResult = Result; /// All the expected ways a Zia command could be invalid. #[derive(Debug, PartialEq, Eq, Clone, Error)] pub enum ZiaError { + /// e.g. an empty string. + #[error("No concepts recognised in expression")] + EmptyExpression, + /// e.g. ((a b). + #[error("Not all opening parentheses match closing parentheses")] + UnmatchedParentheses, /// When specifying a reduction rule that already exists. - #[error("That reduction rule already exists.")] - RedundantReduction, + #[error("That reduction rule for {syntax} already exists.")] + RedundantReduction { + syntax: String, + }, /// When specifying a definition that already exists. #[error("That definition already exists.")] RedundantComposition, diff --git a/zia/src/lexer.rs b/zia/src/lexer.rs index 698438d0..162f86c4 100644 --- a/zia/src/lexer.rs +++ b/zia/src/lexer.rs @@ -1,11 +1,14 @@ -pub struct Lexeme { +use crate::{concepts::ConcreteConceptType, mixed_concept::ConceptId}; + +#[derive(Debug)] +pub struct Lexeme { pub text: String, - pub category: Category, + pub category: Category, } #[derive(Debug, PartialEq, Eq)] -pub enum Category { - Concept(ConceptKind), +pub enum Category { + Concept(ConceptKind), Whitespace, OpeningParenthesis { closing_position: Option, @@ -16,9 +19,14 @@ pub enum Category { } #[derive(Debug, PartialEq, Eq)] -pub enum ConceptKind { - Concrete, - Abstract, +pub enum ConceptKind { + Concrete { + id: CI, + concrete_type: ConcreteConceptType, + }, + Abstract { + id: CI, + }, New, Variable, } diff --git a/zia/src/lib.rs b/zia/src/lib.rs index 982b696c..d95e8359 100755 --- a/zia/src/lib.rs +++ b/zia/src/lib.rs @@ -157,6 +157,8 @@ mod errors; mod lexer; +mod nester; + mod map_err_variant; #[cfg(test)] @@ -164,8 +166,6 @@ mod mock_snap_shot; mod mixed_concept; -mod parser; - #[macro_use] mod reduction_reason; diff --git a/zia/src/mixed_concept.rs b/zia/src/mixed_concept.rs index 52e47a56..8efbb824 100644 --- a/zia/src/mixed_concept.rs +++ b/zia/src/mixed_concept.rs @@ -3,6 +3,7 @@ use std::{ hash::Hash, }; -pub trait MixedConcept: Clone + Copy + Debug + Display + Eq + Hash { +pub trait ConceptId: Clone + Copy + Debug + Display + Eq + Hash {} +pub trait MixedConcept: ConceptId { fn uncommitted(id: usize) -> Self; } diff --git a/zia/src/mock_snap_shot.rs b/zia/src/mock_snap_shot.rs index 0b54049c..53054e37 100644 --- a/zia/src/mock_snap_shot.rs +++ b/zia/src/mock_snap_shot.rs @@ -6,6 +6,7 @@ use crate::{ context_search_test::check_order, delta::Apply, mixed_concept::MixedConcept, + multi_threaded::ArcFamily, snap_shot::Reader, }; use bimap::BiMap; @@ -22,6 +23,8 @@ pub enum ConceptId { Uncommitted(usize), } +impl crate::mixed_concept::ConceptId for ConceptId {} + impl MixedConcept for ConceptId { fn uncommitted(id: usize) -> Self { Self::Uncommitted(id) @@ -88,22 +91,28 @@ impl MockSnapShot { } } -impl Apply>> for MockSnapShot { +impl Apply>, ArcFamily> for MockSnapShot { fn apply< D: SharedDelta< NestedDelta = NestedDelta< Self::ConceptId, Arc>, D, + ArcFamily, >, >, >( &mut self, - _: NestedDelta>, D>, + _: NestedDelta< + ConceptId, + Arc>, + D, + ArcFamily, + >, ) { } } -impl Reader>> for MockSnapShot { +impl Reader>, ArcFamily> for MockSnapShot { type CommittedConceptId = usize; type ConceptId = ConceptId; type MixedConcept<'a> = Concept; @@ -126,6 +135,7 @@ impl Reader>> for MockSnapShot { Self::ConceptId, Arc>, D, + ArcFamily, >, >, >( @@ -134,6 +144,7 @@ impl Reader>> for MockSnapShot { Self::ConceptId, Arc>, D, + ArcFamily, >, concept_id: Self::ConceptId, ) -> Option { @@ -152,6 +163,7 @@ impl Reader>> for MockSnapShot { Self::ConceptId, Arc>, D, + ArcFamily, >, >, >( @@ -160,6 +172,7 @@ impl Reader>> for MockSnapShot { Self::ConceptId, Arc>, D, + ArcFamily, >, s: &str, ) -> Option { @@ -175,11 +188,17 @@ impl Reader>> for MockSnapShot { Self::ConceptId, Arc>, D, + ArcFamily, >, >, >( &self, - _: &NestedDelta>, D>, + _: &NestedDelta< + Self::ConceptId, + Arc>, + D, + ArcFamily, + >, cc: ConcreteConceptType, ) -> Option { self.concrete_concepts.get_by_right(&cc).copied() @@ -191,11 +210,17 @@ impl Reader>> for MockSnapShot { Self::ConceptId, Arc>, D, + ArcFamily, >, >, >( &self, - _: &NestedDelta>, D>, + _: &NestedDelta< + Self::ConceptId, + Arc>, + D, + ArcFamily, + >, concept_id: Self::ConceptId, ) -> Option { self.concrete_concepts.get_by_left(&concept_id).copied() diff --git a/zia/src/multi_threaded.rs b/zia/src/multi_threaded.rs index 3bda869c..29bcaa24 100644 --- a/zia/src/multi_threaded.rs +++ b/zia/src/multi_threaded.rs @@ -1,43 +1,54 @@ use crate::{ - ast::impl_syntax_tree, + ast::GenericSyntaxTree, context::Context as GenericContext, - context_cache::impl_cache, + context_cache::GenericCache, context_delta::{DirectConceptDelta, NestedDelta, SharedDelta}, context_search::ContextSearch, context_snap_shot::{ConceptId as ContextConceptId, ContextSnapShot}, - mixed_concept::MixedConcept, - variable_mask_list::impl_variable_mask_list, + mixed_concept::ConceptId, + nester::SharedReference, + reduction_reason::ReductionReason, + variable_mask_list::VariableMaskList, }; use lazy_static::lazy_static; use std::{fmt::Debug, sync::Arc}; -impl_syntax_tree!(Arc, MultiThreadedSyntaxTree); -impl_cache!(Arc, MultiThreadedContextCache); -impl_variable_mask_list!(Arc, MultiThreadedVariableMaskList); -impl_reduction_reason!(Arc, MultiThreadedReductionReason); +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct ArcFamily; + +impl SharedReference for ArcFamily { + type Share = Arc; + + fn share(owned: T) -> Self::Share { + Arc::new(owned) + } + + fn make_mut(refcounter: &mut Self::Share) -> &mut T { + Arc::make_mut(refcounter) + } +} + +pub type MTSyntaxTree = GenericSyntaxTree; +pub type MTContextCache = GenericCache; +pub type MTVariableMaskList = VariableMaskList; +pub type MTReductionReason = ReductionReason; pub type Context = GenericContext< - ContextSnapShot, - MultiThreadedContextCache< - MultiThreadedReductionReason>, - >, + ContextSnapShot, SharedDirectConceptDelta, - MultiThreadedVariableMaskList>, SharedContextDelta, ContextConceptId, + ArcFamily, >; pub type MTContextSearch<'s, 'v, S, CCI> = ContextSearch< 's, 'v, S, - MultiThreadedContextCache< - MultiThreadedReductionReason>, - >, - MultiThreadedVariableMaskList>, SharedDirectConceptDelta, SharedContextDelta, CCI, + ArcFamily, >; // Saves having to construct a new `Context` each time. @@ -45,27 +56,31 @@ lazy_static! { pub static ref NEW_CONTEXT: Context = Context::new().unwrap(); } -type MultiThreadedContextDelta = - NestedDelta, SharedContextDelta>; +type MultiThreadedContextDelta = NestedDelta< + CCI, + SharedDirectConceptDelta, + SharedContextDelta, + ArcFamily, +>; #[derive(Debug)] -pub struct SharedContextDelta( +pub struct SharedContextDelta( pub Arc>, ); -impl Clone for SharedContextDelta { +impl Clone for SharedContextDelta { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl Default for SharedContextDelta { +impl Default for SharedContextDelta { fn default() -> Self { Self(MultiThreadedContextDelta::default().into()) } } -impl SharedDelta for SharedContextDelta { +impl SharedDelta for SharedContextDelta { type NestedDelta = MultiThreadedContextDelta; fn get_mut(&mut self) -> Option<&mut Self::NestedDelta> { @@ -86,7 +101,7 @@ impl SharedDelta for SharedContextDelta { } } -impl AsRef> +impl AsRef> for SharedContextDelta { fn as_ref(&self) -> &MultiThreadedContextDelta { @@ -95,3 +110,30 @@ impl AsRef> } pub type SharedDirectConceptDelta = Arc>; + +#[cfg(test)] +mod tests { + use crate::{nester::NestedSyntaxTree, ConceptKind}; + + use super::Context; + + #[test] + fn precendence_test() { + let ctx = Context::new().unwrap(); + let lexeme = ctx.lex("(a b) c"); + let nested_syntax = Context::nest(lexeme).unwrap(); + assert_eq!( + nested_syntax, + NestedSyntaxTree::from_concept_kind(&ConceptKind::New, "a".into()) + .append_node(NestedSyntaxTree::from_concept_kind( + &ConceptKind::New, + "b".into() + )) + .nest() + .append_node(NestedSyntaxTree::from_concept_kind( + &ConceptKind::New, + "c".into() + )) + ); + } +} diff --git a/zia/src/nester.rs b/zia/src/nester.rs new file mode 100644 index 00000000..07366aaf --- /dev/null +++ b/zia/src/nester.rs @@ -0,0 +1,155 @@ +use crate::{ + ast::SyntaxLeaf, concepts::ConcreteConceptType, mixed_concept::ConceptId, + ConceptKind, +}; +use std::{borrow::Borrow, fmt::Debug, marker::PhantomData, ops::Deref}; + +pub enum Node { + Parent { + children: Vec>, + }, + Leaf(SyntaxLeaf), +} + +impl PartialEq + for Node +{ + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::Parent { + children: l_children, + }, + Self::Parent { + children: r_children, + }, + ) => l_children + .iter() + .zip(r_children.iter()) + .all(|(l, r)| l.as_ref() == r.as_ref()), + (Self::Leaf(l0), Self::Leaf(r0)) => l0 == r0, + _ => false, + } + } +} +impl Debug + for Node +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Parent { + children, + } => f + .debug_struct("Parent") + .field( + "children", + &children + .iter() + .map(std::convert::AsRef::as_ref) + .collect::>(), + ) + .finish(), + Self::Leaf(arg0) => f.debug_tuple("Leaf").field(arg0).finish(), + } + } +} +impl Eq + for Node +{ +} +pub trait SharedReference: Debug + Clone + PartialEq + Eq { + type Share: AsRef + Borrow + Clone + Deref; + fn share(owned: T) -> Self::Share; + + fn make_mut(refcounter: &mut Self::Share) -> &mut T; +} + +#[derive(PartialEq, Eq)] +pub struct NestedSyntaxTree { + pub node: Node, + pub syntax: String, + pub concept: Option, + pub _phantom: PhantomData, +} +impl Debug for NestedSyntaxTree { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NestedSyntaxTree") + .field("node", &self.node) + .field("syntax", &self.syntax) + .field("concept", &self.concept) + .finish() + } +} +impl NestedSyntaxTree { + pub fn from_concept_kind(c: &ConceptKind, syntax: String) -> Self { + Self { + node: Node::Leaf(match c { + ConceptKind::Variable => SyntaxLeaf::Variable, + ConceptKind::Concrete { + concrete_type, + .. + } if concrete_type == &ConcreteConceptType::ExistsSuchThat => { + SyntaxLeaf::Quantifier + }, + ConceptKind::Abstract { + .. + } + | ConceptKind::Concrete { + .. + } + | ConceptKind::New => SyntaxLeaf::Constant, + }), + syntax, + concept: match c { + ConceptKind::New | ConceptKind::Variable => None, + ConceptKind::Concrete { + id, + .. + } + | ConceptKind::Abstract { + id, + } => Some(*id), + }, + _phantom: PhantomData, + } + } + + pub fn nest(self) -> Self { + Self { + syntax: format!("({})", &self.syntax), + node: Node::Parent { + children: vec![SR::share(self)], + }, + concept: None, + _phantom: PhantomData, + } + } + + pub fn append_node(self, new_nested_syntax: Self) -> Self { + let share_nested_syntax = SR::share(new_nested_syntax); + let shared_self = SR::share(self); + Self { + node: Node::Parent { + children: match &shared_self.node { + Node::Leaf(_) => { + vec![shared_self.clone(), share_nested_syntax.clone()] + }, + Node::Parent { + children, + } => { + let mut new_children = children.clone(); + new_children.push(share_nested_syntax.clone()); + new_children + }, + }, + }, + syntax: format!( + "{} {}", + shared_self.syntax, share_nested_syntax.syntax + ), + concept: None, /* TODO: consider trying to identify a concept + * from pair */ + _phantom: PhantomData, + } + } +} diff --git a/zia/src/parser.rs b/zia/src/parser.rs deleted file mode 100644 index bac7659e..00000000 --- a/zia/src/parser.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::errors::{ZiaError, ZiaResult}; - -pub fn parse_line(buffer: &str) -> ZiaResult> { - let mut tokens: Vec = [].to_vec(); - let mut token = String::new(); - let parenthesis_level = buffer.chars().try_fold(0, |p_level, letter| { - parse_letter(letter, p_level, &mut token, &mut tokens) - })?; - if parenthesis_level != 0 { - return Err(ZiaError::MissingSymbol { - symbol: ")", - }); - } - if !token.is_empty() { - tokens.push(token); - } - Ok(tokens) -} - -fn parse_letter( - letter: char, - mut parenthesis_level: u8, - token: &mut String, - tokens: &mut Vec, -) -> ZiaResult { - match letter { - '(' => { - push_token(letter, parenthesis_level, token, tokens); - Ok(parenthesis_level + 1) - }, - ')' => { - if parenthesis_level > 0 { - parenthesis_level -= 1; - push_token(letter, parenthesis_level, token, tokens); - Ok(parenthesis_level) - } else { - Err(ZiaError::MissingSymbol { - symbol: "(", - }) - } - }, - ' ' => { - push_token(letter, parenthesis_level, token, tokens); - Ok(parenthesis_level) - }, - '\n' | '\r' => Ok(parenthesis_level), - _ => { - token.push(letter); - Ok(parenthesis_level) - }, - } -} - -fn push_token( - letter: char, - parenthesis_level: u8, - token: &mut String, - tokens: &mut Vec, -) { - if !token.is_empty() & (parenthesis_level == 0) { - tokens.push(token.clone()); - *token = String::new(); - } - if parenthesis_level != 0 { - token.push(letter); - } -} diff --git a/zia/src/reduction_reason.rs b/zia/src/reduction_reason.rs index 03c4acaa..b76a7edb 100644 --- a/zia/src/reduction_reason.rs +++ b/zia/src/reduction_reason.rs @@ -1,310 +1,413 @@ -use std::{collections::HashMap, fmt::Debug}; +use std::{collections::HashMap, fmt::Debug, hash::Hash}; + +use maplit::hashmap; use crate::{ - ast::SyntaxTree, - context_cache::ContextCache, + ast::{GenericSyntaxTree, SyntaxKey}, context_search::{ComparisonReason, ReductionTruthResult}, + mixed_concept::ConceptId, + nester::SharedReference, substitute::Substitutions, variable_mask_list::VariableMask, }; -pub trait ReductionReason -where - Self: Clone + Debug + From> + PartialEq, -{ - type Syntax: SyntaxTree; - - fn simplify_reasoning( - reason: Option, - reversed_reason: Option, - ) -> ComparisonReason; - - fn determine_reduction_truth( - left: &RRSharedSyntax, - right: &RRSharedSyntax, - reduce: impl Fn(&RRSharedSyntax) -> ReductionResult, - ) -> ReductionTruthResult; +pub type Reduction = (SharedSyntax, ReductionReason); - fn recursive_reason( - previous: Option, - last: Self, - previously_reduced_syntax: &RRSharedSyntax, - ) -> Self; +pub type ReductionResult = Option>; - fn existence( - substitutions: Substitutions>, - generalisation: RRSharedSyntax, - ) -> Self; - - fn inference(implication: RRSharedSyntax, reason: Self) -> Self; - - fn explicit() -> Self; - - fn default(operator_id: ReductionReasonConceptId) -> Self; - - fn rule( - generalisation: RRSharedSyntax, - variable_mask: VariableMask, - reason: Self, - ) -> Self; - - fn partial( - partial_reductions: HashMap, Reduction>, - ) -> Self; +pub type SharedSyntax = + ::Share>; +type PartialReductionReasons = + HashMap, Reduction>; +#[derive(Clone)] +pub enum ReductionReason { + Comparison(SR::Share>), + Explicit, + Rule { + generalisation: SharedSyntax, + variable_mask: VariableMask, + reason: SR::Share, + }, + Inference { + implication: SharedSyntax, + reason: SR::Share, + }, + Default { + operator: CI, + }, + Partial(PartialReductionReasons), + Existence { + substitutions: Substitutions, + generalisation: SharedSyntax, + }, + Recursive { + syntax: SharedSyntax, + reason: SR::Share, + from: SR::Share, + }, + SyntaxCannotReduceToItself, + LeftReducesToRight { + reason: SR::Share, + left: SharedSyntax, + right: SharedSyntax, + }, + RightReducesToLeft { + reason: SR::Share, + left: SharedSyntax, + right: SharedSyntax, + }, } -pub type Reduction = (RRSharedSyntax, RR); +impl Eq for ReductionReason {} -pub type ReductionResult = Option>; +impl Debug for ReductionReason { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Comparison(arg0) => { + f.debug_tuple("Comparison").field(arg0.as_ref()).finish() + }, + Self::Explicit => write!(f, "Explicit"), + Self::Rule { + generalisation, + variable_mask, + reason, + } => f + .debug_struct("Rule") + .field("generalisation", generalisation.as_ref()) + .field( + "variable_mask", + &convert_to_syntax_keys::(variable_mask), + ) + .field("reason", reason.as_ref()) + .finish(), + Self::Inference { + implication, + reason, + } => f + .debug_struct("Inference") + .field("implication", implication.as_ref()) + .field("reason", reason.as_ref()) + .finish(), + Self::Default { + operator, + } => f.debug_struct("Default").field("operator", operator).finish(), + Self::Partial(arg0) => f + .debug_tuple("Partial") + .field( + &arg0 + .iter() + .map(|(k, (v0, v1))| (k, (v0.as_ref(), v1))) + .collect::>(), + ) + .finish(), + Self::Existence { + substitutions, + generalisation, + } => f + .debug_struct("Existence") + .field( + "substitutions", + &convert_to_syntax_keys::, CI, SR>( + substitutions, + ), + ) + .field("generalisation", generalisation.as_ref()) + .finish(), + Self::Recursive { + syntax, + reason, + from, + } => f + .debug_struct("Recursive") + .field("syntax", syntax.as_ref()) + .field("reason", reason.as_ref()) + .field("from", from.as_ref()) + .finish(), + Self::SyntaxCannotReduceToItself => { + write!(f, "SyntaxCannotReduceToItself") + }, + Self::LeftReducesToRight { + reason, + left, + right, + } => f + .debug_struct("LeftReducesToRight") + .field("reason", reason.as_ref()) + .field("left", left.as_ref()) + .field("right", right.as_ref()) + .finish(), + Self::RightReducesToLeft { + reason, + left, + right, + } => f + .debug_struct("RightReducesToLeft") + .field("reason", reason.as_ref()) + .field("left", left.as_ref()) + .field("right", right.as_ref()) + .finish(), + } + } +} +// TODO: implement more efficient way of comparing HashMaps with SharedSyntax values +pub fn convert_to_syntax_keys< + K: Eq + Hash + Clone, + CI: ConceptId, + SR: SharedReference, +>( + h: &HashMap>, +) -> HashMap> { + h.iter().map(|(k, v)| (k.clone(), v.key())).collect() +} -pub type RRSharedSyntax = as SyntaxTree>::SharedSyntax; -type ReductionReasonConceptId = as SyntaxTree>::ConceptId; -pub type RRSyntax = ::Syntax; -pub type SharedSyntax = as SyntaxTree>::SharedSyntax; -pub type Syntax = RRSyntax<::RR>; +type PartialReductionReasonKeys = + HashMap, (SyntaxKey, ReductionReason)>; -macro_rules! impl_reduction_reason { - ($refcounter:tt, $reduction_reason:tt) => { - use crate::{ - context_search::{ComparisonReason, ReductionTruthResult}, - reduction_reason::Reduction, - substitute::Substitutions, - }; - #[derive(Clone, PartialEq, Debug)] - pub enum $reduction_reason { - Comparison($refcounter>), - Explicit, - Rule { - generalisation: S::SharedSyntax, - variable_mask: VariableMask, - reason: $refcounter, +// TODO: implement more efficient way of comparing PartialReductionReasons +fn collect_to_syntax_keys( + h: &PartialReductionReasons, +) -> PartialReductionReasonKeys { + h.iter() + .map(|(k, (v1, v2))| (k.clone(), (v1.key(), v2.clone()))) + .collect::>() +} +impl PartialEq for ReductionReason { + fn eq(&self, other: &Self) -> bool { + match self { + Self::Comparison(c1) => { + matches!(other, Self::Comparison(c2) if c1.as_ref() == c2.as_ref()) }, - Inference { - implication: S::SharedSyntax, - reason: $refcounter, + Self::Explicit => matches!(other, Self::Explicit), + Self::Rule { + generalisation: g1, + variable_mask: vm1, + reason: r1, + } => { + matches!(other, Self::Rule{generalisation: g2, variable_mask: vm2, + reason:r2} if g1.key() == g2.key() && convert_to_syntax_keys::(vm1) == convert_to_syntax_keys::(vm2) && r1.as_ref() == r2.as_ref()) }, - Default { - operator: S::ConceptId, + Self::Inference { + implication: i1, + reason: r1, + } => { + matches!(other, Self::Inference {implication:i2, reason:r2} if i1.as_ref() == i2.as_ref() && r1.as_ref() == r2.as_ref()) }, - Partial(HashMap>), - Existence { - substitutions: Substitutions, - generalisation: S::SharedSyntax, + Self::Default { + operator: o1, + } => matches!(other, Self::Default { operator: o2 } if o1 == o2), + Self::Partial(p1) => { + matches!(other, Self::Partial(p2) if collect_to_syntax_keys(p1) == collect_to_syntax_keys(p2)) }, - Recursive { - syntax: S::SharedSyntax, - reason: $refcounter, - from: $refcounter, + Self::Existence { + substitutions: s1, + generalisation: g1, + } => { + matches!(other, Self::Existence { substitutions: s2, generalisation: g2 } if convert_to_syntax_keys::, CI, SR>(s1)== convert_to_syntax_keys::, CI, SR>(s2) && g1.key() == g2.key()) }, - SyntaxCannotReduceToItself, - LeftReducesToRight { - reason: $refcounter, - left: S::SharedSyntax, - right: S::SharedSyntax, + Self::Recursive { + syntax: s1, + reason: r1, + from: f1, + } => { + matches!(other, Self::Recursive { syntax: s2, reason: r2, from: f2 } if s1.key() == s2.key() && r1.as_ref() == r2.as_ref() && f1.as_ref() == f2.as_ref()) }, - RightReducesToLeft { - reason: $refcounter, - left: S::SharedSyntax, - right: S::SharedSyntax, + Self::SyntaxCannotReduceToItself => todo!(), + Self::LeftReducesToRight { + reason: _, + left: _, + right: _, + } => todo!(), + Self::RightReducesToLeft { + reason: r1, + left: l1, + right: right1, + } => { + matches!(other, Self::RightReducesToLeft { reason: r2, left: l2, right: right2 } if r1.as_ref() == r2.as_ref() && l1.key() == l2.key() && right1.key() == right2.key()) }, } + } +} - impl From>> - for $reduction_reason - { - fn from( - comparison_reason: ComparisonReason<$reduction_reason>, - ) -> Self { - Self::Comparison(comparison_reason.into()) - } - } +impl From> + for ReductionReason +{ + fn from(comparison_reason: ComparisonReason) -> Self { + Self::Comparison(SR::share(comparison_reason)) + } +} - impl $reduction_reason { - fn determine_evidence_of_reduction( - left: &S::SharedSyntax, - right: &S::SharedSyntax, - reduce: impl Fn(&S::SharedSyntax) -> ReductionResult, - ) -> Option { - reduce(left).and_then(|(reduced_left, reason)| { - if &reduced_left == right { - Some(reason) - } else { - Self::determine_evidence_of_reduction( - &reduced_left, - right, - reduce, - ) - .map(|new_reason| Self::Recursive { - syntax: left.clone(), - reason: new_reason.into(), - from: reason.into(), - }) - } +impl ReductionReason { + fn determine_evidence_of_reduction( + left: &SharedSyntax, + right: &SharedSyntax, + reduce: impl Fn(&SharedSyntax) -> ReductionResult, + ) -> Option { + reduce(left).and_then(|(reduced_left, reason)| { + if reduced_left.key() == right.key() { + Some(reason) + } else { + Self::determine_evidence_of_reduction( + &reduced_left, + right, + reduce, + ) + .map(|new_reason| Self::Recursive { + syntax: left.clone(), + reason: SR::share(new_reason), + from: SR::share(reason), }) } - } + }) + } +} - impl ReductionReason for $reduction_reason { - type Syntax = S; +impl ReductionReason { + pub fn simplify_reasoning( + reason: Option, + reversed_reason: Option, + ) -> ComparisonReason { + match (&reason, &reversed_reason) { + (Some(Self::Comparison(cr)), rr) => match cr.as_ref() { + ComparisonReason::Reduction { + reason: comparsion_reason, + reversed_reason: reversed_comparison_reason, + } if rr == reversed_comparison_reason => { + ComparisonReason::Reduction { + reversed_reason: reversed_comparison_reason.clone(), + reason: comparsion_reason.clone(), + } + }, + _ => ComparisonReason::Reduction { + reason, + reversed_reason, + }, + }, + (r, Some(Self::Comparison(cr))) => match cr.as_ref() { + ComparisonReason::Reduction { + reason: reversed_comparison_reason, + reversed_reason: comparison_reason, + } if r == comparison_reason => ComparisonReason::Reduction { + reversed_reason: reversed_comparison_reason.clone(), + reason: comparison_reason.clone(), + }, + _ => ComparisonReason::Reduction { + reason, + reversed_reason, + }, + }, + _ => ComparisonReason::Reduction { + reason, + reversed_reason, + }, + } + } - fn simplify_reasoning( - reason: Option, - reversed_reason: Option, - ) -> ComparisonReason { - match (&reason, &reversed_reason) { - (Some(Self::Comparison(cr)), rr) => match cr.as_ref() { - ComparisonReason::Reduction { - reason: comparsion_reason, - reversed_reason: reversed_comparison_reason, - } if rr == reversed_comparison_reason => { - ComparisonReason::Reduction { - reversed_reason: reversed_comparison_reason - .clone(), - reason: comparsion_reason.clone(), - } - }, - _ => ComparisonReason::Reduction { - reason, - reversed_reason, - }, + pub fn determine_reduction_truth( + left: &SharedSyntax, + right: &SharedSyntax, + reduce: impl Fn(&SharedSyntax) -> ReductionResult, + ) -> ReductionTruthResult { + if left.key() == right.key() { + Some((false, Self::SyntaxCannotReduceToItself)) + } else { + match ( + Self::determine_evidence_of_reduction(left, right, &reduce), + Self::determine_evidence_of_reduction(right, left, reduce), + ) { + (Some(_), Some(_)) => panic!( + "{:#?} and {:#?} reduce to each other?!", + left.as_ref(), + right.as_ref() + ), + (Some(reason), None) => Some(( + true, + Self::LeftReducesToRight { + reason: SR::share(reason), + left: left.clone(), + right: right.clone(), }, - (r, Some(Self::Comparison(cr))) => match cr.as_ref() { - ComparisonReason::Reduction { - reason: reversed_comparison_reason, - reversed_reason: comparison_reason, - } if r == comparison_reason => { - ComparisonReason::Reduction { - reversed_reason: reversed_comparison_reason - .clone(), - reason: comparison_reason.clone(), - } - }, - _ => ComparisonReason::Reduction { - reason, - reversed_reason, - }, + )), + (None, Some(reason)) => Some(( + false, + Self::RightReducesToLeft { + reason: SR::share(reason), + left: left.clone(), + right: right.clone(), }, - _ => ComparisonReason::Reduction { - reason, - reversed_reason, - }, - } - } - - fn determine_reduction_truth( - left: &S::SharedSyntax, - right: &S::SharedSyntax, - reduce: impl Fn(&S::SharedSyntax) -> ReductionResult, - ) -> ReductionTruthResult { - if left == right { - Some((false, Self::SyntaxCannotReduceToItself)) - } else { - match ( - Self::determine_evidence_of_reduction( - left, right, &reduce, - ), - Self::determine_evidence_of_reduction( - right, left, reduce, - ), - ) { - (Some(_), Some(_)) => panic!( - "{:#?} and {:#?} reduce to each other?!", - left, right - ), - (Some(reason), None) => Some(( - true, - Self::LeftReducesToRight { - reason: reason.into(), - left: left.clone(), - right: right.clone(), - }, - )), - (None, Some(reason)) => Some(( - false, - Self::RightReducesToLeft { - reason: reason.into(), - left: left.clone(), - right: right.clone(), - }, - )), - (None, None) => None, - } - } + )), + (None, None) => None, } + } + } - fn recursive_reason( - previous: Option, - last: Self, - previously_reduced_syntax: &S::SharedSyntax, - ) -> Self { - previous.map_or(last.clone(), |from| Self::Recursive { - from: from.into(), - reason: last.into(), - syntax: previously_reduced_syntax.clone(), - }) - } + pub fn recursive_reason( + previous: Option, + last: Self, + previously_reduced_syntax: &SharedSyntax, + ) -> Self { + previous.map_or(last.clone(), |from| Self::Recursive { + from: SR::share(from), + reason: SR::share(last), + syntax: previously_reduced_syntax.clone(), + }) + } - fn existence( - substitutions: Substitutions, - generalisation: S::SharedSyntax, - ) -> Self { - Self::Existence { - substitutions, - generalisation, - } - } + pub const fn existence( + substitutions: Substitutions, + generalisation: SharedSyntax, + ) -> Self { + Self::Existence { + substitutions, + generalisation, + } + } - fn inference(implication: S::SharedSyntax, reason: Self) -> Self { - Self::Inference { - implication, - reason: reason.into(), - } - } + pub fn inference(implication: SharedSyntax, reason: Self) -> Self { + Self::Inference { + implication, + reason: SR::share(reason), + } + } - fn explicit() -> Self { - Self::Explicit - } + pub const fn explicit() -> Self { + Self::Explicit + } - fn default(operator: S::ConceptId) -> Self { - Self::Default { - operator, - } - } + pub const fn default(operator: CI) -> Self { + Self::Default { + operator, + } + } - fn rule( - generalisation: S::SharedSyntax, - variable_mask: VariableMask, - reason: Self, - ) -> Self { - Self::Rule { - generalisation, - variable_mask: variable_mask.clone(), - reason: reason.into(), - } - } + pub fn rule( + generalisation: SharedSyntax, + variable_mask: VariableMask, + reason: Self, + ) -> Self { + Self::Rule { + generalisation, + variable_mask, + reason: SR::share(reason), + } + } - fn partial( - partial_reductions: HashMap>, - ) -> Self { - debug_assert!(partial_reductions.len() > 0); - let mut flattened_partial_reductions = hashmap! {}; - for (unreduced_concept, (reduced_concept, reduction_reason)) in - partial_reductions - { - if let Self::Partial(inner_partial_reductions) = - reduction_reason - { - flattened_partial_reductions - .extend(inner_partial_reductions); - } else { - flattened_partial_reductions.insert( - unreduced_concept, - (reduced_concept, reduction_reason), - ); - } - } - Self::Partial(flattened_partial_reductions) + pub fn partial( + partial_reductions: HashMap, Reduction>, + ) -> Self { + debug_assert!(!partial_reductions.is_empty()); + let mut flattened_partial_reductions = hashmap! {}; + for (unreduced_concept, (reduced_concept, reduction_reason)) in + partial_reductions + { + if let Self::Partial(inner_partial_reductions) = reduction_reason { + flattened_partial_reductions.extend(inner_partial_reductions); + } else { + flattened_partial_reductions.insert( + unreduced_concept, + (reduced_concept, reduction_reason), + ); } } - }; + Self::Partial(flattened_partial_reductions) + } } diff --git a/zia/src/single_threaded.rs b/zia/src/single_threaded.rs index c6bb7a84..9e6a189c 100644 --- a/zia/src/single_threaded.rs +++ b/zia/src/single_threaded.rs @@ -1,34 +1,40 @@ use crate::{ - ast::impl_syntax_tree, context::Context as GenericContext, - context_cache::impl_cache, context_delta::{DirectConceptDelta, NestedDelta, SharedDelta}, context_snap_shot::{ConceptId as ContextConceptId, ContextSnapShot}, errors::ZiaResult, - variable_mask_list::impl_variable_mask_list, + nester::SharedReference, }; use std::{fmt::Debug, rc::Rc}; +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct RcFamily; -impl_syntax_tree!(Rc, SingleThreadedSyntaxTree); -impl_cache!(Rc, SingleThreadedContextCache); -impl_variable_mask_list!(Rc, SingleThreadedVariableMaskList); -impl_reduction_reason!(Rc, SingleThreadedReductionReason); +impl SharedReference for RcFamily { + type Share = Rc; + + fn share(owned: T) -> Self::Share { + Rc::new(owned) + } + + fn make_mut(refcounter: &mut Self::Share) -> &mut T { + Rc::make_mut(refcounter) + } +} pub type Context = GenericContext< - ContextSnapShot, - SingleThreadedContextCache< - SingleThreadedReductionReason< - SingleThreadedSyntaxTree, - >, - >, + ContextSnapShot, SharedDirectConceptDelta, - SingleThreadedVariableMaskList>, SharedContextDelta, ContextConceptId, + RcFamily, >; -type SingleThreadedContextDelta = - NestedDelta; +type SingleThreadedContextDelta = NestedDelta< + ContextConceptId, + SharedDirectConceptDelta, + SharedContextDelta, + RcFamily, +>; #[derive(Clone, Default, Debug)] pub struct SharedContextDelta(Rc); diff --git a/zia/src/snap_shot.rs b/zia/src/snap_shot.rs index 3032a58b..00729f68 100644 --- a/zia/src/snap_shot.rs +++ b/zia/src/snap_shot.rs @@ -1,5 +1,5 @@ use crate::{ - ast::SyntaxTree, + ast::GenericSyntaxTree, concepts::{ConceptTrait, ConcreteConceptType, Hand}, context_delta::{ Composition, ConceptDelta, DirectConceptDelta, NestedDelta, @@ -7,6 +7,7 @@ use crate::{ }, errors::{ZiaError, ZiaResult}, mixed_concept::MixedConcept, + nester::SharedReference, }; use std::{ convert::TryFrom, @@ -14,7 +15,7 @@ use std::{ hash::Hash, }; -pub trait Reader +pub trait Reader where SDCD: Clone + AsRef> @@ -37,114 +38,141 @@ where &self, concept_id: Self::ConceptId, ) -> Option>; - fn read_concept< + fn maybe_read_concept< 'a, - D: SharedDelta>, + D: SharedDelta>, >( &'a self, - delta: &NestedDelta, + delta: &NestedDelta, id: Self::ConceptId, - ) -> Self::MixedConcept<'a> { - delta - .get_concept(&id) - .and_then(|cds| { - let mut concept = self.get_concept(id); - for cd in cds { - match cd { - ConceptDelta::Direct(dcd) => match dcd.as_ref() { - DirectConceptDelta::New(delta) => { - debug_assert!(concept.is_none()); // Assert that concept hasn't already been committed - concept = Some((&NewDirectConceptDelta{ + ) -> Option> { + delta.get_concept(&id).and_then(|cds| { + let mut concept = self.get_concept(id); + for cd in cds { + match cd { + ConceptDelta::Direct(dcd) => match dcd.as_ref() { + DirectConceptDelta::New(delta) => { + debug_assert!(concept.is_none()); // Assert that concept hasn't already been committed + concept = Some( + (&NewDirectConceptDelta { delta: delta.clone(), - new_concept_id: id - }).into()); - }, - DirectConceptDelta::Remove(concept_id) => { - debug_assert_eq!(*concept_id, id); - debug_assert!(concept.is_some()); - concept = None; - }, - DirectConceptDelta::Compose { - change, - composition_id, - } => { - debug_assert_eq!(*composition_id, id); - match change { - ValueChange::Create(comp) => { - let [mut left, mut right] = self.concepts_from_composition(delta, *comp); - concept - .as_mut() - .unwrap() - .change_composition(ValueChange::Create( - [&mut left, &mut right], - )) - .unwrap(); - }, - ValueChange::Update { - before, - after, - } => { - let [mut before_left, mut before_right] = self.concepts_from_composition(delta, *before); - let [mut after_left, mut after_right] = self.concepts_from_composition(delta, *after); - concept - .as_mut() - .unwrap() - .change_composition( - ValueChange::Update { - before: [ - &mut before_left, - &mut before_right, - ], - after: [ - &mut after_left, - &mut after_right, - ], - }, - ) - .unwrap(); - }, - ValueChange::Remove(comp) => { - let [mut left, mut right] = self.concepts_from_composition(delta, *comp); - concept - .as_mut() - .unwrap() - .change_composition(ValueChange::Remove( - [&mut left, &mut right], - )) - .unwrap(); - }, - }; - }, - DirectConceptDelta::Reduce { - change, - unreduced_id, - } => { - debug_assert_eq!(*unreduced_id, id); - concept - .as_mut() - .expect("concept must already exist") - .change_reduction(*change); - }, + new_concept_id: id, + }) + .into(), + ); + }, + DirectConceptDelta::Remove(concept_id) => { + debug_assert_eq!(*concept_id, id); + debug_assert!(concept.is_some()); + concept = None; }, - ConceptDelta::Indirect(delta) => { - let c = concept.as_mut().expect("Concept doesn't exist"); - c.apply_indirect(delta); + DirectConceptDelta::Compose { + change, + composition_id, + } => { + debug_assert_eq!(*composition_id, id); + match change { + ValueChange::Create(comp) => { + let [mut left, mut right] = self + .concepts_from_composition( + delta, *comp, + ); + concept + .as_mut() + .unwrap() + .change_composition( + ValueChange::Create([ + &mut left, &mut right, + ]), + ) + .unwrap(); + }, + ValueChange::Update { + before, + after, + } => { + let [mut before_left, mut before_right] = + self.concepts_from_composition( + delta, *before, + ); + let [mut after_left, mut after_right] = + self.concepts_from_composition( + delta, *after, + ); + concept + .as_mut() + .unwrap() + .change_composition( + ValueChange::Update { + before: [ + &mut before_left, + &mut before_right, + ], + after: [ + &mut after_left, + &mut after_right, + ], + }, + ) + .unwrap(); + }, + ValueChange::Remove(comp) => { + let [mut left, mut right] = self + .concepts_from_composition( + delta, *comp, + ); + concept + .as_mut() + .unwrap() + .change_composition( + ValueChange::Remove([ + &mut left, &mut right, + ]), + ) + .unwrap(); + }, + } }, - } + DirectConceptDelta::Reduce { + change, + unreduced_id, + } => { + debug_assert_eq!(*unreduced_id, id); + concept + .as_mut() + .expect("concept must already exist") + .change_reduction(*change); + }, + }, + ConceptDelta::Indirect(delta) => { + let c = + concept.as_mut().expect("Concept doesn't exist"); + c.apply_indirect(delta); + }, } - concept - }) - .unwrap_or_else(|| { - self.get_concept(id) - .unwrap_or_else(|| panic!("No concept with id = {id}")) - }) + } + concept + }) + } + fn read_concept< + 'a, + D: SharedDelta>, + >( + &'a self, + delta: &NestedDelta, + id: Self::ConceptId, + ) -> Self::MixedConcept<'a> { + self.maybe_read_concept(delta, id).unwrap_or_else(|| { + self.get_concept(id) + .unwrap_or_else(|| panic!("No concept with id = {id}")) + }) } fn concepts_from_composition< 'a, - D: SharedDelta>, + D: SharedDelta>, >( &'a self, - delta: &NestedDelta, + delta: &NestedDelta, comp: Composition, ) -> [Self::MixedConcept<'a>; 2] { [ @@ -153,43 +181,38 @@ where ] } fn get_label< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept_id: Self::ConceptId, ) -> Option; fn ast_from_symbol< - Syntax, - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, s: &str, - ) -> Syntax + ) -> GenericSyntaxTree where - Syntax: SyntaxTree, + SR: SharedReference, { self.concept_from_label(delta, s).map_or_else( || s.into(), |concept| { - let syntax = Syntax::from(s); + let syntax = GenericSyntaxTree::::from(s); self.bind_concept_to_syntax(delta, syntax, concept) }, ) } fn bind_concept_to_syntax< - Syntax, - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, - syntax: Syntax, + delta: &NestedDelta, + syntax: GenericSyntaxTree, concept: Self::ConceptId, - ) -> Syntax - where - Syntax: SyntaxTree, - { + ) -> GenericSyntaxTree { if self.concrete_concept_type(delta, concept) == Some(ConcreteConceptType::ExistsSuchThat) { @@ -198,35 +221,38 @@ where syntax.bind_nonquantifier_concept(concept) } } - fn new_syntax_from_concept_that_has_no_label_or_composition<'a, Syntax>( + fn new_syntax_from_concept_that_has_no_label_or_composition<'a>( &'a self, concept: &Self::MixedConcept<'a>, - ) -> Syntax - where - Syntax: SyntaxTree, - { + ) -> GenericSyntaxTree { let quantifier = concept.get_concrete_concept_type() == Some(ConcreteConceptType::ExistsSuchThat); if quantifier { - SyntaxTree::new_quantifier_concept(concept.id()) + GenericSyntaxTree::::new_quantifier_concept( + concept.id(), + ) } else if concept.anonymous_variable() { - SyntaxTree::new_leaf_variable(concept.id()) + GenericSyntaxTree::::new_leaf_variable( + concept.id(), + ) } else { - SyntaxTree::new_constant_concept(concept.id()) + GenericSyntaxTree::::new_constant_concept( + concept.id(), + ) } } fn concept_from_label< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, s: &str, ) -> Option; fn get_reduction_of_composition< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept: Self::ConceptId, ) -> Self::ConceptId { self.read_concept(delta, concept) @@ -244,10 +270,10 @@ where .unwrap_or(concept) } fn is_disconnected< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept: Self::ConceptId, ) -> bool { self.read_concept(delta, concept).get_reduction().is_none() @@ -265,10 +291,10 @@ where .is_none() } fn righthand_of_without_label_is_empty< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, con: Self::ConceptId, ) -> bool { self.concrete_concept_id(delta, ConcreteConceptType::Label) @@ -279,10 +305,10 @@ where .is_none() } fn get_normal_form< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept: Self::ConceptId, ) -> Option { self.read_concept(delta, concept) @@ -290,10 +316,10 @@ where .map(|n| self.get_normal_form(delta, n).unwrap_or(n)) } fn get_concept_of_label< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept: Self::ConceptId, ) -> Option { let label_concept_id = @@ -303,10 +329,10 @@ where .find_as_hand_in_composition_with(label_concept_id, Hand::Right) } fn contains< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, outer: Self::ConceptId, inner: Self::ConceptId, ) -> bool { @@ -322,10 +348,10 @@ where } } fn check_reductions< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, outer_concept: Self::ConceptId, inner_concept: Self::ConceptId, ) -> ZiaResult<()> { @@ -343,10 +369,10 @@ where } fn get_reduction_or_reduction_of_composition< 'a, - D: SharedDelta>, + D: SharedDelta>, >( &'a self, - delta: &NestedDelta, + delta: &NestedDelta, concept: Self::ConceptId, ) -> Self::MixedConcept<'a> { self.read_concept( @@ -357,17 +383,30 @@ where ) } fn concrete_concept_id< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, cc: ConcreteConceptType, ) -> Option; + fn maybe_concrete_concept_type< + D: SharedDelta>, + >( + &self, + delta: &NestedDelta, + concept_id: Self::ConceptId, + ) -> Option { + self.maybe_read_concept(delta, concept_id) + .and_then(|c| c.get_concrete_concept_type()) + } + fn concrete_concept_type< - D: SharedDelta>, + D: SharedDelta>, >( &self, - delta: &NestedDelta, + delta: &NestedDelta, concept_id: Self::ConceptId, - ) -> Option; + ) -> Option { + self.read_concept(delta, concept_id).get_concrete_concept_type() + } } diff --git a/zia/src/substitute.rs b/zia/src/substitute.rs index a9816036..c9bc1117 100644 --- a/zia/src/substitute.rs +++ b/zia/src/substitute.rs @@ -1,14 +1,19 @@ use std::collections::HashMap; -use crate::ast::SyntaxTree; +use crate::{ + ast::{GenericSyntaxTree, SyntaxKey}, + context_cache::SharedSyntax, + mixed_concept::ConceptId, + nester::SharedReference, +}; -pub type Substitutions = HashMap; +pub type Substitutions = HashMap, SharedSyntax>; -pub fn substitute( - syntax: &mut Syntax, - substitutions: &Substitutions, +pub fn substitute( + syntax: &mut GenericSyntaxTree, + substitutions: &Substitutions, ) { - if let Some(substitution) = substitutions.get(syntax) { + if let Some(substitution) = substitutions.get(&syntax.key()) { *syntax = substitution.as_ref().clone(); } else if let Some((left, right)) = syntax.get_expansion_mut() { substitute(left, substitutions); diff --git a/zia/src/variable_mask_list.rs b/zia/src/variable_mask_list.rs index 0252b508..cace75bb 100644 --- a/zia/src/variable_mask_list.rs +++ b/zia/src/variable_mask_list.rs @@ -1,87 +1,83 @@ #![allow(clippy::single_component_path_imports)] +use std::{collections::HashMap, fmt::Debug}; -use std::{collections::HashMap, ops::Deref}; +use crate::{ + context_cache::SharedSyntax, mixed_concept::ConceptId, + nester::SharedReference, reduction_reason::convert_to_syntax_keys, +}; -use crate::ast::SyntaxTree; - -macro_rules! impl_variable_mask_list { - ($refcounter:tt, $vml:tt) => { - use crate::variable_mask_list::{VariableMask, VariableMaskList}; - #[derive(Clone, PartialEq, Debug)] - pub struct $vml { - head: VariableMask, - tail: Option<$refcounter<$vml>>, - } - impl From> for $vml { - fn from(head: VariableMask) -> Self { - Self { - head, - tail: None, - } - } - } - - impl VariableMaskList for $vml { - type Shared = $refcounter<$vml>; - type Syntax = Syntax; - - /// returns None if `head` is equal to one of the nodes. - /// This prevents cycles in reduction evaluations - fn push( - list: &$refcounter, - head: VariableMask, - ) -> Option { - (!list.contains(&head)).then(|| Self { - head, - tail: Some(list.clone()), - }) - } - - fn contains(&self, node: &VariableMask) -> bool { - &self.head == node - || self - .tail - .as_ref() - .map_or(false, |vml| vml.contains(node)) - } - - fn get( - &self, - concept_id: Syntax::ConceptId, - ) -> Option<&Syntax::SharedSyntax> { - self.head.get(&concept_id).or_else(|| { - self.tail.as_ref().and_then(|vml| vml.get(concept_id)) - }) - } +#[derive(Clone)] +pub struct VariableMaskList { + head: VariableMask, + tail: Option>, +} - fn tail(&self) -> Option<&$refcounter> { - self.tail.as_ref() - } +impl PartialEq + for VariableMaskList +{ + fn eq(&self, other: &Self) -> bool { + convert_to_syntax_keys::(&self.head) + == convert_to_syntax_keys::(&other.head) + && self.tail.as_ref().map(std::convert::AsRef::as_ref) + == other.tail.as_ref().map(std::convert::AsRef::as_ref) + } +} +impl Eq for VariableMaskList {} +impl Debug for VariableMaskList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let tail = self.tail.as_ref().map(std::convert::AsRef::as_ref); + f.debug_struct("GenericVariableMaskList") + .field( + "head", + &self + .head + .iter() + .map(|(k, v)| (*k, v.as_ref())) + .collect::>(), + ) + .field("tail", &tail) + .finish() + } +} +impl From> + for VariableMaskList +{ + fn from(head: VariableMask) -> Self { + Self { + head, + tail: None, } - }; + } } -pub(crate) use impl_variable_mask_list; - -pub trait VariableMaskList: Sized + From> { - type Shared: Clone + Deref + From; - type Syntax: SyntaxTree; - fn push( - list: &Self::Shared, - head: VariableMask, - ) -> Option; +impl VariableMaskList { + /// returns None if `head` is equal to one of the nodes. + /// This prevents cycles in reduction evaluations + pub fn push( + list: &SR::Share, + head: VariableMask, + ) -> Option { + (!list.as_ref().contains(&head)).then(|| Self { + head, + tail: Some(list.clone()), + }) + } - fn contains(&self, node: &VariableMask) -> bool; + pub fn contains(&self, node: &VariableMask) -> bool { + convert_to_syntax_keys::(&self.head) + == convert_to_syntax_keys::(node) + || self.tail.as_ref().is_some_and(|vml| vml.as_ref().contains(node)) + } - fn get( - &self, - concept_id: ::ConceptId, - ) -> Option<&::SharedSyntax>; + pub fn get(&self, concept_id: CI) -> Option<&SharedSyntax> { + self.head.get(&concept_id).or_else(|| { + self.tail.as_ref().and_then(|vml| vml.as_ref().get(concept_id)) + }) + } - fn tail(&self) -> Option<&Self::Shared>; + pub const fn tail(&self) -> Option<&SR::Share> { + self.tail.as_ref() + } } -pub type VariableMask = HashMap< - ::ConceptId, - ::SharedSyntax, ->; +pub type VariableMask = HashMap>; diff --git a/zia/tests/lexer.rs b/zia/tests/lexer.rs index fd7019d3..c0ad73f4 100644 --- a/zia/tests/lexer.rs +++ b/zia/tests/lexer.rs @@ -1,3 +1,4 @@ +use assert_matches::assert_matches; use proptest::prelude::*; use zia::{multi_threaded::NEW_CONTEXT, ConceptKind, LexemeCategory}; @@ -45,9 +46,9 @@ fn lexer_indentifies_concrete_concept() { let cont = NEW_CONTEXT.clone(); let lexemes = cont.lex("let"); assert_eq!(lexemes.len(), 1); - assert_eq!( + assert_matches!( lexemes.first().unwrap().category, - LexemeCategory::Concept(ConceptKind::Concrete) + LexemeCategory::Concept(ConceptKind::Concrete { .. }) ); } @@ -56,9 +57,9 @@ fn lexer_indentifies_abstract_concept() { let cont = NEW_CONTEXT.clone(); let lexemes = cont.lex("and"); assert_eq!(lexemes.len(), 1); - assert_eq!( + assert_matches!( lexemes.first().unwrap().category, - LexemeCategory::Concept(ConceptKind::Abstract) + LexemeCategory::Concept(ConceptKind::Abstract { .. }) ); } diff --git a/zia/tests/reductions.rs b/zia/tests/reductions.rs index abfd9958..8a8c8148 100644 --- a/zia/tests/reductions.rs +++ b/zia/tests/reductions.rs @@ -99,10 +99,16 @@ fn redundancy() { assert_eq!(cont.execute("let a b -> c"), ""); assert_eq!( cont.execute("let a b -> c"), - ZiaError::RedundantReduction.to_string() + ZiaError::RedundantReduction { + syntax: "a b".into() + } + .to_string() ); assert_eq!( cont.execute("let c d -> c d"), - ZiaError::RedundantReduction.to_string() + ZiaError::RedundantReduction { + syntax: "c d".into() + } + .to_string() ); } diff --git a/zia/tests/syntax.proptest-regressions b/zia/tests/syntax.proptest-regressions index beb3074a..b504c105 100644 --- a/zia/tests/syntax.proptest-regressions +++ b/zia/tests/syntax.proptest-regressions @@ -6,3 +6,6 @@ # everyone who runs the test benefits from these saved cases. cc 0e86e99d5e09d217c020d6176077975edafc4d4de9fc282a94b6a8ba1c231854 # shrinks to a = "!", b = "a", c = "𑊊" cc 179e5d7b2c463efbd666fa00b99240b90d061cc015d672cdb11aca664e784fd4 # shrinks to a = "b", b = "b", c = "b" +cc 09af4c275247069e7395351d0acff66709b1c5de7fbfa072dd770b8f2dee25c4 # shrinks to a = "(" +cc e9b3362f6b56ee17a4cf67e7bca9a881d980e19e508a8dfc72bad84153d92d02 # shrinks to a = "" +cc 1e17315465e19f95906797d52c33a52d71dad16081e1b2bc2bf9586f8b1b266e # shrinks to a = "a)"