forked from Orchid/orchid
bkp
This commit is contained in:
419
Cargo.lock
generated
419
Cargo.lock
generated
@@ -2,6 +2,17 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
@@ -21,12 +32,30 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@@ -36,12 +65,70 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed"
|
||||
dependencies = [
|
||||
"borsh-derive",
|
||||
"cfg_aliases",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh-derive"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"syn 2.0.52",
|
||||
"syn_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
|
||||
dependencies = [
|
||||
"bytecheck_derive",
|
||||
"ptr_meta",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytecheck_derive"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "const_panic"
|
||||
version = "0.2.8"
|
||||
@@ -154,12 +241,24 @@ version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -181,13 +280,22 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash 0.7.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.8.11",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
@@ -197,6 +305,16 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
@@ -206,6 +324,12 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "konst"
|
||||
version = "0.3.9"
|
||||
@@ -245,6 +369,12 @@ version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "never"
|
||||
version = "0.1.0"
|
||||
@@ -302,7 +432,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"derive_destructure",
|
||||
"dyn-clone",
|
||||
"hashbrown",
|
||||
"hashbrown 0.14.5",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"never",
|
||||
@@ -311,6 +441,7 @@ dependencies = [
|
||||
"orchid-api-traits",
|
||||
"ordered-float",
|
||||
"rust-embed",
|
||||
"rust_decimal",
|
||||
"substack",
|
||||
"trait-set",
|
||||
]
|
||||
@@ -319,10 +450,10 @@ dependencies = [
|
||||
name = "orchid-extension"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.8.11",
|
||||
"derive_destructure",
|
||||
"dyn-clone",
|
||||
"hashbrown",
|
||||
"hashbrown 0.14.5",
|
||||
"itertools",
|
||||
"konst",
|
||||
"never",
|
||||
@@ -335,7 +466,6 @@ dependencies = [
|
||||
"paste",
|
||||
"substack",
|
||||
"trait-set",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -343,7 +473,7 @@ name = "orchid-host"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"derive_destructure",
|
||||
"hashbrown",
|
||||
"hashbrown 0.14.5",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"orchid-api",
|
||||
@@ -384,6 +514,44 @@ version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
||||
dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
@@ -402,6 +570,26 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
|
||||
dependencies = [
|
||||
"ptr_meta_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ptr_meta_derive"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
@@ -420,6 +608,80 @@ dependencies = [
|
||||
"proc-macro2 1.0.78",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rend"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bytecheck",
|
||||
"bytes",
|
||||
"hashbrown 0.12.3",
|
||||
"ptr_meta",
|
||||
"rend",
|
||||
"rkyv_derive",
|
||||
"seahash",
|
||||
"tinyvec",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.3.0"
|
||||
@@ -454,6 +716,22 @@ dependencies = [
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"borsh",
|
||||
"bytes",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rkyv",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
@@ -463,6 +741,12 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
@@ -472,12 +756,49 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "seahash"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.120"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
@@ -489,6 +810,12 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
|
||||
|
||||
[[package]]
|
||||
name = "stdio-perftest"
|
||||
version = "0.1.0"
|
||||
@@ -538,6 +865,56 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.78",
|
||||
"quote 1.0.35",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trait-set"
|
||||
version = "0.3.0"
|
||||
@@ -549,12 +926,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
@@ -588,6 +959,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
@@ -641,6 +1018,24 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
|
||||
10
notes/comm_arch.md
Normal file
10
notes/comm_arch.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Communication Architecture
|
||||
|
||||
- **Communication medium** 1-1 duplex ordered reliable and a request/reply notify protocol defined on top (`orchid-base` mostly)
|
||||
|
||||
- **Protocol definition** plain objects that define nothing beside serialization/deserialization and English descriptions of invariants (`orchid-api`)
|
||||
|
||||
- **Active objects** smart objects that represent resources and communicate their modification through the protocol, sorted into 3 categories for asymmetric communication: common/extension/host. Some ext/host logic is defined in `orchid-base` to ensure that other behaviour within it can rely on certain global functionality. ext/host also manage their respective connection state (`orchid-base`, `orchid-extension`, `orchid-host`)
|
||||
|
||||
- **Application** (client, server) binaries that use active objects to implement actual application behaviour (`orcx`, `orchid-std`)
|
||||
|
||||
@@ -5,7 +5,5 @@ mod relations;
|
||||
|
||||
pub use coding::{Coding, Decode, Encode};
|
||||
pub use helpers::{encode_enum, read_exact, write_exact};
|
||||
pub use hierarchy::{
|
||||
Extends, InHierarchy, TLBool, TLFalse, TLTrue, UnderRoot,
|
||||
};
|
||||
pub use hierarchy::{Extends, InHierarchy, TLBool, TLFalse, TLTrue, UnderRoot};
|
||||
pub use relations::{Channel, MsgSet, Request};
|
||||
|
||||
@@ -7,6 +7,7 @@ use orchid_api_traits::Request;
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::atom::LocalAtom;
|
||||
use crate::error::ProjErrOrRef;
|
||||
use crate::expr::Expr;
|
||||
use crate::interner::TStr;
|
||||
use crate::proto::HostExtReq;
|
||||
@@ -38,7 +39,7 @@ pub enum Token {
|
||||
Slot(TreeTicket),
|
||||
/// A static compile-time error returned by erroring lexers if
|
||||
/// the rest of the source is likely still meaningful
|
||||
Bottom(String),
|
||||
Bottom(ProjErrOrRef),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Coding)]
|
||||
|
||||
@@ -17,5 +17,6 @@ orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" }
|
||||
orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
||||
ordered-float = "4.2.0"
|
||||
rust-embed = "8.3.0"
|
||||
rust_decimal = "1.35.0"
|
||||
substack = "1.1.0"
|
||||
trait-set = "0.3.0"
|
||||
|
||||
10
orchid-base/src/as_api.rs
Normal file
10
orchid-base/src/as_api.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use orchid_api_traits::Coding;
|
||||
|
||||
pub trait AsApi: Sized {
|
||||
type Api: Sized;
|
||||
type Ctx<'a>;
|
||||
fn to_api(&self, ctx: Self::Ctx<'_>) -> Self::Api;
|
||||
fn into_api(self, ctx: Self::Ctx<'_>) -> Self::Api { self.to_api(ctx) }
|
||||
fn from_api_ref(api: &Self::Api, ctx: Self::Ctx<'_>) -> Self;
|
||||
fn from_api(api: Self::Api, ctx: Self::Ctx<'_>) -> Self { Self::from_api_ref(&api, ctx) }
|
||||
}
|
||||
@@ -27,22 +27,26 @@ impl ErrorPosition {
|
||||
location: self.position.to_api(),
|
||||
}
|
||||
}
|
||||
pub fn new(msg: &str, position: Pos) -> Self {
|
||||
Self { message: Some(Arc::new(msg.to_string())), position }
|
||||
}
|
||||
}
|
||||
impl From<Pos> for ErrorPosition {
|
||||
fn from(origin: Pos) -> Self { Self { position: origin, message: None } }
|
||||
}
|
||||
|
||||
pub struct ErrorDetails {
|
||||
#[derive(Clone)]
|
||||
pub struct OwnedError {
|
||||
pub description: Tok<String>,
|
||||
pub message: Arc<String>,
|
||||
pub locations: Vec<ErrorPosition>,
|
||||
pub positions: Vec<ErrorPosition>,
|
||||
}
|
||||
impl ErrorDetails {
|
||||
impl OwnedError {
|
||||
pub fn from_api(err: &ProjErr) -> Self {
|
||||
Self {
|
||||
description: deintern(err.description),
|
||||
message: err.message.clone(),
|
||||
locations: err.locations.iter().map(ErrorPosition::from_api).collect(),
|
||||
positions: err.locations.iter().map(ErrorPosition::from_api).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ pub mod event;
|
||||
pub mod msg;
|
||||
// pub mod gen;
|
||||
pub mod api_utils;
|
||||
pub mod as_api;
|
||||
pub mod box_cow;
|
||||
pub mod char_filter;
|
||||
pub mod error;
|
||||
@@ -13,7 +14,8 @@ pub mod interner;
|
||||
pub mod join;
|
||||
pub mod location;
|
||||
pub mod name;
|
||||
pub mod number;
|
||||
pub mod reqnot;
|
||||
pub mod sequence;
|
||||
pub mod tokens;
|
||||
pub mod tree;
|
||||
// pub mod virt_fs;
|
||||
|
||||
150
orchid-base/src/number.rs
Normal file
150
orchid-base/src/number.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
use std::num::IntErrorKind;
|
||||
use std::ops::Range;
|
||||
|
||||
use ordered_float::NotNan;
|
||||
use rust_decimal::Decimal;
|
||||
|
||||
/// A number, either floating point or unsigned int, parsed by Orchid.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Numeric {
|
||||
/// A nonnegative integer
|
||||
Uint(u64),
|
||||
/// A binary float other than NaN
|
||||
Float(NotNan<f64>),
|
||||
/// A decimal number
|
||||
Decimal(Decimal),
|
||||
}
|
||||
impl Numeric {
|
||||
pub fn decimal(num: i64, scale: u32) -> Self { Self::Decimal(Decimal::new(num, scale)) }
|
||||
pub fn float(value: f64) -> Self { Self::Float(NotNan::new(value).unwrap()) }
|
||||
}
|
||||
|
||||
/// Rasons why [parse_num] might fail. See [NumError].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum NumErrorKind {
|
||||
/// The literal describes [f64::NAN]
|
||||
NaN,
|
||||
/// Some integer appearing in the literal overflows [usize]
|
||||
Overflow,
|
||||
/// A character that isn't a digit in the given base was found
|
||||
InvalidDigit,
|
||||
}
|
||||
impl NumErrorKind {
|
||||
fn from_int(kind: &IntErrorKind) -> Self {
|
||||
match kind {
|
||||
IntErrorKind::InvalidDigit => Self::InvalidDigit,
|
||||
IntErrorKind::NegOverflow | IntErrorKind::PosOverflow => Self::Overflow,
|
||||
_ => panic!("Impossible error condition"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error produced by [parse_num]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct NumError {
|
||||
/// Location
|
||||
pub range: Range<usize>,
|
||||
/// Reason
|
||||
pub kind: NumErrorKind,
|
||||
}
|
||||
|
||||
/// Parse a numbre literal out of text
|
||||
pub fn parse_num(string: &str) -> Result<Numeric, NumError> {
|
||||
let overflow_err = NumError { range: 0..string.len(), kind: NumErrorKind::Overflow };
|
||||
let (radix, noprefix, pos) = (string.strip_prefix("0x").map(|s| (16u8, s, 2)))
|
||||
.or_else(|| string.strip_prefix("0b").map(|s| (2u8, s, 2)))
|
||||
.or_else(|| string.strip_prefix("0o").map(|s| (8u8, s, 2)))
|
||||
.unwrap_or((10u8, string, 0));
|
||||
// identity
|
||||
let (base, exponent) = match noprefix.split_once('p') {
|
||||
Some((b, e)) => {
|
||||
let (s, d, len) = e.strip_prefix('-').map_or((1, e, 0), |ue| (-1, ue, 1));
|
||||
(b, s * int_parse(d, 10, pos + b.len() + 1 + len)? as i32)
|
||||
},
|
||||
None => (noprefix, 0),
|
||||
};
|
||||
match base.split_once('.') {
|
||||
None => {
|
||||
let base_usize = int_parse(base, radix, pos)?;
|
||||
if let Ok(pos_exp) = u32::try_from(exponent) {
|
||||
if let Some(radical) = u64::from(radix).checked_pow(pos_exp) {
|
||||
let number = base_usize.checked_mul(radical).ok_or(overflow_err)?;
|
||||
return Ok(Numeric::Uint(number));
|
||||
}
|
||||
}
|
||||
let f = (base_usize as f64) * (radix as f64).powi(exponent);
|
||||
let err = NumError { range: 0..string.len(), kind: NumErrorKind::NaN };
|
||||
Ok(Numeric::Float(NotNan::new(f).map_err(|_| err)?))
|
||||
},
|
||||
Some((whole, part)) => {
|
||||
let whole_n = int_parse(whole, radix, pos)?;
|
||||
let part_n = int_parse(part, radix, pos + whole.len() + 1)?;
|
||||
let scale = part.chars().filter(|c| *c != '_').count() as u32;
|
||||
if radix == 10 {
|
||||
let mut scaled_unit = Decimal::ONE;
|
||||
(scaled_unit.set_scale(scale))
|
||||
.map_err(|_| NumError { range: 0..string.len(), kind: NumErrorKind::Overflow })?;
|
||||
Ok(Numeric::Decimal(Decimal::from(whole_n) + scaled_unit * Decimal::from(part_n)))
|
||||
} else {
|
||||
let real_val = whole_n as f64 + (part_n as f64 / (radix as f64).powi(scale as i32));
|
||||
let f = real_val * (radix as f64).powi(exponent);
|
||||
Ok(Numeric::Float(NotNan::new(f).expect("None of the inputs are NaN")))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn int_parse(s: &str, radix: u8, start: usize) -> Result<u64, NumError> {
|
||||
let s = s.chars().filter(|c| *c != '_').collect::<String>();
|
||||
let range = start..(start + s.len());
|
||||
u64::from_str_radix(&s, radix as u32)
|
||||
.map_err(|e| NumError { range, kind: NumErrorKind::from_int(e.kind()) })
|
||||
}
|
||||
|
||||
/// Filter for characters that can appear in numbers
|
||||
pub fn numchar(c: char) -> bool { c.is_alphanumeric() | "._-".contains(c) }
|
||||
/// Filter for characters that can start numbers
|
||||
pub fn numstart(c: char) -> bool { c.is_ascii_digit() }
|
||||
|
||||
/// Print a number as a base-16 floating point literal
|
||||
#[must_use]
|
||||
pub fn print_nat16(num: NotNan<f64>) -> String {
|
||||
if *num == 0.0 {
|
||||
return "0x0".to_string();
|
||||
} else if num.is_infinite() {
|
||||
return match num.is_sign_positive() {
|
||||
true => "Infinity".to_string(),
|
||||
false => "-Infinity".to_string(),
|
||||
};
|
||||
} else if num.is_nan() {
|
||||
return "NaN".to_string();
|
||||
}
|
||||
let exp = num.log(16.0).floor();
|
||||
let man = *num / 16_f64.powf(exp);
|
||||
format!("0x{man}p{exp:.0}")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{parse_num, Numeric};
|
||||
|
||||
#[test]
|
||||
fn just_ints() {
|
||||
let test = |s, n| assert_eq!(parse_num(s), Ok(Numeric::Uint(n)));
|
||||
test("12345", 12345);
|
||||
test("0xcafebabe", 0xcafebabe);
|
||||
test("0o751", 0o751);
|
||||
test("0b111000111", 0b111000111);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimals() {
|
||||
let test = |s, n| assert_eq!(parse_num(s), Ok(n));
|
||||
test("3.1417", Numeric::decimal(31417, 4));
|
||||
test("0xf.cafe", Numeric::float(0xf as f64 + 0xcafe as f64 / 0x10000 as f64));
|
||||
test("34p3", Numeric::Uint(34000));
|
||||
test("0x2p3", Numeric::Uint(0x2 * 0x1000));
|
||||
test("1.5p3", Numeric::decimal(1500, 0));
|
||||
test("0x2.5p3", Numeric::float((0x25 * 0x100) as f64));
|
||||
}
|
||||
}
|
||||
15
orchid-base/src/tokens.rs
Normal file
15
orchid-base/src/tokens.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use orchid_api::tree::{Placeholder, PlaceholderKind};
|
||||
|
||||
use crate::interner::{deintern, Tok};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OwnedPh {
|
||||
pub name: Tok<String>,
|
||||
pub kind: PlaceholderKind,
|
||||
}
|
||||
impl OwnedPh {
|
||||
pub fn to_api(&self) -> Placeholder {
|
||||
Placeholder { name: self.name.marker(), kind: self.kind.clone() }
|
||||
}
|
||||
pub fn from_api(ph: Placeholder) -> Self { Self { name: deintern(ph.name), kind: ph.kind } }
|
||||
}
|
||||
@@ -22,4 +22,3 @@ ordered-float = "4.2.0"
|
||||
paste = "1.0.15"
|
||||
substack = "1.1.0"
|
||||
trait-set = "0.3.0"
|
||||
typeid = "1.0.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::any::{type_name, Any};
|
||||
use std::any::{type_name, Any, TypeId};
|
||||
use std::io::{Read, Write};
|
||||
use std::ops::Deref;
|
||||
|
||||
@@ -9,7 +9,6 @@ use orchid_api_traits::{Coding, Decode, Request};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::reqnot::Requester;
|
||||
use trait_set::trait_set;
|
||||
use typeid::ConstTypeId;
|
||||
|
||||
use crate::error::ProjectError;
|
||||
use crate::expr::{ExprHandle, GenExpr};
|
||||
@@ -33,19 +32,22 @@ impl<A: Atomic> AtomCard for A {
|
||||
|
||||
pub trait AtomicFeatures: Atomic {
|
||||
fn factory(self) -> AtomFactory;
|
||||
fn info() -> &'static AtomInfo;
|
||||
type Info: AtomDynfo;
|
||||
const INFO: &'static Self::Info;
|
||||
}
|
||||
pub trait AtomicFeaturesImpl<Variant: AtomicVariant> {
|
||||
fn _factory(self) -> AtomFactory;
|
||||
fn _info() -> &'static AtomInfo;
|
||||
type _Info: AtomDynfo;
|
||||
const _INFO: &'static Self::_Info;
|
||||
}
|
||||
impl<A: Atomic + AtomicFeaturesImpl<A::Variant>> AtomicFeatures for A {
|
||||
fn factory(self) -> AtomFactory { self._factory() }
|
||||
fn info() -> &'static AtomInfo { Self::_info() }
|
||||
type Info = <Self as AtomicFeaturesImpl<A::Variant>>::_Info;
|
||||
const INFO: &'static Self::Info = Self::_INFO;
|
||||
}
|
||||
|
||||
pub fn get_info<A: AtomCard>(sys: &(impl DynSystemCard + ?Sized)) -> (u64, &AtomInfo) {
|
||||
atom_info_for(sys, ConstTypeId::of::<A>()).unwrap_or_else(|| {
|
||||
pub fn get_info<A: AtomCard>(sys: &(impl DynSystemCard + ?Sized)) -> (u64, &'static dyn AtomDynfo) {
|
||||
atom_info_for(sys, TypeId::of::<A>()).unwrap_or_else(|| {
|
||||
panic!("Atom {} not associated with system {}", type_name::<A>(), sys.name())
|
||||
})
|
||||
}
|
||||
@@ -75,14 +77,14 @@ impl<A: AtomCard> Deref for TypAtom<A> {
|
||||
fn deref(&self) -> &Self::Target { &self.value }
|
||||
}
|
||||
|
||||
pub struct AtomInfo {
|
||||
pub tid: ConstTypeId,
|
||||
pub decode: fn(&[u8]) -> Box<dyn Any>,
|
||||
pub call: fn(&[u8], SysCtx, ExprTicket) -> GenExpr,
|
||||
pub call_ref: fn(&[u8], SysCtx, ExprTicket) -> GenExpr,
|
||||
pub same: fn(&[u8], SysCtx, &[u8]) -> bool,
|
||||
pub handle_req: fn(&[u8], SysCtx, &mut dyn Read, &mut dyn Write),
|
||||
pub drop: fn(&[u8], SysCtx),
|
||||
pub trait AtomDynfo: Send + Sync + 'static {
|
||||
fn tid(&self) -> TypeId;
|
||||
fn decode(&self, data: &[u8]) -> Box<dyn Any>;
|
||||
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||
fn same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool;
|
||||
fn handle_req(&self, buf: &[u8], ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write);
|
||||
fn drop(&self, buf: &[u8], ctx: SysCtx);
|
||||
}
|
||||
|
||||
trait_set! {
|
||||
@@ -102,4 +104,4 @@ impl Clone for AtomFactory {
|
||||
pub struct ErrorNotCallable;
|
||||
impl ProjectError for ErrorNotCallable {
|
||||
const DESCRIPTION: &'static str = "This atom is not callable";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
use std::{any::{type_name, Any}, borrow::Cow, io::{Read, Write}, num::NonZeroU64};
|
||||
use std::any::{type_name, Any, TypeId};
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
use orchid_api::{atom::LocalAtom, expr::ExprTicket};
|
||||
use orchid_api::atom::LocalAtom;
|
||||
use orchid_api::expr::ExprTicket;
|
||||
use orchid_api_traits::{Decode, Encode};
|
||||
use orchid_base::id_store::{IdRecord, IdStore};
|
||||
use typeid::ConstTypeId;
|
||||
|
||||
use crate::{atom::{AtomCard, AtomFactory, AtomInfo, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable}, expr::{bot, ExprHandle, GenExpr}, system::{atom_info_for, SysCtx}};
|
||||
use crate::atom::{
|
||||
AtomCard, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable,
|
||||
};
|
||||
use crate::expr::{bot, ExprHandle, GenExpr};
|
||||
use crate::system::{atom_info_for, SysCtx};
|
||||
|
||||
pub struct OwnedVariant;
|
||||
impl AtomicVariant for OwnedVariant {}
|
||||
@@ -19,26 +27,37 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
|
||||
LocalAtom { drop: true, data }
|
||||
})
|
||||
}
|
||||
fn _info() -> &'static AtomInfo {
|
||||
fn with_atom<U>(mut b: &[u8], f: impl FnOnce(IdRecord<'_, Box<dyn DynOwnedAtom>>) -> U) -> U {
|
||||
f(OBJ_STORE.get(NonZeroU64::decode(&mut b)).expect("Received invalid atom ID"))
|
||||
}
|
||||
&const {
|
||||
AtomInfo {
|
||||
tid: ConstTypeId::of::<Self>(),
|
||||
decode: |mut b| Box::new(<Self as Atomic>::Data::decode(&mut b)),
|
||||
call: |b, ctx, arg| with_atom(b, |a| a.remove().dyn_call(ctx, arg)),
|
||||
call_ref: |b, ctx, arg| with_atom(b, |a| a.dyn_call_ref(ctx, arg)),
|
||||
same: |b1, ctx, b2| with_atom(b1, |a1| with_atom(b2, |a2| a1.dyn_same(ctx, &**a2))),
|
||||
handle_req: |b, ctx, req, rep| with_atom(b, |a| a.dyn_handle_req(ctx, req, rep)),
|
||||
drop: |b, ctx| with_atom(b, |a| a.remove().dyn_free(ctx)),
|
||||
}
|
||||
}
|
||||
type _Info = OwnedAtomDynfo<A>;
|
||||
const _INFO: &'static Self::_Info = &OwnedAtomDynfo(PhantomData);
|
||||
}
|
||||
|
||||
fn with_atom<U>(mut b: &[u8], f: impl FnOnce(IdRecord<'_, Box<dyn DynOwnedAtom>>) -> U) -> U {
|
||||
f(OBJ_STORE.get(NonZeroU64::decode(&mut b)).expect("Received invalid atom ID"))
|
||||
}
|
||||
|
||||
pub struct OwnedAtomDynfo<T: OwnedAtom>(PhantomData<T>);
|
||||
impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn decode(&self, data: &[u8]) -> Box<dyn Any> {
|
||||
Box::new(<T as AtomCard>::Data::decode(&mut &data[..]))
|
||||
}
|
||||
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
with_atom(buf, |a| a.remove().dyn_call(ctx, arg))
|
||||
}
|
||||
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
with_atom(buf, |a| a.dyn_call_ref(ctx, arg))
|
||||
}
|
||||
fn same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool {
|
||||
with_atom(buf, |a1| with_atom(buf2, |a2| a1.dyn_same(ctx, &**a2)))
|
||||
}
|
||||
fn handle_req(&self, buf: &[u8], ctx: SysCtx, req: &mut dyn Read, rep: &mut dyn Write) {
|
||||
with_atom(buf, |a| a.dyn_handle_req(ctx, req, rep))
|
||||
}
|
||||
fn drop(&self, buf: &[u8], ctx: SysCtx) { with_atom(buf, |a| a.remove().dyn_free(ctx)) }
|
||||
}
|
||||
|
||||
/// Atoms that have a [Drop]
|
||||
pub trait OwnedAtom: AtomCard + Send + Sync + Any + Clone + 'static {
|
||||
pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Send + Sync + Any + Clone + 'static {
|
||||
fn val(&self) -> Cow<'_, Self::Data>;
|
||||
#[allow(unused_variables)]
|
||||
fn call_ref(&self, arg: ExprHandle) -> GenExpr { bot(ErrorNotCallable) }
|
||||
@@ -61,7 +80,7 @@ pub trait OwnedAtom: AtomCard + Send + Sync + Any + Clone + 'static {
|
||||
fn free(self, ctx: SysCtx) {}
|
||||
}
|
||||
pub trait DynOwnedAtom: Send + Sync + 'static {
|
||||
fn atom_tid(&self) -> ConstTypeId;
|
||||
fn atom_tid(&self) -> TypeId;
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
fn encode(&self, buffer: &mut dyn Write);
|
||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenExpr;
|
||||
@@ -71,7 +90,7 @@ pub trait DynOwnedAtom: Send + Sync + 'static {
|
||||
fn dyn_free(self: Box<Self>, ctx: SysCtx);
|
||||
}
|
||||
impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
fn atom_tid(&self) -> ConstTypeId { ConstTypeId::of::<T>() }
|
||||
fn atom_tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn as_any_ref(&self) -> &dyn Any { self }
|
||||
fn encode(&self, buffer: &mut dyn Write) { self.val().as_ref().encode(buffer) }
|
||||
fn dyn_call_ref(&self, ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
@@ -81,7 +100,7 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
self.call(ExprHandle::from_args(ctx, arg))
|
||||
}
|
||||
fn dyn_same(&self, ctx: SysCtx, other: &dyn DynOwnedAtom) -> bool {
|
||||
if ConstTypeId::of::<Self>() != other.as_any_ref().type_id() {
|
||||
if TypeId::of::<Self>() != other.as_any_ref().type_id() {
|
||||
return false;
|
||||
}
|
||||
let other_self = other.as_any_ref().downcast_ref().expect("The type_ids are the same");
|
||||
@@ -93,4 +112,4 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
fn dyn_free(self: Box<Self>, ctx: SysCtx) { self.free(ctx) }
|
||||
}
|
||||
|
||||
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
|
||||
pub(crate) static OBJ_STORE: IdStore<Box<dyn DynOwnedAtom>> = IdStore::new();
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
use std::{any::type_name, fmt, io::Write};
|
||||
use std::any::{type_name, Any, TypeId};
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use orchid_api::atom::LocalAtom;
|
||||
use orchid_api::expr::ExprTicket;
|
||||
use orchid_api_traits::{Coding, Decode, Encode};
|
||||
use typeid::ConstTypeId;
|
||||
|
||||
use crate::{atom::{get_info, AtomCard, AtomFactory, AtomInfo, Atomic, AtomicFeaturesImpl, AtomicVariant, ErrorNotCallable}, expr::{bot, ExprHandle, GenExpr}, system::SysCtx};
|
||||
use crate::atom::{
|
||||
get_info, AtomCard, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant,
|
||||
ErrorNotCallable,
|
||||
};
|
||||
use crate::expr::{bot, ExprHandle, GenExpr};
|
||||
use crate::system::SysCtx;
|
||||
|
||||
pub struct ThinVariant;
|
||||
impl AtomicVariant for ThinVariant {}
|
||||
@@ -16,22 +24,32 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
|
||||
LocalAtom { drop: false, data: buf }
|
||||
})
|
||||
}
|
||||
fn _info() -> &'static AtomInfo {
|
||||
&const {
|
||||
AtomInfo {
|
||||
tid: ConstTypeId::of::<Self>(),
|
||||
decode: |mut b| Box::new(Self::decode(&mut b)),
|
||||
call: |mut b, ctx, extk| Self::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
|
||||
call_ref: |mut b, ctx, extk| Self::decode(&mut b).call(ExprHandle::from_args(ctx, extk)),
|
||||
handle_req: |mut b, ctx, req, rep| Self::decode(&mut b).handle_req(ctx, Decode::decode(req), rep),
|
||||
same: |mut b1, ctx, mut b2| Self::decode(&mut b1).same(ctx, &Self::decode(&mut b2)),
|
||||
drop: |mut b1, _| eprintln!("Received drop signal for non-drop atom {:?}", Self::decode(&mut b1)),
|
||||
}
|
||||
}
|
||||
type _Info = ThinAtomDynfo<Self>;
|
||||
const _INFO: &'static Self::_Info = &ThinAtomDynfo(PhantomData);
|
||||
}
|
||||
|
||||
pub struct ThinAtomDynfo<T: ThinAtom>(PhantomData<T>);
|
||||
impl<T: ThinAtom> AtomDynfo for ThinAtomDynfo<T> {
|
||||
fn tid(&self) -> TypeId { TypeId::of::<T>() }
|
||||
fn decode(&self, mut data: &[u8]) -> Box<dyn Any> { Box::new(T::decode(&mut data)) }
|
||||
fn call(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
||||
}
|
||||
fn call_ref(&self, buf: &[u8], ctx: SysCtx, arg: ExprTicket) -> GenExpr {
|
||||
T::decode(&mut &buf[..]).call(ExprHandle::from_args(ctx, arg))
|
||||
}
|
||||
fn handle_req(&self, buf: &[u8], ctx: SysCtx, req: &mut dyn std::io::Read, rep: &mut dyn Write) {
|
||||
T::decode(&mut &buf[..]).handle_req(ctx, Decode::decode(req), rep)
|
||||
}
|
||||
fn same(&self, buf: &[u8], ctx: SysCtx, buf2: &[u8]) -> bool {
|
||||
T::decode(&mut &buf[..]).same(ctx, &T::decode(&mut &buf2[..]))
|
||||
}
|
||||
fn drop(&self, buf: &[u8], _ctx: SysCtx) {
|
||||
eprintln!("Received drop signal for non-drop atom {:?}", T::decode(&mut &buf[..]))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug {
|
||||
pub trait ThinAtom: AtomCard<Data = Self> + Coding + fmt::Debug + Send + Sync + 'static {
|
||||
#[allow(unused_variables)]
|
||||
fn call(&self, arg: ExprHandle) -> GenExpr { bot(ErrorNotCallable) }
|
||||
#[allow(unused_variables)]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use orchid_base::location::Pos;
|
||||
|
||||
use crate::{atom::{AtomicFeatures, TypAtom}, error::{ProjectError, ProjectResult}, expr::{atom, bot_obj, ExprHandle, GenExpr, OwnedExpr}, system::downcast_atom};
|
||||
use crate::atom::{AtomicFeatures, TypAtom};
|
||||
use crate::error::{ProjectError, ProjectResult};
|
||||
use crate::expr::{atom, bot_obj, ExprHandle, GenExpr, OwnedExpr};
|
||||
use crate::system::downcast_atom;
|
||||
|
||||
pub trait TryFromExpr: Sized {
|
||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self>;
|
||||
@@ -25,14 +28,14 @@ impl ProjectError for ErrorNotAtom {
|
||||
pub struct ErrorUnexpectedType(Pos);
|
||||
impl ProjectError for ErrorUnexpectedType {
|
||||
const DESCRIPTION: &'static str = "Type error";
|
||||
fn one_position(&self) -> Pos {
|
||||
self.0.clone()
|
||||
}
|
||||
fn one_position(&self) -> Pos { self.0.clone() }
|
||||
}
|
||||
|
||||
impl<A: AtomicFeatures> TryFromExpr for TypAtom<A> {
|
||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<Self> {
|
||||
OwnedExpr::new(expr).foreign_atom().map_err(|ex| ErrorNotAtom(ex.pos.clone()).pack())
|
||||
OwnedExpr::new(expr)
|
||||
.foreign_atom()
|
||||
.map_err(|ex| ErrorNotAtom(ex.pos.clone()).pack())
|
||||
.and_then(|f| downcast_atom(f).map_err(|f| ErrorUnexpectedType(f.pos).pack()))
|
||||
}
|
||||
}
|
||||
@@ -43,13 +46,13 @@ pub trait ToExpr {
|
||||
|
||||
impl<T: ToExpr> ToExpr for ProjectResult<T> {
|
||||
fn to_expr(self) -> GenExpr {
|
||||
match self {
|
||||
Err(e) => bot_obj(e),
|
||||
Ok(t) => t.to_expr(),
|
||||
}
|
||||
match self {
|
||||
Err(e) => bot_obj(e),
|
||||
Ok(t) => t.to_expr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: AtomicFeatures> ToExpr for A {
|
||||
fn to_expr(self) -> GenExpr { atom(self) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ use orchid_base::interner::{deintern, init_replica, sweep_replica};
|
||||
use orchid_base::name::PathSlice;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
|
||||
use crate::atom::AtomInfo;
|
||||
use crate::atom::AtomDynfo;
|
||||
use crate::error::{err_or_ref_to_api, unpack_err};
|
||||
use crate::fs::VirtFS;
|
||||
use crate::lexer::LexContext;
|
||||
@@ -48,7 +48,7 @@ pub struct SystemRecord {
|
||||
pub fn with_atom_record<T>(
|
||||
systems: &Mutex<HashMap<SysId, SystemRecord>>,
|
||||
atom: &Atom,
|
||||
cb: impl FnOnce(&AtomInfo, CtedObj, &[u8]) -> T,
|
||||
cb: impl FnOnce(&'static dyn AtomDynfo, CtedObj, &[u8]) -> T,
|
||||
) -> T {
|
||||
let mut data = &atom.data[..];
|
||||
let systems_g = systems.lock().unwrap();
|
||||
@@ -77,7 +77,7 @@ pub fn extension_main(data: ExtensionData) {
|
||||
mem::drop(systems.lock().unwrap().remove(&sys_id)),
|
||||
HostExtNotif::AtomDrop(AtomDrop(atom)) => {
|
||||
with_atom_record(&systems, &atom, |rec, cted, data| {
|
||||
(rec.drop)(data, SysCtx{ reqnot, id: atom.owner, cted })
|
||||
rec.drop(data, SysCtx{ reqnot, id: atom.owner, cted })
|
||||
})
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -10,7 +10,7 @@ use orchid_api::error::{GetErrorDetails, ProjErr, ProjErrId, ProjErrOrRef};
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_base::boxed_iter::{box_once, BoxedIter};
|
||||
use orchid_base::clone;
|
||||
use orchid_base::error::{ErrorDetails, ErrorPosition};
|
||||
use orchid_base::error::{ErrorPosition, OwnedError};
|
||||
use orchid_base::interner::{deintern, intern};
|
||||
use orchid_base::location::{GetSrc, Pos};
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
@@ -290,12 +290,16 @@ pub(crate) fn err_or_ref_to_api(err: ProjectErrorObj) -> ProjErrOrRef {
|
||||
}
|
||||
|
||||
pub fn err_from_api(err: &ProjErr, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
|
||||
Arc::new(RelayedError { id: None, reqnot, details: ErrorDetails::from_api(err).into() })
|
||||
Arc::new(RelayedError { id: None, reqnot, details: OwnedError::from_api(err).into() })
|
||||
}
|
||||
|
||||
pub(crate) fn err_from_api_or_ref(err: &ProjErrOrRef, reqnot: ReqNot<ExtMsgSet>) -> ProjectErrorObj {
|
||||
pub(crate) fn err_from_api_or_ref(
|
||||
err: &ProjErrOrRef,
|
||||
reqnot: ReqNot<ExtMsgSet>,
|
||||
) -> ProjectErrorObj {
|
||||
match err {
|
||||
ProjErrOrRef::Known(id) => Arc::new(RelayedError { id: Some(*id), reqnot, details: OnceLock::default() }),
|
||||
ProjErrOrRef::Known(id) =>
|
||||
Arc::new(RelayedError { id: Some(*id), reqnot, details: OnceLock::default() }),
|
||||
ProjErrOrRef::New(err) => err_from_api(err, reqnot),
|
||||
}
|
||||
}
|
||||
@@ -303,18 +307,18 @@ pub(crate) fn err_from_api_or_ref(err: &ProjErrOrRef, reqnot: ReqNot<ExtMsgSet>)
|
||||
struct RelayedError {
|
||||
pub id: Option<ProjErrId>,
|
||||
pub reqnot: ReqNot<ExtMsgSet>,
|
||||
pub details: OnceLock<ErrorDetails>,
|
||||
pub details: OnceLock<OwnedError>,
|
||||
}
|
||||
impl RelayedError {
|
||||
fn details(&self) -> &ErrorDetails {
|
||||
fn details(&self) -> &OwnedError {
|
||||
let Self { id, reqnot, details: data } = self;
|
||||
data.get_or_init(clone!(reqnot; move || {
|
||||
let id = id.expect("Either data or ID must be initialized");
|
||||
let projerr = reqnot.request(GetErrorDetails(id));
|
||||
ErrorDetails {
|
||||
OwnedError {
|
||||
description: deintern(projerr.description),
|
||||
message: projerr.message,
|
||||
locations: projerr.locations.iter().map(ErrorPosition::from_api).collect_vec(),
|
||||
positions: projerr.locations.iter().map(ErrorPosition::from_api).collect_vec(),
|
||||
}
|
||||
}))
|
||||
}
|
||||
@@ -325,6 +329,6 @@ impl DynProjectError for RelayedError {
|
||||
fn as_any_ref(&self) -> &dyn std::any::Any { self }
|
||||
fn into_packed(self: Arc<Self>) -> ProjectErrorObj { self }
|
||||
fn positions(&self) -> BoxedIter<'_, ErrorPosition> {
|
||||
Box::new(self.details().locations.iter().cloned())
|
||||
Box::new(self.details().positions.iter().cloned())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ use trait_set::trait_set;
|
||||
|
||||
use crate::atom::Atomic;
|
||||
use crate::atom_owned::{OwnedAtom, OwnedVariant};
|
||||
use crate::conv::{ToExpr, TryFromExpr};
|
||||
use crate::expr::{ExprHandle, GenExpr};
|
||||
use crate::system::SysCtx;
|
||||
use crate::conv::{ToExpr, TryFromExpr};
|
||||
|
||||
trait_set! {
|
||||
trait FunCB = FnOnce(ExprHandle) -> GenExpr + DynClone + Send + Sync + 'static;
|
||||
@@ -16,7 +16,9 @@ trait_set! {
|
||||
|
||||
pub struct Fun(Box<dyn FunCB>);
|
||||
impl Fun {
|
||||
pub fn new<I: TryFromExpr, O: ToExpr>(f: impl FnOnce(I) -> O + Clone + Send + Sync + 'static) -> Self {
|
||||
pub fn new<I: TryFromExpr, O: ToExpr>(
|
||||
f: impl FnOnce(I) -> O + Clone + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
Self(Box::new(|eh| I::try_from_expr(eh).map(f).to_expr()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use orchid_base::reqnot::{ReqNot, Requester};
|
||||
use crate::error::{
|
||||
err_from_api_or_ref, err_or_ref_to_api, pack_err, unpack_err, ProjectErrorObj, ProjectResult,
|
||||
};
|
||||
use crate::tree::{GenTok, GenTokTree};
|
||||
use crate::tree::{OwnedTok, OwnedTokTree};
|
||||
|
||||
pub struct LexContext<'a> {
|
||||
pub text: &'a Tok<String>,
|
||||
@@ -20,13 +20,13 @@ pub struct LexContext<'a> {
|
||||
pub reqnot: ReqNot<ExtMsgSet>,
|
||||
}
|
||||
impl<'a> LexContext<'a> {
|
||||
pub fn recurse(&self, tail: &'a str) -> ProjectResult<(&'a str, GenTokTree)> {
|
||||
pub fn recurse(&self, tail: &'a str) -> ProjectResult<(&'a str, OwnedTokTree)> {
|
||||
let start = self.pos(tail);
|
||||
self
|
||||
.reqnot
|
||||
.request(SubLex { pos: start, id: self.id })
|
||||
.map_err(|e| pack_err(e.iter().map(|e| err_from_api_or_ref(e, self.reqnot.clone()))))
|
||||
.map(|lx| (&self.text[lx.pos as usize..], GenTok::Slot(lx.ticket).at(start..lx.pos)))
|
||||
.map(|lx| (&self.text[lx.pos as usize..], OwnedTok::Slot(lx.ticket).at(start..lx.pos)))
|
||||
}
|
||||
|
||||
pub fn pos(&self, tail: &'a str) -> u32 { (self.text.len() - tail.len()) as u32 }
|
||||
@@ -47,7 +47,7 @@ pub trait Lexer: Send + Sync + Sized + Default + 'static {
|
||||
fn lex<'a>(
|
||||
tail: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, GenTokTree)>>;
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>>;
|
||||
}
|
||||
|
||||
pub trait DynLexer: Send + Sync + 'static {
|
||||
@@ -56,7 +56,7 @@ pub trait DynLexer: Send + Sync + 'static {
|
||||
&self,
|
||||
tail: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, GenTokTree)>>;
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>>;
|
||||
}
|
||||
|
||||
impl<T: Lexer> DynLexer for T {
|
||||
@@ -65,7 +65,7 @@ impl<T: Lexer> DynLexer for T {
|
||||
&self,
|
||||
tail: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, GenTokTree)>> {
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>> {
|
||||
T::lex(tail, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
pub mod atom;
|
||||
pub mod atom_owned;
|
||||
pub mod atom_thin;
|
||||
pub mod conv;
|
||||
pub mod entrypoint;
|
||||
pub mod error;
|
||||
pub mod expr;
|
||||
@@ -10,6 +13,3 @@ pub mod other_system;
|
||||
pub mod system;
|
||||
pub mod system_ctor;
|
||||
pub mod tree;
|
||||
pub mod conv;
|
||||
pub mod atom_thin;
|
||||
pub mod atom_owned;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use orchid_api_traits::Decode;
|
||||
use std::any::TypeId;
|
||||
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_api::system::SysId;
|
||||
use orchid_api_traits::Decode;
|
||||
use orchid_base::reqnot::ReqNot;
|
||||
use typeid::ConstTypeId;
|
||||
|
||||
use crate::atom::{get_info, AtomCard, AtomInfo, AtomicFeatures, ForeignAtom, TypAtom};
|
||||
use crate::atom::{get_info, AtomCard, AtomDynfo, AtomicFeatures, ForeignAtom, TypAtom};
|
||||
use crate::fs::DeclFs;
|
||||
use crate::fun::Fun;
|
||||
use crate::lexer::LexerObj;
|
||||
@@ -15,44 +15,45 @@ use crate::tree::GenTree;
|
||||
/// System as consumed by foreign code
|
||||
pub trait SystemCard: Default + Send + Sync + 'static {
|
||||
type Ctor: SystemCtor;
|
||||
const ATOM_DEFS: &'static [Option<fn() -> &'static AtomInfo>];
|
||||
const ATOM_DEFS: &'static [Option<&'static dyn AtomDynfo>];
|
||||
}
|
||||
|
||||
pub trait DynSystemCard: Send + Sync + 'static {
|
||||
fn name(&self) -> &'static str;
|
||||
/// Atoms explicitly defined by the system card. Do not rely on this for
|
||||
/// querying atoms as it doesn't include the general atom types
|
||||
fn atoms(&self) -> &'static [Option<fn() -> &'static AtomInfo>];
|
||||
fn atoms(&self) -> &'static [Option<&'static dyn AtomDynfo>];
|
||||
}
|
||||
|
||||
/// Atoms supported by this package which may appear in all extensions.
|
||||
/// The indices of these are bitwise negated, such that the MSB of an atom index
|
||||
/// marks whether it belongs to this package (0) or the importer (1)
|
||||
fn general_atoms() -> &'static [Option<fn () -> &'static AtomInfo>] {
|
||||
&[Some(Fun::info)]
|
||||
}
|
||||
fn general_atoms() -> &'static [Option<&'static dyn AtomDynfo>] { &[Some(Fun::INFO)] }
|
||||
|
||||
pub fn atom_info_for(
|
||||
sys: &(impl DynSystemCard + ?Sized),
|
||||
tid: ConstTypeId,
|
||||
) -> Option<(u64, &AtomInfo)> {
|
||||
tid: TypeId,
|
||||
) -> Option<(u64, &'static dyn AtomDynfo)> {
|
||||
(sys.atoms().iter().enumerate().map(|(i, o)| (i as u64, o)))
|
||||
.chain(general_atoms().iter().enumerate().map(|(i, o)| (!(i as u64), o)))
|
||||
.filter_map(|(i, o)| o.as_ref().map(|a| (i, a())))
|
||||
.find(|ent| ent.1.tid == tid)
|
||||
.filter_map(|(i, o)| o.as_ref().map(|a| (i, *a)))
|
||||
.find(|ent| ent.1.tid() == tid)
|
||||
}
|
||||
|
||||
pub fn atom_by_idx(sys: &(impl DynSystemCard + ?Sized), tid: u64) -> Option<&'static AtomInfo> {
|
||||
pub fn atom_by_idx(
|
||||
sys: &(impl DynSystemCard + ?Sized),
|
||||
tid: u64,
|
||||
) -> Option<&'static dyn AtomDynfo> {
|
||||
if (tid >> (u64::BITS - 1)) & 1 == 1 {
|
||||
general_atoms()[!tid as usize].map(|f| f())
|
||||
general_atoms()[!tid as usize]
|
||||
} else {
|
||||
sys.atoms()[tid as usize].map(|f| f())
|
||||
sys.atoms()[tid as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SystemCard> DynSystemCard for T {
|
||||
fn name(&self) -> &'static str { T::Ctor::NAME }
|
||||
fn atoms(&self) -> &'static [Option<fn() -> &'static AtomInfo>] { Self::ATOM_DEFS }
|
||||
fn atoms(&self) -> &'static [Option<&'static dyn AtomDynfo>] { Self::ATOM_DEFS }
|
||||
}
|
||||
|
||||
/// System as defined by author
|
||||
@@ -85,7 +86,7 @@ pub fn downcast_atom<A: AtomCard>(foreign: ForeignAtom) -> Result<TypAtom<A>, Fo
|
||||
match info_ent {
|
||||
None => Err(foreign),
|
||||
Some((_, info)) => {
|
||||
let val = (info.decode)(data);
|
||||
let val = info.decode(data);
|
||||
let value = *val.downcast::<A::Data>().expect("atom decode returned wrong type");
|
||||
Ok(TypAtom { value, data: foreign })
|
||||
},
|
||||
|
||||
@@ -4,38 +4,34 @@ use ahash::HashMap;
|
||||
use dyn_clone::{clone_box, DynClone};
|
||||
use itertools::Itertools;
|
||||
use orchid_api::tree::{
|
||||
MacroRule, Paren, Placeholder, PlaceholderKind, Token, TokenTree, Tree, TreeId, TreeModule,
|
||||
MacroRule, Paren, PlaceholderKind, Token, TokenTree, Tree, TreeId, TreeModule,
|
||||
TreeTicket,
|
||||
};
|
||||
use orchid_base::interner::{intern, Tok};
|
||||
use orchid_base::interner::intern;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::VName;
|
||||
use orchid_base::tokens::OwnedPh;
|
||||
use ordered_float::NotNan;
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::atom::AtomFactory;
|
||||
use crate::conv::ToExpr;
|
||||
use crate::error::{err_or_ref_to_api, ProjectErrorObj};
|
||||
use crate::expr::GenExpr;
|
||||
use crate::system::DynSystem;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GenPh {
|
||||
pub name: Tok<String>,
|
||||
pub kind: PlaceholderKind,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GenTokTree {
|
||||
pub tok: GenTok,
|
||||
pub struct OwnedTokTree {
|
||||
pub tok: OwnedTok,
|
||||
pub range: Range<u32>,
|
||||
}
|
||||
impl GenTokTree {
|
||||
impl OwnedTokTree {
|
||||
pub fn into_api(self, sys: &dyn DynSystem) -> TokenTree {
|
||||
TokenTree { token: self.tok.into_api(sys), range: self.range }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ph(s: &str) -> GenPh {
|
||||
pub fn ph(s: &str) -> OwnedPh {
|
||||
match s.strip_prefix("..") {
|
||||
Some(v_tail) => {
|
||||
let (mid, priority) = match v_tail.split_once(':') {
|
||||
@@ -49,29 +45,30 @@ pub fn ph(s: &str) -> GenPh {
|
||||
if konst::string::starts_with(name, "_") {
|
||||
panic!("Names starting with an underscore indicate a single-name scalar placeholder")
|
||||
}
|
||||
GenPh { name: intern(name), kind: PlaceholderKind::Vector { nonzero, priority } }
|
||||
OwnedPh { name: intern(name), kind: PlaceholderKind::Vector { nonzero, priority } }
|
||||
},
|
||||
None => match konst::string::strip_prefix(s, "$_") {
|
||||
Some(name) => GenPh { name: intern(name), kind: PlaceholderKind::Name },
|
||||
Some(name) => OwnedPh { name: intern(name), kind: PlaceholderKind::Name },
|
||||
None => match konst::string::strip_prefix(s, "$") {
|
||||
None => panic!("Invalid placeholder"),
|
||||
Some(name) => GenPh { name: intern(name), kind: PlaceholderKind::Scalar },
|
||||
Some(name) => OwnedPh { name: intern(name), kind: PlaceholderKind::Scalar },
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum GenTok {
|
||||
Lambda(Vec<GenTokTree>, Vec<GenTokTree>),
|
||||
pub enum OwnedTok {
|
||||
Lambda(Vec<OwnedTokTree>, Vec<OwnedTokTree>),
|
||||
Name(VName),
|
||||
S(Paren, Vec<GenTokTree>),
|
||||
S(Paren, Vec<OwnedTokTree>),
|
||||
Atom(AtomFactory),
|
||||
Slot(TreeTicket),
|
||||
Ph(GenPh),
|
||||
Ph(OwnedPh),
|
||||
Bottom(ProjectErrorObj),
|
||||
}
|
||||
impl GenTok {
|
||||
pub fn at(self, range: Range<u32>) -> GenTokTree { GenTokTree { tok: self, range } }
|
||||
impl OwnedTok {
|
||||
pub fn at(self, range: Range<u32>) -> OwnedTokTree { OwnedTokTree { tok: self, range } }
|
||||
pub fn into_api(self, sys: &dyn DynSystem) -> Token {
|
||||
match self {
|
||||
Self::Lambda(x, body) => Token::Lambda(
|
||||
@@ -79,32 +76,33 @@ impl GenTok {
|
||||
body.into_iter().map(|tt| tt.into_api(sys)).collect_vec(),
|
||||
),
|
||||
Self::Name(n) => Token::Name(n.into_iter().map(|t| t.marker()).collect_vec()),
|
||||
Self::Ph(GenPh { name, kind }) => Token::Ph(Placeholder { name: name.marker(), kind }),
|
||||
Self::Ph(ph) => Token::Ph(ph.to_api()),
|
||||
Self::S(p, body) => Token::S(p, body.into_iter().map(|tt| tt.into_api(sys)).collect_vec()),
|
||||
Self::Slot(tk) => Token::Slot(tk),
|
||||
Self::Atom(at) => Token::Atom(at.build(sys)),
|
||||
Self::Bottom(err) => Token::Bottom(err_or_ref_to_api(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GenMacro {
|
||||
pub pattern: Vec<GenTokTree>,
|
||||
pub pattern: Vec<OwnedTokTree>,
|
||||
pub priority: NotNan<f64>,
|
||||
pub template: Vec<GenTokTree>,
|
||||
pub template: Vec<OwnedTokTree>,
|
||||
}
|
||||
|
||||
pub fn tokv_into_api(
|
||||
tokv: impl IntoIterator<Item = GenTokTree>,
|
||||
tokv: impl IntoIterator<Item = OwnedTokTree>,
|
||||
sys: &dyn DynSystem,
|
||||
) -> Vec<TokenTree> {
|
||||
tokv.into_iter().map(|tok| tok.into_api(sys)).collect_vec()
|
||||
}
|
||||
|
||||
pub fn wrap_tokv(items: Vec<GenTokTree>, range: Range<u32>) -> GenTokTree {
|
||||
pub fn wrap_tokv(items: Vec<OwnedTokTree>, range: Range<u32>) -> OwnedTokTree {
|
||||
match items.len() {
|
||||
1 => items.into_iter().next().unwrap(),
|
||||
_ => GenTok::S(Paren::Round, items).at(range),
|
||||
_ => OwnedTok::S(Paren::Round, items).at(range),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +118,8 @@ impl GenTree {
|
||||
}
|
||||
pub fn rule(
|
||||
prio: f64,
|
||||
pat: impl IntoIterator<Item = GenTokTree>,
|
||||
tpl: impl IntoIterator<Item = GenTokTree>,
|
||||
pat: impl IntoIterator<Item = OwnedTokTree>,
|
||||
tpl: impl IntoIterator<Item = OwnedTokTree>,
|
||||
) -> Self {
|
||||
GenItem::Rule(GenMacro {
|
||||
pattern: pat.into_iter().collect(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::io::Write as _;
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicU16, AtomicU32, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::{Arc, Mutex, RwLock, Weak};
|
||||
@@ -12,16 +13,16 @@ use orchid_api::atom::{Atom, AtomDrop, AtomSame, CallRef, FinalCall, Fwd, Fwded}
|
||||
use orchid_api::error::{ErrNotif, ProjErrOrRef, ProjResult, ReportError};
|
||||
use orchid_api::expr::{Acquire, Expr, ExprNotif, ExprTicket, Release, Relocate};
|
||||
use orchid_api::interner::IntReq;
|
||||
use orchid_api::parser::CharFilter;
|
||||
use orchid_api::parser::{CharFilter, Lexed, SubLexed};
|
||||
use orchid_api::proto::{
|
||||
ExtHostNotif, ExtHostReq, ExtensionHeader, HostExtNotif, HostExtReq, HostHeader, HostMsgSet
|
||||
ExtHostNotif, ExtHostReq, ExtensionHeader, HostExtNotif, HostHeader, HostMsgSet,
|
||||
};
|
||||
use orchid_api::system::{NewSystem, SysDeclId, SysId, SystemDecl, SystemDrop};
|
||||
use orchid_api::tree::{GetConstTree, Tree, TreeId};
|
||||
use orchid_api_traits::{Coding, Decode, Encode, Request};
|
||||
use orchid_api_traits::{Coding, Decode, Encode};
|
||||
use orchid_base::char_filter::char_filter_match;
|
||||
use orchid_base::clone;
|
||||
use orchid_base::interner::{deintern, intern};
|
||||
use orchid_base::interner::{deintern, intern, Tok};
|
||||
use orchid_base::reqnot::{ReqNot, Requester as _};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
@@ -230,24 +231,28 @@ impl System {
|
||||
pub fn const_tree(&self) -> Tree {
|
||||
self.0.ext.0.reqnot.request(GetConstTree(self.0.id, self.0.const_root_id))
|
||||
}
|
||||
pub fn request<R: Coding>(&self, req: impl Request<Response = ProjResult<R>> + Into<HostExtReq>) -> ProjResult<R> {
|
||||
pub fn catch_err<R: Coding>(&self, cb: impl FnOnce() -> ProjResult<R>) -> ProjResult<R> {
|
||||
let mut errors = Vec::new();
|
||||
if let Ok(err) = self.0.err_rec.lock().unwrap().try_recv() {
|
||||
eprintln!("Errors left in queue");
|
||||
errors.push(err);
|
||||
}
|
||||
let value = self.0.ext.0.reqnot.request(req).inspect_err(|e| errors.extend(e.iter().cloned()));
|
||||
let value = cb().inspect_err(|e| errors.extend(e.iter().cloned()));
|
||||
while let Ok(err) = self.0.err_rec.lock().unwrap().try_recv() {
|
||||
errors.push(err);
|
||||
}
|
||||
if !errors.is_empty() {
|
||||
Err(errors)
|
||||
} else {
|
||||
value
|
||||
}
|
||||
if !errors.is_empty() { Err(errors) } else { value }
|
||||
}
|
||||
pub fn has_lexer(&self) -> bool { !self.0.lex_filter.0.is_empty() }
|
||||
pub fn can_lex(&self, c: char) -> bool { char_filter_match(&self.0.lex_filter, c) }
|
||||
pub fn lex(
|
||||
&self,
|
||||
source: Tok<String>,
|
||||
pos: usize,
|
||||
r: impl FnMut(usize) -> ProjResult<SubLexed>,
|
||||
) -> ProjResult<Lexed> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for System {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@@ -263,3 +268,7 @@ impl fmt::Debug for System {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Deref for System {
|
||||
type Target = SystemInstData;
|
||||
fn deref(&self) -> &Self::Target { self.0.as_ref() }
|
||||
}
|
||||
|
||||
118
orchid-host/src/lex.rs
Normal file
118
orchid-host/src/lex.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
use orchid_api::tree::Paren;
|
||||
use orchid_base::intern;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::number::parse_num;
|
||||
|
||||
use crate::extension::System;
|
||||
use crate::results::{mk_err, num_to_err, OwnedResult};
|
||||
use crate::tree::{OwnedTok, OwnedTokTree};
|
||||
|
||||
pub struct LexCtx<'a> {
|
||||
pub systems: &'a [System],
|
||||
pub source: Tok<String>,
|
||||
pub src: &'a str,
|
||||
}
|
||||
impl<'a> LexCtx<'a> {
|
||||
pub fn get_pos(&self) -> u32 { self.source.len() as u32 - self.src.len() as u32 }
|
||||
pub fn strip_prefix(&mut self, tgt: &str) -> bool {
|
||||
if let Some(src) = self.src.strip_prefix(tgt) {
|
||||
self.src = src;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
pub fn strip_char(&mut self, tgt: char) -> bool {
|
||||
if let Some(src) = self.src.strip_prefix(tgt) {
|
||||
self.src = src;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
pub fn trim(&mut self, filter: impl Fn(char) -> bool) {
|
||||
self.src = self.src.trim_start_matches(filter);
|
||||
}
|
||||
pub fn trim_ws(&mut self, br: bool) {
|
||||
self.trim(|c| c.is_whitespace() && br || !"\r\n".contains(c))
|
||||
}
|
||||
pub fn get_start_matches(&mut self, filter: impl Fn(char) -> bool) -> &'a str {
|
||||
let rest = self.src.trim_start_matches(filter);
|
||||
let matches = &self.src[..self.src.len() - rest.len()];
|
||||
self.src = rest;
|
||||
matches
|
||||
}
|
||||
}
|
||||
|
||||
const PARENS: &[(char, char, Paren)] =
|
||||
&[('(', ')', Paren::Round), ('[', ']', Paren::Square), ('{', '}', Paren::Curly)];
|
||||
|
||||
pub fn lex_tok(ctx: &mut LexCtx, br: bool) -> OwnedResult<OwnedTokTree> {
|
||||
assert!(
|
||||
!ctx.src.is_empty() && !ctx.src.starts_with(char::is_whitespace),
|
||||
"Lexing empty string or whitespace to token! Invocations of lex_tok should check for empty string"
|
||||
);
|
||||
for (open, close, paren) in PARENS {
|
||||
let paren_pos = ctx.get_pos();
|
||||
if ctx.strip_char(*open) {
|
||||
let mut body = Vec::new();
|
||||
return loop {
|
||||
ctx.trim_ws(true);
|
||||
if ctx.strip_char(*close) {
|
||||
break Ok(OwnedTokTree {
|
||||
tok: OwnedTok::S(paren.clone(), body),
|
||||
range: paren_pos..ctx.get_pos(),
|
||||
});
|
||||
} else if ctx.src.is_empty() {
|
||||
return Err(vec![mk_err(
|
||||
intern!(str: "unclosed paren"),
|
||||
format!("this {open} has no matching {close}"),
|
||||
[Pos::Range(paren_pos..paren_pos + 1).into()],
|
||||
)]);
|
||||
}
|
||||
body.push(lex_tok(ctx, true)?);
|
||||
};
|
||||
}
|
||||
}
|
||||
if ctx.strip_char('\\') {
|
||||
let bs_pos = ctx.get_pos() - 1;
|
||||
let mut arg = Vec::new();
|
||||
loop {
|
||||
ctx.trim_ws(true);
|
||||
if ctx.strip_char('.') {
|
||||
break;
|
||||
} else if ctx.src.is_empty() {
|
||||
return Err(vec![mk_err(
|
||||
intern!(str: "Unclosed lambda"),
|
||||
"Lambdae started with \\ should separate arguments from body with .",
|
||||
[Pos::Range(bs_pos..bs_pos + 1).into()],
|
||||
)]);
|
||||
}
|
||||
arg.push(lex_tok(ctx, true)?);
|
||||
}
|
||||
let mut body = Vec::new();
|
||||
return loop {
|
||||
ctx.trim_ws(br);
|
||||
let pos_before_end = ctx.get_pos();
|
||||
if !br && ctx.strip_char('\n')
|
||||
|| PARENS.iter().any(|(_, e, _)| ctx.strip_char(*e))
|
||||
|| ctx.src.is_empty()
|
||||
{
|
||||
break Ok(OwnedTokTree { tok: OwnedTok::Lambda(arg, body), range: bs_pos..pos_before_end });
|
||||
}
|
||||
body.push(lex_tok(ctx, br)?);
|
||||
};
|
||||
}
|
||||
if ctx.src.starts_with(char::is_numeric) {
|
||||
let num_pos = ctx.get_pos();
|
||||
let num_str = ctx.get_start_matches(|c| c.is_alphanumeric() || "._".contains(c));
|
||||
return Ok(OwnedTokTree {
|
||||
range: num_pos..ctx.get_pos(),
|
||||
tok: match parse_num(num_str) {
|
||||
Err(e) => OwnedTok::Bottom(num_to_err(e, num_pos)),
|
||||
Ok(v) => todo!(),
|
||||
},
|
||||
});
|
||||
}
|
||||
for sys in ctx.systems {}
|
||||
todo!()
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
pub mod child;
|
||||
pub mod expr;
|
||||
pub mod extension;
|
||||
pub mod lex;
|
||||
pub mod results;
|
||||
pub mod tree;
|
||||
|
||||
36
orchid-host/src/results.rs
Normal file
36
orchid-host/src/results.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use orchid_base::error::{ErrorPosition, OwnedError};
|
||||
use orchid_base::intern;
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::number::{NumError, NumErrorKind};
|
||||
|
||||
pub type OwnedResult<T> = Result<T, Vec<OwnedError>>;
|
||||
|
||||
pub fn mk_err(
|
||||
description: Tok<String>,
|
||||
message: impl AsRef<str>,
|
||||
posv: impl IntoIterator<Item = ErrorPosition>,
|
||||
) -> OwnedError {
|
||||
OwnedError {
|
||||
description,
|
||||
message: Arc::new(message.as_ref().to_string()),
|
||||
positions: posv.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_to_err(NumError { kind, range }: NumError, offset: u32) -> OwnedError {
|
||||
OwnedError {
|
||||
description: intern!(str: "Failed to parse number"),
|
||||
message: Arc::new(
|
||||
match kind {
|
||||
NumErrorKind::NaN => "NaN emerged during parsing",
|
||||
NumErrorKind::InvalidDigit => "non-digit character encountered",
|
||||
NumErrorKind::Overflow => "The number being described is too large or too accurate",
|
||||
}
|
||||
.to_string(),
|
||||
),
|
||||
positions: vec![Pos::Range(offset + range.start as u32..offset + range.end as u32).into()],
|
||||
}
|
||||
}
|
||||
24
orchid-host/src/tree.rs
Normal file
24
orchid-host/src/tree.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use orchid_api::tree::Paren;
|
||||
use orchid_base::error::OwnedError;
|
||||
use orchid_base::name::VName;
|
||||
use orchid_base::tokens::OwnedPh;
|
||||
|
||||
use crate::extension::AtomHand;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OwnedTokTree {
|
||||
pub tok: OwnedTok,
|
||||
pub range: Range<u32>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum OwnedTok {
|
||||
Lambda(Vec<OwnedTokTree>, Vec<OwnedTokTree>),
|
||||
Name(VName),
|
||||
S(Paren, Vec<OwnedTokTree>),
|
||||
Atom(AtomHand),
|
||||
Ph(OwnedPh),
|
||||
Bottom(OwnedError),
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use orchid_extension::atom::AtomicFeatures;
|
||||
use orchid_extension::atom::{AtomDynfo, AtomicFeatures};
|
||||
use orchid_extension::fs::DeclFs;
|
||||
use orchid_extension::fun::Fun;
|
||||
use orchid_extension::system::{System, SystemCard};
|
||||
@@ -22,16 +22,25 @@ impl SystemCtor for StdSystem {
|
||||
}
|
||||
impl SystemCard for StdSystem {
|
||||
type Ctor = Self;
|
||||
const ATOM_DEFS: &'static [Option<fn() -> &'static orchid_extension::atom::AtomInfo>] = &[
|
||||
Some(StringAtom::info)
|
||||
];
|
||||
const ATOM_DEFS: &'static [Option<&'static dyn AtomDynfo>] = &[Some(StringAtom::INFO)];
|
||||
}
|
||||
impl System for StdSystem {
|
||||
fn lexers() -> Vec<orchid_extension::lexer::LexerObj> { vec![&StringLexer] }
|
||||
fn vfs() -> DeclFs { DeclFs::Mod(&[]) }
|
||||
fn env() -> GenTree {
|
||||
GenTree::module([("std", GenTree::module([("string", GenTree::module([
|
||||
("concat", GenTree::cnst(Fun::new(|left: OrcString| Fun::new(move |right: OrcString| StringAtom::new(Arc::new(left.get_string().to_string() + &right.get_string()))))))
|
||||
]))]))])
|
||||
GenTree::module([(
|
||||
"std",
|
||||
GenTree::module([(
|
||||
"string",
|
||||
GenTree::module([(
|
||||
"concat",
|
||||
GenTree::cnst(Fun::new(|left: OrcString| {
|
||||
Fun::new(move |right: OrcString| {
|
||||
StringAtom::new(Arc::new(left.get_string().to_string() + &right.get_string()))
|
||||
})
|
||||
})),
|
||||
)]),
|
||||
)]),
|
||||
)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ use orchid_base::interner::{deintern, Tok};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_extension::atom::{Atomic, TypAtom};
|
||||
use orchid_extension::atom_owned::{OwnedAtom, OwnedVariant};
|
||||
use orchid_extension::conv::TryFromExpr;
|
||||
use orchid_extension::error::{ProjectError, ProjectResult};
|
||||
use orchid_extension::expr::{ExprHandle, OwnedExpr};
|
||||
use orchid_extension::system::{downcast_atom, SysCtx};
|
||||
use orchid_extension::conv::TryFromExpr;
|
||||
|
||||
pub static STR_REPO: IdStore<Arc<String>> = IdStore::new();
|
||||
|
||||
@@ -59,10 +59,12 @@ impl StringAtom {
|
||||
fn get_value(&self) -> Arc<String> { self.try_local_value().expect("no string found for ID") }
|
||||
}
|
||||
impl OwnedAtom for StringAtom {
|
||||
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(match self {
|
||||
Self::Int(tok) => StringVal::Int(tok.marker()),
|
||||
Self::Val(id) => StringVal::Val(*id),
|
||||
}) }
|
||||
fn val(&self) -> Cow<'_, Self::Data> {
|
||||
Cow::Owned(match self {
|
||||
Self::Int(tok) => StringVal::Int(tok.marker()),
|
||||
Self::Val(id) => StringVal::Val(*id),
|
||||
})
|
||||
}
|
||||
fn same(&self, _ctx: SysCtx, other: &Self) -> bool { self.get_value() == other.get_value() }
|
||||
fn handle_req(
|
||||
&self,
|
||||
@@ -90,9 +92,7 @@ impl OrcString {
|
||||
pub struct NotString(Pos);
|
||||
impl ProjectError for NotString {
|
||||
const DESCRIPTION: &'static str = "A string was expected";
|
||||
fn one_position(&self) -> Pos {
|
||||
self.0.clone()
|
||||
}
|
||||
fn one_position(&self) -> Pos { self.0.clone() }
|
||||
}
|
||||
impl TryFromExpr for OrcString {
|
||||
fn try_from_expr(expr: ExprHandle) -> ProjectResult<OrcString> {
|
||||
@@ -101,4 +101,4 @@ impl TryFromExpr for OrcString {
|
||||
.map_err(|p| NotString(p).pack())
|
||||
.map(OrcString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use orchid_base::vname;
|
||||
use orchid_extension::atom::AtomicFeatures;
|
||||
use orchid_extension::error::{ErrorSansOrigin, ProjectErrorObj, ProjectResult};
|
||||
use orchid_extension::lexer::{LexContext, Lexer};
|
||||
use orchid_extension::tree::{wrap_tokv, GenTok, GenTokTree};
|
||||
use orchid_extension::tree::{wrap_tokv, OwnedTok, OwnedTokTree};
|
||||
|
||||
use super::str_atom::StringAtom;
|
||||
|
||||
@@ -119,15 +119,15 @@ impl Lexer for StringLexer {
|
||||
fn lex<'a>(
|
||||
full_string: &'a str,
|
||||
ctx: &'a LexContext<'a>,
|
||||
) -> Option<ProjectResult<(&'a str, GenTokTree)>> {
|
||||
) -> Option<ProjectResult<(&'a str, OwnedTokTree)>> {
|
||||
full_string.strip_prefix('"').map(|mut tail| {
|
||||
let mut parts = vec![];
|
||||
let mut cur = String::new();
|
||||
let commit_str = |str: &mut String, tail: &str, parts: &mut Vec<GenTokTree>| {
|
||||
let commit_str = |str: &mut String, tail: &str, parts: &mut Vec<OwnedTokTree>| {
|
||||
let str_val = parse_string(str)
|
||||
.inspect_err(|e| ctx.report(e.clone().into_proj(ctx.pos(tail) - str.len() as u32)))
|
||||
.unwrap_or_default();
|
||||
let tok = GenTok::Atom(StringAtom::new_int(intern(&str_val)).factory());
|
||||
let tok = OwnedTok::Atom(StringAtom::new_int(intern(&str_val)).factory());
|
||||
parts.push(tok.at(ctx.tok_ran(str.len() as u32, tail)));
|
||||
*str = String::new();
|
||||
};
|
||||
@@ -137,8 +137,8 @@ impl Lexer for StringLexer {
|
||||
return Ok((rest, wrap_tokv(parts, ctx.pos(full_string)..ctx.pos(rest))));
|
||||
} else if let Some(rest) = tail.strip_prefix('$') {
|
||||
commit_str(&mut cur, tail, &mut parts);
|
||||
parts.push(GenTok::Name(VName::literal("++")).at(ctx.tok_ran(1, rest)));
|
||||
parts.push(GenTok::Name(vname!(std::string::convert)).at(ctx.tok_ran(1, rest)));
|
||||
parts.push(OwnedTok::Name(VName::literal("++")).at(ctx.tok_ran(1, rest)));
|
||||
parts.push(OwnedTok::Name(vname!(std::string::convert)).at(ctx.tok_ran(1, rest)));
|
||||
match ctx.recurse(rest) {
|
||||
Ok((new_tail, tree)) => {
|
||||
tail = new_tail;
|
||||
|
||||
@@ -17,35 +17,6 @@ use crate::foreign::atom::AtomGenerator;
|
||||
use crate::foreign::inert::Inert;
|
||||
use crate::libs::std::number::Numeric;
|
||||
|
||||
/// Rasons why [parse_num] might fail. See [NumError].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum NumErrorKind {
|
||||
/// The literal describes [f64::NAN]
|
||||
NaN,
|
||||
/// Some integer appearing in the literal overflows [usize]
|
||||
Overflow,
|
||||
/// A character that isn't a digit in the given base was found
|
||||
InvalidDigit,
|
||||
}
|
||||
impl NumErrorKind {
|
||||
fn from_int(kind: &IntErrorKind) -> Self {
|
||||
match kind {
|
||||
IntErrorKind::InvalidDigit => Self::InvalidDigit,
|
||||
IntErrorKind::NegOverflow | IntErrorKind::PosOverflow => Self::Overflow,
|
||||
_ => panic!("Impossible error condition"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error produced by [parse_num]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct NumError {
|
||||
/// Location
|
||||
pub range: Range<usize>,
|
||||
/// Reason
|
||||
pub kind: NumErrorKind,
|
||||
}
|
||||
|
||||
impl NumError {
|
||||
/// Convert into [ProjectErrorObj]
|
||||
pub fn into_proj(
|
||||
@@ -64,73 +35,7 @@ impl NumError {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a numbre literal out of text
|
||||
pub fn parse_num(string: &str) -> Result<Numeric, NumError> {
|
||||
let overflow_err = NumError { range: 0..string.len(), kind: NumErrorKind::Overflow };
|
||||
let (radix, noprefix, pos) = (string.strip_prefix("0x").map(|s| (16u8, s, 2)))
|
||||
.or_else(|| string.strip_prefix("0b").map(|s| (2u8, s, 2)))
|
||||
.or_else(|| string.strip_prefix("0o").map(|s| (8u8, s, 2)))
|
||||
.unwrap_or((10u8, string, 0));
|
||||
// identity
|
||||
let (base, exponent) = match noprefix.split_once('p') {
|
||||
Some((b, e)) => {
|
||||
let (s, d, len) = e.strip_prefix('-').map_or((1, e, 0), |ue| (-1, ue, 1));
|
||||
(b, s * int_parse(d, 10, pos + b.len() + 1 + len)? as i32)
|
||||
},
|
||||
None => (noprefix, 0),
|
||||
};
|
||||
match base.split_once('.') {
|
||||
None => {
|
||||
let base_usize = int_parse(base, radix, pos)?;
|
||||
if let Ok(pos_exp) = u32::try_from(exponent) {
|
||||
if let Some(radical) = usize::from(radix).checked_pow(pos_exp) {
|
||||
let number = base_usize.checked_mul(radical).ok_or(overflow_err)?;
|
||||
return Ok(Numeric::Uint(number));
|
||||
}
|
||||
}
|
||||
let f = (base_usize as f64) * (radix as f64).powi(exponent);
|
||||
let err = NumError { range: 0..string.len(), kind: NumErrorKind::NaN };
|
||||
Ok(Numeric::Float(NotNan::new(f).map_err(|_| err)?))
|
||||
},
|
||||
Some((whole, part)) => {
|
||||
let whole_n = int_parse(whole, radix, pos)? as f64;
|
||||
let part_n = int_parse(part, radix, pos + whole.len() + 1)? as f64;
|
||||
let real_val = whole_n + (part_n / (radix as f64).powi(part.len() as i32));
|
||||
let f = real_val * (radix as f64).powi(exponent);
|
||||
Ok(Numeric::Float(NotNan::new(f).expect("None of the inputs are NaN")))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn int_parse(s: &str, radix: u8, start: usize) -> Result<usize, NumError> {
|
||||
let s = s.chars().filter(|c| *c != '_').collect::<String>();
|
||||
let range = start..(start + s.len());
|
||||
usize::from_str_radix(&s, radix as u32)
|
||||
.map_err(|e| NumError { range, kind: NumErrorKind::from_int(e.kind()) })
|
||||
}
|
||||
|
||||
/// Filter for characters that can appear in numbers
|
||||
pub fn numchar(c: char) -> bool { c.is_alphanumeric() | "._-".contains(c) }
|
||||
/// Filter for characters that can start numbers
|
||||
pub fn numstart(c: char) -> bool { c.is_ascii_digit() }
|
||||
|
||||
/// Print a number as a base-16 floating point literal
|
||||
#[must_use]
|
||||
pub fn print_nat16(num: NotNan<f64>) -> String {
|
||||
if *num == 0.0 {
|
||||
return "0x0".to_string();
|
||||
} else if num.is_infinite() {
|
||||
return match num.is_sign_positive() {
|
||||
true => "Infinity".to_string(),
|
||||
false => "-Infinity".to_string(),
|
||||
};
|
||||
} else if num.is_nan() {
|
||||
return "NaN".to_string();
|
||||
}
|
||||
let exp = num.log(16.0).floor();
|
||||
let man = *num / 16_f64.powf(exp);
|
||||
format!("0x{man}p{exp:.0}")
|
||||
}
|
||||
|
||||
/// [LexerPlugin] for a number literal
|
||||
#[derive(Clone)]
|
||||
@@ -150,30 +55,3 @@ impl LexerPlugin for NumericLexer {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::libs::std::number::Numeric;
|
||||
use crate::parse::numeric::parse_num;
|
||||
|
||||
#[test]
|
||||
fn just_ints() {
|
||||
let test = |s, n| assert_eq!(parse_num(s), Ok(Numeric::Uint(n)));
|
||||
test("12345", 12345);
|
||||
test("0xcafebabe", 0xcafebabe);
|
||||
test("0o751", 0o751);
|
||||
test("0b111000111", 0b111000111);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimals() {
|
||||
let test = |s, n| assert_eq!(parse_num(s).map(|n| n.as_f64()), Ok(n));
|
||||
test("3.1417", 3.1417);
|
||||
test("3.1417", 3_f64 + 1417_f64 / 10000_f64);
|
||||
test("0xf.cafe", 0xf as f64 + 0xcafe as f64 / 0x10000 as f64);
|
||||
test("34p3", 34000f64);
|
||||
test("0x2p3", (0x2 * 0x1000) as f64);
|
||||
test("1.5p3", 1500f64);
|
||||
test("0x2.5p3", (0x25 * 0x100) as f64);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user