From 03662d980f12c23ef49f133efb4b012837a19b67 Mon Sep 17 00:00:00 2001 From: Andrew Segavac Date: Sun, 17 Aug 2025 16:10:13 -0600 Subject: [PATCH] switching language to tswq --- .gitignore | 130 +-- .rustfmt.toml | 1 - Cargo.lock | 501 --------- Cargo.toml | 18 - Dockerfile | 5 - build.rs | 5 - bun.lock | 412 ++++++++ docker-compose.yml | 6 - eslint.config.ts | 18 + package.json | 31 + packages/boringlang/package.json | 26 + packages/boringlang/src/index.ts | 11 + packages/boringlang/tsconfig.json | 19 + prettier.config.ts | 10 + src/ast.rs | 410 -------- src/builtins.rs | 3 - src/compiler.rs | 124 --- src/errors.rs | 64 -- src/grammar.lalrpop | 352 ------- src/interpreter.rs | 654 ------------ src/main.rs | 119 --- src/trait_checking.rs | 156 --- src/type_alias_resolution.rs | 379 ------- src/type_checking.rs | 1638 ----------------------------- src/types.rs | 58 - tsconfig.json | 19 + 26 files changed, 573 insertions(+), 4596 deletions(-) delete mode 100644 .rustfmt.toml delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 Dockerfile delete mode 100644 build.rs create mode 100644 bun.lock delete mode 100644 docker-compose.yml create mode 100644 eslint.config.ts create mode 100644 package.json create mode 100644 packages/boringlang/package.json create mode 100644 packages/boringlang/src/index.ts create mode 100644 packages/boringlang/tsconfig.json create mode 100644 prettier.config.ts delete mode 100644 src/ast.rs delete mode 100644 src/builtins.rs delete mode 100644 src/compiler.rs delete mode 100644 src/errors.rs delete mode 100644 src/grammar.lalrpop delete mode 100644 src/interpreter.rs delete mode 100644 src/main.rs delete mode 100644 src/trait_checking.rs delete mode 100644 src/type_alias_resolution.rs delete mode 100644 src/type_checking.rs delete mode 100644 src/types.rs create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index b3ac432..4adc998 100644 --- a/.gitignore +++ b/.gitignore @@ -1,112 +1,36 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class +.direnv/ -# C extensions -*.so +# dependencies (bun install) +node_modules -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST +# output +out +dist +*.tgz -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec +# code coverage +coverage +*.lcov -# Installer logs -pip-log.txt -pip-delete-this-directory.txt +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments +# dotenv environment variable files .env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ +.env.development.local +.env.test.local +.env.production.local +.env.local -# Spyder project settings -.spyderproject -.spyproject +# caches +.eslintcache +.cache +*.tsbuildinfo -# Rope project settings -.ropeproject +# IntelliJ based IDEs +.idea -# mkdocs documentation -/site - -# mypy -.mypy_cache/ - - -#Added by cargo -# -#already existing elements are commented out - -/target -**/*.rs.bk +# Finder (MacOS) folder config +.DS_Store \ No newline at end of file diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index 25acc7b..0000000 --- a/.rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -max_width=140 # Not ideal diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 895adbf..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,501 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bit-set" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "boring-lang" -version = "0.0.1" -dependencies = [ - "clap", - "lalrpop", - "lalrpop-util", - "regex", - "thiserror", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "diff" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "ena" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" -dependencies = [ - "log", -] - -[[package]] -name = "fixedbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "hermit-abi" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" -dependencies = [ - "either", -] - -[[package]] -name = "lalrpop" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15174f1c529af5bf1283c3bc0058266b483a67156f79589fab2a25e23cf8988" -dependencies = [ - "ascii-canvas", - "atty", - "bit-set", - "diff", - "ena", - "itertools", - "lalrpop-util", - "petgraph", - "pico-args", - "regex", - "regex-syntax", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "lalrpop-util" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e58cce361efcc90ba8a0a5f982c741ff86b603495bb15a998412e957dcd278" -dependencies = [ - "regex", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "once_cell" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" - -[[package]] -name = "petgraph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pico-args" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom", - "redox_syscall", -] - -[[package]] -name = "regex" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", - "thread_local", -] - -[[package]] -name = "regex-syntax" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" - -[[package]] -name = "rustversion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" - -[[package]] -name = "siphasher" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1" - -[[package]] -name = "string_cache" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a" -dependencies = [ - "lazy_static", - "new_debug_unreachable", - "phf_shared", - "precomputed-hash", -] - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "syn" -version = "1.0.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 1d8be69..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "boring-lang" -version = "0.0.1" -authors = ["asegavac"] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[build-dependencies.lalrpop] # <-- We added this and everything after! -version = "0.19.6" -features = ["lexer"] - -[dependencies] -lalrpop-util = "0.19.6" -regex = "1" -# inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" } -clap = "2.33.0" -thiserror = "1" diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 57c8b8e..0000000 --- a/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM rust:1.89 - -# RUN apt update && apt-get install -y llvm clang -RUN rustup component add rustfmt -WORKDIR /code diff --git a/build.rs b/build.rs deleted file mode 100644 index 23c7d3f..0000000 --- a/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern crate lalrpop; - -fn main() { - lalrpop::process_root().unwrap(); -} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..6ade591 --- /dev/null +++ b/bun.lock @@ -0,0 +1,412 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "boringlang", + "dependencies": { + "ohm-js": "^17.2.1", + }, + "devDependencies": { + "@types/bun": "latest", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "jiti": "^2.5.1", + "prettier": "^3.6.2", + "typescript": "^5.9.2", + "typescript-language-server": "^4.4.0", + "vscode-langservers-extracted": "^4.10.0", + }, + }, + "packages/boringlang": { + "name": "boringlang", + "version": "0.1.0", + "dependencies": { + "@bunli/core": "latest", + }, + "devDependencies": { + "@bunli/test": "latest", + "@types/bun": "latest", + "bunli": "latest", + }, + }, + }, + "packages": { + "@bunli/core": ["@bunli/core@0.1.0", "", { "dependencies": { "@bunli/utils": "0.1.0", "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0" } }, "sha512-+1hZ3cLgFLbpXndHhxZDkGNYj8zLvxmTSW4y+Kna6sJXI/L1lKaQGZBzu8+LmUckG+25BMydgocP59yaRURRag=="], + + "@bunli/test": ["@bunli/test@0.1.0", "", { "dependencies": { "@bunli/core": "0.1.0" }, "peerDependencies": { "bun": ">=1.0.0" } }, "sha512-kSvZ/CxoJ6xZLTCEF53bJnOqAGsMI2qd5oq9PwW9n4wPvnJhHO624+cS+1LHUhmCc68LzI0QyxoWTZJ1SnUqAg=="], + + "@bunli/utils": ["@bunli/utils@0.1.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "bun": ">=1.0.0" } }, "sha512-2KR4ZWhkFzRR4PYc9FB0Y738Xle98Heyr8se6YK+vetDXxhlBiM4W2WZ7IBHmZn12PcXedc5DBvDjrvOdXXv/Q=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="], + + "@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], + + "@eslint/js": ["@eslint/js@9.33.0", "", {}, "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], + + "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.2.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zygk+yeaww9kBw2JBWwA13KyOKySxbnetms/WyRFaUYhxiuJHkzv1c6/Ou7sIHa9Gbq4fYQEhx88Ywy1wu2oTQ=="], + + "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.2.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-k2akVmSvJHuzpwgwIU8ltary7EQbqlbvxgtYlVqYvnqUpRdRbkuJXAZhN5zuDNTftaG4l22Q/bX04tBB8Txmjg=="], + + "@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.2.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-bxXZlLD6DJ8rc/Ht0Cgm0BH1AJVO/axOElXJP42LUUKQ/U4t3OKkFDbFiTPGphcy5teMLkoYl+a2Cz8P9q2gVQ=="], + + "@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.2.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-g+CzF02RzKgSmuEHNLoDTtiiQR33cEZWcd/tWR+24h92xe5wXuqQsV7vQJLR6e44BWkDOACpTIrfW4UAaHw4Cw=="], + + "@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.2.20", "", { "os": "linux", "cpu": "none" }, "sha512-zB3aKckyUdKENLP+lm/PoXQPBTthJsY7dhYih+qVT95N29acLO2eWeSHgRkS7Pl2FV+mLJo9LvjRhC8oaSSoOw=="], + + "@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.2.20", "", { "os": "linux", "cpu": "x64" }, "sha512-KJZ0zJKadKCD6EI/mBv/0PUysMpd1r4o3WhQ73PjCZx2w95Ka2fSBAIsy9e/rxc07D4LHr26nGyMmC1K8IcS6Q=="], + + "@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.2.20", "", { "os": "linux", "cpu": "x64" }, "sha512-xtYPn84ur9U7YaS0+rwjs6YMgSv5Z4gMnqPQ1QTLw92nt1v9Cw17YypVab4zUk222o5Y6kS3DRkDdSHBh8uQfA=="], + + "@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.2.20", "", { "os": "linux", "cpu": "x64" }, "sha512-XPtQITGbJXgUrMXOJo3IShwQd3awB93ZIh5+4S3DF9Ek/lwXVSuueIIAfnveR/r9JRgEA5+g/1ZHVf1/3qaElg=="], + + "@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.2.20", "", { "os": "linux", "cpu": "x64" }, "sha512-rANapFZRrgOTeotaf556iIxguyjQbensL6gT3cXZDnXG+aVhv65hSnjqzM7vfHxlzoXbAmoUkJOpce0qEg/HlA=="], + + "@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.2.20", "", { "os": "win32", "cpu": "x64" }, "sha512-Jt4bAf30qG4SvnL6tO4QzZNbMjg5sLZHif22rZLwX7W6rWPAvgqyYdwDSGHN8Kkbe6KqV4DceyKQgRr83sU66Q=="], + + "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.2.20", "", { "os": "win32", "cpu": "x64" }, "sha512-2291+pyVQ771zd8jgCNJ/jpPBaLJg/X7BWX06M9GpBNmC1tu3Rfr3LaWP8C/XTi80PZJnzNZGeMlcDhRY57y/A=="], + + "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + + "@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="], + + "@types/bun": ["@types/bun@1.2.20", "", { "dependencies": { "bun-types": "1.2.20" } }, "sha512-dX3RGzQ8+KgmMw7CsW4xT5ITBSCrSbfHc36SNT31EOUg/LA9JWq0VDdEXDRSe1InVWpd2yLUM1FUF/kEOyTzYA=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="], + + "@types/react": ["@types/react@19.1.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg=="], + + "@vscode/l10n": ["@vscode/l10n@0.0.18", "", {}, "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-regex": ["ansi-regex@6.2.0", "", {}, "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + + "boringlang": ["boringlang@workspace:packages/boringlang"], + + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "bun": ["bun@1.2.20", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.2.20", "@oven/bun-darwin-x64": "1.2.20", "@oven/bun-darwin-x64-baseline": "1.2.20", "@oven/bun-linux-aarch64": "1.2.20", "@oven/bun-linux-aarch64-musl": "1.2.20", "@oven/bun-linux-x64": "1.2.20", "@oven/bun-linux-x64-baseline": "1.2.20", "@oven/bun-linux-x64-musl": "1.2.20", "@oven/bun-linux-x64-musl-baseline": "1.2.20", "@oven/bun-windows-x64": "1.2.20", "@oven/bun-windows-x64-baseline": "1.2.20" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-1ZGQynT+jPOHLY4IfzSubjbWcXsY2Z+irhW5D8RKC0wQ6KG4MvtgniAYQbSFYINGg8Wb2ydx+WgAG2BdhngAfw=="], + + "bun-types": ["bun-types@1.2.20", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-pxTnQYOrKvdOwyiyd/7sMt9yFOenN004Y6O4lCcCUoKVej48FS5cvTw9geRaEcB9TsDZaJKAxPTVvi8tFsVuXA=="], + + "bunli": ["bunli@0.1.1", "", { "dependencies": { "@bunli/core": "0.1.0", "@bunli/utils": "0.1.0", "glob": "^11.0.0", "zod": "^3.24.1" }, "bin": { "bunli": "dist/cli.js" } }, "sha512-hRNwQZGtXaKSnwGW1cCVPlBG14QMKAcQIg01Vf8eVmyJzIu2LE/wF5uFkdKXAXF/SDGVs9LZcXK9I8oQn5igRg=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "core-js": ["core-js@3.45.0", "", {}, "sha512-c2KZL9lP4DjkN3hk/an4pWn5b5ZefhRJnAc42n6LJ19kSnbeRbdQZE5dSeE2LBol1OwJD3X1BQvFTAsa8ReeDA=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], + + "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.33.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.33.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], + + "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.4", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.11.7" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="], + + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "lru-cache": ["lru-cache@11.1.0", "", {}, "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "node-html-parser": ["node-html-parser@6.1.13", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "ohm-js": ["ohm-js@17.2.1", "", {}, "sha512-4cXF0G09fAYU9z61kTfkNbKK1Kz/sGEZ5NbVWHoe9Qi7VB7y+Spwk051CpUTfUENdlIr+vt8tMV4/LosTE2cDQ=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-scurry": ["path-scurry@2.0.0", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + + "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="], + + "request-light": ["request-light@0.7.0", "", {}, "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "typescript-language-server": ["typescript-language-server@4.4.0", "", { "bin": { "typescript-language-server": "lib/cli.mjs" } }, "sha512-enWhplhHX7PA0q+IcKHBMpTQh9I2Bmb3L45rwnkATHMsZ7YLduyyCdOmVUWJSYZfkWaBMiKwi/e2FQo4xsKeWw=="], + + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "vscode-css-languageservice": ["vscode-css-languageservice@6.3.7", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-5TmXHKllPzfkPhW4UE9sODV3E0bIOJPOk+EERKllf2SmAczjfTmYeq5txco+N3jpF8KIZ6loj/JptpHBQuVQRA=="], + + "vscode-html-languageservice": ["vscode-html-languageservice@5.5.1", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-/ZdEtsZ3OiFSyL00kmmu7crFV9KwWR+MgpzjsxO60DQH7sIfHZM892C/E4iDd11EKocr+NYuvOA4Y7uc3QzLEA=="], + + "vscode-json-languageservice": ["vscode-json-languageservice@5.6.1", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "jsonc-parser": "^3.3.1", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-IQIURBF2VMKBdWcMunbHSI3G2WmJ9H7613E1hRxIXX7YsAPSdBxnEiIUrTnsSW/3fk+QW1kfsvSigqgAFYIYtg=="], + + "vscode-jsonrpc": ["vscode-jsonrpc@9.0.0-next.9", "", {}, "sha512-IM/RHL7ZklEUh1N2Rh4OjRL6D9MyIXq3v+zIkPLXq74hM1eW7WRLP0/cjzNu/baRFC00sFxJm95RBKsT8dXzRQ=="], + + "vscode-langservers-extracted": ["vscode-langservers-extracted@4.10.0", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "core-js": "^3.20.1", "jsonc-parser": "^3.2.1", "regenerator-runtime": "^0.13.9", "request-light": "^0.7.0", "semver": "^7.6.1", "typescript": "^4.0.5", "vscode-css-languageservice": "^6.2.14", "vscode-html-languageservice": "^5.2.0", "vscode-json-languageservice": "^5.3.11", "vscode-languageserver": "^10.0.0-next.3", "vscode-languageserver-textdocument": "^1.0.11", "vscode-languageserver-types": "^3.17.5", "vscode-markdown-languageservice": "^0.5.0-alpha.6", "vscode-nls": "^5.2.0", "vscode-uri": "^3.0.8" }, "bin": { "vscode-css-language-server": "bin/vscode-css-language-server", "vscode-eslint-language-server": "bin/vscode-eslint-language-server", "vscode-html-language-server": "bin/vscode-html-language-server", "vscode-json-language-server": "bin/vscode-json-language-server", "vscode-markdown-language-server": "bin/vscode-markdown-language-server" } }, "sha512-EFf9uQI4dAKbzMQFjDvVm1xJq1DXAQvBEuEfPGrK/xzfsL5xWTfIuRr90NgfmqwO+IEt6vLZm9EOj6R66xIifg=="], + + "vscode-languageserver": ["vscode-languageserver@10.0.0-next.14", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.6-next.14" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-1TqBDfRLlAIPs6MR5ISI8z7sWlvGL3oHGm9GAHLNOmBZ2+9pmw0yR9vB44/SYuU4bSizxU24tXDFW+rw9jek4A=="], + + "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.6-next.14", "", { "dependencies": { "vscode-jsonrpc": "9.0.0-next.9", "vscode-languageserver-types": "3.17.6-next.6" } }, "sha512-0VD83wxN5kI9vgeaIDQnAxgrbZfKiFNIxdFY5LKe3SZdZd+LAJLMrklSrwfefS7hEzaHw6Z++VFdVJJU+gh1Zg=="], + + "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="], + + "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], + + "vscode-markdown-languageservice": ["vscode-markdown-languageservice@0.5.0-alpha.11", "", { "dependencies": { "@vscode/l10n": "^0.0.10", "node-html-parser": "^6.1.5", "picomatch": "^2.3.1", "vscode-languageserver-protocol": "^3.17.1", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.7" } }, "sha512-P1uBMAD5iylgpcweWCU1kQwk8SZngktnljXsZk1vFPorXv1mrEI7BkBpOUU0fhVssKgvFlCNLkI7KmwZLC7pdA=="], + + "vscode-nls": ["vscode-nls@5.2.0", "", {}, "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng=="], + + "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + + "glob/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "vscode-langservers-extracted/typescript": ["typescript@4.9.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="], + + "vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.17.6-next.6", "", {}, "sha512-aiJY5/yW+xzw7KPNlwi3gQtddq/3EIn5z8X8nCgJfaiAij2R1APKePngv+MUdLdYJBVTLu+Qa0ODsT+pHgYguQ=="], + + "vscode-markdown-languageservice/@vscode/l10n": ["@vscode/l10n@0.0.10", "", {}, "sha512-E1OCmDcDWa0Ya7vtSjp/XfHFGqYJfh+YPC1RkATU71fTac+j1JjCcB3qwSzmlKAighx2WxhLlfhS0RwAN++PFQ=="], + + "vscode-markdown-languageservice/vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "vscode-markdown-languageservice/vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + } +} diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 74077fd..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: "3" -services: - boring: - build: . - volumes: - - .:/code/ diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000..3fde38d --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from "eslint/config"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; + +export default defineConfig([ + { + files: ["**/*.ts"], + rules: { + "prettier/prettier": [ + "error", + {}, + { + usePrettierrc: true, + }, + ], + }, + }, + eslintPluginPrettierRecommended, +]); diff --git a/package.json b/package.json new file mode 100644 index 0000000..4bb68a7 --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "boringlang", + "description": "The Boring programming language", + "private": true, + "author": "Andrew Segavac", + "homepage": "https://code.buildbetter.boats/asegavac/boringlang", + "repository": { + "type": "git", + "url": "ssh://gitea@code.buildbetter.boats:2282/asegavac/boringlang.git" + }, + "scripts": { + "build": "bun run --filter 'boringlang' build", + "format": "bun run prettier **/*.ts", + "type-check": "bun run tsc --noEmit", + "check": "bun run format -- --check && bun run type-check" + }, + "devDependencies": { + "@types/bun": "latest", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "jiti": "^2.5.1", + "prettier": "^3.6.2", + "typescript": "^5.9.2", + "typescript-language-server": "^4.4.0", + "vscode-langservers-extracted": "^4.10.0" + }, + "workspaces": ["packages/*"], + "dependencies": { + "ohm-js": "^17.2.1" + } +} diff --git a/packages/boringlang/package.json b/packages/boringlang/package.json new file mode 100644 index 0000000..a363ada --- /dev/null +++ b/packages/boringlang/package.json @@ -0,0 +1,26 @@ +{ + "name": "boringlang", + "version": "0.1.0", + "type": "module", + "description": "The Boring programming language CLI", + "author": "Andrew Segavac", + "homepage": "https://code.buildbetter.boats/asegavac/boringlang", + "repository": { + "type": "git", + "url": "ssh://gitea@code.buildbetter.boats:2282/asegavac/boringlang.git" + }, + "scripts": { + "dev": "bun run src/index.ts", + "build": "bun build ./src/index.ts --outfile dist/boringlang --compile", + "test": "bun test", + "type-check": "tsc --noEmit", + }, + "dependencies": { + "@bunli/core": "latest", + }, + "devDependencies": { + "@bunli/test": "latest", + "@types/bun": "latest", + "bunli": "latest" + } +} diff --git a/packages/boringlang/src/index.ts b/packages/boringlang/src/index.ts new file mode 100644 index 0000000..b3b20f5 --- /dev/null +++ b/packages/boringlang/src/index.ts @@ -0,0 +1,11 @@ +#!/usr/bin/env bun +import { createCLI } from "@bunli/core"; + +const cli = createCLI({ + name: "boringlang", + version: "0.1.0", + description: "Boring programming language CLI", +}); + + +await cli.run(); diff --git a/packages/boringlang/tsconfig.json b/packages/boringlang/tsconfig.json new file mode 100644 index 0000000..061cf8c --- /dev/null +++ b/packages/boringlang/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "outDir": "./dist", + "rootDir": "./src", + "types": ["bun-types"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "test/**/*"] +} \ No newline at end of file diff --git a/prettier.config.ts b/prettier.config.ts new file mode 100644 index 0000000..40065a0 --- /dev/null +++ b/prettier.config.ts @@ -0,0 +1,10 @@ +import { type Config } from "prettier"; + +const config: Config = { + trailingComma: "all", + singleQuote: false, + printWidth: 80, + semi: true, +}; + +export default config; diff --git a/src/ast.rs b/src/ast.rs deleted file mode 100644 index ac683fa..0000000 --- a/src/ast.rs +++ /dev/null @@ -1,410 +0,0 @@ -use std::cell::RefCell; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct IdGenerator { - id_key: String, - counter: RefCell, -} - -impl IdGenerator { - pub fn new(key: &str) -> Self { - IdGenerator { - id_key: key.to_string(), - counter: RefCell::new(0), - } - } - - pub fn next(&self) -> String { - *self.counter.borrow_mut() += 1; - (self.id_key.to_owned() + &self.counter.borrow().to_string()).to_string() - } -} - -pub fn new_unit() -> TypeUsage { - TypeUsage::Named(NamedTypeUsage { - type_parameters: GenericUsage::Known(GenericInstantiation { parameters: vec![] }), - name: Identifier { - name: Spanned { - span: Span { left: 0, right: 0 }, //todo: figure out a sane value for these - value: "unit".to_string(), - }, - }, - }) -} - -pub fn new_never() -> TypeUsage { - TypeUsage::Named(NamedTypeUsage { - type_parameters: GenericUsage::Known(GenericInstantiation { parameters: vec![] }), - name: Identifier { - name: Spanned { - span: Span { left: 0, right: 0 }, //todo: figure out a sane value for these - value: "!".to_string(), - }, - }, - }) -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Span { - pub left: usize, - pub right: usize, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Spanned { - pub span: Span, - pub value: T, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FunctionTypeUsage { - pub arguments: Vec, - pub return_type: Box, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct NamedTypeUsage { - pub type_parameters: GenericUsage, - pub name: Identifier, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct UnknownTypeUsage { - pub name: String, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum NamespaceTypeUsage { - Type(NamedTypeUsage), // Module -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum TypeUsage { - Function(FunctionTypeUsage), - Named(NamedTypeUsage), - Unknown(UnknownTypeUsage), - Namespace(NamespaceTypeUsage), -} - -impl TypeUsage { - pub fn new_unknown(id_gen: &IdGenerator) -> TypeUsage { - return TypeUsage::Unknown(UnknownTypeUsage { name: id_gen.next() }); - } - - pub fn new_named(identifier: &Identifier, generic_usage: &GenericUsage) -> TypeUsage { - return TypeUsage::Named(NamedTypeUsage { - type_parameters: generic_usage.clone(), - name: identifier.clone(), - }); - } - - pub fn new_builtin(name: String) -> TypeUsage { - TypeUsage::Named(NamedTypeUsage { - type_parameters: GenericUsage::Known(GenericInstantiation { parameters: vec![] }), - name: Identifier { - name: Spanned { - span: Span { left: 0, right: 0 }, //todo: figure out a sane value for these - value: name, - }, - }, - }) - } - - pub fn new_function(arg_count: usize, id_gen: &IdGenerator) -> TypeUsage { - return TypeUsage::Function(FunctionTypeUsage { - arguments: (0..arg_count).map(|_| TypeUsage::new_unknown(&id_gen)).collect(), - return_type: Box::new(TypeUsage::new_unknown(&id_gen)), - }); - } - - pub fn replace_type(&self, old: &str, new: &Identifier) -> TypeUsage { - match &self { - TypeUsage::Function(function) => { - return TypeUsage::Function(FunctionTypeUsage { - arguments: function.arguments.iter().map(|arg| arg.replace_type(old, new)).collect(), - return_type: Box::new(function.return_type.replace_type(old, new)), - }); - } - TypeUsage::Named(named) => { - let name = if named.name.name.value == old { - new.clone() - } else { - named.name.clone() - }; - return TypeUsage::Named(NamedTypeUsage { - type_parameters: named.type_parameters.clone(), - name: name, - }); - } - TypeUsage::Namespace(namespace) => return TypeUsage::Namespace(namespace.clone()), - TypeUsage::Unknown(unkown) => return TypeUsage::Unknown(unkown.clone()), - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct GenericParameter { - pub name: Identifier, - pub bounds: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Generic { - pub parameters: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct GenericInstantiation { - pub parameters: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum GenericUsage { - Known(GenericInstantiation), - Unknown, -} - -impl GenericUsage { - pub fn new(type_parameters: &[TypeUsage]) -> Self { - GenericUsage::Known(GenericInstantiation { - parameters: type_parameters.iter().map(|tp| tp.clone()).collect(), - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Operator { - Mul, - Div, - Plus, - Minus, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LiteralInt { - pub value: Spanned, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LiteralFloat { - pub value: Spanned, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LiteralBool { - pub value: Spanned, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LiteralString { - pub value: Spanned, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LiteralStruct { - pub type_parameters: GenericUsage, - pub name: Identifier, - pub fields: Vec<(Identifier, Expression)>, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Identifier { - pub name: Spanned, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FunctionCall { - pub source: Expression, - pub arguments: Vec, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StructGetter { - pub type_parameters: GenericUsage, - pub source: Expression, - pub attribute: Identifier, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Operation { - pub left: Expression, - pub op: Operator, - pub right: Expression, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct VariableUsage { - pub name: Identifier, - pub type_parameters: GenericUsage, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct IfExpression { - pub condition: Expression, - pub block: Block, - pub else_: Option, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Subexpression { - LiteralInt(LiteralInt), - LiteralFloat(LiteralFloat), - LiteralBool(LiteralBool), - LiteralString(LiteralString), - LiteralStruct(LiteralStruct), - FunctionCall(FunctionCall), - VariableUsage(VariableUsage), - If(IfExpression), - StructGetter(StructGetter), - Block(Block), - Op(Operation), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Expression { - pub subexpression: Box, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ReturnStatement { - pub source: Expression, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct LetStatement { - pub variable_name: Identifier, - pub expression: Expression, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum AssignmentTarget { - Variable(VariableUsage), - StructAttr(StructGetter), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct AssignmentStatement { - pub source: AssignmentTarget, - pub expression: Expression, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Statement { - Return(ReturnStatement), - Let(LetStatement), - Assignment(AssignmentStatement), - Expression(Expression), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Block { - pub statements: Vec, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct VariableDeclaration { - pub name: Identifier, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FunctionDeclaration { - pub generic: Generic, - pub name: Identifier, - pub arguments: Vec, - pub return_type: TypeUsage, -} - -impl FunctionDeclaration { - pub fn to_type(&self) -> TypeUsage { - TypeUsage::Function(FunctionTypeUsage { - arguments: self.arguments.iter().map(|arg| arg.type_.clone()).collect(), - return_type: Box::new(self.return_type.clone()), - }) - } - - pub fn to_method_type(&self) -> TypeUsage { - TypeUsage::Function(FunctionTypeUsage { - arguments: self.arguments[1..self.arguments.len()] - .iter() - .map(|arg| arg.type_.clone()) - .collect(), - return_type: Box::new(self.return_type.clone()), - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Function { - pub declaration: FunctionDeclaration, - pub block: Block, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PrimitiveTypeDeclaration { - pub name: String, // cannot be identifier as it's not declared anywhere specific, it's builtins -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StructField { - pub name: Identifier, - pub type_: TypeUsage, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StructTypeDeclaration { - pub generic: Generic, - pub name: Identifier, - pub fields: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum TraitItem { - FunctionDeclaration(FunctionDeclaration), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TraitTypeDeclaration { - pub generic: Generic, - pub name: Identifier, - pub functions: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum TypeDeclaration { - Struct(StructTypeDeclaration), - Primitive(PrimitiveTypeDeclaration), - Trait(TraitTypeDeclaration), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Impl { - pub generic: Generic, - pub struct_: NamedTypeUsage, - pub trait_: Option, - pub functions: Vec, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ModuleItem { - Function(Function), - TypeDeclaration(TypeDeclaration), - Impl(Impl), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Module { - pub items: Vec, -} diff --git a/src/builtins.rs b/src/builtins.rs deleted file mode 100644 index c389d01..0000000 --- a/src/builtins.rs +++ /dev/null @@ -1,3 +0,0 @@ -use std::collections::HashMap; - -use crate::ast; diff --git a/src/compiler.rs b/src/compiler.rs deleted file mode 100644 index 48fc3e0..0000000 --- a/src/compiler.rs +++ /dev/null @@ -1,124 +0,0 @@ -use inkwell::builder::Builder; -use inkwell::context::Context; -use inkwell::module::Module; -use inkwell::values::{BasicValueEnum, FunctionValue, IntValue}; -use std::collections::HashMap; -use std::convert::TryInto; -use std::mem; - -use crate::ast; - -type Scope<'ctx> = HashMap>; - -pub struct ModuleCodeGen<'ctx> { - context: &'ctx Context, - module: Module<'ctx>, - builder: Builder<'ctx>, - scope: Scope<'ctx>, -} - -impl<'ctx> ModuleCodeGen<'ctx> { - pub fn new(context: &'ctx Context, name: String) -> Self { - return ModuleCodeGen { - context: context, - module: context.create_module(&name), - builder: context.create_builder(), - scope: Scope::new(), - }; - } - - pub fn gen_literal_int(&mut self, literal_int: &ast::LiteralInt) -> IntValue<'ctx> { - self.context - .i64_type() - .const_int(unsafe { mem::transmute::(literal_int.value) }, true) - } - - pub fn gen_op_expression(&mut self, scope: &Scope<'ctx>, operation: &ast::Operation) -> IntValue<'ctx> { - let lhs_result = self.gen_expression(scope, &operation.left); - let rhs_result = self.gen_expression(scope, &operation.right); - self.gen_op_int(&lhs_result, &rhs_result, &operation.op) - } - - pub fn gen_op_int(&mut self, lhs: &IntValue<'ctx>, rhs: &IntValue<'ctx>, op: &ast::Operator) -> IntValue<'ctx> { - match *op { - ast::Operator::Plus => self.builder.build_int_add(*lhs, *rhs, "add"), - ast::Operator::Minus => self.builder.build_int_sub(*lhs, *rhs, "sub"), - ast::Operator::Mul => self.builder.build_int_mul(*lhs, *rhs, "mul"), - ast::Operator::Div => self.builder.build_int_signed_div(*lhs, *rhs, "div"), - } - } - - pub fn gen_expression(&mut self, scope: &Scope<'ctx>, expression: &Box) -> IntValue<'ctx> { - match &**expression { - ast::Expression::LiteralInt(literal_int) => self.gen_literal_int(&literal_int), - ast::Expression::Identifier(identifier) => match scope[&identifier.name] { - BasicValueEnum::IntValue(value) => value, - _ => panic!("function returned type other than int, no types yet"), - }, - ast::Expression::FunctionCall(function_call) => self.gen_function_call(scope, &function_call), - ast::Expression::Op(operation) => self.gen_op_expression(scope, &operation), - } - } - - pub fn gen_function_call(&mut self, scope: &Scope<'ctx>, function_call: &ast::FunctionCall) -> IntValue<'ctx> { - let fn_value = self.module.get_function(&function_call.name.name).unwrap(); - let mut arguments = Vec::new(); - for expression in (&function_call.arguments).into_iter() { - arguments.push(BasicValueEnum::IntValue(self.gen_expression(scope, &expression))); - } - - let result = self - .builder - .build_call(fn_value, &arguments, &function_call.name.name) - .try_as_basic_value() - .left() - .unwrap(); - match result { - BasicValueEnum::IntValue(value) => value, - _ => panic!("function returned type other than int, no types yet"), - } - } - - // Generates a FunctionValue for an `ast::Function`. This does not genereate a body, - // that task is left to the `gen_function` function. The reason this is split - // between two functions is that first all signatures are generated and then all bodies. This - // allows bodies to reference `FunctionValue` wherever they are declared in the file. - pub fn gen_signature(&mut self, function: &ast::Function) -> FunctionValue { - let mut args = Vec::new(); - for _ in &function.arguments { - args.push(self.context.i64_type().into()); - } - let fn_type = self.context.i64_type().fn_type(&args, false); - let fn_value = self.module.add_function(&function.name.name, fn_type, None); - fn_value - } - - pub fn gen_function(&mut self, function: &ast::Function) { - let fn_value = self.module.get_function(&function.name.name).unwrap(); - let basic_block = self.context.append_basic_block(fn_value, "entry"); - - self.builder.position_at_end(basic_block); - - let mut scope = self.scope.clone(); - for (i, param) in (&function.arguments).into_iter().enumerate() { - scope.insert(param.name.name.to_string(), fn_value.get_nth_param(i.try_into().unwrap()).unwrap()); - } - let body = &function.block; - let return_value = self.gen_expression(&scope, &body.expression); - self.builder.build_return(Some(&return_value)); - } - - pub fn gen_module(&mut self, module: ast::Module) { - // generate all signatures before the fuction bodies - for function in &module.functions { - self.gen_signature(&function); - } - for function in module.functions { - self.gen_function(&function); - } - } - - pub fn dump(&self) -> String { - self.module.print_to_string().to_string() - } -} diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 0a0c20d..0000000 --- a/src/errors.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::ast; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum TypingError { - #[error("unknown named type")] - TypeDoesNotExist { identifier: ast::Identifier }, - #[error("identifier is not type")] - IdentifierIsNotType { identifier: ast::Identifier }, - #[error("argument length mismatch")] - ArgumentLengthMismatch { - // TODO: add position - }, - #[error("type mismatch")] - TypeMismatch { - type_one: ast::TypeUsage, - type_two: ast::TypeUsage, - }, - #[error("unknown field name")] - UnknownFieldName { identifier: ast::Identifier }, - #[error("cannot assign to method")] - CannotAssignToMethod { identifier: ast::Identifier }, - #[error("multiple field name matches")] - MultipleFieldName { identifier: ast::Identifier }, - #[error("attribute gotten of non-struct")] - AttributeOfNonstruct { identifier: ast::Identifier }, - #[error("name is not a struct, cannot instaniate")] - NotAStructLiteral { identifier: ast::Identifier }, - #[error("struct literal fields mismatch")] - StructLiteralFieldsMismatch { struct_name: ast::Identifier }, - #[error("missing trait function")] - MissingTraitFunction { - struct_name: ast::Identifier, - function_name: ast::Identifier, - }, - #[error("function not in trait")] - FunctionNotInTrait { function_name: ast::Identifier }, - #[error("impl trait must be trait")] - ImplTraitMustBeTrait { trait_name: ast::Identifier }, - #[error("function call used with non-function")] - FunctionCallNotAFunction { - // TODO: add position - }, - #[error("`if` condition must be bool")] - IfConditionMustBeBool { - // TODO: add position - }, - #[error("cannot use type as an expression")] - TypeIsNotAnExpression { type_name: ast::Identifier }, - #[error("wrong number of type parameters")] - WrongNumberOfTypeParameters { - // TODO: add position - }, - #[error("invalid use of alias")] - InvalidUseofAlias, - #[error("alias cannot have type parameters")] - InvalidTypeParameterOnAlias { - alias: ast::Identifier, - }, - #[error("type cannot be used for generic")] - InvalidTypeForGeneric, - #[error("multiple errors")] - MultipleErrors { errors: Vec }, -} diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop deleted file mode 100644 index 47a16d0..0000000 --- a/src/grammar.lalrpop +++ /dev/null @@ -1,352 +0,0 @@ -use crate::ast; - -grammar(id_generator: &ast::IdGenerator); - -match { - r"[0-9]+", - r"[0-9]+\.[0-9]+", - r"[A-Za-z_][A-Za-z0-9_]*", - ":", - ";", - "{", - "}", - "(", - ")", - "[", - "]", - "", - ".", - "+", - "-", - "*", - "/", - "fn", - "return", - "let", - "true", - "false", - "if", - "else", - "=", - "for", - "type", - "trait", - "struct", - "impl", - ",", - r"'(\\'|[^'])*'", - r#""(\\"|[^"])*""#, - - r"\s*" => { }, - r"//[^\n\r]*[\n\r]*" => { }, // `// comment` -} - - -pub LiteralInt: String = { - => literal.to_string() -}; - -pub SpannedLiteralInt: ast::LiteralInt = { - > => ast::LiteralInt{value: literal_int, type_: ast::TypeUsage::new_builtin("i64".to_string())} -}; - -pub LiteralFloat: String = { - => literal.to_string() -}; - -pub SpannedLiteralFloat: ast::LiteralFloat = { - > => ast::LiteralFloat{value: literal_float, type_: ast::TypeUsage::new_builtin("f64".to_string())} -}; - -pub LiteralBool: String = { - "true" => "true".to_string(), - "false" => "false".to_string(), -}; - -pub SpannedLiteralBool: ast::LiteralBool = { - > => ast::LiteralBool{value: literal_bool, type_: ast::TypeUsage::new_builtin("bool".to_string())} -}; - -pub LiteralString: String = { - => String::from(&s[1..s.len()-1]), - => String::from(&s[1..s.len()-1]), -}; - -pub SpannedLiteralString: ast::LiteralString = { - > => ast::LiteralString{value: literal_string, type_: ast::TypeUsage::new_builtin("String".to_string())} -}; - - -pub Identifier: String = { - => i.to_string() -}; - -pub GenericUsage: ast::GenericUsage = { - "[" > "]" => ast::GenericUsage::new(&tp), -}; - -pub LiteralStructField: (ast::Identifier, ast::Expression) = { - ":" => (field, expr) -}; - -pub LiteralStruct: ast::LiteralStruct = { - "{" > "}" => { - match gu { - Some(tp) => { - ast::LiteralStruct{ - type_parameters: tp.clone(), - name: i.clone(), - fields: field_list, - type_: ast::TypeUsage::new_named(&i, &tp), - } - }, - None => { - ast::LiteralStruct{ - type_parameters: ast::GenericUsage::new(&[]), - name: i.clone(), - fields: field_list, - type_: ast::TypeUsage::new_named(&i, &ast::GenericUsage::new(&[])), - } - } - } - } -}; - -pub SpannedIdentifier: ast::Identifier = { - > => ast::Identifier{name: i} -}; - -pub FunctionCall: ast::FunctionCall = { - "(" > ")" => ast::FunctionCall{source: source, arguments: args, type_: ast::TypeUsage::new_unknown(&id_generator)} -}; - -pub StructGetter: ast::StructGetter = { - "." => match gu { - Some(tp) => ast::StructGetter{type_parameters: tp, source: source, attribute: field, type_: ast::TypeUsage::new_unknown(&id_generator)}, - None => ast::StructGetter{type_parameters: ast::GenericUsage::Unknown, source: source, attribute: field, type_: ast::TypeUsage::new_unknown(&id_generator)}, - } -}; - -pub VariableUsage: ast::VariableUsage = { - => match gu { - Some(tp) => ast::VariableUsage{name: identifier, type_parameters: tp.clone(), type_: ast::TypeUsage::new_unknown(&id_generator)}, - None => ast::VariableUsage{name: identifier, type_parameters: ast::GenericUsage::Unknown, type_: ast::TypeUsage::new_unknown(&id_generator)}, - } -}; - -pub IfExpression: ast::IfExpression = { - "if" "("")" => ast::IfExpression{condition: c, block: b, else_: None, type_: ast::TypeUsage::new_unknown(&id_generator)}, - "if" "("")" "else" => ast::IfExpression{condition: c, block: b, else_: Some(e), type_: ast::TypeUsage::new_unknown(&id_generator)}, -}; - -pub Expression: ast::Expression = { - "+" => { - ast::Expression{ - subexpression: Box::new(ast::Subexpression::Op(ast::Operation{left: l, op: ast::Operator::Plus, right: r})), - type_: ast::TypeUsage::new_unknown(&id_generator), - } - }, - "-" => { - ast::Expression{ - subexpression: Box::new(ast::Subexpression::Op(ast::Operation{left: l, op: ast::Operator::Minus, right: r})), - type_: ast::TypeUsage::new_unknown(&id_generator), - } - }, - Factor, -}; - -pub Factor: ast::Expression = { - "*" => { - ast::Expression{ - subexpression: Box::new(ast::Subexpression::Op(ast::Operation{left: l, op: ast::Operator::Mul, right: r})), - type_: ast::TypeUsage::new_unknown(&id_generator), - } - }, - "/" => { - ast::Expression{ - subexpression: Box::new(ast::Subexpression::Op(ast::Operation{left: l, op: ast::Operator::Div, right: r})), - type_: ast::TypeUsage::new_unknown(&id_generator), - } - }, - Term, -}; - -pub Term: ast::Expression = { - SpannedLiteralInt => ast::Expression{subexpression: Box::new(ast::Subexpression::LiteralInt(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - SpannedLiteralFloat => ast::Expression{subexpression: Box::new(ast::Subexpression::LiteralFloat(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - SpannedLiteralBool => ast::Expression{subexpression: Box::new(ast::Subexpression::LiteralBool(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - SpannedLiteralString => ast::Expression{subexpression: Box::new(ast::Subexpression::LiteralString(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - LiteralStruct => ast::Expression{subexpression: Box::new(ast::Subexpression::LiteralStruct(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - FunctionCall => ast::Expression{subexpression: Box::new(ast::Subexpression::FunctionCall(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - StructGetter => ast::Expression{subexpression: Box::new(ast::Subexpression::StructGetter(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - VariableUsage => ast::Expression{subexpression: Box::new(ast::Subexpression::VariableUsage(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - IfExpression => ast::Expression{subexpression: Box::new(ast::Subexpression::If(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - Block => ast::Expression{subexpression: Box::new(ast::Subexpression::Block(<>)), type_: ast::TypeUsage::new_unknown(&id_generator)}, - "(" ")" => e, -}; - - -pub ReturnStatement: ast::ReturnStatement = { - "return" => ast::ReturnStatement{source: e} -}; - -pub LetStatement: ast::LetStatement = { - //TODO: support destructuring with tuples, when they exist. - //TODO: add mut, weak - "let" "=" => ast::LetStatement{variable_name: n, type_: ast::TypeUsage::new_unknown(&id_generator), expression: e}, - "let" ":" "=" => ast::LetStatement{variable_name: n, type_: t, expression: e}, -}; - -pub AssignmentStatement: ast::AssignmentStatement = { - "=" => ast::AssignmentStatement{source: ast::AssignmentTarget::Variable(v), expression: e}, - "=" => ast::AssignmentStatement{source: ast::AssignmentTarget::StructAttr(sg), expression: e}, -}; - -pub Statement: ast::Statement = { - ";" => ast::Statement::Return(r), - ";" => ast::Statement::Let(l), - ";" => ast::Statement::Assignment(a), - ";" => ast::Statement::Expression(e), -}; - -pub Block: ast::Block = { - "{" )*> "}" => match e { - None => ast::Block{statements: v, type_: ast::TypeUsage::new_unknown(&id_generator)}, - Some(e) => { - let mut v = v; - v.push(ast::Statement::Expression(e)); - ast::Block{statements: v, type_: ast::TypeUsage::new_unknown(&id_generator)} - } - } -}; - -pub PartialNamedTypeUsage: ast::NamedTypeUsage = { - => match gu { - Some(tp) => ast::NamedTypeUsage{type_parameters: tp, name: n}, - None => ast::NamedTypeUsage{type_parameters: ast::GenericUsage::Unknown, name: n}, - }, -}; - -pub NamedTypeUsage: ast::NamedTypeUsage = { - => match gu { - Some(tp) => ast::NamedTypeUsage{type_parameters: tp, name: n}, - None => ast::NamedTypeUsage{type_parameters: ast::GenericUsage::new(&[]), name: n}, - }, -}; - -pub PartialTypeUsage: ast::TypeUsage = { - => ast::TypeUsage::Named(n), - "fn" "(" > ")" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: Box::new(ast::new_unit())}), - "fn" "(" > ")" ":" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: Box::new(rt)}), -}; - -pub TypeUsage: ast::TypeUsage = { - => ast::TypeUsage::Named(n), - "fn" "(" > ")" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: Box::new(ast::new_unit())}), - "fn" "(" > ")" ":" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: Box::new(rt)}), -}; - -pub VariableDeclaration: ast::VariableDeclaration = { - ":" => ast::VariableDeclaration{name: i, type_: t}, -}; - -pub GenericParameter: ast::GenericParameter = { - => ast::GenericParameter{name: i, bounds: vec!()}, - ":" > => ast::GenericParameter{name: i, bounds: bounds}, -}; - -pub Generic: ast::Generic = { - "[" > "]" => ast::Generic{parameters: p}, -}; - -pub FunctionDeclaration: ast::FunctionDeclaration = { - "fn" "(" > ")" => ast::FunctionDeclaration{name: n, generic: g, arguments: args, return_type: ast::new_unit()}, - "fn" "(" > ")" ":" => ast::FunctionDeclaration{name: n, generic: g, arguments: args, return_type: rt}, - "fn" "(" > ")" => ast::FunctionDeclaration{name: n, generic: ast::Generic{parameters: vec!()}, arguments: args, return_type: ast::new_unit()}, - "fn" "(" > ")" ":" => ast::FunctionDeclaration{name: n, generic: ast::Generic{parameters: vec!()}, arguments: args, return_type: rt}, -}; - -pub Function: ast::Function = { - => ast::Function{declaration: d, block: b} -}; - -pub StructField: ast::StructField = { - ":" => ast::StructField{name: i, type_: t}, -}; - -pub StructTypeDeclaration: ast::StructTypeDeclaration = { - "type" "struct" "{" > "}" => match g { - Some(generic) => ast::StructTypeDeclaration{name: i, generic: generic, fields: f}, - None => ast::StructTypeDeclaration{name: i, generic: ast::Generic{parameters: vec!()}, fields: f}, - } -}; - -pub TraitItem: ast::TraitItem = { - ";" => ast::TraitItem::FunctionDeclaration(fd), -}; - -pub TraitTypeDeclaration: ast::TraitTypeDeclaration = { - "type" "trait" "{" "}" => ast::TraitTypeDeclaration{name: i, generic: g, functions: ti}, - "type" "trait" "{" "}" => ast::TraitTypeDeclaration{name: i, generic: ast::Generic{parameters: vec!()}, functions: ti}, -}; - -pub TypeDeclaration: ast::TypeDeclaration = { - => ast::TypeDeclaration::Struct(s), - => ast::TypeDeclaration::Trait(t), -}; - -pub Impl: ast::Impl = { - "impl" "{" "}" => { - let generic = match g { - Some(g) => g, - None => ast::Generic{parameters: vec!()}, - }; - ast::Impl{generic: generic, trait_: None, struct_: s, functions: f} - }, - "impl" "for" "{" "}" => { - let generic = match g { - Some(g) => g, - None => ast::Generic{parameters: vec!()}, - }; - ast::Impl{generic: generic, trait_: Some(t), struct_: s, functions: f} - } -}; - -pub ModuleItem: ast::ModuleItem = { - => ast::ModuleItem::Function(f), - => ast::ModuleItem::TypeDeclaration(td), - => ast::ModuleItem::Impl(i), -}; - -pub Module: ast::Module = { - => ast::Module{items: i} -}; - -// From https://lalrpop.github.io/lalrpop/tutorial/006_macros.html -// Comma separated list of T with optional trailing comma -Comma: Vec = { - ",")*> => match e { - None => v, - Some(e) => { - let mut v = v; - v.push(e); - v - } - } -}; - -// PlusSeparated separated list of T with optional trailing comma -PlusSeparated: Vec = { - "+")*> => match e { - None => v, - Some(e) => { - let mut v = v; - v.push(e); - v - } - } -}; - -Spanned: ast::Spanned = { - => ast::Spanned{span: ast::Span{left: l, right: r}, value: rule} -}; diff --git a/src/interpreter.rs b/src/interpreter.rs deleted file mode 100644 index bd5541c..0000000 --- a/src/interpreter.rs +++ /dev/null @@ -1,654 +0,0 @@ -use crate::ast; -use std::collections::HashMap; -use std::sync::{Arc, Mutex}; - -#[derive(Debug, Clone)] -pub enum NumericValue { - I8(i8), - I16(i16), - I32(i32), - I64(i64), - ISize(isize), - - U8(u8), - U16(u16), - U32(u32), - U64(u64), - USize(usize), - - F32(f32), - F64(f64), -} - -#[derive(Debug, Clone)] -pub struct StructValue { - source: ast::StructTypeDeclaration, - fields: HashMap, -} - -type BuiltinFunction = fn(Vec) -> Value; - -#[derive(Debug, Clone)] -pub enum FunctionRef { - User(ast::Function), - Builtin(BuiltinFunction), -} - -#[derive(Debug, Clone)] -pub struct Function { - pub partial: Vec, - pub ref_: FunctionRef, -} - -#[derive(Debug, Clone)] -pub enum Value { - Numeric(NumericValue), - Bool(bool), - String(String), - Function(Function), - Struct(Arc>), - Unit, -} - -#[derive(Debug, Clone)] -pub enum NamedEntity { - TypeDeclaration(ast::TypeDeclaration), - Variable(Value), -} - -#[derive(Debug, Clone)] -struct Context { - pub environment: HashMap, - pub impls: HashMap, - pub current_module: ast::Module, -} - -impl Context { - fn set_variable(&mut self, name: String, value: &Value) { - self.environment.insert(name.to_string(), NamedEntity::Variable(value.clone())); - } - - fn new_env(&self) -> Context { - return Context::from_module(&self.current_module); - } - - fn from_module(module: &ast::Module) -> Context { - let mut ctx = Context { - environment: create_builtins(), - impls: HashMap::new(), - current_module: module.clone(), - }; - - for item in ctx.current_module.items.iter() { - match item { - ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Struct(struct_)) => { - ctx.environment.insert( - struct_.name.name.value.to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Struct(struct_.clone())), - ); - } - ast::ModuleItem::Function(function) => { - ctx.environment.insert( - function.declaration.name.name.value.to_string(), - NamedEntity::Variable(Value::Function(Function { - partial: vec![], - ref_: FunctionRef::User(function.clone()), - })), - ); - } - ast::ModuleItem::Impl(impl_) => { - ctx.impls.insert(impl_.struct_.name.name.value.to_string(), impl_.clone()); - } - _ => {} - } - } - return ctx; - } -} - -fn create_builtins() -> HashMap { - let mut result = HashMap::new(); - result.insert( - "i8".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "i8".to_string(), - })), - ); - result.insert( - "i16".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "i16".to_string(), - })), - ); - result.insert( - "i32".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "i32".to_string(), - })), - ); - result.insert( - "i64".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "i64".to_string(), - })), - ); - result.insert( - "isize".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "isize".to_string(), - })), - ); - - result.insert( - "u8".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "u8".to_string(), - })), - ); - result.insert( - "u16".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "u16".to_string(), - })), - ); - result.insert( - "u32".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "u32".to_string(), - })), - ); - result.insert( - "u64".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "u64".to_string(), - })), - ); - result.insert( - "usize".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "usize".to_string(), - })), - ); - - result.insert( - "f32".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "f32".to_string(), - })), - ); - result.insert( - "f64".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "f64".to_string(), - })), - ); - - result.insert( - "bool".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "bool".to_string(), - })), - ); - - result.insert( - "!".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "!".to_string(), - })), - ); - result.insert( - "unit".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "!".to_string(), - })), - ); - result.insert( - "String".to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Primitive(ast::PrimitiveTypeDeclaration { - name: "String".to_string(), - })), - ); - - return result; -} - -pub enum ExpressionResult { - Value(Value), - Return(Value), -} - -pub struct TreeWalkInterpreter {} - -impl TreeWalkInterpreter { - pub fn with_module(self: &Self, module: &ast::Module) -> Value { - let mut ctx = Context::from_module(module); - - let main = match &ctx.environment["main"] { - NamedEntity::Variable(Value::Function(func)) => match &func.ref_ { - FunctionRef::User(ref_) => ref_.clone(), - _ => panic!("main should be a user defined function"), - }, - _ => panic!("main should be a user defined function"), - }; - - return self.with_function(&mut ctx, &main); - } - - fn with_function(self: &Self, ctx: &mut Context, function: &ast::Function) -> Value { - let result = self.with_block(ctx, &function.block); - return match result { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => r, - }; - } - - fn with_block(self: &Self, ctx: &mut Context, block: &ast::Block) -> ExpressionResult { - let mut last = ExpressionResult::Value(Value::Unit); - for statement in block.statements.iter() { - let result = self.with_statement(ctx, statement); - match result { - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - ExpressionResult::Value(r) => { - last = ExpressionResult::Value(r); - } - } - } - return last; - } - - fn with_statement(self: &Self, ctx: &mut Context, statement: &ast::Statement) -> ExpressionResult { - match statement { - ast::Statement::Return(return_statement) => { - let result = match self.with_expression(ctx, &return_statement.source) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - return ExpressionResult::Return(result); - } - ast::Statement::Let(let_statement) => { - let result = match self.with_expression(ctx, &let_statement.expression) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - ctx.set_variable(let_statement.variable_name.name.value.to_string(), &result); - return ExpressionResult::Value(Value::Unit); - } - ast::Statement::Assignment(assignment_statement) => { - return self.with_assignment_statement(ctx, assignment_statement); - } - ast::Statement::Expression(expression) => { - return self.with_expression(ctx, expression); - } - } - } - - fn with_assignment_statement(self: &Self, ctx: &mut Context, statement: &ast::AssignmentStatement) -> ExpressionResult { - let result = match self.with_expression(ctx, &statement.expression) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - match &statement.source { - ast::AssignmentTarget::Variable(variable) => { - ctx.set_variable(variable.name.name.value.to_string(), &result); - } - ast::AssignmentTarget::StructAttr(struct_attr) => { - let mut source = match self.with_expression(ctx, &struct_attr.source) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - match &mut source { - Value::Struct(s) => { - let mut struct_ = s.lock().unwrap(); - struct_.fields.insert(struct_attr.attribute.name.value.clone(), result); - } - _ => panic!("set attr on nonstruct, should never happen due to type system"), - } - } - } - return ExpressionResult::Value(Value::Unit); - } - - fn with_expression(self: &Self, ctx: &mut Context, expression: &ast::Expression) -> ExpressionResult { - match &*expression.subexpression { - ast::Subexpression::LiteralInt(literal_int) => { - let value: i64 = literal_int.value.value.parse().unwrap(); - return ExpressionResult::Value(Value::Numeric(NumericValue::I64(value))); - } - ast::Subexpression::LiteralFloat(literal_float) => { - let value: f64 = literal_float.value.value.parse().unwrap(); - return ExpressionResult::Value(Value::Numeric(NumericValue::F64(value))); - } - ast::Subexpression::LiteralBool(literal_bool) => { - let value: bool = if &literal_bool.value.value == "true" { true } else { false }; - return ExpressionResult::Value(Value::Bool(value)); - } - ast::Subexpression::LiteralString(literal_string) => { - let value: String = literal_string.value.value.to_string(); - return ExpressionResult::Value(Value::String(value)); - } - ast::Subexpression::LiteralStruct(literal_struct) => { - let declaration = match &ctx.environment[&literal_struct.name.name.value] { - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Struct(declaration)) => declaration.clone(), - _ => panic!("not a struct"), - }; - - let mut fields = HashMap::new(); - for field in declaration.fields.iter() { - for (field_name, field_expression) in literal_struct.fields.iter() { - if field.name.name.value == field_name.name.value { - let field_result = match self.with_expression(ctx, field_expression) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - fields.insert(field.name.name.value.to_string(), field_result); - } - } - } - return ExpressionResult::Value(Value::Struct(Arc::new(Mutex::new(StructValue { - source: declaration.clone(), - fields: fields, - })))); - } - ast::Subexpression::FunctionCall(function_call) => { - let source = match self.with_expression(ctx, &function_call.source) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - let mut argument_values = vec![]; - for arg in function_call.arguments.iter() { - let argument_value = match self.with_expression(ctx, arg) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - argument_values.push(argument_value); - } - match &source { - Value::Function(function) => match &function.ref_ { - FunctionRef::User(user_function) => { - let mut fn_ctx = ctx.new_env(); - let mut i = 0; - for partial_arg in &function.partial { - fn_ctx.set_variable( - user_function.declaration.arguments[i].name.name.value.to_string(), - &partial_arg.clone(), - ); - i = i + 1; - } - for argument_value in &argument_values { - fn_ctx.set_variable( - user_function.declaration.arguments[i].name.name.value.to_string(), - &argument_value.clone(), - ); - } - return ExpressionResult::Value(self.with_function(&mut fn_ctx, user_function)); - } - FunctionRef::Builtin(builtin_function) => { - let all_values = function - .partial - .iter() - .map(|val| val.clone()) - .chain(argument_values.into_iter()) - .collect(); - return ExpressionResult::Value(builtin_function(all_values)); - } - }, - _ => panic!("type error: function call source must be a function"), - } - } - ast::Subexpression::VariableUsage(variable_usage) => { - if !ctx.environment.contains_key(&variable_usage.name.name.value) { - panic!("{}", variable_usage.name.name.value.clone()); - } - let variable_value = match &ctx.environment[&variable_usage.name.name.value] { - NamedEntity::Variable(v) => v.clone(), - _ => panic!("variable lookup of type"), - }; - return ExpressionResult::Value(variable_value); - } - ast::Subexpression::If(if_expression) => { - let condition = match self.with_expression(ctx, &if_expression.condition) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - - match &condition { - Value::Bool(cond) => { - if cond.clone() { - return self.with_block(ctx, &if_expression.block); - } else { - return match &if_expression.else_ { - Some(else_) => self.with_block(ctx, else_), - None => ExpressionResult::Value(Value::Unit), - }; - } - } - _ => panic!("TypeError: condition must be bool"), - } - } - ast::Subexpression::StructGetter(struct_getter) => { - let source = match self.with_expression(ctx, &struct_getter.source) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - match &source { - Value::Struct(struct_) => { - let s = struct_.lock().unwrap(); - if s.fields.contains_key(&struct_getter.attribute.name.value) { - return ExpressionResult::Value(s.fields[&struct_getter.attribute.name.value].clone()); - } - for module_item in &ctx.current_module.items { - match module_item { - ast::ModuleItem::Impl(impl_) => { - if impl_.struct_.name.name.value == s.source.name.name.value { - for method in &impl_.functions { - if method.declaration.name.name.value == struct_getter.attribute.name.value { - // if first type matches, partial apply self - if method.declaration.arguments.len() > 0 { - match &method.declaration.arguments[0].type_ { - ast::TypeUsage::Named(arg_named) => { - if arg_named.name.name.value == "Self" { - return ExpressionResult::Value(Value::Function(Function { - partial: vec![source.clone()], - ref_: FunctionRef::User(method.clone()), - })); - } - } - _ => {} - } - } - return ExpressionResult::Value(Value::Function(Function { - partial: vec![], - ref_: FunctionRef::User(method.clone()), - })); - } - } - } - } - _ => {} - } - } - panic!("TypeError: Method not found"); - } - _ => { - panic!("TypeError: struct getter used with non-struct"); - } - } - } - ast::Subexpression::Block(block) => { - return self.with_block(ctx, block); - } - ast::Subexpression::Op(op) => { - let left = match self.with_expression(ctx, &op.left) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - let right = match self.with_expression(ctx, &op.right) { - ExpressionResult::Value(r) => r, - ExpressionResult::Return(r) => { - return ExpressionResult::Return(r); - } - }; - let result = match (&left, &op.op, &right) { - //I - (Value::Numeric(NumericValue::I8(l)), ast::Operator::Plus, Value::Numeric(NumericValue::I8(r))) => { - Value::Numeric(NumericValue::I8(l + r)) - } - (Value::Numeric(NumericValue::I8(l)), ast::Operator::Minus, Value::Numeric(NumericValue::I8(r))) => { - Value::Numeric(NumericValue::I8(l - r)) - } - (Value::Numeric(NumericValue::I8(l)), ast::Operator::Mul, Value::Numeric(NumericValue::I8(r))) => { - Value::Numeric(NumericValue::I8(l * r)) - } - (Value::Numeric(NumericValue::I8(l)), ast::Operator::Div, Value::Numeric(NumericValue::I8(r))) => { - Value::Numeric(NumericValue::I8(l / r)) - } - - (Value::Numeric(NumericValue::I16(l)), ast::Operator::Plus, Value::Numeric(NumericValue::I16(r))) => { - Value::Numeric(NumericValue::I16(l + r)) - } - (Value::Numeric(NumericValue::I16(l)), ast::Operator::Minus, Value::Numeric(NumericValue::I16(r))) => { - Value::Numeric(NumericValue::I16(l - r)) - } - (Value::Numeric(NumericValue::I16(l)), ast::Operator::Mul, Value::Numeric(NumericValue::I16(r))) => { - Value::Numeric(NumericValue::I16(l * r)) - } - (Value::Numeric(NumericValue::I16(l)), ast::Operator::Div, Value::Numeric(NumericValue::I16(r))) => { - Value::Numeric(NumericValue::I16(l / r)) - } - - (Value::Numeric(NumericValue::I32(l)), ast::Operator::Plus, Value::Numeric(NumericValue::I32(r))) => { - Value::Numeric(NumericValue::I32(l + r)) - } - (Value::Numeric(NumericValue::I32(l)), ast::Operator::Minus, Value::Numeric(NumericValue::I32(r))) => { - Value::Numeric(NumericValue::I32(l - r)) - } - (Value::Numeric(NumericValue::I32(l)), ast::Operator::Mul, Value::Numeric(NumericValue::I32(r))) => { - Value::Numeric(NumericValue::I32(l * r)) - } - (Value::Numeric(NumericValue::I32(l)), ast::Operator::Div, Value::Numeric(NumericValue::I32(r))) => { - Value::Numeric(NumericValue::I32(l / r)) - } - - (Value::Numeric(NumericValue::I64(l)), ast::Operator::Plus, Value::Numeric(NumericValue::I64(r))) => { - Value::Numeric(NumericValue::I64(l + r)) - } - (Value::Numeric(NumericValue::I64(l)), ast::Operator::Minus, Value::Numeric(NumericValue::I64(r))) => { - Value::Numeric(NumericValue::I64(l - r)) - } - (Value::Numeric(NumericValue::I64(l)), ast::Operator::Mul, Value::Numeric(NumericValue::I64(r))) => { - Value::Numeric(NumericValue::I64(l * r)) - } - (Value::Numeric(NumericValue::I64(l)), ast::Operator::Div, Value::Numeric(NumericValue::I64(r))) => { - Value::Numeric(NumericValue::I64(l / r)) - } - - //U - (Value::Numeric(NumericValue::U8(l)), ast::Operator::Plus, Value::Numeric(NumericValue::U8(r))) => { - Value::Numeric(NumericValue::U8(l + r)) - } - (Value::Numeric(NumericValue::U8(l)), ast::Operator::Minus, Value::Numeric(NumericValue::U8(r))) => { - Value::Numeric(NumericValue::U8(l - r)) - } - (Value::Numeric(NumericValue::U8(l)), ast::Operator::Mul, Value::Numeric(NumericValue::U8(r))) => { - Value::Numeric(NumericValue::U8(l * r)) - } - (Value::Numeric(NumericValue::U8(l)), ast::Operator::Div, Value::Numeric(NumericValue::U8(r))) => { - Value::Numeric(NumericValue::U8(l / r)) - } - - (Value::Numeric(NumericValue::U16(l)), ast::Operator::Plus, Value::Numeric(NumericValue::U16(r))) => { - Value::Numeric(NumericValue::U16(l + r)) - } - (Value::Numeric(NumericValue::U16(l)), ast::Operator::Minus, Value::Numeric(NumericValue::U16(r))) => { - Value::Numeric(NumericValue::U16(l - r)) - } - (Value::Numeric(NumericValue::U16(l)), ast::Operator::Mul, Value::Numeric(NumericValue::U16(r))) => { - Value::Numeric(NumericValue::U16(l * r)) - } - (Value::Numeric(NumericValue::U16(l)), ast::Operator::Div, Value::Numeric(NumericValue::U16(r))) => { - Value::Numeric(NumericValue::U16(l / r)) - } - - (Value::Numeric(NumericValue::U32(l)), ast::Operator::Plus, Value::Numeric(NumericValue::U32(r))) => { - Value::Numeric(NumericValue::U32(l + r)) - } - (Value::Numeric(NumericValue::U32(l)), ast::Operator::Minus, Value::Numeric(NumericValue::U32(r))) => { - Value::Numeric(NumericValue::U32(l - r)) - } - (Value::Numeric(NumericValue::U32(l)), ast::Operator::Mul, Value::Numeric(NumericValue::U32(r))) => { - Value::Numeric(NumericValue::U32(l * r)) - } - (Value::Numeric(NumericValue::U32(l)), ast::Operator::Div, Value::Numeric(NumericValue::U32(r))) => { - Value::Numeric(NumericValue::U32(l / r)) - } - - (Value::Numeric(NumericValue::U64(l)), ast::Operator::Plus, Value::Numeric(NumericValue::U64(r))) => { - Value::Numeric(NumericValue::U64(l + r)) - } - (Value::Numeric(NumericValue::U64(l)), ast::Operator::Minus, Value::Numeric(NumericValue::U64(r))) => { - Value::Numeric(NumericValue::U64(l - r)) - } - (Value::Numeric(NumericValue::U64(l)), ast::Operator::Mul, Value::Numeric(NumericValue::U64(r))) => { - Value::Numeric(NumericValue::U64(l * r)) - } - (Value::Numeric(NumericValue::U64(l)), ast::Operator::Div, Value::Numeric(NumericValue::U64(r))) => { - Value::Numeric(NumericValue::U64(l / r)) - } - - //F - (Value::Numeric(NumericValue::F32(l)), ast::Operator::Plus, Value::Numeric(NumericValue::F32(r))) => { - Value::Numeric(NumericValue::F32(l + r)) - } - (Value::Numeric(NumericValue::F32(l)), ast::Operator::Minus, Value::Numeric(NumericValue::F32(r))) => { - Value::Numeric(NumericValue::F32(l - r)) - } - (Value::Numeric(NumericValue::F32(l)), ast::Operator::Mul, Value::Numeric(NumericValue::F32(r))) => { - Value::Numeric(NumericValue::F32(l * r)) - } - (Value::Numeric(NumericValue::F32(l)), ast::Operator::Div, Value::Numeric(NumericValue::F32(r))) => { - Value::Numeric(NumericValue::F32(l / r)) - } - - (Value::Numeric(NumericValue::F64(l)), ast::Operator::Plus, Value::Numeric(NumericValue::F64(r))) => { - Value::Numeric(NumericValue::F64(l + r)) - } - (Value::Numeric(NumericValue::F64(l)), ast::Operator::Minus, Value::Numeric(NumericValue::F64(r))) => { - Value::Numeric(NumericValue::F64(l - r)) - } - (Value::Numeric(NumericValue::F64(l)), ast::Operator::Mul, Value::Numeric(NumericValue::F64(r))) => { - Value::Numeric(NumericValue::F64(l * r)) - } - (Value::Numeric(NumericValue::F64(l)), ast::Operator::Div, Value::Numeric(NumericValue::F64(r))) => { - Value::Numeric(NumericValue::F64(l / r)) - } - - //fail - _ => panic!(""), - }; - return ExpressionResult::Value(result); - } - } - } -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index eaddf9d..0000000 --- a/src/main.rs +++ /dev/null @@ -1,119 +0,0 @@ -// mod types; -mod ast; -mod errors; -mod interpreter; -mod trait_checking; -mod type_checking; -#[macro_use] -extern crate lalrpop_util; - -lalrpop_mod!(pub grammar); // synthesized by LALRPOP - -use std::fs; - -extern crate clap; -use clap::{App, Arg}; - -fn main() { - let matches = App::new("Boring Language Compiler") - .version("0.0.1") - .author("Andrew Segavac") - .about("Compiles boringlang files") - .arg( - Arg::with_name("OUTPUT") - .short("o") - .long("out") - .value_name("OUTOUT") - .help("Sets an output file") - .takes_value(true), - ) - .arg(Arg::with_name("INPUT").help("Sets the input file").required(true).index(1)) - .arg(Arg::with_name("v").short("v").multiple(true).help("Sets the level of verbosity")) - .get_matches(); - let input = matches.value_of("INPUT").unwrap(); - - let contents = fs::read_to_string(input).expect("input file not found"); - let unknown_id_gen = ast::IdGenerator::new("S"); - let module_ast = grammar::ModuleParser::new().parse(&unknown_id_gen, &contents).unwrap(); //TODO: convert to error - // println!("ast: {:#?}", &module_ast); - - // println!("resolved ast: {:#?}", &resolved_ast); - let trait_checker = trait_checking::TraitChecker {}; - match trait_checker.with_module(&module_ast) { - Ok(_) => {} - Err(err) => { - println!("trait checking error: {:#?}", &err); - return; - } - } - let type_checker = type_checking::TypeChecker {}; - let type_checking_result = type_checker.with_module(&module_ast); - match &type_checking_result { - Ok((checked_ast, subst)) => { - println!("checked ast: {:#?}", &checked_ast); - println!("substitutions: {:#?}", &subst); - let interpreter = interpreter::TreeWalkInterpreter {}; - let result = interpreter.with_module(&checked_ast); - println!("final result: {:#?}", &result); - } - Err(err) => { - println!("type checking error: {:#?}", &err); - } - } - - // let context = Context::create(); - // let mut code_gen = compiler::ModuleCodeGen::new(&context, "main".to_string()); - // code_gen.gen_module(module_ast); - // - // let mut f = fs::File::create(output).expect("Unable to create out file"); - // f.write_all(code_gen.dump().as_bytes()).expect("Unable to write data"); -} - -#[test] -fn grammar() { - let id_gen = ast::IdGenerator::new("S"); - assert!(grammar::LiteralIntParser::new().parse(&id_gen, "22").is_ok()); - assert!(grammar::IdentifierParser::new().parse(&id_gen, "foo").is_ok()); - assert!(grammar::LiteralIntParser::new().parse(&id_gen, "2a").is_err()); - - assert!(grammar::TermParser::new().parse(&id_gen, "22").is_ok()); - assert!(grammar::TermParser::new().parse(&id_gen, "foo").is_ok()); - - assert!(grammar::ExpressionParser::new().parse(&id_gen, "22 * foo").is_ok()); - assert!(grammar::ExpressionParser::new().parse(&id_gen, "22 * 33").is_ok()); - assert!(grammar::ExpressionParser::new().parse(&id_gen, "(22 * 33) + 24").is_ok()); - - assert!(grammar::BlockParser::new().parse(&id_gen, "{ (22 * 33) + 24 }").is_ok()); - assert!(grammar::BlockParser::new().parse(&id_gen, "{ (22 * 33) + 24; 25 }").is_ok()); - // assert!(grammar::BlockParser::new().parse("{ (22 * 33) + 24\n 24 }").is_ok()); - assert!(grammar::BlockParser::new().parse(&id_gen, "{ }").is_ok()); - - assert!(grammar::VariableDeclarationParser::new().parse(&id_gen, "foo: i32").is_ok()); - assert!(grammar::VariableDeclarationParser::new().parse(&id_gen, "foo").is_err()); - assert!(grammar::VariableDeclarationParser::new().parse(&id_gen, "1234").is_err()); - - assert!(grammar::FunctionParser::new() - .parse(&id_gen, "fn add(a: i32, b: i32): i32 { a + b }") - .is_ok()); - assert!(grammar::FunctionParser::new() - .parse(&id_gen, "fn random_dice_roll(): i32 { 4 }") - .is_ok()); - assert!(grammar::FunctionParser::new() - .parse(&id_gen, "fn add(a: i32, b: i32): i32 { a + }") - .is_err()); - assert!(grammar::FunctionParser::new() - .parse(&id_gen, "fn add(a: i32, b: i32): i32") - .is_err()); - - assert!(grammar::FunctionCallParser::new().parse(&id_gen, "foo(1, 2)").is_ok()); - - assert!(grammar::ModuleParser::new() - .parse(&id_gen, "fn add(a: i32, b: i32): i32 { a + b }") - .is_ok()); - assert!(grammar::ModuleParser::new() - .parse( - &id_gen, - "fn add(a: i32, b: i32): i32 { a + b } fn subtract(a: i32, b: i32): i32 { a - b }" - ) - .is_ok()); -} diff --git a/src/trait_checking.rs b/src/trait_checking.rs deleted file mode 100644 index 1144abe..0000000 --- a/src/trait_checking.rs +++ /dev/null @@ -1,156 +0,0 @@ -use crate::ast; -use crate::errors; -use std::collections::HashMap; - -pub type Result = std::result::Result; - -#[derive(Debug, Clone, PartialEq, Eq)] -struct Context { - pub environment_traits: HashMap, -} - -fn create_builtins() -> HashMap { - let result = HashMap::::new(); - return result; -} - -fn compare_struct_trait( - struct_: &ast::TypeUsage, - trait_: &ast::TypeUsage, - struct_name: &ast::Identifier, - trait_name: &ast::Identifier, -) -> Result<()> { - match struct_ { - ast::TypeUsage::Named(named) => match trait_ { - ast::TypeUsage::Named(trait_named) => { - if named.name.name.value == trait_named.name.name.value { - return Ok(()); - } - return Err(errors::TypingError::TypeMismatch { - type_one: struct_.clone(), - type_two: trait_.clone(), - }); - } - ast::TypeUsage::Function(_) => { - return Err(errors::TypingError::TypeMismatch { - type_one: struct_.clone(), - type_two: trait_.clone(), - }); - } - _ => panic!("Unknown in function definition"), - }, - ast::TypeUsage::Function(function) => match trait_ { - ast::TypeUsage::Named(_) => { - return Err(errors::TypingError::TypeMismatch { - type_one: struct_.clone(), - type_two: trait_.clone(), - }); - } - ast::TypeUsage::Function(trait_function) => { - if function.arguments.len() != trait_function.arguments.len() { - return Err(errors::TypingError::TypeMismatch { - type_one: struct_.clone(), - type_two: trait_.clone(), - }); - } - for (i, _) in function.arguments.iter().enumerate() { - compare_struct_trait(&function.arguments[i], &trait_function.arguments[i], struct_name, trait_name)?; - } - compare_struct_trait(&function.return_type, &trait_function.return_type, struct_name, trait_name)?; - return Ok(()); - } - _ => panic!("Unknown in function definition"), - }, - _ => panic!("Unknown in function definition"), - } -} - -pub struct TraitChecker {} - -impl TraitChecker { - pub fn with_module(self: &Self, module: &ast::Module) -> Result<()> { - let mut ctx = Context { - environment_traits: create_builtins(), - }; - - for item in module.items.iter() { - match item { - ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Trait(trait_)) => { - ctx.environment_traits.insert(trait_.name.name.value.to_string(), trait_.clone()); - } - _ => {} - } - } - - for item in module.items.iter() { - match item { - ast::ModuleItem::Impl(impl_) => { - self.with_impl(&ctx, impl_)?; - } - _ => {} - } - } - return Ok(()); - } - - fn with_impl(self: &Self, ctx: &Context, impl_: &ast::Impl) -> Result<()> { - // See if trait actually matches - match &impl_.trait_ { - Some(trait_) => { - // assert trait functions satisfied - if !ctx.environment_traits.contains_key(&trait_.name.name.value) { - return Err(errors::TypingError::TypeDoesNotExist { - identifier: trait_.name.clone(), - }); - } - let trait_declaration = &ctx.environment_traits[&trait_.name.name.value]; - for trait_item in trait_declaration.functions.iter() { - match trait_item { - ast::TraitItem::FunctionDeclaration(declaration) => { - let mut found = false; - for impl_function in impl_.functions.iter() { - if impl_function.declaration.name.name.value == declaration.name.name.value { - found = true; - compare_struct_trait( - &impl_function.declaration.to_type(), - &declaration.to_type(), - &impl_.struct_.name, - &trait_.name, - )?; - } - } - if found == false { - return Err(errors::TypingError::MissingTraitFunction { - struct_name: impl_.struct_.name.clone(), - function_name: declaration.name.clone(), - }); - } - } - } - } - // assert all functions are in trait - for impl_function in impl_.functions.iter() { - let mut found = false; - for trait_item in trait_declaration.functions.iter() { - match trait_item { - ast::TraitItem::FunctionDeclaration(declaration) => { - if impl_function.declaration.name.name.value == declaration.name.name.value { - found = true; - break; - } - } - }; - } - if found == false { - return Err(errors::TypingError::FunctionNotInTrait { - function_name: impl_function.declaration.name.clone(), - }); - } - } - } - None => {} - } - // TODO: check for duplicate functions - return Ok(()); - } -} diff --git a/src/type_alias_resolution.rs b/src/type_alias_resolution.rs deleted file mode 100644 index 29d55bc..0000000 --- a/src/type_alias_resolution.rs +++ /dev/null @@ -1,379 +0,0 @@ -use crate::ast; -use crate::errors; - -pub type Result = std::result::Result; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -struct Context { - pub type_aliases: Vec, -} - -fn resolve_type(ctx: &Context, type_: &ast::NamedTypeUsage) -> Result { - let mut changed = true; - let mut result = ast::TypeUsage::Named(type_.clone()); - while changed { - changed = false; - let current = &result.clone(); - match current { - ast::TypeUsage::Named(named) => { - for alias in ctx.type_aliases.iter() { - if named.name.name.value == alias.name.name.value { // is alias, replace - changed = true; - result = alias.replaces.clone(); - } - } - } - _ => break, - } - } - match &result { - ast::TypeUsage::Named(named) => { - match &named.type_parameters { - ast::GenericUsage::Known(known) => { - let mut result_params = vec!(); - for param in known.parameters.iter() { - result_params.push(process_type(ctx, param)?); - } - let mut new_named = named.clone(); - new_named.type_parameters = ast::GenericUsage::new(&result_params); - result = ast::TypeUsage::Named(new_named); - }, - _ => {} - } - }, - ast::TypeUsage::Function(func) => { - match &type_.type_parameters { - ast::GenericUsage::Known(known) => { - if known.parameters.len() > 0 { - return Err(errors::TypingError::InvalidTypeParameterOnAlias{alias: type_.name.clone()}); - } - }, - _ => {} //skip - } - }, - _ => { - panic!("alias of a non-type, not possible"); - } - } - return Ok(result); -} - -fn process_type(ctx: &Context, type_: &ast::TypeUsage) -> Result { - match type_ { - ast::TypeUsage::Named(named) => { - return Ok(resolve_type(ctx, named)?); - } - ast::TypeUsage::Function(function) => { - let mut arguments = vec!(); - for a in function.arguments.iter() { - arguments.push(process_type(ctx, &a.clone())?); - } - return Ok(ast::TypeUsage::Function(ast::FunctionTypeUsage { - arguments: arguments, - return_type: Box::new(process_type(ctx, &function.return_type.clone())?), - })); - } - ast::TypeUsage::Unknown(unknown) => { - return Ok(ast::TypeUsage::Unknown(unknown.clone())); - }, - ast::TypeUsage::Namespace(namespace) => { - match namespace { - ast::NamespaceTypeUsage::Type(named_type)=> { - let result = resolve_type(ctx, named_type)?; - match result { - ast::TypeUsage::Named(named) => { - return Ok(ast::TypeUsage::Namespace(ast::NamespaceTypeUsage::Type(named))); - }, - _ => { - return Err(errors::TypingError::InvalidUseofAlias); - } - } - } - } - } - } -} - -pub struct TypeAliasResolver {} - -impl TypeAliasResolver { - pub fn with_module(self: &Self, module: &ast::Module) -> Result { - let mut ctx = Context { type_aliases: vec![] }; - for item in module.items.iter() { - match item { - ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Alias(alias)) => { - ctx.type_aliases.push(alias.clone()); - } - _ => {} - } - } - - let mut items = vec!(); - for item in module.items.iter() { - items.push(match item { - ast::ModuleItem::Function(function) => ast::ModuleItem::Function(self.with_function(&ctx, function)?), - ast::ModuleItem::TypeDeclaration(type_declaration) => { - ast::ModuleItem::TypeDeclaration(self.with_type_declaration(&ctx, type_declaration)?) - } - ast::ModuleItem::Impl(impl_) => ast::ModuleItem::Impl(self.with_impl(&ctx, impl_)?), - }); - } - - return Ok(ast::Module { - items: items, - }); - } - - fn with_function(self: &Self, ctx: &Context, function: &ast::Function) -> Result { - return Ok(ast::Function { - declaration: self.with_function_declaration(ctx, &function.declaration)?, - block: self.with_block(ctx, &function.block)?, - }); - } - - fn with_function_declaration(self: &Self, ctx: &Context, declaration: &ast::FunctionDeclaration) -> Result { - let mut arguments = vec!(); - for arg in declaration.arguments.iter() { - arguments.push(ast::VariableDeclaration { - name: arg.name.clone(), - type_: process_type(ctx, &arg.type_)?, - }); - } - return Ok(ast::FunctionDeclaration { - name: declaration.name.clone(), - generic: declaration.generic.clone(), - arguments: arguments, - return_type: process_type(ctx, &declaration.return_type)?, - }); - } - - fn with_type_declaration(self: &Self, ctx: &Context, type_declaration: &ast::TypeDeclaration) -> Result { - match type_declaration { - ast::TypeDeclaration::Struct(struct_) => { - return Ok(ast::TypeDeclaration::Struct(self.with_struct_declaration(ctx, struct_)?)); - } - ast::TypeDeclaration::Primitive(primitive) => { - return Ok(ast::TypeDeclaration::Primitive(primitive.clone())); - } - ast::TypeDeclaration::Alias(alias) => { - return Ok(ast::TypeDeclaration::Alias(alias.clone())); - } - ast::TypeDeclaration::Trait(trait_) => { - return Ok(ast::TypeDeclaration::Trait(self.with_trait(ctx, trait_)?)); - } - } - } - - fn with_struct_declaration(self: &Self, ctx: &Context, struct_: &ast::StructTypeDeclaration) -> Result { - let mut fields = vec!(); - for field in struct_.fields.iter() { - fields.push(ast::StructField { - name: field.name.clone(), - type_: process_type(ctx, &field.type_)?, - }); - } - return Ok(ast::StructTypeDeclaration { - generic: struct_.generic.clone(), - name: struct_.name.clone(), - fields: fields, - }); - } - - fn with_trait(self: &Self, ctx: &Context, trait_: &ast::TraitTypeDeclaration) -> Result { - let mut trait_ctx = ctx.clone(); - trait_ctx.type_aliases.push(ast::AliasTypeDeclaration { - name: ast::Identifier { - name: ast::Spanned { - span: ast::Span { left: 0, right: 0 }, //todo: figure out a sane value for these - value: "Self".to_string(), - }, - }, - replaces: ast::TypeUsage::Named(ast::NamedTypeUsage { - type_parameters: ast::GenericUsage::Unknown, - name: trait_.name.clone(), - }), - }); - let mut functions = vec!(); - for f in trait_.functions.iter() { - functions.push(match f { - ast::TraitItem::Function(function) => ast::TraitItem::Function(self.with_function(&trait_ctx, function)?), - ast::TraitItem::FunctionDeclaration(function_declaration) => { - ast::TraitItem::FunctionDeclaration(self.with_function_declaration(&trait_ctx, function_declaration)?) - } - }); - } - return Ok(ast::TraitTypeDeclaration { - generic: trait_.generic.clone(), - name: trait_.name.clone(), - functions: functions, - }); - } - - fn with_impl(self: &Self, ctx: &Context, impl_: &ast::Impl) -> Result { - let mut impl_ctx = ctx.clone(); - impl_ctx.type_aliases.push(ast::AliasTypeDeclaration { - name: ast::Identifier { - name: ast::Spanned { - span: ast::Span { left: 0, right: 0 }, //todo: figure out a sane value for these - value: "Self".to_string(), - }, - }, - replaces: ast::TypeUsage::Named(impl_.struct_.clone()), - }); - let mut functions = vec!(); - for f in impl_.functions.iter() { - functions.push(self.with_function(&impl_ctx, f)?); - } - return Ok(ast::Impl { - generic: impl_.generic.clone(), - trait_: impl_.trait_.clone(), - struct_: impl_.struct_.clone(), - functions: functions, - }); - } - - fn with_block(self: &Self, ctx: &Context, block: &ast::Block) -> Result { - let mut statements = vec!(); - for s in block.statements.iter() { - statements.push(self.with_statement(ctx, s)?); - } - return Ok(ast::Block { - statements: statements, - type_: process_type(ctx, &block.type_)?, - }); - } - - fn with_statement(self: &Self, ctx: &Context, statement: &ast::Statement) -> Result { - match statement { - ast::Statement::Return(return_statement) => { - return Ok(ast::Statement::Return(self.with_return_statement(ctx, return_statement)?)); - } - ast::Statement::Let(let_statement) => { - return Ok(ast::Statement::Let(self.with_let_statement(ctx, let_statement)?)); - } - ast::Statement::Assignment(assignment_statement) => { - return Ok(ast::Statement::Assignment(self.with_assignment_statement(ctx, assignment_statement)?)); - } - ast::Statement::Expression(expression) => { - return Ok(ast::Statement::Expression(self.with_expression(ctx, expression)?)); - } - } - } - - fn with_return_statement(self: &Self, ctx: &Context, statement: &ast::ReturnStatement) -> Result { - return Ok(ast::ReturnStatement { - source: self.with_expression(ctx, &statement.source)?, - }); - } - - fn with_let_statement(self: &Self, ctx: &Context, statement: &ast::LetStatement) -> Result { - return Ok(ast::LetStatement { - variable_name: statement.variable_name.clone(), - expression: self.with_expression(ctx, &statement.expression)?, - type_: process_type(ctx, &statement.type_)?, - }); - } - - fn with_assignment_statement(self: &Self, ctx: &Context, statement: &ast::AssignmentStatement) -> Result { - return Ok(ast::AssignmentStatement { - source: match &statement.source { - ast::AssignmentTarget::Variable(variable) => ast::AssignmentTarget::Variable(ast::VariableUsage { - type_parameters: variable.type_parameters.clone(), - name: variable.name.clone(), - type_: process_type(ctx, &variable.type_)?, - }), - ast::AssignmentTarget::StructAttr(struct_attr) => ast::AssignmentTarget::StructAttr(ast::StructGetter { - type_parameters: struct_attr.type_parameters.clone(), - source: self.with_expression(ctx, &struct_attr.source)?, - attribute: struct_attr.attribute.clone(), - type_: process_type(ctx, &struct_attr.type_)?, - }), - }, - expression: self.with_expression(ctx, &statement.expression)?, - }); - } - - fn with_expression(self: &Self, ctx: &Context, expression: &ast::Expression) -> Result { - return Ok(ast::Expression { - subexpression: Box::new(match &*expression.subexpression { - ast::Subexpression::LiteralInt(literal_int) => ast::Subexpression::LiteralInt(ast::LiteralInt { - value: literal_int.value.clone(), - type_: process_type(ctx, &literal_int.type_)?, - }), - ast::Subexpression::LiteralFloat(literal_float) => ast::Subexpression::LiteralFloat(ast::LiteralFloat { - value: literal_float.value.clone(), - type_: process_type(ctx, &literal_float.type_)?, - }), - ast::Subexpression::LiteralBool(literal_bool) => ast::Subexpression::LiteralBool(ast::LiteralBool { - value: literal_bool.value.clone(), - type_: process_type(ctx, &literal_bool.type_)?, - }), - ast::Subexpression::LiteralString(literal_string) => ast::Subexpression::LiteralString(ast::LiteralString { - value: literal_string.value.clone(), - type_: process_type(ctx, &literal_string.type_)?, - }), - ast::Subexpression::LiteralStruct(literal_struct) => { - let result = resolve_type( - ctx, - &ast::NamedTypeUsage { - type_parameters: literal_struct.type_parameters.clone(), - name: literal_struct.name.clone(), - }, - )?; - let new_name = match &result { - ast::TypeUsage::Named(named) => named.name.clone(), - _ => panic!("LiteralStruct resolved to non-named-type"), - }; - let mut fields = vec!(); - for field in literal_struct.fields.iter() { - fields.push((field.0.clone(), self.with_expression(ctx, &field.1)?)); - } - ast::Subexpression::LiteralStruct(ast::LiteralStruct { - type_parameters: literal_struct.type_parameters.clone(), - name: new_name.clone(), - fields: fields, - type_: process_type(ctx, &literal_struct.type_)?, - }) - } - ast::Subexpression::FunctionCall(function_call) => { - let mut arguments = vec!(); - for arg in function_call.arguments.iter() { - arguments.push(self.with_expression(ctx, arg)?); - } - ast::Subexpression::FunctionCall(ast::FunctionCall { - source: self.with_expression(ctx, &function_call.source)?, - arguments: arguments, - type_: process_type(ctx, &function_call.type_)?, - }) - }, - ast::Subexpression::VariableUsage(variable_usage) => ast::Subexpression::VariableUsage(ast::VariableUsage { - name: variable_usage.name.clone(), - type_parameters: variable_usage.type_parameters.clone(), - type_: process_type(ctx, &variable_usage.type_)?, - }), - ast::Subexpression::If(if_expression) => ast::Subexpression::If(ast::IfExpression { - condition: self.with_expression(ctx, &if_expression.condition)?, - block: self.with_block(ctx, &if_expression.block)?, - else_: match &if_expression.else_ { - Some(else_) => Some(self.with_block(ctx, else_)?), - None => None, - }, - type_: process_type(ctx, &if_expression.type_)?, - }), - ast::Subexpression::StructGetter(struct_getter) => ast::Subexpression::StructGetter(ast::StructGetter { - type_parameters: struct_getter.type_parameters.clone(), - source: self.with_expression(ctx, &struct_getter.source)?, - attribute: struct_getter.attribute.clone(), - type_: process_type(ctx, &struct_getter.type_)?, - }), - ast::Subexpression::Block(block) => ast::Subexpression::Block(self.with_block(ctx, &block)?), - ast::Subexpression::Op(op) => ast::Subexpression::Op(ast::Operation { - left: self.with_expression(ctx, &op.left)?, - op: op.op.clone(), - right: self.with_expression(ctx, &op.right)?, - }), - }), - type_: process_type(ctx, &expression.type_)?, - }); - } -} diff --git a/src/type_checking.rs b/src/type_checking.rs deleted file mode 100644 index b387527..0000000 --- a/src/type_checking.rs +++ /dev/null @@ -1,1638 +0,0 @@ -use crate::ast; -use crate::errors; -use std::collections::HashMap; -use std::rc::Rc; - -pub type SubstitutionMap = HashMap; - -pub type Result = std::result::Result; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TypeConstructor { - generic: ast::Generic, - type_usage: ast::TypeUsage, -} - -fn type_meets_trait_bounds(ctx: &Context, type_: &ast::TypeUsage, bounds: &Vec) -> bool { - for bound in bounds.iter() { - let named = match type_ { - ast::TypeUsage::Named(named) => named, - ast::TypeUsage::Function(_) => { - return false; - } - ast::TypeUsage::Unknown(_) => { - return true; // unknown this pass, skip, test once known - } - ast::TypeUsage::Namespace(_) => { - panic!("impossible"); - } - }; - match &ctx.environment[&named.name.name.value] { - NamedEntity::NamedType(named_type) => { - let mut found = false; - for impl_ in named_type.impls.iter() { - if impl_.trait_ == Some(bound.name.value.to_string()) { - found = true; - break; - } - } - if found == false { - return false; - } - } - _ => { - panic!("type is a variable, this should not happen"); - } - } - } - return true; -} - -fn replace_generic_with_concrete(replace: &ast::Identifier, with_type: &ast::TypeUsage, in_type: &ast::TypeUsage) -> ast::TypeUsage { - match in_type { - ast::TypeUsage::Named(named) => { - let mut result = named.clone(); - if named.name.name.value == replace.name.value { - return with_type.clone(); - } - result.type_parameters = match &named.type_parameters { - ast::GenericUsage::Known(known) => { - let mut param_result = vec![]; - for param in known.parameters.iter() { - param_result.push(replace_generic_with_concrete(replace, with_type, param)); - } - ast::GenericUsage::new(¶m_result) - } - ast::GenericUsage::Unknown => ast::GenericUsage::Unknown, - }; - return ast::TypeUsage::Named(result); - } - ast::TypeUsage::Function(func) => { - let result = ast::TypeUsage::Function(ast::FunctionTypeUsage { - arguments: func - .arguments - .iter() - .map(|arg| replace_generic_with_concrete(replace, with_type, arg)) - .collect(), - return_type: Box::new(replace_generic_with_concrete(replace, with_type, &func.return_type)), - }); - return result; - } - _ => { - // in_type is unknown, skip - return in_type.clone(); - } - }; -} - -impl TypeConstructor { - fn from_declaration(declaration: &ast::FunctionDeclaration) -> TypeConstructor { - return TypeConstructor { - generic: declaration.generic.clone(), - type_usage: declaration.to_type(), - }; - } - fn construct(&self, ctx: &Context, usage: &ast::GenericUsage) -> Result { - match usage { - ast::GenericUsage::Known(known_usage) => { - let mut result = self.type_usage.clone(); - if known_usage.parameters.len() != self.generic.parameters.len() { - return Err(errors::TypingError::WrongNumberOfTypeParameters {}); - } - // 1. for arg in args, assert arg matches self.generic traits via impl name - // 2. replace type usage names with arg types - for i in 0..known_usage.parameters.len() { - if !type_meets_trait_bounds(ctx, &known_usage.parameters[i], &self.generic.parameters[i].bounds) { - return Err(errors::TypingError::InvalidTypeForGeneric); - } - result = replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &self.type_usage); - } - return Ok(result); - } - ast::GenericUsage::Unknown => { - // generate new Unknown Types for matching - let mut result = self.type_usage.clone(); - for param in self.generic.parameters.iter() { - let id = ctx.id_generator.next(); - let unknown = ast::TypeUsage::Unknown(ast::UnknownTypeUsage { name: id }); - result = replace_generic_with_concrete(¶m.name, &unknown, &self.type_usage); - } - return Ok(result); - } - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct EnvImpl { - trait_: Option, - functions: HashMap, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum TypeType { - Scalar, - Trait, - Struct, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct EnvType { - generic: ast::Generic, - is_a: TypeType, - fields: HashMap, - impls: Vec, -} - -impl EnvType { - fn from_struct(struct_: &ast::StructTypeDeclaration) -> EnvType { - return EnvType { - generic: struct_.generic.clone(), - is_a: TypeType::Struct, - fields: struct_ - .fields - .iter() - .map(|field| (field.name.name.value.to_string(), field.type_.clone())) - .collect(), - impls: vec![], - }; - } - - fn from_trait(trait_: &ast::TraitTypeDeclaration) -> EnvType { - let mut functions = HashMap::new(); - for func in trait_.functions.iter() { - match func { - ast::TraitItem::FunctionDeclaration(fd) => { - functions.insert(fd.name.name.value.to_string(), TypeConstructor::from_declaration(&fd)); - } - } - } - let impl_ = EnvImpl { - trait_: Some(trait_.name.name.value.to_string()), - functions: functions, - }; - return EnvType { - generic: trait_.generic.clone(), - is_a: TypeType::Trait, - fields: HashMap::new(), - impls: vec![impl_], - }; - } - - fn type_construct(&self, ctx: &Context, usage: &ast::GenericUsage) -> Result { - // steps - // 1. Check if matches bounds, create unknowns if necessary. - // 2. Replace all (Named+generics or function args/return) recursively. - // 3. Return updated, plus known generic usage to replace any unknown usage. - let known_usage = match usage { - ast::GenericUsage::Known(known) => known.clone(), - ast::GenericUsage::Unknown => { - let mut new_unknowns = vec![]; - for _ in 0..self.generic.parameters.len() { - new_unknowns.push(ast::TypeUsage::new_unknown(&ctx.id_generator)); - } - ast::GenericInstantiation { - parameters: new_unknowns.iter().map(|tp| tp.clone()).collect(), - } - } - }; - if known_usage.parameters.len() != self.generic.parameters.len() { - return Err(errors::TypingError::WrongNumberOfTypeParameters {}); - } - for i in 0..known_usage.parameters.len() { - if !type_meets_trait_bounds(ctx, &known_usage.parameters[i], &self.generic.parameters[i].bounds) { - return Err(errors::TypingError::InvalidTypeForGeneric); - } - } - // Generic type matches, time to replace - let mut result = self.clone(); - for i in 0..known_usage.parameters.len() { - let mut fields = HashMap::new(); - for (k, v) in result.fields.iter() { - let type_usage = replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &v); - fields.insert(k.clone(), type_usage); - } - let mut impls = vec![]; - for impl_ in result.impls.iter() { - let mut functions = HashMap::new(); - for (name, func) in impl_.functions.iter() { - let type_usage = - replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &func.type_usage); - - functions.insert( - name.clone(), - TypeConstructor { - generic: func.generic.clone(), - type_usage: type_usage, - }, - ); - } - impls.push(EnvImpl { - trait_: impl_.trait_.clone(), - functions: functions, - }); - } - result = EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: self.is_a.clone(), - fields: fields, - impls: impls, - }; - } - return Ok(result); - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum NamedEntity { - NamedType(EnvType), - Function(TypeConstructor), - Variable(ast::TypeUsage), -} - -fn create_builtins() -> HashMap { - let mut result = HashMap::new(); - result.insert( - "i8".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "i16".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "i32".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "i64".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "isize".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - - result.insert( - "u8".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "u16".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "u32".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "u64".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "usize".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - - result.insert( - "f32".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "f64".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - - result.insert( - "bool".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "!".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "unit".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - result.insert( - "String".to_string(), - NamedEntity::NamedType(EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Scalar, - fields: HashMap::new(), - impls: vec![], - }), - ); - return result; -} - -enum StructAttr { - Field(ast::TypeUsage), - Method(TypeConstructor), -} - -fn apply_self(type_name: &str, constructor: &TypeConstructor) -> TypeConstructor { - match &constructor.type_usage { - ast::TypeUsage::Function(func) => { - if func.arguments.len() > 0 { - match &func.arguments[0] { - ast::TypeUsage::Named(named) => { - if type_name == named.name.name.value || type_name == "Self" { - let result = ast::TypeUsage::Function(ast::FunctionTypeUsage { - arguments: func.arguments[1..func.arguments.len()].iter().map(|arg| arg.clone()).collect(), - return_type: func.return_type.clone(), - }); - return TypeConstructor { - generic: constructor.generic.clone(), - type_usage: result, - }; - } - } - _ => {} - } - } - } - _ => {} - } - return constructor.clone(); -} - -fn get_attr(ctx: &Context, get_from: &NamedEntity, attribute: &ast::Identifier) -> Result { - match get_from { - NamedEntity::NamedType(env_type) => { - if env_type.fields.contains_key(&attribute.name.value) { - return Ok(StructAttr::Field(env_type.fields[&attribute.name.value].clone())); - } - let mut result = Vec::new(); - for impl_ in env_type.impls.iter() { - if impl_.functions.contains_key(&attribute.name.value) { - result.push(impl_.functions[&attribute.name.value].clone()) - } - } - if result.len() == 0 { - return Err(errors::TypingError::UnknownFieldName { - identifier: attribute.clone(), - }); - } - if result.len() > 1 { - return Err(errors::TypingError::MultipleFieldName { - identifier: attribute.clone(), - }); - } - return Ok(StructAttr::Method(result[0].clone())); - } - NamedEntity::Variable(type_) => match type_ { - ast::TypeUsage::Named(named) => { - let env_type = match &ctx.environment[&named.name.name.value] { - NamedEntity::NamedType(env_type) => env_type, - _ => panic!("variable has non-type as type"), - }; - let type_ = env_type.type_construct(ctx, &named.type_parameters)?; - - let attr = get_attr(ctx, &NamedEntity::NamedType(type_), attribute)?; - let method = match attr { - StructAttr::Field(field) => return Ok(StructAttr::Field(field)), - StructAttr::Method(method) => method, - }; - return Ok(StructAttr::Method(apply_self(&named.name.name.value, &method))); - } - _ => { - return Err(errors::TypingError::AttributeOfNonstruct { - identifier: attribute.clone(), - }); - } - }, - NamedEntity::Function(_) => { - return Err(errors::TypingError::AttributeOfNonstruct { - identifier: attribute.clone(), - }); - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -struct Context { - pub current_function_return: Option, - pub environment: HashMap, - pub id_generator: Rc, - pub current_self: Option, -} - -impl Context { - fn add_variable(&self, name: String, type_usage: &ast::TypeUsage) -> Context { - let mut ctx = self.clone(); - ctx.environment.insert(name.to_string(), NamedEntity::Variable(type_usage.clone())); - return ctx; - } - - fn set_current_function_return(&self, function: &ast::TypeUsage) -> Context { - let mut ctx = self.clone(); - ctx.current_function_return = Some(function.clone()); - return ctx; - } - - fn add_generic(&self, generic: &ast::Generic) -> Result { - let mut ctx = self.clone(); - for parameter in generic.parameters.iter() { - let mut env_type = EnvType { - generic: ast::Generic { parameters: vec![] }, - is_a: TypeType::Trait, - fields: HashMap::new(), - impls: vec![], - }; - for bound in parameter.bounds.iter() { - if !self.environment.contains_key(&bound.name.value) { - return Err(errors::TypingError::TypeDoesNotExist { identifier: bound.clone() }); - } - match &self.environment[&bound.name.value] { - NamedEntity::NamedType(named_type) => { - env_type.impls.push(named_type.impls[0].clone()); - } - _ => {} - } - } - ctx.environment - .insert(parameter.name.name.value.clone(), NamedEntity::NamedType(env_type)); - } - return Ok(ctx); - } - - fn add_impl(&self, impl_: &ast::Impl, traits: &HashMap) -> Result { - let mut functions = HashMap::new(); - for func in impl_.functions.iter() { - if func.declaration.arguments.len() == 0 { - continue; - } - match &func.declaration.arguments[0].type_ { - ast::TypeUsage::Named(named) => { - if named.name.name.value != "Self" { - continue; - } - } - _ => { - continue; - } - } - let type_constructor = TypeConstructor::from_declaration(&func.declaration); - let resolved_tc = TypeConstructor { - generic: type_constructor.generic.clone(), - type_usage: type_constructor.type_usage.replace_type(&"Self", &impl_.struct_.name), - }; - // is self function, add to context for this type - functions.insert(func.declaration.name.name.value.to_string(), resolved_tc); - } - let mut result = self.clone(); - let mut env_named = result.environment[&impl_.struct_.name.name.value].clone(); - match &mut env_named { - NamedEntity::NamedType(env_type) => { - env_type.impls.push(EnvImpl { - trait_: match &impl_.trait_ { - Some(trait_) => Some(trait_.name.name.value.to_string()), - None => None, - }, - functions: functions, - }); - result - .environment - .insert(impl_.struct_.name.name.value.to_string(), NamedEntity::NamedType(env_type.clone())); - } - NamedEntity::Variable(_) => { - return Err(errors::TypingError::IdentifierIsNotType { - identifier: impl_.struct_.name.clone(), - }); - } - NamedEntity::Function(_) => { - return Err(errors::TypingError::IdentifierIsNotType { - identifier: impl_.struct_.name.clone(), - }); - } - } - return Ok(result); - } -} - -fn type_exists(ctx: &Context, type_: &ast::TypeUsage) -> Result<()> { - let result = match type_ { - ast::TypeUsage::Named(named) => { - if !ctx.environment.contains_key(&named.name.name.value) { - return Err(errors::TypingError::TypeDoesNotExist { - identifier: named.name.clone(), - }); - } - match ctx.environment[&named.name.name.value] { - NamedEntity::NamedType(_) => { - // is a type - } - _ => { - return Err(errors::TypingError::IdentifierIsNotType { - identifier: named.name.clone(), - }); - } - } - } - ast::TypeUsage::Unknown(_) => {} // do nothing - ast::TypeUsage::Namespace(_) => {} - ast::TypeUsage::Function(function) => { - let mut errs = vec![]; - for arg in function.arguments.iter() { - match type_exists(ctx, arg) { - Ok(_) => {} - Err(err) => errs.push(err), - }; - } - match type_exists(ctx, &function.return_type) { - Ok(_) => {} - Err(err) => errs.push(err), - } - if errs.len() > 0 { - return Err(errors::TypingError::MultipleErrors { errors: errs }); - } - } - }; - return Ok(result); -} - -fn apply_substitution(ctx: &Context, substitution: &SubstitutionMap, type_: &ast::TypeUsage) -> Result { - let result = match type_ { - ast::TypeUsage::Named(named) => ast::TypeUsage::Named(named.clone()), - ast::TypeUsage::Unknown(unknown) => { - if substitution.contains_key(&unknown.name) { - substitution[&unknown.name].clone() - } else { - ast::TypeUsage::Unknown(unknown.clone()) - } - } - ast::TypeUsage::Namespace(namespace) => ast::TypeUsage::Namespace(namespace.clone()), - ast::TypeUsage::Function(function) => { - let mut arguments = vec![]; - for arg in function.arguments.iter() { - arguments.push(apply_substitution(ctx, substitution, arg)?); - } - ast::TypeUsage::Function(ast::FunctionTypeUsage { - arguments: arguments, - return_type: Box::new(apply_substitution(ctx, substitution, &function.return_type)?), - }) - } - }; - type_exists(ctx, &result)?; - return Ok(result); -} - -fn compose_substitutions(ctx: &Context, s1: &SubstitutionMap, s2: &SubstitutionMap) -> Result { - let mut result = SubstitutionMap::new(); - for k in s2.keys() { - result.insert(k.to_string(), apply_substitution(ctx, s1, &s2[k])?); - } - return Ok(s1.into_iter().map(|(k, v)| (k.clone(), v.clone())).chain(result).collect()); -} - -fn unify(ctx: &Context, t1: &ast::TypeUsage, t2: &ast::TypeUsage) -> Result { - match (t1, t2) { - (ast::TypeUsage::Named(named1), ast::TypeUsage::Named(named2)) => { - if named1.name.name.value == named2.name.name.value - || (named1.name.name.value == "Self" && Some(named2.name.name.value.clone()) == ctx.current_self) - || (named2.name.name.value == "Self" && Some(named1.name.name.value.clone()) == ctx.current_self) - { - let mut result = SubstitutionMap::new(); - match (&named1.type_parameters, &named2.type_parameters) { - (ast::GenericUsage::Known(known1), ast::GenericUsage::Known(known2)) => { - if known1.parameters.len() != known2.parameters.len() { - return Err(errors::TypingError::TypeMismatch { - type_one: t1.clone(), - type_two: t2.clone(), - }); - } - for (i, _) in known1.parameters.iter().enumerate() { - result = compose_substitutions( - ctx, - &result, - &unify( - ctx, - &apply_substitution(ctx, &result, &known1.parameters[i])?, - &apply_substitution(ctx, &result, &known2.parameters[i])?, - )?, - )?; - } - } - _ => { - panic!("should never be unknown") - } - } - return Ok(result); - } - } - _ => {} - } - match t1 { - ast::TypeUsage::Unknown(unknown) => { - return Ok(var_bind(&unknown.name, t2)); - } - _ => {} - } - match t2 { - ast::TypeUsage::Unknown(unknown) => { - return Ok(var_bind(&unknown.name, t1)); - } - _ => {} - } - match (t1, t2) { - (ast::TypeUsage::Function(f1), ast::TypeUsage::Function(f2)) => { - let mut result = unify(ctx, &*f1.return_type, &*f2.return_type)?; - if f1.arguments.len() != f2.arguments.len() { - panic!("Argument lengths don't match"); - } - for (i, _) in f1.arguments.iter().enumerate() { - result = compose_substitutions( - ctx, - &result, - &unify( - ctx, - &apply_substitution(ctx, &result, &f1.arguments[i])?, - &apply_substitution(ctx, &result, &f2.arguments[i])?, - )?, - )?; - } - return Ok(result); - } - _ => {} - } - return Err(errors::TypingError::TypeMismatch { - type_one: t1.clone(), - type_two: t2.clone(), - }); -} - -fn var_bind(name: &str, t: &ast::TypeUsage) -> SubstitutionMap { - match t { - ast::TypeUsage::Unknown(unknown) => { - if name == unknown.name { - return SubstitutionMap::new(); - } - } - _ => {} - } - if contains(t, name) { - panic!("Type contains a reference to itself") - } - let mut substitution = SubstitutionMap::new(); - substitution.insert(name.to_string(), t.clone()); - return substitution; -} - -fn contains(t: &ast::TypeUsage, name: &str) -> bool { - match t { - ast::TypeUsage::Named(_) => return false, - ast::TypeUsage::Unknown(unknown) => unknown.name == name, - ast::TypeUsage::Namespace(_) => return false, - ast::TypeUsage::Function(f) => { - if contains(&*f.return_type, name) { - return true; - } - for arg in f.arguments.iter() { - if contains(&arg.clone(), name) { - return true; - } - } - return false; - } - } -} - -pub struct TypeChecker {} - -impl TypeChecker { - pub fn with_module(self: &Self, module: &ast::Module) -> Result<(ast::Module, SubstitutionMap)> { - let mut ctx = Context { - environment: create_builtins(), - current_function_return: None, - id_generator: Rc::new(ast::IdGenerator::new("T")), - current_self: None, - }; - - let mut traits = HashMap::new(); - - for item in module.items.iter() { - match item { - ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Struct(struct_)) => { - ctx.environment.insert( - struct_.name.name.value.to_string(), - NamedEntity::NamedType(EnvType::from_struct(&struct_)), - ); - } - ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Trait(trait_)) => { - traits.insert(trait_.name.name.value.to_string(), trait_.clone()); - ctx.environment.insert( - trait_.name.name.value.to_string(), - NamedEntity::NamedType(EnvType::from_trait(&trait_)), - ); - } - ast::ModuleItem::Function(function) => { - let function_type = ast::FunctionTypeUsage { - arguments: function.declaration.arguments.iter().map(|arg| arg.type_.clone()).collect(), - return_type: Box::new(function.declaration.return_type.clone()), - }; - ctx.environment.insert( - function.declaration.name.name.value.to_string(), - NamedEntity::Function(TypeConstructor { - generic: function.declaration.generic.clone(), - type_usage: ast::TypeUsage::Function(function_type), - }), - ); - } - _ => {} - } - } - - for item in module.items.iter() { - match item { - ast::ModuleItem::Impl(impl_) => { - if !ctx.environment.contains_key(&impl_.struct_.name.name.value) { - return Err(errors::TypingError::IdentifierIsNotType { - identifier: impl_.struct_.name.clone(), - }); - } - ctx = ctx.add_impl(&impl_, &traits)?; - } - _ => {} - } - } - - let mut subst = SubstitutionMap::new(); - let mut items = vec![]; - for item in module.items.iter() { - items.push(match item { - ast::ModuleItem::Function(function) => { - let (func, fn_subst) = self.with_function(&ctx, &subst, function)?; - subst = compose_substitutions(&ctx, &subst, &fn_subst)?; - ast::ModuleItem::Function(func) - } - ast::ModuleItem::TypeDeclaration(type_declaration) => { - let (ty_decl, ty_subst) = self.with_type_declaration(&ctx, &subst, type_declaration)?; - subst = compose_substitutions(&ctx, &subst, &ty_subst)?; - ast::ModuleItem::TypeDeclaration(ty_decl) - } - ast::ModuleItem::Impl(impl_) => { - let (impl_result, impl_subst) = self.with_impl(&ctx, &subst, impl_)?; - // TODO: errors on generics not exist at global scope - // subst = compose_substitutions(&ctx, &subst, &impl_subst)?; - ast::ModuleItem::Impl(impl_result) - } - }); - } - let result = ast::Module { items: items }; - return Ok((result, subst)); - } - - fn with_function_declaration(self: &Self, ctx: &Context, declaration: &ast::FunctionDeclaration) -> Result { - for arg in declaration.arguments.iter() { - type_exists(ctx, &arg.type_)?; - } - type_exists(ctx, &declaration.return_type)?; - return Ok(declaration.clone()); - } - - fn with_function( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - function: &ast::Function, - ) -> Result<(ast::Function, SubstitutionMap)> { - let gen_ctx = ctx.add_generic(&function.declaration.generic)?; - let declaration = self.with_function_declaration(&gen_ctx, &function.declaration)?; - // add args to env - let mut function_ctx = gen_ctx.set_current_function_return(&declaration.return_type.clone()); - for arg in declaration.arguments.iter() { - function_ctx = function_ctx.add_variable(arg.name.name.value.to_string(), &arg.type_.clone()); - } - - let (block, substitution) = self.with_block(&function_ctx, incoming_substitutions, &function.block)?; - let mut substitution = compose_substitutions(&function_ctx, incoming_substitutions, &substitution)?; - match &block.type_ { - ast::TypeUsage::Named(named) => { - if named.name.name.value != "!" { - substitution = compose_substitutions( - &function_ctx, - &substitution, - &unify(&function_ctx, &declaration.return_type, &block.type_)?, - )?; - } - } - _ => { - substitution = compose_substitutions( - &function_ctx, - &substitution, - &unify(&function_ctx, &declaration.return_type, &block.type_)?, - )?; - } - } - - return Ok(( - ast::Function { - declaration: ast::FunctionDeclaration { - generic: declaration.generic.clone(), - name: declaration.name.clone(), - arguments: declaration.arguments.iter().map(|arg| arg.clone()).collect(), - return_type: declaration.return_type.clone(), - }, - block: block, - }, - substitution, - )); - } - - fn with_type_declaration( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - type_declaration: &ast::TypeDeclaration, - ) -> Result<(ast::TypeDeclaration, SubstitutionMap)> { - match type_declaration { - ast::TypeDeclaration::Struct(struct_) => { - let result = self.with_struct_declaration(ctx, struct_)?; - return Ok((ast::TypeDeclaration::Struct(result), SubstitutionMap::new())); - } - ast::TypeDeclaration::Primitive(primitive) => { - return Ok((ast::TypeDeclaration::Primitive(primitive.clone()), SubstitutionMap::new())); - } - ast::TypeDeclaration::Trait(trait_) => { - let (result, subst) = self.with_trait_declaration(ctx, incoming_substitutions, trait_)?; - return Ok((ast::TypeDeclaration::Trait(result), subst)); - } - } - } - - fn with_trait_declaration( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - trait_: &ast::TraitTypeDeclaration, - ) -> Result<(ast::TraitTypeDeclaration, SubstitutionMap)> { - let mut gen_ctx = ctx.add_generic(&trait_.generic)?; - gen_ctx - .environment - .insert("Self".to_string(), gen_ctx.environment[&trait_.name.name.value].clone()); - gen_ctx.current_self = Some(trait_.name.name.value.clone()); - let mut substitutions = incoming_substitutions.clone(); - let mut result_functions = vec![]; - for item in &trait_.functions { - match item { - ast::TraitItem::FunctionDeclaration(declaration) => { - let result_declaration = self.with_function_declaration(&gen_ctx, declaration)?; - result_functions.push(ast::TraitItem::FunctionDeclaration(result_declaration)); - } - } - } - Ok(( - ast::TraitTypeDeclaration { - generic: trait_.generic.clone(), - name: trait_.name.clone(), - functions: result_functions, - }, - substitutions, - )) - } - - fn with_struct_declaration(self: &Self, ctx: &Context, struct_: &ast::StructTypeDeclaration) -> Result { - let struct_ctx = ctx.add_generic(&struct_.generic)?; - let mut fields = vec![]; - for field in struct_.fields.iter() { - type_exists(&struct_ctx, &field.type_)?; - fields.push(ast::StructField { - name: field.name.clone(), - type_: field.type_.clone(), - }); - } - return Ok(ast::StructTypeDeclaration { - generic: struct_.generic.clone(), - name: struct_.name.clone(), - fields: fields, - }); - } - - fn with_impl( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - impl_: &ast::Impl, - ) -> Result<(ast::Impl, SubstitutionMap)> { - let mut impl_ctx = ctx.add_generic(&impl_.generic)?; - impl_ctx - .environment - .insert("Self".to_string(), impl_ctx.environment[&impl_.struct_.name.name.value].clone()); - impl_ctx.current_self = Some(impl_.struct_.name.name.value.clone()); - - let mut substitutions = incoming_substitutions.clone(); - type_exists( - &impl_ctx, - &ast::TypeUsage::new_named(&impl_.struct_.name.clone(), &ast::GenericUsage::Unknown), - )?; - let mut functions = vec![]; - for function in impl_.functions.iter() { - let (result, function_subs) = self.with_function(&impl_ctx, &substitutions, function)?; - substitutions = compose_substitutions(&impl_ctx, &substitutions, &function_subs)?; - functions.push(result); - } - return Ok(( - ast::Impl { - generic: impl_.generic.clone(), - trait_: impl_.trait_.clone(), - struct_: impl_.struct_.clone(), - functions: functions, - }, - substitutions, - )); - } - - fn with_block( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - block: &ast::Block, - ) -> Result<(ast::Block, SubstitutionMap)> { - let mut substitutions = incoming_substitutions.clone(); - let mut block_ctx = ctx.clone(); - // if return it's always never - // if last is expression it's that else unit - let mut has_return = false; - for statement in block.statements.iter() { - match statement { - ast::Statement::Return(_) => { - has_return = true; - } - _ => {} - } - } - let mut statements = vec![]; - for s in block.statements.iter() { - let (statement_ctx, result, statement_substitutions) = self.with_statement(&block_ctx, &substitutions, s)?; - block_ctx = statement_ctx; - substitutions = compose_substitutions(&block_ctx, &substitutions, &statement_substitutions)?; - statements.push(result); - } - if !has_return { - match block.statements.last().unwrap() { - ast::Statement::Expression(expr) => { - substitutions = compose_substitutions(&block_ctx, &substitutions, &unify(&block_ctx, &block.type_, &expr.type_)?)?; - } - _ => { - substitutions = compose_substitutions(&block_ctx, &substitutions, &unify(&block_ctx, &block.type_, &ast::new_unit())?)?; - } - } - } - let result_type = if has_return { - ast::new_never() - } else { - apply_substitution(&block_ctx, &substitutions, &block.type_)? - }; - let block_result = ast::Block { - statements: statements, - type_: result_type, - }; - return Ok((block_result, substitutions)); - } - - fn with_statement( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - statement: &ast::Statement, - ) -> Result<(Context, ast::Statement, SubstitutionMap)> { - match statement { - ast::Statement::Return(return_statement) => { - let (result, subst) = self.with_return_statement(ctx, incoming_substitutions, return_statement)?; - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; - return Ok((ctx.clone(), ast::Statement::Return(result), subst)); - } - ast::Statement::Let(let_statement) => { - let (let_ctx, result, subst) = self.with_let_statement(ctx, incoming_substitutions, let_statement)?; - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; - return Ok((let_ctx, ast::Statement::Let(result), subst)); - } - ast::Statement::Assignment(assignment_statement) => { - let (result, subst) = self.with_assignment_statement(ctx, incoming_substitutions, assignment_statement)?; - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; - return Ok((ctx.clone(), ast::Statement::Assignment(result), subst)); - } - ast::Statement::Expression(expression) => { - let (result, subst) = self.with_expression(ctx, incoming_substitutions, expression)?; - let subst = compose_substitutions(ctx, &incoming_substitutions, &subst)?; - return Ok((ctx.clone(), ast::Statement::Expression(result), subst)); - } - } - } - - fn with_return_statement( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - statement: &ast::ReturnStatement, - ) -> Result<(ast::ReturnStatement, SubstitutionMap)> { - let (result, subst) = self.with_expression(ctx, incoming_substitutions, &statement.source)?; - let mut substitution = compose_substitutions(ctx, &incoming_substitutions, &subst)?; - let mut is_never = false; - match &result.type_ { - ast::TypeUsage::Named(named) => { - if named.name.name.value == "!" { - is_never = true; - } - } - _ => {} - } - if !is_never { - substitution = compose_substitutions( - ctx, - &subst, - &unify(ctx, &ctx.current_function_return.as_ref().unwrap(), &result.type_)?, - )?; - } - - return Ok((ast::ReturnStatement { source: result }, substitution)); - } - - fn with_let_statement( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - statement: &ast::LetStatement, - ) -> Result<(Context, ast::LetStatement, SubstitutionMap)> { - let (result, subst) = self.with_expression(ctx, incoming_substitutions, &statement.expression)?; - let let_ctx = ctx.add_variable(statement.variable_name.name.value.clone(), &result.type_); - let substitution = compose_substitutions(ctx, &subst, &unify(ctx, &statement.type_, &result.type_)?)?; - return Ok(( - let_ctx, - ast::LetStatement { - variable_name: statement.variable_name.clone(), - expression: result, - type_: apply_substitution(ctx, &substitution, &statement.type_)?, - }, - substitution, - )); - } - - fn with_assignment_statement( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - statement: &ast::AssignmentStatement, - ) -> Result<(ast::AssignmentStatement, SubstitutionMap)> { - let (expr, subst) = self.with_expression(ctx, incoming_substitutions, &statement.expression)?; - let mut substitution = compose_substitutions(ctx, &incoming_substitutions, &subst)?; - - let result_as = ast::AssignmentStatement { - source: match &statement.source { - ast::AssignmentTarget::Variable(variable) => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &variable.type_, &expr.type_)?)?; - ast::AssignmentTarget::Variable(ast::VariableUsage { - name: variable.name.clone(), - type_parameters: variable.type_parameters.clone(), - type_: apply_substitution(ctx, &substitution, &variable.type_)?, - }) - } - ast::AssignmentTarget::StructAttr(struct_attr) => { - let (source, subst) = self.with_expression(ctx, &substitution, &struct_attr.source)?; - let mut subst = subst.clone(); - - let field_type = match get_attr(ctx, &NamedEntity::Variable(source.type_.clone()), &struct_attr.attribute)? { - StructAttr::Field(type_) => type_, - StructAttr::Method(_) => { - return Err(errors::TypingError::CannotAssignToMethod { - identifier: struct_attr.attribute.clone(), - }) - } - }; - - subst = compose_substitutions(ctx, &subst, &unify(ctx, &struct_attr.type_, &field_type)?)?; - - let substitution = compose_substitutions( - ctx, - &compose_substitutions(ctx, &substitution, &subst)?, - &unify(ctx, &struct_attr.type_, &expr.type_)?, - )?; - ast::AssignmentTarget::StructAttr(ast::StructGetter { - type_parameters: struct_attr.type_parameters.clone(), - source: source, - attribute: struct_attr.attribute.clone(), - type_: apply_substitution(ctx, &substitution, &struct_attr.type_)?, - }) - } - }, - expression: expr, - }; - return Ok((result_as, substitution)); - } - - fn with_expression( - self: &Self, - ctx: &Context, - incoming_substitutions: &SubstitutionMap, - expression: &ast::Expression, - ) -> Result<(ast::Expression, SubstitutionMap)> { - let mut substitution = incoming_substitutions.clone(); - let subexpression = Box::new(match &*expression.subexpression { - ast::Subexpression::LiteralInt(literal_int) => { - let (result, subst) = self.with_literal_int(ctx, &substitution, literal_int)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::LiteralInt(result) - } - ast::Subexpression::LiteralFloat(literal_float) => { - let (result, subst) = self.with_literal_float(ctx, &substitution, literal_float)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::LiteralFloat(result) - } - ast::Subexpression::LiteralBool(literal_bool) => { - let (result, subst) = self.with_literal_bool(ctx, &substitution, literal_bool)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::LiteralBool(result) - } - ast::Subexpression::LiteralString(literal_string) => { - let (result, subst) = self.with_literal_string(ctx, &substitution, literal_string)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::LiteralString(result) - } - ast::Subexpression::LiteralStruct(literal_struct) => { - let (result, subst) = self.with_literal_struct(ctx, &substitution, literal_struct)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::LiteralStruct(result) - } - ast::Subexpression::FunctionCall(function_call) => { - let (result, subst) = self.with_function_call(ctx, &substitution, function_call)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &function_call.type_)?)?; - ast::Subexpression::FunctionCall(result) - } - ast::Subexpression::VariableUsage(variable_usage) => { - let (result, subst) = self.with_variable_usage(ctx, &substitution, variable_usage)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &variable_usage.type_)?)?; - ast::Subexpression::VariableUsage(result) - } - ast::Subexpression::If(if_expression) => { - let (result, subst) = self.with_if(ctx, &substitution, if_expression)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::If(result) - } - ast::Subexpression::StructGetter(struct_getter) => { - let (result, subst) = self.with_struct_getter(ctx, &substitution, struct_getter)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::StructGetter(result) - } - ast::Subexpression::Block(block) => { - let (result, subst) = self.with_block_expression(ctx, &substitution, block)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.type_)?)?; - ast::Subexpression::Block(result) - } - ast::Subexpression::Op(op) => { - let (result, subst) = self.with_op(ctx, &substitution, op)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.left.type_)?)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &expression.type_, &result.right.type_)?)?; - ast::Subexpression::Op(result) - } - }); - - let expr = ast::Expression { - subexpression: subexpression, - type_: apply_substitution(ctx, &substitution, &expression.type_)?, - }; - return Ok((expr, substitution)); - } - - fn with_literal_int( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - literal_int: &ast::LiteralInt, - ) -> Result<(ast::LiteralInt, SubstitutionMap)> { - Ok(( - ast::LiteralInt { - value: literal_int.value.clone(), - type_: apply_substitution(ctx, &substitution, &literal_int.type_)?, - }, - substitution.clone(), - )) - } - - fn with_literal_float( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - literal_float: &ast::LiteralFloat, - ) -> Result<(ast::LiteralFloat, SubstitutionMap)> { - Ok(( - ast::LiteralFloat { - value: literal_float.value.clone(), - type_: apply_substitution(ctx, &substitution, &literal_float.type_)?, - }, - substitution.clone(), - )) - } - - fn with_literal_bool( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - literal_bool: &ast::LiteralBool, - ) -> Result<(ast::LiteralBool, SubstitutionMap)> { - Ok(( - ast::LiteralBool { - value: literal_bool.value.clone(), - type_: apply_substitution(ctx, &substitution, &literal_bool.type_)?, - }, - substitution.clone(), - )) - } - - fn with_literal_string( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - literal_string: &ast::LiteralString, - ) -> Result<(ast::LiteralString, SubstitutionMap)> { - Ok(( - ast::LiteralString { - value: literal_string.value.clone(), - type_: apply_substitution(ctx, &substitution, &literal_string.type_)?, - }, - substitution.clone(), - )) - } - - fn with_literal_struct( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - literal_struct: &ast::LiteralStruct, - ) -> Result<(ast::LiteralStruct, SubstitutionMap)> { - let mut substitution = substitution.clone(); - let struct_type = match &ctx.environment[&literal_struct.name.name.value] { - NamedEntity::NamedType(env_type) => match &env_type.is_a { - TypeType::Struct => env_type.type_construct(ctx, &literal_struct.type_parameters)?, - _ => { - return Err(errors::TypingError::NotAStructLiteral { - identifier: literal_struct.name.clone(), - }); - } - }, - _ => { - return Err(errors::TypingError::NotAStructLiteral { - identifier: literal_struct.name.clone(), - }); - } - }; - - if struct_type.fields.len() != literal_struct.fields.len() { - return Err(errors::TypingError::StructLiteralFieldsMismatch { - struct_name: literal_struct.name.clone(), - }); - } - let mut fields = vec![]; - for (type_field_name, type_field_type) in struct_type.fields.iter() { - let mut found = false; - let mut field_expression: Option = None; - let mut field_name: Option = None; - for field in literal_struct.fields.iter() { - if type_field_name == &field.0.name.value { - found = true; - let (result, subst) = self.with_expression(ctx, &substitution, &field.1)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, type_field_type, &result.type_)?)?; - field_expression = Some(result); - field_name = Some(field.0.clone()); - } - } - if !found { - return Err(errors::TypingError::StructLiteralFieldsMismatch { - struct_name: literal_struct.name.clone(), - }); - } - fields.push((field_name.unwrap(), field_expression.unwrap())); - } - Ok(( - ast::LiteralStruct { - type_parameters: literal_struct.type_parameters.clone(), - name: literal_struct.name.clone(), - fields: fields, - type_: apply_substitution(ctx, &substitution, &literal_struct.type_)?, - }, - substitution, - )) - } - - fn with_function_call( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - function_call: &ast::FunctionCall, - ) -> Result<(ast::FunctionCall, SubstitutionMap)> { - let mut substitution = substitution.clone(); - let (source, subst) = self.with_expression(ctx, &substitution, &function_call.source)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - match &source.type_ { - ast::TypeUsage::Function(fn_type) => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &function_call.type_, &*fn_type.return_type)?)?; - if function_call.arguments.len() != fn_type.arguments.len() { - return Err(errors::TypingError::ArgumentLengthMismatch {}); - } - } - ast::TypeUsage::Named(_) => { - return Err(errors::TypingError::FunctionCallNotAFunction {}); - } - _ => {} - } - let mut arguments = vec![]; - for (i, arg) in function_call.arguments.iter().enumerate() { - let (result, subst) = self.with_expression(ctx, &substitution, arg)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - - match &source.type_ { - ast::TypeUsage::Function(fn_type) => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &fn_type.arguments[i], &result.type_)?)?; - } - ast::TypeUsage::Named(_) => { - return Err(errors::TypingError::FunctionCallNotAFunction {}); - } - _ => {} - } - arguments.push(result); - } - Ok(( - ast::FunctionCall { - source: source.clone(), - arguments: arguments, - type_: apply_substitution(ctx, &substitution, &function_call.type_)?, - }, - substitution, - )) - } - - fn with_variable_usage( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - variable_usage: &ast::VariableUsage, - ) -> Result<(ast::VariableUsage, SubstitutionMap)> { - let mut substitution = substitution.clone(); - match &ctx.environment[&variable_usage.name.name.value] { - NamedEntity::NamedType(named_type) => { - let type_ = ast::TypeUsage::Namespace(ast::NamespaceTypeUsage::Type(ast::NamedTypeUsage { - name: variable_usage.name.clone(), - type_parameters: variable_usage.type_parameters.clone(), - })); - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &variable_usage.type_, &type_)?)?; - } - NamedEntity::Variable(variable) => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &variable_usage.type_, &variable)?)?; - } - NamedEntity::Function(function) => { - substitution = compose_substitutions( - ctx, - &substitution, - &unify( - ctx, - &variable_usage.type_, - &function.construct(ctx, &variable_usage.type_parameters)?, - )?, - )?; - } - } - Ok(( - ast::VariableUsage { - name: variable_usage.name.clone(), - type_parameters: variable_usage.type_parameters.clone(), // Redundant to type - type_: apply_substitution(ctx, &substitution, &variable_usage.type_)?, - }, - substitution, - )) - } - - fn with_if( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - if_expression: &ast::IfExpression, - ) -> Result<(ast::IfExpression, SubstitutionMap)> { - let mut substitution = substitution.clone(); - let (condition, subst) = self.with_expression(ctx, &substitution, &if_expression.condition)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - - let (block_result, subst) = self.with_block(ctx, &substitution, &if_expression.block)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - - let else_ = match &if_expression.else_ { - Some(else_) => { - let (result, subst) = self.with_block(ctx, &substitution, else_)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - Some(result) - } - None => None, - }; - - match &condition.type_ { - ast::TypeUsage::Named(named) => { - if named.name.name.value != "bool" { - return Err(errors::TypingError::IfConditionMustBeBool {}); - } - } - ast::TypeUsage::Function(_) => { - return Err(errors::TypingError::IfConditionMustBeBool {}); - } - _ => {} - }; - - let mut never_count = 0; - match &block_result.type_ { - ast::TypeUsage::Named(named) => { - if named.name.name.value != "!" { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &if_expression.type_, &block_result.type_)?)?; - } else { - never_count += 1; - } - } - _ => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &if_expression.type_, &block_result.type_)?)?; - } - }; - - match &else_ { - Some(else_block) => { - match &else_block.type_ { - ast::TypeUsage::Named(named) => { - if named.name.name.value != "!" { - substitution = - compose_substitutions(ctx, &substitution, &unify(ctx, &if_expression.type_, &else_block.type_)?)?; - } else { - never_count += 1; - } - } - _ => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &if_expression.type_, &else_block.type_)?)?; - } - }; - } - None => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &if_expression.type_, &ast::new_unit())?)?; - } - } - - let result_type = if never_count == 2 { - ast::new_never() - } else { - apply_substitution(ctx, &substitution, &if_expression.type_)? - }; - - Ok(( - ast::IfExpression { - condition: condition, - block: block_result, - else_: else_, - type_: result_type, - }, - substitution, - )) - } - - fn with_struct_getter( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - struct_getter: &ast::StructGetter, - ) -> Result<(ast::StructGetter, SubstitutionMap)> { - let mut substitution = substitution.clone(); - let (source, subst) = self.with_expression(ctx, &substitution, &struct_getter.source)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - - let field_type = match get_attr(ctx, &NamedEntity::Variable(source.type_.clone()), &struct_getter.attribute)? { - StructAttr::Field(type_) => type_, - StructAttr::Method(constructor) => constructor.construct(ctx, &struct_getter.type_parameters)?, - }; - - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &struct_getter.type_, &field_type)?)?; - - Ok(( - ast::StructGetter { - type_parameters: struct_getter.type_parameters.clone(), - source: source, - attribute: struct_getter.attribute.clone(), - type_: apply_substitution(ctx, &substitution, &struct_getter.type_)?, - }, - substitution, - )) - } - - fn with_block_expression( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - block: &ast::Block, - ) -> Result<(ast::Block, SubstitutionMap)> { - let mut substitution = substitution.clone(); - let (result, subst) = self.with_block(ctx, &substitution, &block)?; - substitution = compose_substitutions(ctx, &substitution, &subst)?; - Ok((result, substitution)) - } - - fn with_op( - self: &Self, - ctx: &Context, - substitution: &SubstitutionMap, - op: &ast::Operation, - ) -> Result<(ast::Operation, SubstitutionMap)> { - let mut substitution = substitution.clone(); - let (expr_left, subst_left) = self.with_expression(ctx, &substitution, &op.left)?; - let (expr_right, subst_right) = self.with_expression(ctx, &substitution, &op.right)?; - substitution = compose_substitutions(ctx, &substitution, &subst_left)?; - substitution = compose_substitutions(ctx, &substitution, &subst_right)?; - Ok(( - ast::Operation { - left: expr_left, - op: op.op.clone(), - right: expr_right, - }, - substitution, - )) - } -} diff --git a/src/types.rs b/src/types.rs deleted file mode 100644 index 9748860..0000000 --- a/src/types.rs +++ /dev/null @@ -1,58 +0,0 @@ -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum Signedness { - Signed, - Unsigned, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum IntBitness { - X8, - X16, - X32, - X64, - X128, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum FloatBitness { - X32, - X64, - X128, -} - -#[derive(Clone, Eq, PartialEq, Hash)] -pub struct IntTypeDef { - pub signedness: Signedness, - pub bitness: IntBitness, -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct FloatTypeDef { - pub bitness: FloatBitness, -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct FunctionTypeDef { - pub arguments: Vec, - pub return_type: Box, -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub enum Type { - Bool, - Int(IntTypeDef), - Float(FloatTypeDef), - Function(FunctionTypeDef), - // String(StringTypeDef), - // Struct(StructTypeDef), - // Trait(TraitTypeDef), - // Void, - // Never, -} - -/// Used for places where type info may or may not be solved. -#[derive(Clone, Eq, PartialEq, Hash)] -pub enum SpecifiedType { - Unknown, - Type(Type), -} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9379317 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "outDir": "./dist", + "rootDir": ".", + "types": ["bun-types"] + }, + "include": ["./**/*"], + "exclude": ["node_modules", "dist", "test/**/*"] +}