diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml
index 9f57be65..e78a05be 100644
--- a/.github/workflows/github-release.yml
+++ b/.github/workflows/github-release.yml
@@ -85,7 +85,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
- name: build-artifacts
+ name: build-artifacts-${{ matrix.os }}
path: artifacts/*
if-no-files-found: error
retention-days: 1
@@ -96,9 +96,14 @@ jobs:
steps:
- uses: actions/checkout@v3
+
- uses: actions/download-artifact@v3
with:
- name: build-artifacts
+ name: build-artifacts-windows-latest
+ path: build-artifacts
+ - uses: actions/download-artifact@v3
+ with:
+ name: build-artifacts-ubuntu-latest
path: build-artifacts
- name: Print artifacts
diff --git a/.github/workflows/performance-and-size.yml b/.github/workflows/performance-and-size.yml
index a3c964c7..2a99cbd2 100644
--- a/.github/workflows/performance-and-size.yml
+++ b/.github/workflows/performance-and-size.yml
@@ -8,7 +8,7 @@ env:
CARGO_TERM_COLOR: always
jobs:
- hyperfine:
+ run-benchmarks:
runs-on: ubuntu-latest
steps:
@@ -34,32 +34,49 @@ jobs:
- name: Download files
run: |
- curl -O https://gist.githubusercontent.com/kaleidawave/5dcb9ec03deef1161ebf0c9d6e4b88d8/raw/03156048e214af0ceee4005ba8b86f96690dcbb2/demo.ts > demo.ts
-
curl https://esm.sh/v128/react-dom@18.2.0/es2022/react-dom.mjs > react.js
- - name: Run parser, minfier, stringer performance
+ - name: Run checker performance
shell: bash
run: |
- curl https://esm.sh/v128/react-dom@18.2.0/es2022/react-dom.mjs > react.js
+ # Generate a file which contains everything that Ezno currently implements
+ cargo run -p ezno-parser --example code_blocks_to_script ./checker/specification/specification.md demo.ts
- echo "### Hyperfine">> $GITHUB_STEP_SUMMARY
- echo "\`\`\`shell">> $GITHUB_STEP_SUMMARY
- hyperfine './target/release/ezno ast-explorer --file react.js uglifier' >> $GITHUB_STEP_SUMMARY
+ echo "
+ Input
+
+ \`\`\`ts
+ " >> $GITHUB_STEP_SUMMARY
+ cat demo.ts >> $GITHUB_STEP_SUMMARY
+ echo "\`\`\`
+
+ " >> $GITHUB_STEP_SUMMARY
+
+ # Printing diagnostics, so turn colors off for GH Summary
+ NO_COLOR=1
+
+ echo "
+ Diagnostics
+
+ \`\`\`" >> $GITHUB_STEP_SUMMARY
+ ./target/release/ezno check demo.ts --timings &>> $GITHUB_STEP_SUMMARY
+ echo "\`\`\`
+
+ " >> $GITHUB_STEP_SUMMARY
+
+ echo "### Checking
+ \`\`\`shell" >> $GITHUB_STEP_SUMMARY
+ hyperfine './target/release/ezno check demo.ts' >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
- - name: Run checker performance
+ - name: Run parser, minfier/stringer performance
shell: bash
- if: false
run: |
- echo "### Output">> $GITHUB_STEP_SUMMARY
- echo "\`\`\`shell">> $GITHUB_STEP_SUMMARY
- ./target/release/ezno check demo.ts >> $GITHUB_STEP_SUMMARY
- echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
-
- echo "### Hyperfine">> $GITHUB_STEP_SUMMARY
- echo "\`\`\`shell">> $GITHUB_STEP_SUMMARY
- hyperfine './target/release/ezno check demo.ts' >> $GITHUB_STEP_SUMMARY
+ curl https://esm.sh/v128/react-dom@18.2.0/es2022/react-dom.mjs > react.js
+
+ echo "### Parsing and writing out minified form of `react-dom`
+ \`\`\`shell">> $GITHUB_STEP_SUMMARY
+ hyperfine './target/release/ezno ast-explorer --file react.js uglifier' >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
- name: Print (linux) binary size
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d1d7c945..080238a0 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -95,7 +95,7 @@ jobs:
- uses: brndnmtthws/rust-action-cargo-binstall@v1
if: ${{ github.event.inputs.ezno-version != 'none' }}
with:
- packages: wasm-bindgen-cli@0.2.87
+ packages: wasm-bindgen-cli@0.2.89
- name: Set NPM package version & build
id: set-npm-version
@@ -140,11 +140,15 @@ jobs:
run: |
git add .
git commit -m "Release: ${{ steps.release.outputs.new-versions-description }}"
+
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git config user.name "github-actions[bot]"
# Create tags
echo '${{ steps.release.outputs.new-versions }}' | jq -r '.[]' | while read -r update; do
git tag "release/$update"
done
+
git push --tags origin main
- name: Discord
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 902ea5d6..4f9844dd 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -71,7 +71,7 @@ jobs:
- uses: brndnmtthws/rust-action-cargo-binstall@v1
if: steps.changes.outputs.src == 'true'
with:
- packages: wasm-bindgen-cli@0.2.87
+ packages: wasm-bindgen-cli@0.2.89
- uses: denoland/setup-deno@v1
if: steps.changes.outputs.src == 'true'
with:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 94a16890..db09f18b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -32,6 +32,10 @@ If you want to check all the checker tests
```shell
cargo test -p ezno-checker-specification
+# Also
+cargo test -p ezno-checker-specification -F staging
+# and
+cargo test -p ezno-checker-specification -F all
```
If you want to test the lexing and parsing in Ezno's parser
@@ -46,7 +50,7 @@ cargo run -p ezno-parser --example lex path/to/file.ts
### Useful commands
- Check source is valid with `cargo check --workspace`
-- Check that code is formatted in accordance with the specification with `cargo fmt --all --check`
+- Check that code is formatted in accordance with the configuration with `cargo fmt --all --check`
- Run all tests `cargo test --workspace --verbose`
- Use `cargo clippy -- --allow warnings` to find blocking lints
diff --git a/Cargo.lock b/Cargo.lock
index 139cc7b0..2e877d84 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,15 +2,6 @@
# It is not intended for manual editing.
version = 3
-[[package]]
-name = "aho-corasick"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
-dependencies = [
- "memchr",
-]
-
[[package]]
name = "argh"
version = "0.1.12"
@@ -50,9 +41,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
-version = "0.13.1"
+version = "0.21.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
[[package]]
name = "bimap"
@@ -73,6 +64,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+[[package]]
+name = "bitflags"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+
[[package]]
name = "bumpalo"
version = "3.14.0"
@@ -85,12 +82,6 @@ version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -109,17 +100,15 @@ dependencies = [
[[package]]
name = "console"
-version = "0.14.1"
+version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45"
+checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
- "regex",
- "terminal_size",
"unicode-width",
- "winapi 0.3.9",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -128,10 +117,29 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"wasm-bindgen",
]
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
+dependencies = [
+ "cfg-if",
+]
+
[[package]]
name = "derive-debug-extras"
version = "0.2.2"
@@ -241,11 +249,17 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
[[package]]
name = "erased-serde"
-version = "0.3.31"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c"
+checksum = "4adbf0983fe06bd3a5c19c8477a637c2389feb0994eca7a59e3b961054aa7c0a"
dependencies = [
"serde",
]
@@ -342,47 +356,21 @@ version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
"redox_syscall",
- "windows-sys",
-]
-
-[[package]]
-name = "fsevent"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
-dependencies = [
- "bitflags",
- "fsevent-sys",
+ "windows-sys 0.52.0",
]
[[package]]
name = "fsevent-sys"
-version = "2.0.1"
+version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
+checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
-[[package]]
-name = "fuchsia-zircon"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
-dependencies = [
- "bitflags",
- "fuchsia-zircon-sys",
-]
-
-[[package]]
-name = "fuchsia-zircon-sys"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
-
[[package]]
name = "get-field-by-type"
version = "0.0.3"
@@ -403,27 +391,27 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.12.3"
+version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "indexmap"
-version = "1.9.3"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
- "autocfg",
+ "equivalent",
"hashbrown",
]
[[package]]
name = "inotify"
-version = "0.7.1"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f"
+checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"inotify-sys",
"libc",
]
@@ -437,15 +425,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "iovec"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
-dependencies = [
- "libc",
-]
-
[[package]]
name = "iterator-endiate"
version = "0.2.1"
@@ -468,26 +447,30 @@ dependencies = [
]
[[package]]
-name = "kernel32-sys"
-version = "0.2.2"
+name = "kqueue"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
dependencies = [
- "winapi 0.2.8",
- "winapi-build",
+ "kqueue-sys",
+ "libc",
]
[[package]]
-name = "lazy_static"
-version = "1.4.0"
+name = "kqueue-sys"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+]
[[package]]
-name = "lazycell"
-version = "1.3.0"
+name = "lazy_static"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "levenshtein"
@@ -527,53 +510,16 @@ dependencies = [
"syn 1.0.109",
]
-[[package]]
-name = "memchr"
-version = "2.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
-
[[package]]
name = "mio"
-version = "0.6.23"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
+checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
- "cfg-if 0.1.10",
- "fuchsia-zircon",
- "fuchsia-zircon-sys",
- "iovec",
- "kernel32-sys",
"libc",
"log",
- "miow",
- "net2",
- "slab",
- "winapi 0.2.8",
-]
-
-[[package]]
-name = "mio-extras"
-version = "2.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
-dependencies = [
- "lazycell",
- "log",
- "mio",
- "slab",
-]
-
-[[package]]
-name = "miow"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
-dependencies = [
- "kernel32-sys",
- "net2",
- "winapi 0.2.8",
- "ws2_32-sys",
+ "wasi",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -585,33 +531,23 @@ dependencies = [
"winconsole",
]
-[[package]]
-name = "net2"
-version = "0.2.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac"
-dependencies = [
- "cfg-if 0.1.10",
- "libc",
- "winapi 0.3.9",
-]
-
[[package]]
name = "notify"
-version = "4.0.17"
+version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257"
+checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [
- "bitflags",
+ "bitflags 2.4.1",
+ "crossbeam-channel",
"filetime",
- "fsevent",
"fsevent-sys",
"inotify",
+ "kqueue",
"libc",
+ "log",
"mio",
- "mio-extras",
"walkdir",
- "winapi 0.3.9",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -631,9 +567,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "ordered-float"
-version = "3.9.2"
+version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc"
+checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e"
dependencies = [
"num-traits",
]
@@ -701,38 +637,9 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
]
-[[package]]
-name = "regex"
-version = "1.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
-
[[package]]
name = "rgb"
version = "0.8.37"
@@ -789,9 +696,9 @@ dependencies = [
[[package]]
name = "serde-wasm-bindgen"
-version = "0.5.0"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
+checksum = "b9b713f70513ae1f8d92665bbbbda5c295c2cf1da5542881ae5eefe20c9af132"
dependencies = [
"js-sys",
"serde",
@@ -820,15 +727,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "slab"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
-
[[package]]
name = "source-map"
version = "0.14.7"
@@ -895,16 +793,6 @@ dependencies = [
"winapi-util",
]
-[[package]]
-name = "terminal_size"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
-dependencies = [
- "libc",
- "winapi 0.3.9",
-]
-
[[package]]
name = "tokenizer-lib"
version = "1.5.1"
@@ -936,21 +824,27 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
[[package]]
name = "wasm-bindgen"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
+checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
+checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
@@ -963,9 +857,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
+checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -973,9 +867,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.87"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
+checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
@@ -986,15 +880,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
-
-[[package]]
-name = "winapi"
-version = "0.2.8"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]]
name = "winapi"
@@ -1006,12 +894,6 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu",
]
-[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
-
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
@@ -1024,7 +906,7 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
- "winapi 0.3.9",
+ "winapi",
]
[[package]]
@@ -1041,7 +923,25 @@ checksum = "664fdcefd3903fbe6c463659a3fe4e7a541e717bbf6084cb1cfa98fcb6d88361"
dependencies = [
"lazy_static",
"rgb",
- "winapi 0.3.9",
+ "winapi",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[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]]
@@ -1050,7 +950,37 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[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",
]
[[package]]
@@ -1059,45 +989,117 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
]
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[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.0"
@@ -1106,19 +1108,21 @@ checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.52.0"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
+name = "windows_x86_64_msvc"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
-dependencies = [
- "winapi 0.2.8",
- "winapi-build",
-]
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "yansi"
diff --git a/Cargo.toml b/Cargo.toml
index f268feb0..38987f0f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -54,10 +54,10 @@ path = "src/main.rs"
[dependencies]
# ezno-web-framework = { path = "./plugins/web" }
-console = "0.14.1"
+console = "0.15.7"
codespan-reporting = "0.11.1"
argh = "0.1.6"
-base64 = "0.13.0"
+base64 = "0.21.5"
enum-variants-strings = "0.2.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.107"
@@ -75,11 +75,11 @@ features = ["extras"]
package = "ezno-parser"
[target.'cfg(target_family = "wasm")'.dependencies]
-wasm-bindgen = "=0.2.87"
-serde-wasm-bindgen = "0.5.0"
+wasm-bindgen = "=0.2.89"
+serde-wasm-bindgen = "0.6.3"
console_error_panic_hook = "0.1.7"
js-sys = "0.3"
[target.'cfg(not(target_family = "wasm"))'.dependencies]
multiline-term-input = "0.1.0"
-notify = "4.0.17"
+notify = "6.1.0"
diff --git a/checker/Cargo.toml b/checker/Cargo.toml
index 23810828..da4c87c5 100644
--- a/checker/Cargo.toml
+++ b/checker/Cargo.toml
@@ -8,6 +8,7 @@ homepage = "https://kaleidawave.github.io/posts/introducing-ezno"
authors = ["Ben "]
edition = "2021"
categories = ["compilers"]
+keywords = ["javascript", "typechecker", "checker", "typescript", "types"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -33,16 +34,16 @@ iterator-endiate = "0.2"
bimap = "0.6.2"
path-absolutize = { version = "3.0.14", features = ["use_unix_paths_on_wasm"] }
-indexmap = "1.7.0"
+indexmap = "2.1.0"
either = "1.6.1"
levenshtein = "1.0.5"
once_cell = "1.10.0"
-ordered-float = "3.0.0"
+ordered-float = "4.2.0"
map_vec = "0.3.0"
serde = { version = "1.0", features = ["derive"] }
# For trait object safe thingy
-erased-serde = "0.3"
+erased-serde = "0.4.1"
[dependencies.parser]
path = "../parser"
diff --git a/checker/definitions/internal-full.d.ts b/checker/definitions/internal-full.d.ts
index 623d6eb3..c78668cc 100644
--- a/checker/definitions/internal-full.d.ts
+++ b/checker/definitions/internal-full.d.ts
@@ -1,23 +1,3 @@
-// ↓↓ Ezno Functions ↓↓
-declare function debug_context(): void performs const debug_context;
-declare function print_type(t: any): void performs const print_type;
-declare function debug_type(t: any): void performs const debug_type;
-declare function debug_type_rust(t: any): void performs const debug_type_rust;
-declare function debug_effects_rust(t: () => {}): void performs const debug_effects_rust;
-declare function debug_effects(t: () => {}): void performs const debug_effects;
-declare function is_dependent(t: any): void performs const is_dependent;
-
-declare function context_id(): void performs const context_id;
-declare function context_id_chain(): void performs const context_id_chain;
-
-// A function, as it should be!
-declare function satisfies(t: T): T performs const satisfies;
-
-declare function compile_type_to_object(): any performs const compile_type_to_object;
-// ↑↑ Ezno Functions ↑↑
-
-declare var undefined: undefined;
-
interface nominal Array {
[index: number]: T | undefined;
@@ -38,17 +18,18 @@ interface nominal Array {
}
}
- map(cb: (t: T) => U): Array performs {
+ // TODO this argument
+ map(cb: (t: T, i?: number, self: Array) => U): Array performs {
const { length } = this, u: Array = [];
let i: number = 0;
while (i < length) {
- const value = this[i++];
- u.push(cb(value))
+ const value = this[i];
+ u.push(cb(value, i++, this))
}
return u;
}
- filter(cb: (t: T) => boolean): Array performs {
+ filter(cb: (t: T, i?: number, self: Array) => boolean): Array performs {
const { length } = this, filtered: Array = [];
let i: number = 0;
while (i < length) {
@@ -60,7 +41,7 @@ interface nominal Array {
return filtered;
}
- find(cb: (t: T) => boolean): T | undefined performs {
+ find(cb: (t: T, i?: number, self: Array) => boolean): T | undefined performs {
const { length } = this;
let i: number = 0;
while (i < length) {
@@ -71,7 +52,7 @@ interface nominal Array {
}
}
- every(cb: (t: T) => boolean): boolean performs {
+ every(cb: (t: T, i?: number, self: Array) => boolean): boolean performs {
const { length } = this;
let i: number = 0;
while (i < length) {
@@ -84,7 +65,7 @@ interface nominal Array {
return true
}
- some(cb: (t: T) => boolean): boolean performs {
+ some(cb: (t: T, i?: number, self: Array) => boolean): boolean performs {
const { length } = this;
let i: number = 0;
while (i < length) {
@@ -108,9 +89,19 @@ interface nominal Array {
return false
}
- // last() performs {
- // return this[this.length - 1]
- // }
+ join(joiner: string = ","): string performs {
+ const { length } = this;
+ let i = 1;
+ if (length === 0) {
+ return ""
+ }
+ // TODO conversion
+ let s: string = "" + this[0];
+ while (i < length) {
+ s += this[i++];
+ }
+ return s
+ }
}
interface Math {
@@ -140,6 +131,12 @@ interface nominal string {
toLowerCase(): string performs const lowercase;
get length(): number performs const string_length;
+
+ // TODO
+ slice(start: number, end?: number): string performs const slice;
+
+ // TODO
+ split(splitter: string): Array performs const split;
}
interface Console {
diff --git a/checker/definitions/internal.d.ts b/checker/definitions/internal.d.ts
index a4804291..b35f9196 100644
--- a/checker/definitions/internal.d.ts
+++ b/checker/definitions/internal.d.ts
@@ -18,7 +18,7 @@ declare function satisfies(t: T): T performs const satisfies;
declare function compile_type_to_object(): any performs const compile_type_to_object;
// ↑↑ Ezno Functions ↑↑
-declare var undefined: undefined;
+// declare var undefined: undefined;
interface nominal Array {
[index: number]: T | undefined;
@@ -98,7 +98,7 @@ interface Symbols {
iterator: 199
}
-declare var Symbol: Symbols;
+declare const Symbol: Symbols;
interface Object {
@DoNotIncludeThis
@@ -114,10 +114,10 @@ interface Object {
// }
}
-declare var JSON: JSON;
-declare var Math: Math;
-declare var console: Console;
-declare var Object: Object;
+declare const JSON: JSON;
+declare const Math: Math;
+declare const console: Console;
+declare const Object: Object;
declare function JSXH(tag: string, attributes: any, children?: any) performs {
return { tag, attributes, children }
diff --git a/checker/docs/inference.md b/checker/docs/inference.md
index 81301ce4..d3a7f782 100644
--- a/checker/docs/inference.md
+++ b/checker/docs/inference.md
@@ -35,11 +35,6 @@ print_properties({ x: 1, get y() { Reflect.set(this, "z", 3); return 2 } })
This may be solved in the future by a different way of checking parameters, but for now it is recognised as a use case that should be avoided.
-### #TODO
-- Mutable and immutable bases in `Context`
-- Modify RootPoly so only open poly and Typed generic and parameter can have a aliases, rest is handled by Context
-- Think about how function constraints work (they may not exist under `Type`)
-
### Inferable properties
There are two types of inference, type based *coalescence*:
diff --git a/checker/examples/check.rs b/checker/examples/check.rs
index 1d61d2d4..fc18dd83 100644
--- a/checker/examples/check.rs
+++ b/checker/examples/check.rs
@@ -13,7 +13,7 @@ fn main() {
let now = Instant::now();
let (diagnostics, post_check_data) = check_project::<_, synthesis::EznoParser>(
- path.to_path_buf(),
+ vec![path.to_path_buf()],
std::iter::once(ezno_checker::INTERNAL_DEFINITION_FILE_PATH.into()).collect(),
|path: &std::path::Path| {
if path == PathBuf::from(ezno_checker::INTERNAL_DEFINITION_FILE_PATH) {
@@ -23,11 +23,12 @@ fn main() {
}
},
None,
+ (),
);
let args: Vec<_> = env::args().collect();
- if let Ok(mut post_check_data) = post_check_data {
+ if let Ok(post_check_data) = post_check_data {
if args.iter().any(|arg| arg == "--types") {
eprintln!("Types:");
for (type_id, item) in post_check_data.types.into_vec_temp() {
@@ -36,8 +37,7 @@ fn main() {
}
if args.iter().any(|arg| arg == "--events") {
eprintln!("Events on entry:");
- let entry_module =
- post_check_data.modules.remove(&post_check_data.entry_source).unwrap();
+ let (_, entry_module) = post_check_data.modules.into_iter().next().unwrap();
for item in entry_module.facts.get_events() {
eprintln!("\t{item:?}");
}
@@ -51,10 +51,23 @@ fn main() {
} else {
eprintln!("Diagnostics:");
for diagnostic in diagnostics {
- eprintln!("\t{}", diagnostic.reason());
- if let Diagnostic::PositionWithAdditionalLabels { labels, .. } = diagnostic {
- for (label, _) in labels.iter() {
- eprintln!("\t\t({})", label);
+ let prefix: char = match diagnostic.kind() {
+ ezno_checker::DiagnosticKind::Error => 'E',
+ ezno_checker::DiagnosticKind::Warning => 'W',
+ ezno_checker::DiagnosticKind::Info => 'I',
+ };
+ match diagnostic {
+ Diagnostic::Global { reason, kind: _ } => {
+ eprintln!("\t{prefix}: {reason}");
+ }
+ Diagnostic::Position { reason, position, kind: _ } => {
+ eprintln!("\t{prefix}: {reason} {position:?}");
+ }
+ Diagnostic::PositionWithAdditionalLabels { reason, position, labels, kind: _ } => {
+ eprintln!("\t{prefix}: {reason} {position:?}");
+ for (reason, position) in labels {
+ eprintln!("\t\t{reason} {position:?}");
+ }
}
}
}
diff --git a/checker/specification/build.rs b/checker/specification/build.rs
index 092ff4bf..c1fc3a7f 100644
--- a/checker/specification/build.rs
+++ b/checker/specification/build.rs
@@ -94,7 +94,7 @@ fn markdown_lines_append_test_to_rust(
let mut errors = Vec::new();
for (_, line) in lines.by_ref() {
if line.starts_with("#") {
- panic!("block with no diagnostics or break between")
+ panic!("block with no diagnostics or break between in {test_title}")
} else if line.starts_with('-') {
let error =
line.strip_prefix("- ").unwrap().replace('\\', "").replace('"', "\\\"");
diff --git a/checker/specification/specification.md b/checker/specification/specification.md
index 4d9c6fb6..0978a0f1 100644
--- a/checker/specification/specification.md
+++ b/checker/specification/specification.md
@@ -19,10 +19,10 @@ const z: object = 4
```ts
let x: number = 3
-x = "not a number"
+x = "hello world"
```
-- Type "not a number" is not assignable to type number
+- Type "hello world" is not assignable to type number
#### Variable references
@@ -37,11 +37,11 @@ const b: string = a
```ts
let a = 2
-a = "not a number"
-let b: number = a
+a = "hello world"
+let b: boolean = a
```
-- Type "not a number" is not assignable to type number
+- Type "hello world" is not assignable to type boolean
#### Variable references does not exist
@@ -65,7 +65,7 @@ const a = 3;
- Cannot redeclare variable a
-#### Un-intialised variables are undefined
+#### Unintialised variables are undefined
> Might be a usage warning at some point
@@ -76,28 +76,209 @@ b satisfies string;
- Expected string, found undefined
-### Generic types
+### Properties
-#### Generic interface
+#### Property exists
```ts
-interface Wrapper {
- internal: T
+let my_obj = { a: 3 }
+const a = my_obj.a
+const b = my_obj.b
+```
+
+- No property 'b' on { a: 3 }
+
+#### Property updates registered
+
+```ts
+let my_obj = { a: 3 }
+my_obj.a = 4
+let b: 3 = my_obj.a
+```
+
+- Type 4 is not assignable to type 3
+
+#### Property references
+
+```ts
+const my_obj = { a: 2 }
+const three: 3 = my_obj.a
+```
+
+- Type 2 is not assignable to type 3
+
+#### Object property constraints
+
+```ts
+const my_obj: { a: number } = { a: 2 }
+my_obj.a = "hello world"
+```
+
+- Type "hello world" does not meet property constraint number
+
+#### Objects checks
+
+```ts
+const my_obj: { b: 3 } = { a: 2 }
+```
+
+- Type { a: 2 } is not assignable to type { b: 3 }
+
+#### Getters
+
+```ts
+let global = 0;
+const object = {
+ get getValue() {
+ return global++
+ },
}
-const my_wrapped: Wrapper = { internal: "hi" }
+object.getValue satisfies string
+object.getValue satisfies boolean
```
-- Type { internal: "hi" } is not assignable to type Wrapper\
+> Also test that side effects work here
-#### Array property checking
+- Expected string, found 0
+- Expected boolean, found 1
+
+#### Object spread
```ts
-const numbers1: Array = [1, 2, "3"]
-const numbers2: Array = ["hi", "3"]
+const obj1 = { a: 2, b: 3 };
+const obj2 = { b: 4, ...obj1, a: 6 };
+
+obj2.b satisfies 100;
+obj2.a satisfies boolean;
```
-- Type [1, 2, "3"] is not assignable to type Array\
+- Expected 100, found 3
+- Expected boolean, found 6
+
+#### Set property with key
+
+```ts
+const obj = { a: 2 }
+
+function setProperty(key: string, value) {
+ obj[key] = value;
+}
+
+setProperty("b", 6)
+obj satisfies string;
+```
+
+- Expected string, found { a: 2, b: 6 }
+
+#### Delete properties
+
+```ts
+const x = { a: 2, b: 3 }
+delete x.b;
+const b = x.b;
+```
+
+- No property 'b' on { a: 2 }
+
+### Constant evaluation
+
+#### Arithmetic
+
+```ts
+const x: 4 = 2 + 3
+const y: 6 = 2 * 3
+const z: 8 = (2 * 3) - 2
+```
+
+- Type 5 is not assignable to type 4
+- Type 4 is not assignable to type 8
+
+#### Bitwise arithmetic
+
+```ts
+const x: 2 = 2 & 3
+const y: 6 = 2 ^ 7
+const z: 14 = 8 | 4
+```
+
+- Type 5 is not assignable to type 6
+- Type 12 is not assignable to type 14
+
+#### Logical operators
+
+```ts
+const x: 2 = 3 && 2
+const y: 6 = 3 && false
+const z: false = true || 4
+```
+
+- Type false is not assignable to type 6
+- Type true is not assignable to type false
+
+#### Equality
+
+```ts
+(4 === 2) satisfies true;
+(4 !== 2) satisfies string;
+```
+
+- Expected true, found false
+- Expected string, found true
+
+#### Inequality
+
+```ts
+(Math.PI > 3) satisfies true;
+(4 < 2) satisfies true;
+(4 > 2) satisfies number;
+(2 >= 2) satisfies string;
+```
+
+- Expected true, found false
+- Expected number, found true
+- Expected string, found true
+
+#### String operations (constant functions can use `this`)
+
+```ts
+"hi".toUpperCase() satisfies number
+```
+
+- Expected number, found "HI"
+
+#### Math operations
+
+```ts
+Math.cos(0) satisfies 0
+Math.sqrt(16) satisfies 1
+Math.floor(723.22) satisfies 2;
+```
+
+- Expected 0, found 1
+- Expected 1, found 4
+- Expected 2, found 723
+
+#### Updating assignments
+
+```ts
+let a = 5, b = 6;
+a++;
+a satisfies 4;
+b *= 4;
+b satisfies 23;
+```
+
+- Expected 4, found 6
+- Expected 23, found 24
+
+#### Index into string
+
+```ts
+("something"[2]) satisfies number;
+```
+
+- Expected number, found "m"
### Function checking
@@ -132,32 +313,18 @@ func satisfies () => string
- Expected () => string, found () => 2
-#### Generic type argument restriction
+#### Set property on dependent observed
```ts
-function map(a: T, b: (t: T) => U) {
- return b(a)
+function add_property(obj: { prop: number }) {
+ obj.prop = 2;
+ (obj.prop satisfies 4);
}
-
-map(2, Math.sin)
-map("string", Math.sin)
```
-- Argument of type "string" is not assignable to parameter of type number
-
-> Because `Math.sin` set T to number
-
-#### Parameters are always considered generic
+> Not number
-```ts
-function id(a) {
- return a
-}
-
-const d: 3 = id(2)
-```
-
-- Type 2 is not assignable to type 3
+- Expected 4, found 2
#### Type checking basic function types
@@ -237,25 +404,93 @@ const x: (a: string) => number = a => a.to;
- No property 'to' on string
+#### Expected argument from parameter declaration
+
+```ts
+function map(a: (a: number) => number) {}
+
+// No annotation on `a`. But error comes from body
+// (rather than parameter assignment)
+map(a => a.t)
+```
+
+- No property 't' on number
+
+#### Assignment to parameter
+
+```ts
+function alterParameter(a: number, b: { prop: string }) {
+ a = 2;
+ a = "hi";
+
+ b.prop = 3;
+
+ // Observed
+ b.prop = "hello";
+ b.prop satisfies "hello";
+}
+```
+
+> Assigning straight to `a` might be disallowed by an option in the future. Right now it is allowed by JavaScript and so is allowed
+
+- Type \"hi\" is not assignable to type number
+- Type 3 does not meet property constraint string
+
+#### Type of rest parameter
+
+```ts
+function myRestFunction(...r: string[]) {
+ r satisfies boolean;
+}
+```
+
+- Expected boolean, found Array\
+
+#### Destructuring parameter
+
+```ts
+function myFunction({ a }: { a: number }) {
+ a satisfies boolean;
+ return a
+}
+
+myFunction({ a: 6 }) satisfies string;
+```
+
+- Expected boolean, found number
+- Expected string, found 6
+
### Function calling
#### Argument type against parameter
```ts
function func(a: number) {}
-func("not a number")
+func("hello world")
```
-- Argument of type "not a number" is not assignable to parameter of type number
+- Argument of type "hello world" is not assignable to parameter of type number
+
+#### Parameters are always considered generic
+
+```ts
+function id(a) {
+ return a
+}
+
+const d: 3 = id(2)
+```
+
+- Type 2 is not assignable to type 3
#### Generic type argument parameter
```ts
function func(a: T) {}
-func("not a number")
+func("hello world")
```
-- Argument of type "not a number" is not assignable to parameter of type number
+- Argument of type "hello world" is not assignable to parameter of type number
#### Get value of property on parameter
@@ -322,6 +557,20 @@ call(Math.sqrt) satisfies 2
- Expected 2, found 3
+#### Constant call and operation with a parameter
+
+> An example of the generic constructor type (namely call and operation)
+
+```ts
+function floorPlusB(a: number, b: number) {
+ return Math.floor(a) + b
+}
+
+floorPlusB(100.22, 5) satisfies 8
+```
+
+- Expected 8, found 105
+
#### This in object literal
```ts
@@ -350,68 +599,83 @@ function getToUpperCase(s: string) {
- Expected "HEY", found "HI"
-### Closures
+#### This as generic argument
-#### Reading variable
+```ts
+function callToUpperCase(s: string) {
+ return s.toUpperCase()
+}
+
+(callToUpperCase("hi") satisfies "HEY")
+```
+
+- Expected "HEY", found "HI"
+
+#### Calling new on a function
```ts
-function kestrel(a) {
- return function (_b) {
- return a
- }
+function MyClass(value) {
+ this.value = value
}
-kestrel(3)(2) satisfies 4
+new MyClass("hi").value satisfies "hello"
```
-- Expected 4, found 3
+- Expected "hello", found "hi"
-#### Nesting
+#### Arguments in to rest parameter
```ts
-function kestrel2(a) {
- return _b => _c => a
+function myRestFunction(...r: string[]) {
+ return r[0] + r[1]
}
-kestrel2(3)(2)(6) satisfies 4
+myRestFunction("hello ", "world") satisfies number;
```
-- Expected 4, found 3
+- Expected number, found "hello world"
-#### Carry across objects
+#### Default parameter
```ts
-function magicNumber(a: number) {
- return {
- plusOne() { return a + 1 },
- doubled() { return 2 * a }
- }
+function withDefault(x: number = 1) {
+ return x
}
-const myNumber = magicNumber(4);
-myNumber.plusOne() satisfies 5
-myNumber.doubled() satisfies 6
+withDefault() satisfies 2;
+withDefault(3) satisfies 3;
```
-- Expected 6, found 8
+- Expected 2, found 1
-#### Stateful
+#### Default parameter side effect
```ts
-function myClosure(a) {
- return {
- getValue() { return a },
- setValue(b) { a = b }
- }
+let b: number = 0
+function doThing(a = (b += 2)) {
+ return a
}
-const value = myClosure(4);
-value.getValue() satisfies 4;
-value.setValue(10);
-value.getValue() satisfies 6
+doThing("hello");
+b satisfies 0;
+doThing();
+b satisfies 1;
```
-- Expected 6, found 10
+- Expected 1, found 2
+
+#### Tagged template literal
+
+```ts
+function myTag(static_parts: Array, name: string) {
+ return static_parts[0] + name
+}
+
+const name = "Ben";
+myTag`${name}Hello ` satisfies "Hi Ben"
+```
+
+- Expected "Hi Ben", found "Hello Ben"
### Effects
@@ -423,7 +687,8 @@ value.getValue() satisfies 6
let a: number = 0
function func() {
a = 4;
- // Important that subsequent reads use the new value, not the same free variable
+ // Important that subsequent reads use the
+ // new value, not the same free variable
a satisfies 4;
}
@@ -462,20 +727,6 @@ obj.a satisfies 3
- Expected 3, found 4
-#### Constant call and operation with a parameter
-
-> An example of the generic constructor type (namely call and operation)
-
-```ts
-function sinPlusB(a: number, b: number) {
- return Math.floor(a) + b
-}
-
-sinPlusB(100.22, 5) satisfies 8
-```
-
-- Expected 8, found 105
-
#### Effects carry through dependent calls
```ts
@@ -544,268 +795,157 @@ setAtoString(myObject);
> Error could be better. Full one contains labels with more information
-- Assignment mismatch
-
-#### Mutating an object by a function
-
-> This is where the object loses its constant-ness
-
-```ts
-function doThingWithCallback(callback: (obj: { x: number }) => any) {
- const obj: { x: number } = { x: 8 };
- callback(obj);
- (obj.x satisfies 8);
- return obj;
-}
-
-const object = doThingWithCallback((obj: { x: number }) => obj.x = 2);
-(object.x satisfies string);
-```
-
-- Expected 8, found number
-- Expected string, found 2
-
-#### Assigning to parameter observed via effect
-
-```ts
-function add_property(obj: { prop: number }) {
- obj.prop += 2;
-}
-
-const obj = { prop: 4 };
-add_property(obj);
-(obj.prop satisfies 8);
-```
-
-- Expected 8, found 6
-
-### Constant evaluation
-
-#### Arithmetic
-
-```ts
-const x: 4 = 2 + 3
-const y: 6 = 2 * 3
-const z: 8 = (2 * 3) - 2
-```
-
-- Type 5 is not assignable to type 4
-- Type 4 is not assignable to type 8
-
-#### Bitwise arithmetic
-
-```ts
-const x: 2 = 2 & 3
-const y: 6 = 2 ^ 7
-const z: 14 = 8 | 4
-```
-
-- Type 5 is not assignable to type 6
-- Type 12 is not assignable to type 14
-
-#### Logical operators
-
-```ts
-const x: 2 = 3 && 2
-const y: 6 = 3 && false
-const z: false = true || 4
-```
-
-- Type false is not assignable to type 6
-- Type true is not assignable to type false
-
-#### Equality
-
-```ts
-(4 === 2) satisfies true;
-(4 !== 2) satisfies string;
-```
-
-- Expected true, found false
-- Expected string, found true
-
-#### Inequality
-
-```ts
-(Math.PI > 3) satisfies true;
-(4 < 2) satisfies true;
-(4 > 2) satisfies number;
-(2 >= 2) satisfies string;
-```
-
-- Expected true, found false
-- Expected number, found true
-- Expected string, found true
-
-#### String operations (constant functions can use `this`)
-
-```ts
-"hi".toUpperCase() satisfies number
-```
-
-- Expected number, found "HI"
-
-#### Math operations
-
-```ts
-Math.cos(0) satisfies 0;
-Math.sqrt(16) satisfies 1;
-Math.floor(723.22) satisfies 2
-```
-
-- Expected 0, found 1
-- Expected 1, found 4
-- Expected 2, found 723
-
-#### Updating assignments
+- Assignment mismatch
+
+#### Property assignment from conditional
```ts
-let a = 5, b = 6;
-a++;
-a satisfies 4;
-b *= 4;
-b satisfies 23;
+function getObject(condition: boolean) {
+ const mainObject = { a: 2 };
+ const object = condition ? mainObject : { b: 3 };
+ object.c = 4;
+ mainObject.c satisfies string;
+ return mainObject
+}
```
-- Expected 4, found 6
-- Expected 23, found 24
+- Expected string, found 4
-### Objects
+#### Mutating an object by a function
-#### Property exists
+> This is where the object loses its constant-ness
```ts
-let my_obj = { a: 3 }
-const a = my_obj.a
-const b = my_obj.b
+function doThingWithCallback(callback: (obj: { x: number }) => any) {
+ const obj: { x: number } = { x: 8 };
+ callback(obj);
+ (obj.x satisfies 8);
+ return obj;
+}
+
+const object = doThingWithCallback((obj: { x: number }) => obj.x = 2);
+(object.x satisfies string);
```
-- No property 'b' on { a: 3 }
+- Expected 8, found number
+- Expected string, found 2
-#### Property updates registered
+#### Assigning to parameter observed via effect
```ts
-let my_obj = { a: 3 }
-my_obj.a = 4
-let b: 3 = my_obj.a
+function add_property(obj: { prop: number }) {
+ obj.prop += 2;
+}
+
+const obj = { prop: 4 };
+add_property(obj);
+(obj.prop satisfies 8);
```
-- Type 4 is not assignable to type 3
+- Expected 8, found 6
-#### Property references
+#### Functions create objects
```ts
-const my_obj = { a: 2 }
-const three: 3 = my_obj.a
+function newObject() {
+ return { prop: 2 }
+}
+
+const a = newObject(), b = newObject();
+const c = a;
+(a === c) satisfies false;
+(a === b) satisfies string;
```
-- Type 2 is not assignable to type 3
+- Expected false, found true
+- Expected string, found false
-#### Object property constraints
+### Closures
+
+#### Reading variable
```ts
-const my_obj: { a: number } = { a: 2 }
-my_obj.a = "not a number"
+function kestrel(a) {
+ return function (_b) {
+ return a
+ }
+}
+
+kestrel(3)(2) satisfies 4
```
-- Type "not a number" does not meet property constraint number
+- Expected 4, found 3
-#### Objects checks
+#### Nesting
```ts
-const my_obj: { b: 3 } = { a: 2 }
+function kestrel2(a) {
+ return _b => _c => a
+}
+
+kestrel2(3)(2)(6) satisfies 4
```
-- Type { a: 2 } is not assignable to type { b: 3 }
+- Expected 4, found 3
-#### Getters
+#### Carry across objects
```ts
-let global = 0;
-const object = {
- get getValue() {
- return global++
- },
+function magicNumber(a: number) {
+ return {
+ plusOne() { return a + 1 },
+ doubled() { return 2 * a }
+ }
}
-object.getValue satisfies string
-object.getValue satisfies boolean
+const myNumber = magicNumber(4);
+myNumber.plusOne() satisfies 5
+myNumber.doubled() satisfies 6
```
-> Also test that side effects work here
-
-- Expected string, found 0
-- Expected boolean, found 1
+- Expected 6, found 8
-#### Object spread
+#### Stateful
```ts
-const obj1 = { a: 2, b: 3 };
-const obj2 = { b: 4, ...obj1, a: 6 };
+function myClosure(a) {
+ return {
+ getValue() { return a },
+ setValue(b) { a = b }
+ }
+}
-obj2.b satisfies 100;
-obj2.a satisfies boolean;
+const value = myClosure(4);
+value.getValue() satisfies 4;
+value.setValue(10);
+value.getValue() satisfies 6
```
-- Expected 100, found 3
-- Expected boolean, found 6
+- Expected 6, found 10
-#### Array pushing and pop-ing
+### Collection types
-> TODO maybe separate
+#### Array push
```ts
const x = [1]
x.push("hi")
x[1] satisfies 3
x.length satisfies 4;
-x.pop() satisfies "hi";
-x.length satisfies 1;
```
- Expected 3, found "hi"
- Expected 4, found 2
-#### Functions create objects
-
-```ts
-function newObject() {
- return { prop: 2 }
-}
-
-const a = newObject(), b = newObject();
-const c = a;
-(a === c) satisfies false;
-(a === b) satisfies string;
-```
-
-- Expected false, found true
-- Expected string, found false
-
-#### Set property with key
-
-```ts
-const obj = { a: 2 }
-
-function setProperty(key: string, value) {
- obj[key] = value;
-}
-
-setProperty("b", 6)
-obj satisfies string;
-```
-
-- Expected string, found { a: 2, b: 6 }
-
-#### Delete properties
+#### Array pop
```ts
-const x = { a: 2, b: 3 }
-delete x.b;
-const b = x.b;
+const myArray = [6, "hi"]
+myArray.pop() satisfies 3;
+myArray.length satisfies 1;
```
-- No property 'b' on { a: 2 }
+- Expected 3, found "hi"
### Control flow
@@ -857,7 +997,7 @@ a satisfies string
- Expected string, found "hi" | 0
-#### If else
+#### If and else (across function)
```ts
function print_number(value: number) {
@@ -996,6 +1136,20 @@ while (a < i) {
> Important that type is widened to 'number' (think it is an open poly in this case)
+#### Limit to iterations
+
+```ts
+let a: number = 0;
+while (a++ < 1_000_000) {}
+
+a satisfies string;
+```
+
+> The important part is that it doesn't run the loop. Eventually this might be run in a way that is not calling the assign to variable
+> function that evaluates `a = a + 1` a million times. There also should be per project, per module, per loop configuration
+
+- Expected string, found number
+
#### While loop unrolling as an effect
```ts
@@ -1030,6 +1184,29 @@ while (i++ < 10) {
- Expected 2, found 8
+#### Break with label
+
+```ts
+let a: number = 0;
+let result;
+
+top: while (a++ < 10) {
+ let b: number = 0;
+ while (b++ < 10) {
+ if (a === 3 && b === 2) {
+ result = a * b;
+ break top
+ }
+ }
+}
+
+a satisfies string;
+result satisfies boolean;
+```
+
+- Expected string, found 3
+- Expected boolean, found 6
+
#### Continue in a while loop
> With the continue the update to `a` only happens on even runs (5 times)
@@ -1071,7 +1248,7 @@ const x: X = { a: 2, b: false }
```ts
type MyNumber = number;
"hi" satisfies MyNumber;
-4 satisfies MyNumber
+4 satisfies MyNumber;
```
- Expected MyNumber, found "hi"
@@ -1079,12 +1256,62 @@ type MyNumber = number;
#### Declare variable
```ts
-declare var global_number: number
+declare const global_number: number
const my_number: string = global_number
```
- Type number is not assignable to type string
+#### Function (and interface) hoisting
+
+> Using functions and interface **before** their position of declaration in the source
+
+```ts
+getFive() satisfies 4;
+
+function getFive() {
+ return 5
+}
+
+let x: X = { a: 3 }
+
+interface X {
+ a: 2
+}
+```
+
+- Expected 4, found 5
+- Type { a: 3 } is not assignable to type X
+
+#### RegExp
+
+> RegExp = Regular expression
+> In the future, their definition could be considered and evaluated at runtime
+
+```ts
+/hi/ satisfies string;
+```
+
+- Expected string, found /hi/
+
+#### Null and undefined
+
+```ts
+undefined satisfies null;
+null satisfies undefined;
+```
+
+- Expected null, found undefined
+- Expected undefined, found null
+
+#### void operator
+
+```ts
+(void 2) satisfies string;
+```
+
+- Expected string, found undefined
+
#### (untagged) Template literal
```ts
@@ -1420,19 +1647,47 @@ getA({ p: 2 })
> I think reasons contains more information
-#### Function subtyping
+#### Function parameter subtyping
```ts
// Perfectly fine
-const x: (a: number) => string = (a: 4) => "hi"
+const x: (a: number) => string = (p: string | number) => "hi"
// Bad
-const y: (a: 4) => string = (a: number) => "hi"
+const y: (a: number | string) => string = (p: number) => "hi"
```
-- Type (a: number) => "hi" is not assignable to type (a: 4) => string
+- Type (p: number) => "hi" is not assignable to type (a: number | string) => string
> I think reasons contains more information
+#### Function return type subtyping
+
+```ts
+const x: (a: number) => number = p => 4
+const y: (a: number) => number = p => "a number"
+```
+
+- Type (p: number) => "a number" is not assignable to type (a: number) => number
+
+#### `void` return type
+
+> This works similarly to undefined except that it accepts any function return type
+
+```ts
+function runWithCallback(cb: () => void): void {
+ cb() satisfies string;
+
+ return 5;
+}
+
+runWithCallback(() => 3)
+```
+
+> Here argument is fine. In the body the return type is `any` (inferred constraint, but doesn't matter)
+
+- Expected string, found any
+- Cannot return 5 because the function is expected to return void
+
#### Indexing into (fixed) type
```ts
@@ -1487,13 +1742,28 @@ function getSecondCharacter(s: string) {
- Expected boolean, found (s: string) => string | undefined
- Expected "b", found "t"
-#### Index into string
+### Generic types
+
+#### Generic interface
```ts
-("something"[2] satisfies number);
+interface Wrapper {
+ internal: T
+}
+
+const my_wrapped: Wrapper = { internal: "hi" }
```
-- Expected number, found "m"
+- Type { internal: "hi" } is not assignable to type Wrapper\
+
+#### Array property checking
+
+```ts
+const numbers1: Array = [1, 2, "3"]
+const numbers2: Array = ["hi", "3"]
+```
+
+- Type [1, 2, "3"] is not assignable to type Array\
### Prototypes
@@ -1516,7 +1786,7 @@ const p = { b: 2 }
Object.setPrototypeOf(x, p);
const p_of_x = Object.getPrototypeOf(x);
// ('a' in p_of_x.a) satisfies false;
-p === p_of_x satisfies string;
+(p === p_of_x) satisfies string;
```
- Expected string, found true
@@ -1584,6 +1854,21 @@ export type MyNumber = string;
- Expected MyNumber, found 2
+#### Import type and variable
+
+```ts
+import { MyNumber } from "./types";
+2 satisfies MyNumber;
+MyNumber satisfies boolean;
+
+// in types.ts
+export type MyNumber = string;
+export const MyNumber = 6;
+```
+
+- Expected MyNumber, found 2
+- Expected boolean, found 6
+
#### Export let
```ts
diff --git a/checker/specification/test.rs b/checker/specification/test.rs
index 72ea11cf..623ab3bf 100644
--- a/checker/specification/test.rs
+++ b/checker/specification/test.rs
@@ -53,7 +53,7 @@ fn check_errors(
// let result = panic::catch_unwind(|| {
let result = checker::check_project::<_, EznoParser>(
- PathBuf::from("main.ts"),
+ vec![PathBuf::from("main.ts")],
std::iter::once(checker::INTERNAL_DEFINITION_FILE_PATH.into()).collect(),
|path| {
if path == std::path::Path::new(checker::INTERNAL_DEFINITION_FILE_PATH) {
@@ -68,6 +68,7 @@ fn check_errors(
}
},
type_check_options,
+ (),
);
// });
diff --git a/checker/specification/to_implement.md b/checker/specification/to_implement.md
index a0ec8387..8b1c0a98 100644
--- a/checker/specification/to_implement.md
+++ b/checker/specification/to_implement.md
@@ -27,33 +27,34 @@ function add_property(obj: { prop: number }) {
- Expected 4, found 2
-#### Calling on or type
+#### Generic type argument restriction
```ts
-type Func1 = () => 3;
-type Func2 = () => 2;
-function callFunc(func: (() => T) | (() => U)): 3 | 2 {
- return func()
+function map(a: T, b: (t: T) => U) {
+ return b(a)
}
-print_type(callFunc)
+map(2, Math.sin)
+map("string", Math.sin)
```
-- Expected "a" | "b" | "c" found "d"
+- Argument of type "string" is not assignable to parameter of type number
-#### This as generic argument
+> Because `Math.sin` set T to number
-> Was working, now broken for some reason :(
+#### Calling on or type
```ts
-function callToUpperCase(s: string) {
- return s.toUpperCase()
+type Func1 = () => 3;
+type Func2 = () => 2;
+function callFunc(func: (() => T) | (() => U)): 3 | 2 {
+ return func()
}
-(callToUpperCase("hi") satisfies "HEY")
+print_type(callFunc)
```
-- Expected "HEY", found "HI"
+- Expected "a" | "b" | "c" found "d"
#### Symmetric or
@@ -142,62 +143,81 @@ if (a === "hi") {
- Expected "hello", found "hi"
-### Looping
+### This
-#### For loops
+#### Bind function
```ts
-function func(array: Array) {
- for (const item of array) {
- item satisfies number
- }
+function ChangeThis(this: { value: any }) {
+ return this.value
}
+
+const x = ChangeThis.bind({ value: 2 })
+x() satisfies 3
```
-- Expected number found string
+- Expected 3, found 2
+
+### Iteration
-#### Constant loops
+#### For-in fixed object
```ts
-function join(array: Array) {
- let buf = ""
- for (let item of array) {
- buf += item
- }
- return buf
+let properties: string = "";
+for (const property in { a: 1, b: 2, c: 3 }) {
+ properties += property;
}
-
-join(["a", "b", "c"]) satisfies "cba"
+properties satisfies boolean;
```
-- Expected "cba" found "abc"
+- Expected boolean, found "abc"
-### This
+#### For-in non fixed object
-#### Calling new on a function
+> TypeScript anonymous object annotations do not guarantee ordering and the subtyping rules allow for the RHS to have more
+> properties than defined
```ts
-function MyClass(value) {
- this.value = value
+declare const myObject: { a: 1, b: 2, c: 3 };
+
+let properties: string = "";
+for (const property in myObject) {
+ properties += property;
}
+properties satisfies boolean;
+```
+
+- Expected boolean, found string
+
+> TODO for in and generators
+
+#### For loops
-new MyClass("hi").value satisfies "hello"
+```ts
+function func(array: Array) {
+ for (const item of array) {
+ item satisfies number
+ }
+}
```
-- Expected "hello", found "hi"
+- Expected number found string
-#### Bind function
+#### Constant for loop
```ts
-function ChangeThis(this: { value: any }) {
- return this.value
+function join(array: Array) {
+ let buf = ""
+ for (let item of array) {
+ buf += item
+ }
+ return buf
}
-const x = ChangeThis.bind({ value: 2 })
-x() satisfies 3
+join(["a", "b", "c"]) satisfies "cba"
```
-- Expected 3, found 2
+- Expected "cba" found "abc"
### Inference
@@ -238,7 +258,7 @@ x = 0
call() satisfies 2
```
-- Cannot call ...
+- Cannot call TODO
- Expected 2 found 1
#### Property restriction
@@ -254,7 +274,7 @@ print_type(call)
### Asynchronous functions and promises
-#TODO promise
+> TODO Promise properties
#### Async function
@@ -300,13 +320,11 @@ function x*() {
(await x) satisfies string;
```
-- #TODO
+- TODO
-### Proxy and Object
+### `Proxy` and `Object`
-#TODO effects
-#TODO traps
-#TODO Object.defineProperty
+> TODO effects, different traps and `Object.defineProperty`
#### Proxy object with default callback
@@ -331,6 +349,8 @@ a.prop3 satisfies "prop2"
### Collections
+> TODO filter, every and all, find, etc
+
#### Simple array map
```ts
@@ -341,6 +361,8 @@ function mapper(a: Array) {
print_type(mapper)
```
+- TODO
+
#### Generic array map
```ts
@@ -351,20 +373,9 @@ function mapper(a: Array, func: T => U) {
print_type(mapper)
```
-### Expressions
-
-#### Statements, declarations and expressions
-
-```ts
-function myTag(static_parts: Array, first_name: string) {
- return first_name + static_parts[0]
-}
-
-const name = "Ben";
-myTag`Hello ${name}` satisfies "Hi Ben"
-```
+- TODO
-- Expected "Hi Ben", found "Hello Ben"
+### Expressions
#### Bad arithmetic operator
@@ -378,33 +389,6 @@ console + 2
- Expected number, found Console
-#### Expected argument
-
-> Requires synthesising arguments later ...?
-
-```ts
-function map(a: (a: number) => number) {}
-
-map(a => a.t)
-```
-
-> No property t on string
-
-#### Spread arguments
-
-```ts
-function spread(main, ...others) {
- return {
- main,
- others,
- }
-}
-
-spread(1, 2, 3) satisfies string
-```
-
-- TODO...
-
#### Array spread
```ts
@@ -419,7 +403,16 @@ array2[2] satisfies string;
### Classes
-> TODO extends
+#### Extends
+
+```ts
+class BaseClass extends class { x: 2 } {
+ y: 3
+}
+
+const b = new BaseClass;
+print_type(b.x);
+```
#### Privacy
@@ -438,3 +431,38 @@ class MyClass {
- Cannot get private property "#a"
- Expected 3, found 2
+
+### Recursion
+
+#### Application
+
+```ts
+function x(a: number) {
+ if (a > 10 || a < 0) {
+ return a
+ }
+ return a--
+}
+
+print_type(x(4))
+print_type(x(90))
+```
+
+- TODO
+
+### Function checking
+
+#### Default parameter side effect on parameter
+
+> I don't think this works because of fact combining
+
+```ts
+function doThing(a, b = (a += 2)) {
+ return a
+}
+
+doThing(3) satisfies 2;
+doThing(6, 1) satisfies 6;
+```
+
+- Expected 2, found 5
diff --git a/checker/src/behavior/modules.rs b/checker/src/behavior/modules.rs
deleted file mode 100644
index 26f280b9..00000000
--- a/checker/src/behavior/modules.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use super::variables::VariableMutability;
-use crate::{context::facts::Facts, TypeId, VariableId};
-
-use source_map::Span;
-
-#[derive(Debug)]
-pub struct NamePair<'a> {
- pub value: &'a str,
- pub r#as: &'a str,
- pub position: Span,
-}
-
-pub enum ImportKind<'a, T: Iterator- >> {
- Parts(T),
- All {
- under: &'a str,
- position: Span,
- },
- /// From `export * from ...`
- Everything,
-}
-
-pub struct SynthesisedModule {
- pub content: M,
- pub exported: Exported,
- /// TODO ...
- pub facts: Facts,
-}
-
-/// TODO tidy
-#[derive(Clone, Debug, Default, binary_serialize_derive::BinarySerializable)]
-pub struct Exported {
- pub default: Option,
- pub named: Vec<(String, (VariableId, VariableMutability))>,
- pub named_types: Vec<(String, TypeId)>,
-}
-
-pub enum TypeOrVariable {
- ExportedVariable((VariableId, VariableMutability)),
- Type(TypeId),
-}
-
-impl Exported {
- pub(crate) fn get_export(&self, want: &str) -> Option {
- self.named
- .iter()
- .find_map(|(export, value)| {
- (export == want).then_some(TypeOrVariable::ExportedVariable((value.0, value.1)))
- })
- .or_else(|| {
- self.named_types.iter().find_map(|(export, value)| {
- (export == want).then_some(TypeOrVariable::Type(*value))
- })
- })
- }
-}
-
-/// After a syntax error
-pub struct InvalidModule;
-
-pub type FinalModule = Result, InvalidModule>;
diff --git a/checker/src/context/calling.rs b/checker/src/context/calling.rs
deleted file mode 100644
index 116ac5de..00000000
--- a/checker/src/context/calling.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-use super::facts::Facts;
-use crate::{events::EventResult, Environment, FunctionId};
-
-/// For anything that might involve a call, including gets, sets and actual calls
-pub(crate) trait CallCheckingBehavior {
- // TODO
- const CHECK_PARAMETERS: bool;
-
- fn get_latest_facts<'a>(&'a mut self, environment: &'a mut Environment) -> &'a mut Facts;
-
- fn in_recursive_cycle(&self, function_id: FunctionId) -> bool;
-
- fn new_function_target(
- &mut self,
- function_id: FunctionId,
- cb: impl for<'a> FnOnce(&'a mut Target) -> T,
- ) -> T;
-}
-
-pub struct CheckThings;
-
-impl CallCheckingBehavior for CheckThings {
- const CHECK_PARAMETERS: bool = true;
-
- fn get_latest_facts<'a>(&'a mut self, environment: &'a mut Environment) -> &'a mut Facts {
- &mut environment.facts
- }
-
- fn in_recursive_cycle(&self, _function_id: FunctionId) -> bool {
- // cannot get in a loop from checking
- false
- }
-
- fn new_function_target(
- &mut self,
- function_id: FunctionId,
- cb: impl for<'a> FnOnce(&'a mut Target) -> T,
- ) -> T {
- let mut target = Target(vec![TargetKind::Function(function_id)]);
- cb(&mut target)
- }
-}
-
-pub(crate) struct Target(Vec);
-
-pub(crate) enum TargetKind {
- Conditional(Facts),
- Function(FunctionId),
-}
-
-impl CallCheckingBehavior for Target {
- const CHECK_PARAMETERS: bool = false;
-
- fn get_latest_facts<'b>(&'b mut self, environment: &'b mut Environment) -> &'b mut Facts {
- self.0
- .iter_mut()
- .rev()
- .find_map(
- |kind| if let TargetKind::Conditional(facts) = kind { Some(facts) } else { None },
- )
- .unwrap_or(&mut environment.facts)
- }
-
- fn in_recursive_cycle(&self, function_id: FunctionId) -> bool {
- self.0.iter().any(|kind| matches!(kind, TargetKind::Function(id) if function_id == *id))
- }
-
- fn new_function_target(
- &mut self,
- function_id: FunctionId,
- cb: impl for<'a> FnOnce(&'a mut Target) -> T,
- ) -> T {
- self.0.push(TargetKind::Function(function_id));
- let value = cb(self);
- self.0.pop();
- value
- }
-}
-
-impl Target {
- /// TODO temp for loop unrolling
- pub(crate) fn new_default() -> Self {
- Target(Vec::new())
- }
-
- pub(crate) fn new_conditional_target(
- &mut self,
- cb: impl for<'a> FnOnce(&'a mut Target) -> Option,
- ) -> (Facts, Option) {
- self.0.push(TargetKind::Conditional(Facts::default()));
- let result = cb(self);
- if let Some(TargetKind::Conditional(facts)) = self.0.pop() {
- (facts, result)
- } else {
- unreachable!()
- }
- }
-}
diff --git a/checker/src/context/environment.rs b/checker/src/context/environment.rs
index 3eba3e59..9d8fe486 100644
--- a/checker/src/context/environment.rs
+++ b/checker/src/context/environment.rs
@@ -2,18 +2,18 @@ use source_map::{SourceId, Span, SpanWithSource};
use std::collections::HashSet;
use crate::{
- behavior::{
+ diagnostics::{NotInLoopOrCouldNotFindLabel, TypeCheckError, TypeStringRepresentation, TDZ},
+ events::{Event, FinalEvent, RootReference},
+ features::{
assignments::{Assignable, AssignmentKind, Reference},
functions,
- modules::{Exported, ImportKind, NamePair},
+ modules::Exported,
operations::{
evaluate_logical_operation_with_expression,
evaluate_pure_binary_operation_handle_errors, MathematicalAndBitwise,
},
variables::{VariableMutability, VariableOrImport, VariableWithValue},
},
- diagnostics::{NotInLoopOrCouldNotFindLabel, TypeCheckError, TypeStringRepresentation, TDZ},
- events::{Event, RootReference},
subtyping::BasicEquality,
types::{
is_type_truthy_falsy,
@@ -25,7 +25,7 @@ use crate::{
};
use super::{
- calling::CheckThings, facts::Publicity, get_on_ctx, get_value_of_variable, AssignmentError,
+ facts::Publicity, get_on_ctx, get_value_of_variable, invocation::CheckThings, AssignmentError,
ClosedOverReferencesInScope, Context, ContextType, Environment, GeneralContext,
SetPropertyError,
};
@@ -49,6 +49,20 @@ pub struct Syntax<'a> {
pub location: ContextLocation,
}
+/// Code under a dynamic boundary can run more than once
+#[derive(Debug, Clone, Copy)]
+pub enum DynamicBoundaryKind {
+ Loop,
+ Function,
+}
+
+impl DynamicBoundaryKind {
+ #[must_use]
+ pub fn can_use_variable_before_definition(self) -> bool {
+ matches!(self, Self::Function)
+ }
+}
+
impl<'a> ContextType for Syntax<'a> {
fn as_general_context(et: &Context) -> GeneralContext<'_> {
GeneralContext::Syntax(et)
@@ -58,8 +72,12 @@ impl<'a> ContextType for Syntax<'a> {
Some(&self.parent)
}
- fn is_dynamic_boundary(&self) -> bool {
- matches!(self.scope, Scope::Function { .. } | Scope::Looping { .. })
+ fn is_dynamic_boundary(&self) -> Option {
+ match &self.scope {
+ Scope::Function { .. } => Some(DynamicBoundaryKind::Function),
+ Scope::Iteration { .. } => Some(DynamicBoundaryKind::Loop),
+ _ => None,
+ }
}
fn is_conditional(&self) -> bool {
@@ -121,6 +139,7 @@ pub enum Scope {
InterfaceEnvironment {
this_constraint: TypeId,
},
+ DefaultFunctionParameter {},
FunctionAnnotation {},
/// For ifs, elses, or lazy operators
Conditional {
@@ -130,7 +149,7 @@ pub enum Scope {
is_switch: Option