svg-filters & basic parser #15
19 changed files with 1 additions and 1885 deletions
339
Cargo.lock
generated
339
Cargo.lock
generated
|
@ -82,133 +82,6 @@ dependencies = [
|
||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-channel"
|
|
||||||
version = "2.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
|
|
||||||
dependencies = [
|
|
||||||
"concurrent-queue",
|
|
||||||
"event-listener-strategy",
|
|
||||||
"futures-core",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-executor"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0"
|
|
||||||
dependencies = [
|
|
||||||
"async-task",
|
|
||||||
"concurrent-queue",
|
|
||||||
"fastrand",
|
|
||||||
"futures-lite",
|
|
||||||
"slab",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-fs"
|
|
||||||
version = "2.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
|
|
||||||
dependencies = [
|
|
||||||
"async-lock",
|
|
||||||
"blocking",
|
|
||||||
"futures-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-io"
|
|
||||||
version = "2.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964"
|
|
||||||
dependencies = [
|
|
||||||
"async-lock",
|
|
||||||
"cfg-if",
|
|
||||||
"concurrent-queue",
|
|
||||||
"futures-io",
|
|
||||||
"futures-lite",
|
|
||||||
"parking",
|
|
||||||
"polling",
|
|
||||||
"rustix",
|
|
||||||
"slab",
|
|
||||||
"tracing",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-lock"
|
|
||||||
version = "3.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener",
|
|
||||||
"event-listener-strategy",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-net"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
|
|
||||||
dependencies = [
|
|
||||||
"async-io",
|
|
||||||
"blocking",
|
|
||||||
"futures-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-process"
|
|
||||||
version = "2.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-io",
|
|
||||||
"async-lock",
|
|
||||||
"async-signal",
|
|
||||||
"async-task",
|
|
||||||
"blocking",
|
|
||||||
"cfg-if",
|
|
||||||
"event-listener",
|
|
||||||
"futures-lite",
|
|
||||||
"rustix",
|
|
||||||
"tracing",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-signal"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d"
|
|
||||||
dependencies = [
|
|
||||||
"async-io",
|
|
||||||
"async-lock",
|
|
||||||
"atomic-waker",
|
|
||||||
"cfg-if",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"rustix",
|
|
||||||
"signal-hook-registry",
|
|
||||||
"slab",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-task"
|
|
||||||
version = "4.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atomic-waker"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -248,19 +121,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "blocking"
|
|
||||||
version = "1.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-task",
|
|
||||||
"futures-io",
|
|
||||||
"futures-lite",
|
|
||||||
"piper",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
version = "1.14.0"
|
version = "1.14.0"
|
||||||
|
@ -331,15 +191,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "concurrent-queue"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
|
|
||||||
dependencies = [
|
|
||||||
"crossbeam-utils",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "countme"
|
name = "countme"
|
||||||
version = "3.0.1"
|
version = "3.0.1"
|
||||||
|
@ -515,12 +366,6 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "easy-parallel"
|
|
||||||
version = "3.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2afbb9b0aef60e4f0d2b18129b6c0dff035a6f7dbbd17c2f38c1432102ee223c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ego-tree"
|
name = "ego-tree"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
@ -560,16 +405,6 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eval"
|
name = "eval"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -580,27 +415,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "event-listener"
|
|
||||||
version = "5.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
|
|
||||||
dependencies = [
|
|
||||||
"concurrent-queue",
|
|
||||||
"parking",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "event-listener-strategy"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "exr"
|
name = "exr"
|
||||||
version = "1.71.0"
|
version = "1.71.0"
|
||||||
|
@ -617,12 +431,6 @@ dependencies = [
|
||||||
"zune-inflate",
|
"zune-inflate",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fastrand"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdeflate"
|
name = "fdeflate"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -663,31 +471,6 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-core"
|
|
||||||
version = "0.3.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-io"
|
|
||||||
version = "0.3.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-lite"
|
|
||||||
version = "2.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
|
|
||||||
dependencies = [
|
|
||||||
"fastrand",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"parking",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
|
@ -827,18 +610,14 @@ dependencies = [
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"drop_bomb",
|
"drop_bomb",
|
||||||
"easy-parallel",
|
|
||||||
"ego-tree",
|
"ego-tree",
|
||||||
"enumset",
|
"enumset",
|
||||||
"futures-lite",
|
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"indoc",
|
"indoc",
|
||||||
"logos",
|
"logos",
|
||||||
"num_cpus",
|
|
||||||
"owo-colors",
|
"owo-colors",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
"rowan",
|
"rowan",
|
||||||
"smol",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -870,12 +649,6 @@ dependencies = [
|
||||||
"redox_syscall 0.4.1",
|
"redox_syscall 0.4.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.4.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
|
@ -974,16 +747,6 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "num_threads"
|
name = "num_threads"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -1014,12 +777,6 @@ dependencies = [
|
||||||
"supports-color",
|
"supports-color",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.9.10"
|
version = "0.9.10"
|
||||||
|
@ -1085,23 +842,6 @@ dependencies = [
|
||||||
"siphasher",
|
"siphasher",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project-lite"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "piper"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391"
|
|
||||||
dependencies = [
|
|
||||||
"atomic-waker",
|
|
||||||
"fastrand",
|
|
||||||
"futures-io",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.10"
|
version = "0.17.10"
|
||||||
|
@ -1115,21 +855,6 @@ dependencies = [
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polling"
|
|
||||||
version = "3.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"concurrent-queue",
|
|
||||||
"hermit-abi",
|
|
||||||
"pin-project-lite",
|
|
||||||
"rustix",
|
|
||||||
"tracing",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -1274,19 +999,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.38.34"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.1",
|
|
||||||
"errno",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.16"
|
version = "1.0.16"
|
||||||
|
@ -1330,15 +1042,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-registry"
|
|
||||||
version = "1.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -1351,38 +1054,12 @@ version = "0.3.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slab"
|
|
||||||
version = "0.4.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.11.2"
|
version = "1.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smol"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-executor",
|
|
||||||
"async-fs",
|
|
||||||
"async-io",
|
|
||||||
"async-lock",
|
|
||||||
"async-net",
|
|
||||||
"async-process",
|
|
||||||
"blocking",
|
|
||||||
"futures-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.8"
|
version = "0.9.8"
|
||||||
|
@ -1486,22 +1163,6 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing"
|
|
||||||
version = "0.1.40"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
|
||||||
dependencies = [
|
|
||||||
"pin-project-lite",
|
|
||||||
"tracing-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing-core"
|
|
||||||
version = "0.1.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
|
|
|
@ -16,13 +16,9 @@ rowan = "0.15.15"
|
||||||
drop_bomb = "0.1.5"
|
drop_bomb = "0.1.5"
|
||||||
enumset = "1.1.3"
|
enumset = "1.1.3"
|
||||||
indoc = "2"
|
indoc = "2"
|
||||||
num_cpus = "1.16"
|
|
||||||
dashmap = "5.5.3"
|
dashmap = "5.5.3"
|
||||||
crossbeam = "0.8.4"
|
crossbeam = "0.8.4"
|
||||||
owo-colors = {version = "4", features = ["supports-colors"]}
|
owo-colors = {version = "4", features = ["supports-colors"]}
|
||||||
smol = "2"
|
|
||||||
futures-lite = "2.3"
|
|
||||||
easy-parallel = "3.3.1"
|
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
|
||||||
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
|
||||||
|
|
||||||
use self::{
|
|
||||||
error::{Error, WorldCreationError},
|
|
||||||
mod_tree::ModuleTree,
|
|
||||||
namespace::Registry,
|
|
||||||
source_file::SourceFile,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod error;
|
|
||||||
mod mod_tree;
|
|
||||||
mod namespace;
|
|
||||||
mod nodes;
|
|
||||||
mod path;
|
|
||||||
mod source_file;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Loc<T: AstNode> {
|
|
||||||
file: PathBuf,
|
|
||||||
syntax_el: AstPtr<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AstNode> Loc<T> {
|
|
||||||
pub fn new(file: PathBuf, syntax_el: &T) -> Self {
|
|
||||||
Self {
|
|
||||||
file,
|
|
||||||
syntax_el: AstPtr::new(syntax_el),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn file(&self) -> &PathBuf {
|
|
||||||
&self.file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct World {
|
|
||||||
entry_point: PathBuf,
|
|
||||||
files: HashMap<PathBuf, SourceFile>,
|
|
||||||
errors: Vec<Error>,
|
|
||||||
module_tree: ModuleTree,
|
|
||||||
registry: Registry,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl World {
|
|
||||||
pub fn new(entry_point: PathBuf) -> Result<Self, WorldCreationError> {
|
|
||||||
let entry_point = entry_point.canonicalize().unwrap();
|
|
||||||
let source = match std::fs::read_to_string(&entry_point) {
|
|
||||||
Ok(f) => f,
|
|
||||||
Err(e) => return Err(WorldCreationError::FailedToOpenEntryPoint(entry_point, e)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let (src, mut errors) = SourceFile::parse_from(&entry_point, source);
|
|
||||||
|
|
||||||
let (module_tree, mut files, new_errors, registry) =
|
|
||||||
ModuleTree::parse_from_main(&entry_point, &src);
|
|
||||||
errors.extend(new_errors);
|
|
||||||
module_tree.print_tree(&src.tree());
|
|
||||||
dbg!(&errors);
|
|
||||||
|
|
||||||
let _ = files.insert(entry_point.clone(), src);
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
files,
|
|
||||||
entry_point,
|
|
||||||
errors,
|
|
||||||
module_tree,
|
|
||||||
registry,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
use std::{fmt::Display, path::PathBuf};
|
|
||||||
|
|
||||||
use crate::lst_parser::error::SyntaxError;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
Syntax(PathBuf, SyntaxError),
|
|
||||||
FailedToOpenFileMod(PathBuf, std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error {
|
|
||||||
pub fn from_syntax(file: PathBuf, e: SyntaxError) -> Self {
|
|
||||||
Self::Syntax(file, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum WorldCreationError {
|
|
||||||
FailedToOpenEntryPoint(PathBuf, std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for WorldCreationError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
WorldCreationError::FailedToOpenEntryPoint(entry_path, e) => {
|
|
||||||
write!(f, "failed to open entry_point '{entry_path:?}': {e}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,281 +0,0 @@
|
||||||
use std::{
|
|
||||||
cell::RefCell,
|
|
||||||
collections::HashMap,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
rc::Rc,
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use rowan::ast::{AstNode, SyntaxNodePtr};
|
|
||||||
|
|
||||||
use crate::{lst_parser::syntax_kind::SyntaxKind, Lang, SyntaxNode};
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
error::Error,
|
|
||||||
namespace::Registry,
|
|
||||||
nodes::{self, Mod, ModBody, ModName, Root},
|
|
||||||
path::{ItemPath, OwnedItemPath},
|
|
||||||
source_file::SourceFile,
|
|
||||||
Loc,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ModuleTree {
|
|
||||||
modules: Rc<HashMap<String, Rc<Module>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct ModuleParsingContext {
|
|
||||||
files: Rc<RefCell<HashMap<PathBuf, SourceFile>>>,
|
|
||||||
errors: Rc<RefCell<Vec<Error>>>,
|
|
||||||
reg: Rc<RefCell<Registry>>,
|
|
||||||
proj_dir: Rc<PathBuf>,
|
|
||||||
cur_path: Vec<String>,
|
|
||||||
cur_file: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleParsingContext {
|
|
||||||
fn new(entry_path: &Path) -> Self {
|
|
||||||
let proj_dir = entry_path.parent().unwrap().to_owned();
|
|
||||||
Self {
|
|
||||||
files: Rc::new(RefCell::new(HashMap::new())),
|
|
||||||
errors: Rc::new(RefCell::new(Vec::new())),
|
|
||||||
reg: Rc::new(RefCell::new(Registry::new())),
|
|
||||||
proj_dir: Rc::new(entry_path.to_owned()),
|
|
||||||
cur_path: Vec::new(),
|
|
||||||
cur_file: entry_path.to_owned(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn entry_path(&self) -> PathBuf {
|
|
||||||
self.proj_dir.to_path_buf()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_mod_file_path(&self, mod_path: &[String], mod_name: &str) -> PathBuf {
|
|
||||||
let mut entry_path = self.entry_path();
|
|
||||||
for el in mod_path {
|
|
||||||
entry_path.push(format!("{el}/"));
|
|
||||||
}
|
|
||||||
entry_path.push(format!("{mod_name}.owo"));
|
|
||||||
entry_path
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_cur_path(&mut self, name_to_add: String) {
|
|
||||||
self.cur_path.push(name_to_add);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_cur_file(&mut self, new: PathBuf) {
|
|
||||||
self.cur_file = new;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_errs(&self, errs: Vec<Error>) {
|
|
||||||
self.errors.borrow_mut().extend(errs);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_child_modules(
|
|
||||||
&self,
|
|
||||||
node: &SyntaxNode,
|
|
||||||
name: Option<String>,
|
|
||||||
) -> HashMap<String, Rc<Module>> {
|
|
||||||
let mut ctx = self.clone();
|
|
||||||
if let Some(name) = name {
|
|
||||||
ctx.push_cur_path(name)
|
|
||||||
}
|
|
||||||
node.children()
|
|
||||||
.filter_map(Mod::cast)
|
|
||||||
.filter_map(|m| match Module::parse_mod(m, self.clone()) {
|
|
||||||
Ok(module) => Some((module.name(), module)),
|
|
||||||
Err(error) => {
|
|
||||||
self.errors.borrow_mut().push(error);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<HashMap<String, Rc<Module>>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dissolve(self) -> (HashMap<PathBuf, SourceFile>, Vec<Error>, Registry) {
|
|
||||||
let Self {
|
|
||||||
files,
|
|
||||||
errors,
|
|
||||||
mut reg,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
(files.take(), errors.take(), (&*reg).take())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleTree {
|
|
||||||
pub fn parse_from_main(
|
|
||||||
path: &PathBuf,
|
|
||||||
main_file: &SourceFile,
|
|
||||||
) -> (Self, HashMap<PathBuf, SourceFile>, Vec<Error>, Registry) {
|
|
||||||
let entry_path = path.parent().unwrap().to_owned();
|
|
||||||
let ctx = ModuleParsingContext::new(&entry_path);
|
|
||||||
|
|
||||||
let modules = Rc::new(ctx.parse_child_modules(main_file.tree().syntax(), None));
|
|
||||||
|
|
||||||
let (files, errors, reg) = ctx.dissolve();
|
|
||||||
(Self { modules }, files, errors, reg)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_tree(&self, lst: &Root) {
|
|
||||||
let name = "main";
|
|
||||||
print_tree(&name, self.modules.clone(), 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Module {
|
|
||||||
path: Vec<String>,
|
|
||||||
name: String,
|
|
||||||
kind: ModuleKind,
|
|
||||||
children: Rc<HashMap<String, Rc<Module>>>,
|
|
||||||
parent: Option<Rc<Module>>,
|
|
||||||
body: SyntaxNodePtr<Lang>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Module {
|
|
||||||
fn parse_mod(module: Mod, mut ctx: ModuleParsingContext) -> Result<Rc<Self>, Error> {
|
|
||||||
let children = module
|
|
||||||
.syntax()
|
|
||||||
.children()
|
|
||||||
// .map(|n| n.kind())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let r;
|
|
||||||
if children.len() == 1 {
|
|
||||||
let name = &children[0];
|
|
||||||
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
|
|
||||||
r = Self::parse_file_mod(
|
|
||||||
name.text().to_string(),
|
|
||||||
ctx.clone(),
|
|
||||||
Loc::new(ctx.cur_file.clone(), &module),
|
|
||||||
);
|
|
||||||
} else if children.len() == 2 {
|
|
||||||
let name = &children[0];
|
|
||||||
assert_eq!(name.kind(), SyntaxKind::MODULE_NAME);
|
|
||||||
let body = &children[1];
|
|
||||||
assert_eq!(body.kind(), SyntaxKind::MODULE_BODY);
|
|
||||||
r = Ok(Self::parse_inline_mod(module, ctx.clone()));
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
r.map(|module| {
|
|
||||||
let rc = Rc::new(module);
|
|
||||||
ctx.reg.borrow_mut().insert_mod(rc.path(), rc.clone());
|
|
||||||
rc
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_file_mod(
|
|
||||||
name: String,
|
|
||||||
mut ctx: ModuleParsingContext,
|
|
||||||
decl: Loc<Mod>,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
ctx.set_cur_file(ctx.make_mod_file_path(&ctx.cur_path, &name));
|
|
||||||
|
|
||||||
let source = match std::fs::read_to_string(&ctx.cur_file) {
|
|
||||||
Ok(f) => f,
|
|
||||||
Err(e) => return Err(Error::FailedToOpenFileMod(ctx.cur_file, e)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let (source_file, file_errors) = SourceFile::parse_from(&ctx.cur_file, source);
|
|
||||||
|
|
||||||
let old_path = ctx.cur_path.clone();
|
|
||||||
ctx.push_cur_path(name.clone());
|
|
||||||
ctx.push_errs(file_errors);
|
|
||||||
|
|
||||||
let children =
|
|
||||||
Rc::new(ctx.parse_child_modules(source_file.tree().syntax(), Some(name.clone())));
|
|
||||||
let body = SyntaxNodePtr::new(source_file.tree().syntax());
|
|
||||||
|
|
||||||
ctx.files
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(ctx.cur_file.clone(), source_file);
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
path: old_path,
|
|
||||||
name,
|
|
||||||
kind: ModuleKind::File {
|
|
||||||
declaration: decl,
|
|
||||||
file_id: ctx.cur_file.clone(),
|
|
||||||
},
|
|
||||||
children,
|
|
||||||
parent: None,
|
|
||||||
body,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_inline_mod(module: Mod, mut ctx: ModuleParsingContext) -> Self {
|
|
||||||
let mut children = module.syntax().children().collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let body = ModBody::cast(children.pop().unwrap()).unwrap();
|
|
||||||
let name = ModName::cast(children.pop().unwrap())
|
|
||||||
.unwrap()
|
|
||||||
.syntax()
|
|
||||||
.text()
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
let old_path = ctx.cur_path.clone();
|
|
||||||
ctx.push_cur_path(name.clone());
|
|
||||||
let children = Rc::new(ctx.parse_child_modules(body.syntax(), Some(name.clone())));
|
|
||||||
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
kind: ModuleKind::Inline(Loc::new(ctx.cur_file.to_owned(), &module)),
|
|
||||||
children,
|
|
||||||
parent: None,
|
|
||||||
path: old_path,
|
|
||||||
body: SyntaxNodePtr::new(body.syntax()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path(&self) -> ItemPath {
|
|
||||||
let mut p = self.path.clone();
|
|
||||||
p.push(self.name());
|
|
||||||
let mut r_p = ItemPath::new();
|
|
||||||
for i in p {
|
|
||||||
r_p = r_p.push(i);
|
|
||||||
}
|
|
||||||
r_p
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> String {
|
|
||||||
// self.name.to_node(lst.syntax()).syntax().text().to_string()
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn body(&self, files: &HashMap<PathBuf, SourceFile>) -> SyntaxNode {
|
|
||||||
match &self.kind {
|
|
||||||
ModuleKind::Inline(l) => {
|
|
||||||
let file = files.get(l.file()).unwrap();
|
|
||||||
self.body.to_node(file.tree().syntax())
|
|
||||||
}
|
|
||||||
ModuleKind::File { file_id, .. } => files.get(file_id).unwrap().tree().syntax().clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_tree(name: &str, children: Rc<HashMap<String, Rc<Module>>>, level: u32) {
|
|
||||||
const INDENT_STR: &str = " ";
|
|
||||||
|
|
||||||
for _ in 0..level {
|
|
||||||
print!("{}", INDENT_STR);
|
|
||||||
}
|
|
||||||
print!("{name}\n");
|
|
||||||
|
|
||||||
// for (name, module) in children.iter() {
|
|
||||||
// ;
|
|
||||||
// }
|
|
||||||
children
|
|
||||||
.iter()
|
|
||||||
.for_each(|(name, m)| print_tree(name, m.children.clone(), level + 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum ModuleKind {
|
|
||||||
Inline(Loc<nodes::Mod>),
|
|
||||||
File {
|
|
||||||
declaration: Loc<nodes::Mod>,
|
|
||||||
file_id: PathBuf,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
use std::{
|
|
||||||
cell::RefCell,
|
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
mod_tree::Module,
|
|
||||||
nodes,
|
|
||||||
path::{ItemPath, OwnedItemPath},
|
|
||||||
};
|
|
||||||
|
|
||||||
// requires mappings:
|
|
||||||
// names -> sets of references to individual objects
|
|
||||||
// paths -> individual objects
|
|
||||||
// glob paths -> sets of object refs
|
|
||||||
// (OPT/LATER) names (fuzzy) ~> sets of objects
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Registry {
|
|
||||||
defs: Vec<StoreObj<Def>>,
|
|
||||||
mods: Vec<StoreObj<Mod>>,
|
|
||||||
names: HashMap<String, HashSet<RegistryIdx>>,
|
|
||||||
paths: HashMap<OwnedItemPath, RegistryIdx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Registry {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
defs: Vec::new(),
|
|
||||||
mods: Vec::new(),
|
|
||||||
names: HashMap::new(),
|
|
||||||
paths: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: rewrite. has lots of flaws
|
|
||||||
pub fn insert_mod(&mut self, path: ItemPath<'_>, module: Rc<Module>) -> Option<RegistryIdx> {
|
|
||||||
let idx = self.mods.len();
|
|
||||||
let Some(name) = path.name() else { return None };
|
|
||||||
self.mods.push(StoreObj::new(&name, Mod { module }));
|
|
||||||
|
|
||||||
if let Some(set) = self.names.get_mut(&name) {
|
|
||||||
set.insert(RegistryIdx::Mod(idx));
|
|
||||||
} else {
|
|
||||||
self.names
|
|
||||||
.insert(name, HashSet::from([RegistryIdx::Mod(idx)]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if self
|
|
||||||
.paths
|
|
||||||
.get(&path.clone().into())
|
|
||||||
.is_some_and(|other_idx| *other_idx != RegistryIdx::Mod(idx))
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
self.paths.insert(path.into(), RegistryIdx::Mod(idx))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Registry {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
|
|
||||||
pub enum RegistryIdx {
|
|
||||||
Def(usize),
|
|
||||||
Mod(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct StoreObj<T> {
|
|
||||||
inner: Rc<InnerStoreObj<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> StoreObj<T> {
|
|
||||||
pub fn new(name: impl ToString, item: T) -> Self {
|
|
||||||
Self {
|
|
||||||
inner: Rc::new(InnerStoreObj {
|
|
||||||
name: name.to_string(),
|
|
||||||
obj: item,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct InnerStoreObj<T> {
|
|
||||||
name: String,
|
|
||||||
obj: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Mod {
|
|
||||||
module: Rc<Module>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Def {
|
|
||||||
node: nodes::Def,
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
use crate::lst_parser::syntax_kind::SyntaxKind::*;
|
|
||||||
use crate::SyntaxNode;
|
|
||||||
use rowan::Language;
|
|
||||||
macro_rules! ast_nodes {
|
|
||||||
($($ast:ident, $kind:ident);+) => {
|
|
||||||
$(
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct $ast(SyntaxNode);
|
|
||||||
impl rowan::ast::AstNode for $ast {
|
|
||||||
type Language = crate::Lang;
|
|
||||||
|
|
||||||
fn can_cast(kind: <Self::Language as Language>::Kind) -> bool {
|
|
||||||
kind == $kind
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cast(node: SyntaxNode) -> Option<Self> {
|
|
||||||
if node.kind() == $kind {
|
|
||||||
Some(Self(node))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn syntax(&self) -> &SyntaxNode {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
};
|
|
||||||
}
|
|
||||||
ast_nodes!(
|
|
||||||
Def, DEF;
|
|
||||||
DefName, DEF_NAME;
|
|
||||||
DefBody, DEF_BODY;
|
|
||||||
|
|
||||||
Mod, MODULE;
|
|
||||||
ModName, MODULE_NAME;
|
|
||||||
ModBody, MODULE_BODY;
|
|
||||||
|
|
||||||
Use, USE;
|
|
||||||
UsePat, USE_PAT;
|
|
||||||
PatItem, PAT_ITEM;
|
|
||||||
PatGlob, PAT_GLOB;
|
|
||||||
PatGroup, PAT_GROUP;
|
|
||||||
|
|
||||||
Literal, LITERAL;
|
|
||||||
IntLit, INT_NUM;
|
|
||||||
FloatLit, FLOAT_NUM;
|
|
||||||
StringLit, STRING;
|
|
||||||
|
|
||||||
Matrix, MATRIX;
|
|
||||||
MatrixRow, MAT_ROW;
|
|
||||||
Vector, VEC;
|
|
||||||
List, LIST;
|
|
||||||
CollectionItem, COLLECTION_ITEM;
|
|
||||||
|
|
||||||
ParenthesizedExpr, PARENTHESIZED_EXPR;
|
|
||||||
Expression, EXPR;
|
|
||||||
|
|
||||||
Pipeline, PIPELINE;
|
|
||||||
|
|
||||||
Instruction, INSTR;
|
|
||||||
InstructionName, INSTR_NAME;
|
|
||||||
InstructionParams, INSTR_PARAMS;
|
|
||||||
|
|
||||||
AttributeSet, ATTR_SET;
|
|
||||||
Attribute, ATTR;
|
|
||||||
AttributeName, ATTR_NAME;
|
|
||||||
AttributeValue, ATTR_VALUE;
|
|
||||||
|
|
||||||
ParseError, PARSE_ERR;
|
|
||||||
LexError, LEX_ERR;
|
|
||||||
|
|
||||||
Root, ROOT;
|
|
||||||
Eof, EOF
|
|
||||||
);
|
|
|
@ -1,94 +0,0 @@
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
pub struct ItemPath<'a> {
|
|
||||||
items: Vec<Cow<'a, str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
pub struct OwnedItemPath {
|
|
||||||
items: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OwnedItemPath {
|
|
||||||
pub fn name(&self) -> Option<String> {
|
|
||||||
self.items.last().cloned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ItemPath<'_>> for OwnedItemPath {
|
|
||||||
fn from(value: ItemPath<'_>) -> Self {
|
|
||||||
Self {
|
|
||||||
items: value
|
|
||||||
.items
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| v.into_owned())
|
|
||||||
.collect::<Vec<String>>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ItemPath<'a> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { items: Vec::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_slices(slice: &[&'a str]) -> Self {
|
|
||||||
Self {
|
|
||||||
items: slice.into_iter().map(|i| (*i).into()).collect::<Vec<_>>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(mut self, item: impl Into<Cow<'a, str>>) -> Self {
|
|
||||||
self.items.push(item.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> Option<String> {
|
|
||||||
self.items.last().cloned().map(|item| item.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> TryFrom<Pattern<'a>> for ItemPath<'a> {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(value: Pattern<'a>) -> Result<Self, Self::Error> {
|
|
||||||
let mut items = Vec::new();
|
|
||||||
|
|
||||||
for i in value.items {
|
|
||||||
match i {
|
|
||||||
PatternEl::Name(n) => items.push(n),
|
|
||||||
PatternEl::Glob => return Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { items })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Pattern<'a> {
|
|
||||||
items: Vec<PatternEl<'a>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Pattern<'a> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { items: Vec::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_name(mut self, name: &'a str) -> Self {
|
|
||||||
self.items.push(PatternEl::Name(name.into()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_glob(mut self) -> Self {
|
|
||||||
self.items.push(PatternEl::Glob);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum PatternEl<'a> {
|
|
||||||
Name(Cow<'a, str>),
|
|
||||||
Glob,
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
|
||||||
|
|
||||||
use crate::lst_parser::{
|
|
||||||
grammar::source_file,
|
|
||||||
input::Input,
|
|
||||||
output::Output,
|
|
||||||
syntax_kind::{self, SyntaxKind},
|
|
||||||
Parser,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
error::Error,
|
|
||||||
nodes::{Def, Mod, Root, Use},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SourceFile {
|
|
||||||
lst: Root,
|
|
||||||
modules: Vec<AstPtr<Mod>>,
|
|
||||||
defs: Vec<AstPtr<Def>>,
|
|
||||||
uses: Vec<AstPtr<Use>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SourceFile {
|
|
||||||
pub fn parse_from(path: &Path, source_text: String) -> (Self, Vec<Error>) {
|
|
||||||
let toks = syntax_kind::lex(&source_text);
|
|
||||||
let input = Input::new(&toks);
|
|
||||||
let mut parser = Parser::new(input);
|
|
||||||
|
|
||||||
source_file(&mut parser);
|
|
||||||
|
|
||||||
let parser_out = parser.finish();
|
|
||||||
let out = Output::from_parser_output(toks, parser_out);
|
|
||||||
|
|
||||||
let lst = out.syntax();
|
|
||||||
|
|
||||||
let mut modules = Vec::new();
|
|
||||||
let mut defs = Vec::new();
|
|
||||||
let mut uses = Vec::new();
|
|
||||||
|
|
||||||
for c in lst.children() {
|
|
||||||
match c.kind() {
|
|
||||||
SyntaxKind::MODULE => modules.push(AstPtr::new(&Mod::cast(c).unwrap())),
|
|
||||||
SyntaxKind::DEF => defs.push(AstPtr::new(&Def::cast(c).unwrap())),
|
|
||||||
SyntaxKind::USE => uses.push(AstPtr::new(&Use::cast(c).unwrap())),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
|
||||||
Self {
|
|
||||||
lst: Root::cast(lst).unwrap(),
|
|
||||||
modules,
|
|
||||||
defs,
|
|
||||||
uses,
|
|
||||||
},
|
|
||||||
out.errors()
|
|
||||||
.into_iter()
|
|
||||||
.map(|err| Error::from_syntax(path.to_owned(), err))
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tree(&self) -> &Root {
|
|
||||||
&self.lst
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn top_level_modules(&self) -> Vec<AstPtr<Mod>> {
|
|
||||||
self.modules.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn top_level_defs(&self) -> Vec<AstPtr<Def>> {
|
|
||||||
self.defs.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn top_level_uses(&self) -> Vec<AstPtr<Use>> {
|
|
||||||
self.uses.clone()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
use crate::lst_parser::syntax_kind::SyntaxKind;
|
use crate::lst_parser::syntax_kind::SyntaxKind;
|
||||||
|
|
||||||
pub mod ast;
|
|
||||||
pub mod lst_parser;
|
pub mod lst_parser;
|
||||||
pub mod world;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum Lang {}
|
pub enum Lang {}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
use lang::{
|
use lang::lst_parser::{self, grammar, input, output::Output, syntax_kind};
|
||||||
ast::World,
|
|
||||||
lst_parser::{self, grammar, input, output::Output, syntax_kind},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
use std::{
|
|
||||||
fmt::Display,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::world::world_creation_pool::WorldCreationPool;
|
|
||||||
|
|
||||||
use easy_parallel::Parallel;
|
|
||||||
use futures_lite::future;
|
|
||||||
use smol::{
|
|
||||||
channel::{unbounded, Sender},
|
|
||||||
Executor,
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::{error::Error, files::Files, registry::Registry};
|
|
||||||
|
|
||||||
pub mod error;
|
|
||||||
pub mod files;
|
|
||||||
pub mod modules;
|
|
||||||
pub mod nodes;
|
|
||||||
pub mod registry;
|
|
||||||
mod world_creation_pool;
|
|
||||||
|
|
||||||
pub struct World {}
|
|
||||||
|
|
||||||
impl World {
|
|
||||||
pub fn new(entry_point: &Path) -> Result<Self, WorldCreationError> {
|
|
||||||
let files = Files::new();
|
|
||||||
let reg = Registry::new();
|
|
||||||
|
|
||||||
let (entry_point_id, errors) = files.add_and_parse(entry_point).map_err(|e| {
|
|
||||||
WorldCreationError::FailedToOpenEntryPoint(entry_point.to_path_buf(), e)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let pool = WorldCreationPool::new(files, reg);
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum WorldCreationError {
|
|
||||||
FailedToOpenEntryPoint(PathBuf, std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for WorldCreationError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
WorldCreationError::FailedToOpenEntryPoint(entry_path, e) => {
|
|
||||||
write!(f, "failed to open entry_point '{entry_path:?}': {e}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use crate::lst_parser::error::SyntaxError;
|
|
||||||
|
|
||||||
use super::files::FileId;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
Syntax(FileId, SyntaxError),
|
|
||||||
FailedToOpenFileMod(PathBuf, std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error {
|
|
||||||
pub fn from_syntax(file: FileId, e: SyntaxError) -> Self {
|
|
||||||
Self::Syntax(file, e)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
use std::{
|
|
||||||
clone, fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
sync::{Arc, Mutex, RwLock},
|
|
||||||
};
|
|
||||||
|
|
||||||
use dashmap::DashMap;
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
lst_parser::{
|
|
||||||
error::SyntaxError, grammar::source_file, input::Input, output::Output, syntax_kind, Parser,
|
|
||||||
},
|
|
||||||
Lang,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{error::Error, modules::Module, nodes};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Loc<N: AstNode<Language = Lang>> {
|
|
||||||
file: FileId,
|
|
||||||
syntax: AstPtr<N>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: AstNode<Language = Lang>> Loc<N> {
|
|
||||||
pub fn new(node: N, file: FileId) -> Self {
|
|
||||||
Self {
|
|
||||||
file,
|
|
||||||
syntax: AstPtr::new(&node),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn file(&self) -> FileId {
|
|
||||||
self.file
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn syntax(&self) -> AstPtr<N> {
|
|
||||||
self.syntax.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// global file store
|
|
||||||
/// contains all known files etc.
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Files {
|
|
||||||
paths: Arc<Mutex<Vec<PathBuf>>>,
|
|
||||||
store: Arc<DashMap<PathBuf, Arc<SourceFile>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Files {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
paths: Arc::new(Mutex::new(Vec::new())),
|
|
||||||
store: Arc::new(DashMap::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_and_parse(&self, path: &Path) -> Result<(FileId, Vec<Error>), std::io::Error> {
|
|
||||||
let (file, errors) = SourceFile::read_and_parse(&path)?;
|
|
||||||
|
|
||||||
// add file to paths and unlock again
|
|
||||||
let id = {
|
|
||||||
let path = path.clone();
|
|
||||||
let mut paths = self.paths.lock().unwrap();
|
|
||||||
let r = paths.len();
|
|
||||||
paths.push(path.to_path_buf());
|
|
||||||
FileId(r)
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = self.store.insert(path.to_path_buf(), Arc::new(file));
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
id,
|
|
||||||
errors
|
|
||||||
.into_iter()
|
|
||||||
.map(|e| Error::from_syntax(id, e))
|
|
||||||
.collect(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, id: FileId) -> Arc<SourceFile> {
|
|
||||||
let path = {
|
|
||||||
let paths = self.paths.lock().unwrap();
|
|
||||||
paths[id.0].clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
self.store.get(&path).unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_path(&self, id: FileId) -> PathBuf {
|
|
||||||
let paths = self.paths.lock().unwrap();
|
|
||||||
paths[id.0].clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path_store(&self) -> Arc<Mutex<Vec<PathBuf>>> {
|
|
||||||
self.paths.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SourceFile {
|
|
||||||
pub lst: RwLock<rowan::GreenNode>,
|
|
||||||
root_module: Option<Arc<Module>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SourceFile {
|
|
||||||
fn read_and_parse(path: &Path) -> Result<(Self, Vec<SyntaxError>), std::io::Error> {
|
|
||||||
let source_text = fs::read_to_string(&path)?;
|
|
||||||
|
|
||||||
let toks = syntax_kind::lex(&source_text);
|
|
||||||
let input = Input::new(&toks);
|
|
||||||
let mut parser = Parser::new(input);
|
|
||||||
|
|
||||||
source_file(&mut parser);
|
|
||||||
|
|
||||||
let events = parser.finish();
|
|
||||||
let out = Output::from_parser_output(toks, events);
|
|
||||||
// let lst = out.syntax();
|
|
||||||
let (lst, errors) = out.dissolve();
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
Self {
|
|
||||||
lst: RwLock::new(lst),
|
|
||||||
root_module: None,
|
|
||||||
},
|
|
||||||
errors,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct FileId(pub usize);
|
|
|
@ -1,175 +0,0 @@
|
||||||
use std::{
|
|
||||||
string::String,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
|
||||||
|
|
||||||
use dashmap::{DashMap, DashSet};
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
|
||||||
|
|
||||||
use crate::SyntaxNode;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
files::{FileId, Loc},
|
|
||||||
nodes,
|
|
||||||
registry::ItemPath,
|
|
||||||
world_creation_pool::{wait_blocker::WaitBlocker, Task, WorkerCtx},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Module {
|
|
||||||
/// is none if this is the root module of the entry point file
|
|
||||||
decl: Option<Loc<nodes::Mod>>,
|
|
||||||
body: ModuleBody,
|
|
||||||
own_path: ItemPath,
|
|
||||||
child_modules: Arc<DashMap<String, Arc<Module>>>,
|
|
||||||
child_defs: Arc<DashMap<String, Def>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Module {
|
|
||||||
pub fn parse_mod_body(
|
|
||||||
ctx: &WorkerCtx,
|
|
||||||
tree: SyntaxNode,
|
|
||||||
path: ItemPath,
|
|
||||||
file: FileId,
|
|
||||||
) -> (DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>, Vec<Task>) {
|
|
||||||
let children: Vec<(String, Arc<Mutex<Option<Arc<Module>>>>, nodes::Mod)> = tree
|
|
||||||
.children()
|
|
||||||
.filter_map(|c| nodes::Mod::cast(c))
|
|
||||||
.map(|m| {
|
|
||||||
let name = nodes::ModName::cast(m.syntax().first_child().unwrap())
|
|
||||||
.expect("ModName should always be first child of Mod");
|
|
||||||
(
|
|
||||||
name.syntax().text().to_string(),
|
|
||||||
Arc::new(Mutex::new(None)),
|
|
||||||
m,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let retv: DashMap<String, Arc<Mutex<Option<Arc<Module>>>>> = children
|
|
||||||
.iter()
|
|
||||||
.map(|(name, mod_r, _)| (name.to_owned(), mod_r.clone()))
|
|
||||||
.collect();
|
|
||||||
let tasks = children
|
|
||||||
.into_iter()
|
|
||||||
.map(|(name, mod_r, loc)| {
|
|
||||||
let mut path = path.clone();
|
|
||||||
path.push(name);
|
|
||||||
Task::ParseMod(Loc::new(loc, file), mod_r, path)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
(retv, tasks)
|
|
||||||
}
|
|
||||||
pub fn parse_file0(
|
|
||||||
ctx: &mut WorkerCtx,
|
|
||||||
file: FileId,
|
|
||||||
path: ItemPath,
|
|
||||||
decl: Option<Loc<nodes::Mod>>,
|
|
||||||
) {
|
|
||||||
let tree = ctx.get_tree(file);
|
|
||||||
|
|
||||||
let (retv, tasks) = Self::parse_mod_body(ctx, tree, path.clone(), file);
|
|
||||||
|
|
||||||
ctx.send_tasks(
|
|
||||||
Task::ParseFileMod1 {
|
|
||||||
file,
|
|
||||||
decl,
|
|
||||||
ret: retv.into(),
|
|
||||||
path,
|
|
||||||
},
|
|
||||||
tasks,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_mod(
|
|
||||||
ctx: &mut WorkerCtx,
|
|
||||||
loc: Loc<nodes::Mod>,
|
|
||||||
path: ItemPath,
|
|
||||||
ret: Arc<Mutex<Option<Module>>>,
|
|
||||||
blocker: WaitBlocker,
|
|
||||||
) {
|
|
||||||
let mod_decl = ctx.resolve_loc(loc);
|
|
||||||
let children = mod_decl.syntax().children().collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if children.len() == 1 {
|
|
||||||
// TODO: file mod
|
|
||||||
todo!()
|
|
||||||
} else if children.len() == 2 {
|
|
||||||
// inline mod
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_inline_mod(
|
|
||||||
ctx: &mut WorkerCtx,
|
|
||||||
decl: Loc<nodes::Mod>,
|
|
||||||
path: ItemPath,
|
|
||||||
ret: Arc<Mutex<Option<Arc<Module>>>>,
|
|
||||||
blocker: WaitBlocker,
|
|
||||||
) {
|
|
||||||
let mod_decl_children = ctx
|
|
||||||
.resolve_loc(decl.clone())
|
|
||||||
.syntax()
|
|
||||||
.children()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
assert_eq!(mod_decl_children.len(), 2);
|
|
||||||
|
|
||||||
let name = nodes::ModName::cast(mod_decl_children[0].clone()).unwrap();
|
|
||||||
let body = nodes::ModBody::cast(mod_decl_children[1].clone()).unwrap();
|
|
||||||
|
|
||||||
let (retv, tasks) =
|
|
||||||
Self::parse_mod_body(ctx, body.syntax().clone(), path.clone(), decl.file());
|
|
||||||
|
|
||||||
ctx.send_tasks(
|
|
||||||
Task::CompleteMod {
|
|
||||||
ret_self: ret,
|
|
||||||
body: ModuleBody::Inline(Loc::new(body, decl.file())),
|
|
||||||
decl: Some(decl),
|
|
||||||
path,
|
|
||||||
child_mods: retv.into(),
|
|
||||||
blocker,
|
|
||||||
},
|
|
||||||
tasks,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn complete_mod(
|
|
||||||
ctx: &mut WorkerCtx,
|
|
||||||
decl: Option<Loc<nodes::Mod>>,
|
|
||||||
ret_self: Arc<Mutex<Option<Arc<Module>>>>,
|
|
||||||
body: ModuleBody,
|
|
||||||
path: ItemPath,
|
|
||||||
child_mods: Arc<DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>>,
|
|
||||||
blocker: WaitBlocker,
|
|
||||||
) {
|
|
||||||
assert!(child_mods
|
|
||||||
.iter()
|
|
||||||
.all(|item| item.value().lock().unwrap().is_some()));
|
|
||||||
|
|
||||||
let module = Arc::new(Module {
|
|
||||||
decl,
|
|
||||||
body,
|
|
||||||
own_path: path,
|
|
||||||
child_modules: Arc::new(
|
|
||||||
Arc::<_>::unwrap_or_clone(child_mods)
|
|
||||||
.into_iter()
|
|
||||||
.map(|(name, module)| {
|
|
||||||
let module = module.lock().unwrap().take().unwrap();
|
|
||||||
(name, module)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
child_defs: Arc::default(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut ret_self = ret_self.lock().unwrap();
|
|
||||||
*ret_self = Some(module);
|
|
||||||
drop(blocker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Def;
|
|
||||||
|
|
||||||
pub enum ModuleBody {
|
|
||||||
Inline(Loc<nodes::ModBody>),
|
|
||||||
File(FileId),
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
use crate::lst_parser::syntax_kind::SyntaxKind::*;
|
|
||||||
use crate::SyntaxNode;
|
|
||||||
use rowan::Language;
|
|
||||||
macro_rules! ast_nodes {
|
|
||||||
($($ast:ident, $kind:ident);+) => {
|
|
||||||
$(
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct $ast(SyntaxNode);
|
|
||||||
impl rowan::ast::AstNode for $ast {
|
|
||||||
type Language = crate::Lang;
|
|
||||||
|
|
||||||
fn can_cast(kind: <Self::Language as Language>::Kind) -> bool {
|
|
||||||
kind == $kind
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cast(node: SyntaxNode) -> Option<Self> {
|
|
||||||
if node.kind() == $kind {
|
|
||||||
Some(Self(node))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn syntax(&self) -> &SyntaxNode {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
};
|
|
||||||
}
|
|
||||||
ast_nodes!(
|
|
||||||
Def, DEF;
|
|
||||||
DefName, DEF_NAME;
|
|
||||||
DefBody, DEF_BODY;
|
|
||||||
|
|
||||||
Mod, MODULE;
|
|
||||||
ModName, MODULE_NAME;
|
|
||||||
ModBody, MODULE_BODY;
|
|
||||||
|
|
||||||
Use, USE;
|
|
||||||
UsePat, USE_PAT;
|
|
||||||
PatItem, PAT_ITEM;
|
|
||||||
PatGlob, PAT_GLOB;
|
|
||||||
PatGroup, PAT_GROUP;
|
|
||||||
|
|
||||||
Literal, LITERAL;
|
|
||||||
IntLit, INT_NUM;
|
|
||||||
FloatLit, FLOAT_NUM;
|
|
||||||
StringLit, STRING;
|
|
||||||
|
|
||||||
Matrix, MATRIX;
|
|
||||||
MatrixRow, MAT_ROW;
|
|
||||||
Vector, VEC;
|
|
||||||
List, LIST;
|
|
||||||
CollectionItem, COLLECTION_ITEM;
|
|
||||||
|
|
||||||
ParenthesizedExpr, PARENTHESIZED_EXPR;
|
|
||||||
Expression, EXPR;
|
|
||||||
|
|
||||||
Pipeline, PIPELINE;
|
|
||||||
|
|
||||||
Instruction, INSTR;
|
|
||||||
InstructionName, INSTR_NAME;
|
|
||||||
InstructionParams, INSTR_PARAMS;
|
|
||||||
|
|
||||||
AttributeSet, ATTR_SET;
|
|
||||||
Attribute, ATTR;
|
|
||||||
AttributeName, ATTR_NAME;
|
|
||||||
AttributeValue, ATTR_VALUE;
|
|
||||||
|
|
||||||
ParseError, PARSE_ERR;
|
|
||||||
LexError, LEX_ERR;
|
|
||||||
|
|
||||||
Root, ROOT;
|
|
||||||
Eof, EOF
|
|
||||||
);
|
|
|
@ -1,41 +0,0 @@
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
|
||||||
|
|
||||||
use dashmap::{DashMap, DashSet};
|
|
||||||
|
|
||||||
use super::modules::Module;
|
|
||||||
|
|
||||||
pub type ItemPath = Vec<String>;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Registry(Arc<RegistryInner>);
|
|
||||||
|
|
||||||
impl Registry {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self(Arc::new(RegistryInner::new()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RegistryInner {
|
|
||||||
/// ids will refer to paths of modules
|
|
||||||
paths: RwLock<Vec<ItemPath>>,
|
|
||||||
modules: DashMap<ItemPath, Arc<Module>>,
|
|
||||||
names: DashMap<String, DashSet<RegistryId>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegistryInner {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
paths: RwLock::new(Vec::new()),
|
|
||||||
modules: DashMap::new(),
|
|
||||||
names: DashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum RegistryId {
|
|
||||||
/// refer to the modlue item itself, the name must be the same as the last item of the path
|
|
||||||
Module(usize),
|
|
||||||
/// refer to a def in a module
|
|
||||||
/// name must refer to name of child of module
|
|
||||||
Def(usize),
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
use std::{
|
|
||||||
collections::HashMap,
|
|
||||||
path::PathBuf,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
thread,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crossbeam::channel::{Receiver, Sender};
|
|
||||||
use dashmap::DashMap;
|
|
||||||
use rowan::ast::{AstNode, AstPtr};
|
|
||||||
|
|
||||||
use crate::{Lang, SyntaxNode};
|
|
||||||
|
|
||||||
use self::wait_blocker::WaitBlocker;
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
error::Error,
|
|
||||||
files::{FileId, Files, Loc},
|
|
||||||
modules::{Module, ModuleBody},
|
|
||||||
nodes,
|
|
||||||
registry::{ItemPath, Registry},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod wait_blocker;
|
|
||||||
|
|
||||||
pub(super) struct WorldCreationPool {
|
|
||||||
workers: Vec<Worker>,
|
|
||||||
tx: Sender<Job>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WorldCreationPool {
|
|
||||||
pub fn new(files: Files, reg: Registry) -> Self {
|
|
||||||
let mut workers = Vec::new();
|
|
||||||
let (tx, rx) = crossbeam::channel::unbounded();
|
|
||||||
|
|
||||||
for i in 0..num_cpus::get() {
|
|
||||||
workers.push(Worker::new(
|
|
||||||
i,
|
|
||||||
files.clone(),
|
|
||||||
reg.clone(),
|
|
||||||
tx.clone(),
|
|
||||||
rx.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
Self { workers, tx }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Job {
|
|
||||||
WaitingFor(WaitBlocker, Task),
|
|
||||||
Awaited(WaitBlocker, Task),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Task {
|
|
||||||
ParseMod(Loc<nodes::Mod>, Arc<Mutex<Option<Arc<Module>>>>, ItemPath),
|
|
||||||
ParseFileMod0 {
|
|
||||||
file: FileId,
|
|
||||||
decl: Option<Loc<nodes::Mod>>,
|
|
||||||
path: ItemPath,
|
|
||||||
},
|
|
||||||
ParseFileMod1 {
|
|
||||||
file: FileId,
|
|
||||||
decl: Option<Loc<nodes::Mod>>,
|
|
||||||
path: ItemPath,
|
|
||||||
ret: Arc<DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>>,
|
|
||||||
},
|
|
||||||
CompleteMod {
|
|
||||||
ret_self: Arc<Mutex<Option<Arc<Module>>>>,
|
|
||||||
decl: Option<Loc<nodes::Mod>>,
|
|
||||||
body: ModuleBody,
|
|
||||||
path: ItemPath,
|
|
||||||
child_mods: Arc<DashMap<String, Arc<Mutex<Option<Arc<Module>>>>>>,
|
|
||||||
blocker: WaitBlocker,
|
|
||||||
},
|
|
||||||
OpenFile(PathBuf),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Worker {
|
|
||||||
id: usize,
|
|
||||||
// thead: thread::JoinHandle<Vec<Error>>,
|
|
||||||
thread: thread::JoinHandle<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WorkerCtx {
|
|
||||||
errors: Vec<Error>,
|
|
||||||
files: Files,
|
|
||||||
local_files: HashMap<PathBuf, SyntaxNode>,
|
|
||||||
pub reg: Registry,
|
|
||||||
tx: Sender<Job>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WorkerCtx {
|
|
||||||
pub fn get_tree(&mut self, id: FileId) -> SyntaxNode {
|
|
||||||
let p = self.files.get_path(id);
|
|
||||||
if self.local_files.contains_key(&p) {
|
|
||||||
self.local_files[&p].clone()
|
|
||||||
} else {
|
|
||||||
let f = self.files.get(id);
|
|
||||||
let lst = SyntaxNode::new_root(f.lst.read().unwrap().clone());
|
|
||||||
self.local_files.insert(p, lst.clone());
|
|
||||||
lst
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_loc<N: AstNode<Language = Lang>>(&mut self, loc: Loc<N>) -> N {
|
|
||||||
let f = self.get_tree(loc.file());
|
|
||||||
|
|
||||||
loc.syntax().to_node(&f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_tasks(&self, task: Task, dependencies: Vec<Task>) {
|
|
||||||
let blocker = WaitBlocker::new();
|
|
||||||
for dep_task in dependencies {
|
|
||||||
self.tx
|
|
||||||
.send(Job::Awaited(blocker.clone(), dep_task))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
self.tx.send(Job::WaitingFor(blocker, task)).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Worker {
|
|
||||||
fn new(id: usize, files: Files, reg: Registry, sender: Sender<Job>, rx: Receiver<Job>) -> Self {
|
|
||||||
let thread_handle = thread::spawn(move || {
|
|
||||||
let ctx = WorkerCtx {
|
|
||||||
errors: Vec::new(),
|
|
||||||
local_files: HashMap::new(),
|
|
||||||
files,
|
|
||||||
reg,
|
|
||||||
tx: sender,
|
|
||||||
};
|
|
||||||
|
|
||||||
for job in &rx {
|
|
||||||
// if matches!(job, Job::WithCond(_, _)) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
match job {
|
|
||||||
Job::WaitingFor(blocker, task) => {
|
|
||||||
if blocker.is_ready() {
|
|
||||||
Self::do_task(&ctx, task, None)
|
|
||||||
} else if rx.is_empty() {
|
|
||||||
if let Some(blocker) =
|
|
||||||
blocker.wait_for(std::time::Duration::from_millis(50))
|
|
||||||
{
|
|
||||||
ctx.tx.send(Job::WaitingFor(blocker, task)).unwrap();
|
|
||||||
} else {
|
|
||||||
Self::do_task(&ctx, task, None)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ctx.tx.send(Job::WaitingFor(blocker, task)).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Job::Awaited(blocker, task) => {
|
|
||||||
Self::do_task(&ctx, task, Some(blocker.clone()));
|
|
||||||
drop(blocker)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if let Job::WithCond(blocker, job_inner) = job_msg {
|
|
||||||
// if blocker.is_ready() {
|
|
||||||
// job = Box::<Job>::into_inner(job_inner);
|
|
||||||
// } else if rx.is_empty() {
|
|
||||||
// if let Some(blocker) =
|
|
||||||
// blocker.wait_for(std::time::Duration::from_millis(50))
|
|
||||||
// {
|
|
||||||
// job = Job::WithCond(blocker, job_inner);
|
|
||||||
// } else {
|
|
||||||
// job = Box::<Job>::into_inner(job_inner);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// job = Job::WithCond(blocker, job_inner);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// job = job_msg;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// match job {
|
|
||||||
// Job::ParseFileMod { file, decl } => todo!(),
|
|
||||||
// Job::OpenFile(path) => todo!(),
|
|
||||||
// Job::WithCond(blocker, job) => {
|
|
||||||
// ctx.tx.send(Job::WithCond(blocker, job)).unwrap()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
thread: thread_handle,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_task(ctx: &WorkerCtx, task: Task, blocker: Option<WaitBlocker>) {
|
|
||||||
match task {
|
|
||||||
Task::ParseMod(_, _, _) => todo!(),
|
|
||||||
Task::ParseFileMod0 { file, decl, path } => todo!(),
|
|
||||||
Task::ParseFileMod1 {
|
|
||||||
file,
|
|
||||||
decl,
|
|
||||||
path,
|
|
||||||
ret,
|
|
||||||
} => todo!(),
|
|
||||||
Task::CompleteMod {
|
|
||||||
ret_self,
|
|
||||||
decl,
|
|
||||||
body,
|
|
||||||
path,
|
|
||||||
child_mods,
|
|
||||||
blocker,
|
|
||||||
} => todo!(),
|
|
||||||
Task::OpenFile(_) => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
use std::{
|
|
||||||
sync::{Arc, Condvar, Mutex},
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// like a WaitGroup from crossbeam, but can also just check if it's the last one
|
|
||||||
pub struct WaitBlocker {
|
|
||||||
inner: Arc<Inner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Inner {
|
|
||||||
waiting: Mutex<usize>,
|
|
||||||
cvar: Condvar,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WaitBlocker {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: Arc::new(Inner {
|
|
||||||
waiting: Mutex::new(1),
|
|
||||||
cvar: Condvar::new(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait(self) {
|
|
||||||
if *self.inner.waiting.lock().unwrap() == 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inner = self.inner.clone();
|
|
||||||
drop(self);
|
|
||||||
|
|
||||||
inner
|
|
||||||
.cvar
|
|
||||||
.wait_while(inner.waiting.lock().unwrap(), |w| *w > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_for(self, dur: Duration) -> Option<Self> {
|
|
||||||
if *self.inner.waiting.lock().unwrap() == 1 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inner = self.inner.clone();
|
|
||||||
drop(self);
|
|
||||||
|
|
||||||
let (_, timeout_res) = inner
|
|
||||||
.cvar
|
|
||||||
.wait_timeout_while(inner.waiting.lock().unwrap(), dur, |w| *w > 0)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if timeout_res.timed_out() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
{
|
|
||||||
let mut w = inner.waiting.lock().unwrap();
|
|
||||||
*w += 1;
|
|
||||||
}
|
|
||||||
Some(Self { inner })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_ready(&self) -> bool {
|
|
||||||
*self.inner.waiting.lock().unwrap() == 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for WaitBlocker {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
let mut w = self.inner.waiting.lock().unwrap();
|
|
||||||
*w += 1;
|
|
||||||
drop(w);
|
|
||||||
Self {
|
|
||||||
inner: self.inner.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for WaitBlocker {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let mut w = self.inner.waiting.lock().unwrap();
|
|
||||||
*w -= 1;
|
|
||||||
if *w == 0 {
|
|
||||||
self.inner.cvar.notify_all()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue