Experimenting with the LSP
This commit is contained in:
Generated
+713
-9
@@ -2,6 +2,15 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.102"
|
version = "1.0.102"
|
||||||
@@ -20,12 +29,28 @@ version = "2.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "borrow-or-share"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boxcar"
|
name = "boxcar"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e"
|
checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.2"
|
version = "3.20.2"
|
||||||
@@ -38,6 +63,12 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.56"
|
version = "1.2.56"
|
||||||
@@ -63,12 +94,51 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "6.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"hashbrown 0.14.5",
|
||||||
|
"lock_api",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
@@ -92,6 +162,26 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
@@ -110,6 +200,93 @@ version = "0.1.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fluent-uri"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e"
|
||||||
|
dependencies = [
|
||||||
|
"borrow-or-share",
|
||||||
|
"ref-cast",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fxhash"
|
name = "fxhash"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -119,6 +296,30 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "globset"
|
||||||
|
version = "0.4.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"bstr",
|
||||||
|
"log",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "2.7.1"
|
version = "2.7.1"
|
||||||
@@ -130,12 +331,46 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httparse"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ignore"
|
||||||
|
version = "0.4.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"globset",
|
||||||
|
"log",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"same-file",
|
||||||
|
"walkdir",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.13.0"
|
||||||
@@ -143,7 +378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown 0.16.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -156,7 +391,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"llvm-sys",
|
"llvm-sys",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"thiserror",
|
"thiserror 2.0.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -179,6 +414,12 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -233,6 +474,22 @@ dependencies = [
|
|||||||
"leaf_parser",
|
"leaf_parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "leaf_lsp"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"boxcar",
|
||||||
|
"leaf_allocators",
|
||||||
|
"leaf_assembly",
|
||||||
|
"leaf_compiler",
|
||||||
|
"leaf_parser",
|
||||||
|
"rangemap",
|
||||||
|
"rust_search",
|
||||||
|
"scc",
|
||||||
|
"tokio",
|
||||||
|
"tower-lsp-server",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leaf_parser"
|
name = "leaf_parser"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -249,6 +506,15 @@ version = "0.2.182"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "llvm-sys"
|
name = "llvm-sys"
|
||||||
version = "211.0.0"
|
version = "211.0.0"
|
||||||
@@ -263,12 +529,69 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ls-types"
|
||||||
|
version = "0.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b73932659f38b27a0145cbcba778739a7d76162f6534329b3ca8866125620996"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"fluent-uri",
|
||||||
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peg"
|
name = "peg"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -296,6 +619,18 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "132dca9b868d927b35b5dd728167b2dee150eb1ad686008fc71ccb298b776fca"
|
checksum = "132dca9b868d927b35b5dd728167b2dee150eb1ad686008fc71ccb298b776fca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "percent-encoding"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@@ -314,12 +649,100 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rangemap"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
|
||||||
|
dependencies = [
|
||||||
|
"ref-cast-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast-impl"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-lite"
|
name = "regex-lite"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30"
|
checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust_search"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d27d7be20245d289c9dde663f06521de08663d73cbaefc45785aa65d02022378"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
"ignore",
|
||||||
|
"num_cpus",
|
||||||
|
"regex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -336,20 +759,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "16c7f49c9d5caa3bf4b3106900484b447b9253fe99670ceb81cb6cb5027855e1"
|
checksum = "16c7f49c9d5caa3bf4b3106900484b447b9253fe99670ceb81cb6cb5027855e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scc"
|
name = "same-file"
|
||||||
version = "3.6.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6012e652611b2fdcb557a7b4be8cee00d8be19397c70011906a68aa4dac2fe37"
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scc"
|
||||||
|
version = "3.6.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45bb5ce9efd4a6e7b0f86c2697fe4c1d78d1f4e6d988c54b752d577cafe22fe8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"saa",
|
"saa",
|
||||||
"sdd",
|
"sdd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sdd"
|
name = "scopeguard"
|
||||||
version = "4.6.5"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4becc2f27bd39aafb78a8a1b4e1d6877ed0a6b5bf096722ed538dc028367a9b5"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sdd"
|
||||||
|
version = "4.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b21a75f5913ab130e4b369fb8693be25f29b983e2ecad4279df9bfa5dd8aaf3e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
@@ -357,12 +795,73 @@ version = "1.0.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.149"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.117"
|
||||||
@@ -374,13 +873,39 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sync_wrapper"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.18"
|
version = "2.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl 2.0.18",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -394,6 +919,117 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.50.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"pin-project-lite",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-layer"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-lsp-server"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f0e711655c89181a6bc6a2cc348131fcd9680085f5b06b6af13427a393a6e72"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"dashmap",
|
||||||
|
"futures",
|
||||||
|
"httparse",
|
||||||
|
"ls-types",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tower",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-service"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-lite",
|
||||||
|
"tracing-attributes",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-attributes"
|
||||||
|
version = "0.1.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-core"
|
||||||
|
version = "0.1.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
@@ -412,6 +1048,68 @@ version = "0.2.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[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-util"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.40"
|
version = "0.8.40"
|
||||||
@@ -431,3 +1129,9 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["allocators", "assembly", "compiler", "parser", "backends/llvm"]
|
members = ["allocators", "assembly", "compiler", "parser", "backends/llvm", "lsp"]
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ pub struct SyncArenaAllocator {
|
|||||||
allocations: Vec<AllocationEntry>,
|
allocations: Vec<AllocationEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SyncArenaAllocator {
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.bump.lock().unwrap().reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Allocator for SyncArenaAllocator {
|
impl Allocator for SyncArenaAllocator {
|
||||||
unsafe fn alloc_unsafe(&self, data: *const u8, layout: Layout, drop_fn: DropFn) -> *mut u8 {
|
unsafe fn alloc_unsafe(&self, data: *const u8, layout: Layout, drop_fn: DropFn) -> *mut u8 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
assembly::Assembly,
|
assembly::Assembly,
|
||||||
types::Type,
|
types::Type,
|
||||||
values::{AnyConst, AnyValue, Value, ValueFlags},
|
values::{AnyConst, AnyValue, Value, ValueFlags, default_associated_values},
|
||||||
};
|
};
|
||||||
use derive_more::{Debug, Display};
|
use derive_more::{Debug, Display};
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
@@ -51,21 +51,10 @@ impl<'l> Value<'l> for &'l StructT<'l> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
|
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
|
||||||
todo!()
|
default_associated_values(self, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_value(&self) -> AnyValue<'l> {
|
fn as_any_value(&self) -> AnyValue<'l> {
|
||||||
AnyValue::Constant(AnyConst::Type(Type::Struct(self)))
|
AnyValue::Constant(AnyConst::Type(Type::Struct(self)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DebugFields<'l, 'r>(&'r OnceLock<FieldMap<'l>>);
|
|
||||||
|
|
||||||
impl std::fmt::Debug for DebugFields<'_, '_> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self.0.get() {
|
|
||||||
Some(v) => std::fmt::Debug::fmt(v, f),
|
|
||||||
None => f.write_str("{}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ impl<'l> Value<'l> for Float {
|
|||||||
Float::F16(v) => v.ty(),
|
Float::F16(v) => v.ty(),
|
||||||
Float::F32(v) => v.ty(),
|
Float::F32(v) => v.ty(),
|
||||||
Float::F64(v) => v.ty(),
|
Float::F64(v) => v.ty(),
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,13 +198,13 @@ impl<'l> Value<'l> for AnyConst<'l> {
|
|||||||
Self::Str(s) => s.ty(),
|
Self::Str(s) => s.ty(),
|
||||||
Self::Struct(t, _) => Type::Struct(t),
|
Self::Struct(t, _) => Type::Struct(t),
|
||||||
Self::SizeOf(_) => Type::USIZE,
|
Self::SizeOf(_) => Type::USIZE,
|
||||||
_ => todo!("{self:?}"),
|
Self::Function(f) => Type::Func(f.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> super::ValueFlags {
|
fn flags(&self) -> super::ValueFlags {
|
||||||
match self {
|
match self {
|
||||||
AnyConst::Function(f) => ValueFlags::Function,
|
AnyConst::Function(_) => ValueFlags::Function,
|
||||||
AnyConst::Type(_) => ValueFlags::Type,
|
AnyConst::Type(_) => ValueFlags::Type,
|
||||||
_ => ValueFlags::Const,
|
_ => ValueFlags::Const,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,17 @@ use derive_more::Debug;
|
|||||||
use leaf_parser::{LineCol, ParseError};
|
use leaf_parser::{LineCol, ParseError};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::SourceFile;
|
use crate::{SourceFile, metadata::CodePosition};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Code {
|
||||||
Unknown = 0x0000,
|
Unknown = 0x0000,
|
||||||
|
|
||||||
Parsing = 0x0100,
|
Parsing = 0x0100,
|
||||||
@@ -36,30 +43,40 @@ pub enum Location {
|
|||||||
file: SourceFile,
|
file: SourceFile,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
},
|
},
|
||||||
Position {
|
|
||||||
#[debug("{:?}", file.file)]
|
|
||||||
file: SourceFile,
|
|
||||||
position: LineCol,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl Location {
|
||||||
pub struct CompilationError {
|
pub fn file(&self) -> Option<&SourceFile> {
|
||||||
|
match self {
|
||||||
|
Location::None => None,
|
||||||
|
Location::Range { file, .. } => Some(file),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn range(&self) -> Range<usize> {
|
||||||
|
match self {
|
||||||
|
Location::None => 0..0,
|
||||||
|
Location::Range { range, .. } => range.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Diagnostic {
|
||||||
pub kind: Kind,
|
pub kind: Kind,
|
||||||
|
pub code: Code,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
pub location: Location,
|
pub position: CodePosition,
|
||||||
pub cause: Option<Box<CompilationError>>,
|
pub cause: Option<Box<Diagnostic>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilationError {
|
impl Diagnostic {
|
||||||
pub fn parsing(file: SourceFile, err: ParseError<LineCol>) -> Self {
|
pub fn parsing_err(file: SourceFile, err: ParseError<LineCol>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind: Kind::Parsing,
|
kind: Kind::Error,
|
||||||
|
code: Code::Parsing,
|
||||||
message: err.to_string(),
|
message: err.to_string(),
|
||||||
location: Location::Position {
|
position: CodePosition::new(file, err.location.offset..err.location.offset + 1),
|
||||||
file,
|
|
||||||
position: err.location,
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
use crate::{diagnostics::Diagnostic, metadata::CodePosition};
|
||||||
|
use leaf_assembly::values::AnyValue;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Event<'l> {
|
||||||
|
Symbol {
|
||||||
|
value: AnyValue<'l>,
|
||||||
|
position: CodePosition,
|
||||||
|
},
|
||||||
|
Definition {
|
||||||
|
value: AnyValue<'l>,
|
||||||
|
position: CodePosition,
|
||||||
|
},
|
||||||
|
Diagnostic(Diagnostic),
|
||||||
|
}
|
||||||
+50
-9
@@ -1,4 +1,4 @@
|
|||||||
use crate::{error::CompilationError, scope::Scope};
|
use crate::{diagnostics::Diagnostic, events::Event, metadata::Metadata, scope::Scope};
|
||||||
use arcstr::literal_substr;
|
use arcstr::literal_substr;
|
||||||
use leaf_allocators::SyncAllocator;
|
use leaf_allocators::SyncAllocator;
|
||||||
use leaf_assembly::{
|
use leaf_assembly::{
|
||||||
@@ -8,9 +8,16 @@ use leaf_assembly::{
|
|||||||
values::{AnyConst, AnyValue},
|
values::{AnyConst, AnyValue},
|
||||||
};
|
};
|
||||||
use leaf_parser::{SourceCode, ast};
|
use leaf_parser::{SourceCode, ast};
|
||||||
use std::{collections::VecDeque, ops::Deref, sync::Arc};
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
collections::{HashMap, VecDeque},
|
||||||
|
ops::Deref,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
mod error;
|
pub mod diagnostics;
|
||||||
|
pub mod events;
|
||||||
|
pub mod metadata;
|
||||||
mod scope;
|
mod scope;
|
||||||
|
|
||||||
pub type SourceFile = Arc<SourceCode>;
|
pub type SourceFile = Arc<SourceCode>;
|
||||||
@@ -19,7 +26,9 @@ type FuncQueue<'l> = VecDeque<(&'l Function<'l>, Arc<ast::Block>, Scope<'l>)>;
|
|||||||
|
|
||||||
pub struct CompilationContext<'l> {
|
pub struct CompilationContext<'l> {
|
||||||
ctx: &'l Context<'l>,
|
ctx: &'l Context<'l>,
|
||||||
alloc: &'l dyn SyncAllocator,
|
_alloc: &'l dyn SyncAllocator,
|
||||||
|
event_callbacks: Vec<Box<dyn Fn(&Event<'_>) + Send + Sync + 'static>>,
|
||||||
|
metadata: Mutex<HashMap<(AnyValue<'l>, TypeId), Arc<dyn Metadata>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'l> Deref for CompilationContext<'l> {
|
impl<'l> Deref for CompilationContext<'l> {
|
||||||
@@ -33,8 +42,20 @@ impl<'l> Deref for CompilationContext<'l> {
|
|||||||
impl<'l> CompilationContext<'l> {
|
impl<'l> CompilationContext<'l> {
|
||||||
pub fn new(alloc: &'l dyn SyncAllocator) -> Self {
|
pub fn new(alloc: &'l dyn SyncAllocator) -> Self {
|
||||||
Self {
|
Self {
|
||||||
alloc,
|
_alloc: alloc,
|
||||||
ctx: Context::new(alloc),
|
ctx: Context::new(alloc),
|
||||||
|
metadata: Default::default(),
|
||||||
|
event_callbacks: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_event_callback(&mut self, callback: impl Fn(&Event<'_>) + Send + Sync + 'static) {
|
||||||
|
self.event_callbacks.push(Box::new(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_event(&self, event: Event) {
|
||||||
|
for callback in &self.event_callbacks {
|
||||||
|
callback(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,32 +63,52 @@ impl<'l> CompilationContext<'l> {
|
|||||||
self.ctx.get_assembly(ident)
|
self.ctx.get_assembly(ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(private_bounds)]
|
||||||
|
pub fn get_metadata<T: Metadata>(&self, v: AnyValue<'l>) -> Option<Arc<T>> {
|
||||||
|
let arc = {
|
||||||
|
let metadata = self.metadata.lock().unwrap();
|
||||||
|
metadata.get(&(v, TypeId::of::<T>()))?.clone()
|
||||||
|
};
|
||||||
|
let ptr = Arc::into_raw(arc);
|
||||||
|
let ptr = ptr as *const T;
|
||||||
|
unsafe { Some(Arc::from_raw(ptr)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(private_bounds)]
|
||||||
|
pub fn set_metadata<T: Metadata>(&self, v: AnyValue<'l>, meta: T) -> Arc<T> {
|
||||||
|
let meta = Arc::new(meta);
|
||||||
|
self.metadata
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert((v, TypeId::of::<T>()), meta.clone());
|
||||||
|
meta
|
||||||
|
}
|
||||||
|
|
||||||
pub fn extend(
|
pub fn extend(
|
||||||
&'l self,
|
&'l self,
|
||||||
ident: AssemblyIdentifier,
|
ident: AssemblyIdentifier,
|
||||||
sources: &[Arc<SourceCode>],
|
sources: &[Arc<SourceCode>],
|
||||||
) -> Result<(), CompilationError> {
|
) -> Result<(), Diagnostic> {
|
||||||
let assembly = self.ctx.get_or_create_assembly(ident.clone());
|
let assembly = self.ctx.get_or_create_assembly(ident.clone());
|
||||||
|
|
||||||
let mut units = Vec::with_capacity(sources.len());
|
let mut units = Vec::with_capacity(sources.len());
|
||||||
for src in sources {
|
for src in sources {
|
||||||
match leaf_parser::parse(src) {
|
match leaf_parser::parse(src) {
|
||||||
Ok(unit) => units.push(unit),
|
Ok(unit) => units.push(unit),
|
||||||
Err(err) => return Err(CompilationError::parsing(src.clone(), err)),
|
Err(err) => return Err(Diagnostic::parsing_err(src.clone(), err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scopes: Vec<_> = sources
|
let mut scopes: Vec<_> = sources
|
||||||
.iter()
|
.iter()
|
||||||
.map(|src| {
|
.map(|src| {
|
||||||
let mut scope = Scope::new(assembly, src.clone());
|
let mut scope = Scope::new(self, assembly, src.clone());
|
||||||
macro_rules! insert_types {
|
macro_rules! insert_types {
|
||||||
($($id:literal : $ty:expr,)*) => {
|
($($id:literal : $ty:expr,)*) => {
|
||||||
$(
|
$(
|
||||||
scope.insert(
|
scope.insert(
|
||||||
literal_substr!($id),
|
literal_substr!($id),
|
||||||
AnyValue::Constant(AnyConst::Type($ty.into())),
|
AnyValue::Constant(AnyConst::Type($ty.into())),
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
)*
|
)*
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ use leaf_parser::SourceCode;
|
|||||||
use std::{
|
use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let start = Instant::now();
|
||||||
let alloc = SyncArenaAllocator::default();
|
let alloc = SyncArenaAllocator::default();
|
||||||
let context = CompilationContext::new(&alloc);
|
let context = CompilationContext::new(&alloc);
|
||||||
let ident = AssemblyIdentifier {
|
let ident = AssemblyIdentifier {
|
||||||
@@ -32,6 +34,7 @@ fn main() {
|
|||||||
println!("{:#?}", err);
|
println!("{:#?}", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let time = start.elapsed();
|
||||||
|
|
||||||
let assembly = context.get_assembly(&ident).unwrap();
|
let assembly = context.get_assembly(&ident).unwrap();
|
||||||
println!("{:#?}\n", assembly);
|
println!("{:#?}\n", assembly);
|
||||||
@@ -60,4 +63,6 @@ fn main() {
|
|||||||
target_machine
|
target_machine
|
||||||
.write_to_file(&module, FileType::Assembly, Path::new("out.asm"))
|
.write_to_file(&module, FileType::Assembly, Path::new("out.asm"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
println!("Codegen time: {time:?}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
use leaf_parser::{LineCol, SourceCode};
|
||||||
|
use std::{
|
||||||
|
any::Any,
|
||||||
|
ops::Range,
|
||||||
|
sync::{Arc, OnceLock},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait Metadata: Any + Send + Sync {}
|
||||||
|
impl<T: Any + Send + Sync> Metadata for T {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CodePosition {
|
||||||
|
pub file: Arc<SourceCode>,
|
||||||
|
pub range: Range<usize>,
|
||||||
|
line_col: OnceLock<Range<LineCol>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CodePosition {
|
||||||
|
pub fn new(file: Arc<SourceCode>, range: Range<usize>) -> Self {
|
||||||
|
Self {
|
||||||
|
file,
|
||||||
|
range,
|
||||||
|
line_col: OnceLock::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn line_col(&self) -> &Range<LineCol> {
|
||||||
|
self.line_col.get_or_init(|| {
|
||||||
|
let mut line_col_range = LineCol {
|
||||||
|
line: 0,
|
||||||
|
column: 0,
|
||||||
|
offset: self.range.start,
|
||||||
|
}..LineCol {
|
||||||
|
line: 0,
|
||||||
|
column: 0,
|
||||||
|
offset: self.range.end,
|
||||||
|
};
|
||||||
|
let mut line = 0;
|
||||||
|
let mut col = 0;
|
||||||
|
|
||||||
|
for (byte_idx, ch) in self.file.text.char_indices() {
|
||||||
|
if byte_idx == self.range.start {
|
||||||
|
line_col_range.start.line = line;
|
||||||
|
line_col_range.start.column = col;
|
||||||
|
}
|
||||||
|
if byte_idx == self.range.end {
|
||||||
|
line_col_range.end.line = line;
|
||||||
|
line_col_range.end.column = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch == '\n' {
|
||||||
|
line += 1;
|
||||||
|
col = 0;
|
||||||
|
} else {
|
||||||
|
col += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.range.end == self.file.text.len() {
|
||||||
|
line_col_range.end.line = line;
|
||||||
|
line_col_range.end.column = col;
|
||||||
|
}
|
||||||
|
line_col_range
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
+143
-142
@@ -1,4 +1,4 @@
|
|||||||
use crate::{FuncQueue, error::*};
|
use crate::{CompilationContext, FuncQueue, diagnostics::*, events::Event, metadata::CodePosition};
|
||||||
use arcstr::{Substr, literal_substr};
|
use arcstr::{Substr, literal_substr};
|
||||||
use leaf_assembly::{
|
use leaf_assembly::{
|
||||||
assembly::Assembly,
|
assembly::Assembly,
|
||||||
@@ -46,31 +46,35 @@ impl<'l, 'r, 'a> ExpressionContext<'l, 'r> {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Variable<'l> {
|
struct Variable<'l> {
|
||||||
value: Arc<OnceLock<AnyValue<'l>>>,
|
value: Arc<OnceLock<AnyValue<'l>>>,
|
||||||
mutable: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Scope<'l> {
|
pub struct Scope<'l> {
|
||||||
|
ctx: &'l CompilationContext<'l>,
|
||||||
assembly: &'l Assembly<'l>,
|
assembly: &'l Assembly<'l>,
|
||||||
source: Arc<SourceCode>,
|
source: Arc<SourceCode>,
|
||||||
values: HashMap<Substr, Variable<'l>>,
|
values: HashMap<Substr, Variable<'l>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'l> Scope<'l> {
|
impl<'l> Scope<'l> {
|
||||||
pub fn new(assembly: &'l Assembly<'l>, source: Arc<SourceCode>) -> Self {
|
pub fn new(
|
||||||
|
ctx: &'l CompilationContext<'l>,
|
||||||
|
assembly: &'l Assembly<'l>,
|
||||||
|
source: Arc<SourceCode>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
ctx,
|
||||||
assembly,
|
assembly,
|
||||||
source,
|
source,
|
||||||
values: HashMap::default(),
|
values: HashMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, name: Substr, value: AnyValue<'l>, mutable: bool) {
|
pub fn insert(&mut self, name: Substr, value: AnyValue<'l>) {
|
||||||
self.values.insert(
|
self.values.insert(
|
||||||
name,
|
name,
|
||||||
Variable {
|
Variable {
|
||||||
value: Arc::new(OnceLock::from(value)),
|
value: Arc::new(OnceLock::from(value)),
|
||||||
mutable,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -82,7 +86,6 @@ impl<'l> Scope<'l> {
|
|||||||
name.clone(),
|
name.clone(),
|
||||||
Variable {
|
Variable {
|
||||||
value: Arc::default(),
|
value: Arc::default(),
|
||||||
mutable: false,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -93,7 +96,7 @@ impl<'l> Scope<'l> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
decl: &[ConstDecl],
|
decl: &[ConstDecl],
|
||||||
fn_queue: &mut FuncQueue<'l>,
|
fn_queue: &mut FuncQueue<'l>,
|
||||||
) -> Result<(), CompilationError> {
|
) -> Result<(), Diagnostic> {
|
||||||
for val in decl {
|
for val in decl {
|
||||||
let expr = self.compile_expression(
|
let expr = self.compile_expression(
|
||||||
&val.value,
|
&val.value,
|
||||||
@@ -105,13 +108,19 @@ impl<'l> Scope<'l> {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
match &val.names {
|
match &val.names {
|
||||||
NamePattern::Single(ident) => self
|
NamePattern::Single(ident) => {
|
||||||
.values
|
self.values
|
||||||
.get_mut(&ident.0)
|
.get_mut(&ident.0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.value
|
.value
|
||||||
.set(expr)
|
.set(expr)
|
||||||
.unwrap(),
|
.unwrap();
|
||||||
|
|
||||||
|
self.ctx.emit_event(Event::Definition {
|
||||||
|
value: expr,
|
||||||
|
position: CodePosition::new(self.source.clone(), ident.range()),
|
||||||
|
});
|
||||||
|
}
|
||||||
NamePattern::Tuple(_) => todo!(),
|
NamePattern::Tuple(_) => todo!(),
|
||||||
NamePattern::List(_) => todo!(),
|
NamePattern::List(_) => todo!(),
|
||||||
}
|
}
|
||||||
@@ -124,7 +133,7 @@ impl<'l> Scope<'l> {
|
|||||||
func: &'l Function<'l>,
|
func: &'l Function<'l>,
|
||||||
block: &Arc<ast::Block>,
|
block: &Arc<ast::Block>,
|
||||||
fn_queue: &mut FuncQueue<'l>,
|
fn_queue: &mut FuncQueue<'l>,
|
||||||
) -> Result<(), CompilationError> {
|
) -> Result<(), Diagnostic> {
|
||||||
let mut builder = func.create_body().unwrap();
|
let mut builder = func.create_body().unwrap();
|
||||||
let mut ret = self.compile_block(
|
let mut ret = self.compile_block(
|
||||||
block,
|
block,
|
||||||
@@ -159,42 +168,42 @@ impl<'l> Scope<'l> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
ctx: &mut ExpressionContext<'l, '_>,
|
ctx: &mut ExpressionContext<'l, '_>,
|
||||||
) -> Result<AnyValue<'l>, CompilationError> {
|
) -> Result<AnyValue<'l>, Diagnostic> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Ident(Ident(name)) => match self.values.get(name) {
|
Expr::Ident(Ident(name)) => match self.values.get(name) {
|
||||||
None => Err(CompilationError {
|
None => Err(Diagnostic {
|
||||||
kind: Kind::SymbolNotFound,
|
kind: Kind::Error,
|
||||||
|
code: Code::SymbolNotFound,
|
||||||
message: format!("Symbol `{name}` does not exist in the current scope."),
|
message: format!("Symbol `{name}` does not exist in the current scope."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), name.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: name.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
}),
|
}),
|
||||||
Some(Variable { value, .. }) => match value.get() {
|
Some(Variable { value, .. }) => match value.get() {
|
||||||
None => Err(CompilationError {
|
None => Err(Diagnostic {
|
||||||
kind: Kind::UninitializedSymbol,
|
kind: Kind::Error,
|
||||||
|
code: Code::UninitializedSymbol,
|
||||||
message: format!("Symbol `{name}` is not initialized at this time."),
|
message: format!("Symbol `{name}` is not initialized at this time."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), name.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: name.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
}),
|
}),
|
||||||
Some(value) => Ok(*value),
|
Some(value) => {
|
||||||
|
self.ctx.emit_event(Event::Symbol {
|
||||||
|
value: *value,
|
||||||
|
position: CodePosition::new(self.source.clone(), name.range()),
|
||||||
|
});
|
||||||
|
Ok(*value)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::Func(func) => self
|
Expr::Func(func) => self
|
||||||
.make_function(func, ctx)
|
.make_function(func, ctx)
|
||||||
.map(|f| AnyValue::Constant(AnyConst::Function(f)))
|
.map(|f| AnyValue::Constant(AnyConst::Function(f)))
|
||||||
.map_err(|err| CompilationError {
|
.map_err(|err| Diagnostic {
|
||||||
kind: Kind::FunctionCompilationFailed,
|
kind: Kind::Error,
|
||||||
|
code: Code::FunctionCompilationFailed,
|
||||||
message: "Could not compile function.".to_string(),
|
message: "Could not compile function.".to_string(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), func.text.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: func.text.range(),
|
|
||||||
},
|
|
||||||
cause: Some(Box::new(err)),
|
cause: Some(Box::new(err)),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -210,18 +219,16 @@ impl<'l> Scope<'l> {
|
|||||||
_ => n.text.parse::<$ty>(),
|
_ => n.text.parse::<$ty>(),
|
||||||
}
|
}
|
||||||
.map(|v| AnyValue::Constant(AnyConst::Int(Int::$id(v))))
|
.map(|v| AnyValue::Constant(AnyConst::Int(Int::$id(v))))
|
||||||
.map_err(|_| CompilationError {
|
.map_err(|_| Diagnostic {
|
||||||
kind: Kind::InvalidInteger,
|
kind: Kind::Error,
|
||||||
|
code: Code::InvalidInteger,
|
||||||
message: format!("`{}` is not a valid integer.", n.text),
|
message: format!("`{}` is not a valid integer.", n.text),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), n.text.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: n.text.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
match n.r#type.as_ref().map(|v| v.as_str()) {
|
let value = match n.r#type.as_ref().map(|v| v.as_str()) {
|
||||||
None if ctx.type_hint == Some(Type::I8) => parse_number!(i8, I8),
|
None if ctx.type_hint == Some(Type::I8) => parse_number!(i8, I8),
|
||||||
None if ctx.type_hint == Some(Type::I16) => parse_number!(i16, I16),
|
None if ctx.type_hint == Some(Type::I16) => parse_number!(i16, I16),
|
||||||
None if ctx.type_hint == Some(Type::I32) => parse_number!(i32, I32),
|
None if ctx.type_hint == Some(Type::I32) => parse_number!(i32, I32),
|
||||||
@@ -248,16 +255,19 @@ impl<'l> Scope<'l> {
|
|||||||
Some("u64") => parse_number!(u64, U64),
|
Some("u64") => parse_number!(u64, U64),
|
||||||
Some("u128") => parse_number!(u128, U128),
|
Some("u128") => parse_number!(u128, U128),
|
||||||
Some("usize") => parse_number!(u64, USize),
|
Some("usize") => parse_number!(u64, USize),
|
||||||
Some(ty) => Err(CompilationError {
|
Some(ty) => Err(Diagnostic {
|
||||||
kind: Kind::InvalidIntegerType,
|
kind: Kind::Error,
|
||||||
|
code: Code::InvalidIntegerType,
|
||||||
message: format!("`{ty}` is not a valid integer type."),
|
message: format!("`{ty}` is not a valid integer type."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), n.text.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: n.text.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
}),
|
}),
|
||||||
}
|
}?;
|
||||||
|
self.ctx.emit_event(Event::Symbol {
|
||||||
|
value: value,
|
||||||
|
position: CodePosition::new(self.source.clone(), n.text.range()),
|
||||||
|
});
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Access(expr) => {
|
Expr::Access(expr) => {
|
||||||
@@ -269,17 +279,22 @@ impl<'l> Scope<'l> {
|
|||||||
if let Some(value) = value.get_associated_value(&field.0) {
|
if let Some(value) = value.get_associated_value(&field.0) {
|
||||||
return Ok(value);
|
return Ok(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let value = 'value: {
|
||||||
match value.ty() {
|
match value.ty() {
|
||||||
Type::Struct(StructT { fields, .. }) => {
|
Type::Struct(StructT { fields, .. }) => {
|
||||||
if let Some(fields) = fields.get() {
|
if let Some(fields) = fields.get() {
|
||||||
if let Some(field) = fields.get(field.0.as_str()) {
|
if let Some(field) = fields.get(field.0.as_str()) {
|
||||||
let builder = ctx.builder.as_mut().unwrap();
|
let builder = ctx.builder.as_mut().unwrap();
|
||||||
return Ok(builder
|
break 'value Some(
|
||||||
|
builder
|
||||||
.get_element_value(value, field.name.as_any_value())
|
.get_element_value(value, field.name.as_any_value())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_any_value());
|
.as_any_value(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
Type::Ptr(PtrT {
|
Type::Ptr(PtrT {
|
||||||
base: Type::Struct(StructT { fields, .. }),
|
base: Type::Struct(StructT { fields, .. }),
|
||||||
@@ -299,19 +314,28 @@ impl<'l> Scope<'l> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(inst);
|
break 'value Some(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
return Err(CompilationError {
|
|
||||||
kind: Kind::FieldNotFound,
|
if let Some(value) = value {
|
||||||
|
self.ctx.emit_event(Event::Symbol {
|
||||||
|
value: value,
|
||||||
|
position: CodePosition::new(self.source.clone(), field.range()),
|
||||||
|
});
|
||||||
|
return Ok(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Diagnostic {
|
||||||
|
kind: Kind::Error,
|
||||||
|
code: Code::FieldNotFound,
|
||||||
message: format!("Value does not contain field `{}`.", field.0),
|
message: format!("Value does not contain field `{}`.", field.0),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), field.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: value_expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -453,28 +477,22 @@ impl<'l> Scope<'l> {
|
|||||||
}
|
}
|
||||||
(Type::Ptr(PtrT { base, .. }), ty, BinaryOp::Assign(_)) => match *base == ty {
|
(Type::Ptr(PtrT { base, .. }), ty, BinaryOp::Assign(_)) => match *base == ty {
|
||||||
true => Ok(builder.store(lhs, rhs).unwrap()),
|
true => Ok(builder.store(lhs, rhs).unwrap()),
|
||||||
false => Err(CompilationError {
|
false => Err(Diagnostic {
|
||||||
kind: Kind::InvalidType,
|
kind: Kind::Error,
|
||||||
|
code: Code::InvalidType,
|
||||||
message: format!(
|
message: format!(
|
||||||
"Cannot assign a value of type `{ty}` to a value of type `{base}`."
|
"Cannot assign a value of type `{ty}` to a value of type `{base}`."
|
||||||
),
|
),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: rhs_expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
(src_ty, Type::Type, BinaryOp::Cast(_)) => {
|
(src_ty, Type::Type, BinaryOp::Cast(_)) => {
|
||||||
let dst_ty =
|
let dst_ty = self.assert_ty(rhs, rhs_expr).map_err(|err| Diagnostic {
|
||||||
self.assert_ty(rhs, rhs_expr)
|
kind: Kind::Error,
|
||||||
.map_err(|err| CompilationError {
|
code: Code::InvalidCast,
|
||||||
kind: Kind::InvalidCast,
|
|
||||||
message: "Cannot perform cast.".to_string(),
|
message: "Cannot perform cast.".to_string(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: expr.range(),
|
|
||||||
},
|
|
||||||
cause: Some(Box::new(err)),
|
cause: Some(Box::new(err)),
|
||||||
})?;
|
})?;
|
||||||
if src_ty == dst_ty {
|
if src_ty == dst_ty {
|
||||||
@@ -533,13 +551,11 @@ impl<'l> Scope<'l> {
|
|||||||
let func = match self.compile_expression(func, ctx)? {
|
let func = match self.compile_expression(func, ctx)? {
|
||||||
AnyValue::Constant(AnyConst::Function(func)) => func,
|
AnyValue::Constant(AnyConst::Function(func)) => func,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::NotAFunction,
|
kind: Kind::Error,
|
||||||
|
code: Code::NotAFunction,
|
||||||
message: "Value is not a function".into(),
|
message: "Value is not a function".into(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), func.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: func.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -574,7 +590,7 @@ impl<'l> Scope<'l> {
|
|||||||
};
|
};
|
||||||
let ctx = self.assembly.ctx();
|
let ctx = self.assembly.ctx();
|
||||||
|
|
||||||
scope.insert(literal_substr!("Self"), struct_ty.as_any_value(), false);
|
scope.insert(literal_substr!("Self"), struct_ty.as_any_value());
|
||||||
let mut field_map = FieldMap::default();
|
let mut field_map = FieldMap::default();
|
||||||
for ast::Field {
|
for ast::Field {
|
||||||
name,
|
name,
|
||||||
@@ -612,14 +628,12 @@ impl<'l> Scope<'l> {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
if mutable.is_some() && !*is_mut {
|
if mutable.is_some() && !*is_mut {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::NotAFunction,
|
kind: Kind::Error,
|
||||||
|
code: Code::NotAFunction,
|
||||||
message: "Cannot obtain a mutable pointer to an immutable value."
|
message: "Cannot obtain a mutable pointer to an immutable value."
|
||||||
.into(),
|
.into(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -677,13 +691,11 @@ impl<'l> Scope<'l> {
|
|||||||
match value.is_lvalue() {
|
match value.is_lvalue() {
|
||||||
false => unsafe {
|
false => unsafe {
|
||||||
if !matches!(ty, Type::Ptr(_)) {
|
if !matches!(ty, Type::Ptr(_)) {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::CannotDereference,
|
kind: Kind::Error,
|
||||||
|
code: Code::CannotDereference,
|
||||||
message: format!("Cannot dereference a value of type `{ty}`."),
|
message: format!("Cannot dereference a value of type `{ty}`."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -703,13 +715,11 @@ impl<'l> Scope<'l> {
|
|||||||
let Type::Ptr(PtrT { base, .. }) = ty else {
|
let Type::Ptr(PtrT { base, .. }) = ty else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::CannotDereference,
|
kind: Kind::Error,
|
||||||
|
code: Code::CannotDereference,
|
||||||
message: format!("Cannot dereference a value of type `{base}`."),
|
message: format!("Cannot dereference a value of type `{base}`."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -735,13 +745,11 @@ impl<'l> Scope<'l> {
|
|||||||
|
|
||||||
// TODO Add support for custom indexing operations
|
// TODO Add support for custom indexing operations
|
||||||
if index.ty() != Type::USIZE {
|
if index.ty() != Type::USIZE {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::InvalidType,
|
kind: Kind::Error,
|
||||||
|
code: Code::InvalidType,
|
||||||
message: "Value is not of type `usize`".into(),
|
message: "Value is not of type `usize`".into(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.index.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: expr.index.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -775,13 +783,11 @@ impl<'l> Scope<'l> {
|
|||||||
None => match ctx.type_hint {
|
None => match ctx.type_hint {
|
||||||
Some(ty) => AnyValue::Constant(AnyConst::Type(ty)),
|
Some(ty) => AnyValue::Constant(AnyConst::Type(ty)),
|
||||||
None => {
|
None => {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::CannotInferType,
|
kind: Kind::Error,
|
||||||
|
code: Code::CannotInferType,
|
||||||
message: "Type cannot be inferred.".into(),
|
message: "Type cannot be inferred.".into(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), ctor.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: ctor.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -791,16 +797,17 @@ impl<'l> Scope<'l> {
|
|||||||
struct_ty @ StructT { fields, .. },
|
struct_ty @ StructT { fields, .. },
|
||||||
))) = ty
|
))) = ty
|
||||||
else {
|
else {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::NotAStruct,
|
kind: Kind::Error,
|
||||||
|
code: Code::NotAStruct,
|
||||||
message: format!("Expected struct type, got value of type `{}`.", ty.ty()),
|
message: format!("Expected struct type, got value of type `{}`.", ty.ty()),
|
||||||
location: Location::Range {
|
position: CodePosition::new(
|
||||||
file: self.source.clone(),
|
self.source.clone(),
|
||||||
range: match &ctor.r#type {
|
match &ctor.r#type {
|
||||||
None => ctor.range(),
|
None => ctor.range(),
|
||||||
Some(ty) => ty.range(),
|
Some(ty) => ty.range(),
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -813,13 +820,11 @@ impl<'l> Scope<'l> {
|
|||||||
} in fields.values()
|
} in fields.values()
|
||||||
{
|
{
|
||||||
let Some(name_value_pair) = ctor.values.get(*fld_name) else {
|
let Some(name_value_pair) = ctor.values.get(*fld_name) else {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::UninitializedField,
|
kind: Kind::Error,
|
||||||
|
code: Code::UninitializedField,
|
||||||
message: format!("Uninitialized field `{fld_name}`."),
|
message: format!("Uninitialized field `{fld_name}`."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -859,7 +864,7 @@ impl<'l> Scope<'l> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
ast: &Arc<ast::Function>,
|
ast: &Arc<ast::Function>,
|
||||||
ctx: &mut ExpressionContext<'l, '_>,
|
ctx: &mut ExpressionContext<'l, '_>,
|
||||||
) -> Result<&'l Function<'l>, CompilationError> {
|
) -> Result<&'l Function<'l>, Diagnostic> {
|
||||||
let ret_ty = match ast.ret.as_ref() {
|
let ret_ty = match ast.ret.as_ref() {
|
||||||
None => AnyValue::Constant(AnyConst::Type(Type::Void)),
|
None => AnyValue::Constant(AnyConst::Type(Type::Void)),
|
||||||
Some(ty) => self.compile_expression(ty, ctx)?,
|
Some(ty) => self.compile_expression(ty, ctx)?,
|
||||||
@@ -885,7 +890,7 @@ impl<'l> Scope<'l> {
|
|||||||
|
|
||||||
let mut scope = self.clone();
|
let mut scope = self.clone();
|
||||||
for (i, arg) in ast.args.iter().enumerate() {
|
for (i, arg) in ast.args.iter().enumerate() {
|
||||||
scope.insert(arg.name.0.clone(), AnyValue::Parameter(i, func), false);
|
scope.insert(arg.name.0.clone(), AnyValue::Parameter(i, func));
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.fn_queue.push_back((func, block.clone(), scope));
|
ctx.fn_queue.push_back((func, block.clone(), scope));
|
||||||
@@ -899,7 +904,7 @@ impl<'l> Scope<'l> {
|
|||||||
value: &Expr,
|
value: &Expr,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
ctx: &mut ExpressionContext<'l, '_>,
|
ctx: &mut ExpressionContext<'l, '_>,
|
||||||
) -> Result<AnyValue<'l>, CompilationError> {
|
) -> Result<AnyValue<'l>, Diagnostic> {
|
||||||
let mut sub_ctx = ExpressionContext {
|
let mut sub_ctx = ExpressionContext {
|
||||||
decl_names: Some(names),
|
decl_names: Some(names),
|
||||||
builder: ctx.builder.as_deref_mut(),
|
builder: ctx.builder.as_deref_mut(),
|
||||||
@@ -922,9 +927,13 @@ impl<'l> Scope<'l> {
|
|||||||
ident.0.clone(),
|
ident.0.clone(),
|
||||||
Variable {
|
Variable {
|
||||||
value: Arc::new(OnceLock::from(value)),
|
value: Arc::new(OnceLock::from(value)),
|
||||||
mutable,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.ctx.emit_event(Event::Definition {
|
||||||
|
value: value,
|
||||||
|
position: CodePosition::new(self.source.clone(), ident.range()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
NamePattern::Tuple(_) => todo!(),
|
NamePattern::Tuple(_) => todo!(),
|
||||||
NamePattern::List(_) => todo!(),
|
NamePattern::List(_) => todo!(),
|
||||||
@@ -936,7 +945,7 @@ impl<'l> Scope<'l> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
block: &Block,
|
block: &Block,
|
||||||
ctx: &mut ExpressionContext<'l, '_>,
|
ctx: &mut ExpressionContext<'l, '_>,
|
||||||
) -> Result<AnyValue<'l>, CompilationError> {
|
) -> Result<AnyValue<'l>, Diagnostic> {
|
||||||
let mut scope = self.clone();
|
let mut scope = self.clone();
|
||||||
let builder = ctx.builder.as_mut().unwrap();
|
let builder = ctx.builder.as_mut().unwrap();
|
||||||
|
|
||||||
@@ -960,7 +969,7 @@ impl<'l> Scope<'l> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
expr: &If,
|
expr: &If,
|
||||||
ctx: &mut ExpressionContext<'l, '_>,
|
ctx: &mut ExpressionContext<'l, '_>,
|
||||||
) -> Result<AnyValue<'l>, CompilationError> {
|
) -> Result<AnyValue<'l>, Diagnostic> {
|
||||||
let If { cond, block, else_ } = expr;
|
let If { cond, block, else_ } = expr;
|
||||||
let condition = self.compile_expression(cond, ctx)?;
|
let condition = self.compile_expression(cond, ctx)?;
|
||||||
self.assert_ty_eq(&condition, cond, &Type::Bool)?;
|
self.assert_ty_eq(&condition, cond, &Type::Bool)?;
|
||||||
@@ -1018,20 +1027,14 @@ impl<'l> Scope<'l> {
|
|||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_ty(
|
fn assert_ty(&self, val: AnyValue<'l>, value_expr: &Expr) -> Result<Type<'l>, Diagnostic> {
|
||||||
&self,
|
|
||||||
val: AnyValue<'l>,
|
|
||||||
value_expr: &Expr,
|
|
||||||
) -> Result<Type<'l>, CompilationError> {
|
|
||||||
match val {
|
match val {
|
||||||
AnyValue::Constant(AnyConst::Type(ty)) => Ok(ty),
|
AnyValue::Constant(AnyConst::Type(ty)) => Ok(ty),
|
||||||
_ => Err(CompilationError {
|
_ => Err(Diagnostic {
|
||||||
kind: Kind::NotAType,
|
kind: Kind::Error,
|
||||||
|
code: Code::NotAType,
|
||||||
message: "Value is not a type.".to_string(),
|
message: "Value is not a type.".to_string(),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), value_expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: value_expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -1042,18 +1045,16 @@ impl<'l> Scope<'l> {
|
|||||||
value: &AnyValue<'l>,
|
value: &AnyValue<'l>,
|
||||||
value_expr: &Expr,
|
value_expr: &Expr,
|
||||||
expected: &Type<'l>,
|
expected: &Type<'l>,
|
||||||
) -> Result<Type<'l>, CompilationError> {
|
) -> Result<Type<'l>, Diagnostic> {
|
||||||
let value_ty = value.ty();
|
let value_ty = value.ty();
|
||||||
match value_ty == *expected {
|
match value_ty == *expected {
|
||||||
true => Ok(value_ty),
|
true => Ok(value_ty),
|
||||||
false => {
|
false => {
|
||||||
return Err(CompilationError {
|
return Err(Diagnostic {
|
||||||
kind: Kind::InvalidType,
|
kind: Kind::Error,
|
||||||
|
code: Code::InvalidType,
|
||||||
message: format!("Expected value of type `{expected}`, found `{value_ty}`."),
|
message: format!("Expected value of type `{expected}`, found `{value_ty}`."),
|
||||||
location: Location::Range {
|
position: CodePosition::new(self.source.clone(), value_expr.range()),
|
||||||
file: self.source.clone(),
|
|
||||||
range: value_expr.range(),
|
|
||||||
},
|
|
||||||
cause: None,
|
cause: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "leaf_lsp"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
leaf_parser = { path = "../parser" }
|
||||||
|
leaf_compiler = { path = "../compiler" }
|
||||||
|
leaf_assembly = { path = "../assembly" }
|
||||||
|
leaf_allocators = { path = "../allocators" }
|
||||||
|
tower-lsp-server = "0.23.0"
|
||||||
|
tokio = { version = "1.50.0", features = ["io-std", "macros", "rt-multi-thread", "sync"] }
|
||||||
|
scc = "3.6.9"
|
||||||
|
rust_search = "2.1.0"
|
||||||
|
rangemap = "1.7.1"
|
||||||
|
boxcar = "0.2.14"
|
||||||
+153
@@ -0,0 +1,153 @@
|
|||||||
|
use crate::utils::UriUtils;
|
||||||
|
use crate::workspace::{Workspace, start_workspace_thread};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use tower_lsp_server::jsonrpc::Result;
|
||||||
|
use tower_lsp_server::ls_types::request::{GotoDeclarationParams, GotoDeclarationResponse};
|
||||||
|
use tower_lsp_server::{Client, LspService, Server};
|
||||||
|
use tower_lsp_server::{LanguageServer, ls_types::*};
|
||||||
|
mod utils;
|
||||||
|
mod workspace;
|
||||||
|
|
||||||
|
struct Backend {
|
||||||
|
client: Client,
|
||||||
|
workspaces: RwLock<Vec<Arc<Workspace>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LanguageServer for Backend {
|
||||||
|
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
|
||||||
|
let mut workspaces = self.workspaces.write().await;
|
||||||
|
for workspace in workspaces.drain(..) {
|
||||||
|
workspace.close().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
for folder in params.workspace_folders.iter().flatten() {
|
||||||
|
workspaces
|
||||||
|
.push(start_workspace_thread(folder.uri.clone(), self.client.clone()).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(InitializeResult {
|
||||||
|
capabilities: ServerCapabilities {
|
||||||
|
hover_provider: Some(HoverProviderCapability::Simple(true)),
|
||||||
|
definition_provider: Some(OneOf::Left(true)),
|
||||||
|
declaration_provider: Some(DeclarationCapability::Simple(true)),
|
||||||
|
text_document_sync: Some(TextDocumentSyncCapability::Options(
|
||||||
|
TextDocumentSyncOptions {
|
||||||
|
save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions {
|
||||||
|
include_text: Some(false),
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
semantic_tokens_provider: Some(
|
||||||
|
SemanticTokensServerCapabilities::SemanticTokensOptions(
|
||||||
|
SemanticTokensOptions {
|
||||||
|
legend: SemanticTokensLegend {
|
||||||
|
token_types: vec![
|
||||||
|
SemanticTokenType::TYPE,
|
||||||
|
SemanticTokenType::FUNCTION,
|
||||||
|
SemanticTokenType::NUMBER,
|
||||||
|
],
|
||||||
|
token_modifiers: vec![],
|
||||||
|
},
|
||||||
|
full: Some(SemanticTokensFullOptions::Bool(true)),
|
||||||
|
range: None,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn initialized(&self, _: InitializedParams) {
|
||||||
|
self.client
|
||||||
|
.log_message(MessageType::INFO, "server initialized!")
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
|
||||||
|
if let Some(w) = self
|
||||||
|
.find_workspace(¶ms.text_document_position_params.text_document.uri)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Ok(w.hover(params).await);
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn goto_declaration(
|
||||||
|
&self,
|
||||||
|
params: GotoDeclarationParams,
|
||||||
|
) -> Result<Option<GotoDeclarationResponse>> {
|
||||||
|
if let Some(w) = self
|
||||||
|
.find_workspace(¶ms.text_document_position_params.text_document.uri)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Ok(w.go_to_declaration(params).await);
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn goto_definition(
|
||||||
|
&self,
|
||||||
|
params: GotoDeclarationParams,
|
||||||
|
) -> Result<Option<GotoDeclarationResponse>> {
|
||||||
|
if let Some(w) = self
|
||||||
|
.find_workspace(¶ms.text_document_position_params.text_document.uri)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Ok(w.go_to_declaration(params).await);
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn did_save(&self, params: DidSaveTextDocumentParams) {
|
||||||
|
if let Some(w) = self.find_workspace(¶ms.text_document.uri).await {
|
||||||
|
w.reload().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn semantic_tokens_full(
|
||||||
|
&self,
|
||||||
|
params: SemanticTokensParams,
|
||||||
|
) -> Result<Option<SemanticTokensResult>> {
|
||||||
|
if let Some(w) = self.find_workspace(¶ms.text_document.uri).await {
|
||||||
|
return Ok(w.semantic_tokens(params).await);
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn shutdown(&self) -> Result<()> {
|
||||||
|
let mut workspaces = self.workspaces.write().await;
|
||||||
|
for workspace in workspaces.drain(..) {
|
||||||
|
workspace.close().await;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend {
|
||||||
|
pub async fn find_workspace(&self, file: &Uri) -> Option<Arc<Workspace>> {
|
||||||
|
let workspaces = self.workspaces.read().await;
|
||||||
|
let path = file.strip_header();
|
||||||
|
workspaces
|
||||||
|
.iter()
|
||||||
|
.find(|w| path.starts_with(&w.base))
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let stdin = tokio::io::stdin();
|
||||||
|
let stdout = tokio::io::stdout();
|
||||||
|
|
||||||
|
let (service, socket) = LspService::new(|client| Backend {
|
||||||
|
client,
|
||||||
|
workspaces: RwLock::default(),
|
||||||
|
});
|
||||||
|
Server::new(stdin, stdout, socket).serve(service).await;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
use leaf_compiler::metadata::CodePosition;
|
||||||
|
use tower_lsp_server::ls_types::{Position, Range, Uri};
|
||||||
|
|
||||||
|
pub trait UriUtils {
|
||||||
|
fn strip_header(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UriUtils for Uri {
|
||||||
|
fn strip_header(&self) -> &str {
|
||||||
|
let Some(("", str)) = self.as_str().split_once("file://") else {
|
||||||
|
unimplemented!()
|
||||||
|
};
|
||||||
|
str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CodePositionUtils {
|
||||||
|
fn lsp_range(&self) -> Range;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CodePositionUtils for CodePosition {
|
||||||
|
fn lsp_range(&self) -> Range {
|
||||||
|
let range = self.line_col();
|
||||||
|
Range {
|
||||||
|
start: Position {
|
||||||
|
line: range.start.line as u32,
|
||||||
|
character: range.start.column as u32,
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: range.end.line as u32,
|
||||||
|
character: range.end.column as u32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,407 @@
|
|||||||
|
use leaf_allocators::SyncArenaAllocator;
|
||||||
|
use leaf_assembly::{
|
||||||
|
assembly::{AssemblyIdentifier, Version},
|
||||||
|
types::{Type, derivations::PtrT},
|
||||||
|
values::{AnyConst, AnyValue, Value},
|
||||||
|
};
|
||||||
|
use leaf_compiler::{CompilationContext, events::Event, metadata::CodePosition};
|
||||||
|
use leaf_parser::{ArcStr, SourceCode};
|
||||||
|
use rangemap::RangeMap;
|
||||||
|
use rust_search::SearchBuilder;
|
||||||
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::Write,
|
||||||
|
ops::Range,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{Arc, OnceLock},
|
||||||
|
};
|
||||||
|
use tokio::sync::{
|
||||||
|
Mutex, Notify, RwLock,
|
||||||
|
mpsc::{Sender, channel},
|
||||||
|
};
|
||||||
|
use tower_lsp_server::{
|
||||||
|
Client,
|
||||||
|
ls_types::{
|
||||||
|
Diagnostic, DiagnosticSeverity, Hover, HoverContents, HoverParams, Location, MarkedString,
|
||||||
|
NumberOrString, Position, Range as LspRange, SemanticToken, SemanticTokenType,
|
||||||
|
SemanticTokens, SemanticTokensParams, SemanticTokensResult, TextDocumentPositionParams,
|
||||||
|
Uri,
|
||||||
|
request::{GotoDeclarationParams, GotoDeclarationResponse},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::utils::{CodePositionUtils, UriUtils};
|
||||||
|
|
||||||
|
pub struct Workspace {
|
||||||
|
pub base: String,
|
||||||
|
sender: Sender<Request>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Workspace {
|
||||||
|
pub async fn close(&self) -> bool {
|
||||||
|
let notify = Arc::new(Notify::new());
|
||||||
|
self.sender
|
||||||
|
.send(Request::Close(notify.clone()))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
notify.notified().await;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn hover(&self, params: HoverParams) -> Option<Hover> {
|
||||||
|
let result = Arc::<(OnceLock<Hover>, Notify)>::default();
|
||||||
|
self.sender
|
||||||
|
.send(Request::Hover(params, result.clone()))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
result.1.notified().await;
|
||||||
|
result.0.get().cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn go_to_declaration(
|
||||||
|
&self,
|
||||||
|
params: GotoDeclarationParams,
|
||||||
|
) -> Option<GotoDeclarationResponse> {
|
||||||
|
let result = Arc::<(OnceLock<GotoDeclarationResponse>, Notify)>::default();
|
||||||
|
self.sender
|
||||||
|
.send(Request::GoToDeclaration(params, result.clone()))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
result.1.notified().await;
|
||||||
|
result.0.get().cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn semantic_tokens(
|
||||||
|
&self,
|
||||||
|
params: SemanticTokensParams,
|
||||||
|
) -> Option<SemanticTokensResult> {
|
||||||
|
let result = Arc::<(OnceLock<SemanticTokensResult>, Notify)>::default();
|
||||||
|
self.sender
|
||||||
|
.send(Request::SemanticTokens(params, result.clone()))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
result.1.notified().await;
|
||||||
|
result.0.get().cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn reload(&self) {
|
||||||
|
self.sender.send(Request::Reload).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Request {
|
||||||
|
Reload,
|
||||||
|
Close(Arc<Notify>),
|
||||||
|
Hover(HoverParams, Arc<(OnceLock<Hover>, Notify)>),
|
||||||
|
GoToDeclaration(
|
||||||
|
GotoDeclarationParams,
|
||||||
|
Arc<(OnceLock<GotoDeclarationResponse>, Notify)>,
|
||||||
|
),
|
||||||
|
SemanticTokens(
|
||||||
|
SemanticTokensParams,
|
||||||
|
Arc<(OnceLock<SemanticTokensResult>, Notify)>,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State<'l> {
|
||||||
|
context: CompilationContext<'l>,
|
||||||
|
files: Arc<RwLock<HashMap<String, FileInfo>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct FileInfo {
|
||||||
|
line_ranges: HashMap<u32, Range<usize>>,
|
||||||
|
symbol_ranges: RangeMap<usize, [u8; size_of::<AnyValue<'_>>()]>,
|
||||||
|
symbol_positions: HashMap<[u8; size_of::<AnyValue<'_>>()], CodePosition>,
|
||||||
|
symbol_definitions: HashMap<[u8; size_of::<AnyValue<'_>>()], CodePosition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'l> State<'l> {
|
||||||
|
pub fn new(alloc: &'l SyncArenaAllocator) -> Self {
|
||||||
|
State {
|
||||||
|
context: CompilationContext::new(alloc),
|
||||||
|
files: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_workspace_thread(url: Uri, client: Client) -> Result<Arc<Workspace>, String> {
|
||||||
|
let base = url.strip_header().to_string();
|
||||||
|
let path = base.clone();
|
||||||
|
let (sender, mut receiver) = channel(1);
|
||||||
|
let _handle = tokio::task::spawn(async move {
|
||||||
|
let mut alloc = SyncArenaAllocator::default();
|
||||||
|
'global: loop {
|
||||||
|
alloc.reset();
|
||||||
|
let mut state = State::new(&alloc);
|
||||||
|
let mut diagnostics = HashMap::<PathBuf, Vec<Diagnostic>>::new();
|
||||||
|
|
||||||
|
let files: Vec<_> = tokio::task::block_in_place(|| {
|
||||||
|
SearchBuilder::default()
|
||||||
|
.location(&path)
|
||||||
|
.ext("leaf")
|
||||||
|
.build()
|
||||||
|
.map(|f| {
|
||||||
|
let mut info = state.files.blocking_write();
|
||||||
|
let info = info.entry(f.clone()).or_default();
|
||||||
|
let text: ArcStr = std::fs::read_to_string(&f).unwrap().into();
|
||||||
|
info.line_ranges = calc_line_ranges(text.as_str());
|
||||||
|
diagnostics.entry(PathBuf::from(&f)).or_default();
|
||||||
|
Arc::new(SourceCode {
|
||||||
|
text,
|
||||||
|
file: f.into(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
|
let diagnostics = Arc::new(Mutex::new(diagnostics));
|
||||||
|
|
||||||
|
{
|
||||||
|
let info = state.files.clone();
|
||||||
|
let diagnostics = diagnostics.clone();
|
||||||
|
state.context.add_event_callback(move |e| unsafe {
|
||||||
|
tokio::task::block_in_place(|| match e {
|
||||||
|
Event::Symbol { value, position } => {
|
||||||
|
let mut info = info.blocking_write();
|
||||||
|
let info = info
|
||||||
|
.entry(position.file.file.to_string_lossy().to_string())
|
||||||
|
.or_default();
|
||||||
|
info.symbol_ranges
|
||||||
|
.insert(position.range.clone(), std::mem::transmute(*value));
|
||||||
|
info.symbol_positions
|
||||||
|
.insert(std::mem::transmute(*value), position.clone());
|
||||||
|
}
|
||||||
|
Event::Definition { value, position } => {
|
||||||
|
let mut info = info.blocking_write();
|
||||||
|
let info = info
|
||||||
|
.entry(position.file.file.to_string_lossy().to_string())
|
||||||
|
.or_default();
|
||||||
|
info.symbol_definitions
|
||||||
|
.insert(std::mem::transmute(*value), position.clone());
|
||||||
|
info.symbol_ranges
|
||||||
|
.insert(position.range.clone(), std::mem::transmute(*value));
|
||||||
|
info.symbol_positions
|
||||||
|
.insert(std::mem::transmute(*value), position.clone());
|
||||||
|
}
|
||||||
|
Event::Diagnostic(diagnostic) => {
|
||||||
|
let mut diagnostics = diagnostics.blocking_lock();
|
||||||
|
diagnostics
|
||||||
|
.entry(diagnostic.position.file.file.clone())
|
||||||
|
.or_default()
|
||||||
|
.extend(make_diagnostics(diagnostic));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(err) = state.context.extend(
|
||||||
|
AssemblyIdentifier {
|
||||||
|
version: Version::default(),
|
||||||
|
name: Cow::Borrowed("Leaf lsp tmp"),
|
||||||
|
},
|
||||||
|
&files,
|
||||||
|
) {
|
||||||
|
let mut diagnostics = diagnostics.lock().await;
|
||||||
|
diagnostics
|
||||||
|
.entry(err.position.file.file.clone())
|
||||||
|
.or_default()
|
||||||
|
.extend(make_diagnostics(&err));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut diagnostics = diagnostics.lock().await;
|
||||||
|
for (file, diagnostics) in diagnostics.drain() {
|
||||||
|
client
|
||||||
|
.publish_diagnostics(Uri::from_file_path(file).unwrap(), diagnostics, None)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some(event) = receiver.recv().await {
|
||||||
|
match event {
|
||||||
|
Request::Reload => {
|
||||||
|
alloc = SyncArenaAllocator::default();
|
||||||
|
continue 'global;
|
||||||
|
}
|
||||||
|
Request::Hover(params, result) => {
|
||||||
|
let value = state
|
||||||
|
.with_file_and_range(
|
||||||
|
¶ms.text_document_position_params,
|
||||||
|
|info, range| unsafe {
|
||||||
|
let Some(symbol) = info.symbol_ranges.get(
|
||||||
|
&(range.start
|
||||||
|
+ params
|
||||||
|
.text_document_position_params
|
||||||
|
.position
|
||||||
|
.character as usize),
|
||||||
|
) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is blasphemy but what can I do? :3
|
||||||
|
Some(std::mem::transmute::<_, AnyValue>(*symbol))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Some(Some(value)) = value {
|
||||||
|
let mut message = String::new();
|
||||||
|
let _ = writeln!(
|
||||||
|
message,
|
||||||
|
"Type: {}",
|
||||||
|
match value.is_lvalue() {
|
||||||
|
false => value.ty(),
|
||||||
|
true => match value.ty() {
|
||||||
|
Type::Ptr(PtrT { base, .. }) => *base,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
result
|
||||||
|
.0
|
||||||
|
.set(Hover {
|
||||||
|
contents: HoverContents::Scalar(MarkedString::String(message)),
|
||||||
|
range: None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.1.notify_one();
|
||||||
|
}
|
||||||
|
Request::GoToDeclaration(params, result) => {
|
||||||
|
let declaration = state
|
||||||
|
.with_file_and_range(
|
||||||
|
¶ms.text_document_position_params,
|
||||||
|
|info, range| {
|
||||||
|
let Some(symbol) = info.symbol_ranges.get(
|
||||||
|
&(range.start
|
||||||
|
+ params
|
||||||
|
.text_document_position_params
|
||||||
|
.position
|
||||||
|
.character as usize),
|
||||||
|
) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
let Some(position) = info.symbol_definitions.get(symbol) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
Some(position.clone())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Some(Some(decl)) = declaration {
|
||||||
|
result
|
||||||
|
.0
|
||||||
|
.set(GotoDeclarationResponse::Scalar(Location {
|
||||||
|
uri: Uri::from_file_path(&decl.file.file).unwrap(),
|
||||||
|
range: decl.lsp_range(),
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.1.notify_one();
|
||||||
|
}
|
||||||
|
Request::SemanticTokens(params, result) => {
|
||||||
|
let info = state.files.read().await;
|
||||||
|
let Some(file) = info.get(params.text_document.uri.strip_header()) else {
|
||||||
|
result.1.notify_one();
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let mut tokens = SemanticTokens::default();
|
||||||
|
for (symbol, position) in file.symbol_positions.iter() {
|
||||||
|
let symbol: AnyValue = unsafe { std::mem::transmute(*symbol) };
|
||||||
|
let line_col = position.line_col();
|
||||||
|
tokens.data.push(SemanticToken {
|
||||||
|
delta_line: line_col.start.line as u32,
|
||||||
|
delta_start: line_col.start.column as u32,
|
||||||
|
length: position.range.len() as u32,
|
||||||
|
token_type: match symbol {
|
||||||
|
AnyValue::Constant(AnyConst::Type(_)) => 0,
|
||||||
|
AnyValue::Constant(AnyConst::Function(_)) => 1,
|
||||||
|
AnyValue::Constant(AnyConst::Int(_) | AnyConst::Float(_)) => 2,
|
||||||
|
_ => continue,
|
||||||
|
},
|
||||||
|
token_modifiers_bitset: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut previous_line = 0;
|
||||||
|
let mut previous_start = 0;
|
||||||
|
tokens.data.sort_by_key(|v| (v.delta_line, v.delta_start));
|
||||||
|
for SemanticToken {
|
||||||
|
delta_line,
|
||||||
|
delta_start,
|
||||||
|
..
|
||||||
|
} in tokens.data.iter_mut()
|
||||||
|
{
|
||||||
|
let line = *delta_line;
|
||||||
|
let start = *delta_start;
|
||||||
|
*delta_start = match line == previous_line {
|
||||||
|
false => start,
|
||||||
|
true => start - previous_start,
|
||||||
|
};
|
||||||
|
*delta_line = line - previous_line;
|
||||||
|
previous_line = line;
|
||||||
|
previous_start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.0.set(SemanticTokensResult::Tokens(tokens)).unwrap();
|
||||||
|
result.1.notify_one();
|
||||||
|
}
|
||||||
|
Request::Close(notify) => {
|
||||||
|
notify.notify_waiters();
|
||||||
|
break 'global;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(Arc::new(Workspace { base, sender }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_line_ranges(text: &str) -> HashMap<u32, Range<usize>> {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
for line in text.split('\n') {
|
||||||
|
let start = line.as_ptr() as usize - text.as_ptr() as usize;
|
||||||
|
map.insert(map.len() as u32, start..start + line.len());
|
||||||
|
}
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State<'_> {
|
||||||
|
async fn with_file_and_range<T>(
|
||||||
|
&self,
|
||||||
|
params: &TextDocumentPositionParams,
|
||||||
|
action: impl FnOnce(&FileInfo, Range<usize>) -> T,
|
||||||
|
) -> Option<T> {
|
||||||
|
let info = self.files.read().await;
|
||||||
|
let Some(info) = info.get(params.text_document.uri.strip_header()) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
let Some(range) = info.line_ranges.get(¶ms.position.line) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
Some(action(info, range.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_diagnostics(diag: &leaf_compiler::diagnostics::Diagnostic) -> Vec<Diagnostic> {
|
||||||
|
vec![Diagnostic {
|
||||||
|
range: diag.position.lsp_range(),
|
||||||
|
severity: Some(match diag.kind {
|
||||||
|
leaf_compiler::diagnostics::Kind::Info => DiagnosticSeverity::INFORMATION,
|
||||||
|
leaf_compiler::diagnostics::Kind::Warning => DiagnosticSeverity::WARNING,
|
||||||
|
leaf_compiler::diagnostics::Kind::Error => DiagnosticSeverity::ERROR,
|
||||||
|
}),
|
||||||
|
code: Some(NumberOrString::Number(diag.code as i32)),
|
||||||
|
code_description: None,
|
||||||
|
source: Some("Leaf compiler".into()),
|
||||||
|
message: diag.message.clone(),
|
||||||
|
related_information: None,
|
||||||
|
tags: None,
|
||||||
|
data: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
use arcstr::ArcStr;
|
pub use arcstr::ArcStr;
|
||||||
pub use parser::{compilation_unit as parse, *};
|
pub use parser::{compilation_unit as parse, *};
|
||||||
use std::{fmt::Debug, path::PathBuf};
|
use std::{fmt::Debug, path::PathBuf};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user