diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 6545e4d..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "C_Cpp.intelliSenseEngineFallback": "enabled"
-}
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 82d3139..713a739 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,91 +3,521 @@
version = 3
[[package]]
-name = "bitmaps"
-version = "2.1.0"
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "async-trait"
+version = "0.1.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
+]
+
+[[package]]
+name = "auto_impl"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bytes"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+
+[[package]]
+name = "cc"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "dashmap"
+version = "5.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
+dependencies = [
+ "cfg-if",
+ "hashbrown",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
+
+[[package]]
+name = "futures-io"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
+
+[[package]]
+name = "futures-task"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
+
+[[package]]
+name = "futures-util"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "gimli"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
+
+[[package]]
+name = "hashbrown"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "idna"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+
+[[package]]
+name = "libc"
+version = "0.2.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
+
+[[package]]
+name = "lock_api"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "lsp-types"
+version = "0.94.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1"
+dependencies = [
+ "bitflags",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "url",
+]
+
+[[package]]
+name = "memchr"
+version = "2.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
+checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+
+[[package]]
+name = "pin-project"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
dependencies = [
- "typenum",
+ "pin-project-internal",
]
[[package]]
-name = "convert_case"
-version = "0.6.0"
+name = "pin-project-internal"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
+checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
- "unicode-segmentation",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
]
[[package]]
-name = "im-rc"
-version = "15.1.0"
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
- "bitmaps",
- "rand_core",
- "rand_xoshiro",
- "sized-chunks",
- "typenum",
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
"version_check",
]
[[package]]
-name = "lazy_static"
-version = "1.4.0"
+name = "proc-macro-error-attr"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.32"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
+[[package]]
+name = "ryu"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.190"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.190"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.107"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_repr"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [
"proc-macro2",
+ "quote",
+ "syn 2.0.38",
]
[[package]]
-name = "rand_core"
-version = "0.6.4"
+name = "signal-hook-registry"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+dependencies = [
+ "libc",
+]
[[package]]
-name = "rand_xoshiro"
-version = "0.6.0"
+name = "slab"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
- "rand_core",
+ "autocfg",
]
[[package]]
-name = "sized-chunks"
-version = "0.6.5"
+name = "smallvec"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
+
+[[package]]
+name = "socket2"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
+checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
- "bitmaps",
- "typenum",
+ "libc",
+ "windows-sys",
]
[[package]]
name = "syn"
-version = "2.0.27"
+version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@@ -95,162 +525,297 @@ dependencies = [
]
[[package]]
-name = "typenum"
-version = "1.16.0"
+name = "syn"
+version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
[[package]]
-name = "unicode-ident"
-version = "1.0.11"
+name = "tinyvec"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
[[package]]
-name = "unicode-segmentation"
-version = "1.10.1"
+name = "tinyvec_macros"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
-name = "version_check"
-version = "0.9.4"
+name = "tokio"
+version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys",
+]
[[package]]
-name = "vulpi-cli"
-version = "0.1.0"
+name = "tokio-macros"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
- "vulpi-lexer",
- "vulpi-location",
- "vulpi-parser",
- "vulpi-report",
- "vulpi-resolver",
- "vulpi-show",
- "vulpi-typer",
- "vulpi-vfs",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
]
[[package]]
-name = "vulpi-intern"
-version = "0.1.0"
+name = "tokio-util"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
- "lazy_static",
- "vulpi-show",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
]
[[package]]
-name = "vulpi-lexer"
-version = "0.1.0"
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
- "vulpi-intern",
- "vulpi-location",
- "vulpi-report",
- "vulpi-syntax",
+ "futures-core",
+ "futures-util",
+ "pin-project",
+ "pin-project-lite",
+ "tower-layer",
+ "tower-service",
]
[[package]]
-name = "vulpi-location"
-version = "0.1.0"
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-lsp"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508"
dependencies = [
- "vulpi-show",
+ "async-trait",
+ "auto_impl",
+ "bytes",
+ "dashmap",
+ "futures",
+ "httparse",
+ "lsp-types",
+ "memchr",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tokio-util",
+ "tower",
+ "tower-lsp-macros",
+ "tracing",
]
[[package]]
-name = "vulpi-macros"
-version = "0.1.0"
+name = "tower-lsp-macros"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
dependencies = [
- "convert_case",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.38",
]
[[package]]
-name = "vulpi-parser"
-version = "0.1.0"
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "vulpi-intern",
- "vulpi-lexer",
- "vulpi-location",
- "vulpi-report",
- "vulpi-syntax",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
]
[[package]]
-name = "vulpi-report"
-version = "0.1.0"
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
- "vulpi-location",
- "vulpi-vfs",
- "yansi",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.38",
]
[[package]]
-name = "vulpi-resolver"
-version = "0.1.0"
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
- "im-rc",
- "vulpi-intern",
- "vulpi-location",
- "vulpi-macros",
- "vulpi-report",
- "vulpi-show",
- "vulpi-syntax",
+ "once_cell",
]
[[package]]
-name = "vulpi-show"
-version = "0.1.0"
+name = "unicode-bidi"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
-name = "vulpi-syntax"
-version = "0.1.0"
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "url"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
- "im-rc",
- "vulpi-intern",
- "vulpi-location",
- "vulpi-macros",
- "vulpi-show",
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
]
[[package]]
-name = "vulpi-tests"
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "vulpi-cli"
version = "0.1.0"
dependencies = [
- "vulpi-lexer",
- "vulpi-location",
- "vulpi-parser",
- "vulpi-report",
- "vulpi-resolver",
- "vulpi-show",
- "vulpi-typer",
- "vulpi-vfs",
+ "tokio",
+ "vulpi-lsp",
]
[[package]]
-name = "vulpi-typer"
+name = "vulpi-location"
+version = "0.1.0"
+
+[[package]]
+name = "vulpi-lsp"
version = "0.1.0"
dependencies = [
- "im-rc",
- "vulpi-intern",
- "vulpi-location",
- "vulpi-macros",
- "vulpi-report",
- "vulpi-show",
- "vulpi-syntax",
+ "tokio",
+ "tower-lsp",
]
[[package]]
name = "vulpi-vfs"
version = "0.1.0"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "vulpi-location",
+ "windows-targets",
]
[[package]]
-name = "yansi"
-version = "0.5.1"
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
diff --git a/Cargo.toml b/Cargo.toml
index 97a0ae1..a8e3e27 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,18 +1,10 @@
[workspace]
members = [
- "crates/vulpi-intern",
- "crates/vulpi-lexer",
- "crates/vulpi-location",
- "crates/vulpi-macros",
- "crates/vulpi-parser",
- "crates/vulpi-report",
- "crates/vulpi-show",
- "crates/vulpi-syntax",
- "crates/vulpi-tests",
- "crates/vulpi-vfs",
- "crates/vulpi-resolver",
"crates/vulpi-cli",
+ "crates/vulpi-lsp",
+ "crates/vulpi-location",
+ "crates/vulpi-vfs"
]
-resolver = "1"
+resolver = "2"
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 67a5123..0000000
--- a/README.md
+++ /dev/null
@@ -1,72 +0,0 @@
-
-The Vulpi Compiler
-
-# Tasks
-
-- [x] Lexer
- - [x] Layout Parsing
- - [x] Escape
- - [ ] Interpolation
-- [ ] Parser
- - [x] Types
- - [x] Algebraic Data Types
- - [x] Declaration
- - [ ] Generalized Version
- - [X] Kinds
- - [x] Records
- - [x] Instance
- - [x] Update
- - [x] Declaration
- - [x] Projection
- - [x] Effects
- - [x] Declaration
- - [x] Handler
- - [ ] Traits
- - [ ] Implementation
- - [ ] Constraint Syntax
- - [x] Abstract Data Types
- - [x] Type Synonyms
- - [x] Tuple
- - [x] Let declarations
- - [x] Let cases
- - [x] Patterns
- - [ ] Record Pattern
- - [x] ADT Pattern
- - [x] Guards
- - [x] Or Pattern
- - [x] Blocks
- - [x] Modules
- - [x] Public / Private things
- - [ ] Deriving Syntax
- - [x] Expressions
- - [x] Operators
- - [ ] Section Patterns
- - [ ] Function applications In Half
- - [x] Pipe and Composition
- - [x] Precedence
- - [x] Type ascription
- - [x] Function Call
- - [x] Let Expression
- - [x] Lambda Expression
- - [x] Do Expression
- - [x] When Expression
- - [x] If Expression
- - [x] Record Expression
- - [x] Tuple Expression
- - [ ] List Expression
- - [x] Unit expression
- - [ ] Attributes
- - [x] Import
-- [x] Resolution
- - [x] Visibility resolution
- - [x] Name resolution
- - [x] Duplicated pattern name checking
- - [x] Or Pattern
- - [x] Desugar
-- [x] Type checker
- - [x] Higher rank polymorphism
- - [x] Higher kinded types
- - [ ] Entailment
- - [ ] Coverage checker
-- [ ] Perceus
-- [ ] LLVM
\ No newline at end of file
diff --git a/crates/vulpi-build/Cargo.toml b/crates/vulpi-build/Cargo.toml
deleted file mode 100644
index 6509194..0000000
--- a/crates/vulpi-build/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "vulpi-build"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
diff --git a/crates/vulpi-build/src/lib.rs b/crates/vulpi-build/src/lib.rs
deleted file mode 100644
index e77916f..0000000
--- a/crates/vulpi-build/src/lib.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-//! Facilities to build a entire crate of vulpi files. This module is responsible for building the
-//! crate from the source files and resolving the modules.
diff --git a/crates/vulpi-cli/Cargo.toml b/crates/vulpi-cli/Cargo.toml
index f04aea6..32d77c1 100644
--- a/crates/vulpi-cli/Cargo.toml
+++ b/crates/vulpi-cli/Cargo.toml
@@ -6,14 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-
-vulpi-lexer = { path = "../vulpi-lexer" }
-vulpi-location = { path = "../vulpi-location" }
-vulpi-parser = { path = "../vulpi-parser" }
-vulpi-report = { path = "../vulpi-report" }
-vulpi-show = { path = "../vulpi-show" }
-vulpi-vfs = { path = "../vulpi-vfs" }
-vulpi-resolver = { path = "../vulpi-resolver" }
-vulpi-typer = { path = "../vulpi-typer" }
-vulpi-syntax = { path = "../vulpi-syntax" }
-vulpi-ir = { path = "../vulpi-ir" }
+tokio = { version = "1.33.0", features = ["full"] }
+vulpi-lsp = {path = "../vulpi-lsp"}
diff --git a/crates/vulpi-cli/src/main.rs b/crates/vulpi-cli/src/main.rs
index df39595..a62a182 100644
--- a/crates/vulpi-cli/src/main.rs
+++ b/crates/vulpi-cli/src/main.rs
@@ -1,87 +1,4 @@
-use std::collections::HashSet;
-use std::path::PathBuf;
-
-use vulpi_ir::compiler;
-use vulpi_parser::parse;
-use vulpi_report::hash_reporter;
-use vulpi_report::renderer::classic::Classic;
-
-use vulpi_report::{hash::HashReporter, Report};
-
-use vulpi_resolver::error::ResolverErrorKind;
-use vulpi_resolver::io::IO;
-use vulpi_resolver::namespaces;
-use vulpi_resolver::paths;
-use vulpi_resolver::resolver;
-use vulpi_resolver::scopes::Symbol;
-use vulpi_show::Show;
-use vulpi_syntax::concrete::tree::Program;
-
-use vulpi_typer::type_checker;
-use vulpi_vfs::real::RealFileSystem;
-use vulpi_vfs::FileSystem;
-
-pub struct Loader {
- pub cwd: PathBuf,
- pub reporter: Report,
- pub fs: RealFileSystem,
- pub loaded: HashSet,
-}
-
-impl Loader {
- pub fn new(cwd: PathBuf) -> Self {
- Self {
- cwd: cwd.clone(),
- reporter: Report::new(HashReporter::new()),
- fs: RealFileSystem::new(cwd),
- loaded: HashSet::new(),
- }
- }
-
- #[allow(clippy::result_unit_err)]
- pub fn start(&mut self) -> Result {
- let Ok(file_id) = self.fs.load(self.cwd.join("main.vp")) else {
- return Err(())
- };
-
- let Ok(source) = self.fs.read(file_id) else {
- return Err(())
- };
-
- let program = parse(self.reporter.clone(), file_id, source);
-
- Ok(program)
- }
-}
-
-impl IO for Loader {
- fn read_module(&mut self, _id: paths::Path) -> Result {
- todo!()
- }
-}
-
-fn main() {
- let cwd = std::env::current_dir().unwrap();
- let mut loader = Loader::new(cwd.clone());
- let program = loader.start().unwrap();
-
- let reporter = hash_reporter();
- let mut namespaces = namespaces();
-
- let program = resolver(reporter.clone(), &mut namespaces, &mut loader)
- .declare(&program)
- .import(&program)
- .resolve(program);
-
- let elaborated = type_checker(reporter.clone())
- .declare(&program)
- .define(&program)
- .output();
-
- if reporter.has_errors() {
- let ctx = Classic::new(&loader.fs, cwd);
- reporter.to_stderr(ctx)
- } else {
- let compiler = compiler().first_pass(elaborated);
- }
+#[tokio::main()]
+async fn main() {
+ vulpi_lsp::start().await;
}
diff --git a/crates/vulpi-intern/Cargo.toml b/crates/vulpi-intern/Cargo.toml
deleted file mode 100644
index b81548a..0000000
--- a/crates/vulpi-intern/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "vulpi-intern"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-vulpi-show = { path = "../vulpi-show" }
-
-lazy_static = "1.4.0"
-
-[features]
-default = ["single-shot"]
-single-shot = []
diff --git a/crates/vulpi-intern/src/lib.rs b/crates/vulpi-intern/src/lib.rs
deleted file mode 100644
index 4e4ba72..0000000
--- a/crates/vulpi-intern/src/lib.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-//! The string interner of the compiler. It is used to store strings in a way that is more efficient
-//! than storing them directly. It is also used to make sure that strings are unique. This is
-//! important for the compiler because it allows us to compare strings by comparing their ids. None
-//! of the implementations implement the [Copy] trait because some of them are heavy to clone.
-
-#[cfg(feature = "single-shot")]
-pub mod no_rc;
-
-#[cfg(feature = "single-shot")]
-pub use no_rc::*;
-
-use std::marker::PhantomData;
-
-/// A interned symbol that contains a phantom data to make it unique.
-#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct Interned(Symbol, PhantomData);
-
-impl Interned {
- pub fn new(symbol: Symbol) -> Self {
- Self(symbol, PhantomData)
- }
-
- pub fn get(&self) -> String {
- self.0.get()
- }
-
- pub fn cast(self) -> Interned {
- Interned::new(self.0)
- }
-}
-
-pub trait Internable: Sized {
- fn intern(&self) -> Interned;
-}
-
-impl std::fmt::Debug for Interned {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_tuple("Interned")
- .field(&self.0)
- .field(&self.1)
- .finish()
- }
-}
diff --git a/crates/vulpi-intern/src/no_rc.rs b/crates/vulpi-intern/src/no_rc.rs
deleted file mode 100644
index 2682bb8..0000000
--- a/crates/vulpi-intern/src/no_rc.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-//! A simple string interner with no reference counting so it lives until the end of the program.
-
-use vulpi_show::Show;
-
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-thread_local! {
- static INTERNER: Interner = Interner::default();
-}
-
-/// A symbol is a reference to a string inside the interner. It is used to compare strings by
-/// comparing their ids instead of comparing their content because it is more efficient (it makes
-/// the comparison an integer comparison instead of a string comparison).
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Symbol {
- Generated(usize),
- Interned(usize),
-}
-
-impl std::fmt::Debug for Symbol {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", self.get())
- }
-}
-
-impl Symbol {
- pub fn intern(string: &str) -> Self {
- INTERNER.with(|i| i.intern(string))
- }
-
- pub fn get(&self) -> String {
- INTERNER.with(|i| i.get(self).unwrap())
- }
-}
-
-impl Show for Symbol {
- fn show(&self) -> vulpi_show::TreeDisplay {
- vulpi_show::TreeDisplay::label(&format!("Symbol: {}", self.get()))
- }
-}
-#[derive(Default)]
-struct Interner {
- id_to_string: RefCell>,
- string_to_id: RefCell>,
- counter: AtomicUsize,
-}
-
-impl Interner {
- fn intern(&self, string: &str) -> Symbol {
- if let Some(id) = self.string_to_id.borrow().get(string) {
- return id.clone();
- }
-
- let mut id_to_string = self.id_to_string.borrow_mut();
- let mut string_to_id = self.string_to_id.borrow_mut();
-
- let id = Symbol::Interned(self.counter.fetch_add(1, Ordering::SeqCst));
- id_to_string.push(string.to_owned());
- string_to_id.insert(string.to_owned(), id.clone());
-
- id
- }
-
- fn get(&self, id: &Symbol) -> Option {
- match id {
- Symbol::Generated(n) => Some(format!("%{n}")),
- Symbol::Interned(id) => self.id_to_string.borrow().get(*id).cloned(),
- }
- }
-}
diff --git a/crates/vulpi-ir/Cargo.toml b/crates/vulpi-ir/Cargo.toml
deleted file mode 100644
index 171b9fd..0000000
--- a/crates/vulpi-ir/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "vulpi-ir"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-vulpi-location = { path = "../vulpi-location" }
-vulpi-syntax = { path = "../vulpi-syntax" }
-vulpi-intern = { path = "../vulpi-intern" }
-vulpi-typer = { path = "../vulpi-typer" }
-vulpi-show = { path = "../vulpi-show" }
-vulpi-macros = { path = "../vulpi-macros" }
diff --git a/crates/vulpi-ir/src/first_pass.rs b/crates/vulpi-ir/src/first_pass.rs
deleted file mode 100644
index 616b569..0000000
--- a/crates/vulpi-ir/src/first_pass.rs
+++ /dev/null
@@ -1,340 +0,0 @@
-use vulpi_syntax::{
- elaborated::{ExprKind, *},
- r#abstract::Qualified,
-};
-use vulpi_typer::r#type::TypeKind;
-
-use crate::{
- ir::{self, FnDecl},
- pattern::{extract_accesors, CaseTree, Problem},
- Context,
-};
-
-type Type = vulpi_typer::Type;
-
-pub trait FirstPass {
- type Output;
-
- fn first_pass(self, context: &mut Context) -> Self::Output;
-}
-
-impl FirstPass for Program {
- type Output = Vec;
-
- fn first_pass(self, context: &mut Context) -> Self::Output {
- for typ in self.types {
- match typ.1 {
- TypeDecl::Enum(variants) => {
- context.enums.insert(typ.0.clone(), variants.clone());
- for (i, (variant, size)) in variants.iter().enumerate() {
- context
- .constructors
- .insert(variant.clone(), (typ.0.clone(), i, *size));
- }
- }
- TypeDecl::Record(fields) => {
- context.records.insert(typ.0.clone(), fields.clone());
- for (i, field) in fields.iter().enumerate() {
- context.fields.insert(field.clone(), (typ.0.clone(), i));
- }
- }
- _ => (),
- }
- }
-
- for effs in self.effects {
- context.eff_types.insert(effs.0.clone(), effs.1.clone());
-
- for (i, eff) in effs.1.into_iter().enumerate() {
- context.effects.insert(eff, (effs.0.clone(), i));
- }
- }
-
- self.lets
- .into_iter()
- .map(|decl| decl.first_pass(context))
- .collect()
- }
-}
-
-impl FirstPass for (Qualified, LetDecl) {
- type Output = FnDecl;
-
- fn first_pass(self, ctx: &mut Context) -> Self::Output {
- let (name, decl) = self;
-
- let mut params = vec![];
- let mut accessors = vec![];
-
- for (binder, _) in decl.binders {
- match *binder {
- PatternKind::Wildcard => params.push(ctx.fresh()),
- PatternKind::Variable(x) => params.push(x),
- _ => {
- let value = ctx.fresh();
- params.push(value.clone());
- let expr = ir::ExprKind::Variable(value);
- let new_accessors = extract_accesors(&binder, Box::new(expr));
- accessors.extend(new_accessors);
- }
- }
- }
-
- let tree = Problem::new(&decl.body);
-
- let body = tree.compile();
-
- let arms: Vec<_> = decl
- .body
- .into_iter()
- .map(|x| (x.patterns, x.expr))
- .collect();
-
- let mut bodies = vec![];
-
- let arm_params = arms.first().map(|x| x.0.len()).unwrap_or_default();
- let arm_params = (0..arm_params).map(|_| ctx.fresh()).collect::>();
-
- for (patterns, body) in arms {
- let mut acessors = vec![];
-
- for (pattern, param) in patterns.iter().zip(arm_params.iter()) {
- let new_accessors =
- extract_accesors(pattern, Box::new(ir::ExprKind::Variable(param.clone())));
- acessors.extend(new_accessors);
- }
-
- let body = body.first_pass(ctx);
-
- let mut accessors: Vec<_> = acessors
- .into_iter()
- .map(|x| ir::Statement::Let(x.0, x.1))
- .collect();
-
- accessors.push(ir::Statement::Expr(body));
-
- let block = ir::ExprKind::Block(accessors);
- bodies.push(Box::new(block));
- }
-
- let mut block = accessors
- .into_iter()
- .map(|(x, y)| ir::Statement::Let(x, y))
- .collect::>();
-
- if let CaseTree::Leaf(x) = body {
- block.push(ir::Statement::Expr(bodies.swap_remove(x)))
- } else {
- block.push(ir::Statement::Expr(Box::new(ir::ExprKind::Tree(
- body, bodies,
- ))));
- }
-
- let body = Box::new(ir::ExprKind::Block(block));
-
- FnDecl { name, params, body }
- }
-}
-
-impl FirstPass for Literal {
- type Output = ir::ExprKind;
-
- fn first_pass(self, context: &mut Context) -> Self::Output {
- match *self {
- LiteralKind::String(s) => ir::ExprKind::Literal(ir::Literal::String(s)),
- LiteralKind::Integer(i) => ir::ExprKind::Literal(ir::Literal::Integer(i)),
- LiteralKind::Float(f) => ir::ExprKind::Literal(ir::Literal::Float(f)),
- LiteralKind::Char(c) => ir::ExprKind::Literal(ir::Literal::Char(c)),
- LiteralKind::Unit => ir::ExprKind::Tuple(vec![]),
- }
- }
-}
-
-impl FirstPass for StatementKind {
- type Output = Vec;
-
- fn first_pass(self, context: &mut Context) -> Self::Output {
- match self {
- StatementKind::Let(l) => match *l.pattern {
- PatternKind::Wildcard => vec![ir::Statement::Expr(l.expr.first_pass(context))],
- PatternKind::Variable(s) => vec![ir::Statement::Let(s, l.expr.first_pass(context))],
- _ => {
- let name = context.fresh();
-
- let scrutinee = Box::new(ir::ExprKind::Variable(name.clone()));
- let accessors = extract_accesors(&l.pattern, scrutinee);
-
- let first = ir::Statement::Let(name, l.expr.first_pass(context));
-
- let accessors = accessors
- .into_iter()
- .map(|x| ir::Statement::Let(x.0, x.1))
- .collect::>();
-
- let mut block = vec![first];
- block.extend(accessors);
-
- block
- }
- },
- StatementKind::Expr(expr) => vec![ir::Statement::Expr(expr.first_pass(context))],
- StatementKind::Error => unreachable!(),
- }
- }
-}
-
-impl FirstPass for Expr {
- type Output = ir::Expr;
-
- fn first_pass(self, ctx: &mut Context) -> Self::Output {
- match *self {
- ExprKind::Lambda(_) => todo!(),
- ExprKind::Application(x) => {
- let mut args = vec![];
-
- for arg in x.args {
- args.push(arg.first_pass(ctx));
- }
-
- let to_add = arrow_spine(x.typ);
-
- let params = (0..to_add).map(|_| ctx.fresh()).collect::>();
-
- for param in params.clone() {
- args.push(Box::new(ir::ExprKind::Variable(param.clone())));
- }
-
- let result = match *x.func {
- ExprKind::Constructor(_, name) => {
- let (_, i, _) = ctx.constructors.get(&name).unwrap().clone();
-
- let tag = Box::new(ir::ExprKind::Tag(name, i));
-
- let args = std::iter::once(tag).chain(args.into_iter()).collect();
-
- Box::new(ir::ExprKind::Tuple(args))
- }
- ExprKind::Function(name, _) => Box::new(ir::ExprKind::Function(name, args)),
- _ => {
- let func = x.func.first_pass(ctx);
- Box::new(ir::ExprKind::Application(func, args))
- }
- };
-
- if !params.is_empty() {
- Box::new(ir::ExprKind::Lambda(params, result))
- } else {
- result
- }
- }
- ExprKind::Variable(n) => Box::new(ir::ExprKind::Variable(n)),
- ExprKind::Constructor(_, name) => {
- let (_, i, size) = ctx.constructors.get(&name).unwrap().clone();
-
- let params = (0..size).map(|_| ctx.fresh()).collect::>();
-
- let tag = Box::new(ir::ExprKind::Tag(name, i));
-
- let args: Vec<_> = params
- .iter()
- .map(|x| Box::new(ir::ExprKind::Variable(x.clone())))
- .collect();
-
- let result: Vec<_> = std::iter::once(tag).chain(args.into_iter()).collect();
-
- let result = Box::new(ir::ExprKind::Tuple(result));
-
- if !params.is_empty() {
- Box::new(ir::ExprKind::Lambda(params, result))
- } else {
- result
- }
- }
- ExprKind::Function(name, _) => Box::new(ir::ExprKind::FunPtr(name)),
- ExprKind::When(when) => {
- let problem = Problem::new(&when.arms);
-
- let tree = problem.compile();
-
- let mut exprs = Vec::new();
-
- let scrutinee: Vec<_> = when.scrutinee.iter().map(|_| ctx.fresh()).collect();
-
- let mut bodies: Vec<_> = when
- .scrutinee
- .into_iter()
- .zip(scrutinee.iter())
- .map(|(x, name)| ir::Statement::Let(name.clone(), x.first_pass(ctx)))
- .collect();
-
- for arm in when.arms {
- let mut statements = Vec::new();
-
- for (i, pat) in arm.patterns.into_iter().enumerate() {
- let scrutinee = Box::new(ir::ExprKind::Variable(scrutinee[i].clone()));
-
- let accessors = extract_accesors(&pat, scrutinee);
-
- let accessors = accessors
- .into_iter()
- .map(|x| ir::Statement::Let(x.0, x.1))
- .collect::>();
-
- statements.extend(accessors);
- }
-
- statements.push(ir::Statement::Expr(arm.expr.first_pass(ctx)));
-
- exprs.push(Box::new(ir::ExprKind::Block(statements)))
- }
-
- bodies.push(ir::Statement::Expr(Box::new(ir::ExprKind::Tree(
- tree, exprs,
- ))));
-
- Box::new(ir::ExprKind::Block(bodies))
- }
- ExprKind::Do(block) => {
- let block = block
- .into_iter()
- .flat_map(|x| x.first_pass(ctx))
- .collect::>();
-
- Box::new(ir::ExprKind::Block(block))
- }
- ExprKind::Literal(lit) => Box::new(lit.first_pass(ctx)),
- ExprKind::Effect(_, _) => todo!(),
- ExprKind::Let(_) => todo!(),
- ExprKind::Projection(proj) => {
- let (name, place) = ctx.fields.get(&proj.field).unwrap();
- todo!()
- }
- ExprKind::RecordInstance(_) => todo!(),
- ExprKind::RecordUpdate(_) => todo!(),
- ExprKind::Tuple(_) => todo!(),
- ExprKind::Handler(_) => todo!(),
- ExprKind::Cases(_) => todo!(),
- ExprKind::Error => unreachable!(),
- }
- }
-}
-
-pub fn arrow_spine(mut typ: Type) -> usize {
- let mut count = 0;
-
- loop {
- match typ.as_ref() {
- TypeKind::Arrow(l) => {
- count += 1;
- typ = l.body.clone();
- }
- TypeKind::Forall(n) => {
- typ = n.body.clone();
- }
- TypeKind::Exists(n) => {
- typ = n.body.clone();
- }
- _ => break count,
- }
- }
-}
diff --git a/crates/vulpi-ir/src/ir.rs b/crates/vulpi-ir/src/ir.rs
deleted file mode 100644
index e982f44..0000000
--- a/crates/vulpi-ir/src/ir.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use vulpi_intern::Symbol;
-use vulpi_macros::Show;
-use vulpi_syntax::r#abstract::Qualified;
-
-use crate::pattern::CaseTree;
-
-#[derive(Clone, Show)]
-pub struct FnDecl {
- pub name: Qualified,
- pub params: Vec,
- pub body: Expr,
-}
-
-#[derive(Clone, Show)]
-pub enum Literal {
- String(Symbol),
- Integer(Symbol),
- Float(Symbol),
- Char(Symbol),
-}
-
-#[derive(Clone, Show)]
-pub enum ExprKind {
- Variable(Symbol),
- Function(Qualified, Vec),
- FunPtr(Qualified),
-
- Lambda(Vec, Expr),
- Application(Expr, Vec),
-
- Projection(Expr, usize),
-
- Tree(CaseTree, Vec),
-
- Block(Vec),
-
- Literal(Literal),
- Tuple(Vec),
- Tag(Qualified, usize),
-}
-
-#[derive(Clone, Show)]
-pub enum Statement {
- Let(Symbol, Expr),
- Expr(Expr),
-}
-
-pub type Expr = Box;
diff --git a/crates/vulpi-ir/src/lib.rs b/crates/vulpi-ir/src/lib.rs
deleted file mode 100644
index 9b5adc3..0000000
--- a/crates/vulpi-ir/src/lib.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-//! Intermediate representation of a Vulpi program.
-
-use std::collections::HashMap;
-
-use crate::first_pass::FirstPass;
-
-use vulpi_intern::Symbol;
-use vulpi_show::Show;
-use vulpi_syntax::{elaborated::*, r#abstract::Qualified};
-use vulpi_typer::{Real, Type};
-
-pub mod first_pass;
-pub mod ir;
-pub mod pattern;
-
-#[derive(Default)]
-pub struct Context {
- pub enums: HashMap>,
- pub records: HashMap>,
- pub fields: HashMap,
- pub constructors: HashMap,
- pub eff_types: HashMap>,
- pub effects: HashMap,
- pub bound: HashMap,
- pub counter: usize,
-}
-
-impl Context {
- pub fn add_bound(&mut self, name: Symbol) {
- let count = self.bound.entry(name).or_insert(0);
- *count += 1;
- }
-
- pub fn fresh(&mut self) -> Symbol {
- self.counter += 1;
- Symbol::Generated(self.counter)
- }
-
- pub fn remove_bound(&mut self, name: Symbol) {
- let count = self.bound.entry(name.clone()).or_insert(0);
- *count -= 1;
-
- if *count == 0 {
- self.bound.remove(&name);
- }
- }
-
- pub fn is_bound(&self, name: Symbol) -> bool {
- self.bound.contains_key(&name)
- }
-
- pub fn first_pass(mut self, program: Program>) -> Self {
- let result = program.first_pass(&mut self);
- println!("{}", result.show());
- self
- }
-}
-
-pub fn compiler() -> Context {
- Context::default()
-}
diff --git a/crates/vulpi-ir/src/pattern.rs b/crates/vulpi-ir/src/pattern.rs
deleted file mode 100644
index d7395ab..0000000
--- a/crates/vulpi-ir/src/pattern.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-//! Compilation of patterns
-
-use std::{
- collections::{HashSet, VecDeque},
- fmt::Display,
-};
-
-use vulpi_intern::Symbol;
-use vulpi_macros::Show;
-use vulpi_syntax::{
- elaborated::PatternArm,
- elaborated::{Literal, Pattern, PatternKind},
- r#abstract::Qualified,
-};
-use vulpi_typer::{Real, Type};
-
-use crate::ir::{Expr, ExprKind};
-
-#[derive(PartialEq, Hash, Eq, Clone, Show)]
-pub enum Case {
- Tuple(usize),
- Cons(Qualified, usize),
- Literal(Literal),
- Wildcard,
-}
-
-#[derive(Clone, Debug)]
-pub struct Row(usize, VecDeque);
-
-pub fn head_constructor(pat: &Pattern) -> Option {
- match &**pat {
- PatternKind::Wildcard => None,
- PatternKind::Variable(_) => None,
- PatternKind::Literal(pat) => Some(Case::Literal(pat.clone())),
- PatternKind::Application(app) => Some(Case::Cons(app.func.clone(), app.args.len())),
- PatternKind::Error => unreachable!(),
- PatternKind::Tuple(pats) => Some(Case::Tuple(pats.len())),
- }
-}
-
-impl Row {
- pub fn pop_front(self) -> Self {
- let mut pats = self.1;
- pats.pop_front();
- Row(self.0, pats)
- }
-
- pub fn preppend(self, patterns: Vec) -> Self {
- let mut pats = self.1.clone();
- pats.pop_front();
- let mut vec: VecDeque<_> = patterns.into();
- vec.extend(pats);
- Row(self.0, vec)
- }
-
- pub fn first(&self) -> Option<&Pattern> {
- self.1.front()
- }
-
- pub fn inline(self) -> Self {
- match *self.first().unwrap().clone() {
- PatternKind::Wildcard => self.pop_front(),
- PatternKind::Variable(_) => self.pop_front(),
- PatternKind::Literal(_) => self.pop_front(),
- PatternKind::Application(app) => self.preppend(app.args),
- PatternKind::Tuple(app) => self.preppend(app),
- PatternKind::Error => todo!(),
- }
- }
-
- pub fn specialize(self, case: &Case) -> Option {
- match (case, &**self.first().unwrap()) {
- (Case::Tuple(n), PatternKind::Tuple(pats)) if *n == pats.len() => Some(self.inline()),
- (Case::Cons(q, _), PatternKind::Application(a)) if a.func == *q => Some(self.inline()),
- (Case::Literal(l), PatternKind::Literal(p)) if l == p => Some(self.inline()),
- (Case::Tuple(n), PatternKind::Variable(_) | PatternKind::Wildcard) => {
- Some(self.preppend(vec![Box::new(PatternKind::Wildcard); *n]))
- }
- (Case::Cons(_, n), PatternKind::Variable(_) | PatternKind::Wildcard) => {
- Some(self.preppend(vec![Box::new(PatternKind::Wildcard); *n]))
- }
- (Case::Literal(_), PatternKind::Variable(_) | PatternKind::Wildcard) => {
- Some(self.pop_front())
- }
- (Case::Wildcard, PatternKind::Variable(_) | PatternKind::Wildcard) => {
- Some(self.pop_front())
- }
- _ => None,
- }
- }
-
- pub fn is_all_wildcards(&self) -> bool {
- self.1
- .iter()
- .all(|p| matches!(&**p, PatternKind::Wildcard | PatternKind::Variable(_)))
- }
-
- pub fn is_empty(&self) -> bool {
- self.1.is_empty()
- }
-
- pub fn len(&self) -> usize {
- self.1.len()
- }
-}
-
-#[derive(Clone, Show)]
-pub enum CaseTree {
- Leaf(usize),
- Fail,
- Select(usize, Vec<(Case, CaseTree)>),
-}
-
-impl Display for Case {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Case::Tuple(n) => write!(f, "tuple({})", n),
- Case::Cons(q, n) => write!(f, "cons({}, {})", q.name.get(), n),
- Case::Literal(_) => write!(f, "literal"),
- Case::Wildcard => write!(f, "wildcard"),
- }
- }
-}
-
-impl Display for CaseTree {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- CaseTree::Leaf(n) => write!(f, "{}", n),
- CaseTree::Fail => write!(f, "fail"),
- CaseTree::Select(n, switches) => {
- writeln!(f, "select {n} {{")?;
- for (case, tree) in switches {
- writeln!(f, " {} => {},\n", case, tree)?;
- }
- write!(f, "}}")
- }
- }
- }
-}
-
-#[derive(Clone)]
-pub struct Problem {
- pub rows: Vec,
- pub place: usize,
-}
-
-impl Problem {
- pub fn new(arms: &[PatternArm>]) -> Problem {
- let mut rows = vec![];
-
- for (i, arm) in arms.iter().enumerate() {
- let mut pats = VecDeque::new();
- pats.extend(arm.patterns.clone());
- rows.push(Row(i, pats));
- }
-
- Problem { rows, place: 0 }
- }
-
- pub fn is_empty(&self) -> bool {
- self.rows.is_empty()
- }
-
- pub fn first(&self) -> &Row {
- self.rows.first().unwrap()
- }
-
- pub fn specialize(self, place: usize, case: &Case) -> Problem {
- Problem {
- place,
- rows: self
- .rows
- .into_iter()
- .filter_map(|row| row.specialize(case))
- .collect(),
- }
- }
-
- pub fn head_constructors(&self) -> HashSet {
- self.rows
- .iter()
- .filter_map(|row| head_constructor(row.first().unwrap()))
- .collect()
- }
-
- pub fn compile(self) -> CaseTree {
- if self.is_empty() {
- CaseTree::Fail
- } else if self.first().is_all_wildcards() {
- CaseTree::Leaf(self.first().0)
- } else {
- let head_constructors = self.head_constructors();
- let mut switches = vec![];
-
- if head_constructors.is_empty() {
- return self
- .clone()
- .specialize(self.place + 1, &Case::Wildcard)
- .compile();
- }
-
- for (i, constructor) in head_constructors.into_iter().enumerate() {
- let subproblem = self.clone().specialize(i, &constructor);
- let subswitch = subproblem.compile();
- switches.push((constructor, subswitch));
- }
-
- CaseTree::Select(self.place, switches)
- }
- }
-}
-
-pub fn extract_accesors(pat: &Pattern, scrutinee: Expr) -> Vec<(Symbol, Expr)> {
- pub fn go(pat: &Pattern, scrutinee: Expr, map: &mut Vec<(Symbol, Expr)>) {
- match &**pat {
- PatternKind::Wildcard => (),
- PatternKind::Variable(s) => map.push((s.clone(), scrutinee)),
- PatternKind::Literal(_) => (),
- PatternKind::Application(app) => {
- for (i, arg) in app.args.iter().enumerate() {
- go(
- arg,
- Box::new(ExprKind::Projection(scrutinee.clone(), i)),
- map,
- );
- }
- }
- PatternKind::Tuple(args) => {
- for (i, arg) in args.iter().enumerate() {
- go(
- arg,
- Box::new(ExprKind::Projection(scrutinee.clone(), i)),
- map,
- );
- }
- }
- PatternKind::Error => unreachable!(),
- }
- }
-
- let mut map = vec![];
- go(pat, scrutinee, &mut map);
- map
-}
diff --git a/crates/vulpi-lexer/Cargo.toml b/crates/vulpi-lexer/Cargo.toml
deleted file mode 100644
index e85fb32..0000000
--- a/crates/vulpi-lexer/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "vulpi-lexer"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-
-
-vulpi-intern = { path = "../vulpi-intern" }
-vulpi-location = { path = "../vulpi-location" }
-vulpi-syntax = { path = "../vulpi-syntax" }
-vulpi-report = { path = "../vulpi-report" }
diff --git a/crates/vulpi-lexer/src/error.rs b/crates/vulpi-lexer/src/error.rs
deleted file mode 100644
index 256f8cf..0000000
--- a/crates/vulpi-lexer/src/error.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-//! Error types for the lexing process. These are converted into [vulpi_report::Diagnostic].
-
-use vulpi_location::Span;
-use vulpi_report::IntoDiagnostic;
-
-/// The kind of lexing error.
-pub enum ErrorKind {
- UnfinishedString,
-}
-
-/// A lexing error.
-pub struct Error {
- pub location: Span,
- pub message: ErrorKind,
-}
-
-impl IntoDiagnostic for Error {
- fn message(&self) -> vulpi_report::Text {
- match self.message {
- ErrorKind::UnfinishedString => vulpi_report::Text::from("unfinished string literal"),
- }
- }
-
- fn severity(&self) -> vulpi_report::Severity {
- vulpi_report::Severity::Error
- }
-
- fn location(&self) -> Span {
- self.location.clone()
- }
-}
diff --git a/crates/vulpi-lexer/src/lib.rs b/crates/vulpi-lexer/src/lib.rs
deleted file mode 100644
index b165ccf..0000000
--- a/crates/vulpi-lexer/src/lib.rs
+++ /dev/null
@@ -1,468 +0,0 @@
-//! The entry point for the Vulpi Lexer. This module contains the first phase o all of the
-//! compilers, the lexing phase. This phase splits a source code into [Token]s that are like "words"
-//! that contain no connection to other "words". e.g
-//!
-//! ```hs
-//! // If we had a function called lex that given a source code returns a [Vec] then:
-//! lex("1 + 2")
-//! // Would return
-//! vec![Token::Num(1), Token::Plus, Token::Num(2)]
-//! ```
-//!
-//! This example does not connect tokens it only classify and return a vector of them. The Vulpi
-//! lexer, instead, return [Token]s on demand and work with white spaces in order to make
-//! *layout parsing* just like haskell.
-//!
-//! The layout parsing of Vulpi gets whitespace information and turns this information into a set of
-//! virtual braces and semicolons. e.g.
-//!
-//! ```hs
-//! do
-//! a c
-//! b
-//! ```
-//!
-//! Turns into
-//!
-//! ```hs
-//! do { a c; b; }
-//! ```
-//!
-//! Following these rules:
-//! - Some words are *layout keywords*, these keywords start blocks of indentation and:
-//! - We start a new layout block emitting a block start and push the current column to the stack
-//! after eating all of the spaces and newlines after the layout keyword.
-//! - If it's a newline then we need to run the rule
-//! - We get the last layout from the stack and we compare if the current column is:
-//! - Greater: We just continue to the next rule
-//! - Equal: We emit a semicolon
-//! - Less: We emit a block end
-//!
-
-pub mod error;
-mod literals;
-
-use std::{iter::Peekable, str::Chars};
-
-use vulpi_intern::Symbol;
-use vulpi_location::{Byte, FileId, Span, Spanned};
-use vulpi_report::{Diagnostic, Report};
-use vulpi_syntax::tokens::{Comment, Token, TokenData};
-
-/// Checks if a char is a valid identifier part.
-fn is_identifier_char(char: &char) -> bool {
- char.is_alphanumeric() || matches!(char, |'_'| '!' | '?' | '\'')
-}
-
-/// Checks if a char is a whitespace, tab or something like that.
-fn is_whitespace(char: &char) -> bool {
- matches!(char, '\t' | '\x0C' | '\r' | ' ')
-}
-
-/// Checks if a char is a whitespace, tab or something like that.
-fn is_whitespace_or_line_break(char: &char) -> bool {
- matches!(char, '\n') || is_whitespace(char)
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-enum Either {
- Left(T),
- Right(U),
-}
-
-#[derive(Clone)]
-enum LexState {
- Common,
- PushLayout,
-}
-/// A state that can be stored and recovered further in the lexing process.
-#[derive(Clone)]
-pub struct State {
- index: usize,
- start: usize,
- column: usize,
- line: usize,
- file: FileId,
- layout: Vec,
- lex_state: LexState,
- reporter: Report,
-}
-
-/// The lexer struct that contains the input and the current state. This struct is the entry point
-/// for the lexer.
-#[derive(Clone)]
-pub struct Lexer<'a> {
- peekable: Peekable>,
- input: &'a str,
- state: State,
-}
-
-impl<'a> Lexer<'a> {
- pub fn new(input: &'a str, file: FileId, reporter: Report) -> Self {
- Self {
- peekable: input.chars().peekable(),
- input,
- state: State {
- index: 0,
- start: 0,
- line: 0,
- file,
- column: 0,
- layout: vec![],
- lex_state: LexState::Common,
- reporter,
- },
- }
- }
-
- pub fn from(state: State, input: &'a str) -> Self {
- Self {
- peekable: input[state.index..].chars().peekable(),
- input,
- state,
- }
- }
-
- fn advance(&mut self) -> Option {
- let char = self.peekable.next()?;
- self.state.index += char.len_utf8();
-
- self.state.column += 1;
-
- if char == '\n' {
- self.state.column = 0;
- self.state.line += 1;
- }
-
- Some(char)
- }
-
- fn save(&mut self) {
- self.state.start = self.state.index;
- }
-
- fn span(&self) -> Span {
- Span {
- file: self.state.file,
- start: Byte(self.state.start),
- end: Byte(self.state.index),
- }
- }
-
- fn report(&mut self, message: error::ErrorKind) {
- self.state.reporter.report(Diagnostic::new(error::Error {
- location: self.span(),
- message,
- }));
- }
-
- fn spanned(&self, token: T) -> Spanned {
- Spanned::new(token, self.span())
- }
-
- fn accumulate(&mut self, predicate: fn(&char) -> bool) {
- while let Some(char) = self.peekable.peek() {
- if predicate(char) {
- self.advance();
- } else {
- break;
- }
- }
- }
-
- fn lex_whitespace(&mut self) -> Spanned {
- self.save();
-
- self.accumulate(is_whitespace_or_line_break);
-
- let whitespace = &self.input[self.state.start..self.state.index];
- let whitespace = Symbol::intern(whitespace);
-
- self.spanned(whitespace)
- }
-
- fn lex_comment(&mut self) -> Either> {
- let whitespace = self.lex_whitespace();
-
- self.save();
-
- let mut cloned = self.peekable.clone();
- cloned.next();
-
- if let Some(('-', '-')) = self.peekable.peek().zip(cloned.peek()) {
- self.accumulate(|char| *char != '\n');
- let symbol = Symbol::intern(&self.input[self.state.start..self.state.index]);
- let comment = self.spanned(symbol);
-
- Either::Left(Comment {
- comment,
- whitespace,
- })
- } else {
- Either::Right(whitespace)
- }
- }
-
- fn lex_comments(&mut self) -> (Vec, Spanned) {
- let mut comments = vec![];
-
- loop {
- match self.lex_comment() {
- Either::Left(comment) => comments.push(comment),
- Either::Right(whitespace) => break (comments, whitespace),
- }
- }
- }
-
- fn classify_identifier(&mut self) -> TokenData {
- let data = &self.input[self.state.start..self.state.index];
- match data {
- "is" => {
- self.state.lex_state = LexState::PushLayout;
- TokenData::Is
- }
- "do" => {
- self.state.lex_state = LexState::PushLayout;
- TokenData::Do
- }
- "where" => {
- self.state.lex_state = LexState::PushLayout;
- TokenData::Where
- }
- "cases" => {
- self.state.lex_state = LexState::PushLayout;
- TokenData::Cases
- }
- "effect" => TokenData::Effect,
- "handle" => TokenData::Handle,
- "mod" => TokenData::Mod,
- "let" => TokenData::Let,
- "when" => TokenData::When,
- "with" => TokenData::With,
- "if" => TokenData::If,
- "else" => TokenData::Else,
- "then" => TokenData::Then,
- "use" => TokenData::Use,
- "as" => TokenData::As,
- "type" => TokenData::Type,
- "pub" => TokenData::Pub,
- "in" => TokenData::In,
- "forall" => TokenData::Forall,
- "_" => TokenData::Wildcard,
- "external" => TokenData::External,
- _ => TokenData::LowerIdent,
- }
- }
-
- fn classify_token(&mut self, line: usize) -> (TokenData, Symbol) {
- let last_layout = self.state.layout.last();
-
- let cond = last_layout.is_some() && self.state.column < *last_layout.unwrap();
- if line != self.state.line || cond {
- let column = self.state.column;
- let last = self.state.layout.last();
-
- match last {
- None => (),
- Some(last_column) if column > *last_column => (),
- Some(last_column) if column < *last_column => {
- self.state.layout.pop();
- return (TokenData::End, Symbol::intern("end"));
- }
- Some(_) => return (TokenData::Sep, Symbol::intern("sep")),
- }
- }
-
- let result = if let Some(char) = self.advance() {
- match char {
- '{' => TokenData::LBrace,
- '}' => TokenData::RBrace,
- '(' => {
- if let Some(')') = self.peekable.peek() {
- self.advance();
- TokenData::Unit
- } else {
- TokenData::LPar
- }
- }
- ')' => TokenData::RPar,
- '[' => TokenData::LBracket,
- ']' => TokenData::RBracket,
- '<' => {
- if let Some('-') = self.peekable.peek() {
- self.advance();
- TokenData::LeftArrow
- } else {
- TokenData::Less
- }
- }
- '>' => {
- if let Some('=') = self.peekable.peek() {
- self.advance();
- TokenData::GreaterEqual
- } else {
- TokenData::Greater
- }
- }
- '-' => {
- if let Some('>') = self.peekable.peek() {
- self.advance();
- TokenData::RightArrow
- } else {
- TokenData::Minus
- }
- }
- '+' => TokenData::Plus,
- '*' => TokenData::Star,
- '/' => TokenData::Slash,
- '\\' => TokenData::BackSlash,
- '%' => TokenData::Percent,
- '^' => TokenData::Caret,
- '&' => {
- if let Some('&') = self.peekable.peek() {
- self.advance();
- TokenData::And
- } else {
- TokenData::Ampersand
- }
- }
- '|' => {
- if let Some('|') = self.peekable.peek() {
- self.advance();
- TokenData::Or
- } else if let Some('>') = self.peekable.peek() {
- self.advance();
- TokenData::PipeRight
- } else {
- TokenData::Bar
- }
- }
- '~' => TokenData::Tilde,
- '!' => {
- if let Some('=') = self.peekable.peek() {
- self.advance();
- TokenData::NotEqual
- } else {
- TokenData::Exclamation
- }
- }
- '=' => {
- if let Some('=') = self.peekable.peek() {
- self.advance();
- TokenData::DoubleEqual
- } else if let Some('>') = self.peekable.peek() {
- self.advance();
- TokenData::FatArrow
- } else {
- TokenData::Equal
- }
- }
- ':' => TokenData::Colon,
- ';' => TokenData::Semicolon,
- ',' => TokenData::Comma,
- '.' => TokenData::Dot,
- '0'..='9' => {
- self.accumulate(|char| char.is_ascii_digit());
- if let Some('.') = self.peekable.peek() {
- self.advance();
- self.accumulate(|char| char.is_ascii_digit());
- TokenData::Float
- } else {
- TokenData::Int
- }
- }
- '"' => return self.string(),
- 'A'..='Z' => {
- self.accumulate(is_identifier_char);
- TokenData::UpperIdent
- }
- c if is_identifier_char(&c) => {
- self.accumulate(is_identifier_char);
- self.classify_identifier()
- }
- _ => TokenData::Error,
- }
- } else if self.state.layout.pop().is_some() {
- TokenData::End
- } else {
- TokenData::Eof
- };
-
- let symbol = Symbol::intern(&self.input[self.state.start..self.state.index]);
- (result, symbol)
- }
-
- pub fn pop_layout(&mut self) {
- self.state.layout.pop();
- }
-
- /// Lexes a single token from the input.
- pub fn bump(&mut self) -> Token {
- let line = self.state.line;
-
- let (comments, whitespace) = self.lex_comments();
- self.save();
-
- let (kind, value) = match self.state.lex_state {
- LexState::Common => self.classify_token(line),
-
- LexState::PushLayout => {
- self.state.lex_state = LexState::Common;
-
- let last = self.state.layout.last().copied().unwrap_or_default();
-
- if self.state.column <= last {
- self.classify_token(line)
- } else {
- self.state.layout.push(self.state.column);
- (TokenData::Begin, Symbol::intern("begin"))
- }
- }
- };
-
- Token {
- comments,
- whitespace,
- kind,
- value: self.spanned(value),
- }
- }
-}
-
-impl<'a> Iterator for Lexer<'a> {
- type Item = Token;
-
- fn next(&mut self) -> Option {
- if self.state.index >= self.input.len() {
- None
- } else {
- Some(self.bump())
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use vulpi_report::hash::HashReporter;
-
- use super::*;
-
- #[test]
- fn test_lex() {
- let mut lexer = Lexer::new(
- "
- let x =
- \"a\\\"ta\"
- ",
- FileId(0),
- Report::new(HashReporter::new()),
- );
-
- let mut token = lexer.bump();
-
- while token.kind != TokenData::Eof {
- token = lexer.bump();
- assert!(token.kind != TokenData::Error);
- }
- }
-}
diff --git a/crates/vulpi-lexer/src/literals.rs b/crates/vulpi-lexer/src/literals.rs
deleted file mode 100644
index 71ad25c..0000000
--- a/crates/vulpi-lexer/src/literals.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-//! Lexing of literals like strings, integers, floats, etc.
-
-use vulpi_intern::Symbol;
-use vulpi_syntax::tokens::TokenData;
-
-use crate::{error::ErrorKind, Lexer};
-
-impl<'a> Lexer<'a> {
- /// Parses a character of a char literal
- pub fn char(&mut self) -> Option {
- match self.peekable.peek() {
- Some('\\') => self.escape(),
- Some(_) => self.advance(),
- None => None,
- }
- }
-
- /// Parses escaped characters
- pub(crate) fn escape(&mut self) -> Option {
- self.advance();
-
- let result = match self.peekable.peek() {
- Some('n') => '\n',
- Some('r') => '\r',
- Some('t') => '\t',
- Some('0') => '\0',
- Some('\\') => '\\',
- Some('\'') => '\'',
- Some('"') => '"',
- _ => return None,
- };
-
- self.advance();
-
- Some(result)
- }
-
- pub(crate) fn string(&mut self) -> (TokenData, Symbol) {
- let mut string = String::new();
-
- while let Some(c) = self.peekable.peek() {
- match c {
- '\\' => {
- if let Some(res) = self.escape() {
- string.push(res);
- } else {
- self.accumulate(|x| *x != '"');
- return (TokenData::Error, Symbol::intern(&string));
- }
- }
- '"' => break,
- _ => {
- string.push(self.advance().unwrap());
- }
- }
- }
-
- if let Some('"') = self.peekable.peek() {
- self.advance();
- (TokenData::String, Symbol::intern(&string))
- } else {
- self.report(ErrorKind::UnfinishedString);
- (TokenData::Error, Symbol::intern(&string))
- }
- }
-}
diff --git a/crates/vulpi-location/Cargo.toml b/crates/vulpi-location/Cargo.toml
index 7bafbbc..58cc76c 100644
--- a/crates/vulpi-location/Cargo.toml
+++ b/crates/vulpi-location/Cargo.toml
@@ -6,4 +6,3 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-vulpi-show = { path = "../vulpi-show" }
diff --git a/crates/vulpi-location/src/lib.rs b/crates/vulpi-location/src/lib.rs
index a874ffd..03efef0 100644
--- a/crates/vulpi-location/src/lib.rs
+++ b/crates/vulpi-location/src/lib.rs
@@ -1,98 +1,10 @@
-//! This module exposes a lot of structures that locate things inside a source code. It's really
-//! useful to generate error messages.
-
-use std::fmt::Debug;
-
-use vulpi_show::{Show, TreeDisplay};
-
-/// A new-type for a usize. It's used to locate a byte inside a source code.
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
-pub struct Byte(pub usize);
-
-/// A span that locates a piece of data inside a source code.
-#[derive(Clone, Default)]
pub struct Span {
- pub file: FileId,
- pub start: Byte,
- pub end: Byte,
-}
-
-impl Show for Span {
- fn show(&self) -> vulpi_show::TreeDisplay {
- TreeDisplay::label("Span").with(TreeDisplay::label(&format!(
- "{}~{}",
- self.start.0, self.end.0
- )))
- }
-}
-
-impl Debug for Span {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{:?}~{:?}", self.start.0, self.end.0)
- }
+ pub start: usize,
+ pub end: usize,
}
impl Span {
- pub fn new(file: FileId, start: Byte, end: Byte) -> Self {
- Self { file, start, end }
- }
-
- pub fn from_usize(file: FileId, start: usize, end: usize) -> Self {
- Self {
- file,
- start: Byte(start),
- end: Byte(end),
- }
- }
-
- pub fn mix(self, other: Self) -> Self {
- Self {
- file: self.file,
- start: std::cmp::min(self.start, other.start),
- end: std::cmp::max(self.end, other.end),
- }
- }
-}
-
-/// A span that locates a piece of data inside a source code.
-#[derive(Clone)]
-pub struct Spanned {
- pub data: T,
- pub span: Span,
-}
-
-impl Show for Spanned {
- fn show(&self) -> vulpi_show::TreeDisplay {
- TreeDisplay::label("Spanned")
- .with(TreeDisplay::label(&format!(
- "{}~{}",
- self.span.start.0, self.span.end.0
- )))
- .with(self.data.show())
+ pub fn new(start: usize, end: usize) -> Self {
+ Self { start, end }
}
-}
-
-impl Spanned {
- pub fn map(&self, f: impl FnOnce(&T) -> U) -> Spanned {
- Spanned {
- data: f(&self.data),
- span: self.span.clone(),
- }
- }
-}
-
-impl Debug for Spanned {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_tuple("Spanned").field(&self.data).finish()
- }
-}
-
-impl Spanned {
- pub fn new(data: T, range: Span) -> Self {
- Self { data, span: range }
- }
-}
-
-/// The identifier of a file.
-#[derive(Clone, Default, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
-pub struct FileId(pub usize);
+}
\ No newline at end of file
diff --git a/crates/vulpi-show/Cargo.toml b/crates/vulpi-lsp/Cargo.toml
similarity index 73%
rename from crates/vulpi-show/Cargo.toml
rename to crates/vulpi-lsp/Cargo.toml
index cfb32f1..579ea95 100644
--- a/crates/vulpi-show/Cargo.toml
+++ b/crates/vulpi-lsp/Cargo.toml
@@ -1,8 +1,10 @@
[package]
-name = "vulpi-show"
+name = "vulpi-lsp"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+tokio = "1.33.0"
+tower-lsp = "0.20.0"
diff --git a/crates/vulpi-lsp/src/lib.rs b/crates/vulpi-lsp/src/lib.rs
new file mode 100644
index 0000000..7149614
--- /dev/null
+++ b/crates/vulpi-lsp/src/lib.rs
@@ -0,0 +1,58 @@
+use tower_lsp::jsonrpc::Result;
+use tower_lsp::lsp_types::*;
+use tower_lsp::{Client, LanguageServer, LspService, Server};
+
+#[derive(Debug)]
+struct Backend {
+ client: Client,
+}
+
+#[tower_lsp::async_trait]
+impl LanguageServer for Backend {
+ async fn initialize(&self, _: InitializeParams) -> Result {
+ Ok(InitializeResult {
+ capabilities: ServerCapabilities {
+ hover_provider: Some(HoverProviderCapability::Simple(true)),
+ completion_provider: Some(CompletionOptions::default()),
+ ..Default::default()
+ },
+ ..Default::default()
+ })
+ }
+
+ async fn initialized(&self, _: InitializedParams) {
+ self.client
+ .log_message(MessageType::INFO, "server initialized!")
+ .await;
+ }
+
+ async fn shutdown(&self) -> Result<()> {
+ Ok(())
+ }
+
+ async fn completion(&self, _: CompletionParams) -> Result