diff --git a/.github/workflows/lines-of-code.yml b/.github/workflows/lines-of-code.yml index ef53e347..fe05ed51 100644 --- a/.github/workflows/lines-of-code.yml +++ b/.github/workflows/lines-of-code.yml @@ -23,23 +23,22 @@ jobs: - name: Run update script run: | function record { - cratePath=$1 + crate_path=$1 name=$2 - if [ -d "$cratePath/src" ] ; then - linesOfRustCode=$(scc -c --no-cocomo -f json -i rs "$cratePath/src" | jq '.[] | .Code'); + if [ -d "$crate_path/src" ] ; then + lines_of_code=$(scc -c --no-cocomo -f json -i rs "$crate_path/src" | jq '.[] | .Code'); else - linesOfRustCode=$(scc -c --no-cocomo -f json -i rs "$cratePath" | jq '.[] | .Code'); + lines_of_code=$(scc -c --no-cocomo -f json -i rs "$crate_path" | jq '.[] | .Code'); fi - echo "\`$name\` has $linesOfRustCode lines of code" >> $GITHUB_STEP_SUMMARY; + echo "\`$name\` has $lines_of_code lines of code" >> $GITHUB_STEP_SUMMARY; curl \ --header "Content-Type: application/json" \ --header "X-POST-ACCESS-KEY: ${{ secrets.PROJECTS_POST_ACCESS_KEY }}" \ - --data "{\"project\":\"$name\",\"language\":\"rust\",\"loc\":$linesOfRustCode}" \ - -w "\nUpdated-project: \n" \ - https://projects.kaleidawave.workers.dev/update-project; + --data "{\"project\":\"$name\",\"language\":\"rust\",\"loc\":$lines_of_code}" \ + https://kaleidawave-projectinformation.web.val.run/update-project; } record "parser" "ezno-parser" diff --git a/.github/workflows/performance-and-size.yml b/.github/workflows/performance-and-size.yml index e248bd27..1db6316d 100644 --- a/.github/workflows/performance-and-size.yml +++ b/.github/workflows/performance-and-size.yml @@ -27,25 +27,37 @@ jobs: - uses: brndnmtthws/rust-action-cargo-binstall@v1 with: - packages: hyperfine + packages: hyperfine ripgrep - name: Install valgrind run: sudo apt-get install valgrind + - name: Get last run + id: get-last-run + run: | + # First result should come up within 10 runs from main + id=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + '/repos/kaleidawave/ezno/actions/runs?branch=main&per_page=10' \ + --jq '[.workflow_runs[] | select(.path == ".github/workflows/examples.yml")][0].id') + echo "run_id=$id" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ github.token }} + - name: Build Ezno run: cargo build --release env: CARGO_PROFILE_RELEASE_DEBUG: true - # TODO need to lookup existing workflow on main - # even if this worked, it might have issues with newer features added in this run - # - name: Get base ezno - # if: github.ref_name != 'main' - # uses: actions/download-artifact@v4 - # continue-on-error: true - # with: - # name: latest-checker - # path: previous-ezno + - name: Get base ezno + if: github.ref_name != 'main' + uses: actions/download-artifact@v4 + continue-on-error: true + with: + name: latest-checker + path: previous-ezno + run-id: ${{ steps.get-last-run.outputs.run_id }} - name: Set compilers id: compilers @@ -134,14 +146,14 @@ jobs: shell: bash if: github.ref_name != 'main' run: | - echo "::group::Running all" + echo "::group::Running with staging" - cat ./checker/specification/specification.md ./checker/specification/staging.md > all.md - cargo run -p ezno-parser --example code_blocks_to_script all.md --comment-headers --out ./all.tsx + cat ./checker/specification/specification.md ./checker/specification/staging.md > with-staging.md + cargo run -p ezno-parser --example code_blocks_to_script with-staging.md --comment-headers --out ./with-staging.tsx - ./target/release/ezno check all.tsx --timings || true + ./target/release/ezno check with-staging.tsx --timings || true + ./target/release/ezno check with-staging.tsx --timings || true - hyperfine -i -L compiler ${{ steps.compilers.outputs.BINARIES }} '{compiler} check all.tsx' echo "::endgroup::" - name: Run checker performance on large file @@ -167,19 +179,24 @@ jobs: run: | IFS=',' read -ra ITEMS <<< ${{ steps.compilers.outputs.BINARIES }} + export RUST_BACKTRACE=1 + for compiler in ${ITEMS[@]}; do echo "::group::Running $compiler" echo "::group::Callgrind" - valgrind --tool=callgrind --callgrind-out-file=cpu-out $compiler check demo.tsx | true - echo "CPU usage:" - head -n100 cpu-out + { + valgrind --tool=callgrind --callgrind-out-file=./cpu-out $compiler check demo.tsx --max-diagnostics 0 + } || true + ls + echo "::notice::CPU usage:$(rg "summary: (.*)" -or '$1' -N --color never ./cpu_out)" echo "::endgroup::" - + echo "::group::Valgrind" - valgrind --log-file=memory-out $compiler check demo.tsx | true - echo "Memory usage:" - cat memory-out + { + valgrind --log-file=memory-out $compiler check demo.tsx --max-diagnostics 0 + } || true + echo "::notice::Memory usage:$(rg "([0-9,]*) bytes allocated" -or '$1' -N --color never memory-out)" echo "::endgroup::" echo "::endgroup::" @@ -205,10 +222,10 @@ jobs: echo "::endgroup::" done - # - name: Upload checker - # if: github.ref == 'main' - # uses: actions/upload-artifact@v4 - # with: - # name: latest-checker - # path: target/release/ezno - # retention-days: 90 + - name: Upload checker + if: github.ref == 'main' + uses: actions/upload-artifact@v4 + with: + name: latest-checker + path: target/release/ezno + retention-days: 90 diff --git a/Cargo.lock b/Cargo.lock index 0ae6d154..20c5e57c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,55 +1,50 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "argh" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219" +checksum = "34ff18325c8a36b82f992e533ece1ec9f9a9db446bd1c14d4f936bac88fcd240" dependencies = [ "argh_derive", "argh_shared", + "rust-fuzzy-search", ] [[package]] name = "argh_derive" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a" +checksum = "adb7b2b83a50d329d5d8ccc620f5c7064028828538bdf5646acd60dc1f767803" dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] name = "argh_shared" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531" +checksum = "a464143cc82dedcdc3928737445362466b7674b5db4e2eb8e869846d6d84f4f6" dependencies = [ "serde", ] -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "binary-serialize-derive" @@ -66,27 +61,27 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "cc" -version = "1.2.0" +version = "1.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" dependencies = [ "shlex", ] @@ -107,19 +102,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "console" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.52.0", -] - [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -146,21 +128,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - [[package]] name = "derive-debug-extras" version = "0.3.0" @@ -178,7 +145,7 @@ checksum = "42e5ddace13a8459cb452b19e01f59f16d3e2049c8b808f338a13eeadc326e33" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] @@ -199,7 +166,7 @@ dependencies = [ "either_n", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] @@ -229,12 +196,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c91ae510829160d5cfb19eb4ae7b6e01d44b767ca8f727c6cee936e53cc9ae5" -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "enum-variants-strings" version = "0.3.0" @@ -254,7 +215,7 @@ dependencies = [ "proc-macro2", "quote", "string-cases", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] @@ -265,12 +226,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -280,7 +241,6 @@ dependencies = [ "argh", "base64", "codespan-reporting", - "console", "console_error_panic_hook", "enum-variants-strings", "ezno-checker", @@ -294,7 +254,7 @@ dependencies = [ "pretty_assertions", "self-replace", "serde", - "serde-wasm-bindgen", + "serde-wasm-bindgen 0.6.5", "serde_json", "simple-json-parser", "tsify", @@ -326,7 +286,6 @@ dependencies = [ "iterator-endiate", "levenshtein", "match_deref", - "ordered-float", "path-absolutize", "regress", "serde", @@ -344,6 +303,7 @@ dependencies = [ "ezno-checker", "ezno-parser", "pretty_assertions", + "simple-markdown-parser", ] [[package]] @@ -380,9 +340,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "file-id" @@ -454,10 +414,22 @@ dependencies = [ ] [[package]] -name = "glob" +name = "getrandom" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "gloo-utils" @@ -485,11 +457,11 @@ dependencies = [ [[package]] name = "inotify" -version = "0.9.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.8.0", "inotify-sys", "libc", ] @@ -511,16 +483,17 @@ checksum = "cab947031a0a0cb37f982ef2a0ab3bacfd3de5ed97dd5c7e98bcc92bba357112" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -558,9 +531,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libredox" @@ -568,32 +541,22 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "libc", "redox_syscall", ] [[package]] name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "macro_rules_attribute" @@ -613,9 +576,9 @@ checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" [[package]] name = "match_deref" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30dd27efba9ccf9069f76ff0b7b65eb293a844d9918e15a36098de609c9aacd7" +checksum = "6653e44fdfe194f0276ecec9460aff0dfbe621f87097984d1816bd62ec626a53" dependencies = [ "proc-macro2", "quote", @@ -630,14 +593,14 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi", - "windows-sys 0.48.0", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] @@ -651,9 +614,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" dependencies = [ "libc", "log", @@ -668,12 +631,11 @@ dependencies = [ [[package]] name = "notify" -version = "6.1.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.6.0", - "crossbeam-channel", + "bitflags 2.8.0", "filetime", "fsevent-sys", "inotify", @@ -681,32 +643,29 @@ dependencies = [ "libc", "log", "mio", + "notify-types", "walkdir", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "notify-debouncer-full" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fd166739789c9ff169e654dc1501373db9d80a4c3f972817c8a4d7cf8f34e" +checksum = "d2d88b1a7538054351c8258338df7c931a590513fb3745e8c15eb9ff4199b8d1" dependencies = [ - "crossbeam-channel", "file-id", "log", "notify", - "parking_lot", + "notify-types", "walkdir", ] [[package]] -name = "num-traits" -version = "0.2.19" +name = "notify-types" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] +checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" [[package]] name = "once_cell" @@ -716,11 +675,11 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.68" +version = "0.10.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "cfg-if", "foreign-types", "libc", @@ -737,20 +696,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", @@ -758,38 +717,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "ordered-float" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65ee1f9701bf938026630b455d5315f490640234259037edb259798b3bcf85e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - [[package]] name = "paste" version = "1.0.15" @@ -832,29 +759,29 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", ] [[package]] @@ -876,24 +803,36 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "rust-fuzzy-search" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a157657054ffe556d8858504af8a672a054a6e0bd9e8ee531059100c0fa11bb2" + [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "same-file" @@ -906,26 +845,20 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "core-foundation", "core-foundation-sys", "libc", @@ -934,9 +867,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -975,13 +908,35 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde-wasm-bindgen" version = "0.6.5" @@ -995,13 +950,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] @@ -1012,14 +967,14 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -1035,15 +990,23 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simple-json-parser" -version = "0.0.2" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "837c5f8866aeabd3ac8addcf50ef1e2779fe8c2a8d74bdd97102bdfe5605c629" +checksum = "401316a5107f070bf2d7e15de68e1412d585226540647d306f296d9a1e1acef9" [[package]] -name = "smallvec" -version = "1.13.2" +name = "simple-markdown-parser" +version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "ba27333f5476b16a7d78585cc0b939209ec5a04b56752e8fbd75ca340f536d89" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "serde", + "serde-wasm-bindgen 0.4.5", + "tsify", + "wasm-bindgen", +] [[package]] name = "source-map" @@ -1077,9 +1040,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1095,17 +1058,18 @@ dependencies = [ "either_n", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] name = "tempfile" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys 0.59.0", @@ -1143,6 +1107,7 @@ checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0" dependencies = [ "gloo-utils", "serde", + "serde-wasm-bindgen 0.5.0", "serde_json", "tsify-macros", "wasm-bindgen", @@ -1157,14 +1122,14 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-width" @@ -1194,36 +1159,46 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-derive" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ab6c8bffb3f89584781211283fb57337d6902faab6eaee38f336977bdf177d" +checksum = "8ab8fdb87408dab27d43267c311c89135b35d13f8b3081e88451ddeff742c93a" dependencies = [ "js-sys", "wasm-bindgen", @@ -1232,9 +1207,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-derive-macro" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87c28b31d27616bc69a891700ef0445d2cbaa0340fdacb145145256d5f5fcbb" +checksum = "f2fbc080f15cb38f447d52bbae64630c2d4925a9ecb5d140d56c0910b69b4cc7" dependencies = [ "proc-macro2", "quote", @@ -1243,9 +1218,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1253,28 +1228,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -1322,22 +1300,13 @@ dependencies = [ "winapi", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -1346,22 +1315,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -1370,46 +1324,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1422,36 +1358,18 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -1460,15 +1378,18 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" +name = "wit-bindgen-rt" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] [[package]] name = "yansi" diff --git a/Cargo.toml b/Cargo.toml index cdd8e08d..273d2569 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,27 +39,26 @@ path = "src/main.rs" # ezno-web-framework = { path = "./plugins/web" } argh = "0.1" -base64 = "0.21" -console = "0.15" +base64 = "0.22" codespan-reporting = "0.11" enum-variants-strings = "0.3" # For `StrComparison` for string comparison -pretty_assertions = "1.3.0" +pretty_assertions = "1.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -simple-json-parser = "0.0.2" +simple-json-parser = "0.0" js-sys = "0.3" [target.'cfg(not(target_family = "wasm"))'.dependencies] # For updating binary -self-replace = "1.3.7" +self-replace = "1.3" # For updating binary and possibly more in the future -native-tls = "0.2.11" +native-tls = "0.2" # For CLI input across multiple lines -multiline-term-input = "0.1.0" +multiline-term-input = "0.1" # For watching files -notify = "6.1.0" -notify-debouncer-full = "0.3.1" +notify = "8" +notify-debouncer-full = "0.5" glob = "0.3" [dependencies.checker] @@ -76,11 +75,14 @@ package = "ezno-parser" [target.'cfg(target_family = "wasm")'.dependencies] wasm-bindgen = "0.2" -wasm-bindgen-derive = "0.2.1" -serde-wasm-bindgen = "0.6.3" -console_error_panic_hook = "0.1.7" +wasm-bindgen-derive = "0.3" +serde-wasm-bindgen = "0.6" +console_error_panic_hook = "0.1" js-sys = "0.3" -tsify = "0.4.5" +tsify = "0.4" + +[dev-dependencies] +pretty_assertions = "1.3.0" [workspace.lints.clippy] all = { level = "deny", priority = -1 } diff --git a/README.md b/README.md index f0c1165e..b049ed43 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A fast and correct TypeScript type checker and compiler with additional experime > [!IMPORTANT] > Ezno is in active development and **does not currently support enough features to check existing projects** (see [blocking issues](https://github.com/kaleidawave/ezno/labels/blocking)). Check out the [getting started guide](./checker/documentation/getting-started.md) for experimenting with what it [currently supports](./checker/specification/specification.md). - + What Ezno is: - A type checker for JavaScript usable through a CLI ([with a LSP also in the works](https://github.com/kaleidawave/ezno/issues/22)) @@ -12,7 +12,7 @@ What Ezno is: - A *imperative* type system that tracks and evaluates the side effects of functions and control flow structures. It is similar to an interpreter, but acts with types instead of *values* and does not run IO, side effects, etc. - A collection of experiments of types. Many are being worked out and are in the prototype stage. Some of the new behaviors benefit JavaScript specifically and others could be applied to other languages - Written in Rust -- [Fast](https://github.com/kaleidawave/ezno/actions/workflows/performance-and-size.yml) and [Small](https://github.com/kaleidawave/ezno/actions/workflows/lines-of-code.yml) +- [Fast](https://kaleidawave-getlatestgithubrun.web.val.run/kaleidawave/ezno/main?workflow=performance) and [Small](https://kaleidawave-getlatestgithubrun.web.val.run/kaleidawave/ezno/main?workflow=lines-of-code) - Open source! [You can help build Ezno!](https://github.com/kaleidawave/ezno/issues?q=is%3Aopen+label%3Agood-first-issue%2Cfeedback-needed) - A challenge to the status quo of type checking, optimisations and compilation through deeper static analysis beyond syntax analysis! @@ -29,6 +29,8 @@ Read more about Ezno (in chronological order) - [A preview of the checker](https://kaleidawave.github.io/posts/a-preview-of-the-checker/) - [The quest continues](https://kaleidawave.github.io/posts/the-quest-continues/) - [Sets, types and type checking](https://kaleidawave.github.io/posts/sets-types-and-type-checking/) (*general post*) +- [Experimental types](https://kaleidawave.github.io/posts/experimental-types/) +- [Mapped types and properties](https://kaleidawave.github.io/posts/mapped-types/) --- @@ -36,10 +38,10 @@ This project is a workspace consisting of a few crates: | Crate | Lines Of Code | Contains | |---|---|---| -| checker | ![checker lines of code](https://projects.kaleidawave.workers.dev/project/ezno-checker/badge) | Stores for types and contexts, type checking logic and optional synthesis over the parser AST | -| parser | ![parser lines of code](https://projects.kaleidawave.workers.dev/project/ezno-parser/badge) | AST definitions, logic for parsing, AST to string and visiting | - - +| checker | ![checker lines of code](https://kaleidawave-projectinformation.web.val.run/project/ezno-checker/badge) | Stores for types and contexts, type checking logic and optional synthesis over the parser AST | +| parser | ![parser lines of code](https://kaleidawave-projectinformation.web.val.run/project/ezno-parser/badge) | AST definitions, logic for parsing, AST to string and visiting | + + ## Help contribute diff --git a/checker/Cargo.toml b/checker/Cargo.toml index 1b2fd01e..c56df7e0 100644 --- a/checker/Cargo.toml +++ b/checker/Cargo.toml @@ -38,16 +38,14 @@ iterator-endiate = "0.2" path-absolutize = { version = "3.0", features = ["use_unix_paths_on_wasm"] } either = "1.6" levenshtein = "1" -ordered-float = "4.2" regress = { version = "0.10", features = ["utf16"] } serde = { version = "1.0", features = ["derive"], optional = true } -simple-json-parser = "0.0.2" +simple-json-parser = "0.0" [target.'cfg(target_family = "wasm")'.dependencies] -tsify = "0.4.5" -# TODO needs unfixed change in source-map -wasm-bindgen = "=0.2.89" +tsify = "0.4" +wasm-bindgen = "0.2" [dependencies.parser] path = "../parser" diff --git a/checker/README.md b/checker/README.md index 4d55a172..3d09766b 100644 --- a/checker/README.md +++ b/checker/README.md @@ -1,5 +1,6 @@ # Ezno's Checker +![checker lines of code](https://kaleidawave-projectinformation.web.val.run/project/ezno-checker/badge) [![crates.io badge](https://img.shields.io/crates/v/ezno-checker?style=flat-square)](https://crates.io/crates/ezno-checker) [![docs.rs badge](https://img.shields.io/docsrs/ezno-checker?style=flat-square)](https://docs.rs/ezno-checker/latest) diff --git a/checker/definitions/internal.ts.d.bin b/checker/definitions/internal.ts.d.bin index c2573ea2..9ff78b9f 100644 Binary files a/checker/definitions/internal.ts.d.bin and b/checker/definitions/internal.ts.d.bin differ diff --git a/checker/definitions/overrides.d.ts b/checker/definitions/overrides.d.ts index b5c0e66f..ce9cf0e4 100644 --- a/checker/definitions/overrides.d.ts +++ b/checker/definitions/overrides.d.ts @@ -359,6 +359,8 @@ interface PropertyDescriptor { enumerable?: boolean; } +declare class Date { } + declare class Object { @Constant static setPrototypeOf(on: object, to: object): object; @@ -457,42 +459,31 @@ declare const document: Document; // declare function createItem(a: any); // ↓↓ Ezno testing functions ↓↓ -@Constant -declare function print_type(...args: Array): void; -@Constant -declare function debug_type(...args: Array): void; -@Constant -declare function print_and_debug_type(...args: Array): void; -@Constant -declare function print_constraint(t: any): void; -@Constant -declare function debug_type_rust(t: any): void; -@Constant -declare function debug_type_rust_independent(t: any): void; - -@Constant -declare function debug_effects_rust(t: () => {}): void; -@Constant -declare function debug_effects(t: () => {}): void; - -@Constant -declare function is_dependent(t: any): void; -@Constant -declare function print_environment_state(): any; - -@Constant -declare function debug_context(): void; -@Constant -declare function context_id(): void; -@Constant -declare function context_id_chain(): void; -@Constant -declare function debug_type_independent(t: any): void; - -// A function, as it should be! -@Constant -declare function satisfies(t: T): T; - -@Constant -declare function compile_type_to_object(): any; +@Constant("ezno:print_type") +declare function print_type(...args: Array): void +@Constant("ezno:debug_type") +declare function debug_type(...args: Array): void +@Constant("ezno:debug_type_independent") +declare function debug_type_independent(...args: Array): void +@Constant("ezno:print_and_debug_type") +declare function print_and_debug_type(...args: Array): void +@Constant("ezno:debug_type_rust") +declare function debug_type_rust(t: any): void +@Constant("ezno:debug_type_rust_independent") +declare function debug_type_rust_independent(t: any): void + +@Constant("ezno:print_constraint") +declare function print_constraint(t: any): void +@Constant("ezno:debug_constraint") +declare function debug_constraint(a: any); + +@Constant("ezno:debug_effects") +declare function debug_effects(t: () => {}): void +@Constant("ezno:debug_effects_rust") +declare function debug_effects_rust(t: () => {}): void + +@Constant("ezno:is_dependent") +declare function is_dependent(t: any): void +@Constant("ezno:print_environment_state") +declare function print_environment_state(): any // ↑↑ Ezno Functions ↑↑ diff --git a/checker/definitions/simple.d.ts b/checker/definitions/simple.d.ts index 01aed46e..7f0c4585 100644 --- a/checker/definitions/simple.d.ts +++ b/checker/definitions/simple.d.ts @@ -1,43 +1,36 @@ // This contains some of definitions from overrides. Some can be removed during development to test things (and to remove things that might be causing a crash) -@Constant +@Constant("ezno:print_type") declare function print_type(...args: Array): void -@Constant +@Constant("ezno:debug_type") declare function debug_type(...args: Array): void -@Constant +@Constant("ezno:debug_type_independent") declare function debug_type_independent(...args: Array): void -@Constant +@Constant("ezno:print_and_debug_type") declare function print_and_debug_type(...args: Array): void -@Constant -declare function print_constraint(t: any): void -@Constant +@Constant("ezno:debug_type_rust") declare function debug_type_rust(t: any): void -@Constant +@Constant("ezno:debug_type_rust_independent") declare function debug_type_rust_independent(t: any): void -@Constant -declare function debug_effects_rust(t: () => {}): void -@Constant +@Constant("ezno:debug_constraint") +declare function debug_constraint(a: any); +@Constant("ezno:print_constraint") +declare function print_constraint(t: any): void + +@Constant("ezno:debug_effects") declare function debug_effects(t: () => {}): void +@Constant("ezno:debug_effects_rust") +declare function debug_effects_rust(t: () => {}): void -@Constant +@Constant("ezno:is_dependent") declare function is_dependent(t: any): void -@Constant +@Constant("ezno:print_environment_state") declare function print_environment_state(): any -@Constant -declare function debug_context(): void -@Constant -declare function context_id(): void -@Constant -declare function context_id_chain(): void - -@Constant -declare function debug_state(): void - -// A function, as it should be! -@Constant -declare function satisfies(t: YE): YE +// // A function, as it should be! +// @Constant +// declare function satisfies(t: YE): YE interface ImportEnv { [key: string]: string; diff --git a/checker/examples/calculate_subtypes.rs b/checker/examples/calculate_subtypes.rs index 72da1ee0..82a07811 100644 --- a/checker/examples/calculate_subtypes.rs +++ b/checker/examples/calculate_subtypes.rs @@ -1,14 +1,13 @@ +use ezno_checker::types::{ + generics::contributions::Contributions, + properties::{PropertyKey, Publicity}, + TypeStore, +}; use ezno_checker::{ features::objects::ObjectBuilder, subtyping::{type_is_subtype, type_is_subtype_object, State, SubTypingOptions}, - types::{ - generics::contributions::Contributions, - properties::{PropertyKey, Publicity}, - TypeStore, - }, - Constant, Environment, PropertyValue, RootContext, TypeId, + Constant, Environment, PropertyValue, RootContext, TypeId, VariableId, }; -use source_map::Nullable; fn main() { let root = RootContext::new_with_primitive_references(); @@ -48,6 +47,8 @@ fn basics(environment: &mut Environment, types: &mut TypeStore) { } fn contributions(environment: &mut Environment, types: &mut TypeStore) { + use source_map::{Nullable, SourceId, SpanWithSource}; + // TODO types API, which doesn't is less hand-holdy let generic_parameter = environment.new_explicit_type_parameter("T", Some(TypeId::NUMBER_TYPE), None, types); @@ -60,22 +61,18 @@ fn contributions(environment: &mut Environment, types: &mut TypeStore) { )]); let or = types.new_or_type(generic_parameter.type_id, object); - let parameter = types.new_function_parameter(or); + let parameter = types.new_function_parameter(or, VariableId(SourceId::NULL, 0), ""); let five = types.new_constant_type(Constant::Number(5f64.try_into().unwrap())); let five_obj = { - let mut basis = ObjectBuilder::new( - None, - types, - source_map::SpanWithSource::NULL, - &mut environment.info, - ); + let mut basis = + ObjectBuilder::new(None, types, SpanWithSource::NULL, &mut environment.info); basis.append( Publicity::Public, PropertyKey::String(std::borrow::Cow::Owned("inner".to_owned())), PropertyValue::Value(five), - source_map::SpanWithSource::NULL, + SpanWithSource::NULL, &mut environment.info, ); basis.build_object() diff --git a/checker/fuzz/Cargo.lock b/checker/fuzz/Cargo.lock index 41ecf126..5e80babb 100644 --- a/checker/fuzz/Cargo.lock +++ b/checker/fuzz/Cargo.lock @@ -1,41 +1,41 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "arbitrary" -version = "1.3.2" +name = "allocator-api2" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] -name = "autocfg" -version = "1.3.0" +name = "arbitrary" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "binary-serialize-derive" -version = "0.0.1" +version = "0.0.3" dependencies = [ "syn-helpers", ] [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "cc" -version = "1.0.98" +version = "1.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "either_n" @@ -138,9 +138,15 @@ dependencies = [ "syn", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ezno-checker" -version = "0.0.16" +version = "0.0.18" dependencies = [ "binary-serialize-derive", "derive-debug-extras", @@ -150,8 +156,8 @@ dependencies = [ "ezno-parser", "iterator-endiate", "levenshtein", - "ordered-float", "path-absolutize", + "regress", "simple-json-parser", "source-map", "temporary-annex", @@ -159,9 +165,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ezno-checker-fuzz" +version = "0.0.0" +dependencies = [ + "ezno-checker", + "libfuzzer-sys", +] + [[package]] name = "ezno-parser" -version = "0.1.5" +version = "0.1.7" dependencies = [ "derive-debug-extras", "derive-enum-from-into", @@ -181,22 +195,20 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "ezno-parser-fuzz" -version = "0.0.0" -dependencies = [ - "ezno-checker", - "libfuzzer-sys", -] - [[package]] name = "ezno-parser-visitable-derive" -version = "0.0.7" +version = "0.0.9" dependencies = [ "string-cases", "syn-helpers", ] +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "get-field-by-type" version = "0.0.4" @@ -228,6 +240,17 @@ dependencies = [ "web-sys", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "iterator-endiate" version = "0.2.1" @@ -236,25 +259,26 @@ checksum = "cab947031a0a0cb37f982ef2a0ab3bacfd3de5ed97dd5c7e98bcc92bba357112" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -266,26 +290,25 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libfuzzer-sys" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" dependencies = [ "arbitrary", "cc", - "once_cell", ] [[package]] name = "log" -version = "0.4.21" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "macro_rules_attribute" @@ -304,28 +327,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" [[package]] -name = "num-traits" -version = "0.2.19" +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "ordered-float" -version = "4.2.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" -dependencies = [ - "num-traits", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "paste" @@ -353,27 +364,43 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] +[[package]] +name = "regress" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ef7fa9ed0256d64a688a3747d0fef7a88851c18a5e1d57f115f38ec2e09366" +dependencies = [ + "hashbrown", + "memchr", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "self-rust-tokenize" @@ -397,18 +424,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -428,20 +455,27 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "simple-json-parser" -version = "0.0.2" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "837c5f8866aeabd3ac8addcf50ef1e2779fe8c2a8d74bdd97102bdfe5605c629" +checksum = "401316a5107f070bf2d7e15de68e1412d585226540647d306f296d9a1e1acef9" [[package]] name = "source-map" @@ -464,9 +498,9 @@ checksum = "a31d23461f9e0fbe756cf9d5a36be93740fe12c8b094409a5f78f0f912ee2b6f" [[package]] name = "syn" -version = "2.0.66" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -536,35 +570,36 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -573,9 +608,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -583,9 +618,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -596,15 +631,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -612,27 +650,27 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -646,48 +684,48 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/checker/specification/Cargo.toml b/checker/specification/Cargo.toml index 81dbbd2b..c36d5d0c 100644 --- a/checker/specification/Cargo.toml +++ b/checker/specification/Cargo.toml @@ -23,3 +23,6 @@ checker = { path = "..", version = "*", package = "ezno-checker", features = [ ] } parser = { path = "../../parser", version = "*", package = "ezno-parser" } pretty_assertions = "1.3.0" + +[build-dependencies] +simple-markdown-parser = { version = "0.0" } diff --git a/checker/specification/README.md b/checker/specification/README.md index 17f841f6..d5c654b3 100644 --- a/checker/specification/README.md +++ b/checker/specification/README.md @@ -11,6 +11,16 @@ These can all be ran as tests using the markdown to Rust test code transpiler in - Blocks can be split into files with a `// in file.ts` comment, below which all code is in the `file.ts` file. Default is `main.tsx` - **Code in blocks is indented with tabs not spaces** +Run +```shell +# Base +cargo test -p ezno-checker-specification +# Base + staging +cargo test -p ezno-checker-specification -F staging +# Base + staging + to_implement +cargo test -p ezno-checker-specification -F all +``` + --- Other tests unrelated to specific checking features can be found in `checker/tests` diff --git a/checker/specification/build.rs b/checker/specification/build.rs index 1c597410..310d197a 100644 --- a/checker/specification/build.rs +++ b/checker/specification/build.rs @@ -1,8 +1,9 @@ -use std::error::Error; -use std::fs::{read_to_string, File}; -use std::io::Write; -use std::mem; -use std::path::Path; +use std::{ + error::Error, + fs::{read_to_string, File}, + io::Write, + path::Path, +}; fn main() -> Result<(), Box> { println!("cargo:rerun-if-changed=specification.md"); @@ -14,7 +15,7 @@ fn main() -> Result<(), Box> { if cfg!(feature = "base") { let specification = read_to_string("./specification.md")?; - markdown_lines_append_test_to_rust(specification.lines().enumerate(), &mut out)?; + specification_to_tests(&specification, &mut out)?; } if cfg!(feature = "staging") { @@ -22,7 +23,7 @@ fn main() -> Result<(), Box> { writeln!(&mut out, "mod staging {{ ").unwrap(); writeln!(&mut out, "use super::{{check_expected_diagnostics, TypeCheckOptions}}; ") .unwrap(); - markdown_lines_append_test_to_rust(staging.lines().enumerate(), &mut out)?; + specification_to_tests(&staging, &mut out)?; writeln!(&mut out, "}}").unwrap(); } @@ -31,151 +32,184 @@ fn main() -> Result<(), Box> { writeln!(&mut out, "mod to_implement {{ ").unwrap(); writeln!(&mut out, "use super::{{check_expected_diagnostics, TypeCheckOptions}}; ") .unwrap(); - markdown_lines_append_test_to_rust(to_implement.lines().enumerate(), &mut out)?; + specification_to_tests(&to_implement, &mut out)?; writeln!(&mut out, "}}").unwrap(); } Ok(()) } -const DEFAULT_FILE_PATH: &str = "main.tsx"; +fn specification_to_tests(source: &str, out: &mut File) -> Result<(), Box> { + let mut current_unit = Unit::empty(); + let mut current_section = ""; -fn markdown_lines_append_test_to_rust( - mut lines: std::iter::Enumerate>, - out: &mut File, -) -> Result<(), Box> { - let mut first_section = true; + // Using the fact that it is linear, we don't need the heading chain + let _ = simple_markdown_parser::parse(source, |item| { + if let simple_markdown_parser::MarkdownElement::Heading { level: 3, text } = item { + let existing = std::mem::replace(&mut current_unit, Unit::empty()); + if !existing.is_empty() { + let _ = existing.to_rust(out); + } - while let Some((heading_idx, line)) = lines.next() { - if let Some(section_heading) = line.strip_prefix("### ") { - if !first_section { + if !current_section.is_empty() { writeln!(out, "}}").unwrap(); } - first_section = false; - let section_heading = heading_to_rust_identifier(section_heading); - writeln!(out, "mod {section_heading} {{").unwrap(); - continue; + current_section = text.0; + writeln!( + out, + "mod {rust_name} {{", + rust_name = heading_to_rust_identifier(current_section) + ) + .unwrap(); + } else if let simple_markdown_parser::MarkdownElement::Heading { level: 4, text } = item { + let existing = std::mem::replace(&mut current_unit, Unit::empty()); + if !existing.is_empty() { + let _ = existing.to_rust(out); + } + current_unit.name = text.0; + } else if let simple_markdown_parser::MarkdownElement::CodeBlock { language: _, code } = + item + { + current_unit.modules = code_to_modules(code); + } else if let simple_markdown_parser::MarkdownElement::Paragraph(item) = item { + if let Some(options) = item.0.strip_prefix("With") { + current_unit.options = options.split(',').collect(); + } + } else if let simple_markdown_parser::MarkdownElement::ListItem { level: _, text } = item { + current_unit.expected_diagnostics.push(text.0); } + }); - if !line.starts_with("#### ") { - continue; - } + if !current_unit.is_empty() { + current_unit.to_rust(out)?; + } + + if !current_section.is_empty() { + writeln!(out, "}}")?; + } + + Ok(()) +} + +struct Module<'a> { + path: &'a str, + code: &'a str, +} - let heading = line.strip_prefix("####").unwrap().trim_start(); - let test_title = heading_to_rust_identifier(heading); +struct Unit<'a> { + name: &'a str, + modules: Vec>, + expected_diagnostics: Vec<&'a str>, + options: Vec<&'a str>, +} - pub struct File<'a> { - path: &'a str, - code: String, +impl Unit<'_> { + pub fn empty() -> Unit<'static> { + Unit { + name: "", + modules: Vec::new(), + expected_diagnostics: Vec::new(), + options: Vec::new(), } + } - // pub struct Block { - // /// Vec for FS tests - // files: Vec, - // expected_diagnostics: Vec, - // options: Vec - // } - - let files = { - let mut files = Vec::::new(); - let mut current_filename = None; - for (_, line) in lines.by_ref() { - // Also handles TSX - if line.starts_with("```ts") { - break; - } - } - let mut code = String::new(); - - for (_, line) in lines.by_ref() { - if let Some(path) = line.strip_prefix("// in ") { - if !code.trim().is_empty() { - files.push(File { - path: current_filename.unwrap_or(DEFAULT_FILE_PATH), - code: mem::take(&mut code), - }); - } - current_filename = Some(path); - continue; - } - if line == "```" { - break; - } - code.push_str(line); - code.push('\n') + pub fn is_empty(&self) -> bool { + self.name.is_empty() + } + + pub fn to_rust(self, out: &mut impl std::io::Write) -> Result<(), Box> { + let heading_idx = 0; + + // &[{code_as_list}], + // &[{expected_diagnostics}], + // {options} + writeln!( + out, + "#[test] fn {rust_name}() {{ + super::check_expected_diagnostics( + \"{heading}\", {heading_idx},", + rust_name = heading_to_rust_identifier(self.name), + heading = self.name, + ) + .unwrap(); + + // Code + { + write!(out, "&[")?; + for Module { path, code } in self.modules { + write!(out, "(\"{path}\",r#\"{code}\"#),")?; } - files.push(File { path: current_filename.unwrap_or(DEFAULT_FILE_PATH), code }); - files - }; - - let (expected_diagnostics, options) = { - let mut expected_diagnostics = Vec::new(); - let mut options = None::>; - for (_, line) in lines.by_ref() { - if let (Some(args), false) = (line.strip_prefix("With "), options.is_some()) { - options = Some(args.split(',').collect()); - } else if line.starts_with("#") { - panic!("block with no diagnostics or break between in {test_title}") - } else if let Some(diagnostic) = line.strip_prefix("-") { - let error = diagnostic.trim().replace('\\', "").replace('"', "\\\""); - expected_diagnostics.push(format!("\"{}\"", error)) - } else if !expected_diagnostics.is_empty() { - break; - } + write!(out, "],")?; + } + + // Diagnostics + { + write!(out, "&[")?; + for diagnostic in self.expected_diagnostics { + // Using two hashest because of private identifers + write!(out, "r##\"{diagnostic}\"##,", diagnostic = diagnostic.replace('\\', ""))?; } - (expected_diagnostics, options) - }; - - let expected_diagnostics = expected_diagnostics.join(", "); - - let heading_idx = heading_idx + 1; - // TODO don't allocate - let code_as_list = files - .into_iter() - .map(|File { path, code }| format!("(\"{path}\",r#\"{code}\"#),")) - .reduce(|mut acc, slice| { - acc.push_str(&slice); - acc - }) - .unwrap(); + write!(out, "],")?; + } - let options = if let Some(options) = options { - let arguments = options - .into_iter() - .map(|value| format!("{value}: true")) - .reduce(|mut acc, slice| { - acc.push_str(&slice); - acc.push_str(", "); - acc - }) - .unwrap(); - format!("Some(super::TypeCheckOptions {{ {arguments}, ..super::TypeCheckOptions::default() }})") + // Options + if !self.options.is_empty() { + write!(out, "Some(super::TypeCheckOptions {{")?; + for option in self.options { + write!(out, "{option}: true, ")?; + } + write!(out, "..super::TypeCheckOptions::default() }})")?; } else { - format!("None") - }; + write!(out, "None")?; + } - writeln!( - out, - "#[test] fn {test_title}() {{ - super::check_expected_diagnostics( - \"{heading}\", {heading_idx}, - &[{code_as_list}], &[{expected_diagnostics}], - {options} - ) - }}", - )?; - } - if !first_section { - writeln!(out, "}}").unwrap(); + writeln!(out, ")}}")?; + Ok(()) } - - Ok(()) } +/// TODO move to `simple_markdown` for links fn heading_to_rust_identifier(heading: &str) -> String { - heading - .replace("...", "") - .replace([' ', '-', '/', '.', '+'], "_") - .replace(['*', '\'', '`', '"', '&', '!', '(', ')', ',', ':'], "") - .to_lowercase() + let mut buf = String::with_capacity(heading.len()); + let mut last_was_underscore = false; + for chr in heading.chars() { + if let '*' | '\'' | '`' | '"' | '&' | '!' | '(' | ')' | '[' | ']' | ',' | '|' | ':' = chr { + continue; + } + if let ' ' | '-' | '/' | '.' | '+' | '#' = chr { + if !last_was_underscore { + buf.push('_'); + last_was_underscore = true; + } + } else { + buf.extend(chr.to_lowercase()); + last_was_underscore = false; + } + } + buf +} + +const DEFAULT_MODULE_PATH: &str = "main.tsx"; + +fn code_to_modules(code: &str) -> Vec { + let mut modules = Vec::::new(); + let mut current_module_name = None; + let mut start: usize = 0; + + for line in code.lines() { + if let Some(path) = line.strip_prefix("// in ") { + let offset = unsafe { line.as_ptr().offset_from(code.as_ptr()) } as usize; + let code = code[start..offset].trim(); + if !code.is_empty() { + let path = current_module_name.unwrap_or(DEFAULT_MODULE_PATH); + modules.push(Module { path, code }); + } + current_module_name = Some(path); + start = offset + line.len(); + } + } + + let path = current_module_name.unwrap_or(DEFAULT_MODULE_PATH); + modules.push(Module { path, code: &code[start..] }); + modules } diff --git a/checker/specification/specification.md b/checker/specification/specification.md index 7e2841af..dbac00b1 100644 --- a/checker/specification/specification.md +++ b/checker/specification/specification.md @@ -2433,6 +2433,8 @@ function func2(a: number) { } ``` +With advanced_numbers + - This equality is always false as GreaterThan<4> and 3 have no overlap - Expected string, found boolean - This equality is always false as LessThan<2> and 6 have no overlap @@ -2518,6 +2520,8 @@ function func(a: string, b: number) { } ``` +With advanced_numbers + - Expected string, found true - Expected null, found boolean @@ -2530,6 +2534,8 @@ function func(a: number) { } ``` +With advanced_numbers + - Expected string, found boolean #### Ranges after operators @@ -2576,6 +2582,8 @@ function func(x: number) { } ``` +With advanced_numbers + - This equality is always false as ExclusiveRange<-5, 5> and 6 have no overlap #### Transistivity @@ -2588,9 +2596,11 @@ function func(a: number, b: number, c: number) { } ``` +With advanced_numbers + - Expected 5, found true -### Operators across conditions +#### Operators across conditions ```ts function func(param: boolean) { @@ -2623,6 +2633,14 @@ function func3(p1: Not, p2: Not) { - This equality is always false as "hi" and Not\ have no overlap +#### NaN + +```ts +const value: string = 0 / 0 + 1; +``` + +- Type NaN is not assignable to type string + ### Statements, declarations and expressions > Some of these are part of synthesis, rather than checking @@ -3008,6 +3026,15 @@ function func(x: X | null) { - No property 'a' on X | null - Expected number, found undefined | string +#### Escape sequences handled + +```ts +const x: "\"" = '"'; +const y: "Hi" = `Hello\``; +``` + +- Type "Hello`" is not assignable to type "Hi" + ### Regular expressions #### `RegExp` constructor @@ -4098,12 +4125,12 @@ type Required = { #### Readonly ```ts -type Mutable = { +type Immutable = { readonly [P in keyof T]: T[P]; }; interface Y { a: string } -declare let x: Mutable; +declare let x: Immutable; x.a = "hi"; ``` @@ -4118,13 +4145,11 @@ type Mutable = { interface Y { readonly a: string } declare let x: Mutable; -x.a = "hi"; x.a = 4; +x.a = "hi"; ``` - - -- Type 4 does not meet property constraint "hi" +- Type 4 does not meet property constraint string #### `as` rewrite @@ -4496,6 +4521,19 @@ function func(param: boolean) { #### Assertions annotation +```ts +declare function isNumber(param: any): asserts param is number; +declare const value: any; + +if (isNumber(value)) { + value satisfies string; +} +``` + +- Expected string, found number + +#### Assertions annotation return type checked + ```ts function func1(param: any): asserts param is number { if (typeof param !== "string") { @@ -4510,9 +4548,7 @@ function func2(param: any): asserts param is boolean { } ``` -> TODO `any` should be parameter name - -- Cannot return asserts any is string because the function is expected to return asserts any is number +- Cannot return asserts param is string because the function is expected to return asserts param is number #### External predicate @@ -4582,8 +4618,47 @@ for (let i = 0; i < 3; i++) { } ``` +With advanced_numbers + - This equality is always false as LessThan<3> and 50 have no overlap +#### Narrowing chains + +```ts +export type User = { username: string, password: string }; +export type AuthPredicate = (username: string, password: string) => boolean; +export type Auth = User | User[] | AuthPredicate; + +function run(auth: Auth) { + if (Array.isArray(auth)) { + auth satisfies number; + } else if (typeof auth === "function") { + auth("hi", 5) satisfies string; + } else { + auth satisfies boolean; + } +} +``` + +- Expected number, found Array\ +- Argument of type 5 is not assignable to parameter of type string +- Expected string, found boolean +- Expected boolean, found { username: string, password: string } + +#### Narrowing free variable + +```ts +function func(value: any) { + function isNumber() { return typeof value === "number" } + + if (isNumber()) { + value satisfies string + } +} +``` + +- Expected string, found number + ### Object constraint > Any references to a annotated variable **must** be within its LHS type. These test that it carries down to objects. @@ -4749,13 +4824,13 @@ proxy1.a satisfies string; #### Proxy subtyping ```ts -const proxy1 = new Proxy({}, { get(_target, prop, _receiver) { return prop } }); +const proxy1 = new Proxy({}, { get(_target, prop, receiver) { return prop } }); proxy1 satisfies { a: "a", b: "b" }; proxy1 satisfies { c: "d" }; ``` -- Expected { c: "d" }, found Proxy [ {}, { get: (_target: any, prop: any, _receiver: any) => any } ] +- Expected { c: "d" }, found Proxy [ {}, { get: (_target: any, prop: any, receiver: any) => any } ] #### Proxy across functions diff --git a/checker/specification/test.rs b/checker/specification/test.rs index b98dd727..001e6a89 100644 --- a/checker/specification/test.rs +++ b/checker/specification/test.rs @@ -1,22 +1,14 @@ -#![allow(unused)] use std::{ - collections::HashSet, panic, path::{Path, PathBuf}, - process, - sync::{Arc, Mutex}, }; use checker::{ - diagnostics, source_map::{Nullable, SourceId}, synthesis::EznoParser, TypeCheckOptions, }; -// This is here as it is used in the included `/specification.rs` -use parser::ASTNode; - mod specification { use super::{check_expected_diagnostics, TypeCheckOptions}; diff --git a/checker/specification/to_implement.md b/checker/specification/to_implement.md index 5856c16b..f1708540 100644 --- a/checker/specification/to_implement.md +++ b/checker/specification/to_implement.md @@ -541,20 +541,6 @@ a satisfies string; - Expected string, found [7, 6] -#### Optional interface property - -> TODO needs `Logical`-ish `PropertyValue` - -```ts -declare const global: { a?: string }; - -("a" in global) satisfies string; -(global.a) satisfies 2; -``` - -- Expected string, found boolean -- Expected 2, found string | undefined - ### Runtime #### Free variable + anytime calls @@ -606,7 +592,7 @@ class MyClass { ((new MyClass).getA() satisfies 3); ``` -- Cannot get private property "#a" +- Cannot get private property '#a' - Expected 3, found 2 #### Implements diff --git a/checker/src/context/environment.rs b/checker/src/context/environment.rs index 2c5decc7..c077e550 100644 --- a/checker/src/context/environment.rs +++ b/checker/src/context/environment.rs @@ -79,7 +79,7 @@ impl DynamicBoundaryKind { } } -impl<'a> ContextType for Syntax<'a> { +impl ContextType for Syntax<'_> { fn as_general_context(et: &Context) -> GeneralContext<'_> { GeneralContext::Syntax(et) } @@ -238,16 +238,16 @@ impl Scope { } } -impl<'a> Environment<'a> { +impl Environment<'_> { /// Handles all assignments, including updates and destructuring /// /// Will evaluate the expression with the right timing and conditions, including never if short circuit - pub fn assign_handle_errors<'b, T: crate::ReadFromFS, A: crate::ASTImplementation>( + pub fn assign_handle_errors<'a, T: crate::ReadFromFS, A: crate::ASTImplementation>( &mut self, lhs: Assignable, operator: AssignmentKind, // Can be `None` for increment and decrement - expression: Option<&'b A::Expression<'b>>, + expression: Option<&'a A::Expression<'a>>, assignment_position: Span, checking_data: &mut CheckingData, ) -> TypeId { @@ -1337,11 +1337,11 @@ impl<'a> Environment<'a> { None } - pub fn declare_interface<'b, A: crate::ASTImplementation>( + pub fn declare_interface<'a, A: crate::ASTImplementation>( &mut self, name: &str, - parameters: Option<&'b [A::TypeParameter<'b>]>, - extends: Option<&'b [A::TypeAnnotation<'b>]>, + parameters: Option<&'a [A::TypeParameter<'a>]>, + extends: Option<&'a [A::TypeAnnotation<'a>]>, types: &mut TypeStore, ) -> Result { // Interface merging @@ -1396,10 +1396,10 @@ impl<'a> Environment<'a> { } /// Registers the class type - pub fn declare_class<'b, A: crate::ASTImplementation>( + pub fn declare_class<'a, A: crate::ASTImplementation>( &mut self, name: &str, - type_parameters: Option<&'b [A::TypeParameter<'b>]>, + type_parameters: Option<&'a [A::TypeParameter<'a>]>, types: &mut TypeStore, ) -> Result { { @@ -1460,10 +1460,10 @@ impl<'a> Environment<'a> { Ok(class_type) } - pub fn declare_alias<'b, A: crate::ASTImplementation>( + pub fn declare_alias<'a, A: crate::ASTImplementation>( &mut self, name: &str, - parameters: Option<&'b [A::TypeParameter<'b>]>, + parameters: Option<&'a [A::TypeParameter<'a>]>, _position: Span, types: &mut TypeStore, ) -> Result { @@ -1493,11 +1493,11 @@ impl<'a> Environment<'a> { } // TODO copy this logic for interface and class - pub fn register_alias<'b, U: crate::ReadFromFS, A: crate::ASTImplementation>( + pub fn register_alias<'a, U: crate::ReadFromFS, A: crate::ASTImplementation>( &mut self, on: TypeId, - ast_parameters: Option<&'b [A::TypeParameter<'b>]>, - to: &'b A::TypeAnnotation<'b>, + ast_parameters: Option<&'a [A::TypeParameter<'a>]>, + to: &'a A::TypeAnnotation<'a>, position: Span, checking_data: &mut CheckingData, ) { diff --git a/checker/src/context/information.rs b/checker/src/context/information.rs index 6f13dcd8..4a2d23f4 100644 --- a/checker/src/context/information.rs +++ b/checker/src/context/information.rs @@ -284,7 +284,7 @@ pub struct ModuleInformation<'a> { pub module: &'a LocalInformation, } -impl<'a> InformationChain for ModuleInformation<'a> { +impl InformationChain for ModuleInformation<'_> { fn get_chain_of_info(&self) -> impl Iterator { IntoIterator::into_iter([self.top, self.module]) } @@ -383,9 +383,11 @@ pub fn merge_info( if let Some(otherwise) = otherwise { onto.extend(otherwise, None); } else { + let options = + crate::features::narrowing::NarrowingOptions { number_intrinsics: false }; // Could negate existing, but starting again handles types better let values = crate::features::narrowing::narrow_based_on_expression_into_vec( - condition, true, parents, types, + condition, true, parents, types, &options, ); onto.narrowed_values = values; diff --git a/checker/src/context/mod.rs b/checker/src/context/mod.rs index 8749cdbe..7576cc1c 100644 --- a/checker/src/context/mod.rs +++ b/checker/src/context/mod.rs @@ -285,7 +285,7 @@ impl Context { } } - pub(crate) fn debug(&self) -> String { + pub(crate) fn _debug(&self) -> String { use std::fmt::Write; const INDENT: &str = "\t"; @@ -1002,11 +1002,11 @@ pub enum AssignmentError { value_type: TypeStringRepresentation, value_position: SpanWithSource, }, - PropertyConstraint { - property_constraint: TypeStringRepresentation, - value_type: TypeStringRepresentation, - assignment_position: SpanWithSource, - }, + // PropertyConstraint { + // property_constraint: TypeStringRepresentation, + // value_type: TypeStringRepresentation, + // assignment_position: SpanWithSource, + // }, VariableUsedInTDZ(VariableUsedInTDZ), } diff --git a/checker/src/diagnostics.rs b/checker/src/diagnostics.rs index 2d1afed0..7b8b5c15 100644 --- a/checker/src/diagnostics.rs +++ b/checker/src/diagnostics.rs @@ -274,9 +274,47 @@ impl TypeStringRepresentation { }); Self::from_property_constraint(*on, generics, ctx, types, debug_mode) } - crate::types::logical::Logical::BasedOnKey { .. } => { - Self("TODO based on key?".to_owned()) + crate::types::logical::Logical::BasedOnKey( + crate::types::logical::BasedOnKey::Left { value, key_arguments }, + ) => { + let property_generics = GenericChainLink::MappedPropertyLink { + parent_link: generics.as_ref(), + value: &key_arguments, + }; + // let value = *value; + // if let crate::types::logical::Logical::Pure(ref value) = value { + + // if let crate::types::properties::PropertyValue::Value(value) = value.inner_simple() { + // let value = if let Some(crate::types::CovariantContribution::TypeId(value)) = + // property_generics.get_argument_covariant(*value) + // { + // value + // } else { + // *value + // }; + + // let ty = types.get_type_by_id(value); + // crate::utilities::notify!("{:?}", ty); + + // // Skip interface stuff + // if let crate::Type::Constructor(crate::types::Constructor::Property { result, .. }) = ty { + // let value = print_type_with_type_arguments(*result, Some(property_generics), types, ctx, debug_mode); + // return Self(value) + // } + // } + // } + // crate::utilities::notify!("{:?}", value); + Self::from_property_constraint( + *value, + Some(property_generics), + ctx, + types, + debug_mode, + ) } + crate::types::logical::Logical::BasedOnKey( + crate::types::logical::BasedOnKey::Right(_right), + ) => Self("TODO BasedOnKey::Right".to_owned()), } } } @@ -557,17 +595,17 @@ impl From> for Diagnostic { )], kind, }, - AssignmentError::PropertyConstraint { - property_constraint: property_type, - value_type, - assignment_position, - } => Diagnostic::Position { - reason: format!( - "Type {value_type} does not meet property constraint {property_type}" - ), - position: assignment_position, - kind, - }, + // AssignmentError::PropertyConstraint { + // property_constraint: property_type, + // value_type, + // assignment_position, + // } => Diagnostic::Position { + // reason: format!( + // "Type {value_type} does not meet property constraint {property_type}" + // ), + // position: assignment_position, + // kind, + // }, AssignmentError::Constant(position) => Diagnostic::Position { reason: "Cannot assign to constant".into(), position, diff --git a/checker/src/features/conditional.rs b/checker/src/features/conditional.rs index d46db3a3..080328bf 100644 --- a/checker/src/features/conditional.rs +++ b/checker/src/features/conditional.rs @@ -36,6 +36,10 @@ where }; } + let options = crate::features::narrowing::NarrowingOptions { + number_intrinsics: checking_data.options.advanced_numbers, + }; + let (truthy_result, truthy_info) = { let mut truthy_environment = environment .new_lexical_environment(Scope::Conditional { antecedent: condition, is_switch: None }); @@ -45,6 +49,7 @@ where false, environment, &mut checking_data.types, + &options, ); crate::utilities::notify!("Narrowed value {:?} in true branch", values); @@ -80,6 +85,7 @@ where true, environment, &mut checking_data.types, + &options, ); crate::utilities::notify!("Narrowed value {:?} in false branch", values); diff --git a/checker/src/features/constant_functions.rs b/checker/src/features/constant_functions.rs index ecf8497b..494c0c4a 100644 --- a/checker/src/features/constant_functions.rs +++ b/checker/src/features/constant_functions.rs @@ -3,7 +3,6 @@ use source_map::SpanWithSource; use crate::{ context::{ - get_on_ctx, information::{InformationChain, ObjectProtectionState}, invocation::CheckThings, }, @@ -104,9 +103,7 @@ pub(crate) fn call_constant_function( "abs" => num.abs(), _ => unreachable!(), }; - - let Ok(num) = result.try_into() else { return Ok(ConstantOutput::Value(TypeId::NAN)) }; - Ok(ConstantOutput::Value(types.new_constant_type(Constant::Number(num)))) + Ok(ConstantOutput::Value(types.new_constant_type(Constant::Number(result)))) } "imul" => { if let [x, y] = arguments { @@ -114,7 +111,7 @@ pub(crate) fn call_constant_function( (types.get_type_by_id(x.value), types.get_type_by_id(y.value)) { // TODO is this correct, what about overflow? - let result = (x.into_inner() as i32) * (y.into_inner() as i32); + let result = (*x as i32) * (*y as i32); Ok(ConstantOutput::Value( types.new_constant_type(Constant::Number(result.into())), )) @@ -133,11 +130,7 @@ pub(crate) fn call_constant_function( let result = types.new_constant_type(match id { "toUpperCase" => Constant::String(s.to_uppercase()), "toLowerCase" => Constant::String(s.to_lowercase()), - "string_length" => Constant::Number( - (s.encode_utf16().count() as f64) - .try_into() - .map_err(|_| ConstantFunctionError::CannotComputeConstant)?, - ), + "string_length" => Constant::Number(s.encode_utf16().count() as f64), _ => unreachable!(), }); Ok(ConstantOutput::Value(result)) @@ -146,14 +139,10 @@ pub(crate) fn call_constant_function( Err(ConstantFunctionError::CannotComputeConstant) } } - "debug_number" => { - let arg = arguments.iter().next().unwrap(); - Ok(ConstantOutput::Diagnostic(format!( - "number: {:?}", - crate::types::intrinsics::get_range_and_mod_class(arg.value, types) - ))) - } - "print_type" | "debug_type" | "print_and_debug_type" | "debug_type_independent" => { + "ezno:print_type" + | "ezno:debug_type" + | "ezno:print_and_debug_type" + | "ezno:debug_type_independent" => { fn to_string( print: bool, debug: bool, @@ -194,7 +183,7 @@ pub(crate) fn call_constant_function( Ok(ConstantOutput::Diagnostic(buf)) } } - "print_constraint" => { + "ezno:print_constraint" | "ezno:debug_constraint" => { let ty = arguments .first() .ok_or(ConstantFunctionError::CannotComputeConstant)? @@ -206,13 +195,15 @@ pub(crate) fn call_constant_function( .find_map(|i| i.object_constraints.get(&ty).copied()); if let Some(constraint) = constraint { - let constraint_as_string = print_type(constraint, types, environment, false); + crate::utilities::notify!("constraint={:?}", constraint); + let debug = id == "ezno:debug_constraint"; + let constraint_as_string = print_type(constraint, types, environment, debug); Ok(ConstantOutput::Diagnostic(format!("Constraint is: {constraint_as_string}"))) } else { Ok(ConstantOutput::Diagnostic("No associate constraint".to_owned())) } } - "debug_type_rust" | "debug_type_rust_independent" => { + "ezno:debug_type_rust" | "ezno:debug_type_rust_independent" => { let id = arguments .first() .ok_or(ConstantFunctionError::CannotComputeConstant)? @@ -222,7 +213,7 @@ pub(crate) fn call_constant_function( let ty = types.get_type_by_id(id); Ok(ConstantOutput::Diagnostic(format!("Type is: {id:?} = {ty:?}"))) } - "debug_effects" | "debug_effects_rust" => { + "ezno:debug_effects" | "ezno:debug_effects_rust" => { let ty = arguments .first() .ok_or(ConstantFunctionError::CannotComputeConstant)? @@ -662,19 +653,12 @@ pub(crate) fn call_constant_function( Err(ConstantFunctionError::CannotComputeConstant) } } - // "RegExp:constructor" => { - // crate::utilities::notify!("TODO check argument"); - // if let Some(arg) = arguments.first() { - // Ok(ConstantOutput::Value(features::regular_expressions::new_regexp(features::regular_expressions::TypeIdOrString::TypeId(arg), types, environment))) - // } else { - // Err(ConstantFunctionError::CannotComputeConstant) - // } - // } // TODO "JSON:parse" => { crate::utilities::notify!("TODO JSON:parse"); Err(ConstantFunctionError::CannotComputeConstant) } + // TODO "JSON:stringify" => { crate::utilities::notify!("TODO JSON:stringify"); Err(ConstantFunctionError::CannotComputeConstant) @@ -752,32 +736,32 @@ pub(crate) fn call_constant_function( // Ok(ConstantOutput::Diagnostic(output)) // } // } - "debug_state" => { - Ok(ConstantOutput::Diagnostic(format!("State={:?}", environment.info.state))) - } - "debug_context" => Ok(ConstantOutput::Diagnostic(environment.debug())), - "context_id" => Ok(ConstantOutput::Diagnostic(format!("in {:?}", environment.context_id))), - "context_id_chain" => Ok(ConstantOutput::Diagnostic({ - use std::fmt::Write; - let mut buf = format!("{:?}", environment.context_id); - for ctx in environment.parents_iter().skip(1) { - write!(&mut buf, " <- {:?}", get_on_ctx!(ctx.context_id)) - .map_err(|_| ConstantFunctionError::CannotComputeConstant)?; - } - buf - })), - "is_dependent" => Ok(ConstantOutput::Diagnostic(format!( - "is dependent {:?}", - types - .get_type_by_id( - arguments - .first() - .ok_or(ConstantFunctionError::CannotComputeConstant)? - .non_spread_type() - .map_err(|()| ConstantFunctionError::CannotComputeConstant)? - ) - .is_dependent() - ))), + // "debug_state" => { + // Ok(ConstantOutput::Diagnostic(format!("State={:?}", environment.info.state))) + // } + // "debug_context" => Ok(ConstantOutput::Diagnostic(environment.debug())), + // "context_id" => Ok(ConstantOutput::Diagnostic(format!("in {:?}", environment.context_id))), + // "context_id_chain" => Ok(ConstantOutput::Diagnostic({ + // use std::fmt::Write; + // let mut buf = format!("{:?}", environment.context_id); + // for ctx in environment.parents_iter().skip(1) { + // write!(&mut buf, " <- {:?}", get_on_ctx!(ctx.context_id)) + // .map_err(|_| ConstantFunctionError::CannotComputeConstant)?; + // } + // buf + // })), + // "is_dependent" => Ok(ConstantOutput::Diagnostic(format!( + // "is dependent {:?}", + // types + // .get_type_by_id( + // arguments + // .first() + // .ok_or(ConstantFunctionError::CannotComputeConstant)? + // .non_spread_type() + // .map_err(|()| ConstantFunctionError::CannotComputeConstant)? + // ) + // .is_dependent() + // ))), // "compile_type_to_object" => { // if let Some(value) = call_site_type_args { // let value = crate::types::others::create_object_for_type( diff --git a/checker/src/features/functions.rs b/checker/src/features/functions.rs index 43081834..9978e5cd 100644 --- a/checker/src/features/functions.rs +++ b/checker/src/features/functions.rs @@ -5,7 +5,6 @@ use source_map::{Nullable, SourceId, SpanWithSource}; use crate::{ context::{ environment::{ContextLocation, ExpectedReturnType, FunctionScope}, - get_on_ctx, information::{merge_info, LocalInformation}, ContextType, Syntax, }, @@ -381,7 +380,7 @@ pub struct ClassPropertiesToRegister<'a, A: crate::ASTImplementation> { pub properties: Vec>, } -impl<'a, A: crate::ASTImplementation> FunctionRegisterBehavior<'a, A> { +impl FunctionRegisterBehavior<'_, A> { #[must_use] pub fn is_async(&self) -> bool { match self { @@ -941,15 +940,18 @@ where } } - // TODO collect here because of lifetime mutation issues from closed over + // TODO has to collect here because of lifetime mutation issues from closed over let continues_to_close_over = function_closes_over .into_iter() .filter(|r| match r { RootReference::Variable(id) => { // Keep if body does not contain id - let contains = base_environment - .parents_iter() - .any(|c| get_on_ctx!(&c.variable_names).contains_key(id)); + let contains = base_environment.parents_iter().any(|c| { + crate::context::get_on_ctx!(&c.variables) + .values() + .map(crate::features::variables::VariableOrImport::get_id) + .any(|vid| vid == *id) + }); crate::utilities::notify!("v-id {:?} con {:?}", id, contains); contains @@ -1061,7 +1063,7 @@ fn get_expected_parameters_from_type( .into_iter() .map(|p| SynthesisedParameter { ty: substitute( - if let Type::RootPolyType(PolyNature::Parameter { fixed_to }) = + if let Type::RootPolyType(PolyNature::Parameter { fixed_to, .. }) = types.get_type_by_id(p.ty) { *fixed_to diff --git a/checker/src/features/iteration.rs b/checker/src/features/iteration.rs index e638cbb1..4197de48 100644 --- a/checker/src/features/iteration.rs +++ b/checker/src/features/iteration.rs @@ -59,6 +59,10 @@ pub fn synthesise_iteration( max_inline: checking_data.options.max_inline_count, }; + let options = crate::features::narrowing::NarrowingOptions { + number_intrinsics: checking_data.options.advanced_numbers, + }; + match behavior { IterationBehavior::While(condition) => { let (condition, result, ..) = environment.new_lexical_environment_fold_into_parent( @@ -77,6 +81,7 @@ pub fn synthesise_iteration( false, environment, &mut checking_data.types, + &options, ); crate::utilities::notify!("{:?}", values); @@ -256,6 +261,7 @@ pub fn synthesise_iteration( false, environment, &mut checking_data.types, + &options, ); crate::utilities::notify!( @@ -307,6 +313,7 @@ pub fn synthesise_iteration( false, environment, &mut checking_data.types, + &options, ); environment.info.narrowed_values = values; @@ -365,10 +372,13 @@ pub fn synthesise_iteration( checking_data, ); + // TODO not parameter. Is free variable let variable = checking_data.types.register_type(Type::RootPolyType(PolyNature::Parameter { - // TODO can do `"prop1" | "prop2" | "prop3" | ...` + // TODO can do `"prop1" | "prop2" | "prop3" | ...`. Item of rhs. fixed_to: TypeId::STRING_TYPE, + // TODO temp + variable_id: VariableId(environment.get_source(), 0), })); let ((), result, ..) = environment.new_lexical_environment_fold_into_parent( @@ -770,7 +780,7 @@ impl LoopStructure { } pub fn known_to_never_exist(self, types: &TypeStore) -> bool { - self.calculate_iterations_f64(types).map_or(false, f64::is_infinite) + self.calculate_iterations_f64(types).is_ok_and(f64::is_infinite) } fn calculate_iterations_f64(self, types: &TypeStore) -> Result { diff --git a/checker/src/features/mod.rs b/checker/src/features/mod.rs index 0af0ae5f..6044d2c0 100644 --- a/checker/src/features/mod.rs +++ b/checker/src/features/mod.rs @@ -28,7 +28,7 @@ use crate::{ diagnostics::TypeStringRepresentation, events::RootReference, types::{ - get_constraint, helpers, + self, logical::{Logical, LogicalOrValid}, properties, PartiallyAppliedGenerics, TypeStore, }, @@ -63,14 +63,14 @@ pub(crate) fn string_name_to_type(name: &str) -> Option { /// Returns result of `typeof *on*` pub fn type_of_operator(on: TypeId, types: &mut TypeStore) -> TypeId { - if let Some(constraint) = get_constraint(on, types) { + if let Some(constraint) = types::get_constraint(on, types) { if let Some(str_name) = type_to_js_string_name(constraint) { // TODO make them interal types under `TypeId::*` as to not recreate types types.new_constant_type(crate::Constant::String(str_name.to_owned())) } else { // TODO if always object or function then could get more accurate tag - types.register_type(crate::Type::Constructor(crate::types::Constructor::TypeOperator( - crate::types::TypeOperator::TypeOf(on), + types.register_type(crate::Type::Constructor(types::Constructor::TypeOperator( + types::TypeOperator::TypeOf(on), ))) } } else { @@ -78,7 +78,7 @@ pub fn type_of_operator(on: TypeId, types: &mut TypeStore) -> TypeId { if let crate::Type::Constant(cst) = ty { // TODO backing type let name = match cst { - crate::Constant::NaN | crate::Constant::Number(_) => "number", + crate::Constant::Number(_) => "number", crate::Constant::String(_) => "string", crate::Constant::Boolean(_) => "boolean", crate::Constant::Symbol { key: _ } => "symbol", @@ -122,7 +122,7 @@ pub fn instance_of_operator( ) -> TypeId { let rhs_prototype = if let Type::SpecialObject(SpecialObject::Function(func, _)) = types.get_type_by_id(rhs) { - use crate::types::functions::FunctionBehavior; + use types::functions::FunctionBehavior; let func = types.get_function_from_id(*func); match &func.behavior { @@ -140,6 +140,7 @@ pub fn instance_of_operator( instance_of_operator_rhs_prototype(lhs, rhs_prototype, information, types) } +/// TODO Lhs conditional pub(crate) fn instance_of_operator_rhs_prototype( lhs: TypeId, rhs_prototype: TypeId, @@ -147,11 +148,18 @@ pub(crate) fn instance_of_operator_rhs_prototype( types: &mut TypeStore, ) -> TypeId { // TODO frozen prototypes - if let Some(constraint) = get_constraint(lhs, types) { - if let Type::PartiallyAppliedGenerics(crate::types::PartiallyAppliedGenerics { + crate::utilities::notify!("{:?}", lhs); + if let Some(constraint) = types::get_constraint(lhs, types) { + crate::utilities::notify!("constraint {:?}", lhs); + let raw_constraint = types::helpers::get_aliased(constraint, types).unwrap_or(constraint); + if raw_constraint == rhs_prototype { + return TypeId::TRUE; + } + let raw_constraint_ty = types.get_type_by_id(raw_constraint); + if let Type::PartiallyAppliedGenerics(types::PartiallyAppliedGenerics { on, arguments: _, - }) = types.get_type_by_id(constraint) + }) = raw_constraint_ty { if *on == rhs_prototype { return TypeId::TRUE; @@ -159,13 +167,19 @@ pub(crate) fn instance_of_operator_rhs_prototype( crate::utilities::notify!("Here?"); } - types.register_type(Type::Constructor(crate::types::Constructor::TypeOperator( - crate::types::TypeOperator::IsPrototype { lhs, rhs_prototype }, + types.register_type(Type::Constructor(types::Constructor::TypeOperator( + types::TypeOperator::HasPrototype { lhs, rhs_prototype }, ))) - } else if extends_prototype(lhs, rhs_prototype, information) { - TypeId::TRUE + } else if let Type::Object(types::ObjectNature::RealDeal) = types.get_type_by_id(lhs) { + let extends = extends_prototype(lhs, rhs_prototype, information); + if extends { + TypeId::TRUE + } else { + TypeId::FALSE + } } else { - TypeId::FALSE + crate::utilities::notify!("TODO might be missed case"); + TypeId::OPEN_BOOLEAN_TYPE } } @@ -176,14 +190,17 @@ pub fn await_expression( checking_data: &mut CheckingData, position: SpanWithSource, ) -> TypeId { - if let Some(constraint) = get_constraint(on, &checking_data.types) { + let types = &checking_data.types; + if let Some(constraint) = types::get_constraint(on, types) { + let raw_constraint = types::helpers::get_aliased(constraint, types).unwrap_or(constraint); + // TODO mark type as awaited - let inner_type = get_promise_value(constraint, &checking_data.types); + let inner_type = get_promise_value(raw_constraint, types); if let Some(result) = inner_type { crate::utilities::notify!("Queue await effect"); checking_data .types - .register_type(Type::Constructor(crate::types::Constructor::Awaited { on, result })) + .register_type(Type::Constructor(types::Constructor::Awaited { on, result })) } else { crate::utilities::notify!( "Await on {:?}, got {:?}", @@ -227,9 +244,8 @@ pub(crate) fn create_closed_over_references( .map(|reference| { match reference { RootReference::Variable(on) => { - let c = None::< - &crate::types::generics::substitution::SubstitutionArguments<'static>, - >; + let c = + None::<&types::generics::substitution::SubstitutionArguments<'static>>; let value = get_value_of_variable(current_environment, *on, c, types); let ty = if let Some(value) = value { @@ -278,7 +294,7 @@ pub fn delete_operator( { let constraint = - environment.get_object_constraint(rhs).or_else(|| get_constraint(rhs, types)); + environment.get_object_constraint(rhs).or_else(|| types::get_constraint(rhs, types)); if let Some(constraint) = constraint { let constraint_type = types.get_type_by_id(constraint); @@ -361,7 +377,7 @@ pub fn delete_operator( // Cannot `delete` from non-configurable if let Ok(LogicalOrValid::Logical(Logical::Pure(value))) = - crate::types::properties::get_property_unbound( + types::properties::get_property_unbound( (rhs, None), (publicity, &under, None), false, @@ -384,9 +400,9 @@ pub fn delete_operator( // ); // TODO not great - let dependency = if get_constraint(rhs, types).is_some() { - Some(types.register_type(Type::Constructor(crate::types::Constructor::TypeOperator( - crate::types::TypeOperator::HasProperty(rhs, under.into_owned()), + let dependency = if types::get_constraint(rhs, types).is_some() { + Some(types.register_type(Type::Constructor(types::Constructor::TypeOperator( + types::TypeOperator::HasProperty(rhs, under.into_owned()), )))) } else { None @@ -404,11 +420,10 @@ pub fn in_operator( types: &mut TypeStore, ) -> TypeId { // TODO if any - if get_constraint(rhs, types).is_some() { - let dependency = - types.register_type(Type::Constructor(crate::types::Constructor::TypeOperator( - crate::types::TypeOperator::HasProperty(rhs, under.into_owned()), - ))); + if types::get_constraint(rhs, types).is_some() { + let dependency = types.register_type(Type::Constructor(types::Constructor::TypeOperator( + types::TypeOperator::HasProperty(rhs, under.into_owned()), + ))); environment.info.events.push(crate::events::Event::Miscellaneous( crate::events::MiscellaneousEvents::Has { @@ -431,7 +446,7 @@ pub(crate) fn has_property( information: &impl InformationChain, types: &mut TypeStore, ) -> TypeId { - if let Some((condition, truthy, falsy)) = helpers::get_type_as_conditional(rhs, types) { + if let Some((condition, truthy, falsy)) = types::helpers::get_type_as_conditional(rhs, types) { let truthy_result = has_property((publicity, key), truthy, information, types); let otherwise_result = has_property((publicity, key), falsy, information, types); types.new_conditional_type(condition, truthy_result, otherwise_result) @@ -494,7 +509,7 @@ pub(crate) fn has_property( } Type::RootPolyType(_) | Type::Constructor(_) => { crate::utilities::notify!("Queue event / create dependent"); - let constraint = get_constraint(rhs, types).unwrap(); + let constraint = types::get_constraint(rhs, types).unwrap(); has_property((publicity, key), constraint, information, types) } } diff --git a/checker/src/features/modules.rs b/checker/src/features/modules.rs index 3f876dcb..fae56735 100644 --- a/checker/src/features/modules.rs +++ b/checker/src/features/modules.rs @@ -415,26 +415,31 @@ pub fn import_file( let (mut file_path, mut definition_file_path) = (None::, None::); // TODO JSON parse error - let _res = simple_json_parser::parse_with_exit_signal(&package_json, |path, value| { - // if let Some(ref export) = export { - // todo!() - // } else { - if let [JSONKey::Slice("main")] = path { - if let RootJSONValue::String(s) = value { - file_path = Some(s.to_owned().into()); - } else { - // invalid type - } - } else if let [JSONKey::Slice("types")] = path { - if let RootJSONValue::String(s) = value { - definition_file_path = Some(s.to_owned().into()); - } else { - // invalid type + let _res = simple_json_parser::parse_with_exit_signal( + &package_json, + |path, value| { + // if let Some(ref export) = export { + // todo!() + // } else { + if let [JSONKey::Slice("main")] = path { + if let RootJSONValue::String(s) = value { + file_path = Some(s.to_owned().into()); + } else { + // invalid type + } + } else if let [JSONKey::Slice("types")] = path { + if let RootJSONValue::String(s) = value { + definition_file_path = Some(s.to_owned().into()); + } else { + // invalid type + } } - } - // } - file_path.is_some() && definition_file_path.is_some() - }); + // } + file_path.is_some() && definition_file_path.is_some() + }, + false, + true, + ); file_path.ok_or(()).map(|entry| { (package_root.join(entry), definition_file_path.map(|dfp| package_root.join(dfp))) diff --git a/checker/src/features/narrowing.rs b/checker/src/features/narrowing.rs index 52d840be..248e9f40 100644 --- a/checker/src/features/narrowing.rs +++ b/checker/src/features/narrowing.rs @@ -10,14 +10,19 @@ use crate::{ use super::operations::{CanonicalEqualityAndInequality, MathematicalOrBitwiseOperation}; +pub struct NarrowingOptions { + pub number_intrinsics: bool, +} + pub fn narrow_based_on_expression_into_vec( condition: TypeId, negate: bool, information: &impl InformationChain, types: &mut TypeStore, + options: &NarrowingOptions, ) -> Map { let mut into = Default::default(); - narrow_based_on_expression(condition, negate, &mut into, information, types); + narrow_based_on_expression(condition, negate, &mut into, information, types, options); into.iter_mut().for_each(|(on, value)| *value = types.new_narrowed(*on, *value)); into } @@ -28,6 +33,7 @@ pub fn narrow_based_on_expression( into: &mut Map, information: &impl InformationChain, types: &mut TypeStore, + options: &NarrowingOptions, ) { let r#type = types.get_type_by_id(condition); if let Type::Constructor(constructor) = r#type { @@ -48,7 +54,6 @@ pub fn narrow_based_on_expression( let type_from_name = crate::features::string_name_to_type(c); if let Some(type_from_name) = type_from_name { if negate { - crate::utilities::notify!("{:?}", from); // TODO temp fix let narrowed_to = if let Some(TypeId::ANY_TYPE) = crate::types::get_constraint(from, types) @@ -59,6 +64,10 @@ pub fn narrow_based_on_expression( types, ) } else { + crate::utilities::notify!( + "type_from_name={:?}", + type_from_name + ); let mut result = Vec::new(); build_union_from_filter( from, @@ -71,7 +80,27 @@ pub fn narrow_based_on_expression( }; into.insert(origin, narrowed_to); } else { - into.insert(origin, type_from_name); + let narrowed_to = if let Some(TypeId::ANY_TYPE) = + crate::types::get_constraint(from, types) + { + type_from_name + } else { + // crate::utilities::notify!("type_from_name={:?}", type_from_name); + let mut result = Vec::new(); + build_union_from_filter( + from, + Filter::IsType(type_from_name), + &mut result, + information, + types, + ); + if result.is_empty() { + type_from_name + } else { + types.new_or_type_from_iterator(result) + } + }; + into.insert(origin, narrowed_to); } } else { crate::utilities::notify!("Type name was (shouldn't be here)"); @@ -81,7 +110,7 @@ pub fn narrow_based_on_expression( } } else if let Type::Constructor(Constructor::BinaryOperator { lhs: operand, - operator: MathematicalOrBitwiseOperation::Modulo, + operator: MathematicalOrBitwiseOperation::Remainder, rhs: modulo, result: _, }) = lhs_type @@ -165,9 +194,23 @@ pub fn narrow_based_on_expression( }) = types.get_type_by_id(get_origin(lhs, types)) { if crate::types::helpers::type_equal(*truthy_result, rhs, types) { - narrow_based_on_expression(*condition, false, into, information, types); + narrow_based_on_expression( + *condition, + false, + into, + information, + types, + options, + ); } else if crate::types::helpers::type_equal(*otherwise_result, rhs, types) { - narrow_based_on_expression(*condition, true, into, information, types); + narrow_based_on_expression( + *condition, + true, + into, + information, + types, + options, + ); } } // PROPERTY NARROWING HERE (x.a: b => x: {a: b}) @@ -211,9 +254,9 @@ pub fn narrow_based_on_expression( lhs, operator: CanonicalEqualityAndInequality::LessThan, rhs, - } => { + } if options.number_intrinsics => { if negate { - crate::utilities::notify!("Skipping negate on less"); + crate::utilities::notify!("Skipping negate on LessThan result"); return; } let lhs = get_origin(*lhs, types); @@ -224,7 +267,7 @@ pub fn narrow_based_on_expression( rhs, types, ); - // TODO need to merge. This is very bad + // TODO might need to update to narrower type let narrowed_to = if let Some(existing) = into.get(&lhs) { crate::utilities::notify!("Here"); types.new_and_type(*existing, narrowed_to) @@ -239,7 +282,7 @@ pub fn narrow_based_on_expression( lhs, types, ); - // TODO need to merge. This is very bad + // TODO might need to update to narrower type let narrowed_to = if let Some(existing) = into.get(&rhs) { crate::utilities::notify!("Here"); types.new_and_type(narrowed_to, *existing) @@ -249,7 +292,7 @@ pub fn narrow_based_on_expression( into.insert(rhs, narrowed_to); } } - Constructor::TypeOperator(TypeOperator::IsPrototype { lhs, rhs_prototype }) => { + Constructor::TypeOperator(TypeOperator::HasPrototype { lhs, rhs_prototype }) => { let (lhs, rhs_prototype) = (*lhs, *rhs_prototype); let constraint = crate::types::get_constraint(lhs, types).unwrap_or(lhs); // TODO want a mix of two @@ -260,6 +303,12 @@ pub fn narrow_based_on_expression( let filter = Filter::HasPrototype(rhs_prototype); let filter = if negate { Filter::Not(&filter) } else { filter }; build_union_from_filter(constraint, filter, &mut result, information, types); + crate::utilities::notify!( + "Here {:?} {:?} result={:?}", + lhs, + types.get_type_by_id(lhs), + result + ); types.new_or_type_from_iterator(result) }; into.insert(lhs, narrowed_to); @@ -303,15 +352,32 @@ pub fn narrow_based_on_expression( } constructor => { if let Some(condition) = as_logical_not(constructor, types) { - narrow_based_on_expression(condition, !negate, into, information, types); + narrow_based_on_expression( + condition, + !negate, + into, + information, + types, + options, + ); } else if let Some((lhs, rhs)) = as_logical_and(constructor, types) { // De Morgan's laws if negate { // OR: Pull assertions from left and right, merge if both branches assert something - let lhs_requests = - narrow_based_on_expression_into_vec(lhs, negate, information, types); - let rhs_requests = - narrow_based_on_expression_into_vec(rhs, negate, information, types); + let lhs_requests = narrow_based_on_expression_into_vec( + lhs, + negate, + information, + types, + options, + ); + let rhs_requests = narrow_based_on_expression_into_vec( + rhs, + negate, + information, + types, + options, + ); for (on, lhs_request) in lhs_requests { if let Some(rhs_request) = rhs_requests.get(&on) { @@ -331,25 +397,56 @@ pub fn narrow_based_on_expression( } } else { // AND: Pull assertions from left and right - narrow_based_on_expression(lhs, negate, into, information, types); - narrow_based_on_expression(rhs, negate, into, information, types); + narrow_based_on_expression(lhs, negate, into, information, types, options); + narrow_based_on_expression(rhs, negate, into, information, types, options); } } else if let Some((lhs, rhs)) = as_logical_or(constructor, types) { // De Morgan's laws if negate { // AND: Pull assertions from left and right - narrow_based_on_expression(lhs, negate, into, information, types); - narrow_based_on_expression(rhs, negate, into, information, types); + narrow_based_on_expression(lhs, negate, into, information, types, options); + narrow_based_on_expression(rhs, negate, into, information, types, options); } else { // OR: Pull assertions from left and right, merge if both branches assert something - let lhs_requests = - narrow_based_on_expression_into_vec(lhs, negate, information, types); - let rhs_requests = - narrow_based_on_expression_into_vec(rhs, negate, information, types); + let lhs_requests = narrow_based_on_expression_into_vec( + lhs, + negate, + information, + types, + options, + ); + let rhs_requests = narrow_based_on_expression_into_vec( + rhs, + negate, + information, + types, + options, + ); + + crate::utilities::notify!( + "lhs={}, rhs={}", + crate::types::printing::print_type(lhs, types, information, true), + crate::types::printing::print_type(rhs, types, information, true) + ); for (on, lhs_request) in lhs_requests { if let Some(rhs_request) = rhs_requests.get(&on) { let rhs_request = *rhs_request; + crate::utilities::notify!( + "merging lhs={}, rhs={}", + crate::types::printing::print_type( + lhs_request, + types, + information, + true + ), + crate::types::printing::print_type( + rhs_request, + types, + information, + true + ) + ); let (lhs_request, rhs_request) = ( crate::types::get_constraint(lhs_request, types) .unwrap_or(lhs_request), @@ -363,7 +460,33 @@ pub fn narrow_based_on_expression( } } } else { - crate::utilities::notify!("Here?, {:?}", constructor); + let constraint = crate::types::get_constraint(condition, types).unwrap(); + if let Type::Constructor(Constructor::TypeExtends( + crate::types::TypeExtends { .. }, + )) = types.get_type_by_id(constraint) + { + // TODO why isn't this collapsed during calling + narrow_based_on_expression( + constraint, + negate, + into, + information, + types, + options, + ); + } else { + crate::utilities::notify!("Here?, {:?}", constructor); + let mut result = Vec::new(); + build_union_from_filter( + condition, + Filter::from_boolean_cast(!negate), + &mut result, + information, + types, + ); + let narrowed_to = types.new_or_type_from_iterator(result); + into.insert(condition, narrowed_to); + } } } } @@ -371,11 +494,11 @@ pub fn narrow_based_on_expression( if rpt.get_constraint() == TypeId::BOOLEAN_TYPE { let result = if negate { TypeId::FALSE } else { TypeId::TRUE }; into.insert(condition, result); - } else if !negate { + } else { let mut result = Vec::new(); - super::narrowing::build_union_from_filter( + build_union_from_filter( condition, - super::narrowing::NOT_FASLY, + Filter::from_boolean_cast(!negate), &mut result, information, types, @@ -404,10 +527,10 @@ pub(crate) enum Filter<'a> { static NULL_OR_UNDEFINED: Filter<'static> = Filter::NullOrUndefined; pub(crate) static NOT_NULL_OR_UNDEFINED: Filter<'static> = Filter::Not(&NULL_OR_UNDEFINED); -pub(crate) static FASLY: Filter<'static> = Filter::Falsy; -pub(crate) static NOT_FASLY: Filter<'static> = Filter::Not(&FASLY); +pub(crate) static FALSY: Filter<'static> = Filter::Falsy; +pub(crate) static NOT_FALSY: Filter<'static> = Filter::Not(&FALSY); -impl<'a> Filter<'a> { +impl Filter<'_> { // Returns `true` if `value` passes filter pub(crate) fn type_matches_filter( &self, @@ -433,22 +556,23 @@ impl<'a> Filter<'a> { } } Filter::HasPrototype(prototype) => { + let ty = types.get_type_by_id(value); if let Type::PartiallyAppliedGenerics(types::PartiallyAppliedGenerics { on: gen_on, arguments: _, - }) = types.get_type_by_id(value) + }) = ty { let is_equal = prototype == gen_on; let allowed_match = !negate; (allowed_match && is_equal) || (!allowed_match && !is_equal) - } else if let Type::Object(types::ObjectNature::RealDeal) = - types.get_type_by_id(value) - { + } else if let Type::Object(types::ObjectNature::RealDeal) = ty { // This branch can be triggered by conditionals let extends = crate::features::extends_prototype(value, *prototype, information); let allowed_match = !negate; (allowed_match && extends) || (!allowed_match && !extends) + } else if let Some(ty) = types::helpers::get_constraint_or_alias(value, types) { + self.type_matches_filter(ty, information, types, negate) } else { let is_equal = value == *prototype; let allowed_match = !negate; @@ -496,6 +620,14 @@ impl<'a> Filter<'a> { } } } + + pub(crate) fn from_boolean_cast(like: bool) -> Filter<'static> { + if like { + NOT_FALSY + } else { + FALSY + } + } } /// Important that this does not handle `any` well with negated filters. It needs to generate negated types but only has non-mutable access to `TypeStore` @@ -507,7 +639,7 @@ pub(crate) fn build_union_from_filter( information: &impl InformationChain, types: &TypeStore, ) { - if let Some(constraint) = crate::types::get_constraint(on, types) { + if let Some(constraint) = types::helpers::get_constraint_or_alias(on, types) { build_union_from_filter(constraint, filter, found, information, types); } else if let TypeId::BOOLEAN_TYPE = on { build_union_from_filter(TypeId::TRUE, filter, found, information, types); diff --git a/checker/src/features/operations/logical.rs b/checker/src/features/operations/logical.rs index 25ecfc72..0f63e575 100644 --- a/checker/src/features/operations/logical.rs +++ b/checker/src/features/operations/logical.rs @@ -38,7 +38,7 @@ pub fn evaluate_logical_operation_with_expression< let mut result = Vec::new(); narrowing::build_union_from_filter( constraint, - narrowing::FASLY, + narrowing::FALSY, &mut result, env, &checking_data.types, @@ -60,7 +60,7 @@ pub fn evaluate_logical_operation_with_expression< let mut result = Vec::new(); narrowing::build_union_from_filter( constraint, - narrowing::NOT_FASLY, + narrowing::NOT_FALSY, &mut result, env, &checking_data.types, diff --git a/checker/src/features/operations/mathematical_bitwise.rs b/checker/src/features/operations/mathematical_bitwise.rs index 240e659a..5169a89e 100644 --- a/checker/src/features/operations/mathematical_bitwise.rs +++ b/checker/src/features/operations/mathematical_bitwise.rs @@ -10,7 +10,7 @@ pub enum MathematicalOrBitwiseOperation { Subtract, Multiply, Divide, - Modulo, + Remainder, Exponent, BitwiseShiftLeft, BitwiseShiftRight, @@ -66,7 +66,7 @@ pub fn evaluate_mathematical_operation( MathematicalOrBitwiseOperation::Subtract => lhs - rhs, MathematicalOrBitwiseOperation::Multiply => lhs * rhs, MathematicalOrBitwiseOperation::Divide => lhs / rhs, - MathematicalOrBitwiseOperation::Modulo => lhs % rhs, + MathematicalOrBitwiseOperation::Remainder => lhs % rhs, MathematicalOrBitwiseOperation::Exponent => lhs.powf(rhs), MathematicalOrBitwiseOperation::BitwiseShiftLeft => { f64::from((lhs as i32).checked_shl(rhs as u32).unwrap_or(0)) @@ -87,11 +87,7 @@ pub fn evaluate_mathematical_operation( f64::from((lhs as i32) | (rhs as i32)) } }; - let value = ordered_float::NotNan::try_from(value); - let ty = match value { - Ok(value) => types.new_constant_type(Constant::Number(value)), - Err(_) => TypeId::NAN, - }; + let ty = types.new_constant_type(Constant::Number(value)); Ok(ty) } (lhs, rhs) => { diff --git a/checker/src/features/operations/mod.rs b/checker/src/features/operations/mod.rs index a0e3855f..5c0e3e5b 100644 --- a/checker/src/features/operations/mod.rs +++ b/checker/src/features/operations/mod.rs @@ -10,3 +10,8 @@ pub use relation::{ EqualityAndInequality, EqualityAndInequalityResultKind, }; pub use unary::{evaluate_unary_operator, UnaryOperation}; + +pub struct OperatorOptions { + pub advanced_numbers: bool, + pub strict_casts: bool, +} diff --git a/checker/src/features/operations/relation.rs b/checker/src/features/operations/relation.rs index b703e135..904bea82 100644 --- a/checker/src/features/operations/relation.rs +++ b/checker/src/features/operations/relation.rs @@ -37,7 +37,7 @@ pub fn evaluate_equality_inequality_operation( mut rhs: TypeId, info: &impl crate::context::InformationChain, types: &mut crate::types::TypeStore, - strict_casts: bool, + options: &super::OperatorOptions, ) -> Result<(TypeId, EqualityAndInequalityResultKind), ()> { // `NaN == t` is always true if lhs == TypeId::NAN || rhs == TypeId::NAN { @@ -51,7 +51,7 @@ pub fn evaluate_equality_inequality_operation( if let (Type::Constant(lhs), Type::Constant(rhs)) = (types.get_type_by_id(lhs), types.get_type_by_id(rhs)) { - let result = if lhs == rhs { TypeId::TRUE } else { TypeId::FALSE }; + let result = if lhs.equals(rhs) { TypeId::TRUE } else { TypeId::FALSE }; return Ok((result, EqualityAndInequalityResultKind::Constant)); } @@ -81,7 +81,7 @@ pub fn evaluate_equality_inequality_operation( let left_dependent = types.get_type_by_id(lhs).is_dependent(); // Sort if `*constant* == ...`. Ideally want constant type on the RHS - let (lhs, rhs) = if left_dependent { (lhs, rhs) } else { (rhs, rhs) }; + let (lhs, rhs) = if left_dependent { (lhs, rhs) } else { (rhs, lhs) }; let operator = CanonicalEqualityAndInequality::StrictEqual; let result_ty = types.register_type(Type::Constructor(Constructor::CanonicalRelationOperator { @@ -91,29 +91,13 @@ pub fn evaluate_equality_inequality_operation( })); Ok((result_ty, EqualityAndInequalityResultKind::Condition)) - - // } else { - // match attempt_constant_equality(lhs, rhs, types) { - // Ok(ty) => Ok(( - // if ty { TypeId::TRUE } else { TypeId::FALSE }, - // EqualityAndInequalityResultKind::Constant, - // )), - // Err(()) => { - // unreachable!( - // "should have been caught `is_dependent` above, {:?} === {:?}", - // types.get_type_by_id(lhs), - // types.get_type_by_id(rhs) - // ) - // } - // } - // } } EqualityAndInequality::LessThan => { fn attempt_less_than( lhs: TypeId, rhs: TypeId, types: &mut crate::types::TypeStore, - strict_casts: bool, + options: &super::OperatorOptions, ) -> Result { // Similar but reversed semantics to add match (types.get_type_by_id(lhs), types.get_type_by_id(rhs)) { @@ -125,8 +109,8 @@ pub fn evaluate_equality_inequality_operation( Ok(string1 < string2) } (Type::Constant(c1), Type::Constant(c2)) => { - let lhs = cast_as_number(c1, strict_casts)?; - let rhs = cast_as_number(c2, strict_casts)?; + let lhs = cast_as_number(c1, options.strict_casts)?; + let rhs = cast_as_number(c2, options.strict_casts)?; Ok(lhs < rhs) } (lhs, rhs) => { @@ -141,6 +125,7 @@ pub fn evaluate_equality_inequality_operation( || types.get_type_by_id(rhs).is_dependent(); if either_is_dependent { + // Tidies some things for counting loop iterations { if let Type::Constructor(Constructor::BinaryOperator { lhs: op_lhs, @@ -162,18 +147,16 @@ pub fn evaluate_equality_inequality_operation( } } + if !helpers::simple_subtype(lhs, TypeId::NUMBER_TYPE, info, types) + || !helpers::simple_subtype(rhs, TypeId::NUMBER_TYPE, info, types) { - if !helpers::simple_subtype(lhs, TypeId::NUMBER_TYPE, info, types) - || !helpers::simple_subtype(rhs, TypeId::NUMBER_TYPE, info, types) - { - return Err(()); - } + return Err(()); + } + if options.advanced_numbers { let lhs = get_constraint(lhs, types).unwrap_or(lhs); let rhs = get_constraint(rhs, types).unwrap_or(rhs); - // Tidies some things for counting loop iterations - // Checking disjoint-ness for inequalities (TODO under option) via distribution if let ((Some(lhs_range), _), (Some(rhs_range), _)) = ( intrinsics::get_range_and_mod_class(lhs, types), @@ -221,7 +204,7 @@ pub fn evaluate_equality_inequality_operation( EqualityAndInequalityResultKind::Condition, )) } else { - attempt_less_than(lhs, rhs, types, strict_casts).map(|value| { + attempt_less_than(lhs, rhs, types, options).map(|value| { ( if value { TypeId::TRUE } else { TypeId::FALSE }, EqualityAndInequalityResultKind::Constant, @@ -237,7 +220,7 @@ pub fn evaluate_equality_inequality_operation( rhs, info, types, - strict_casts, + options, )?; if equality_result == TypeId::TRUE { @@ -249,7 +232,7 @@ pub fn evaluate_equality_inequality_operation( rhs, info, types, - strict_casts, + options, ) } else { let (less_than_result, warning) = evaluate_equality_inequality_operation( @@ -258,7 +241,7 @@ pub fn evaluate_equality_inequality_operation( rhs, info, types, - strict_casts, + options, )?; Ok((types.new_logical_or_type(equality_result, less_than_result), warning)) } @@ -270,7 +253,7 @@ pub fn evaluate_equality_inequality_operation( rhs, info, types, - strict_casts, + options, )?; if let EqualityAndInequalityResultKind::Condition = kind { Ok((types.new_logical_negation_type(equality_result), kind)) @@ -296,7 +279,7 @@ pub fn evaluate_equality_inequality_operation( rhs, info, types, - strict_casts, + options, )?; if let EqualityAndInequalityResultKind::Condition = kind { Ok((types.new_logical_negation_type(equality_result), kind)) @@ -318,7 +301,7 @@ pub fn evaluate_equality_inequality_operation( lhs, info, types, - strict_casts, + options, ), // Swapping operands! EqualityAndInequality::GreaterThanOrEqual => evaluate_equality_inequality_operation( @@ -327,12 +310,11 @@ pub fn evaluate_equality_inequality_operation( lhs, info, types, - strict_casts, + options, ), } } -#[allow(clippy::let_and_return)] pub fn is_null_or_undefined( ty: TypeId, info: &impl crate::context::InformationChain, @@ -344,7 +326,7 @@ pub fn is_null_or_undefined( TypeId::NULL_TYPE, info, types, - false, + &super::OperatorOptions { strict_casts: false, advanced_numbers: false }, ) .map_or(TypeId::ERROR_TYPE, |(left, _)| left); @@ -357,7 +339,7 @@ pub fn is_null_or_undefined( TypeId::UNDEFINED_TYPE, info, types, - false, + &super::OperatorOptions { strict_casts: false, advanced_numbers: false }, ) .map_or(TypeId::ERROR_TYPE, |(left, _)| left); diff --git a/checker/src/features/operations/unary.rs b/checker/src/features/operations/unary.rs index 5c44e324..e3a18bd3 100644 --- a/checker/src/features/operations/unary.rs +++ b/checker/src/features/operations/unary.rs @@ -53,11 +53,7 @@ pub fn evaluate_unary_operator( UnaryOperation::Negation => -value, UnaryOperation::LogicalNot => unreachable!(), }; - let value = ordered_float::NotNan::try_from(value); - Ok(match value { - Ok(value) => types.new_constant_type(Constant::Number(value)), - Err(_) => TypeId::NAN, - }) + Ok(types.new_constant_type(Constant::Number(value))) } else { match operator { UnaryOperation::BitwiseNot => super::evaluate_mathematical_operation( diff --git a/checker/src/features/regexp.rs b/checker/src/features/regexp.rs index 500e26b6..8740af10 100644 --- a/checker/src/features/regexp.rs +++ b/checker/src/features/regexp.rs @@ -127,10 +127,7 @@ impl RegExp { match matches.into_iter().next() { Some(match_) => { { - let index = types.new_constant_type(Constant::Number( - (match_.start() as f64).try_into().unwrap(), - )); - + let index = types.new_constant_type(Constant::Number(match_.start() as f64)); object.append( Publicity::Public, PropertyKey::String("index".into()), @@ -198,9 +195,7 @@ impl RegExp { } { - let length = types.new_constant_type(Constant::Number( - f64::from(self.groups).try_into().unwrap(), - )); + let length = types.new_constant_type(Constant::Number(f64::from(self.groups))); object.append( Publicity::Public, @@ -290,8 +285,7 @@ impl RegExp { } { - let length = types - .new_constant_type(Constant::Number(f64::from(self.groups).try_into().unwrap())); + let length = types.new_constant_type(Constant::Number(f64::from(self.groups))); object.append( Publicity::Public, diff --git a/checker/src/features/template_literal.rs b/checker/src/features/template_literal.rs index ab68d775..82aed35d 100644 --- a/checker/src/features/template_literal.rs +++ b/checker/src/features/template_literal.rs @@ -1,4 +1,5 @@ use source_map::SpanWithSource; +use std::borrow::Cow; use crate::{ context::invocation::CheckThings, @@ -13,11 +14,12 @@ use crate::{ CheckingData, Constant, Environment, Type, TypeId, }; +/// Assumes that the text parts have been unesscaped #[allow(clippy::needless_pass_by_value)] pub fn synthesise_template_literal_expression<'a, T, A>( tag: Option, - parts_iter: impl Iterator)> + 'a, - final_part: &'a str, + parts_iter: impl Iterator, &'a A::MultipleExpression<'a>)> + 'a, + final_part: Cow<'a, str>, position: SpanWithSource, environment: &mut Environment, checking_data: &mut CheckingData, @@ -41,8 +43,9 @@ where let mut static_part_count = 0u16; for (static_part, dynamic_part) in parts_iter { { - let value = - checking_data.types.new_constant_type(Constant::String(static_part.to_owned())); + let value = checking_data + .types + .new_constant_type(Constant::String(static_part.into_owned())); static_parts.append( crate::types::properties::Publicity::Public, crate::types::properties::PropertyKey::from_usize(static_part_count.into()), @@ -75,7 +78,7 @@ where if !final_part.is_empty() { let value = - checking_data.types.new_constant_type(Constant::String(final_part.to_owned())); + checking_data.types.new_constant_type(Constant::String(final_part.into_owned())); static_parts.append( crate::types::properties::Publicity::Public, crate::types::properties::PropertyKey::from_usize(static_part_count.into()), @@ -89,9 +92,9 @@ where { // TODO spread - let static_part_array_length = checking_data.types.new_constant_type(Constant::Number( - f64::from(static_part_count).try_into().unwrap(), - )); + let static_part_array_length = checking_data + .types + .new_constant_type(Constant::Number(f64::from(static_part_count))); // TODO: Should there be a position here? static_parts.append( @@ -141,7 +144,7 @@ where let mut acc = TypeId::EMPTY_STRING; for (static_part, dynamic_part) in parts_iter { let lhs = - checking_data.types.new_constant_type(Constant::String(static_part.to_owned())); + checking_data.types.new_constant_type(Constant::String(static_part.into_owned())); let result = super::operations::evaluate_mathematical_operation( acc, crate::features::operations::MathematicalOrBitwiseOperation::Add, @@ -183,7 +186,7 @@ where acc } else { let value = - checking_data.types.new_constant_type(Constant::String(final_part.to_owned())); + checking_data.types.new_constant_type(Constant::String(final_part.into_owned())); let result = super::operations::evaluate_mathematical_operation( acc, crate::features::operations::MathematicalOrBitwiseOperation::Add, diff --git a/checker/src/lib.rs b/checker/src/lib.rs index d7ee7802..e11f65f6 100644 --- a/checker/src/lib.rs +++ b/checker/src/lib.rs @@ -64,8 +64,6 @@ where } } -use levenshtein::levenshtein; - pub trait ASTImplementation: Sized { type ParseOptions; /// Custom allocator etc @@ -578,7 +576,7 @@ fn parse_source( let current = checking_data.options.measure_time.then(std::time::Instant::now); // TODO abstract using similar to import logic - let is_js = path.extension().and_then(|s| s.to_str()).map_or(false, |s| s.ends_with("js")); + let is_js = path.extension().and_then(|s| s.to_str()).is_some_and(|s| s.ends_with("js")); let parse_options = A::parse_options( is_js, @@ -798,8 +796,9 @@ pub fn get_closest<'a, 'b>( closest_one: &'b str, ) -> Option> { const MIN_DISTANCE: usize = 2; - let candidates = - items.filter(|item| levenshtein(closest_one, item) <= MIN_DISTANCE).collect::>(); + let candidates = items + .filter(|item| levenshtein::levenshtein(closest_one, item) <= MIN_DISTANCE) + .collect::>(); match candidates.len() { 0 => None, 1.. => Some(candidates), diff --git a/checker/src/synthesis/assignments.rs b/checker/src/synthesis/assignments.rs index 867622f6..ca5ca7b9 100644 --- a/checker/src/synthesis/assignments.rs +++ b/checker/src/synthesis/assignments.rs @@ -36,10 +36,10 @@ impl SynthesiseToAssignable for LHSOfAssignment { ) -> Assignable { match self { LHSOfAssignment::ObjectDestructuring { members, spread, position: _ } => { - synthesise_object_to_reference(members, spread, environment, checking_data) + synthesise_object_to_reference(members, spread.as_ref(), environment, checking_data) } LHSOfAssignment::ArrayDestructuring { members, spread, position: _ } => { - synthesise_array_to_reference(members, spread, environment, checking_data) + synthesise_array_to_reference(members, spread.as_ref(), environment, checking_data) } LHSOfAssignment::VariableOrPropertyAccess(access) => Assignable::Reference( synthesise_access_to_reference(access, environment, checking_data), @@ -56,10 +56,10 @@ impl SynthesiseToAssignable for VariableField { ) -> Assignable { match self { VariableField::Object { members, spread, position: _ } => { - synthesise_object_to_reference(members, spread, environment, checking_data) + synthesise_object_to_reference(members, spread.as_ref(), environment, checking_data) } VariableField::Array { members, spread, position: _ } => { - synthesise_array_to_reference(members, spread, environment, checking_data) + synthesise_array_to_reference(members, spread.as_ref(), environment, checking_data) } VariableField::Name(ident) => Assignable::Reference(match ident { VariableIdentifier::Standard(name, position) => Reference::Variable( @@ -79,7 +79,7 @@ fn synthesise_object_to_reference< U: SynthesiseToAssignable + parser::DestructuringFieldInto, >( items: &[parser::WithComment>], - spread: &Option>, + spread: Option<&parser::SpreadDestructuringField>, environment: &mut Environment, checking_data: &mut CheckingData, ) -> Assignable { @@ -144,7 +144,7 @@ fn synthesise_array_to_reference< U: SynthesiseToAssignable + parser::DestructuringFieldInto, >( items: &[parser::WithComment>], - spread: &Option>, + spread: Option<&parser::SpreadDestructuringField>, environment: &mut Environment, checking_data: &mut CheckingData, ) -> Assignable { diff --git a/checker/src/synthesis/expressions.rs b/checker/src/synthesis/expressions.rs index b7ab5cfa..0d7311ec 100644 --- a/checker/src/synthesis/expressions.rs +++ b/checker/src/synthesis/expressions.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, convert::TryInto, str::FromStr}; +use std::{borrow::Cow, str::FromStr}; use parser::{ ast::TypeOrConst, @@ -12,7 +12,7 @@ use parser::{ TemplateLiteral, }, functions::MethodHeader, - ASTNode, Expression, ExpressionOrStatementPosition, + strings, ASTNode, Expression, ExpressionOrStatementPosition, }; use source_map::{Nullable, SpanWithSource}; @@ -35,7 +35,7 @@ use crate::{ evaluate_equality_inequality_operation, evaluate_logical_operation_with_expression, evaluate_mathematical_operation, evaluate_unary_operator, EqualityAndInequality, EqualityAndInequalityResultKind, LogicalOperator, MathematicalOrBitwiseOperation, - UnaryOperation, + OperatorOptions, UnaryOperation, }, template_literal::synthesise_template_literal_expression, variables::VariableWithValue, @@ -92,7 +92,8 @@ pub(super) fn synthesise_expression( ) -> TypeId { let instance: Instance = match expression { Expression::StringLiteral(value, ..) => { - return checking_data.types.new_constant_type(Constant::String(value.clone())) + let value = strings::unescape_string_content(value).into_owned(); + return checking_data.types.new_constant_type(Constant::String(value)); } Expression::RegexLiteral { pattern, flags, position } => { let regexp = checking_data.types.new_regexp(pattern, flags, position); @@ -114,18 +115,12 @@ pub(super) fn synthesise_expression( } } Expression::NumberLiteral(value, ..) => { - let not_nan = if let Ok(v) = f64::try_from(value.clone()) { - if let Ok(value) = v.try_into() { - value - } else { - crate::utilities::notify!("Returning zero here? {:?}", value); - return TypeId::ZERO; - } + return if let Ok(value) = f64::try_from(value.clone()) { + checking_data.types.new_constant_type(Constant::Number(value)) } else { crate::utilities::notify!("TODO big int"); - return TypeId::UNIMPLEMENTED_ERROR_TYPE; + TypeId::UNIMPLEMENTED_ERROR_TYPE }; - return checking_data.types.new_constant_type(Constant::Number(not_nan)); } Expression::BooleanLiteral(value, ..) => { return checking_data.types.new_constant_type(Constant::Boolean(*value)) @@ -206,9 +201,8 @@ pub(super) fn synthesise_expression( { // TODO spread - let length = checking_data.types.new_constant_type(Constant::Number( - (elements.len() as f64).try_into().unwrap(), - )); + let length = + checking_data.types.new_constant_type(Constant::Number(elements.len() as f64)); let value = crate::types::properties::PropertyValue::Value(length); // TODO: Should there be a position here? @@ -230,33 +224,53 @@ pub(super) fn synthesise_expression( object_literal.position.with_source(environment.get_source()), expecting, )), - Expression::TemplateLiteral(TemplateLiteral { tag, parts, last, position }) => { + Expression::TemplateLiteral(TemplateLiteral { tag, parts, final_part, position }) => { let tag = tag.as_ref().map(|expr| { synthesise_expression(expr, environment, checking_data, TypeId::ANY_TYPE) }); Instance::RValue(synthesise_template_literal_expression::<_, EznoParser>( tag, - parts.iter().map(|(l, r)| (l.as_str(), r)), - last.as_str(), + parts.iter().map(|(l, r)| (strings::unescape_string_content(l), r)), + strings::unescape_string_content(final_part), position.with_source(environment.get_source()), environment, checking_data, )) } Expression::BinaryOperation { lhs, operator, rhs, position } => { + fn logical_operator_from_binary_operator( + operator: BinaryOperator, + ) -> Option { + match operator { + BinaryOperator::LogicalAnd => Some(LogicalOperator::And), + BinaryOperator::LogicalOr => Some(LogicalOperator::Or), + BinaryOperator::NullCoalescing => Some(LogicalOperator::NullCoalescing), + _ => None, + } + } + + fn equality_inequality_operator_from_binary_operator( + operator: BinaryOperator, + ) -> Option { + match operator { + BinaryOperator::StrictEqual => Some(EqualityAndInequality::StrictEqual), + BinaryOperator::StrictNotEqual => Some(EqualityAndInequality::StrictNotEqual), + BinaryOperator::Equal => Some(EqualityAndInequality::Equal), + BinaryOperator::NotEqual => Some(EqualityAndInequality::NotEqual), + BinaryOperator::GreaterThan => Some(EqualityAndInequality::GreaterThan), + BinaryOperator::LessThan => Some(EqualityAndInequality::LessThan), + BinaryOperator::LessThanEqual => Some(EqualityAndInequality::LessThanOrEqual), + BinaryOperator::GreaterThanEqual => { + Some(EqualityAndInequality::GreaterThanOrEqual) + } + _ => None, + } + } + let lhs_ty = synthesise_expression(lhs, environment, checking_data, TypeId::ANY_TYPE); - if let BinaryOperator::LogicalAnd - | BinaryOperator::LogicalOr - | BinaryOperator::NullCoalescing = operator - { - let operator = match operator { - BinaryOperator::LogicalAnd => LogicalOperator::And, - BinaryOperator::LogicalOr => LogicalOperator::Or, - BinaryOperator::NullCoalescing => LogicalOperator::NullCoalescing, - _ => unreachable!(), - }; + if let Some(operator) = logical_operator_from_binary_operator(*operator) { return evaluate_logical_operation_with_expression( (lhs_ty, lhs.get_position()), operator, @@ -266,35 +280,21 @@ pub(super) fn synthesise_expression( expecting, // TODO unwrap ) .unwrap(); - } else if let BinaryOperator::StrictEqual - | BinaryOperator::StrictNotEqual - | BinaryOperator::Equal - | BinaryOperator::NotEqual - | BinaryOperator::GreaterThan - | BinaryOperator::LessThan - | BinaryOperator::LessThanEqual - | BinaryOperator::GreaterThanEqual = operator + } else if let Some(operator) = + equality_inequality_operator_from_binary_operator(*operator) { let rhs_ty = synthesise_expression(rhs, environment, checking_data, TypeId::ANY_TYPE); - let operator = match operator { - BinaryOperator::StrictEqual => EqualityAndInequality::StrictEqual, - BinaryOperator::StrictNotEqual => EqualityAndInequality::StrictNotEqual, - BinaryOperator::Equal => EqualityAndInequality::Equal, - BinaryOperator::NotEqual => EqualityAndInequality::NotEqual, - BinaryOperator::GreaterThan => EqualityAndInequality::GreaterThan, - BinaryOperator::LessThan => EqualityAndInequality::LessThan, - BinaryOperator::LessThanEqual => EqualityAndInequality::LessThanOrEqual, - BinaryOperator::GreaterThanEqual => EqualityAndInequality::GreaterThanOrEqual, - _ => unreachable!(), - }; let result = evaluate_equality_inequality_operation( lhs_ty, &operator, rhs_ty, environment, &mut checking_data.types, - checking_data.options.strict_casts, + &OperatorOptions { + strict_casts: checking_data.options.strict_casts, + advanced_numbers: checking_data.options.advanced_numbers, + }, ); if let Ok((result, warning)) = result { @@ -366,7 +366,7 @@ pub(super) fn synthesise_expression( BinaryOperator::Subtract => MathematicalOrBitwiseOperation::Subtract, BinaryOperator::Multiply => MathematicalOrBitwiseOperation::Multiply, BinaryOperator::Divide => MathematicalOrBitwiseOperation::Divide, - BinaryOperator::Modulo => MathematicalOrBitwiseOperation::Modulo, + BinaryOperator::Remainder => MathematicalOrBitwiseOperation::Remainder, BinaryOperator::Exponent => MathematicalOrBitwiseOperation::Exponent, BinaryOperator::BitwiseShiftLeft => { MathematicalOrBitwiseOperation::BitwiseShiftLeft @@ -387,8 +387,8 @@ pub(super) fn synthesise_expression( ); return TypeId::UNIMPLEMENTED_ERROR_TYPE; } - _ => { - unreachable!() + operator => { + unreachable!("{:?}", operator) } }; let result = evaluate_mathematical_operation( @@ -864,7 +864,7 @@ pub(super) fn synthesise_expression( let (result, special) = call_function( super_type, CalledWithNew::Super { this_type }, - &None, + None, Some(arguments), environment, checking_data, @@ -911,7 +911,7 @@ pub(super) fn synthesise_expression( let (result, special) = call_function( on, CalledWithNew::None, - type_arguments, + type_arguments.as_deref(), Some(arguments), environment, checking_data, @@ -930,8 +930,8 @@ pub(super) fn synthesise_expression( let (result, _) = call_function( on, called_with_new, - type_arguments, - arguments.as_ref(), + type_arguments.as_deref(), + arguments.as_deref(), environment, checking_data, *position, @@ -1176,8 +1176,8 @@ fn operator_to_assignment_kind( BinaryAssignmentOperator::DivideAssign => { AssignmentKind::PureUpdate(MathematicalOrBitwiseOperation::Divide) } - BinaryAssignmentOperator::ModuloAssign => { - AssignmentKind::PureUpdate(MathematicalOrBitwiseOperation::Modulo) + BinaryAssignmentOperator::RemainderAssign => { + AssignmentKind::PureUpdate(MathematicalOrBitwiseOperation::Remainder) } BinaryAssignmentOperator::ExponentAssign => { AssignmentKind::PureUpdate(MathematicalOrBitwiseOperation::Exponent) @@ -1207,8 +1207,8 @@ fn operator_to_assignment_kind( fn call_function( function_type_id: TypeId, called_with_new: CalledWithNew, - type_arguments: &Option>, - arguments: Option<&Vec>, + type_arguments: Option<&[parser::TypeAnnotation]>, + arguments: Option<&[FunctionArgument]>, environment: &mut Environment, checking_data: &mut CheckingData, call_site: parser::Span, diff --git a/checker/src/synthesis/extensions/is_expression.rs b/checker/src/synthesis/extensions/is_expression.rs index 23eff9f0..494104af 100644 --- a/checker/src/synthesis/extensions/is_expression.rs +++ b/checker/src/synthesis/extensions/is_expression.rs @@ -57,6 +57,7 @@ pub(crate) fn synthesise_is_expression( returned.unwrap_or(TypeId::UNDEFINED_TYPE) } +/// `name` for type annotation pub(crate) fn new_is_type( item: TypeId, rhs: &parser::TypeAnnotation, diff --git a/checker/src/synthesis/extensions/jsx.rs b/checker/src/synthesis/extensions/jsx.rs index c8c3f3f3..92fd9ec9 100644 --- a/checker/src/synthesis/extensions/jsx.rs +++ b/checker/src/synthesis/extensions/jsx.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; -use parser::{ASTNode, Expression, JSXAttribute, JSXElement, JSXNode, JSXRoot}; +use parser::{ + jsx::{JSXAttribute, JSXElement, JSXElementChildren, JSXNode, JSXRoot}, + ASTNode, Expression, +}; use crate::{ context::invocation::CheckThings, @@ -140,7 +143,7 @@ pub(crate) fn synthesise_jsx_element( // ); // } - let child_nodes = if let parser::JSXElementChildren::Children(ref children) = element.children { + let child_nodes = if let JSXElementChildren::Children(ref children) = element.children { // fn get_children() { let mut synthesised_child_nodes = ObjectBuilder::new( Some(TypeId::ARRAY_TYPE), @@ -175,9 +178,7 @@ pub(crate) fn synthesise_jsx_element( { // TODO spread - let length = checking_data - .types - .new_constant_type(Constant::Number(f64::from(count).try_into().unwrap())); + let length = checking_data.types.new_constant_type(Constant::Number(f64::from(count))); // TODO: Should there be a position here? synthesised_child_nodes.append( diff --git a/checker/src/synthesis/functions.rs b/checker/src/synthesis/functions.rs index ab5dbf65..49ce8e29 100644 --- a/checker/src/synthesis/functions.rs +++ b/checker/src/synthesis/functions.rs @@ -243,7 +243,22 @@ pub(super) fn synthesise_type_annotation_function_parameters { @@ -413,8 +427,6 @@ fn synthesise_function_parameters< }, ); - let name = variable_field_to_string(parameter.name.get_ast_ref()); - SynthesisedParameter { name, is_optional: optional, @@ -432,6 +444,11 @@ fn synthesise_function_parameters< synthesise_type_annotation(annotation, environment, checking_data) }); + let id = crate::VariableId(environment.get_source(), rest_parameter.position.start); + let name = variable_field_to_string(&rest_parameter.name); + let ty = checking_data.types.new_function_parameter(parameter_constraint, id, &name); + // environment.info.object_constraints.insert(variable_ty, parameter_constraint); + let item_type = if let TypeId::ERROR_TYPE = parameter_constraint { TypeId::ERROR_TYPE } else if let Type::PartiallyAppliedGenerics(PartiallyAppliedGenerics { @@ -452,10 +469,6 @@ fn synthesise_function_parameters< TypeId::ERROR_TYPE }; - let variable_ty = checking_data.types.new_function_parameter(parameter_constraint); - - // environment.info.object_constraints.insert(variable_ty, parameter_constraint); - register_variable( &rest_parameter.name, environment, @@ -464,7 +477,7 @@ fn synthesise_function_parameters< // TODO constant parameter option constant: false, space: Some(parameter_constraint), - initial_value: Some(variable_ty), + initial_value: Some(ty), // :<) allow_reregistration: true, }, @@ -474,7 +487,7 @@ fn synthesise_function_parameters< SynthesisedRestParameter { item_type, - ty: variable_ty, + ty, name, position: rest_parameter.position.with_source(environment.get_source()), } @@ -585,7 +598,7 @@ fn get_parameter_name(parameter: &parser::VariableField) -> String { /// This synthesise is for function types, references and interfaces. #[allow(clippy::too_many_arguments)] pub(super) fn synthesise_function_annotation( - type_parameters: &Option>, + type_parameters: Option<&[TypeParameter]>, parameters: &parser::type_annotations::TypeAnnotationFunctionParameters, // This Option rather than Option because function type references are always some return_type: Option<&TypeAnnotation>, diff --git a/checker/src/synthesis/interfaces.rs b/checker/src/synthesis/interfaces.rs index edd068e5..78995d94 100644 --- a/checker/src/synthesis/interfaces.rs +++ b/checker/src/synthesis/interfaces.rs @@ -220,7 +220,7 @@ pub(super) fn synthesise_signatures( CommonTypes::Never => TypeId::NEVER_TYPE, }, TypeAnnotation::StringLiteral(value, ..) => { - checking_data.types.new_constant_type(Constant::String(value.clone())) + let value = strings::unescape_string_content(value).into_owned(); + checking_data.types.new_constant_type(Constant::String(value)) } TypeAnnotation::NumberLiteral(value, _) => { - let constant = Constant::Number( - f64::try_from(value.clone()).expect("big int number type").try_into().unwrap(), - ); + let constant = + Constant::Number(f64::try_from(value.clone()).expect("big int number type")); checking_data.types.new_constant_type(constant) } TypeAnnotation::BooleanLiteral(value, _) => { @@ -393,7 +392,7 @@ pub fn synthesise_type_annotation( } => { let position = position.with_source(environment.get_source()); let function_type = synthesise_function_annotation( - type_parameters, + type_parameters.as_deref(), parameters, Some(return_type), environment, @@ -708,13 +707,14 @@ pub fn synthesise_type_annotation( crate::utilities::notify!("Unknown decorator skipping {:#?}", decorator.name); synthesise_type_annotation(inner, environment, checking_data) } - TypeAnnotation::TemplateLiteral { parts, last, .. } => { + TypeAnnotation::TemplateLiteral { parts, final_part, .. } => { // Using the existing thing breaks because we try to do `"..." + string` and // the evaluate_mathematical_operator expects literal or poly values (not just types) let mut acc = TypeId::EMPTY_STRING; for (static_part, dynamic_part) in parts { - let lhs = - checking_data.types.new_constant_type(Constant::String(static_part.to_owned())); + let lhs = checking_data.types.new_constant_type(Constant::String( + strings::unescape_string_content(static_part).into_owned(), + )); acc = if let TypeId::EMPTY_STRING = acc { lhs } else { @@ -745,10 +745,12 @@ pub fn synthesise_type_annotation( }; acc = checking_data.types.register_type(Type::Constructor(constructor)); } - if last.is_empty() { + if final_part.is_empty() { acc } else { - let lhs = checking_data.types.new_constant_type(Constant::String(last.to_owned())); + let lhs = checking_data.types.new_constant_type(Constant::String( + strings::unescape_string_content(final_part).into_owned(), + )); if let TypeId::EMPTY_STRING = acc { lhs } else { @@ -799,16 +801,19 @@ pub fn synthesise_type_annotation( } TypeAnnotation::Is { reference, is, position: _ } => { let item_type = match reference { - parser::type_annotations::IsItem::Reference(name) => environment - .variables - .get(name) - .and_then(|variable| { - environment - .info - .variable_current_value - .get(&variable.get_origin_variable_id()) - }) - .copied(), + parser::type_annotations::IsItem::Reference(name) => { + // Fine to do this environment? + environment + .variables + .get(name) + .and_then(|variable| { + environment + .info + .variable_current_value + .get(&variable.get_origin_variable_id()) + }) + .copied() + } parser::type_annotations::IsItem::This => { // TODO let based_on = TypeId::UNIMPLEMENTED_ERROR_TYPE; @@ -850,8 +855,6 @@ pub fn synthesise_type_annotation( result_union: TypeId::ERROR_TYPE, }); checking_data.types.register_type(ty) - // crate::types::TypeExtends { item, extends }, - // )); } TypeAnnotation::This(position) => { checking_data.raise_unimplemented_error( diff --git a/checker/src/types/calling.rs b/checker/src/types/calling.rs index 9ea6c083..0352d871 100644 --- a/checker/src/types/calling.rs +++ b/checker/src/types/calling.rs @@ -609,8 +609,7 @@ fn call_logical( // TODO just for debugging. These have their constant things called every time AND queue an event let is_independent_function = const_fn_ident.ends_with("independent"); - let call_anyway = const_fn_ident.starts_with("debug") - || const_fn_ident.starts_with("print") + let call_anyway = const_fn_ident.starts_with("ezno") || is_independent_function || matches!( const_fn_ident.as_str(), @@ -1704,9 +1703,7 @@ impl FunctionType { // Set length of spread array if let Some(mut basis) = basis { - let length = types.new_constant_type(crate::Constant::Number( - (count as f64).try_into().unwrap(), - )); + let length = types.new_constant_type(crate::Constant::Number(count as f64)); basis.append( crate::types::properties::Publicity::Public, @@ -2012,18 +2009,19 @@ fn synthesise_argument_expressions_wrt_parameters Result Ok(f64::from(*number)), + Constant::Number(number) => Ok(*number), Constant::String(str) => match str.parse::() { Ok(value) => Ok(value), Err(_) => { @@ -17,7 +17,7 @@ pub(crate) fn cast_as_number(cst: &Constant, strict_casts: bool) -> Result Ok(if *val { 1f64 } else { 0f64 }), - Constant::Undefined | Constant::NaN => Ok(f64::NAN), + Constant::Undefined => Ok(f64::NAN), Constant::Symbol { key: _ } => todo!(), } } @@ -38,10 +38,10 @@ pub(crate) fn cast_as_boolean(cst: &Constant, strict_casts: bool) -> Result number.into_inner() != 0., + Constant::Number(number) => *number != 0., Constant::String(value) => !value.is_empty(), Constant::Boolean(value) => *value, - Constant::Undefined | Constant::NaN => false, + Constant::Undefined => false, Constant::Symbol { key: _ } => todo!(), }) } diff --git a/checker/src/types/disjoint.rs b/checker/src/types/disjoint.rs index 9e088ea6..fd109a6d 100644 --- a/checker/src/types/disjoint.rs +++ b/checker/src/types/disjoint.rs @@ -139,7 +139,7 @@ pub fn types_are_disjoint( number_range_disjoint(args, rhs, types) } else if let Type::Constructor(Constructor::BinaryOperator { lhs: _lhs, - operator: MathematicalOrBitwiseOperation::Modulo, + operator: MathematicalOrBitwiseOperation::Remainder, rhs, result: _, }) = lhs_ty @@ -150,15 +150,15 @@ pub fn types_are_disjoint( ) = (types.get_type_by_id(*rhs), rhs_ty) { crate::utilities::notify!("{:?}", (num, lhs_mod)); - // Modulos return negative for negative number :( + // Remainders return negative for negative number :( // Checking whether out of range here - num.abs() > **lhs_mod + num.abs() > *lhs_mod } else { false } } else if let Type::Constructor(Constructor::BinaryOperator { lhs: _lhs, - operator: MathematicalOrBitwiseOperation::Modulo, + operator: MathematicalOrBitwiseOperation::Remainder, rhs, result: _, }) = rhs_ty @@ -169,9 +169,9 @@ pub fn types_are_disjoint( ) = (types.get_type_by_id(*rhs), lhs_ty) { crate::utilities::notify!("{:?}", (num, rhs_mod)); - // Modulos return negative for negative number :( + // Remainders return negative for negative number :( // Checking whether out of range here - num.abs() > **rhs_mod + num.abs() > *rhs_mod } else { false } @@ -201,7 +201,7 @@ pub fn types_are_disjoint( types_are_disjoint(lhs, rhs, already_checked, information, types) } else if let Type::Constant(lhs_cst) = lhs_ty { if let Type::Constant(rhs_cst) = rhs_ty { - lhs_cst != rhs_cst + !lhs_cst.equals(rhs_cst) } else { types_are_disjoint( lhs_cst.get_backing_type(), @@ -213,17 +213,33 @@ pub fn types_are_disjoint( } } else if let Type::Constant(rhs_cst) = rhs_ty { types_are_disjoint(rhs_cst.get_backing_type(), lhs, already_checked, information, types) + } else if let TypeId::FUNCTION_TYPE = lhs { + !matches!( + rhs_ty, + Type::FunctionReference(_) + | Type::SpecialObject(crate::types::SpecialObject::Function(..)) + ) + } else if let TypeId::FUNCTION_TYPE = rhs { + !matches!( + lhs_ty, + Type::FunctionReference(_) + | Type::SpecialObject(crate::types::SpecialObject::Function(..)) + ) } else if let Type::Object(crate::types::ObjectNature::AnonymousTypeAnnotation( _properties, )) = lhs_ty { - // TODO check properties + crate::utilities::notify!( + "TODO check properties on object type annotation. Skipping for now" + ); false } else if let Type::Object(crate::types::ObjectNature::AnonymousTypeAnnotation( _properties, )) = rhs_ty { - // TODO check properties + crate::utilities::notify!( + "TODO check properties on object type annotation. Skipping for now" + ); false } else { crate::utilities::notify!( @@ -252,7 +268,7 @@ fn number_modulo_disjoint( return false; }; - let offset = 0f64.try_into().unwrap(); + let offset = 0f64; let this = crate::utilities::modulo_class::ModuloClass::new(*argument, offset); // Little bit complex here because dealing with decimal types, not integers diff --git a/checker/src/types/generics/contributions.rs b/checker/src/types/generics/contributions.rs index 776ab745..f13cc7cd 100644 --- a/checker/src/types/generics/contributions.rs +++ b/checker/src/types/generics/contributions.rs @@ -45,11 +45,7 @@ impl CovariantContribution { types.new_constant_type(crate::Constant::String(slice)) } CovariantContribution::Number(number) => { - if let Ok(number) = number.try_into() { - types.new_constant_type(crate::Constant::Number(number)) - } else { - TypeId::NAN - } + types.new_constant_type(crate::Constant::Number(number)) } CovariantContribution::CaseInsensitive(on) => { let inner = on.into_type(types); @@ -116,14 +112,13 @@ pub struct Contributions<'a> { pub call_site_type_arguments: Option<&'a TypeRestrictions>, // /// From other parameters - // #[allow(unused)] // pub existing_covariant: &'a mut X, /// Only for explicit generic parameters pub staging_covariant: TriMap, pub staging_contravariant: TriMap, } -impl<'a> Contributions<'a> { +impl Contributions<'_> { /// TODO return position? #[must_use] pub fn get_standard_restriction(&self, under: TypeId) -> Option { diff --git a/checker/src/types/generics/substitution.rs b/checker/src/types/generics/substitution.rs index 1a6c6900..7041ee95 100644 --- a/checker/src/types/generics/substitution.rs +++ b/checker/src/types/generics/substitution.rs @@ -30,7 +30,7 @@ pub struct SubstitutionArguments<'a> { pub(crate) closures: Vec, } -impl<'a> ClosureChain for SubstitutionArguments<'a> { +impl ClosureChain for SubstitutionArguments<'_> { fn get_fact_from_closure(&self, _fact: &LocalInformation, cb: T) -> Option where T: Fn(ClosureId) -> Option, @@ -39,7 +39,7 @@ impl<'a> ClosureChain for SubstitutionArguments<'a> { } } -impl<'a> SubstitutionArguments<'a> { +impl SubstitutionArguments<'_> { /// TODO this might need to be done per context pub fn set_during_application(&mut self, ty: TypeId, value: TypeId) { self.arguments.insert(ty, value); @@ -483,7 +483,11 @@ pub(crate) fn substitute( rhs, environment, types, - false, + // TODO pass down + &crate::features::operations::OperatorOptions { + strict_casts: false, + advanced_numbers: false, + }, ); if let Ok((left, _warning)) = result { @@ -501,7 +505,7 @@ pub(crate) fn substitute( crate::types::TypeOperator::HasProperty(_, _) => { unreachable!("'HasProperty' should be specialised by events") } - crate::types::TypeOperator::IsPrototype { lhs, rhs_prototype } => { + crate::types::TypeOperator::HasPrototype { lhs, rhs_prototype } => { let lhs = substitute(lhs, arguments, environment, types); let rhs_prototype = substitute(rhs_prototype, arguments, environment, types); crate::features::instance_of_operator_rhs_prototype( @@ -519,6 +523,7 @@ pub(crate) fn substitute( let item = substitute(item, arguments, environment, types); let extends = substitute(extends, arguments, environment, types); + // Just do boolean values here { use crate::types::printing::print_type; @@ -546,38 +551,11 @@ pub(crate) fn substitute( types, ); - // let base = crate::types::get_larger_type(item, types); - // let does_extend = base == extends; - // crate::utilities::notify!( - // "Extends result {:?} base={:?} extends={:?}", - // does_extend, - // crate::types::printing::print_type(base, types, environment, true), - // crate::types::printing::print_type(extends, types, environment, true) - // ); if result.is_subtype() { TypeId::TRUE } else { TypeId::FALSE } - - // let does_extend = get_larger_type(ty, types) == extends; - // crate::utilities::notify!("Extends result {:?}", does_extend); - // if does_extend { - // TypeId::TRUE - // } else { - // TypeId::FALSE - // } - - // TODO special behavior that doesn't need to collect errors... - // let result = type_is_subtype(extends, ty, environment, types); - - // let does_extend = matches!(result, crate::subtyping::SubTypeResult::IsSubType); - - // if does_extend { - // TypeId::TRUE - // } else { - // TypeId::FALSE - // } } Constructor::Awaited { .. } => todo!("should have effect result"), Constructor::KeyOf(on) => { @@ -618,6 +596,13 @@ pub(crate) fn compute_extends_rule( otherwise_result, ); types.new_or_type(lhs, rhs) + } else if let Some(_constraint) = super::super::get_constraint(item, types) { + let specialised_result = + Type::Constructor(Constructor::TypeExtends(crate::types::TypeExtends { + item, + extends, + })); + types.register_type(specialised_result) } else { let mut state = State { already_checked: Default::default(), diff --git a/checker/src/types/helpers.rs b/checker/src/types/helpers.rs index f8b6ab18..0eec1627 100644 --- a/checker/src/types/helpers.rs +++ b/checker/src/types/helpers.rs @@ -48,11 +48,28 @@ pub(crate) fn _assign_to_tuple(_ty: TypeId) -> TypeId { // if let PropertyKey::Type(slice) = } +pub(crate) fn get_reference_name(types: &TypeStore, ty: TypeId) -> Option<&str> { + match types.get_type_by_id(ty) { + Type::RootPolyType( + PolyNature::Parameter { variable_id, .. } + | PolyNature::FreeVariable { + reference: crate::types::RootReference::Variable(variable_id), + .. + }, + ) => Some(types.get_parameter_name(*variable_id)), + Type::RootPolyType(PolyNature::FreeVariable { + reference: crate::types::RootReference::This, + .. + }) => Some("this"), + _ => None, + } +} + pub fn get_array_length( ctx: &impl InformationChain, on: TypeId, types: &TypeStore, -) -> Result, Option> { +) -> Result> { let length_property = properties::PropertyKey::String(std::borrow::Cow::Borrowed("length")); let id = properties::get_simple_property_value(ctx, on, &length_property, types).ok_or(None)?; if let Type::Constant(Constant::Number(n)) = types.get_type_by_id(id) { @@ -155,9 +172,7 @@ impl Counter { pub(crate) fn into_type(self, types: &mut TypeStore) -> TypeId { match self { - Counter::On(value) => { - types.new_constant_type(Constant::Number((value as f64).try_into().unwrap())) - } + Counter::On(value) => types.new_constant_type(Constant::Number(value as f64)), Counter::AddTo(ty) => ty, } } @@ -315,7 +330,7 @@ pub fn type_equal(lhs: TypeId, rhs: TypeId, types: &TypeStore) -> bool { } else if let (Type::Constant(lhs), Type::Constant(rhs)) = (types.get_type_by_id(lhs), types.get_type_by_id(rhs)) { - lhs == rhs + lhs.equals(rhs) } else { false } @@ -377,11 +392,26 @@ pub fn get_larger_type(on: TypeId, types: &TypeStore) -> TypeId { } } +#[must_use] +pub fn get_aliased(on: TypeId, types: &TypeStore) -> Option { + if let Type::AliasTo { to, parameters: None, .. } = types.get_type_by_id(on) { + Some(*to) + } else { + None + } +} + #[must_use] pub fn get_constraint_or_alias(on: TypeId, types: &TypeStore) -> Option { match types.get_type_by_id(on) { - Type::RootPolyType(rpt) => Some(rpt.get_constraint()), - Type::Constructor(constr) => Some(constr.get_constraint()), + Type::RootPolyType(rpt) => { + let constraint = rpt.get_constraint(); + Some(get_aliased(constraint, types).unwrap_or(constraint)) + } + Type::Constructor(constr) => { + let constraint = constr.get_constraint(); + Some(get_aliased(constraint, types).unwrap_or(constraint)) + } Type::AliasTo { to, parameters: None, .. } => Some(*to), Type::Narrowed { narrowed_to, .. } => Some(*narrowed_to), _ => None, diff --git a/checker/src/types/intrinsics.rs b/checker/src/types/intrinsics.rs index cde00b31..028bc874 100644 --- a/checker/src/types/intrinsics.rs +++ b/checker/src/types/intrinsics.rs @@ -321,6 +321,7 @@ pub fn new_intrinsic(intrinsic: &Intrinsic, argument: TypeId, types: &mut TypeSt } #[must_use] +#[allow(clippy::float_cmp)] pub fn get_range_and_mod_class( ty: TypeId, types: &TypeStore, @@ -415,14 +416,12 @@ pub fn get_range_and_mod_class( } } -type BetterF64 = ordered_float::NotNan; - /// Unit. No combinations at this point #[derive(Debug)] pub enum PureNumberIntrinsic { - GreaterThan(BetterF64), - LessThan(BetterF64), - Modulo { modulo: BetterF64, offset: BetterF64 }, + GreaterThan(f64), + LessThan(f64), + Modulo { modulo: f64, offset: f64 }, } impl PureNumberIntrinsic { @@ -438,10 +437,9 @@ impl PureNumberIntrinsic { match *on { TypeId::GREATER_THAN => Ok(PureNumberIntrinsic::GreaterThan(*number)), TypeId::LESS_THAN => Ok(PureNumberIntrinsic::LessThan(*number)), - TypeId::MULTIPLE_OF => Ok(PureNumberIntrinsic::Modulo { - modulo: *number, - offset: 0f64.try_into().unwrap(), - }), + TypeId::MULTIPLE_OF => { + Ok(PureNumberIntrinsic::Modulo { modulo: *number, offset: 0f64 }) + } _ => todo!(), } } else { diff --git a/checker/src/types/mod.rs b/checker/src/types/mod.rs index 81dcd86b..3e216f0d 100644 --- a/checker/src/types/mod.rs +++ b/checker/src/types/mod.rs @@ -226,13 +226,12 @@ pub enum PolyNature { /// This allows for /// - event application to work on known values /// - more accurate return types - /// - `fixed_to` can point to [`PolyNature::FunctionGeneric`] - Parameter { fixed_to: TypeId }, + Parameter { fixed_to: TypeId, variable_id: crate::VariableId }, /// This is on a structure (`class`, `interface` and `type` alias) StructureGeneric { name: String, extends: TypeId }, /// From `infer U`. InferGeneric { name: String, extends: TypeId }, - /// For explicit generics (or on external definitions) + /// For explicit generics (or on external definitions). Note can be a standalone parameter in some cases FunctionGeneric { name: String, extends: TypeId }, /// For mapped types MappedGeneric { name: String, extends: TypeId }, @@ -273,7 +272,7 @@ impl PolyNature { pub fn is_inferrable(&self) -> bool { matches!( self, - Self::Parameter { fixed_to: to } | Self::FreeVariable { based_on: to, .. } | Self::CatchVariable(to) + Self::Parameter { fixed_to: to, .. } | Self::FreeVariable { based_on: to, .. } | Self::CatchVariable(to) // TODO matches TypeId::unknown if matches!(*to, TypeId::ANY_TYPE) ) @@ -283,7 +282,7 @@ impl PolyNature { #[must_use] pub fn get_constraint(&self) -> TypeId { match self { - PolyNature::Parameter { fixed_to: to } + PolyNature::Parameter { fixed_to: to, .. } | PolyNature::FunctionGeneric { extends: to, .. } | PolyNature::MappedGeneric { extends: to, .. } | PolyNature::FreeVariable { based_on: to, .. } @@ -405,6 +404,7 @@ pub enum Constructor { on: TypeId, under: properties::PropertyKey<'static>, result: TypeId, + /// Also descibes if was from a type annotation mode: AccessMode, }, /// For await a poly type @@ -434,7 +434,7 @@ impl Constructor { Constructor::TypeOperator(op) => match op { // TODO union of names TypeOperator::TypeOf(_) => TypeId::STRING_TYPE, - TypeOperator::IsPrototype { .. } | TypeOperator::HasProperty(..) => { + TypeOperator::HasPrototype { .. } | TypeOperator::HasProperty(..) => { TypeId::BOOLEAN_TYPE } }, @@ -514,7 +514,7 @@ pub struct PartiallyAppliedGenerics { #[derive(Clone, Debug, binary_serialize_derive::BinarySerializable)] pub enum TypeOperator { - IsPrototype { + HasPrototype { lhs: TypeId, rhs_prototype: TypeId, }, @@ -559,7 +559,7 @@ impl TypeExtends { // === rhs Ok(Self { item: *lhs, extends: *rhs }) } - } else if let Type::Constructor(Constructor::TypeOperator(TypeOperator::IsPrototype { + } else if let Type::Constructor(Constructor::TypeOperator(TypeOperator::HasPrototype { lhs, rhs_prototype, })) = rhs_ty diff --git a/checker/src/types/printing.rs b/checker/src/types/printing.rs index 81a2f1ca..4cd9a8ce 100644 --- a/checker/src/types/printing.rs +++ b/checker/src/types/printing.rs @@ -122,10 +122,11 @@ pub fn print_type_into_buf( | PolyNature::StructureGeneric { name, extends: _ } => { if debug { if let PolyNature::FunctionGeneric { .. } = nature { - write!(buf, "(fg {} {}) ", ty.0, name).unwrap(); + write!(buf, "(fg {} {})", ty.0, name).unwrap(); + } else { + write!(buf, "(sg {} {})", ty.0, name).unwrap(); } - } - if let Some(arg) = args.and_then(|args| args.get_argument_covariant(ty)) { + } else if let Some(arg) = args.and_then(|args| args.get_argument_covariant(ty)) { use crate::types::CovariantContribution; if debug { buf.push_str("(specialised with) "); @@ -139,20 +140,13 @@ pub fn print_type_into_buf( } } - // for (more, arg) in structure_args.iter().nendiate() { - // print_type_into_buf(*arg, buf, cycles, args, types, info, debug); - // if more { - // buf.push_str(" | "); - // } - // } + // for (more, arg) in structure_args.iter().nendiate() { + // print_type_into_buf(*arg, buf, cycles, args, types, info, debug); + // if more { + // buf.push_str(" | "); + // } + // } } else { - if debug { - if let PolyNature::FunctionGeneric { extends, .. } = nature { - print_type_into_buf(*extends, buf, cycles, args, types, info, debug); - } else { - write!(buf, "(sg {})", ty.0).unwrap(); - } - } buf.push_str(name); } } @@ -174,7 +168,7 @@ pub fn print_type_into_buf( } print_type_into_buf(*to, buf, cycles, args, types, info, debug); } - PolyNature::Parameter { fixed_to: to } => { + PolyNature::Parameter { fixed_to: to, variable_id: _ } => { if debug { write!(buf, "(param {}) @ ", ty.0).unwrap(); } @@ -298,7 +292,11 @@ pub fn print_type_into_buf( (*otherwise_result, crate::types::TypeExtends::from_type(*condition, types)) { buf.push_str("asserts "); - print_type_into_buf(item, buf, cycles, args, types, info, debug); + if let Some(name) = crate::types::helpers::get_reference_name(types, item) { + buf.push_str(name); + } else { + print_type_into_buf(item, buf, cycles, args, types, info, debug); + } buf.push_str(" is "); print_type_into_buf(extends, buf, cycles, args, types, info, debug); return; @@ -363,7 +361,7 @@ pub fn print_type_into_buf( // } // } } - Constructor::Property { on, under, result, mode: _ } => { + Constructor::Property { on, under, result, mode } => { // crate::utilities::notify!("before {:?}", types.get_type_by_id(*on)); let on = if let Some(crate::types::CovariantContribution::TypeId(value)) = args.and_then(|arg| arg.get_argument_covariant(*on)) @@ -375,9 +373,37 @@ pub fn print_type_into_buf( // crate::utilities::notify!("after {:?}", types.get_type_by_id(on)); - if crate::types::is_explicit_generic(on, types) - || matches!(types.get_type_by_id(on), Type::Interface { .. } | Type::Object(_)) - { + let is_explicit_generic = crate::types::is_explicit_generic(on, types); + + if let (AccessMode::FromTypeAnnotation, false) = (mode, is_explicit_generic) { + // TODO args on both? + let result = crate::types::get_property_unbound( + (on, args), + (Publicity::Public, under, args), + false, + info, + types, + ); + crate::utilities::notify!("result={:?}", result); + if let Ok(prop) = result { + match prop { + crate::types::logical::LogicalOrValid::Logical( + crate::types::logical::Logical::Pure(value), + ) => { + let result = value.as_get_type(types); + print_type_into_buf(result, buf, cycles, args, types, info, debug); + return; + } + value => { + crate::utilities::notify!("value={:?}", value); + } + } + } else { + crate::utilities::notify!("Error: no index on type annotation"); + } + } + + if is_explicit_generic || matches!(mode, AccessMode::FromTypeAnnotation) { print_type_into_buf(on, buf, cycles, args, types, info, debug); buf.push('['); match under { @@ -415,12 +441,13 @@ pub fn print_type_into_buf( write!(buf, "{ty:?}").unwrap(); buf.push_str(") "); } + print_type_into_buf(*result, buf, cycles, args, types, info, debug); } } Constructor::BinaryOperator { lhs: _, - operator: crate::features::operations::MathematicalOrBitwiseOperation::Modulo, + operator: crate::features::operations::MathematicalOrBitwiseOperation::Remainder, rhs, result: _, } if matches!(types.get_type_by_id(*rhs), Type::Constant(_)) => { @@ -433,26 +460,31 @@ pub fn print_type_into_buf( constructor if debug => match constructor { Constructor::BinaryOperator { lhs, operator, rhs, result: _ } => { print_type_into_buf(*lhs, buf, cycles, args, types, info, debug); - write!(buf, " {operator:?} ").unwrap(); + write!(buf, " ({ty:?}){operator:?} ").unwrap(); print_type_into_buf(*rhs, buf, cycles, args, types, info, debug); } Constructor::CanonicalRelationOperator { lhs, operator, rhs } => { print_type_into_buf(*lhs, buf, cycles, args, types, info, debug); - match operator { - crate::features::operations::CanonicalEqualityAndInequality::StrictEqual => { - buf.push_str(" === "); - } - crate::features::operations::CanonicalEqualityAndInequality::LessThan => { - buf.push_str(" < "); - } + let operator = match operator { + crate::features::operations::CanonicalEqualityAndInequality::StrictEqual => { + "===" + } + crate::features::operations::CanonicalEqualityAndInequality::LessThan => { + "<" } + }; + write!(buf, " ({ty}){operator} ", ty = ty.0).unwrap(); print_type_into_buf(*rhs, buf, cycles, args, types, info, debug); } Constructor::TypeOperator(to) => { write!(buf, "TypeOperator.{to:?}").unwrap(); } Constructor::TypeExtends(TypeExtends { item, extends }) => { - print_type_into_buf(*item, buf, cycles, args, types, info, debug); + if let Some(name) = crate::types::helpers::get_reference_name(types, *item) { + buf.push_str(name); + } else { + print_type_into_buf(*item, buf, cycles, args, types, info, debug); + } buf.push_str(" extends "); print_type_into_buf(*extends, buf, cycles, args, types, info, debug); } @@ -469,7 +501,7 @@ pub fn print_type_into_buf( print_property_key_into_buf(under, buf, cycles, args, types, info, debug); buf.push(']'); if let AccessMode::DoNotBindThis = mode { - buf.push_str(" no bind"); + buf.push_str(" no binding of `this`"); }; buf.push_str(" = "); print_type_into_buf(*result, buf, cycles, args, types, info, debug); @@ -519,12 +551,12 @@ pub fn print_type_into_buf( | Type::Interface { name, parameters: _, .. } | Type::AliasTo { to: _, name, parameters: _ }) => { if debug { - write!(buf, "{name}#{} ", ty.0).unwrap(); + write!(buf, "{name}#{}", ty.0).unwrap(); if let Type::AliasTo { to, .. } = t { - buf.push_str("= "); + buf.push_str(" = "); print_type_into_buf(*to, buf, cycles, args, types, info, debug); } else if let Type::Class { .. } = t { - buf.push_str("(class)"); + buf.push_str(" (class)"); } } else { buf.push_str(name); @@ -656,7 +688,7 @@ pub fn print_type_into_buf( match get_array_length(info, ty, types) { Ok(n) => { buf.push('['); - for i in 0..(n.into_inner() as usize) { + for i in 0..(n as usize) { if i != 0 { buf.push_str(", "); } diff --git a/checker/src/types/properties/access.rs b/checker/src/types/properties/access.rs index 6b17a5c7..d487d1d1 100644 --- a/checker/src/types/properties/access.rs +++ b/checker/src/types/properties/access.rs @@ -44,7 +44,7 @@ fn get_property_from_list( } if let PropertyValue::ConditionallyExists { .. } = value { - crate::utilities::notify!("TODO trailing"); + crate::utilities::notify!("TODO trailing on {:?}", key); // continue; } @@ -643,19 +643,19 @@ pub(crate) fn get_property_unbound( types.get_type_by_id(key) { if let Some(argument) = - under_type_arguments.and_then(|v| v.get_single_argument(key)) + under_type_arguments.and_then(|v| v.get_argument_covariant(key)) { - return get_property_on_type_unbound( + get_property_on_type_unbound( (on, on_type_arguments), - (publicity, &PropertyKey::Type(argument), under_type_arguments), + (publicity, &argument.into_property_key(), under_type_arguments), require_both_logical, info_chain, types, - ); + ) + } else { + crate::utilities::notify!("No mapped argument, returning BasedOnKey::Right"); + Ok(Logical::BasedOnKey(BasedOnKey::Right(PropertyOn { on, key })).into()) } - - crate::utilities::notify!("No mapped argument, returning BasedOnKey::Right"); - Ok(Logical::BasedOnKey(BasedOnKey::Right(PropertyOn { on, key })).into()) } else if get_constraint(on, types).is_some_and(is_inferrable_type) || is_inferrable_type(on) { @@ -681,6 +681,7 @@ pub(crate) fn get_property_unbound( #[derive(Debug, Clone, Copy, binary_serialize_derive::BinarySerializable)] pub enum AccessMode { Regular, + FromTypeAnnotation, /// For destructuring DoNotBindThis, } @@ -1160,7 +1161,7 @@ pub(crate) fn proxy_access( SynthesisedArgument { spread: false, value: resolver, position }, ]; let input = CallingInput { - // TOOD special + // TODO special called_with_new: CalledWithNew::GetterOrSetter { this_type: handler }, // TODO call_site: source_map::Nullable::NULL, diff --git a/checker/src/types/properties/assignment.rs b/checker/src/types/properties/assignment.rs index 14eb510a..7e18e2a8 100644 --- a/checker/src/types/properties/assignment.rs +++ b/checker/src/types/properties/assignment.rs @@ -74,8 +74,19 @@ pub fn set_property( // Doing this regardless of E::CHECK_PARAMETERS is how #18 works { - let object_constraint = - environment.get_object_constraint(on).or_else(|| get_constraint(on, types)); + let object_constraint = if let constraint @ Some(_) = environment.get_object_constraint(on) + { + constraint + } else if let Some(constraint) = get_constraint(on, types) { + crate::utilities::notify!( + "constraint={}", + crate::types::printing::print_type(constraint, types, environment, true) + ); + Some(constraint) + } else { + crate::utilities::notify!("No constraint (is an object)"); + None + }; if let Some(object_constraint) = object_constraint { // crate::utilities::notify!("constraint={:?}", types.get_type_by_id(constraint)); @@ -109,6 +120,8 @@ pub fn set_property( // ); if let Ok(LogicalOrValid::Logical(property_constraint)) = property_constraint { + crate::utilities::notify!("property_constraint={:?}", property_constraint); + // TODO property value is readonly // TODO state is writeable etc? // TODO document difference with context.writeable @@ -123,6 +136,7 @@ pub fn set_property( others: Default::default(), object_constraints: Default::default(), }; + let result = crate::subtyping::type_is_subtype_of_property( (&property_constraint, None), new, @@ -160,6 +174,7 @@ pub fn set_property( position, }); } + // if get_constraint(on, types).is_none() { // crate::utilities::notify!("Here"); // return Err(SetPropertyError::AssigningToNonExistent { @@ -167,7 +182,6 @@ pub fn set_property( // position, // }); // } - crate::utilities::notify!("TODO assigning to non existent"); // PropertyValue::Getter(_) // | PropertyValue::Setter(_) @@ -186,6 +200,11 @@ pub fn set_property( // }); // } // } + } else { + crate::utilities::notify!( + "More complex or non existent constraint {:?}. Skipping for now", + property_constraint + ); } } } @@ -429,57 +448,58 @@ fn run_setter_on_object( ) -> SetPropertyResult { match existing { PropertyValue::Deleted | PropertyValue::Value(..) => { - if let (Some(_), PropertyValue::Value(constraint_for_new)) = - (get_constraint(on, types), existing) - { - // TODO ...? - let mut state = State { - already_checked: Default::default(), - mode: Default::default(), - contributions: Default::default(), - others: Default::default(), - object_constraints: Default::default(), - }; - let result = crate::subtyping::type_is_subtype_with_generics( - (constraint_for_new, generics), - (new, None), - &mut state, - environment, - types, - ); - if let SubTypeResult::IsNotSubType(reason) = result { - { - crate::utilities::notify!( - "{} {:?}", - crate::types::printing::print_type( - constraint_for_new, - types, - environment, - true - ), - generics - ); - } - - let property_constraint = TypeStringRepresentation::from_property_constraint( - Logical::Pure(PropertyValue::Value(constraint_for_new)), - generics, - environment, - types, - false, - ); - let value_type = - TypeStringRepresentation::from_type_id(new, environment, types, false); - - // TOOD generics - return Err(SetPropertyError::DoesNotMeetConstraint { - property_constraint, - value_type, - reason, - position, - }); - } - } + // let constraint = get_constraint(on, types); + // if let (Some(_), PropertyValue::Value(constraint_for_new)) = + // (constraint, existing) + // { + // // TODO ...? + // let mut state = State { + // already_checked: Default::default(), + // mode: Default::default(), + // contributions: Default::default(), + // others: Default::default(), + // object_constraints: Default::default(), + // }; + // let result = crate::subtyping::type_is_subtype_with_generics( + // (constraint_for_new, generics), + // (new, None), + // &mut state, + // environment, + // types, + // ); + // if let SubTypeResult::IsNotSubType(reason) = result { + // { + // crate::utilities::notify!( + // "{} {:?}", + // crate::types::printing::print_type( + // constraint_for_new, + // types, + // environment, + // true + // ), + // generics + // ); + // } + + // let property_constraint = TypeStringRepresentation::from_property_constraint( + // Logical::Pure(PropertyValue::Value(constraint_for_new)), + // generics, + // environment, + // types, + // false, + // ); + // let value_type = + // TypeStringRepresentation::from_type_id(new, environment, types, false); + + // // TODO generics + // return Err(SetPropertyError::DoesNotMeetConstraint { + // property_constraint, + // value_type, + // reason, + // position, + // }); + // } + // } let value = if let Some(descriptor) = descriptor { PropertyValue::Configured { on: Box::new(PropertyValue::Value(new)), descriptor } @@ -610,7 +630,7 @@ pub(crate) fn proxy_assign( SynthesisedArgument { spread: false, value: resolver, position }, ]; let input = CallingInput { - // TOOD special + // TODO special called_with_new: CalledWithNew::GetterOrSetter { this_type: handler }, // TODO call_site: source_map::Nullable::NULL, diff --git a/checker/src/types/properties/list.rs b/checker/src/types/properties/list.rs index 9e97c437..a42f38e4 100644 --- a/checker/src/types/properties/list.rs +++ b/checker/src/types/properties/list.rs @@ -81,7 +81,11 @@ pub fn get_properties_on_single_type( } else { // TODO temp fix if idx >= properties.len() { - crate::utilities::notify!("Here! {:?}", properties); + crate::utilities::notify!( + "Here! idx {:?} > properties {:?}", + idx, + properties + ); continue; } properties[idx] = value; diff --git a/checker/src/types/properties/mod.rs b/checker/src/types/properties/mod.rs index 804c740b..540c873d 100644 --- a/checker/src/types/properties/mod.rs +++ b/checker/src/types/properties/mod.rs @@ -83,7 +83,38 @@ impl crate::BinarySerializable for PropertyKey<'static> { } } -impl<'a> PropertyKey<'a> { +#[allow(clippy::float_cmp)] +fn float_as_u8(number: f64) -> Option { + if !number.is_nan() && number == number.trunc() && (0. ..256.).contains(&number) { + Some(number as u8) + } else { + None + } +} + +impl PropertyKey<'_> { + /// For array indexes + #[must_use] + pub fn from_usize(a: usize) -> PropertyKey<'static> { + if let Ok(a) = u8::try_from(a) { + PropertyKey::from_u8(a) + } else { + PropertyKey::String(Cow::Owned(a.to_string())) + } + } + + /// For small array indexes + #[must_use] + pub fn from_u8(a: u8) -> PropertyKey<'static> { + // Trick to not allocate for static property keys under < 10 + static NUMBERS: &str = "0123456789"; + if a < 10 { + PropertyKey::String(Cow::Borrowed(&NUMBERS[(a as usize)..=(a as usize)])) + } else { + PropertyKey::String(Cow::Owned(a.to_string())) + } + } + #[must_use] pub fn into_owned(&self) -> PropertyKey<'static> { match self { @@ -96,8 +127,11 @@ impl<'a> PropertyKey<'a> { if let Type::Constant(c) = types.get_type_by_id(ty) { match c { Constant::Number(n) => { - // if n.fractional ?? - PropertyKey::from_usize(n.into_inner() as usize) + if let Some(n) = float_as_u8(*n) { + PropertyKey::from_u8(n) + } else { + PropertyKey::String(Cow::Owned(n.to_string())) + } } Constant::String(s) => PropertyKey::String(Cow::Owned(s.to_owned())), Constant::Boolean(b) => { @@ -107,7 +141,6 @@ impl<'a> PropertyKey<'a> { // Okay I think? PropertyKey::Type(ty) } - Constant::NaN => PropertyKey::String(Cow::Borrowed("NaN")), Constant::Undefined => PropertyKey::String(Cow::Borrowed("undefined")), } } else { @@ -120,13 +153,7 @@ impl<'a> PropertyKey<'a> { PropertyKey::String(s) => s.parse::().ok(), PropertyKey::Type(t) => { if let Type::Constant(Constant::Number(n)) = types.get_type_by_id(*t) { - // TODO is there a better way - #[allow(clippy::float_cmp)] - if n.trunc() == **n { - Some(**n as usize) - } else { - None - } + float_as_u8(*n).map(|n| n as usize) } else { None } @@ -211,21 +238,6 @@ pub(crate) fn get_simple_property_value( } } -// WIP quick hack for static property keys under < 10 -static NUMBERS: &str = "0123456789"; - -impl<'a> PropertyKey<'a> { - /// For small array indexes - #[must_use] - pub fn from_usize(a: usize) -> Self { - if a < 10 { - Self::String(Cow::Borrowed(&NUMBERS[a..=a])) - } else { - Self::String(Cow::Owned(a.to_string())) - } - } -} - /// TODO getter, setter need a closure id (or implement using `Callable::Type`) #[derive(Clone, Debug, binary_serialize_derive::BinarySerializable)] pub enum PropertyValue { diff --git a/checker/src/types/store.rs b/checker/src/types/store.rs index 263ced34..fb09ed7b 100644 --- a/checker/src/types/store.rs +++ b/checker/src/types/store.rs @@ -4,7 +4,7 @@ use source_map::{Nullable, Span, SpanWithSource}; use crate::{ features::{functions::ClosureId, objects::SpecialObject, regexp::RegExp}, - Constant, Environment, FunctionId, Map as SmallMap, TypeId, + Constant, Environment, FunctionId, Map as SmallMap, TypeId, VariableId, }; use super::{ @@ -26,6 +26,10 @@ pub struct TypeStore { /// Some types are prototypes but have generic parameters but pub(crate) lookup_generic_map: HashMap, + /// For free variables and parameters. For diagnostics (extends and assetion printing). + /// Not held on context because this is more accessible + pub(crate) parameter_names: HashMap, + /// Contains all the function types /// /// TODO is there a faster alternative to a [`HashMap`] like how [`Type`]s are stored in a [`Vec`] @@ -74,12 +78,12 @@ impl Default for TypeStore { // one Type::Constant(Constant::Number(1.into())), // NaN - Type::Constant(Constant::NaN), - Type::Constant(Constant::Number(f64::NEG_INFINITY.try_into().unwrap())), - Type::Constant(Constant::Number(f64::INFINITY.try_into().unwrap())), - Type::Constant(Constant::Number(f64::MIN.try_into().unwrap())), - Type::Constant(Constant::Number(f64::MAX.try_into().unwrap())), - Type::Constant(Constant::Number(f64::EPSILON.try_into().unwrap())), + Type::Constant(Constant::Number(f64::NAN)), + Type::Constant(Constant::Number(f64::NEG_INFINITY)), + Type::Constant(Constant::Number(f64::INFINITY)), + Type::Constant(Constant::Number(f64::MIN)), + Type::Constant(Constant::Number(f64::MAX)), + Type::Constant(Constant::Number(f64::EPSILON)), Type::Constant(Constant::Number({ const THIRTY_TWO_ONE_BITS: i32 = -1i32; THIRTY_TWO_ONE_BITS.into() @@ -208,6 +212,7 @@ impl Default for TypeStore { Self { types, lookup_generic_map, + parameter_names: Default::default(), functions: Default::default(), called_functions: Default::default(), closure_counter: 0, @@ -221,6 +226,7 @@ impl TypeStore { self.types.len() } + #[allow(clippy::float_cmp)] pub fn new_constant_type(&mut self, constant: Constant) -> crate::TypeId { // Reuse existing ids rather than creating new types sometimes match constant { @@ -229,9 +235,9 @@ impl TypeStore { Constant::Number(number) if number == 1f64 => TypeId::ONE, Constant::Number(number) if number == f64::NEG_INFINITY => TypeId::NEG_INFINITY, Constant::Number(number) if number == f64::INFINITY => TypeId::INFINITY, + Constant::Number(number) if number.is_nan() => TypeId::NAN, Constant::Boolean(true) => TypeId::TRUE, Constant::Boolean(false) => TypeId::FALSE, - Constant::NaN => TypeId::NAN, _ => { let ty = Type::Constant(constant); // TODO maybe separate id @@ -451,7 +457,6 @@ impl TypeStore { self.register_type(Type::FunctionReference(id)) } - /// TODO WIP #[allow(clippy::similar_names)] pub(crate) fn new_property_on_type_annotation( &mut self, @@ -466,7 +471,7 @@ impl TypeStore { on: indexee, under, result: TypeId::ANY_TYPE, - mode: AccessMode::Regular, + mode: AccessMode::FromTypeAnnotation, }); self.register_type(ty) } else { @@ -479,7 +484,7 @@ impl TypeStore { ); if let Ok(prop) = result { match prop { - LogicalOrValid::Logical(Logical::Pure(ty)) => ty.as_get_type(self), + LogicalOrValid::Logical(Logical::Pure(value)) => value.as_get_type(self), value => { crate::utilities::notify!("value={:?}", value); TypeId::UNIMPLEMENTED_ERROR_TYPE @@ -506,7 +511,14 @@ impl TypeStore { Ok(self.register_type(ty)) } - pub fn new_function_parameter(&mut self, parameter_constraint: TypeId) -> TypeId { + pub fn new_function_parameter( + &mut self, + parameter_constraint: TypeId, + variable_id: VariableId, + name: &str, + ) -> TypeId { + self.parameter_names.insert(variable_id, name.to_owned()); + // TODO this has problems if there are two generic types. Aka `(a: T, b: T) -> T`. Although I have // no idea why this is possible so should be fine? if let Type::RootPolyType(PolyNature::FunctionGeneric { .. }) = @@ -516,6 +528,7 @@ impl TypeStore { } else { self.register_type(Type::RootPolyType(crate::types::PolyNature::Parameter { fixed_to: parameter_constraint, + variable_id, })) } } @@ -592,7 +605,7 @@ impl TypeStore { /// *Dangerous* . TODO WIP pub(crate) fn _set_inferred_constraint(&mut self, ty: TypeId, constraint: TypeId) { - if let Some(Type::RootPolyType(PolyNature::Parameter { fixed_to })) = + if let Some(Type::RootPolyType(PolyNature::Parameter { fixed_to, variable_id: _ })) = self.types.get_mut(ty.0 as usize) { *fixed_to = constraint; @@ -651,4 +664,8 @@ impl TypeStore { .skip(TypeId::INTERNAL_TYPE_COUNT) .map(|(idx, ty)| (TypeId(idx as u16), ty)) } + + pub(crate) fn get_parameter_name(&self, id: VariableId) -> &str { + self.parameter_names.get(&id).map(String::as_str).unwrap_or_default() + } } diff --git a/checker/src/types/subtyping.rs b/checker/src/types/subtyping.rs index 1fe9fa0c..a22a220e 100644 --- a/checker/src/types/subtyping.rs +++ b/checker/src/types/subtyping.rs @@ -1,4 +1,5 @@ //! Type subtype checking. (making sure the RHS type contains all the properties the LHS type requires) +#![allow(clippy::float_cmp)] use source_map::SpanWithSource; @@ -186,7 +187,7 @@ pub struct State<'a> { pub type StateSavePoint = [u16; 4]; -impl<'a> State<'a> { +impl State<'_> { /// For `or`s, some items might have to be removed if the branch fails #[must_use] pub fn produce_save_point(&self) -> StateSavePoint { @@ -225,15 +226,15 @@ pub(crate) fn type_is_subtype_with_generics( information: &impl InformationChain, types: &TypeStore, ) -> SubTypeResult { - { - let debug = true; - crate::utilities::notify!( - "Checking {} :>= {}, with {:?}", - print_type(base_type, types, information, debug), - print_type(ty, types, information, debug), - base_type_arguments - ); - } + // { + // let debug = true; + // crate::utilities::notify!( + // "Checking {} :>= {}, with {:?}", + // print_type(base_type, types, information, debug), + // print_type(ty, types, information, debug), + // base_type_arguments + // ); + // } if base_type == TypeId::ANY_TYPE || ty == TypeId::NEVER_TYPE { return SubTypeResult::IsSubType; @@ -453,7 +454,7 @@ pub(crate) fn type_is_subtype_with_generics( ), Type::Constant(lhs) => { if let Type::Constant(rhs) = subtype { - if lhs == rhs { + if lhs.equals(rhs) { SubTypeResult::IsSubType } else { SubTypeResult::IsNotSubType(NonEqualityReason::Mismatch) @@ -1310,7 +1311,6 @@ pub(crate) fn type_is_subtype_with_generics( types, ); if let Ok(LogicalOrValid::Logical(property)) = property { - crate::utilities::notify!("Here 3"); match property { Logical::Pure(property) => { crate::utilities::notify!("Here 4 {:?}", property); @@ -1464,7 +1464,9 @@ pub(crate) fn type_is_subtype_with_generics( SubTypeResult::IsNotSubType(NonEqualityReason::Mismatch) } } else { - crate::utilities::notify!("No prototype"); + crate::utilities::notify!( + "No prototype on object when comparing with class => mismatch" + ); SubTypeResult::IsNotSubType(NonEqualityReason::Mismatch) } } @@ -1623,7 +1625,7 @@ pub(crate) fn type_is_subtype_with_generics( fn subtype_function( (left_func, base_type_arguments): (crate::FunctionId, GenericChain), - (subtype, ty, subtypepe_arguments): (&Type, TypeId, GenericChain), + (subtype, ty, subtype_arguments): (&Type, TypeId, GenericChain), state: &mut State, information: &impl InformationChain, types: &TypeStore, @@ -1660,7 +1662,7 @@ fn subtype_function( // Reverse is important let result = type_is_subtype_with_generics( - (right_param_ty, subtypepe_arguments), + (right_param_ty, subtype_arguments), (lhs_param.ty, base_type_arguments), state, information, @@ -1673,7 +1675,7 @@ fn subtype_function( crate::utilities::notify!( "Parameter invalid rhs ({:?} {:?}) <- lhs ({:?} {:?})", rhs, - subtypepe_arguments, + subtype_arguments, lhs, base_type_arguments ); @@ -1699,7 +1701,7 @@ fn subtype_function( } else { let type_is_subtype_with_generics = type_is_subtype_with_generics( (left_func.return_type, base_type_arguments), - (right_func.return_type, subtypepe_arguments), + (right_func.return_type, subtype_arguments), state, information, types, @@ -1715,7 +1717,7 @@ fn subtype_function( fn subtype_floating_properties( (base_type, base_type_arguments): (TypeId, GenericChain), - (ty, subtypepe_arguments): (TypeId, GenericChain), + (ty, subtype_arguments): (TypeId, GenericChain), state: &mut State, information: &impl InformationChain, types: &TypeStore, @@ -1727,7 +1729,7 @@ fn subtype_floating_properties( subtype_properties( (base_type, reversed_flattened_properties_on_base, base_type_arguments), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -1736,7 +1738,7 @@ fn subtype_floating_properties( fn subtype_properties<'a, T>( (base_type, base_properties, base_type_arguments): (TypeId, T, GenericChain), - (ty, subtypepe_arguments): (TypeId, GenericChain), + (ty, subtype_arguments): (TypeId, GenericChain), state: &mut State, information: &impl InformationChain, types: &TypeStore, @@ -1773,7 +1775,7 @@ where let result = check_lhs_property_is_super_type_of_rhs( (*publicity, key), (lhs_property, base_type_arguments, false), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -1790,7 +1792,7 @@ where if let Type::Interface { extends: Some(extends), .. } = types.get_type_by_id(base_type) { let extends_result = type_is_subtype_with_generics( (*extends, base_type_arguments), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -1859,7 +1861,7 @@ where fn check_lhs_property_is_super_type_of_rhs( (publicity, key): (Publicity, &PropertyKey<'_>), (lhs_property, base_type_arguments, optional): (&PropertyValue, GenericChain, bool), - (ty, subtypepe_arguments): (TypeId, GenericChain), + (ty, subtype_arguments): (TypeId, GenericChain), state: &mut State, information: &impl InformationChain, types: &TypeStore, @@ -1867,7 +1869,7 @@ fn check_lhs_property_is_super_type_of_rhs( match lhs_property { PropertyValue::Value(lhs_value) => { let right_result = get_property_unbound( - (ty, subtypepe_arguments), + (ty, subtype_arguments), (publicity, key, base_type_arguments), false, information, @@ -1887,7 +1889,7 @@ fn check_lhs_property_is_super_type_of_rhs( Ok(LogicalOrValid::Logical(res)) => { let res = check_logical_property( (*lhs_value, base_type_arguments, optional), - (res, subtypepe_arguments), + (res, subtype_arguments), state, information, types, @@ -1909,7 +1911,7 @@ fn check_lhs_property_is_super_type_of_rhs( ))) => { crate::utilities::notify!("TODO set as well?"); let get_handler = get_property_unbound( - (handler, subtypepe_arguments), + (handler, subtype_arguments), ( Publicity::Public, &PropertyKey::String(std::borrow::Cow::Borrowed("get")), @@ -1947,14 +1949,14 @@ fn check_lhs_property_is_super_type_of_rhs( map.insert(third, (CovariantContribution::TypeId(handler), 0)); } - let subtypepe_arguments = Some(GenericChainLink::MappedPropertyLink { - parent_link: subtypepe_arguments.as_ref(), + let subtype_arguments = Some(GenericChainLink::MappedPropertyLink { + parent_link: subtype_arguments.as_ref(), value: &map, }); let result = type_is_subtype_with_generics( (*lhs_value, base_type_arguments), - (function.return_type, subtypepe_arguments), + (function.return_type, subtype_arguments), state, information, types, @@ -1971,7 +1973,7 @@ fn check_lhs_property_is_super_type_of_rhs( check_lhs_property_is_super_type_of_rhs( (publicity, key), (lhs_property, base_type_arguments, optional), - (handler, subtypepe_arguments), + (handler, subtype_arguments), state, information, types, @@ -1981,7 +1983,7 @@ fn check_lhs_property_is_super_type_of_rhs( check_lhs_property_is_super_type_of_rhs( (publicity, key), (lhs_property, base_type_arguments, optional), - (handler, subtypepe_arguments), + (handler, subtype_arguments), state, information, types, @@ -2055,14 +2057,14 @@ fn check_lhs_property_is_super_type_of_rhs( check_lhs_property_is_super_type_of_rhs( (publicity, key), (truthy, base_type_arguments, is_optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, ) // if let PropertyValue::Value(lhs_value) = &**truthy { // let property = get_property_unbound( - // (ty, subtypepe_arguments), + // (ty, subtype_arguments), // (publicity, key, base_type_arguments), // information, // types, @@ -2081,7 +2083,7 @@ fn check_lhs_property_is_super_type_of_rhs( // let res = check_logical_property( // (*lhs_value, base_type_arguments), - // (property, subtypepe_arguments), + // (property, subtype_arguments), // state, // information, // types, @@ -2112,7 +2114,7 @@ fn check_lhs_property_is_super_type_of_rhs( check_lhs_property_is_super_type_of_rhs( (publicity, key), (on, base_type_arguments, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2123,7 +2125,7 @@ fn check_lhs_property_is_super_type_of_rhs( fn check_logical_property( (lhs_property_value, lhs_property_value_type_arguments, optional): (TypeId, GenericChain, bool), - (rhs_property, subtypepe_arguments): (Logical, GenericChain), + (rhs_property, subtype_arguments): (Logical, GenericChain), state: &mut State, information: &impl InformationChain, types: &TypeStore, @@ -2141,7 +2143,7 @@ fn check_logical_property( type_is_subtype_with_generics( (lhs_property_value, lhs_property_value_type_arguments), - (rhs_type, subtypepe_arguments), + (rhs_type, subtype_arguments), state, information, types, @@ -2154,7 +2156,7 @@ fn check_logical_property( { let left_result = check_logical_property( (lhs_property_value, lhs_property_value_type_arguments, optional), - (left, subtypepe_arguments), + (left, subtype_arguments), state, information, types, @@ -2163,7 +2165,7 @@ fn check_logical_property( if let SubTypeResult::IsSubType = left_result { check_logical_property( (lhs_property_value, lhs_property_value_type_arguments, optional), - (right, subtypepe_arguments), + (right, subtype_arguments), state, information, types, @@ -2187,7 +2189,7 @@ fn check_logical_property( *on, GenericChainLink::append( TypeId::UNIMPLEMENTED_ERROR_TYPE, - subtypepe_arguments.as_ref(), + subtype_arguments.as_ref(), &antecedent, ), ), @@ -2199,7 +2201,7 @@ fn check_logical_property( Logical::BasedOnKey(kind) => match kind { BasedOnKey::Left { value, key_arguments } => { let property_generics = Some(GenericChainLink::MappedPropertyLink { - parent_link: subtypepe_arguments.as_ref(), + parent_link: subtype_arguments.as_ref(), value: &key_arguments, }); check_logical_property( @@ -2217,7 +2219,7 @@ fn check_logical_property( type_is_subtype_of_property_mapped_key( MappedKey { value: (*extends).into(), key }, (lhs_property_value, lhs_property_value_type_arguments, optional), - (on, subtypepe_arguments), + (on, subtype_arguments), state, information, types, @@ -2226,7 +2228,7 @@ fn check_logical_property( let filter = get_constraint(key, types).unwrap_or(key); let properties = get_properties_on_single_type2( - (on, subtypepe_arguments), + (on, subtype_arguments), types, information, filter, @@ -2234,7 +2236,7 @@ fn check_logical_property( for (_key, rhs_property, _args) in properties { let result = check_logical_property( (lhs_property_value, lhs_property_value_type_arguments, optional), - (Logical::Pure(rhs_property), subtypepe_arguments), + (Logical::Pure(rhs_property), subtype_arguments), state, information, types, @@ -2260,7 +2262,7 @@ pub struct MappedKey { pub fn type_is_subtype_of_property_mapped_key( mapped_key: MappedKey, (base, property_generics, optional): (TypeId, GenericChain, bool), - (ty, subtypepe_arguments): (TypeId, GenericChain), + (ty, subtype_arguments): (TypeId, GenericChain), state: &mut State, information: &impl InformationChain, types: &TypeStore, @@ -2273,11 +2275,11 @@ pub fn type_is_subtype_of_property_mapped_key( "Reading {:?}, with {:?} {:?}", types.get_type_by_id(ty), s, - (property_generics.as_ref(), subtypepe_arguments.as_ref()) + (property_generics.as_ref(), subtype_arguments.as_ref()) ); } let right_property = get_property_unbound( - (ty, subtypepe_arguments), + (ty, subtype_arguments), ( Publicity::Public, &PropertyKey::String(std::borrow::Cow::Owned(s.to_owned())), @@ -2297,7 +2299,7 @@ pub fn type_is_subtype_of_property_mapped_key( }); let result = check_logical_property( (base, property_generics, optional), - (right_property, subtypepe_arguments), + (right_property, subtype_arguments), state, information, types, @@ -2324,7 +2326,7 @@ pub fn type_is_subtype_of_property_mapped_key( | Type::AliasTo { to, name: _, parameters: _ } => type_is_subtype_of_property_mapped_key( MappedKey { value: (*to).into(), key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2333,7 +2335,7 @@ pub fn type_is_subtype_of_property_mapped_key( let left = type_is_subtype_of_property_mapped_key( MappedKey { value: (*left).into(), key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2342,7 +2344,7 @@ pub fn type_is_subtype_of_property_mapped_key( type_is_subtype_of_property_mapped_key( MappedKey { value: (*right).into(), key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2355,7 +2357,7 @@ pub fn type_is_subtype_of_property_mapped_key( let left = type_is_subtype_of_property_mapped_key( MappedKey { value: (*left).into(), key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2366,7 +2368,7 @@ pub fn type_is_subtype_of_property_mapped_key( type_is_subtype_of_property_mapped_key( MappedKey { value: (*right).into(), key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2381,7 +2383,7 @@ pub fn type_is_subtype_of_property_mapped_key( type_is_subtype_of_property_mapped_key( MappedKey { value: value.into(), key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2411,7 +2413,7 @@ pub fn type_is_subtype_of_property_mapped_key( let result = type_is_subtype_of_property_mapped_key( MappedKey { value, key: mapped_key.key }, (base, property_generics, optional), - (ty, subtypepe_arguments), + (ty, subtype_arguments), state, information, types, @@ -2429,8 +2431,8 @@ pub fn type_is_subtype_of_property_mapped_key( Type::Class { .. } => todo!(), Type::Constant(_) => { let right_property = get_property_unbound( - (ty, subtypepe_arguments), - (Publicity::Public, &PropertyKey::Type(key_ty), subtypepe_arguments), + (ty, subtype_arguments), + (Publicity::Public, &PropertyKey::Type(key_ty), subtype_arguments), true, information, types, @@ -2446,7 +2448,7 @@ pub fn type_is_subtype_of_property_mapped_key( }); check_logical_property( (base, property_generics, optional), - (right_property, subtypepe_arguments), + (right_property, subtype_arguments), state, information, types, @@ -2523,6 +2525,28 @@ pub fn type_is_subtype_of_property( type_is_subtype_of_property((on, property_generics), ty, state, information, types) } Logical::BasedOnKey(on) => { + match on { + BasedOnKey::Left { value, key_arguments } => type_is_subtype_of_property( + ( + value, + Some(GenericChainLink::MappedPropertyLink { + value: key_arguments, + parent_link: property_generics.as_ref(), + }), + ), + ty, + state, + information, + types, + ), + BasedOnKey::Right(on) => { + crate::utilities::notify!( + "TODO BasedOnKey::Right, returning temp IsSubType {:?}", + on + ); + SubTypeResult::IsSubType + } + } // if let BasedOnKey::Right { on, key } = on { // if let Type::RootPolyType(PolyNature::MappedGeneric { name: _, extends }) = // types.get_type_by_id(*filter) @@ -2540,8 +2564,6 @@ pub fn type_is_subtype_of_property( // SubTypeResult::IsSubType // } // } else { - crate::utilities::notify!("TODO, returning IsSubType {:?}", on); - SubTypeResult::IsSubType // } } } @@ -2969,7 +2991,7 @@ pub(crate) fn slice_matches_type( } // TODO keyof -#[allow(clippy::only_used_in_recursion)] +#[allow(clippy::only_used_in_recursion, clippy::float_cmp)] pub(crate) fn number_matches_type( (base, base_type_arguments): (TypeId, Option), number: f64, @@ -2980,7 +3002,7 @@ pub(crate) fn number_matches_type( match types.get_type_by_id(base) { Type::Constant(cst) => { if let Constant::Number(base_number) = cst { - *base_number == number + *base_number == number || (base_number.is_nan() && number.is_nan()) } else { false } @@ -2991,7 +3013,6 @@ pub(crate) fn number_matches_type( }) => { let argument = arguments.get_structure_restriction(TypeId::NUMBER_GENERIC).unwrap(); if let Type::Constant(Constant::Number(argument)) = types.get_type_by_id(argument) { - let number: ordered_float::NotNan = number.try_into().unwrap(); (number % argument) == 0. } else { crate::utilities::notify!("Here?"); diff --git a/checker/src/types/terms.rs b/checker/src/types/terms.rs index 16e747eb..8ec7e1a7 100644 --- a/checker/src/types/terms.rs +++ b/checker/src/types/terms.rs @@ -5,17 +5,31 @@ use super::TypeId; /// Terms. `null` is a special object /// TODO: /// - `BigInt` () -#[derive(Eq, PartialEq, Hash, Debug, Clone, binary_serialize_derive::BinarySerializable)] +#[derive(Debug, Clone, binary_serialize_derive::BinarySerializable)] pub enum Constant { - Number(ordered_float::NotNan), + Number(f64), String(String), Boolean(bool), Symbol { key: String }, - NaN, Undefined, } impl Constant { + // Not PartialEq because float + #[must_use] + #[allow(clippy::float_cmp, clippy::match_same_arms)] + pub fn equals(&self, other: &Self) -> bool { + match (self, other) { + (Constant::Number(a), Constant::Number(b)) if a.is_nan() && b.is_nan() => true, + (Constant::Number(a), Constant::Number(b)) => a == b, + (Constant::String(a), Constant::String(b)) => a == b, + (Constant::Boolean(a), Constant::Boolean(b)) => a == b, + (Constant::Symbol { key: a }, Constant::Symbol { key: b }) => a == b, + (Constant::Undefined, Constant::Undefined) => true, + _ => false, + } + } + /// **AS OF THE JS IMPLEMENTATION** #[must_use] pub fn as_js_string(&self) -> Cow { @@ -24,7 +38,6 @@ impl Constant { Constant::String(value) => Cow::Borrowed(value), Constant::Boolean(value) => Cow::Borrowed(if *value { "true" } else { "false" }), Constant::Symbol { key } => Cow::Owned(format!("Symbol({key})")), - Constant::NaN => Cow::Borrowed("NaN"), Constant::Undefined => Cow::Borrowed("undefined"), } } @@ -38,7 +51,6 @@ impl Constant { Constant::String(value) => format!("\"{value}\""), Constant::Boolean(value) => if *value { "true" } else { "false" }.to_owned(), Constant::Symbol { key } => format!("Symbol({key})"), - Constant::NaN => "NaN".to_owned(), Constant::Undefined => "undefined".to_owned(), } } @@ -46,7 +58,7 @@ impl Constant { #[must_use] pub fn get_backing_type(&self) -> TypeId { match self { - Constant::Number(_) | Constant::NaN => TypeId::NUMBER_TYPE, + Constant::Number(_) => TypeId::NUMBER_TYPE, Constant::String(_) => TypeId::STRING_TYPE, Constant::Boolean(_) => TypeId::BOOLEAN_TYPE, Constant::Symbol { .. } => TypeId::SYMBOL_TYPE, diff --git a/checker/src/utilities/float_range.rs b/checker/src/utilities/float_range.rs index c0870212..c95032f3 100644 --- a/checker/src/utilities/float_range.rs +++ b/checker/src/utilities/float_range.rs @@ -1,4 +1,4 @@ -type BetterF64 = ordered_float::NotNan; +#![allow(clippy::float_cmp)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum InclusiveExclusive { @@ -26,28 +26,25 @@ impl InclusiveExclusive { #[derive(Debug, Clone, Copy, PartialEq)] pub struct FloatRange { - pub floor: (InclusiveExclusive, BetterF64), - pub ceiling: (InclusiveExclusive, BetterF64), + pub floor: (InclusiveExclusive, f64), + pub ceiling: (InclusiveExclusive, f64), } impl Default for FloatRange { fn default() -> Self { - Self { - floor: (Exclusive, f64::NEG_INFINITY.try_into().unwrap()), - ceiling: (Exclusive, f64::INFINITY.try_into().unwrap()), - } + Self { floor: (Exclusive, f64::NEG_INFINITY), ceiling: (Exclusive, f64::INFINITY) } } } // TODO try_from (assert ceiling > floor etc) impl FloatRange { #[must_use] - pub fn new_single(on: BetterF64) -> Self { + pub fn new_single(on: f64) -> Self { Self { floor: (Inclusive, on), ceiling: (Inclusive, on) } } #[must_use] - pub fn as_single(self) -> Option { + pub fn as_single(self) -> Option { if let FloatRange { floor: (Inclusive, floor), ceiling: (Inclusive, ceiling) } = self { (floor == ceiling).then_some(floor) } else { @@ -56,33 +53,28 @@ impl FloatRange { } #[must_use] - pub fn new_greater_than(greater_than: BetterF64) -> Self { - FloatRange { - floor: (Exclusive, greater_than), - ceiling: (Exclusive, f64::INFINITY.try_into().unwrap()), - } + pub fn new_greater_than(greater_than: f64) -> Self { + FloatRange { floor: (Exclusive, greater_than), ceiling: (Exclusive, f64::INFINITY) } } #[must_use] - pub fn get_greater_than(self) -> Option { + pub fn get_greater_than(self) -> Option { (self.floor.1 != f64::NEG_INFINITY).then_some(self.floor.1) } #[must_use] - pub fn new_less_than(less_than: BetterF64) -> Self { - FloatRange { - floor: (Exclusive, f64::NEG_INFINITY.try_into().unwrap()), - ceiling: (Exclusive, less_than), - } + pub fn new_less_than(less_than: f64) -> Self { + FloatRange { floor: (Exclusive, f64::NEG_INFINITY), ceiling: (Exclusive, less_than) } } #[must_use] - pub fn get_less_than(self) -> Option { + pub fn get_less_than(self) -> Option { (self.ceiling.1 != f64::INFINITY).then_some(self.ceiling.1) } #[must_use] - pub fn contains(self, value: BetterF64) -> bool { + #[allow(clippy::float_cmp)] + pub fn contains(self, value: f64) -> bool { if self.floor.1 < value && value < self.ceiling.1 { true } else if self.floor.1 == value { @@ -174,10 +166,17 @@ impl FloatRange { let (l_floor, l_ceiling, r_floor, r_ceiling) = (self.floor.1, self.ceiling.1, other.floor.1, other.ceiling.1); // there may be a faster way but being lazy - let corners = - [l_floor * r_floor, l_floor * r_ceiling, r_floor * l_ceiling, l_ceiling * r_ceiling]; - let floor = *corners.iter().min().unwrap(); - let ceiling = *corners.iter().max().unwrap(); + let initial = l_floor * r_floor; + let mut floor = initial; + let mut ceiling = initial; + let other_corners = &[l_floor * r_ceiling, r_floor * l_ceiling, l_ceiling * r_ceiling]; + for corner in other_corners { + if *corner < floor { + floor = *corner; + } else if *corner > ceiling { + ceiling = *corner; + } + } let floor_bound = self.floor.0.mix(other.floor.0); let ceiling_bound = self.ceiling.0.mix(other.ceiling.0); @@ -185,14 +184,14 @@ impl FloatRange { } #[must_use] - pub fn contains_multiple_of(self, multiple_of: BetterF64) -> bool { + pub fn contains_multiple_of(self, multiple_of: f64) -> bool { let (floor, ceiling) = (self.floor.1, self.ceiling.1); let floor = floor / multiple_of; let ceiling = ceiling / multiple_of; // TODO >= ? - ceiling.floor() > *floor + ceiling.floor() > floor } // This will try to get cover @@ -212,38 +211,40 @@ impl FloatRange { // TODO more :) } -impl From> for FloatRange { - fn from(range: std::ops::Range) -> FloatRange { - FloatRange { floor: (Exclusive, range.start), ceiling: (Exclusive, range.end) } - } -} +#[derive(Debug)] +pub struct FloatIsNan; + impl TryFrom> for FloatRange { - type Error = ordered_float::FloatIsNan; + type Error = FloatIsNan; fn try_from(range: std::ops::Range) -> Result { - let floor = ordered_float::NotNan::new(range.start)?; - let ceiling = ordered_float::NotNan::new(range.end)?; - Ok(FloatRange { floor: (Exclusive, floor), ceiling: (Exclusive, ceiling) }) + let floor = range.start; + let ceiling = range.end; + if floor.is_nan() || ceiling.is_nan() { + Err(FloatIsNan) + } else { + Ok(FloatRange { floor: (Exclusive, floor), ceiling: (Exclusive, ceiling) }) + } } } -// TODO more +// TODO inclusive tests and more #[cfg(test)] mod tests { - use super::{BetterF64, FloatRange, InclusiveExclusive}; + use super::{FloatRange, InclusiveExclusive}; - fn e(a: f64) -> (InclusiveExclusive, BetterF64) { - (InclusiveExclusive::Exclusive, a.try_into().unwrap()) + fn e(a: f64) -> (InclusiveExclusive, f64) { + (InclusiveExclusive::Exclusive, a) } - fn i(a: f64) -> (InclusiveExclusive, BetterF64) { - (InclusiveExclusive::Inclusive, a.try_into().unwrap()) + fn _i(a: f64) -> (InclusiveExclusive, f64) { + (InclusiveExclusive::Inclusive, a) } #[test] fn contained_in() { let zero_to_four: FloatRange = FloatRange::try_from(0f64..4f64).unwrap(); - assert!(FloatRange::new_single(2.into()).contained_in(zero_to_four)); + assert!(FloatRange::new_single(2.).contained_in(zero_to_four)); } #[test] diff --git a/checker/src/utilities/modulo_class.rs b/checker/src/utilities/modulo_class.rs index e5753d50..1324726c 100644 --- a/checker/src/utilities/modulo_class.rs +++ b/checker/src/utilities/modulo_class.rs @@ -1,18 +1,16 @@ -type BetterF64 = ordered_float::NotNan; - /// x ≡ *class* [mod *modulo*] #[derive(Debug, Clone, Copy, PartialEq)] pub struct ModuloClass { - pub modulo: BetterF64, - pub offset: BetterF64, + pub modulo: f64, + pub offset: f64, } // TODO more operations impl ModuloClass { #[must_use] - pub fn new(modulo: BetterF64, offset: BetterF64) -> Self { + pub fn new(modulo: f64, offset: f64) -> Self { debug_assert!(modulo != 0.); - if modulo > 0f64.try_into().unwrap() { + if modulo > 0f64 { Self { offset: offset % modulo, modulo } } else { // TODO think this is correct. [1]_{-3} = [2]_{3} @@ -22,7 +20,7 @@ impl ModuloClass { } #[must_use] - pub fn contains(self, value: BetterF64) -> bool { + pub fn contains(self, value: f64) -> bool { // Note -0. = 0. (value - self.offset) % self.modulo == 0. } @@ -50,7 +48,7 @@ impl ModuloClass { } #[must_use] - pub fn offset(self, offset: BetterF64) -> Self { + pub fn offset(self, offset: f64) -> Self { // TODO temp fix if self.is_default() { self @@ -60,7 +58,7 @@ impl ModuloClass { } #[must_use] - pub fn multiply(self, multiple: BetterF64) -> Self { + pub fn multiply(self, multiple: f64) -> Self { // TODO temp fix if self.is_default() { self @@ -88,7 +86,7 @@ impl ModuloClass { /// Using Farey algoirthm /// TODO is there a faster way implemntation /// Note that numerator and denominator are coprime -fn try_get_numerator_denominator(input: BetterF64) -> Result<(i32, i32), ()> { +fn try_get_numerator_denominator(input: f64) -> Result<(i32, i32), ()> { const STEPS: usize = 50; const MARGIN: f64 = 1e-4; @@ -118,7 +116,7 @@ fn try_get_numerator_denominator(input: BetterF64) -> Result<(i32, i32), ()> { Err(()) } -fn gcd_of_float(n1: BetterF64, n2: BetterF64) -> Result { +fn gcd_of_float(n1: f64, n2: f64) -> Result { fn gcd(mut n1: i32, mut n2: i32) -> i32 { while n2 != 0 { let t = n2; @@ -137,13 +135,13 @@ fn gcd_of_float(n1: BetterF64, n2: BetterF64) -> Result { let (c, d) = try_get_numerator_denominator(n2)?; // gcd(a / b, c / d) = gcd(a, c) / lcm(b, d) - Ok(BetterF64::new(f64::from(gcd(a, c)) / f64::from(lcm(b, d))).unwrap()) + Ok(f64::from(gcd(a, c)) / f64::from(lcm(b, d))) } // hmmm impl Default for ModuloClass { fn default() -> Self { - Self { modulo: f64::EPSILON.try_into().unwrap(), offset: BetterF64::new(0.).unwrap() } + Self { modulo: f64::EPSILON, offset: 0. } } } @@ -154,9 +152,6 @@ mod tests { // TODO test negatives etc #[test] fn gcd() { - assert_eq!( - gcd_of_float(BetterF64::new(1. / 3.).unwrap(), BetterF64::new(3. / 2.).unwrap()), - Ok(BetterF64::new(0.16666666666666666).unwrap()) - ); + assert_eq!(gcd_of_float(1. / 3., 3. / 2.), Ok(0.16666666666666666)); } } diff --git a/checker/src/utilities/serialization.rs b/checker/src/utilities/serialization.rs index 60d6e8d7..1a0b2df3 100644 --- a/checker/src/utilities/serialization.rs +++ b/checker/src/utilities/serialization.rs @@ -233,13 +233,13 @@ impl BinarySerializable for TypeId { } } -impl BinarySerializable for ordered_float::NotNan { +impl BinarySerializable for f64 { fn serialize(self, buf: &mut Vec) { - buf.extend_from_slice(&self.into_inner().to_le_bytes()); + buf.extend_from_slice(&self.to_le_bytes()); } fn deserialize>(iter: &mut I, _source: SourceId) -> Self { - Self::new(f64::from_le_bytes([ + f64::from_le_bytes([ iter.next().unwrap(), iter.next().unwrap(), iter.next().unwrap(), @@ -248,8 +248,7 @@ impl BinarySerializable for ordered_float::NotNan { iter.next().unwrap(), iter.next().unwrap(), iter.next().unwrap(), - ])) - .unwrap() + ]) } } diff --git a/parser/README.md b/parser/README.md index 4a8227b3..455eb007 100644 --- a/parser/README.md +++ b/parser/README.md @@ -2,7 +2,7 @@ Contains "string to AST" parser, AST definitions, AST back to text/string form methods and hooks for traversing/visiting AST. Used in `ezno-checker` and the Ezno toolchain. -![parser lines of code](https://projects.kaleidawave.workers.dev/project/ezno-parser/badge) +![parser lines of code](https://kaleidawave-projectinformation.web.val.run/project/ezno-parser/badge) [![crates.io badge](https://img.shields.io/crates/v/ezno-parser?style=flat-square)](https://crates.io/crates/ezno-parser) [![docs.rs badge](https://img.shields.io/docsrs/ezno-parser?style=flat-square)](https://docs.rs/ezno-parser/latest) diff --git a/parser/examples/code_blocks_to_script.rs b/parser/examples/code_blocks_to_script.rs index 4abf44f4..a06c7c3d 100644 --- a/parser/examples/code_blocks_to_script.rs +++ b/parser/examples/code_blocks_to_script.rs @@ -34,7 +34,7 @@ fn main() -> Result<(), Box> { } }); - let content = std::fs::read_to_string(&path)?; + let content = std::fs::read_to_string(path)?; let filters: Vec<&str> = vec!["import", "export"]; @@ -52,7 +52,7 @@ fn main() -> Result<(), Box> { String::new(), |mut a, s| { a.push_str(s); - a.push_str("\n"); + a.push('\n'); a }, ); @@ -82,7 +82,7 @@ fn main() -> Result<(), Box> { let under = PathBuf::from(under); for (header, code) in blocks { let mut name = heading_to_rust_identifier(&header); - name.push_str("."); + name.push('.'); name.push_str(&extension); let mut file = std::fs::File::create(under.join(name))?; // Fix for FLow @@ -247,7 +247,7 @@ fn main() -> Result<(), Box> { } for line in code.lines() { block.push_str("\n\t"); - block.push_str(&line); + block.push_str(line); } // If the block is not terminated, it can change the parsing of the next one if block.ends_with(')') { @@ -262,7 +262,7 @@ fn main() -> Result<(), Box> { } for line in code.lines() { block.push_str("\n\t"); - block.push_str(&line); + block.push_str(line); } block.push('\n'); final_blocks.push((names, block)); diff --git a/parser/examples/duplicate_block.rs b/parser/examples/duplicate_block.rs index 21183a2f..11c4c645 100644 --- a/parser/examples/duplicate_block.rs +++ b/parser/examples/duplicate_block.rs @@ -3,7 +3,7 @@ use ezno_parser::{ visiting::{Chain, ImmutableVariableOrProperty, VisitOptions, Visitor, Visitors}, ASTNode, Declaration, Expression, Module, StatementOrDeclaration, VariableField, }; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; struct Offsets { pub offsets: Vec, @@ -16,7 +16,7 @@ struct Offsets { /// TODO abstract to library /// TODO do for funtions and types fn get_top_level_identifiers(m: &Module) -> (HashSet, HashSet) { - let (mut variables, mut types): (HashSet<_>, HashSet<_>) = Default::default(); + let (mut variables, types): (HashSet<_>, HashSet<_>) = Default::default(); for item in &m.items { match item { StatementOrDeclaration::Declaration(Declaration::Variable(variable)) => { @@ -98,7 +98,7 @@ let z = 6; total.reserve(rest.len() * (SIZE - 1)); for i in 1..SIZE { - let name = format!("{:03}", i); + let name = format!("{i:03}"); for offset in offsets.offsets.iter().copied() { let range = offset as usize..(offset as usize + 3); rest.replace_range(range, &name); @@ -107,7 +107,7 @@ let z = 6; total.push_str(&rest); } - eprintln!("{}", total); + eprintln!("{total}"); } /// TODO this could be collected in the same process as above diff --git a/parser/examples/jsx.rs b/parser/examples/jsx.rs index 3e4ceeb1..c1616a8b 100644 --- a/parser/examples/jsx.rs +++ b/parser/examples/jsx.rs @@ -1,4 +1,4 @@ -use ezno_parser::{ASTNode, JSXRoot, ToStringOptions}; +use ezno_parser::{jsx::JSXRoot, ASTNode, ToStringOptions}; fn main() { let source = "

My page content, wrapped in a layout!

"; diff --git a/parser/examples/lex.rs b/parser/examples/lex.rs index d4d0f9a7..3eb9f3d8 100644 --- a/parser/examples/lex.rs +++ b/parser/examples/lex.rs @@ -35,7 +35,7 @@ fn lex_and_print_tokens(script: String, print_tokens: bool, top_level_html: bool } } else { // Drain anyway - while let Some(_) = receiver.next() {} + while receiver.next().is_some() {} } // println!("{count} tokens"); diff --git a/parser/examples/parse.rs b/parser/examples/parse.rs index ccd5b852..9d7875b5 100644 --- a/parser/examples/parse.rs +++ b/parser/examples/parse.rs @@ -93,7 +93,7 @@ fn parse_path( eprintln!("parsing {:?} ({:?} bytes)", path.display(), source.len()); let now = Instant::now(); - let result = Module::from_string_with_options(source.clone(), parse_options.clone(), None); + let result = Module::from_string_with_options(source.clone(), *parse_options, None); match result { Ok((module, state)) => { @@ -127,13 +127,13 @@ fn parse_path( } if parse_imports { - for import in state.constant_imports.iter() { + for import in &state.constant_imports { // Don't reparse files (+ catches cycles) let resolved_path = path.parent().unwrap().join(import); if fs.get_paths().contains_key(&resolved_path) { continue; } - let _ = parse_path( + let () = parse_path( &resolved_path, timings, parse_imports, @@ -160,7 +160,7 @@ fn parse_path( line_column.column_start += 1; line_column.column_end += 1; } - eprintln!("error on {:?}", line_column); + eprintln!("error on {line_column:?}"); Err(Box::::from(parse_err)) } diff --git a/parser/fuzz/Cargo.lock b/parser/fuzz/Cargo.lock index 6c3c6df6..5380f8b7 100644 --- a/parser/fuzz/Cargo.lock +++ b/parser/fuzz/Cargo.lock @@ -1,21 +1,21 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -24,40 +24,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -74,19 +80,20 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "boa_ast" -version = "0.18.0" -source = "git+https://github.com/boa-dev/boa.git#1eaf9230ae52440a8785d2befb4e380983190f24" +version = "0.20.0" +source = "git+https://github.com/boa-dev/boa.git#db495fe708917645e7d632e5f59461645726cb19" dependencies = [ "arbitrary", - "bitflags 2.5.0", + "bitflags 2.8.0", "boa_interner", "boa_macros", + "boa_string", "indexmap", "num-bigint", "rustc-hash", @@ -94,8 +101,8 @@ dependencies = [ [[package]] name = "boa_gc" -version = "0.18.0" -source = "git+https://github.com/boa-dev/boa.git#1eaf9230ae52440a8785d2befb4e380983190f24" +version = "0.20.0" +source = "git+https://github.com/boa-dev/boa.git#db495fe708917645e7d632e5f59461645726cb19" dependencies = [ "boa_macros", "boa_profiler", @@ -104,8 +111,8 @@ dependencies = [ [[package]] name = "boa_interner" -version = "0.18.0" -source = "git+https://github.com/boa-dev/boa.git#1eaf9230ae52440a8785d2befb4e380983190f24" +version = "0.20.0" +source = "git+https://github.com/boa-dev/boa.git#db495fe708917645e7d632e5f59461645726cb19" dependencies = [ "arbitrary", "boa_gc", @@ -120,9 +127,10 @@ dependencies = [ [[package]] name = "boa_macros" -version = "0.18.0" -source = "git+https://github.com/boa-dev/boa.git#1eaf9230ae52440a8785d2befb4e380983190f24" +version = "0.20.0" +source = "git+https://github.com/boa-dev/boa.git#db495fe708917645e7d632e5f59461645726cb19" dependencies = [ + "cow-utils", "proc-macro2", "quote", "syn", @@ -131,30 +139,44 @@ dependencies = [ [[package]] name = "boa_profiler" -version = "0.18.0" -source = "git+https://github.com/boa-dev/boa.git#1eaf9230ae52440a8785d2befb4e380983190f24" +version = "0.20.0" +source = "git+https://github.com/boa-dev/boa.git#db495fe708917645e7d632e5f59461645726cb19" + +[[package]] +name = "boa_string" +version = "0.20.0" +source = "git+https://github.com/boa-dev/boa.git#db495fe708917645e7d632e5f59461645726cb19" +dependencies = [ + "fast-float2", + "itoa", + "paste", + "rustc-hash", + "ryu-js", + "sptr", + "static_assertions", +] [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytes" -version = "1.6.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "cc" -version = "1.0.99" +version = "1.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -185,9 +207,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cow-utils" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" [[package]] name = "derive-debug-extras" @@ -241,9 +269,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", @@ -258,9 +286,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", @@ -275,9 +303,9 @@ checksum = "4c91ae510829160d5cfb19eb4ae7b6e01d44b767ca8f727c6cee936e53cc9ae5" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -312,17 +340,17 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "ezno-parser" -version = "0.1.5" +version = "0.1.7" dependencies = [ "derive-debug-extras", "derive-enum-from-into", @@ -359,17 +387,23 @@ dependencies = [ [[package]] name = "ezno-parser-visitable-derive" -version = "0.0.7" +version = "0.0.9" dependencies = [ "string-cases", "syn-helpers", ] +[[package]] +name = "fast-float2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55" + [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fnv" @@ -377,6 +411,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "foreign-types" version = "0.3.2" @@ -403,42 +443,42 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", @@ -475,14 +515,26 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gloo-utils" @@ -518,11 +570,13 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ - "ahash", + "allocator-api2", + "equivalent", + "foldhash", ] [[package]] @@ -549,9 +603,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.3" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" +checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" [[package]] name = "httpdate" @@ -561,9 +615,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.29" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -667,9 +721,9 @@ checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] name = "icu_properties" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", @@ -716,21 +770,30 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "icu_normalizer", - "icu_properties", + "idna_adapter", "smallvec", "utf8_iter", ] +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" -version = "2.2.6" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", @@ -738,9 +801,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iterator-endiate" @@ -750,62 +813,62 @@ checksum = "cab947031a0a0cb37f982ef2a0ab3bacfd3de5ed97dd5c7e98bcc92bba357112" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libfuzzer-sys" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" dependencies = [ "arbitrary", "cc", - "once_cell", ] [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "log" -version = "0.4.21" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "macro_rules_attribute" @@ -837,29 +900,29 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", - "windows-sys 0.48.0", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" dependencies = [ "libc", "log", @@ -874,9 +937,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "arbitrary", "num-integer", @@ -903,26 +966,26 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.8.0", "cfg-if", "foreign-types", "libc", @@ -944,15 +1007,15 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", @@ -974,9 +1037,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -984,9 +1047,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", @@ -994,9 +1057,9 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", @@ -1007,18 +1070,18 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1028,15 +1091,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -1044,18 +1107,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -1123,21 +1186,21 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1149,28 +1212,40 @@ dependencies = [ "base64", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "ryu-js" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.8.0", "core-foundation", "core-foundation-sys", "libc", @@ -1179,9 +1254,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -1209,18 +1284,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -1240,11 +1315,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1261,11 +1337,17 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -1284,9 +1366,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1305,6 +1387,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1325,9 +1413,9 @@ checksum = "a31d23461f9e0fbe756cf9d5a36be93740fe12c8b094409a5f78f0f912ee2b6f" [[package]] name = "syn" -version = "2.0.66" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1386,14 +1474,16 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" dependencies = [ "cfg-if", "fastrand", + "getrandom 0.3.1", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1432,9 +1522,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.38.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -1442,7 +1532,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1457,9 +1547,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -1470,15 +1560,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", @@ -1486,9 +1576,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -1526,21 +1616,21 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "url" -version = "2.5.1" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -1567,9 +1657,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" @@ -1586,25 +1676,35 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -1613,21 +1713,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1635,9 +1736,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -1648,15 +1749,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -1664,11 +1768,11 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1686,7 +1790,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1706,18 +1819,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1728,9 +1841,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1740,9 +1853,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1752,15 +1865,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1770,9 +1883,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1782,9 +1895,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1794,9 +1907,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1806,9 +1919,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winreg" @@ -1820,6 +1933,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "write16" version = "1.0.0" @@ -1834,15 +1956,15 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -1852,9 +1974,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", @@ -1864,18 +1986,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", @@ -1884,18 +2006,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", @@ -1905,9 +2027,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", @@ -1916,9 +2038,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", diff --git a/parser/generator/Cargo.toml b/parser/generator/Cargo.toml index 3b5e1670..4c6c8f0a 100644 --- a/parser/generator/Cargo.toml +++ b/parser/generator/Cargo.toml @@ -14,12 +14,12 @@ path = "generator.rs" proc-macro = true [dependencies] -quote = "1.0" -proc-macro2 = "1.0" -self-rust-tokenize = "0.3.3" +quote = "1" +proc-macro2 = "1" +self-rust-tokenize = "0.3" ezno-parser = { path = "..", version = "0.1.7", features = [ "self-rust-tokenize", ] } [dev-dependencies] -pretty_assertions = "1.3.0" +pretty_assertions = "1.3" diff --git a/parser/src/block.rs b/parser/src/block.rs index e37b0f20..a7c0dc5d 100644 --- a/parser/src/block.rs +++ b/parser/src/block.rs @@ -84,7 +84,7 @@ impl ASTNode for StatementOrDeclaration { if let Some(Token(TSXToken::Keyword(TSXKeyword::Enum | TSXKeyword::Type), _)) = reader.peek() { - if reader.peek_n(1).map_or(false, |t| !t.0.is_symbol()) { + if reader.peek_n(1).is_some_and(|t| !t.0.is_symbol()) { return Ok(StatementOrDeclaration::Declaration(Declaration::from_reader( reader, state, options, )?)); diff --git a/parser/src/declarations/classes/class_member.rs b/parser/src/declarations/classes/class_member.rs index df95f620..ec6169b7 100644 --- a/parser/src/declarations/classes/class_member.rs +++ b/parser/src/declarations/classes/class_member.rs @@ -74,7 +74,7 @@ impl ASTNode for ClassMember { state: &mut crate::ParsingState, options: &ParseOptions, ) -> ParseResult { - if reader.peek().map_or(false, |t| t.0.is_comment()) { + if reader.peek().is_some_and(|t| t.0.is_comment()) { let (comment, is_multiline, span) = TSXToken::try_into_comment(reader.next().unwrap()).unwrap(); return Ok(Self::Comment(comment, is_multiline, span)); diff --git a/parser/src/declarations/export.rs b/parser/src/declarations/export.rs index 0adbdd40..ebc9bc11 100644 --- a/parser/src/declarations/export.rs +++ b/parser/src/declarations/export.rs @@ -77,8 +77,7 @@ impl ASTNode for ExportDeclaration { Token(TSXToken::Keyword(TSXKeyword::Default), _) => { reader.next(); if options.type_definition_module - && reader.peek().map_or( - false, + && reader.peek().is_some_and( |t| matches!(t.0, TSXToken::Keyword(kw) if kw.is_in_function_header()), ) { let is_async = reader diff --git a/parser/src/errors.rs b/parser/src/errors.rs index f8585d6b..5214b34f 100644 --- a/parser/src/errors.rs +++ b/parser/src/errors.rs @@ -37,7 +37,7 @@ pub enum ParseErrors<'a> { InvalidLHSOfIs, } -impl<'a> Display for ParseErrors<'a> { +impl Display for ParseErrors<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParseErrors::UnexpectedToken { expected, found } => { @@ -244,7 +244,7 @@ pub(crate) fn parse_lexing_error() -> ParseError { pub trait ParserErrorReason: Display {} -impl<'a> ParserErrorReason for ParseErrors<'a> {} +impl ParserErrorReason for ParseErrors<'_> {} impl ParserErrorReason for LexingErrors {} /// A error for not parsing diff --git a/parser/src/expressions/mod.rs b/parser/src/expressions/mod.rs index de79368b..cb1bf37c 100644 --- a/parser/src/expressions/mod.rs +++ b/parser/src/expressions/mod.rs @@ -18,8 +18,8 @@ use self::{ }; use super::{ - tokens::token_as_identifier, ASTNode, Block, FunctionBase, JSXRoot, ParseError, ParseOptions, - Span, TSXToken, Token, TokenReader, TypeAnnotation, + jsx::JSXRoot, tokens::token_as_identifier, ASTNode, Block, FunctionBase, ParseError, + ParseOptions, Span, TSXToken, Token, TokenReader, TypeAnnotation, }; #[cfg(feature = "extras")] @@ -234,7 +234,7 @@ impl Expression { ) -> ParseResult { if let (true, Some(Token(peek, at))) = (options.partial_syntax, reader.peek()) { let next_is_not_expression_like = peek.is_expression_delimiter() - || start.map_or(false, |start| { + || start.is_some_and(|start| { peek.is_statement_or_declaration_start() && state .line_starts @@ -1781,7 +1781,7 @@ impl Expression { dynamic_part.to_string_from_buffer(buf, options, local); buf.push('}'); } - buf.push_str_contains_new_line(template_literal.last.as_str()); + buf.push_str_contains_new_line(template_literal.final_part.as_str()); buf.push('`'); } Self::ConditionalTernary { condition, truthy_result, falsy_result, .. } => { @@ -1861,8 +1861,7 @@ fn function_header_ish( ) -> bool { kw.is_in_function_header() || (kw.is_special_function_header() - && reader.peek().map_or( - false, + && reader.peek().is_some_and( |Token(t, _)| matches!(t, TSXToken::Keyword(kw) if kw.is_in_function_header()), )) } diff --git a/parser/src/expressions/object_literal.rs b/parser/src/expressions/object_literal.rs index 3e4652c5..2cbdeb0f 100644 --- a/parser/src/expressions/object_literal.rs +++ b/parser/src/expressions/object_literal.rs @@ -208,7 +208,7 @@ impl ASTNode for ObjectLiteralMember { state: &mut crate::ParsingState, options: &ParseOptions, ) -> ParseResult { - if reader.peek().map_or(false, |t| t.0.is_comment()) { + if reader.peek().is_some_and(|t| t.0.is_comment()) { let (comment, is_multiline, span) = TSXToken::try_into_comment(reader.next().unwrap()).unwrap(); return Ok(Self::Comment(comment, is_multiline, span)); diff --git a/parser/src/expressions/operators.rs b/parser/src/expressions/operators.rs index 0e6b0a74..a6e7fc2c 100644 --- a/parser/src/expressions/operators.rs +++ b/parser/src/expressions/operators.rs @@ -14,7 +14,7 @@ use crate::{derive_ASTNode, TSXKeyword, TSXToken}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[apply(derive_ASTNode!)] pub enum BinaryOperator { - Add, Subtract, Multiply, Divide, Modulo, Exponent, + Add, Subtract, Multiply, Divide, Remainder, Exponent, BitwiseShiftLeft, BitwiseShiftRight, BitwiseShiftRightUnsigned, BitwiseAnd, BitwiseXOr, BitwiseOr, @@ -44,7 +44,7 @@ impl BinaryOperator { pub enum BinaryAssignmentOperator { LogicalNullishAssignment, - AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, ModuloAssign, ExponentAssign, + AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, RemainderAssign, ExponentAssign, LogicalAndAssign, LogicalOrAssign, BitwiseShiftLeftAssign, BitwiseShiftRightAssign, BitwiseShiftRightUnsigned, BitwiseAndAssign, BitwiseXOrAssign, BitwiseOrAssign, @@ -130,7 +130,7 @@ impl Operator for BinaryOperator { BinaryOperator::StrictEqual => "===", BinaryOperator::NotEqual => "!=", BinaryOperator::StrictNotEqual => "!==", - BinaryOperator::Modulo => "%", + BinaryOperator::Remainder => "%", BinaryOperator::NullCoalescing => "??", BinaryOperator::LogicalAnd => "&&", BinaryOperator::LogicalOr => "||", @@ -149,7 +149,7 @@ impl Operator for BinaryOperator { match self { BinaryOperator::Pipe | BinaryOperator::Compose => 15, BinaryOperator::Exponent => 14, - BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Modulo => 13, + BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Remainder => 13, BinaryOperator::Add | BinaryOperator::Subtract => 12, BinaryOperator::BitwiseShiftLeft | BinaryOperator::BitwiseShiftRightUnsigned @@ -230,7 +230,7 @@ impl Operator for BinaryAssignmentOperator { BinaryAssignmentOperator::SubtractAssign => "-=", BinaryAssignmentOperator::MultiplyAssign => "*=", BinaryAssignmentOperator::DivideAssign => "/=", - BinaryAssignmentOperator::ModuloAssign => "%=", + BinaryAssignmentOperator::RemainderAssign => "%=", BinaryAssignmentOperator::ExponentAssign => "**=", BinaryAssignmentOperator::BitwiseShiftLeftAssign => "<<=", BinaryAssignmentOperator::BitwiseShiftRightAssign => ">>=", @@ -313,7 +313,7 @@ impl From for BinaryOperator { BinaryAssignmentOperator::SubtractAssign => BinaryOperator::Subtract, BinaryAssignmentOperator::MultiplyAssign => BinaryOperator::Multiply, BinaryAssignmentOperator::DivideAssign => BinaryOperator::Divide, - BinaryAssignmentOperator::ModuloAssign => BinaryOperator::Modulo, + BinaryAssignmentOperator::RemainderAssign => BinaryOperator::Remainder, BinaryAssignmentOperator::ExponentAssign => BinaryOperator::Exponent, BinaryAssignmentOperator::LogicalAndAssign => BinaryOperator::LogicalAnd, BinaryAssignmentOperator::LogicalOrAssign => BinaryOperator::LogicalOr, @@ -371,7 +371,7 @@ impl TryFrom<&TSXToken> for BinaryOperator { TSXToken::Multiply => Ok(BinaryOperator::Multiply), TSXToken::Divide => Ok(BinaryOperator::Divide), TSXToken::Exponent => Ok(BinaryOperator::Exponent), - TSXToken::Modulo => Ok(BinaryOperator::Modulo), + TSXToken::Remainder => Ok(BinaryOperator::Remainder), TSXToken::Equal => Ok(BinaryOperator::Equal), TSXToken::NotEqual => Ok(BinaryOperator::NotEqual), TSXToken::StrictEqual => Ok(BinaryOperator::StrictEqual), diff --git a/parser/src/expressions/template_literal.rs b/parser/src/expressions/template_literal.rs index e9a1f08f..9ed08f54 100644 --- a/parser/src/expressions/template_literal.rs +++ b/parser/src/expressions/template_literal.rs @@ -12,7 +12,7 @@ use visitable_derive::Visitable; pub struct TemplateLiteral { pub tag: Option>, pub parts: Vec<(String, MultipleExpression)>, - pub last: String, + pub final_part: String, pub position: Span, } @@ -47,7 +47,7 @@ impl ASTNode for TemplateLiteral { dynamic_part.to_string_from_buffer(buf, options, local); buf.push('}'); } - buf.push_str_contains_new_line(self.last.as_str()); + buf.push_str_contains_new_line(self.final_part.as_str()); buf.push('`'); } } @@ -73,7 +73,12 @@ impl TemplateLiteral { reader.expect_next(TSXToken::TemplateLiteralExpressionEnd)?; } t @ Token(TSXToken::TemplateLiteralEnd, _) => { - return Ok(Self { parts, last, tag, position: start.union(t.get_end()) }); + return Ok(Self { + parts, + final_part: last, + tag, + position: start.union(t.get_end()), + }); } Token(TSXToken::EOS, _) => return Err(parse_lexing_error()), t => unreachable!("Token {:?}", t), diff --git a/parser/src/generator_helpers.rs b/parser/src/generator_helpers.rs index 0449bfd4..de63519a 100644 --- a/parser/src/generator_helpers.rs +++ b/parser/src/generator_helpers.rs @@ -19,13 +19,13 @@ impl<'a> From<&'a str> for Ident<'a> { } } -impl<'a> IntoAST for Ident<'a> { +impl IntoAST for Ident<'_> { fn into_ast(self) -> Expression { Expression::VariableReference(self.0.to_owned(), source_map::Nullable::NULL) } } -impl<'a> IntoAST for &'a str { +impl IntoAST for &str { fn into_ast(self) -> Expression { Expression::StringLiteral( self.to_owned(), @@ -35,13 +35,13 @@ impl<'a> IntoAST for &'a str { } } -impl<'a> IntoAST for &'a str { +impl IntoAST for &str { fn into_ast(self) -> PropertyReference { PropertyReference::Standard { property: self.to_owned(), is_private: false } } } -impl<'a> IntoAST for &'a str { +impl IntoAST for &str { fn into_ast(self) -> VariableIdentifier { VariableIdentifier::Standard(self.to_owned(), source_map::Nullable::NULL) } diff --git a/parser/src/lexer.rs b/parser/src/lexer.rs index e6d68467..c3708b45 100644 --- a/parser/src/lexer.rs +++ b/parser/src/lexer.rs @@ -6,8 +6,9 @@ use super::{Span, TSXToken}; use crate::{ - errors::LexingErrors, html_tag_contains_literal_content, html_tag_is_self_closing, Comments, - Quoted, + errors::LexingErrors, + jsx::{html_tag_contains_literal_content, html_tag_is_self_closing}, + Comments, Quoted, }; use tokenizer_lib::{sized_tokens::TokenStart, Token, TokenSender}; diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 93633225..0988e261 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -17,6 +17,7 @@ pub mod number; pub mod options; pub mod property_key; pub mod statements; +pub mod strings; mod tokens; pub mod types; mod variable_fields; @@ -32,8 +33,7 @@ pub use errors::{ParseError, ParseErrors, ParseResult}; pub use expressions::{Expression, PropertyReference}; pub use extensions::{ decorators::{Decorated, Decorator}, - is_expression, - jsx::*, + is_expression, jsx, }; pub use functions::{FunctionBase, FunctionBased, FunctionHeader}; pub use generator_helpers::IntoAST; @@ -44,6 +44,7 @@ pub use options::*; pub use property_key::PropertyKey; pub use source_map::{self, SourceId, Span}; pub use statements::Statement; +pub use strings::Quoted; pub use tokens::{TSXKeyword, TSXToken}; pub use types::{ type_annotations::{self, TypeAnnotation}, @@ -75,23 +76,6 @@ attribute_alias! { #[cfg_attr(target_family = "wasm", derive(tsify::Tsify))]; } -/// What surrounds a string -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -#[apply(derive_ASTNode!)] -pub enum Quoted { - Single, - Double, -} - -impl Quoted { - fn as_char(self) -> char { - match self { - Quoted::Single => '\'', - Quoted::Double => '"', - } - } -} - #[derive(Debug, Clone, Copy)] pub struct LocalToStringInformation { under: SourceId, diff --git a/parser/src/property_key.rs b/parser/src/property_key.rs index 945300c7..161923f1 100644 --- a/parser/src/property_key.rs +++ b/parser/src/property_key.rs @@ -31,7 +31,7 @@ pub trait PropertyKeyKind: Debug + PartialEq + Eq + Clone + Sized + Send + Sync pub struct AlwaysPublic; // #[cfg_attr(target_family = "wasm", wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section))] -#[allow(dead_code)] +// #[allow(dead_code)] // const TYPES_ALWAYS_PUBLIC: &str = r" // export type AlwaysPublic = false; // "; @@ -62,7 +62,7 @@ pub enum PublicOrPrivate { } // #[cfg_attr(target_family = "wasm", wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section))] -#[allow(dead_code)] +// #[allow(dead_code)] // const TYPES_PUBLIC_OR_PRIVATE: &str = r" // export type PublicOrPrivate = boolean; // "; diff --git a/parser/src/strings.rs b/parser/src/strings.rs new file mode 100644 index 00000000..d8063181 --- /dev/null +++ b/parser/src/strings.rs @@ -0,0 +1,74 @@ +use crate::derive_ASTNode; +use std::borrow::Cow; + +/// What surrounds a string +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +#[apply(derive_ASTNode!)] +pub enum Quoted { + Single, + Double, +} + +impl Quoted { + #[must_use] + pub fn as_char(self) -> char { + match self { + Quoted::Single => '\'', + Quoted::Double => '"', + } + } +} + +/// Modified version of +#[must_use] +pub fn unescape_string_content(on: &str) -> Cow<'_, str> { + let mut result = Cow::Borrowed(""); + let mut start = 0; + for (index, _matched) in on.match_indices('\\') { + result += &on[start..index]; + start = index + 1; + } + + result += &on[start..]; + result +} + +/// Also for template literals +/// Modified version of +#[must_use] +pub fn escape_string_content(on: &str, string_delimeter: char) -> Cow<'_, str> { + let mut result = Cow::Borrowed(""); + let mut start = 0; + let to_escape: &[char] = match string_delimeter { + '"' => &['\\', '"'], + '\'' => &['\\', '\''], + '`' => &['\\', '`', '$'], + _ => panic!("Unknown string delimeter {string_delimeter:?}"), + }; + for (index, matched) in on.match_indices(to_escape) { + result += &on[start..index]; + result += "\\"; + result += matched; + start = index + 1; + } + + result += &on[start..]; + result +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn unescape() { + assert_eq!(unescape_string_content("Hi \\\"Ben\\\""), "Hi \"Ben\""); + assert_eq!(unescape_string_content("Hello\\`"), "Hello`"); + } + + #[test] + fn escape() { + assert_eq!(escape_string_content("Hi \"Ben\"", '"'), "Hi \\\"Ben\\\""); + assert_eq!(escape_string_content("Hi ${Ben} `", '`'), "Hi \\${Ben} \\`"); + } +} diff --git a/parser/src/tokens.rs b/parser/src/tokens.rs index 1cedf7ed..5120e731 100644 --- a/parser/src/tokens.rs +++ b/parser/src/tokens.rs @@ -1,3 +1,5 @@ +#![allow(non_local_definitions)] + //! Contains the declaration for [`TSXToken`] which are pieces of syntax. Also //! - How tokens are made from consecutive characters //! - Keywords @@ -38,8 +40,8 @@ use crate::{ParseError, Quoted}; "//" => TSXToken::Comment(String::new()), "/=" => TSXToken::DivideAssign, "/*" => TSXToken::MultiLineComment(String::new()), - "%" => TSXToken::Modulo, - "%=" => TSXToken::ModuloAssign, + "%" => TSXToken::Remainder, + "%=" => TSXToken::RemainderAssign, "=" => TSXToken::Assign, "==" => TSXToken::Equal, "===" => TSXToken::StrictEqual, @@ -121,8 +123,8 @@ pub enum TSXToken { /// `>` CloseChevron, Add, Subtract, Multiply, Divide, - QuestionMark, Exponent, Modulo, - AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, ExponentAssign, ModuloAssign, + QuestionMark, Exponent, Remainder, + AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, ExponentAssign, RemainderAssign, Increment, Decrement, BitwiseShiftLeft, BitwiseShiftRight, BitwiseShiftRightUnsigned, BitwiseShiftLeftAssign, BitwiseShiftRightAssign, BitwiseShiftRightUnsignedAssign, @@ -218,7 +220,7 @@ impl tokenizer_lib::sized_tokens::SizedToken for TSXToken { | TSXToken::Subtract | TSXToken::Multiply | TSXToken::Divide - | TSXToken::Modulo + | TSXToken::Remainder | TSXToken::QuestionMark | TSXToken::BitwiseOr | TSXToken::BitwiseXOr @@ -241,7 +243,7 @@ impl tokenizer_lib::sized_tokens::SizedToken for TSXToken { | TSXToken::SubtractAssign | TSXToken::MultiplyAssign | TSXToken::DivideAssign - | TSXToken::ModuloAssign + | TSXToken::RemainderAssign | TSXToken::Exponent | TSXToken::ExponentAssign | TSXToken::Increment @@ -514,7 +516,7 @@ impl TSXToken { | TSXToken::AddAssign | TSXToken::SubtractAssign | TSXToken::DivideAssign - | TSXToken::ModuloAssign + | TSXToken::RemainderAssign | TSXToken::BitwiseOrAssign | TSXToken::BitwiseAndAssign | TSXToken::LogicalOrAssign diff --git a/parser/src/types/type_annotations.rs b/parser/src/types/type_annotations.rs index 68009ab0..2d2b3fbc 100644 --- a/parser/src/types/type_annotations.rs +++ b/parser/src/types/type_annotations.rs @@ -69,7 +69,7 @@ pub enum TypeAnnotation { /// ? TemplateLiteral { parts: Vec<(String, AnnotationWithBinder)>, - last: String, + final_part: String, position: Span, }, /// Declares type as not assignable (still has interior mutability) e.g. `readonly number` @@ -410,7 +410,7 @@ impl ASTNode for TypeAnnotation { reference.to_string_from_buffer(buf, options, local); buf.push(')'); } - Self::TemplateLiteral { parts, last, .. } => { + Self::TemplateLiteral { parts, final_part, .. } => { buf.push('`'); for (static_part, dynamic_part) in parts { buf.push_str_contains_new_line(static_part.as_str()); @@ -419,7 +419,7 @@ impl ASTNode for TypeAnnotation { dynamic_part.to_string_from_buffer(buf, options, local); buf.push('}'); } - buf.push_str_contains_new_line(last.as_str()); + buf.push_str_contains_new_line(final_part.as_str()); buf.push('`'); } Self::Symbol { unique, .. } => { @@ -482,7 +482,7 @@ impl TypeAnnotation { | TSXToken::Comma | TSXToken::OpenChevron ) || peek.is_assignment() - || (start.map_or(false, |start| { + || (start.is_some_and(|start| { peek.is_statement_or_declaration_start() && state .line_starts @@ -737,7 +737,11 @@ impl TypeAnnotation { t => unreachable!("Token {:?}", t), } } - Self::TemplateLiteral { parts, last, position: start.union(end.unwrap()) } + Self::TemplateLiteral { + parts, + final_part: last, + position: start.union(end.unwrap()), + } } Token(TSXToken::Keyword(TSXKeyword::Readonly), start) => { let readonly_type = TypeAnnotation::from_reader_with_config( @@ -1131,7 +1135,7 @@ impl TypeAnnotationFunctionParameters { let mut parameters = Vec::new(); let mut rest_parameter = None; while !matches!(reader.peek(), Some(Token(TSXToken::CloseParentheses, _))) { - while reader.peek().map_or(false, |Token(ty, _)| ty.is_comment()) { + while reader.peek().is_some_and(|Token(ty, _)| ty.is_comment()) { reader.next(); } let mut decorators = Vec::::new(); diff --git a/parser/tests/comments.rs b/parser/tests/comments.rs index e90400b6..b714b897 100644 --- a/parser/tests/comments.rs +++ b/parser/tests/comments.rs @@ -2,9 +2,9 @@ use ezno_parser::{ASTNode, Module}; #[test] fn random_comments() { - let input = r#" + let input = r" const [,,/* hi */] = []; -"# +" .trim_start() .replace(" ", "\t"); diff --git a/parser/tests/expressions.rs b/parser/tests/expressions.rs index 8fe2a0d2..78565f5f 100644 --- a/parser/tests/expressions.rs +++ b/parser/tests/expressions.rs @@ -155,11 +155,11 @@ function Component(item) { #[test] fn regex_and_leading_decimal() { - let input = r#" + let input = r" for (const x in 0.4) {} for await (const [a] of 0.2) {} for (const result of /thing/) {} -"# +" .trim(); let module = Module::from_string(input.to_owned(), Default::default()).unwrap(); @@ -172,9 +172,9 @@ for (const result of /thing/) {} #[test] fn class_and_object_divides() { - let input = r#" + let input = r" const b = class Number {} / 2 -"# +" .trim(); let module = Module::from_string(input.to_owned(), Default::default()).unwrap(); diff --git a/parser/tests/partial.rs b/parser/tests/partial.rs index 26b3a8a8..7c9ada76 100644 --- a/parser/tests/partial.rs +++ b/parser/tests/partial.rs @@ -3,11 +3,11 @@ use pretty_assertions::assert_eq; #[test] fn declarations() { - let input = r#" + let input = r" const x = ; const y = const z = 2 -"# +" .trim_start() .replace(" ", "\t"); @@ -32,10 +32,10 @@ const z = 2 #[test] fn in_statements() { - let input = r#" + let input = r" if () { return 2 -}"# +}" .trim_start() .replace(" ", "\t"); @@ -60,11 +60,11 @@ if () { #[test] fn type_annotations() { // Can't do return type annotation because conflicts with object type - let input = r#" + let input = r" const x: = 5; function y(c: ) { return 2 -}"# +}" .trim_start() .replace(" ", "\t"); @@ -91,7 +91,7 @@ function y(c: ) { fn invalid_syntax() { let sources = [("", true), ("][", false), ("{}}", false)]; - for (source, is_okay) in sources.into_iter() { + for (source, is_okay) in sources { let result = Module::from_string( source.to_owned(), ParseOptions { partial_syntax: true, ..Default::default() }, diff --git a/parser/tests/type_annotations.rs b/parser/tests/type_annotations.rs index 0dfd1d30..8c46e18d 100644 --- a/parser/tests/type_annotations.rs +++ b/parser/tests/type_annotations.rs @@ -3,7 +3,7 @@ use pretty_assertions::assert_eq; #[test] fn statements() { - let input = r#" + let input = r" interface X {} interface Y extends number, Z2 {} type Z1 = 2; @@ -13,7 +13,7 @@ type Z4> = T; type Z5 = this; type Z6 = typeof x.something; type Z7 = X[Y] -"# +" .trim() .to_owned(); @@ -31,11 +31,11 @@ type Z7 = X[Y] #[test] fn variable_parameter_and_return() { - let input = r#" + let input = r" const x: number = 2; function y(a: string): string { return a -}"# +}" .trim_start() .replace(" ", "\t"); @@ -56,12 +56,12 @@ function y(a: string): string { #[cfg(feature = "full-typescript")] fn expression_level_expressions() { // 👎👎👎 - let input = r#" + let input = r" (a satisfies number); (b as number); ({ 1: 2 } as const); (a! + 2) -"# +" .trim() .replace(" ", "\t"); @@ -81,7 +81,7 @@ fn expression_level_expressions() { #[cfg(feature = "full-typescript")] fn function_and_method_overloading() { // use generics and redesign your bad APIs sheeple - let input = r#" + let input = r" function makeDate(timestamp: number): Date function makeDate(m: number, d: number, y: number): Date function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {} @@ -92,7 +92,7 @@ class X { makeDate(m: number, d: number, y: number): Date makeDate(mOrTimestamp: number, d?: number, y?: number): Date {} } -"# +" .trim() .replace(" ", "\t"); @@ -110,9 +110,9 @@ class X { #[test] fn type_definition_module() { - let input = r#" + let input = r" export default function (a: string): string -"# +" .trim() .replace(" ", "\t"); @@ -126,11 +126,11 @@ export default function (a: string): string #[test] fn mapped_type() { - let input = r#" + let input = r" type Record = { [P in T]: V }; type Something = { [P in T as `get${P}`]: V }; type Something = { [P in keyof T]: V } -"# +" .trim(); let parse_options = ParseOptions { type_definition_module: true, ..Default::default() }; @@ -145,11 +145,11 @@ type Something = { [P in keyof T]: V } #[test] #[ignore] fn jsx_nuances() { - let input = r#" + let input = r" function x(a: (a: number, b: T) => T) {} type B = T ? string : (a: number, b: U) => T; -"# +" .trim(); let parse_options = ParseOptions { jsx: true, ..Default::default() }; diff --git a/parser/visitable-derive/README.md b/parser/visitable-derive/README.md index 770429a6..4ba6352d 100644 --- a/parser/visitable-derive/README.md +++ b/parser/visitable-derive/README.md @@ -1,4 +1,4 @@ -![visiting-proc-macro lines of code](https://projects.kaleidawave.workers.dev/project/ezno-parser-visitable-derive/badge) + A package which generates mutable and immutable *visiting* implementations for AST nodes. diff --git a/src/ast_explorer.rs b/src/ast_explorer.rs index d8fd7b8a..a29af511 100644 --- a/src/ast_explorer.rs +++ b/src/ast_explorer.rs @@ -36,13 +36,13 @@ impl ExplorerArguments { eprintln!("Could not find file at {}", file.display()); } } else { - print_to_cli(format_args!("ezno ast-explorer\nUse #exit to leave. Also #switch-mode *mode name* and #load-file *path*")); + print_to_cli(format_args!("ezno ast-explorer\nUse #exist, .exit or close() to leave. Also #switch-mode *mode name* and #load-file *path*")); loop { let input = crate::utilities::cli_input_resolver(self.nested.to_str()); if input.is_empty() { continue; - } else if input.trim() == "#exit" { + } else if let "#exit" | ".exit" | "close()" = input.trim() { break; } else if let Some(new_mode) = input.strip_prefix("#switch-mode ") { self.nested = match ExplorerSubCommand::from_str(new_mode.trim()) { diff --git a/src/build.rs b/src/build.rs index e2b4fcb0..1f8e1223 100644 --- a/src/build.rs +++ b/src/build.rs @@ -182,7 +182,6 @@ mod tests { use super::*; #[test] - #[ignore = "not fixed implemented"] fn tree_shaking() { let source = r#" function make_observable(obj) { @@ -210,16 +209,25 @@ mod tests { let config = BuildConfig { tree_shake: true, ..Default::default() }; - if let Ok(output) = build( + let build_result = build( vec!["index.tsx".into()], &|_path: &std::path::Path| Some(source.to_owned()), config, - ) { - let first_source = &output.artifacts[0].content; - // TODO assert output equal - panic!("{first_source:?}"); - } else { - panic!("build failed") + ); + + match build_result { + Ok(output) => { + let first_source = &output.artifacts[0].content; + let expectation = "function make_observable(obj){return new Proxy(obj,{get(on,prop,_rec){return on[prop]}})}function get_a(){return 1};const obj={a(){return get_a()},b:null,c:2};const value=make_observable(obj);const a_value=value.a();const c_value=value.c"; + + pretty_assertions::assert_eq!(first_source, expectation); + } + Err(output) => { + panic!( + "build failed:\n{diagnostics:#?}", + diagnostics = output.0.diagnostics.get_diagnostics() + ); + } } } } diff --git a/src/cli.rs b/src/cli.rs index fbdd1de4..6eedea99 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,12 +1,4 @@ -#[allow(unused)] -use std::{ - collections::HashSet, - env, fs, - path::{Path, PathBuf}, - process::Command, - process::ExitCode, - time::{Duration, Instant}, -}; +use std::{env, fs, path::PathBuf, process::ExitCode, time::Duration}; use crate::{ build::{build, BuildConfig, BuildOutput, FailedBuildOutput}, @@ -56,7 +48,7 @@ pub(crate) struct ExperimentalArguments { pub(crate) enum ExperimentalSubcommand { Build(BuildArguments), Format(FormatArguments), - #[cfg(not(target_family = "wasm"))] + #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] Upgrade(UpgradeArguments), } @@ -164,18 +156,6 @@ pub(crate) struct UpgradeArguments {} // watch: bool, // } -#[allow(unused)] -fn file_system_resolver(path: &Path) -> Option { - // Cheaty - if path.to_str() == Some("BLANK") { - return Some(String::new()); - } - match fs::read_to_string(path) { - Ok(source) => Some(source), - Err(_) => None, - } -} - fn run_checker( entry_points: Vec, read_file: &T, @@ -195,10 +175,7 @@ fn run_checker( let result = if diagnostics.contains_error() { if let MaxDiagnostics::FixedTo(0) = max_diagnostics { let count = diagnostics.into_iter().count(); - print_to_cli(format_args!( - "Found {count} type errors and warnings {}", - console::Emoji(" 😬", ":/") - )) + print_to_cli(format_args!("Found {count} type errors and warnings",)) } else { report_diagnostics_to_cli( diagnostics, @@ -218,7 +195,7 @@ fn run_checker( max_diagnostics, ) .unwrap(); - print_to_cli(format_args!("No type errors found {}", console::Emoji("🎉", ":)"))); + print_to_cli(format_args!("No type errors found 🎉")); ExitCode::SUCCESS }; @@ -293,7 +270,6 @@ pub fn run_cli( #[cfg(not(target_family = "wasm"))] { - use notify::Watcher; use notify_debouncer_full::new_debouncer; let (tx, rx) = std::sync::mpsc::channel(); @@ -301,7 +277,7 @@ pub fn run_cli( new_debouncer(Duration::from_millis(200), None, tx).unwrap(); for e in &entry_points { - debouncer.watcher().watch(e, notify::RecursiveMode::Recursive).unwrap(); + debouncer.watch(e, notify::RecursiveMode::Recursive).unwrap(); } let _ = run_checker( @@ -396,10 +372,7 @@ pub fn run_cli( build_config.max_diagnostics, ) .unwrap(); - print_to_cli(format_args!( - "Project built successfully {}", - console::Emoji("🎉", ":)") - )); + print_to_cli(format_args!("Project built successfully 🎉",)); ExitCode::SUCCESS } Err(FailedBuildOutput(CheckOutput { module_contents, diagnostics, .. })) => { diff --git a/src/js-cli-and-library/src/cli.js b/src/js-cli-and-library/src/cli.js index d0f620b5..dea3bf66 100644 --- a/src/js-cli-and-library/src/cli.js +++ b/src/js-cli-and-library/src/cli.js @@ -2,14 +2,14 @@ import { initSync, run_cli, parse_module, ReplSystem } from "../build/ezno_lib.js"; import { readFileSync, writeFileSync } from "node:fs"; -import * as readline from 'node:readline/promises'; import { stdin as input, stdout as output } from 'node:process'; +import * as readline from 'node:readline/promises'; const wasmPath = new URL("./shared/ezno_lib_bg.wasm", import.meta.url); if (wasmPath.protocol === "https:") { - initSync(await fetch(wasmPath).then(response => response.arrayBuffer())) + initSync({ module: await fetch(wasmPath).then(response => response.arrayBuffer()) }); } else { - initSync(readFileSync(wasmPath)); + initSync({ module: readFileSync(wasmPath) }); } const onDeno = typeof Deno !== "undefined"; diff --git a/src/repl.rs b/src/repl.rs index 316bb9f1..c80f3900 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -165,7 +165,7 @@ pub(crate) fn run_repl(_arguments: ReplArguments) { pub(crate) fn run_repl(arguments: ReplArguments) { use crate::utilities::print_to_cli; - print_to_cli(format_args!("Entering Repl. Exit with `close()`")); + print_to_cli(format_args!("Entering REPL\n.Use #exist, .exit or close() to leave")); let mut system = match ReplSystem::new(arguments, crate::utilities::FSFunction) { Ok(system) => system, @@ -185,7 +185,7 @@ pub(crate) fn run_repl(arguments: ReplArguments) { let input = crate::utilities::cli_input_resolver(""); if input.is_empty() { continue; - } else if input.trim() == "close()" { + } else if let "#exit" | ".exit" | "close()" = input.trim() { break; } system.execute_statement(input) diff --git a/src/utilities.rs b/src/utilities.rs index 69889bce..55d00755 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -82,10 +82,13 @@ pub(crate) fn print_to_cli(arguments: Arguments) { #[cfg(not(target_family = "wasm"))] pub(crate) fn print_to_cli(arguments: Arguments) { - use std::io; + use std::io::{self, Write}; + let stdout = io::stdout(); + let mut stdout = stdout.lock(); - println!("{arguments}"); - io::Write::flush(&mut io::stdout()).unwrap(); + // Ignore errors here for now + let _ = writeln!(stdout, "{arguments}"); + let _ = Write::flush(&mut stdout); } #[derive(Debug, Copy, Clone)] @@ -141,8 +144,7 @@ impl checker::ReadFromFS for FSFunction { } // yes i implemented it only using `native_tls`... -// TODO or(..., debug_assertions) -#[cfg(not(target_family = "wasm"))] +#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] pub(crate) fn upgrade_self() -> Result> { use native_tls::{TlsConnector, TlsStream}; use std::io::{BufRead, BufReader, BufWriter, Read, Write}; @@ -160,11 +162,16 @@ pub(crate) fn upgrade_self() -> Result> { "GET {path} HTTP/1.1\r\n\ Host: {root}\r\n\ Connection: close\r\n\ - User-Agent: ezno-self-update\r\n\ - \r\n" + User-Agent: ezno-self-update\r\n" ); tls_stream.write_all(request.as_bytes())?; + if let "api.github.com" = path { + tls_stream.write_all( + b"Accept: application/vnd.github+json\r\nX-GitHub-Api-Version: 2022-11-28\r\n", + )?; + } + tls_stream.write_all(b"\r\n")?; Ok(tls_stream) } @@ -197,23 +204,28 @@ pub(crate) fn upgrade_self() -> Result> { let mut version_name = None; // Name comes before assets so okay here on exit signal - let result = parse_with_exit_signal(body, |keys, value| { - if let [JSONKey::Slice("name")] = keys { - if let RootJSONValue::String(s) = value { - version_name = Some(s.to_owned()); - } - } else if let [JSONKey::Slice("assets"), JSONKey::Index(_), JSONKey::Slice("browser_download_url")] = - keys - { - if let RootJSONValue::String(s) = value { - if s.ends_with(EXPECTED_END) { - required_binary = Some(s.to_owned()); - return true; + let result = parse_with_exit_signal( + body, + |keys, value| { + if let [JSONKey::Slice("name")] = keys { + if let RootJSONValue::String(s) = value { + version_name = Some(s.to_owned()); + } + } else if let [JSONKey::Slice("assets"), JSONKey::Index(_), JSONKey::Slice("browser_download_url")] = + keys + { + if let RootJSONValue::String(s) = value { + if s.ends_with(EXPECTED_END) { + required_binary = Some(s.to_owned()); + return true; + } } } - } - false - }); + false + }, + false, + false, + ); if let Err(JSONParseError { at, reason }) = result { return Err(Box::from(format!("JSON parse error: {reason:?} @ {at}"))); @@ -279,14 +291,12 @@ pub(crate) fn upgrade_self() -> Result> { } // Read and discard headers - let mut headers = String::new(); loop { let mut line = String::new(); reader.read_line(&mut line)?; - if line == "\r\n" { + if let "\r\n" = line.as_str() { break; } - headers.push_str(&line); } // Open the file to write the body diff --git a/src/wasm_bindings.rs b/src/wasm_bindings.rs index c11d7c9e..252b1a2f 100644 --- a/src/wasm_bindings.rs +++ b/src/wasm_bindings.rs @@ -13,12 +13,32 @@ const TYPES_WASM_CHECK_OUTPUT: &str = r###" interface WASMCheckOutput { readonly diagnostics: DiagnosticsContainer, get_type_at_position(path: string, pos: number): string; - get_type_at_position_debug(path: string, pos: number): string; + get_type_at_position_with_span(path: string): Module | null; + get_module_ast(path: string): Module | null; } "###; #[wasm_bindgen] pub struct WASMCheckOutput(checker::CheckOutput); +#[wasm_bindgen] +pub struct TypeWithPosition { + type_as_string: String, + position: crate::source_map::SpanWithSource, +} + +#[wasm_bindgen] +impl TypeWithPosition { + #[wasm_bindgen(js_name = type_as_string, getter, skip_typescript)] + pub fn get_type_as_string(&self) -> String { + self.type_as_string.clone() + } + + #[wasm_bindgen(js_name = position, getter, skip_typescript)] + pub fn get_position(&self) -> JsValue { + serde_wasm_bindgen::to_value(&self.position).unwrap() + } +} + #[wasm_bindgen] impl WASMCheckOutput { #[wasm_bindgen(js_name = diagnostics, getter, skip_typescript)] @@ -30,8 +50,10 @@ impl WASMCheckOutput { self.0.get_type_at_position(path, pos, false) } - pub fn get_type_at_position_debug(&self, path: &str, pos: u32) -> Option { - self.0.get_type_at_position(path, pos, true) + pub fn get_type_at_position_with_span(&self, path: &str, pos: u32) -> Option { + self.0 + .get_type_at_position_with_span(path, pos, false) + .map(|(type_as_string, position)| TypeWithPosition { type_as_string, position }) } pub fn get_module_ast(&self, path: &str) -> JsValue { @@ -77,9 +99,7 @@ pub fn check_wasm( const TYPES_WASM_CHECK_OUTPUT: &str = r###" interface WASMBuildOutput { readonly artifacts: Array, - readonly diagnostics: DiagnosticsContainer, - get_type_at_position(path: string, pos: number): string; - get_type_at_position_debug(path: string, pos: number): string; + readonly check_output: WASMCheckOutput, } "###; #[wasm_bindgen] @@ -104,8 +124,12 @@ impl WASMBuildOutput { self.check_output.get_type_at_position(path, pos) } - pub fn get_type_at_position_debug(&self, path: &str, pos: u32) -> Option { - self.check_output.get_type_at_position_debug(path, pos) + pub fn get_type_at_position_with_span(&self, path: &str, pos: u32) -> Option { + self.check_output.get_type_at_position_with_span(path, pos) + } + + pub fn get_module_ast(&self, path: &str) -> JsValue { + self.check_output.get_module_ast(path) } }