diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index b8239db..0000000 --- a/.cargo/config +++ /dev/null @@ -1,3 +0,0 @@ -#[build] -# disabled to allow dynamic library loading -#target = "x86_64-unknown-linux-musl" diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d01ad2f..ea48754 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -16,7 +16,10 @@ jobs: with: toolchain: stable targets: x86_64-unknown-linux-gnu + - run: git checkout -B pr_check - run: rustup component add clippy + - run: cargo install cargo-release - run: cargo test --verbose -- --nocapture - run: cargo clippy --all-targets --all-features -- -D warnings - - run: cargo publish --dry-run + - run: cargo release --no-publish --no-tag --allow-branch pr_check --no-push --dependent-version upgrade minor + #- run: cargo publish --dry-run diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 97e7079..c547f89 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,6 +41,7 @@ on: push: tags: - '**[0-9]+.[0-9]+.[0-9]+*' + pull_request: jobs: # Run 'cargo dist plan' (or host) to determine what tasks we need to do diff --git a/Cargo.lock b/Cargo.lock index cc85c34..02a5926 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,36 +6,69 @@ version = 3 name = "adana" version = "0.16.4" dependencies = [ + "adana-cache-command", + "adana-db", + "adana-script", "adana-script-core", "anyhow", - "arboard", - "bincode", "ctrlc", "dirs", "env_logger", "log", - "nom", "nu-ansi-term", - "regex", "rustyline", "rustyline-derive", +] + +[[package]] +name = "adana-cache-command" +version = "0.16.4" +dependencies = [ + "adana-db", + "adana-script", + "adana-script-core", + "anyhow", + "arboard", + "bincode", + "dirs", + "log", + "nom", + "nu-ansi-term", + "regex", "serde", "serde_json", + "strum", +] + +[[package]] +name = "adana-db" +version = "0.16.4" +dependencies = [ + "anyhow", + "bincode", + "dirs", + "log", + "serde", +] + +[[package]] +name = "adana-script" +version = "0.16.4" +dependencies = [ + "adana-script-core", + "anyhow", + "nom", "serial_test", "slab_tree", - "strum", ] [[package]] name = "adana-script-core" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8a7bb732df5f039dcadd732decc5d1f77c4ab72cc595a1b7d359ea9bfe98ba" +version = "0.16.4" dependencies = [ "anyhow", "libloading", "serde", - "serde_derive", "strum", ] @@ -102,9 +135,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block" @@ -114,9 +147,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" [[package]] name = "byteorder" @@ -158,9 +191,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -168,9 +201,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" @@ -187,9 +220,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -276,12 +309,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -313,9 +346,9 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -347,9 +380,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -362,9 +395,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -372,15 +405,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -389,27 +422,27 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -434,9 +467,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -445,9 +478,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" @@ -457,23 +490,22 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "image" -version = "0.24.7" +version = "0.24.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" dependencies = [ "bytemuck", "byteorder", "color_quant", - "num-rational", "num-traits", "png", "tiff", @@ -481,15 +513,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jpeg-decoder" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "lazy_static" @@ -499,9 +531,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -519,16 +551,16 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall", ] [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -557,9 +589,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -578,9 +610,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -613,7 +645,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", "libc", ] @@ -637,27 +669,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -698,9 +709,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "option-ext" @@ -745,9 +756,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "png" -version = "0.17.10" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -758,9 +769,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -835,15 +846,15 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -858,7 +869,7 @@ version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", "clipboard-win 5.0.0", "fd-lock", @@ -887,9 +898,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "scopeguard" @@ -979,9 +990,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "snowflake" @@ -1030,18 +1041,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", @@ -1050,9 +1061,9 @@ dependencies = [ [[package]] name = "tiff" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ "flate2", "jpeg-decoder", @@ -1091,9 +1102,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" diff --git a/Cargo.toml b/Cargo.toml index 10e7d3d..76f5afd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,33 +1,32 @@ +[workspace] +members = [ + "adana-cache-command", + "adana-db", + "adana-script", + "adana-script-core", + "adana-shell", +] +resolver = "2" -[package] -name = "adana" -rust-version = "1.75" - +[workspace.package] version = "0.16.4" -edition = "2021" authors = ["Nordine Bittich"] -license = "MIT" description = "namespaces aliases for command lines & basic scripting language" homepage = "https://github.com/nbittich/adana" repository = "https://github.com/nbittich/adana" readme = "README.md" -exclude = [ - "vscode/", - "dist/", - ".vscode", - ".history", - ".git", - ".github", - "static_binaries/", - "dynamic_lib/", -] +rust-version = "1.75" +edition = "2021" +license = "MIT" +exclude = ["vscode/", "dist/", ".vscode", ".history", ".git", ".github"] -[dependencies] +[workspace.dependencies] anyhow = "1.0.79" bincode = "1.3.3" -dirs = "5.0.1" # todo maybe replace by the home crate +dirs = "5.0.1" # todo maybe replace by the home crate log = "0.4.20" nom = "7.1.3" +libloading = "0.8.1" nu-ansi-term = "0.50.0" rustyline = "13.0.0" rustyline-derive = "0.10.0" @@ -36,36 +35,17 @@ serde_json = "1.0.113" slab_tree = "0.3.2" strum = { version = "0.26.1", features = ["derive"] } ctrlc = "3.4.2" - -#adana-script-core = { git = "https://github.com/nbittich/adana-script-core.git", branch = "feature/bitwise-and-new-ints" } -adana-script-core = "0.16.1" +env_logger = { version = "0.11.1", default-features = false } arboard = "3.3.0" - -[dependencies.env_logger] -default-features = false -version = "0.11.1" -[dependencies.regex] -version = "1.10.3" -default-features = false -# regex currently requires the standard library, you must re-enable it. -features = ["std"] - -[profile.release] -opt-level = 'z' # Optimize for size. -lto = true # Link Time Optimization (LTO) -codegen-units = 1 # Set this to 1 to allow for maximum size reduction optimizations: -panic = 'abort' # removes the need for this extra unwinding code. -strip = "symbols" - -# The profile that 'cargo dist' will build with -[profile.dist] -inherits = "release" - -[dev-dependencies] -# some test must be run sequentially. -# if library is broken, alternative is: cargo test -- --test-threads 1 +regex = { version = "1.10.3", default-features = false, features = ["std"] } serial_test = "3.0.0" +# workspace specific libs +adana-script-core = { version = "0.16.4", path = "./adana-script-core" } +adana-script = { version = "0.16.4", path = "./adana-script" } +adana-db = { version = "0.16.4", path = "./adana-db" } +adana-cache-command = { version = "0.16.4", path = "./adana-cache-command" } + # Config for 'cargo dist' [workspace.metadata.dist] # The preferred cargo-dist version to use in CI (Cargo.toml SemVer syntax) @@ -77,4 +57,16 @@ installers = ["shell"] # Target platforms to build apps for (Rust target-triple syntax) targets = ["x86_64-unknown-linux-gnu"] # Publish jobs to run in CI -pr-run-mode = "skip" +pr-run-mode = "plan" + +[profile.release] +opt-level = 'z' # Optimize for size. +lto = true # Link Time Optimization (LTO) +codegen-units = 1 # Set this to 1 to allow for maximum size reduction optimizations: +panic = 'abort' # removes the need for this extra unwinding code. +strip = "symbols" + +# The profile that 'cargo dist' will build with +[profile.dist] +inherits = "release" +lto = "thin" diff --git a/adana-cache-command/Cargo.toml b/adana-cache-command/Cargo.toml new file mode 100644 index 0000000..b6362c3 --- /dev/null +++ b/adana-cache-command/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "adana-cache-command" +version.workspace = true +authors.workspace = true +description.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +adana-db.workspace = true +strum.workspace = true +nom.workspace = true +regex.workspace = true +anyhow.workspace = true +adana-script.workspace = true +adana-script-core.workspace = true +bincode.workspace = true +nu-ansi-term.workspace = true +arboard.workspace = true +dirs.workspace = true +serde_json.workspace = true +log.workspace = true +serde.workspace = true diff --git a/src/cache_command/cache.rs b/adana-cache-command/src/cache.rs similarity index 93% rename from src/cache_command/cache.rs rename to adana-cache-command/src/cache.rs index 10832c5..7cfa6a3 100644 --- a/src/cache_command/cache.rs +++ b/adana-cache-command/src/cache.rs @@ -1,7 +1,7 @@ -use std::path::Path; +use std::{collections::BTreeMap, fs::File, io::BufReader, path::Path}; -use crate::db::{Batch, DbOp, Op, Tree, DEFAULT_TREE, SCRIPT_CACHE_KEY}; -use crate::prelude::*; +use adana_db::{Batch, DbOp, Op, Tree, DEFAULT_TREE, SCRIPT_CACHE_KEY}; +use serde::{Deserialize, Serialize}; const DEFAULT_CACHE_KEY: &str = "$___DEF_CACHE_KEY_LOC___$"; @@ -58,7 +58,7 @@ pub fn insert_value( check_cache_name(namespace)?; } db.open_tree(namespace)?; - let mut batch = crate::db::Batch::default(); + let mut batch = Batch::default(); let keys = db.keys(); let aliases: Vec<&str> = aliases @@ -204,7 +204,10 @@ fn check_cache_name(cache_name: &str) -> Option<()> { if cache_name != DEFAULT_TREE && cache_name != SCRIPT_CACHE_KEY { Some(()) } else { - println!("{} you cannot do this.", colors::Red.paint("Warning!")); + println!( + "{} you cannot do this.", + nu_ansi_term::Color::Red.paint("Warning!") + ); None } } diff --git a/src/cache_command/mod.rs b/adana-cache-command/src/lib.rs similarity index 99% rename from src/cache_command/mod.rs rename to adana-cache-command/src/lib.rs index 8111498..2114bc3 100644 --- a/src/cache_command/mod.rs +++ b/adana-cache-command/src/lib.rs @@ -1,7 +1,9 @@ mod cache; mod os_command; mod parser; +mod prelude; mod process; +mod reserved_keywords; pub use cache::get_default_cache; pub use process::process_command; use strum::EnumCount; diff --git a/src/cache_command/os_command.rs b/adana-cache-command/src/os_command.rs similarity index 97% rename from src/cache_command/os_command.rs rename to adana-cache-command/src/os_command.rs index 5643a01..b8c13e4 100644 --- a/src/cache_command/os_command.rs +++ b/adana-cache-command/src/os_command.rs @@ -1,6 +1,10 @@ -use std::ffi::OsString; +use log::debug; use crate::prelude::*; +use std::{ + ffi::OsString, + process::{Command, Stdio}, +}; fn extract_args(s: &str) -> Res> { preceded( multispace0, diff --git a/src/cache_command/parser.rs b/adana-cache-command/src/parser.rs similarity index 99% rename from src/cache_command/parser.rs rename to adana-cache-command/src/parser.rs index 92ccfda..e49649d 100644 --- a/src/cache_command/parser.rs +++ b/adana-cache-command/src/parser.rs @@ -1,7 +1,7 @@ -use crate::prelude::*; - use super::{constants::*, CacheCommand, ChangeDirectoryType}; +use crate::prelude::*; +pub type Res<'a, T> = IResult<&'a str, T>; fn add_command(command: &str) -> Res { map( pair( diff --git a/adana-cache-command/src/prelude.rs b/adana-cache-command/src/prelude.rs new file mode 100644 index 0000000..4595bdc --- /dev/null +++ b/adana-cache-command/src/prelude.rs @@ -0,0 +1,13 @@ +pub use nom::{ + branch::alt, + bytes::complete::{ + tag, tag_no_case, take_till1, take_until, take_until1, take_while, + take_while1, + }, + character::complete::{multispace0, multispace1, space1}, + combinator::{cut, map, opt, rest, verify}, + multi::{many0, separated_list0}, + sequence::{delimited, pair, preceded, separated_pair, terminated}, + IResult, Parser, +}; +pub type Res<'a, T> = IResult<&'a str, T>; diff --git a/src/cache_command/process.rs b/adana-cache-command/src/process.rs similarity index 98% rename from src/cache_command/process.rs rename to adana-cache-command/src/process.rs index eef8cd9..c92e196 100644 --- a/src/cache_command/process.rs +++ b/adana-cache-command/src/process.rs @@ -1,17 +1,14 @@ use std::{collections::BTreeMap, path::PathBuf}; +use crate::reserved_keywords::{check_reserved_keyword, CACHE_COMMAND_DOC}; +use adana_db::{DbOp, SCRIPT_CACHE_KEY}; +use adana_script::print_ast; use adana_script_core::primitive::RefPrimitive; use anyhow::Context; use nom::error::ErrorKind; +use nu_ansi_term::Color::*; use regex::Regex; -use crate::{ - adana_script::print_ast, - db::{DbOp, SCRIPT_CACHE_KEY}, - prelude::colors::*, - reserved_keywords::{check_reserved_keyword, CACHE_COMMAND_DOC}, -}; - use super::{ cache::*, clear_terminal, os_command::exec_command, parser::parse_command, CacheCommand, diff --git a/adana-cache-command/src/reserved_keywords.rs b/adana-cache-command/src/reserved_keywords.rs new file mode 100644 index 0000000..bc2b4d6 --- /dev/null +++ b/adana-cache-command/src/reserved_keywords.rs @@ -0,0 +1,12 @@ +use crate::CacheCommand; + +use adana_script_core::FORBIDDEN_VARIABLE_NAME as SCRIPT_RESERVED_KEYWORDS; +pub const CACHE_COMMAND_DOC: &[(&[&str], &str)] = CacheCommand::doc(); + +pub fn check_reserved_keyword(aliases: &[&str]) -> bool { + CACHE_COMMAND_DOC + .iter() + .flat_map(|c| c.0.iter()) + .chain(SCRIPT_RESERVED_KEYWORDS.iter()) + .any(|c| aliases.iter().any(|al| al.eq_ignore_ascii_case(c))) +} diff --git a/adana-db/Cargo.toml b/adana-db/Cargo.toml new file mode 100644 index 0000000..e3cb85f --- /dev/null +++ b/adana-db/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "adana-db" +version.workspace = true +authors.workspace = true +description.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde.workspace = true +anyhow.workspace = true +bincode.workspace = true +log.workspace = true +dirs.workspace = true diff --git a/src/db/batch.rs b/adana-db/src/batch.rs similarity index 57% rename from src/db/batch.rs rename to adana-db/src/batch.rs index 15c7f93..9600faa 100644 --- a/src/db/batch.rs +++ b/adana-db/src/batch.rs @@ -1,5 +1,3 @@ -use std::vec::IntoIter; - use super::{Key, Value}; #[derive(Debug)] @@ -14,7 +12,15 @@ impl Batch { pub fn add_insert(&mut self, k: K, v: V) { self.0.push(OpType::Insert((k, v))); } - pub fn into_iter(self) -> IntoIter> { - self.0.into_iter() +} +impl Iterator for Batch { + type Item = OpType; + + fn next(&mut self) -> Option { + if self.0.is_empty() { + None + } else { + Some(self.0.remove(0)) + } } } diff --git a/src/db/database.rs b/adana-db/src/database.rs similarity index 87% rename from src/db/database.rs rename to adana-db/src/database.rs index cc2f0cc..b8f42e2 100644 --- a/src/db/database.rs +++ b/adana-db/src/database.rs @@ -1,6 +1,10 @@ -use std::{fmt::Display, path::Path}; +use std::{ + fmt::Display, + path::Path, + sync::{Arc, Mutex}, +}; -use crate::{db::FileDbConfig, prelude::*}; +use crate::FileDbConfig; use anyhow::Context; use log::debug; use serde::de::DeserializeOwned; @@ -71,10 +75,7 @@ where V: 'static + Value + DeserializeOwned + std::fmt::Debug, { fn in_memory_fallback(e: impl Display) -> anyhow::Result> { - eprintln!( - "{} {e} \nAttempt to open a temporary db...\n", - colors::Red.paint("Warning!") - ); + eprintln!("Warning! {e} \nAttempt to open a temporary db...\n",); Ok(Db::InMemory(Default::default())) } pub fn open(config: Config) -> anyhow::Result> { @@ -90,8 +91,7 @@ where } Err(pid_exist @ FileLockError::PidExist(_)) => { eprintln!( - "{} {pid_exist} \nAttempt to open a temporary db...\n", - colors::Red.paint("Warning!") + "Warning! {pid_exist} \nAttempt to open a temporary db...\n", ); let p = path.as_ref(); let pb = p.to_path_buf(); @@ -103,8 +103,7 @@ where Ok(inner_db) => Ok(Db::InMemory(inner_db)), Err(e) => { eprintln!( - "{} {e:?} \nAttempt to deserialize db, could be because it is the first time you use it\n", - colors::Red.paint("Warning!") + "Warning! {e:?} \nAttempt to deserialize db, could be because it is the first time you use it\n", ); Self::in_memory_fallback(e) } @@ -126,8 +125,7 @@ where Ok(inner_db) => Arc::new(Mutex::new(inner_db)), Err(e) => { eprintln!( - "{} {e:?} \nAttempt to deserialize db, could be because it is the first time you use it\n", - colors::Red.paint("Warning!") + "Warning! {e:?} \nAttempt to deserialize db, could be because it is the first time you use it\n", ); Arc::new(Mutex::new(Default::default())) } @@ -156,8 +154,11 @@ where #[cfg(test)] mod test { - use crate::db::{Config, Db, DbOp, Op}; - use crate::prelude::*; + use std::fs::File; + + use serde::Serialize; + + use crate::{Config, Db, DbOp, Op}; #[derive(Serialize, Debug, PartialEq)] struct MyString(String); diff --git a/src/db/file_db.rs b/adana-db/src/file_db.rs similarity index 98% rename from src/db/file_db.rs rename to adana-db/src/file_db.rs index cd2405b..28f3013 100644 --- a/src/db/file_db.rs +++ b/adana-db/src/file_db.rs @@ -1,13 +1,17 @@ use std::{ - sync::mpsc::{Receiver, Sender}, + collections::BTreeMap, + path::PathBuf, + sync::{ + mpsc::{Receiver, Sender}, + Arc, Mutex, MutexGuard, + }, thread::JoinHandle, vec, }; +use log::{debug, error, trace}; use serde::de::DeserializeOwned; -use crate::prelude::*; - use super::{DbOp, FileLock, InMemoryDb, Key, Op, Value}; pub(super) enum Notify { diff --git a/src/db/file_lock.rs b/adana-db/src/file_lock.rs similarity index 98% rename from src/db/file_lock.rs rename to adana-db/src/file_lock.rs index cc9300a..2aa2a0a 100644 --- a/src/db/file_lock.rs +++ b/adana-db/src/file_lock.rs @@ -5,7 +5,7 @@ use std::{ path::{Path, PathBuf}, }; -use crate::prelude::debug; +use log::{debug, error}; #[derive(Debug, Clone)] pub struct FileLock { @@ -57,7 +57,7 @@ impl FileLock { if let Ok(pid) = pid { if pid_exists(pid) { - debug!("{pid} exist!"); + error!("{pid} exist!"); return Err(FileLockError::PidExist(pid)); } } else { diff --git a/src/db/in_memory.rs b/adana-db/src/in_memory.rs similarity index 98% rename from src/db/in_memory.rs rename to adana-db/src/in_memory.rs index 9de01ea..d270e25 100644 --- a/src/db/in_memory.rs +++ b/adana-db/src/in_memory.rs @@ -1,4 +1,6 @@ -use crate::prelude::*; +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; pub const DEFAULT_TREE: &str = "__adana_default"; @@ -192,9 +194,10 @@ impl DbOp for InMemoryDb { #[cfg(test)] mod test { - use crate::db::in_memory::DEFAULT_TREE; - use crate::db::DbOp; - use crate::prelude::*; + use serde::Serialize; + + use super::DEFAULT_TREE; + use crate::DbOp; use super::{InMemoryDb, Op}; diff --git a/src/db/mod.rs b/adana-db/src/lib.rs similarity index 93% rename from src/db/mod.rs rename to adana-db/src/lib.rs index 2ef9085..d4406d7 100644 --- a/src/db/mod.rs +++ b/adana-db/src/lib.rs @@ -10,10 +10,11 @@ pub use database::*; pub use file_db::*; pub use file_lock::*; pub use in_memory::*; -pub use tree::Tree; - -use crate::prelude::*; +use serde::Serialize; +use std::collections::BTreeMap; use std::fmt::Debug; +use std::hash::Hash; +pub use tree::Tree; pub trait Key: Hash + Eq + Send + Clone + Serialize + Debug + Sync + Ord @@ -47,6 +48,9 @@ pub trait Op { fn clear(&mut self); fn contains(&self, k: &K) -> Option; fn len(&self) -> Option; + fn is_empty(&self) -> bool { + self.len().filter(|&s| s > 0).is_none() + } } pub trait DbOp: Op { fn get_current_tree(&self) -> Option; diff --git a/src/db/tree.rs b/adana-db/src/tree.rs similarity index 92% rename from src/db/tree.rs rename to adana-db/src/tree.rs index e6fcb73..1408dcc 100644 --- a/src/db/tree.rs +++ b/adana-db/src/tree.rs @@ -1,6 +1,9 @@ -use std::ops::DerefMut; +use std::{ + collections::BTreeMap, + ops::{Deref, DerefMut}, +}; -use crate::prelude::*; +use serde::{Deserialize, Serialize}; use super::{Key, Op, Value}; diff --git a/adana-script-core/Cargo.toml b/adana-script-core/Cargo.toml new file mode 100644 index 0000000..c5f12a8 --- /dev/null +++ b/adana-script-core/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "adana-script-core" +version.workspace = true +authors.workspace = true +description.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow.workspace = true +libloading.workspace = true +serde.workspace = true +strum.workspace = true diff --git a/adana-script-core/src/lib.rs b/adana-script-core/src/lib.rs new file mode 100644 index 0000000..0a4926e --- /dev/null +++ b/adana-script-core/src/lib.rs @@ -0,0 +1,362 @@ +pub mod primitive; +use std::collections::BTreeMap; + +use constants::{ + BREAK, DROP, ELSE, EULER_NUMBER, FALSE, FOR, IF, IN, MULTILINE, NULL, PI, + REQUIRE, RETURN, STRUCT, TAU, TO_BINARY, TO_HEX, TRUE, WHILE, +}; +use primitive::Primitive; +use serde::{Deserialize, Serialize}; +use strum::EnumCount; + +use self::constants::TO_STRING; +use self::constants::{ + ABS, COS, EVAL, INCLUDE, LENGTH, LN, LOG, PRINT, PRINT_LN, SIN, SQRT, TAN, + TO_BOOL, TO_DOUBLE, TO_INT, TYPE_OF, +}; + +#[macro_use] +pub mod constants { + macro_rules! pi { + () => { + 'π' + }; + } + macro_rules! euler_number { + () => { + 'γ' + }; + } + macro_rules! tau { + () => { + 'τ' + }; + } + pub const TRUE: &str = "true"; + pub const FALSE: &str = "false"; + pub const IF: &str = "if"; + pub const ELSE: &str = "else"; + pub const WHILE: &str = "while"; + pub const TAU: &str = concat!(tau!()); + pub const PI: &str = concat!(pi!()); + pub const EULER_NUMBER: &str = concat!(euler_number!()); + pub const SQRT: &str = "sqrt"; + pub const TO_HEX: &str = "to_hex"; + pub const TO_BINARY: &str = "to_binary"; + pub const TO_INT: &str = "to_int"; + pub const TO_BOOL: &str = "to_bool"; + pub const TO_DOUBLE: &str = "to_double"; + pub const TO_STRING: &str = "to_string"; + pub const ABS: &str = "abs"; + pub const LENGTH: &str = "length"; + pub const LOG: &str = "log"; + pub const LN: &str = "ln"; + pub const SIN: &str = "sin"; + pub const COS: &str = "cos"; + pub const TAN: &str = "tan"; + pub const BREAK: &str = "break"; + pub const RETURN: &str = "return"; + pub const PRINT_LN: &str = "println"; + pub const PRINT: &str = "print"; + pub const INCLUDE: &str = "include"; + pub const DROP: &str = "drop"; + pub const NULL: &str = "null"; + pub const MULTILINE: &str = "multiline"; + pub const STRUCT: &str = "struct"; + pub const EVAL: &str = "eval"; + pub const TYPE_OF: &str = "type_of"; + pub const FOR: &str = "for"; + pub const IN: &str = "in"; + pub const REQUIRE: &str = "require"; + pub const NATIVE_LIB: &[u8; 14] = b"__native_lib__"; +} + +#[derive(Debug, EnumCount)] +pub enum MathConstants { + Pi, + EulerNumber, + Tau, +} + +impl MathConstants { + pub const fn get_symbol(&self) -> char { + match self { + MathConstants::Pi => pi!(), + MathConstants::EulerNumber => euler_number!(), + MathConstants::Tau => tau!(), + } + } + pub const fn get_symbols() -> &'static str { + concat!(pi!(), euler_number!(), tau!()) + } + + pub const fn _get_variants( + ) -> &'static [&'static MathConstants; MathConstants::COUNT] { + &[&MathConstants::Pi, &MathConstants::EulerNumber, &MathConstants::Tau] + } +} + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub enum Value { + Break, + EarlyReturn(Box>), + Drop(Box), + Expression(Vec), + ImplicitMultiply(Box), + Operation(Operator), + BuiltInFunction { + fn_type: BuiltInFunctionType, + expr: Box, + }, + Function { + parameters: Box, + exprs: Vec, + }, + FunctionCall { + parameters: Box, + function: Box, + }, + Null, + Decimal(f64), + U8(u8), + I8(i8), + Integer(i128), + Bool(bool), + Range { + start: Box, + incl_both_end: bool, + end: Box, + }, + NoOp, + String(String), + FString(String, Vec<(String, Value)>), + BlockParen(Vec), + Variable(String), + VariableRef(String), + VariableUnused, + Const(char), + VariableNegate(String), + VariableExpr { + name: Box, + expr: Box, + }, + IfExpr { + cond: Box, + exprs: Vec, + else_expr: Option>, + }, + WhileExpr { + cond: Box, + exprs: Vec, + }, + ForeachExpr { + var: String, + index_var: Option, + iterator: Box, + exprs: Vec, + }, + Array(Vec), + ArrayAccess { + arr: Box, + index: Box, + }, + Struct(BTreeMap), + StructAccess { + struc: Box, + key: String, + }, +} +#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub enum BuiltInFunctionType { + Sqrt, + Abs, + Log, + Ln, + Sin, + Cos, + ToInt, + ToBinary, + ToHex, + ToDouble, + ToBool, + ToString, + Tan, + Println, + Print, + Eval, + TypeOf, + Length, + Include, + Require, +} + +#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] +pub enum Operator { + Add, + Subtr, + Mult, + Div, + Mod, + Pow, + Pow2, + Pow3, + Not, + Less, + Greater, + LessOrEqual, + GreaterOrEqual, + Equal, + NotEqual, + And, + Or, + BitwiseNot, + BitwiseAnd, + BitwiseOr, + BitwiseXor, + BitwiseLShift, + BitwiseRShift, +} + +#[derive(Debug)] +pub enum TreeNodeValue { + Break, + EarlyReturn(Option), + Drop(Vec), + VariableUnused, + VariableAssign(Option), + VariableArrayAssign { name: String, index: Value }, + Ops(Operator), + Primitive(Primitive), + VariableRef(String), + BuiltInFunction(BuiltInFunctionType), + IfExpr(Value), + FString(String, Vec<(String, Value)>), + WhileExpr(Value), + Array(Vec), + Struct(BTreeMap), + StructAccess { struc: Value, key: Primitive }, + ArrayAccess { index: Value, array: Value }, + Function(Value), + FunctionCall(Value), + Foreach(Value), + Null, +} + +impl BuiltInFunctionType { + pub fn as_str(&self) -> &'static str { + match self { + BuiltInFunctionType::Sqrt => SQRT, + BuiltInFunctionType::Abs => ABS, + BuiltInFunctionType::Log => LOG, + BuiltInFunctionType::Ln => LN, + BuiltInFunctionType::Length => LENGTH, + BuiltInFunctionType::Sin => SIN, + BuiltInFunctionType::Cos => COS, + BuiltInFunctionType::Tan => TAN, + BuiltInFunctionType::TypeOf => TYPE_OF, + BuiltInFunctionType::Println => PRINT_LN, + BuiltInFunctionType::Print => PRINT, + BuiltInFunctionType::Eval => EVAL, + BuiltInFunctionType::Include => INCLUDE, + BuiltInFunctionType::Require => REQUIRE, + BuiltInFunctionType::ToInt => TO_INT, + BuiltInFunctionType::ToHex => TO_HEX, + BuiltInFunctionType::ToBinary => TO_BINARY, + BuiltInFunctionType::ToDouble => TO_DOUBLE, + BuiltInFunctionType::ToBool => TO_BOOL, + BuiltInFunctionType::ToString => TO_STRING, + } + } +} +impl Operator { + pub const fn as_str(&self) -> &'static str { + match self { + Operator::Add => "+", + Operator::Subtr => "-", + Operator::Div => "/", + Operator::Mult => "*", + Operator::Pow => "^", + Operator::Pow2 => "²", + Operator::Pow3 => "³", + Operator::Not => "!", + Operator::Mod => "%", + Operator::Less => "<", + Operator::Greater => ">", + Operator::LessOrEqual => "<=", + Operator::GreaterOrEqual => ">=", + Operator::Equal => "==", + Operator::NotEqual => "!=", + Operator::And => "&&", + Operator::Or => "||", + Operator::BitwiseNot => "~", + Operator::BitwiseAnd => "@", + Operator::BitwiseOr => "|", + Operator::BitwiseXor => "$", + Operator::BitwiseLShift => "<<", + Operator::BitwiseRShift => ">>", + } + } +} + +pub const FORBIDDEN_VARIABLE_NAME: &[&str] = &[ + TRUE, + FALSE, + TAU, + IF, + PI, + PRINT_LN, + PRINT, + LENGTH, + EULER_NUMBER, + ABS, + LOG, + TO_INT, + TO_DOUBLE, + TO_HEX, + TO_BINARY, + TO_STRING, + EVAL, + TO_BOOL, + SQRT, + BREAK, + NULL, + FOR, + IN, + DROP, + //READ_LINES, + RETURN, + LN, + SIN, + COS, + TYPE_OF, + TAN, + INCLUDE, + WHILE, + ELSE, + REQUIRE, + MULTILINE, + STRUCT, + Operator::Add.as_str(), + Operator::Subtr.as_str(), + Operator::Div.as_str(), + Operator::Mult.as_str(), + Operator::Pow.as_str(), + Operator::Pow2.as_str(), + Operator::Pow3.as_str(), + Operator::Not.as_str(), + Operator::Mod.as_str(), + Operator::Less.as_str(), + Operator::Greater.as_str(), + Operator::LessOrEqual.as_str(), + Operator::GreaterOrEqual.as_str(), + Operator::Equal.as_str(), + Operator::NotEqual.as_str(), + Operator::And.as_str(), + Operator::Or.as_str(), + Operator::BitwiseNot.as_str(), + Operator::BitwiseAnd.as_str(), + Operator::BitwiseOr.as_str(), + Operator::BitwiseXor.as_str(), + Operator::BitwiseLShift.as_str(), + Operator::BitwiseRShift.as_str(), +]; diff --git a/adana-script-core/src/primitive.rs b/adana-script-core/src/primitive.rs new file mode 100644 index 0000000..6511a07 --- /dev/null +++ b/adana-script-core/src/primitive.rs @@ -0,0 +1,2142 @@ +use std::{ + cmp::Ordering, + collections::BTreeMap, + fmt::Display, + path::{Path, PathBuf}, + sync::{Arc, RwLock}, +}; + +use anyhow::{Context, Result}; + +use serde::{Deserialize, Serialize}; + +use super::{constants::NULL, Value}; + +const MAX_U32_AS_I128: i128 = u32::MAX as i128; + +#[derive(Debug)] +pub struct NativeLibrary { + lib: libloading::Library, + path: PathBuf, +} + +pub type NativeFunctionCallResult = anyhow::Result; +pub type Compiler = dyn FnMut(Value, BTreeMap) -> NativeFunctionCallResult + + Send; +#[allow(improper_ctypes_definitions)] +pub type NativeFunction<'lib> = libloading::Symbol< + 'lib, + fn(Vec, Box) -> NativeFunctionCallResult, +>; +impl NativeLibrary { + /// # Safety + /// trust me bro + pub unsafe fn new(path: &Path) -> anyhow::Result { + let lib = libloading::Library::new(path) + .map_err(|e| anyhow::format_err!("could not load lib, {e}"))?; + Ok(NativeLibrary { lib, path: path.to_path_buf() }) + } + pub fn get_path(&self) -> &Path { + self.path.as_path() + } + /// # Safety + /// trust me bro + + pub unsafe fn get_function( + &self, + key: &str, + ) -> anyhow::Result { + self.lib.get(key.as_bytes()).context("{key} wasn't found") + } + /// # Safety + /// trust me bro + + pub unsafe fn call_function( + &self, + key: &str, + params: Vec, + compiler: Box, + ) -> anyhow::Result { + let fun = self.get_function(key)?; + fun(params, compiler) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[repr(C)] +pub enum Primitive { + U8(u8), + I8(i8), + Int(i128), + Bool(bool), + Ref(RefPrimitive), + Null, + Double(f64), + String(String), + Array(Vec), + Struct(BTreeMap), + Error(String), + Function { + parameters: Vec, + exprs: Vec, + }, + Unit, + NoReturn, + EarlyReturn(Box), + #[serde(skip_serializing, skip_deserializing)] + NativeLibrary(Arc), + #[serde(skip_serializing, skip_deserializing)] + NativeFunction(String, Arc), +} + +pub type RefPrimitive = Arc>; + +// region: traits +impl Primitive { + pub fn ref_prim(self) -> RefPrimitive { + Arc::new(RwLock::new(self)) + } + pub fn to_value(self) -> anyhow::Result { + let v = match self { + Primitive::U8(u) => Value::U8(u), + Primitive::I8(i) => Value::I8(i), + Primitive::Int(i) => Value::Integer(i), + Primitive::Bool(b) => Value::Bool(b), + Primitive::Ref(r) => { + let r = r + .read() + .map_err(|e| { + anyhow::format_err!("could not acquire lock {e}") + })? + .clone(); + r.to_value()? + } + Primitive::Null => Value::Null, + Primitive::Double(d) => Value::Decimal(d), + Primitive::String(s) => Value::String(s), + Primitive::Array(a) => { + let mut vek = vec![]; + for p in a { + let p = p.to_value()?; + vek.push(p); + } + Value::Array(vek) + } + Primitive::Struct(s) => { + let mut map = BTreeMap::new(); + for (k, v) in s { + let p = v.to_value()?; + map.insert(k, p); + } + Value::Struct(map) + } + Primitive::Error(e) => return Err(anyhow::format_err!("{e}")), + Primitive::Function { parameters, exprs } => Value::Function { + parameters: Box::new(Value::BlockParen(parameters)), + exprs, + }, + Primitive::Unit => Value::NoOp, + Primitive::NoReturn => Value::NoOp, + Primitive::EarlyReturn(e) => { + let v = e.to_value()?; + Value::EarlyReturn(Box::new(Some(v))) + } + Primitive::NativeLibrary(_) => { + return Err(anyhow::anyhow!( + "cannot convert native lib to value" + )); + } + Primitive::NativeFunction(_method, _lib) => { + return Err(anyhow::anyhow!( + "cannot convert native function to value" + )); + } + }; + Ok(v) + } +} + +pub trait TypeOf { + fn type_of(&self) -> Self; +} +pub trait BitShift { + fn left_shift(&self, n: &Self) -> Self; + fn right_shift(&self, n: &Self) -> Self; +} +pub trait ToBool { + fn to_bool(&self) -> Self; +} +pub trait ToNumber { + fn to_int(&self) -> Self; + fn to_double(&self) -> Self; +} +pub trait Pow { + fn pow(&self, n: &Self) -> Self; +} + +pub trait And { + fn and(&self, n: &Self) -> Self; + fn bitwise_and(&self, n: &Self) -> Self; +} +pub trait Or { + fn or(&self, n: &Self) -> Self; + fn bitwise_or(&self, n: &Self) -> Self; + fn bitwise_xor(&self, n: &Self) -> Self; +} +pub trait Sqrt { + fn sqrt(&self) -> Self; +} +pub trait Abs { + fn abs(&self) -> Self; +} +pub trait Logarithm { + fn log(&self) -> Self; + fn ln(&self) -> Self; +} + +pub trait DisplayHex { + fn to_hex(&self) -> Self; +} + +pub trait DisplayBinary { + fn to_binary(&self) -> Self; +} + +pub trait Sin { + fn sin(&self) -> Self; +} +pub trait Array { + fn index_at(&self, rhs: &Self) -> Self; + fn len(&self) -> Primitive; + fn is_empty(&self) -> Primitive; + fn swap_mem(&mut self, rhs: &mut Self, index: &Primitive) -> Self; + fn remove(&mut self, key: &Self) -> anyhow::Result<()>; +} + +pub trait Cos { + fn cos(&self) -> Self; +} +pub trait Tan { + fn tan(&self) -> Self; +} + +pub trait Add { + fn add(&self, rhs: &Self) -> Self; +} + +pub trait Neg { + fn neg(&self) -> Self; +} + +pub trait Not { + fn bitwise_not(&self) -> Self; + fn not(&self) -> Self; +} + +pub trait Sub { + fn sub(&self, rhs: &Self) -> Self; +} + +pub trait Mul { + fn mul(&self, rhs: &Self) -> Self; +} + +pub trait Div { + fn div(&self, rhs: &Self) -> Self; +} + +pub trait Rem { + fn rem(&self, rhs: &Self) -> Self; +} +// endregion traits + +// region: impl primitive +#[allow(dead_code)] +impl Primitive { + pub fn is_greater_than(&self, other: &Primitive) -> Primitive { + match self.partial_cmp(other) { + Some(Ordering::Greater) => Primitive::Bool(true), + Some(Ordering::Less) => Primitive::Bool(false), + Some(Ordering::Equal) => Primitive::Bool(false), + None => Primitive::Error(format!( + "call to is_greater_than() for two different types {self} => {other}" + )), + } + } + pub fn is_greater_or_equal(&self, other: &Primitive) -> Primitive { + match self.partial_cmp(other) { + Some(Ordering::Greater) | Some(Ordering::Equal) => Primitive::Bool(true), + Some(Ordering::Less) => Primitive::Bool(false), + None => Primitive::Error(format!( + "call to is_greater_or_equal() for two different types {self} => {other}" + )), + } + } + pub fn is_less_than(&self, other: &Primitive) -> Primitive { + match self.partial_cmp(other) { + Some(Ordering::Less) => Primitive::Bool(true), + Some(Ordering::Greater) => Primitive::Bool(false), + Some(Ordering::Equal) => Primitive::Bool(false), + None => Primitive::Error(format!( + "call to is_less_than() for two different types {self} => {other}" + )), + } + } + pub fn is_less_or_equal(&self, other: &Primitive) -> Primitive { + match self.partial_cmp(other) { + Some(Ordering::Less) | Some(Ordering::Equal) => Primitive::Bool(true), + Some(Ordering::Greater) => Primitive::Bool(false), + None => Primitive::Error(format!( + "call to is_less_or_equal() for two different types {self} => {other}" + )), + } + } + pub fn is_equal(&self, other: &Primitive) -> Primitive { + match self.partial_cmp(other) { + Some(Ordering::Equal) => Primitive::Bool(true), + Some(Ordering::Less) | Some(Ordering::Greater) => Primitive::Bool(false), + None => match (self, other) { + (Primitive::Null, _) | (_, Primitive::Null) => Primitive::Bool(false), + (Primitive::Struct(_), Primitive::Struct(_)) => Primitive::Bool(false), + _ => Primitive::Error(format!( + "call to is_equal() for two different types {self} => {other}" + )), + }, + } + } + pub fn as_ref_ok(&self) -> Result<&Primitive> { + match self { + Primitive::Error(msg) => Err(anyhow::Error::msg(msg.to_string())), + + _ => Ok(self), + } + } +} + +impl Display for Primitive { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Primitive::Ref(s) => { + let lock = s.read().expect("FMT ERROR: could not acquire lock"); + write!(f, "{lock}") + } + Primitive::U8(u) => write!(f, "{u}"), + Primitive::I8(u) => write!(f, "{u}"), + Primitive::Int(i) => write!(f, "{i}"), + Primitive::Double(d) => write!(f, "{d}"), + Primitive::Bool(b) => write!(f, "{b}"), + Primitive::Error(e) => write!(f, "Err: {e}"), + Primitive::String(s) => { + write!(f, "{s}") + } + Primitive::Unit => write!(f, "()"), + Primitive::Array(arr) => { + let joined_arr = arr + .iter() + .map(|p| match p { + Primitive::String(s) => format!(r#""{s}""#), + _ => p.to_string(), + }) + .collect::>(); + write!(f, "[{}]", joined_arr[..].join(", ")) + } + Primitive::Struct(struc) => { + let joined_arr = struc + .iter() + .map(|(k, p)| { + format!( + "\t{k}: {}", + if let Primitive::String(s) = p { + format!(r#""{s}""#) + } else { + p.to_string() + } + ) + }) + .collect::>(); + write!(f, "struct {{\n{}\n}}", joined_arr[..].join(", \n")) + } + Primitive::Function { parameters, exprs: _ } => { + let mut parameters_formatted = String::new(); + let len = parameters.len(); + for (idx, p) in parameters.iter().enumerate() { + match p { + Value::VariableUnused => parameters_formatted.push('_'), + _ => { + parameters_formatted.push('p'); + parameters_formatted.push( + char::from_digit(idx as u32, 10).unwrap_or('0'), + ); + } + } + if idx < len { + parameters_formatted.push(','); + } + } + write!(f, "({parameters_formatted}) => {{..}}") + } + Primitive::NoReturn => write!(f, "!"), + Primitive::Null => write!(f, "{NULL}"), + Primitive::EarlyReturn(p) => write!(f, "{p}"), + Primitive::NativeLibrary { .. } => write!(f, "__native_lib__"), + Primitive::NativeFunction(key, _) => { + write!(f, "__native_fn__{key}") + } + } + } +} + +impl Sin for Primitive { + fn sin(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("SIN ERORR: could not acquire lock!"); + lock.sin() + } + Primitive::U8(i) => Primitive::Double((*i as f64).sin()), + Primitive::I8(i) => Primitive::Double((*i as f64).sin()), + Primitive::Int(i) => Primitive::Double((*i as f64).sin()), + Primitive::Double(d) => Primitive::Double(d.sin()), + + Primitive::Error(e) => panic!("call to sin() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to sin() => {self}")), + } + } +} + +impl Cos for Primitive { + fn cos(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("COS ERORR: could not acquire lock!"); + lock.cos() + } + Primitive::Int(i) => Primitive::Double((*i as f64).cos()), + Primitive::U8(i) => Primitive::Double((*i as f64).cos()), + Primitive::I8(i) => Primitive::Double((*i as f64).cos()), + Primitive::Double(d) => Primitive::Double(d.cos()), + Primitive::Error(e) => panic!("call to cos() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to cos() => {self}")), + } + } +} + +impl Tan for Primitive { + fn tan(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("TAN ERORR: could not acquire lock!"); + lock.tan() + } + + Primitive::U8(i) => Primitive::Double((*i as f64).tan()), + Primitive::I8(i) => Primitive::Double((*i as f64).tan()), + Primitive::Int(i) => Primitive::Double((*i as f64).tan()), + Primitive::Double(d) => Primitive::Double(d.tan()), + Primitive::Error(e) => panic!("call to tan() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to tan() => {self}")), + } + } +} + +impl Logarithm for Primitive { + fn log(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("LOG ERORR: could not acquire lock!"); + lock.log() + } + + Primitive::U8(i) => Primitive::Double((*i as f64).log10()), + Primitive::I8(i) => Primitive::Double((*i as f64).log10()), + Primitive::Int(i) => Primitive::Double((*i as f64).log10()), + Primitive::Double(d) => Primitive::Double(d.log10()), + Primitive::Error(e) => panic!("call to log() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to log() => {self}")), + } + } + fn ln(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = s.read().expect("LN ERORR: could not acquire lock!"); + lock.ln() + } + + Primitive::U8(i) => Primitive::Double((*i as f64).ln()), + Primitive::I8(i) => Primitive::Double((*i as f64).ln()), + Primitive::Int(i) => Primitive::Double((*i as f64).ln()), + Primitive::Double(d) => Primitive::Double(d.ln()), + Primitive::Error(e) => panic!("call to ln() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to ln() => {self}")), + } + } +} + +impl Sqrt for Primitive { + fn sqrt(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("SQRT ERORR: could not acquire lock!"); + lock.sqrt() + } + Primitive::U8(i) => Primitive::Double((*i as f64).sqrt()), + Primitive::I8(i) => Primitive::Double((*i as f64).sqrt()), + Primitive::Int(i) => Primitive::Double((*i as f64).sqrt()), + Primitive::Double(d) => Primitive::Double(d.sqrt()), + Primitive::Error(e) => panic!("call to sqrt() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to sqrt() => {self}")), + } + } +} +impl Abs for Primitive { + fn abs(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("ABS ERORR: could not acquire lock!"); + lock.abs() + } + Primitive::U8(i) => Primitive::U8(*i), + Primitive::I8(i) => Primitive::I8(i.abs()), + Primitive::Int(i) => Primitive::Int(i.abs()), + Primitive::Double(d) => Primitive::Double(d.abs()), + Primitive::Error(e) => panic!("call to abs() on an error. {e}"), + _ => Primitive::Error(format!("illegal call to abs() => {self}")), + } + } +} + +impl Pow for Primitive { + fn pow(&self, rhs: &Self) -> Self { + match (self, rhs) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l.read().expect("POW L ERORR: could not acquire lock!"); + + let r = r.read().expect("POW R ERORR: could not acquire lock!"); + l.pow(&r) + } + (Primitive::Ref(l), r) => { + let l = l.read().expect("POW L ERORR: could not acquire lock!"); + + l.pow(r) + } + (l, Primitive::Ref(r)) => { + let r = r.read().expect("POW R ERORR: could not acquire lock!"); + + l.pow(&r) + } + (Primitive::U8(l), Primitive::U8(r)) => { + Primitive::Int((*l as i128).pow(*r as u32)) + } + (Primitive::U8(l), Primitive::I8(r)) if r > &0 => { + Primitive::Int((*l as i128).pow(*r as u32)) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Double((*l as f64).powf(*r as f64)) + } + #[allow(clippy::manual_range_contains)] + (Primitive::U8(l), Primitive::Int(r)) + if r >= &0 && r <= &MAX_U32_AS_I128 => + { + Primitive::Int((*l as i128).pow(*r as u32)) + } + + (Primitive::I8(l), Primitive::I8(r)) if r > &0 => { + Primitive::Int((*l as i128).pow(*r as u32)) + } + (Primitive::I8(l), Primitive::I8(r)) => { + Primitive::Double((*l as f64).powf(*r as f64)) + } + + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int((*l as i128).pow(*r as u32)) + } + #[allow(clippy::manual_range_contains)] + (Primitive::I8(l), Primitive::Int(r)) + if r >= &0 && r <= &MAX_U32_AS_I128 => + { + Primitive::Int((*l as i128).pow(*r as u32)) + } + + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Double((*l as f64).powf(*r as f64)) + } + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Double((*l as f64).powf(*r as f64)) + } + (Primitive::U8(l), Primitive::Double(r)) => { + Primitive::Double((*l as f64).powf(*r)) + } + (Primitive::I8(l), Primitive::Double(r)) => { + Primitive::Double((*l as f64).powf(*r)) + } + + #[allow(clippy::manual_range_contains)] + (Primitive::Int(l), Primitive::Int(r)) + if r >= &0 && r <= &MAX_U32_AS_I128 => + { + Primitive::Int(l.pow(*r as u32)) + } + + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l.pow(*r as u32)) + } + (Primitive::Int(l), Primitive::I8(r)) if r >= &0 => { + Primitive::Int(l.pow(*r as u32)) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Double((*l as f64).powf(*r as f64)) + } + (Primitive::Int(l), Primitive::Int(r)) => { + Primitive::Double((*l as f64).powf(*r as f64)) + } + (Primitive::Int(l), Primitive::Double(r)) => { + Primitive::Double((*l as f64).powf(*r)) + } + (Primitive::Double(l), Primitive::Int(r)) => { + Primitive::Double(l.powf(*r as f64)) + } + (Primitive::Double(l), Primitive::U8(r)) => { + Primitive::Double(l.powf(*r as f64)) + } + (Primitive::Double(l), Primitive::I8(r)) => { + Primitive::Double(l.powf(*r as f64)) + } + (Primitive::Double(l), Primitive::Double(r)) => { + Primitive::Double(l.powf(*r)) + } + (l, r) => Primitive::Error(format!( + "illegal call to pow() => left: {l} right: {r}" + )), + } + } +} + +impl Add for Primitive { + fn add(&self, rhs: &Self) -> Self { + match (self.clone(), rhs.clone()) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l.read().expect("ADD L ERORR: could not acquire lock!"); + + let r = r.read().expect("ADD R ERORR: could not acquire lock!"); + l.add(&r) + } + (Primitive::Ref(l), r) => { + let l = l.read().expect("ADD L ERORR: could not acquire lock!"); + + l.add(&r) + } + (l, Primitive::Ref(r)) => { + let r = r.read().expect("ADD R ERORR: could not acquire lock!"); + + l.add(&r) + } + (Primitive::U8(l), Primitive::U8(r)) => { + Primitive::Int(l as i128 + r as i128) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int(l as i128 + r as i128) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int(l as i128 + r) + } + (Primitive::U8(l), Primitive::String(s)) => { + Primitive::String(format!("{l}{s}")) + } + (Primitive::U8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 + r) + } + + (Primitive::I8(l), Primitive::I8(r)) => { + Primitive::Int(l as i128 + r as i128) + } + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int(l as i128 + r as i128) + } + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int(l as i128 + r) + } + (Primitive::I8(l), Primitive::String(s)) => { + Primitive::String(format!("{l}{s}")) + } + (Primitive::I8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 + r) + } + + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l + r), + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l + r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l + r as i128) + } + (Primitive::Int(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 + r) + } + (Primitive::Int(l), Primitive::String(s)) => { + Primitive::String(format!("{l}{s}")) + } + + (Primitive::Double(l), Primitive::Int(r)) => { + Primitive::Double(l + r as f64) + } + (Primitive::Double(l), Primitive::U8(r)) => { + Primitive::Double(l + r as f64) + } + (Primitive::Double(l), Primitive::I8(r)) => { + Primitive::Double(l + r as f64) + } + (Primitive::Double(l), Primitive::Double(r)) => { + Primitive::Double(l + r) + } + + (Primitive::Array(mut l), Primitive::Array(mut r)) => { + l.append(&mut r); + Primitive::Array(l) + } + + (Primitive::Array(mut l), r) => { + let r: Primitive = r; + l.push(r); + Primitive::Array(l) + } + (l, Primitive::Array(mut r)) => { + r.insert(0, l); + Primitive::Array(r) + } + (l, Primitive::String(s)) => Primitive::String(format!("{l}{s}")), + + (Primitive::String(s), r) => Primitive::String(format!("{s}{r}")), + (l, r) => Primitive::Error(format!( + "illegal call to add() => left: {l} right: {r}" + )), + } + } +} + +impl Sub for Primitive { + fn sub(&self, rhs: &Self) -> Self { + match (self.clone(), rhs.clone()) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l.read().expect("SUB L ERORR: could not acquire lock!"); + + let r = r.read().expect("SUB R ERORR: could not acquire lock!"); + l.sub(&r) + } + (Primitive::Ref(l), r) => { + let l = l.read().expect("SUB L ERORR: could not acquire lock!"); + + l.sub(&r) + } + (l, Primitive::Ref(r)) => { + let r = r.read().expect("SUB R ERORR: could not acquire lock!"); + + l.sub(&r) + } + + (Primitive::U8(l), Primitive::U8(r)) => { + if let Some(v) = l.checked_sub(r) { + Primitive::U8(v) + } else { + Primitive::Int(l as i128 - r as i128) + } + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int(l as i128 - r as i128) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int(l as i128 - r) + } + (Primitive::U8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 - r) + } + + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int(l as i128 - r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) => { + if let Some(v) = l.checked_sub(r) { + Primitive::I8(v) + } else { + Primitive::Int(l as i128 - r as i128) + } + } + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int(l as i128 - r) + } + (Primitive::I8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 - r) + } + + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l - r), + (Primitive::Int(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 - r) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l - r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l - r as i128) + } + + (Primitive::Double(l), Primitive::Int(r)) => { + Primitive::Double(l - r as f64) + } + (Primitive::Double(l), Primitive::Double(r)) => { + Primitive::Double(l - r) + } + (Primitive::Double(l), Primitive::U8(r)) => { + Primitive::Double(l - r as f64) + } + (Primitive::Double(l), Primitive::I8(r)) => { + Primitive::Double(l - r as f64) + } + + (l, r) => Primitive::Error(format!( + "illegal call to sub() => left: {l} right: {r}" + )), + } + } +} +impl Rem for Primitive { + fn rem(&self, rhs: &Self) -> Self { + match (self.clone(), rhs.clone()) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l.read().expect("REM L ERORR: could not acquire lock!"); + + let r = r.read().expect("REM R ERORR: could not acquire lock!"); + l.rem(&r) + } + (Primitive::Ref(l), r) => { + let l = l.read().expect("REM L ERORR: could not acquire lock!"); + + l.rem(&r) + } + (l, Primitive::Ref(r)) => { + let r = r.read().expect("REM R ERORR: could not acquire lock!"); + + l.rem(&r) + } + + (Primitive::U8(l), Primitive::U8(r)) if r != 0 => { + Primitive::U8(l % r) + } + (Primitive::U8(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l as i128 % r as i128) + } + (Primitive::U8(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l as i128 % r) + } + (Primitive::U8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 % r) + } + (Primitive::U8(_), _) => Primitive::Double(f64::NAN), + + (Primitive::I8(l), Primitive::I8(r)) if r != 0 => { + Primitive::I8(l % r) + } + (Primitive::I8(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l as i128 % r as i128) + } + (Primitive::I8(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l as i128 % r) + } + (Primitive::I8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 % r) + } + (Primitive::I8(_), _) => Primitive::Double(f64::NAN), + + (Primitive::Int(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l % r) + } + (Primitive::Int(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l % r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l % r as i128) + } + (Primitive::Int(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 % r) + } + (Primitive::Int(_), _) => Primitive::Double(f64::NAN), + + (Primitive::Double(l), Primitive::U8(r)) => { + Primitive::Double(l % r as f64) + } + (Primitive::Double(l), Primitive::I8(r)) => { + Primitive::Double(l % r as f64) + } + (Primitive::Double(l), Primitive::Int(r)) => { + Primitive::Double(l % r as f64) + } + (Primitive::Double(l), Primitive::Double(r)) => { + Primitive::Double(l % r) + } + + (l, r) => Primitive::Error(format!( + "illegal call to rem() => left: {l} right: {r}" + )), + } + } +} + +impl Mul for Primitive { + fn mul(&self, rhs: &Self) -> Self { + fn multiply_array(arr: Vec, n: i128) -> Vec { + let arr_size = arr.len(); + arr.into_iter().cycle().take(n as usize * arr_size).collect() + } + match (self.clone(), rhs.clone()) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l.read().expect("MUL L ERORR: could not acquire lock!"); + + let r = r.read().expect("MUL R ERORR: could not acquire lock!"); + l.mul(&r) + } + (Primitive::Ref(l), r) => { + let l = l.read().expect("MUL L ERORR: could not acquire lock!"); + + l.mul(&r) + } + (l, Primitive::Ref(r)) => { + let r = r.read().expect("MUL R ERORR: could not acquire lock!"); + + l.mul(&r) + } + + (Primitive::U8(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l as i128 * r as i128) + } + (Primitive::U8(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l as i128 * r as i128) + } + (Primitive::U8(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l as i128 * r) + } + (Primitive::U8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 * r) + } + (Primitive::U8(l), Primitive::Array(r)) => { + Primitive::Array(multiply_array(r, l as i128)) + } + + (Primitive::I8(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l as i128 * r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l as i128 * r as i128) + } + (Primitive::I8(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l as i128 * r) + } + (Primitive::I8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 * r) + } + (Primitive::I8(l), Primitive::Array(r)) if l >= 0 => { + Primitive::Array(multiply_array(r, l as i128)) + } + + (Primitive::Int(l), Primitive::Int(r)) => { + Primitive::Int(l.wrapping_mul(r)) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l * r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l * r as i128) + } + (Primitive::Int(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 * r) + } + (Primitive::Int(l), Primitive::Array(r)) if l >= 0 => { + Primitive::Array(multiply_array(r, l)) + } + + (Primitive::Double(l), Primitive::Int(r)) => { + Primitive::Double(l * r as f64) + } + (Primitive::Double(l), Primitive::U8(r)) => { + Primitive::Double(l * r as f64) + } + (Primitive::Double(l), Primitive::I8(r)) => { + Primitive::Double(l * r as f64) + } + (Primitive::Double(l), Primitive::Double(r)) => { + Primitive::Double(l * r) + } + + (Primitive::String(l), Primitive::Int(r)) if r >= 0 => { + Primitive::String(l.repeat(r as usize)) + } + (Primitive::String(l), Primitive::U8(r)) => { + Primitive::String(l.repeat(r as usize)) + } + (Primitive::String(l), Primitive::I8(r)) if r >= 0 => { + Primitive::String(l.repeat(r as usize)) + } + + (Primitive::Array(l), Primitive::Int(n)) if n >= 0 => { + Primitive::Array(multiply_array(l, n)) + } + (Primitive::Array(l), Primitive::U8(n)) => { + Primitive::Array(multiply_array(l, n as i128)) + } + (Primitive::Array(l), Primitive::I8(n)) if n >= 0 => { + Primitive::Array(multiply_array(l, n as i128)) + } + + (l, r) => Primitive::Error(format!( + "illegal call to mul() => left: {l} right: {r}" + )), + } + } +} +impl Div for Primitive { + fn div(&self, rhs: &Self) -> Self { + match (self.clone(), rhs.clone()) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l.read().expect("DIV L ERORR: could not acquire lock!"); + + let r = r.read().expect("DIV R ERORR: could not acquire lock!"); + l.div(&r) + } + (Primitive::Ref(l), r) => { + let l = l.read().expect("DIV L ERORR: could not acquire lock!"); + + l.div(&r) + } + (l, Primitive::Ref(r)) => { + let r = r.read().expect("DIV R ERORR: could not acquire lock!"); + + l.div(&r) + } + + (Primitive::U8(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l as i128 / r as i128) + } + (Primitive::U8(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l as i128 / r as i128) + } + (Primitive::U8(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l as i128 / r) + } + (Primitive::U8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 / r) + } + (Primitive::U8(l), Primitive::Int(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::U8(l), Primitive::U8(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::U8(l), Primitive::I8(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::U8(_), _) => Primitive::Double(f64::NAN), + + (Primitive::I8(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l as i128 / r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l as i128 / r as i128) + } + (Primitive::I8(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l as i128 / r) + } + (Primitive::I8(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 / r) + } + (Primitive::I8(l), Primitive::Int(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::I8(l), Primitive::U8(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::I8(l), Primitive::I8(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::I8(_), _) => Primitive::Double(f64::NAN), + + (Primitive::Int(l), Primitive::Int(r)) if r != 0 => { + Primitive::Int(l / r) + } + (Primitive::Int(l), Primitive::U8(r)) if r != 0 => { + Primitive::Int(l / r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) if r != 0 => { + Primitive::Int(l / r as i128) + } + (Primitive::Int(l), Primitive::Double(r)) => { + Primitive::Double(l as f64 / r) + } + (Primitive::Int(l), Primitive::Int(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::Int(l), Primitive::U8(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::Int(l), Primitive::I8(_)) if l >= 1 => { + Primitive::Double(f64::INFINITY) + } + (Primitive::Int(_), _) => Primitive::Double(f64::NAN), + + (Primitive::Double(l), Primitive::Int(r)) => { + Primitive::Double(l / r as f64) + } + (Primitive::Double(l), Primitive::U8(r)) => { + Primitive::Double(l / r as f64) + } + (Primitive::Double(l), Primitive::I8(r)) => { + Primitive::Double(l / r as f64) + } + (Primitive::Double(l), Primitive::Double(r)) => { + Primitive::Double(l / r) + } + + (l, r) => Primitive::Error(format!( + "illegal call to div() => left: {l} right: {r}" + )), + } + } +} + +impl Neg for Primitive { + fn neg(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("NEG ERORR: could not acquire lock!"); + lock.neg() + } + Primitive::U8(n) if *n > i8::MAX as u8 => { + Primitive::Int(-(*n as i128)) + } + Primitive::U8(n) => Primitive::I8(-(*n as i8)), + Primitive::I8(n) => Primitive::I8(-*n), + + Primitive::Int(n) => Primitive::Int(-n), + Primitive::Double(n) => Primitive::Double(-n), + _ => Primitive::Error(format!("invalid call to neg() {self}")), + } + } +} + +impl Not for Primitive { + fn not(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("NOT ERORR: could not acquire lock!"); + lock.not() + } + Primitive::Bool(b) => Primitive::Bool(!b), + _ => Primitive::Error(format!("invalid call to not() {self}")), + } + } + fn bitwise_not(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("NOT ERORR: could not acquire lock!"); + lock.not() + } + Primitive::U8(b) if *b < i8::MAX as u8 => { + Primitive::I8(!(*b as i8)) + } + Primitive::U8(b) => Primitive::Int(!(*b as i128)), + Primitive::I8(b) => Primitive::I8(!b), + Primitive::Int(b) => Primitive::Int(!b), + _ => Primitive::Error(format!( + "invalid call to bitwise_not() {self}" + )), + } + } +} + +impl ToBool for Primitive { + fn to_bool(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("TO_BOOL ERORR: could not acquire lock!"); + lock.to_bool() + } + v @ Primitive::Bool(_) => v.clone(), + Primitive::Double(n) => Primitive::Bool(n > &0.0), + Primitive::U8(n) => Primitive::Bool(n > &0), + Primitive::I8(n) => Primitive::Bool(n > &0), + Primitive::Int(n) => Primitive::Bool(n > &0), + Primitive::Null => Primitive::Bool(false), + Primitive::Array(a) => Primitive::Bool(!a.is_empty()), + Primitive::String(s) => match s.parse::() { + Ok(b) => Primitive::Bool(b), + Err(e) => Primitive::Error(format!( + "invalid cast to bool: {self}, {e}" + )), + }, + _ => Primitive::Error(format!("invalide cast too bool: {self}")), + } + } +} + +impl ToNumber for Primitive { + fn to_int(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("TO_INT ERORR: could not acquire lock!"); + lock.to_int() + } + v @ Primitive::Int(_) => v.clone(), + v @ Primitive::U8(_) => v.clone(), + v @ Primitive::I8(_) => v.clone(), + Primitive::Bool(false) => Primitive::Int(0), + Primitive::Bool(true) => Primitive::Int(1), + Primitive::Double(d) => Primitive::Int(*d as i128), + Primitive::String(s) => match s.parse::() { + Ok(number) => Primitive::Int(number), + Err(e) => Primitive::Error(format!( + "invalid cast to int: {self}, {e}" + )), + }, + _ => Primitive::Error(format!("invalid cast to int: {self}")), + } + } + + fn to_double(&self) -> Self { + match self { + Primitive::Ref(s) => { + let lock = + s.read().expect("TO_DOUBLE ERORR: could not acquire lock!"); + lock.to_double() + } + Primitive::U8(d) => Primitive::Double(*d as f64), + Primitive::I8(d) => Primitive::Double(*d as f64), + Primitive::Int(d) => Primitive::Double(*d as f64), + v @ Primitive::Double(_) => v.clone(), + Primitive::String(s) => match s.parse::() { + Ok(number) => Primitive::Double(number), + Err(e) => Primitive::Error(format!( + "invalid cast to double: {self}, {e}" + )), + }, + _ => Primitive::Error(format!("invalid cast to double: {self}")), + } + } +} + +impl BitShift for Primitive { + fn right_shift(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = + l.read().expect("B_R_SHIFT L ERROR: could not acquire lock!"); + let r = + r.read().expect("B_R_SHIFT R ERROR: could not acquire lock!"); + return l.right_shift(&r); + } else if let &Primitive::Ref(l) = &self { + let l = l + .read() + .expect("B_R_SHIFT SELF ERROR: could not acquire lock!"); + return l.right_shift(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = + r.read().expect("B_R_SHIFT RHS ERROR: could not acquire lock!"); + return self.right_shift(&r); + } + + match (self, rhs) { + (Primitive::U8(l), Primitive::U8(r)) => { + Primitive::Int(*l as i128 >> *r as i128) + } + (Primitive::U8(l), Primitive::Bool(r)) => { + Primitive::U8(l >> if r == &true { 1 } else { 0 }) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 >> r) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int(*l as i128 >> *r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) => { + Primitive::Int(*l as i128 >> *r as i128) + } + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 >> r) + } + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int(*l as i128 >> *r as i128) + } + (Primitive::I8(l), Primitive::Bool(r)) => { + Primitive::I8(l >> if r == &true { 1 } else { 0 }) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l >> *r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l >> *r as i128) + } + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l >> *r), + (Primitive::Int(l), Primitive::Bool(r)) => { + Primitive::Int(l >> if r == &true { 1 } else { 0 }) + } + _ => Primitive::Error(format!( + "illegal call to 'r_shift' => left: {self} right: {rhs}" + )), + } + } + + fn left_shift(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = + l.read().expect("B_L_SHIFT L ERROR: could not acquire lock!"); + let r = + r.read().expect("B_L_SHIFT R ERROR: could not acquire lock!"); + return l.left_shift(&r); + } else if let &Primitive::Ref(l) = &self { + let l = l + .read() + .expect("B_L_SHIFT SELF ERROR: could not acquire lock!"); + return l.left_shift(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = + r.read().expect("B_L_SHIFT RHS ERROR: could not acquire lock!"); + return self.left_shift(&r); + } + + match (self, rhs) { + (Primitive::U8(l), Primitive::U8(r)) => { + Primitive::Int((*l as i128) << *r as i128) + } + (Primitive::U8(l), Primitive::Bool(r)) => { + Primitive::U8(l << if r == &true { 1 } else { 0 }) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int((*l as i128) << r) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int((*l as i128) << r) + } + (Primitive::I8(l), Primitive::I8(r)) => { + Primitive::Int((*l as i128) << (*r as i128)) + } + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int((*l as i128) << r) + } + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int((*l as i128) << *r as i128) + } + (Primitive::I8(l), Primitive::Bool(r)) => { + Primitive::I8(l << if r == &true { 1 } else { 0 }) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l << *r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l << *r as i128) + } + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l << *r), + (Primitive::Int(l), Primitive::Bool(r)) => { + Primitive::Int(l << if r == &true { 1 } else { 0 }) + } + _ => Primitive::Error(format!( + "illegal call to 'l_shift' => left: {self} right: {rhs}" + )), + } + } +} + +impl Or for Primitive { + fn or(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = l.read().expect("OR L ERROR: could not acquire lock!"); + let r = r.read().expect("OR R ERROR: could not acquire lock!"); + return l.or(&r); + } else if let &Primitive::Ref(l) = &self { + let l = l.read().expect("OR SELF ERROR: could not acquire lock!"); + return l.or(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = r.read().expect("OR RHS ERROR: could not acquire lock!"); + return self.or(&r); + } + if let &Primitive::Bool(true) = &self { + return Primitive::Bool(true); + } + if !matches!((self, &rhs), (Primitive::Bool(_), Primitive::Bool(_))) { + Primitive::Error(format!( + "illegal call to 'or' => left: {self} right: {rhs}" + )); + } + rhs.clone() + } + + fn bitwise_or(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = l.read().expect("B_OR L ERROR: could not acquire lock!"); + let r = r.read().expect("B_OR R ERROR: could not acquire lock!"); + return l.bitwise_or(&r); + } else if let &Primitive::Ref(l) = &self { + let l = l.read().expect("B_OR SELF ERROR: could not acquire lock!"); + return l.bitwise_or(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = r.read().expect("B_OR RHS ERROR: could not acquire lock!"); + return self.bitwise_or(&r); + } + + match (self, rhs) { + (Primitive::U8(l), Primitive::U8(r)) => Primitive::U8(l | r), + (Primitive::U8(l), Primitive::Bool(r)) => { + Primitive::U8(l | if r == &true { 1 } else { 0 }) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 | r) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int(*l as i128 | *r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) => Primitive::I8(l | r), + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 | r) + } + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int(*l as i128 | *r as i128) + } + (Primitive::I8(l), Primitive::Bool(r)) => { + Primitive::I8(l | if r == &true { 1 } else { 0 }) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l | *r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l | *r as i128) + } + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l | *r), + (Primitive::Int(l), Primitive::Bool(r)) => { + Primitive::Int(l | if r == &true { 1 } else { 0 }) + } + _ => Primitive::Error(format!( + "illegal call to 'bitwise_or' => left: {self} right: {rhs}" + )), + } + } + + fn bitwise_xor(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = l.read().expect("B_XOR L ERROR: could not acquire lock!"); + let r = r.read().expect("B_XOR R ERROR: could not acquire lock!"); + return l.bitwise_xor(&r); + } else if let &Primitive::Ref(l) = &self { + let l = + l.read().expect("B_XOR SELF ERROR: could not acquire lock!"); + return l.bitwise_xor(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = r.read().expect("B_XOR RHS ERROR: could not acquire lock!"); + return self.bitwise_xor(&r); + } + + match (self, rhs) { + (Primitive::U8(l), Primitive::U8(r)) => Primitive::U8(l ^ r), + (Primitive::U8(l), Primitive::Bool(r)) => { + Primitive::U8(l ^ if r == &true { 1 } else { 0 }) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 ^ r) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int(*l as i128 ^ *r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) => Primitive::I8(l ^ r), + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 ^ r) + } + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int(*l as i128 ^ *r as i128) + } + (Primitive::I8(l), Primitive::Bool(r)) => { + Primitive::I8(l ^ if r == &true { 1 } else { 0 }) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l ^ *r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l ^ *r as i128) + } + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l ^ *r), + (Primitive::Int(l), Primitive::Bool(r)) => { + Primitive::Int(l ^ if r == &true { 1 } else { 0 }) + } + _ => Primitive::Error(format!( + "illegal call to 'bitwise_xor' => left: {self} right: {rhs}" + )), + } + } +} +impl And for Primitive { + fn and(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = l.read().expect("AND L ERROR: could not acquire lock!"); + let r = r.read().expect("AND R ERROR: could not acquire lock!"); + return l.and(&r); + } else if let &Primitive::Ref(l) = &self { + let l = l.read().expect("AND SELF ERROR: could not acquire lock!"); + return l.and(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = r.read().expect("AND RHS ERROR: could not acquire lock!"); + return self.and(&r); + } + if let &Primitive::Bool(false) = &self { + return Primitive::Bool(false); + } + + if !matches!((self, &rhs), (Primitive::Bool(_), Primitive::Bool(_))) { + return Primitive::Error(format!( + "illegal call to 'and' => left: {self} right: {rhs}" + )); + } + + rhs.clone() + } + fn bitwise_and(&self, rhs: &Self) -> Self { + if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { + let l = l.read().expect("B_AND L ERROR: could not acquire lock!"); + let r = r.read().expect("B_AND R ERROR: could not acquire lock!"); + return l.bitwise_and(&r); + } else if let &Primitive::Ref(l) = &self { + let l = + l.read().expect("B_AND SELF ERROR: could not acquire lock!"); + return l.bitwise_and(rhs); + } else if let &Primitive::Ref(r) = &rhs { + let r = r.read().expect("B_AND RHS ERROR: could not acquire lock!"); + return self.bitwise_and(&r); + } + + match (self, rhs) { + (Primitive::U8(l), Primitive::U8(r)) => Primitive::U8(l & r), + (Primitive::U8(l), Primitive::Bool(r)) => { + Primitive::U8(l & if r == &true { 1 } else { 0 }) + } + (Primitive::U8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 & r) + } + (Primitive::U8(l), Primitive::I8(r)) => { + Primitive::Int(*l as i128 & *r as i128) + } + (Primitive::I8(l), Primitive::I8(r)) => Primitive::I8(l & r), + (Primitive::I8(l), Primitive::Int(r)) => { + Primitive::Int(*l as i128 & r) + } + (Primitive::I8(l), Primitive::U8(r)) => { + Primitive::Int(*l as i128 & *r as i128) + } + (Primitive::I8(l), Primitive::Bool(r)) => { + Primitive::I8(l & if r == &true { 1 } else { 0 }) + } + (Primitive::Int(l), Primitive::U8(r)) => { + Primitive::Int(l & *r as i128) + } + (Primitive::Int(l), Primitive::I8(r)) => { + Primitive::Int(l & *r as i128) + } + (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l & *r), + (Primitive::Int(l), Primitive::Bool(r)) => { + Primitive::Int(l & if r == &true { 1 } else { 0 }) + } + _ => Primitive::Error(format!( + "illegal call to 'bitwise_and' => left: {self} right: {rhs}" + )), + } + } +} + +impl PartialOrd for Primitive { + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + if Arc::ptr_eq(l, r) { + return Some(Ordering::Equal); + } + let l = l + .read() + .expect("PARTIAL_CMP L ERORR: could not acquire lock!"); + + let r = r + .read() + .expect("PARTIAL_CMP R ERORR: could not acquire lock!"); + l.partial_cmp(&r) + } + (Primitive::Ref(l), r) => { + let l = l + .read() + .expect("PARTIAL_CMP L ERORR: could not acquire lock!"); + + l.partial_cmp(r) + } + (l, Primitive::Ref(r)) => { + let r = r + .read() + .expect("PARTIAL_CMP R ERORR: could not acquire lock!"); + + l.partial_cmp(&r) + } + + (Primitive::U8(l), Primitive::U8(r)) => l.partial_cmp(r), + (Primitive::U8(l), Primitive::I8(r)) => (*l as i8).partial_cmp(r), + (Primitive::U8(l), Primitive::Int(r)) => { + (*l as i128).partial_cmp(r) + } + (Primitive::U8(l), Primitive::Double(r)) => { + (*l as f64).partial_cmp(r) + } + + (Primitive::I8(l), Primitive::U8(r)) => l.partial_cmp(&(*r as i8)), + (Primitive::I8(l), Primitive::I8(r)) => (*l).partial_cmp(r), + (Primitive::I8(l), Primitive::Int(r)) => { + (*l as i128).partial_cmp(r) + } + (Primitive::I8(l), Primitive::Double(r)) => { + (*l as f64).partial_cmp(r) + } + + (Primitive::Int(l), Primitive::Int(r)) => l.partial_cmp(r), + (Primitive::Int(l), Primitive::U8(r)) => { + l.partial_cmp(&(*r as i128)) + } + (Primitive::Int(l), Primitive::I8(r)) => { + l.partial_cmp(&(*r as i128)) + } + (Primitive::Int(l), Primitive::Double(r)) => { + (*l as f64).partial_cmp(r) + } + + (Primitive::Double(l), Primitive::Int(r)) => { + l.partial_cmp(&(*r as f64)) + } + (Primitive::Double(l), Primitive::U8(r)) => { + l.partial_cmp(&(*r as f64)) + } + (Primitive::Double(l), Primitive::I8(r)) => { + l.partial_cmp(&(*r as f64)) + } + (Primitive::Double(l), Primitive::Double(r)) => l.partial_cmp(r), + + (Primitive::Bool(a), Primitive::Bool(b)) => a.partial_cmp(b), + (l @ Primitive::Bool(_), r) => l.partial_cmp(&(r.to_bool())), + + (Primitive::String(l), Primitive::String(r)) => l.partial_cmp(r), + (Primitive::Unit, Primitive::Unit) => Some(Ordering::Equal), + (Primitive::Array(l), Primitive::Array(r)) => l.partial_cmp(r), + ( + Primitive::Function { parameters: pl, exprs: el }, + Primitive::Function { parameters: pr, exprs: er }, + ) => { + if pl.eq(pr) + && el.iter().zip(er.iter()).filter(|&(a, b)| a != b).count() + == 0 + { + Some(Ordering::Equal) + } else { + None + } + } + (Primitive::Error(l), Primitive::Error(r)) => l.partial_cmp(r), + (Primitive::Null, Primitive::Null) => Some(Ordering::Equal), + (Primitive::EarlyReturn(l), Primitive::EarlyReturn(r)) => { + l.partial_cmp(r) + } + (Primitive::EarlyReturn(l), a) => l.as_ref().partial_cmp(a), + (l, Primitive::EarlyReturn(r)) => l.partial_cmp(r), + (Primitive::Struct(l), Primitive::Struct(r)) => { + if l.eq(r) { + Some(Ordering::Equal) + } else { + None + } + } + (Primitive::NativeLibrary { .. }, _) + | (_, Primitive::NativeLibrary { .. }) => None, + (Primitive::NativeFunction(_, _), _) + | (_, Primitive::NativeFunction(_, _)) => None, + (Primitive::Struct(_), _) => None, + (Primitive::Int(_), _) => None, + (Primitive::U8(_), _) => None, + (Primitive::I8(_), _) => None, + (Primitive::Double(_), _) => None, + (Primitive::String(_), _) => None, + (Primitive::NoReturn, _) => None, + (Primitive::Null, _) => None, + (Primitive::Array(_), _) => None, + (Primitive::Error(_), _) => None, + (Primitive::Unit, _) => None, + (Primitive::Function { parameters: _, exprs: _ }, _) => None, + } + } +} + +impl TypeOf for Primitive { + fn type_of(&self) -> Self { + match self { + Primitive::Ref(l) => { + let l = + l.read().expect("TYPE_OF ERROR: could not acquire lock!"); + l.type_of() + } + Primitive::U8(_) => Primitive::String("u8".to_string()), + Primitive::I8(_) => Primitive::String("i8".to_string()), + Primitive::Int(_) => Primitive::String("int".to_string()), + Primitive::Bool(_) => Primitive::String("bool".to_string()), + Primitive::Null => Primitive::String("null".to_string()), + Primitive::Double(_) => Primitive::String("double".to_string()), + Primitive::String(_) => Primitive::String("string".to_string()), + Primitive::Array(_) => Primitive::String("array".to_string()), + Primitive::Error(_) => Primitive::String("error".to_string()), + Primitive::NativeLibrary(_) => { + Primitive::String("nativeLibrary".into()) + } + Primitive::Function { .. } | Primitive::NativeFunction(_, _) => { + Primitive::String("function".to_string()) + } + Primitive::Struct(_) => Primitive::String("struct".to_string()), + Primitive::Unit => Primitive::String("unit".to_string()), + Primitive::NoReturn => Primitive::String("!".to_string()), + Primitive::EarlyReturn(v) => v.type_of(), + } + } +} + +impl Array for Primitive { + fn index_at(&self, rhs: &Primitive) -> Primitive { + match (self, rhs) { + (Primitive::Ref(l), Primitive::Ref(r)) => { + let l = l + .read() + .expect("INDEX_AT L ERORR: could not acquire lock!"); + + let r = r + .read() + .expect("INDEX_AT R ERORR: could not acquire lock!"); + l.index_at(&r) + } + (Primitive::Ref(l), r) => { + let l = l + .read() + .expect("INDEX_AT L ERORR: could not acquire lock!"); + + l.index_at(r) + } + (l, Primitive::Ref(r)) => { + let r = r + .read() + .expect("INDEX_AT R ERORR: could not acquire lock!"); + + l.index_at(&r) + } + (Primitive::Array(arr), Primitive::Int(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < arr.len() { + arr[idx].clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::Array(arr), Primitive::U8(idx)) => { + let idx = *idx as usize; + if idx < arr.len() { + arr[idx].clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::Array(arr), Primitive::I8(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < arr.len() { + arr[idx].clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::String(s), Primitive::Int(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < s.len() { + let s: String = s.chars().skip(idx).take(1).collect(); + Primitive::String(s) + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::String(s), Primitive::U8(idx)) => { + let idx = *idx as usize; + if idx < s.len() { + let s: String = s.chars().skip(idx).take(1).collect(); + Primitive::String(s) + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::String(s), Primitive::I8(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < s.len() { + let s: String = s.chars().skip(idx).take(1).collect(); + Primitive::String(s) + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::Struct(struc), Primitive::String(key)) => { + if let Some(p) = struc.get(key) { + p.clone() + } else { + Primitive::Null + } + } + (key, value) => Primitive::Error(format!( + "illegal access to array!!! {key} => {value}" + )), + } + } + + fn len(&self) -> Primitive { + match self { + Primitive::Ref(l) => { + let l = l.read().expect("LEN ERROR: could not acquire lock!"); + l.len() + } + Primitive::String(s) => Primitive::Int(s.len() as i128), + Primitive::Array(a) => Primitive::Int(a.len() as i128), + Primitive::Struct(s) => Primitive::Int(s.len() as i128), + _ => Primitive::Error(format!( + "call to len() on a non array value => {self}" + )), + } + } + + fn swap_mem( + &mut self, + rhs: &mut Primitive, + index: &Primitive, + ) -> Primitive { + match (self, index) { + // FIXME this might be more complex than that + // RHS could be equal to self + // using Arc::ptr_eq(&arc1, &arc2) might be safer + (Primitive::Ref(l), Primitive::Ref(r)) => { + let mut l = l + .write() + .expect("SWAP_MEM L ERORR: could not acquire lock!"); + + let r = r + .read() + .expect("SWAP_MEM R ERORR: could not acquire lock!"); + l.swap_mem(rhs, &r) + } + (Primitive::Ref(l), _) => { + let mut l = l + .write() + .expect("SWAP_MEM L ERORR: could not acquire lock!"); + + l.swap_mem(rhs, index) + } + (l, Primitive::Ref(index)) => { + let index = index + .read() + .expect("SWAP_MEM R ERORR: could not acquire lock!"); + + l.swap_mem(rhs, &index) + } + (Primitive::Array(arr), Primitive::Int(idx)) if idx >= &0 => { + let idx = *idx as usize; + if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) + && idx < arr.len() + { + std::mem::swap(&mut arr[idx], rhs); + arr[idx].clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + + (Primitive::Array(arr), Primitive::U8(idx)) => { + let idx = *idx as usize; + if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) + && idx < arr.len() + { + std::mem::swap(&mut arr[idx], rhs); + arr[idx].clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::Array(arr), Primitive::I8(idx)) if idx >= &0 => { + let idx = *idx as usize; + if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) + && idx < arr.len() + { + std::mem::swap(&mut arr[idx], rhs); + arr[idx].clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::Struct(s), Primitive::String(k)) => { + if s.contains_key(k) { + std::mem::swap(s.get_mut(k).unwrap(), rhs); + } else { + s.insert(k.clone(), rhs.clone()); + } + s[k].clone() + } + (Primitive::String(s), Primitive::Int(idx)) if idx >= &0 => { + let idx = *idx as usize; + if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) + && idx < s.len() + { + s.remove(idx); + s.insert_str(idx, &rhs.to_string()); + rhs.clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::String(s), Primitive::I8(idx)) if idx >= &0 => { + let idx = *idx as usize; + if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) + && idx < s.len() + { + s.remove(idx); + s.insert_str(idx, &rhs.to_string()); + rhs.clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + (Primitive::String(s), Primitive::U8(idx)) => { + let idx = *idx as usize; + if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) + && idx < s.len() + { + s.remove(idx); + s.insert_str(idx, &rhs.to_string()); + rhs.clone() + } else { + Primitive::Error("index out of range".to_string()) + } + } + _ => Primitive::Error("invalid call to swap_mem()".to_string()), + } + } + + fn remove(&mut self, key: &Primitive) -> anyhow::Result<()> { + match (self, key) { + // FIXME this might be more complex than that + // RHS could be equal to self + // using Arc::ptr_eq(&arc1, &arc2) might be safer + (Primitive::Ref(l), Primitive::Ref(r)) => { + let mut l = + l.write().expect("REMOVE L ERORR: could not acquire lock!"); + + let r = + r.read().expect("REMOVE R ERORR: could not acquire lock!"); + l.remove(&r) + } + (Primitive::Ref(l), _) => { + let mut l = + l.write().expect("REMOVE L ERORR: could not acquire lock!"); + + l.remove(key) + } + (l, Primitive::Ref(index)) => { + let index = index + .read() + .expect("REMOVE R ERORR: could not acquire lock!"); + + l.remove(&index) + } + (Primitive::Array(arr), Primitive::Int(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < arr.len() { + arr.remove(idx); + Ok(()) + } else { + Err(anyhow::Error::msg("index out of range")) + } + } + (Primitive::Array(arr), Primitive::U8(idx)) => { + let idx = *idx as usize; + if idx < arr.len() { + arr.remove(idx); + Ok(()) + } else { + Err(anyhow::Error::msg("index out of range")) + } + } + (Primitive::Array(arr), Primitive::I8(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < arr.len() { + arr.remove(idx); + Ok(()) + } else { + Err(anyhow::Error::msg("index out of range")) + } + } + + (Primitive::String(s), Primitive::U8(idx)) => { + let idx = *idx as usize; + if idx < s.len() { + s.remove(idx); + Ok(()) + } else { + Err(anyhow::Error::msg("index out of range")) + } + } + (Primitive::String(s), Primitive::I8(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < s.len() { + s.remove(idx); + Ok(()) + } else { + Err(anyhow::Error::msg("index out of range")) + } + } + (Primitive::String(s), Primitive::Int(idx)) if idx >= &0 => { + let idx = *idx as usize; + if idx < s.len() { + s.remove(idx); + Ok(()) + } else { + Err(anyhow::Error::msg("index out of range")) + } + } + (Primitive::Struct(struc), Primitive::String(key)) => { + if let Some(_p) = struc.remove(key) { + Ok(()) + } else { + Err(anyhow::Error::msg("key doesn't exist")) + } + } + _ => Err(anyhow::Error::msg("illegal access to array!!!")), + } + } + + fn is_empty(&self) -> Primitive { + match self.len() { + Primitive::Int(n) => Primitive::Bool(n == 0), + e => Primitive::Error(format!("err: {e}")), + } + } +} +impl PartialEq for Primitive { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Ref(l0), Self::Ref(r0)) => { + if Arc::ptr_eq(l0, r0) { + return true; + } + + let l0 = + l0.read().expect("EQ L ERORR: could not acquire lock!"); + + let r = r0.read().expect("EQ R ERORR: could not acquire lock!"); + l0.eq(&r) + } + (Primitive::Ref(l), _) => { + let l = l.read().expect("EQ L ERORR: could not acquire lock!"); + l.eq(other) + } + (_, Primitive::Ref(r)) => { + let r = r.read().expect("EQ R ERORR: could not acquire lock!"); + self.eq(&r) + } + (Self::U8(l0), Self::U8(r0)) => l0 == r0, + (Self::I8(l0), Self::I8(r0)) => l0 == r0, + (Self::Int(l0), Self::Int(r0)) => l0 == r0, + (Self::Bool(l0), Self::Bool(r0)) => l0 == r0, + (Self::Double(l0), Self::Double(r0)) => l0 == r0, + (Self::String(l0), Self::String(r0)) => l0 == r0, + (Self::Array(l0), Self::Array(r0)) => l0 == r0, + (Self::Struct(l0), Self::Struct(r0)) => l0 == r0, + (Self::Error(l0), Self::Error(r0)) => l0 == r0, + ( + Self::Function { parameters: l_parameters, exprs: l_exprs }, + Self::Function { parameters: r_parameters, exprs: r_exprs }, + ) => l_parameters == r_parameters && l_exprs == r_exprs, + (Self::EarlyReturn(l0), Self::EarlyReturn(r0)) => l0 == r0, + _ => { + core::mem::discriminant(self) == core::mem::discriminant(other) + } + } + } +} +impl DisplayHex for Primitive { + fn to_hex(&self) -> Self { + match self { + Primitive::U8(u) => Primitive::String(format!("{u:#x}")), + Primitive::I8(u) => Primitive::String(format!("{u:#x}")), + Primitive::Int(u) => Primitive::String(format!("{u:#x}")), + + Primitive::Ref(l0) => { + let l0 = + l0.read().expect("EQ L ERORR: could not acquire lock!"); + l0.to_hex() + } + Primitive::Double(d) => { + let bytes = d.to_ne_bytes(); + let u = i64::from_ne_bytes(bytes); + Primitive::String(format!("{u:#x}")) + } + + e => Primitive::Error(format!("could not convert to_hex: {e}")), + } + } +} +impl DisplayBinary for Primitive { + fn to_binary(&self) -> Self { + match self { + Primitive::U8(u) => Primitive::String(format!("{u:#b}")), + Primitive::I8(u) => Primitive::String(format!("{u:#b}")), + Primitive::Int(u) => Primitive::String(format!("{u:#b}")), + + Primitive::Ref(l0) => { + let l0 = + l0.read().expect("EQ L ERORR: could not acquire lock!"); + l0.to_hex() + } + Primitive::Double(d) => { + let bytes = d.to_ne_bytes(); + let u = i64::from_ne_bytes(bytes); + Primitive::String(format!("{u:#b}")) + } + + e => Primitive::Error(format!("could not convert to_binary: {e}")), + } + } +} +// endregion + +#[cfg(test)] +mod test { + use super::Add; + + use super::Primitive; + + #[test] + fn test_add_valid() { + let l = Primitive::Int(1); + let r = Primitive::Int(2); + assert_eq!(l.add(&r), Primitive::Int(3)); + + let l = Primitive::Int(1); + let r = Primitive::Double(2.); + assert_eq!(l.add(&r), Primitive::Double(3.)); + + let l = Primitive::Double(1.); + let r = Primitive::Int(2); + assert_eq!(l.add(&r), Primitive::Double(3.)); + + let l = Primitive::Double(1.); + let r = Primitive::Double(2.); + assert_eq!(l.add(&r), Primitive::Double(3.)); + } +} diff --git a/adana-script/Cargo.toml b/adana-script/Cargo.toml new file mode 100644 index 0000000..5fba23e --- /dev/null +++ b/adana-script/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "adana-script" +version = { workspace = true } +edition = "2021" +exclude = ["static_binaries/", "dynamic_lib/", "examples/", "file_tests/"] +description.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true +license.workspace = true + +[dependencies] +#adana-script-core = { git = "https://github.com/nbittich/adana-script-core.git", branch = "feature/bitwise-and-new-ints" } +nom.workspace = true +adana-script-core.workspace = true +anyhow.workspace = true +slab_tree.workspace = true + +[dev-dependencies] +# some test must run sequentially. +# if library is broken, alternative is: cargo test -- --test-threads 1 +serial_test.workspace = true diff --git a/dynamic_lib/example_lib_src/.gitignore b/adana-script/dynamic_lib/example_lib_src/.gitignore similarity index 100% rename from dynamic_lib/example_lib_src/.gitignore rename to adana-script/dynamic_lib/example_lib_src/.gitignore diff --git a/dynamic_lib/example_lib_src/Cargo.lock b/adana-script/dynamic_lib/example_lib_src/Cargo.lock similarity index 100% rename from dynamic_lib/example_lib_src/Cargo.lock rename to adana-script/dynamic_lib/example_lib_src/Cargo.lock diff --git a/dynamic_lib/example_lib_src/Cargo.toml b/adana-script/dynamic_lib/example_lib_src/Cargo.toml similarity index 100% rename from dynamic_lib/example_lib_src/Cargo.toml rename to adana-script/dynamic_lib/example_lib_src/Cargo.toml diff --git a/dynamic_lib/example_lib_src/src/lib.rs b/adana-script/dynamic_lib/example_lib_src/src/lib.rs similarity index 100% rename from dynamic_lib/example_lib_src/src/lib.rs rename to adana-script/dynamic_lib/example_lib_src/src/lib.rs diff --git a/dynamic_lib/libplugin_example.so b/adana-script/dynamic_lib/libplugin_example.so similarity index 100% rename from dynamic_lib/libplugin_example.so rename to adana-script/dynamic_lib/libplugin_example.so diff --git a/examples/example1.adana b/adana-script/examples/example1.adana similarity index 100% rename from examples/example1.adana rename to adana-script/examples/example1.adana diff --git a/examples/example2.adana b/adana-script/examples/example2.adana similarity index 100% rename from examples/example2.adana rename to adana-script/examples/example2.adana diff --git a/file_tests/includes/deep/deep.adana b/adana-script/file_tests/includes/deep/deep.adana similarity index 100% rename from file_tests/includes/deep/deep.adana rename to adana-script/file_tests/includes/deep/deep.adana diff --git a/file_tests/includes/init.adana b/adana-script/file_tests/includes/init.adana similarity index 100% rename from file_tests/includes/init.adana rename to adana-script/file_tests/includes/init.adana diff --git a/file_tests/includes/init2.adana b/adana-script/file_tests/includes/init2.adana similarity index 100% rename from file_tests/includes/init2.adana rename to adana-script/file_tests/includes/init2.adana diff --git a/file_tests/includes/reverse.adana b/adana-script/file_tests/includes/reverse.adana similarity index 100% rename from file_tests/includes/reverse.adana rename to adana-script/file_tests/includes/reverse.adana diff --git a/file_tests/name.txt b/adana-script/file_tests/name.txt similarity index 100% rename from file_tests/name.txt rename to adana-script/file_tests/name.txt diff --git a/file_tests/sort.adana b/adana-script/file_tests/sort.adana similarity index 100% rename from file_tests/sort.adana rename to adana-script/file_tests/sort.adana diff --git a/file_tests/string.adana b/adana-script/file_tests/string.adana similarity index 100% rename from file_tests/string.adana rename to adana-script/file_tests/string.adana diff --git a/file_tests/test1.adana b/adana-script/file_tests/test1.adana similarity index 100% rename from file_tests/test1.adana rename to adana-script/file_tests/test1.adana diff --git a/file_tests/test2.adana b/adana-script/file_tests/test2.adana similarity index 100% rename from file_tests/test2.adana rename to adana-script/file_tests/test2.adana diff --git a/file_tests/test_array.adana b/adana-script/file_tests/test_array.adana similarity index 100% rename from file_tests/test_array.adana rename to adana-script/file_tests/test_array.adana diff --git a/file_tests/test_fizzbuzz.adana b/adana-script/file_tests/test_fizzbuzz.adana similarity index 100% rename from file_tests/test_fizzbuzz.adana rename to adana-script/file_tests/test_fizzbuzz.adana diff --git a/file_tests/test_fizzbuzz_else.adana b/adana-script/file_tests/test_fizzbuzz_else.adana similarity index 100% rename from file_tests/test_fizzbuzz_else.adana rename to adana-script/file_tests/test_fizzbuzz_else.adana diff --git a/file_tests/test_fn.adana b/adana-script/file_tests/test_fn.adana similarity index 100% rename from file_tests/test_fn.adana rename to adana-script/file_tests/test_fn.adana diff --git a/file_tests/test_if_else.adana b/adana-script/file_tests/test_if_else.adana similarity index 100% rename from file_tests/test_if_else.adana rename to adana-script/file_tests/test_if_else.adana diff --git a/file_tests/test_multiline.adana b/adana-script/file_tests/test_multiline.adana similarity index 100% rename from file_tests/test_multiline.adana rename to adana-script/file_tests/test_multiline.adana diff --git a/file_tests/test_nested.adana b/adana-script/file_tests/test_nested.adana similarity index 100% rename from file_tests/test_nested.adana rename to adana-script/file_tests/test_nested.adana diff --git a/file_tests/test_recursion.adana b/adana-script/file_tests/test_recursion.adana similarity index 100% rename from file_tests/test_recursion.adana rename to adana-script/file_tests/test_recursion.adana diff --git a/file_tests/test_simple_array.adana b/adana-script/file_tests/test_simple_array.adana similarity index 100% rename from file_tests/test_simple_array.adana rename to adana-script/file_tests/test_simple_array.adana diff --git a/file_tests/test_string_arr.adana b/adana-script/file_tests/test_string_arr.adana similarity index 100% rename from file_tests/test_string_arr.adana rename to adana-script/file_tests/test_string_arr.adana diff --git a/file_tests/testfib.adana b/adana-script/file_tests/testfib.adana similarity index 100% rename from file_tests/testfib.adana rename to adana-script/file_tests/testfib.adana diff --git a/src/adana_script/ast.rs b/adana-script/src/ast.rs similarity index 98% rename from src/adana_script/ast.rs rename to adana-script/src/ast.rs index e4e5f86..d743ada 100644 --- a/src/adana_script/ast.rs +++ b/adana-script/src/ast.rs @@ -239,8 +239,7 @@ pub fn to_ast( Ok(curr_node_id) } else { Err(anyhow::Error::msg(format!( - "{} invalid expression! {op_pos:?}", - nu_ansi_term::Color::Red.paint("AST ERROR:") + "AST ERROR: invalid expression! {op_pos:?}", ))) } } @@ -268,8 +267,7 @@ pub fn to_ast( curr_node_id, ), Value::ImplicitMultiply(value) => Err(anyhow::Error::msg(format!( - "{} invalid implicit multiplier, unreachable branch: {value:?}", - nu_ansi_term::Color::Red.paint("AST BUG:"), + "AST BUG: invalid implicit multiplier, unreachable branch: {value:?}", ))), Value::Decimal(num) => append_to_current_and_return( @@ -432,8 +430,7 @@ pub fn to_ast( // for assignment // We need Primitive::Ref to make it happen Err(anyhow::Error::msg(format!( - "{} invalid variable expression {name:?} => {expr:?}", - nu_ansi_term::Color::Red.paint("AST ERROR:"), + "AST ERROR: invalid variable expression {name:?} => {expr:?}", ))) }?; diff --git a/src/adana_script/compute.rs b/adana-script/src/compute.rs similarity index 99% rename from src/adana_script/compute.rs rename to adana-script/src/compute.rs index 7de0a19..badb829 100644 --- a/src/adana_script/compute.rs +++ b/adana-script/src/compute.rs @@ -1,5 +1,4 @@ use anyhow::{Context, Error}; -use nu_ansi_term::Color::Red; use slab_tree::{NodeRef, Tree}; use std::{ borrow::Borrow, @@ -8,7 +7,7 @@ use std::{ sync::Arc, }; -use crate::{adana_script::parser::parse_instructions, prelude::BTreeMap}; +use crate::{parser::parse_instructions, prelude::BTreeMap}; use super::{ast::to_ast, require_dynamic_lib::require_dynamic_lib}; use adana_script_core::{ @@ -526,8 +525,8 @@ fn compute_recur( _ => { return Err(anyhow::format_err!( - "COMPUTE: illegal array access! {index:?}" - )) + "COMPUTE: illegal array access! {index:?}" + )) } }; @@ -955,7 +954,7 @@ fn compute_instructions( let mut scoped_ctx = ctx.clone(); 'while_loop: while matches!( - compute_lazy(*cond.clone(), &mut scoped_ctx, shared_lib)?, + compute_lazy(*cond.clone(), &mut scoped_ctx, shared_lib,)?, Primitive::Bool(true) ) { for instruction in &exprs { @@ -1046,8 +1045,7 @@ pub fn compute( ) -> anyhow::Result { let (rest, instructions) = parse_instructions(s).map_err(|e| { anyhow::Error::msg(format!( - "{} could not parse instructions. \n{e:?} => {e}", - Red.paint("PARSER ERROR:") + "PARSER ERROR: could not parse instructions. \n{e:?} => {e}", )) })?; @@ -1058,10 +1056,7 @@ pub fn compute( anyhow::ensure!( rest.trim().is_empty(), - format!( - "{} rest is not empty! {instructions:?} => {rest}", - Red.paint("PARSING ERROR:") - ) + format!("PARSING ERROR: rest is not empty! {instructions:?} => {rest}",) ); compute_instructions(instructions, ctx, shared_lib) diff --git a/src/adana_script/mod.rs b/adana-script/src/lib.rs similarity index 75% rename from src/adana_script/mod.rs rename to adana-script/src/lib.rs index 2b1bd80..1c2fc6d 100644 --- a/src/adana_script/mod.rs +++ b/adana-script/src/lib.rs @@ -1,32 +1,30 @@ mod ast; mod compute; mod parser; +mod prelude; mod require_dynamic_lib; mod string_parser; use std::collections::BTreeMap; use adana_script_core::TreeNodeValue; pub use compute::compute; -use nu_ansi_term::Color; use slab_tree::Tree; -use crate::adana_script::ast::to_ast; -use crate::adana_script::parser::parse_instructions; +use crate::ast::to_ast; +use crate::parser::parse_instructions; pub fn print_ast(script: &str) -> anyhow::Result<()> { let (rest, instructions) = parse_instructions(script).map_err(|e| { anyhow::Error::msg(format!( - "{} could not parse instructions. {e}", - Color::Red.paint("PRINT AST ERROR:") + "PRINT AST ERROR: could not parse instructions. {e}", )) })?; anyhow::ensure!( rest.trim().is_empty(), format!( - "{} rest is not empty! {instructions:#?} => {rest}", - Color::Red.paint("PRINT AST ERROR:") + "PRINT AST ERROR: rest is not empty! {instructions:#?} => {rest}", ) ); diff --git a/src/adana_script/parser.rs b/adana-script/src/parser.rs similarity index 97% rename from src/adana_script/parser.rs rename to adana-script/src/parser.rs index f822b19..55cda74 100644 --- a/src/adana_script/parser.rs +++ b/adana-script/src/parser.rs @@ -3,19 +3,19 @@ use nom::{ error::{Error, ErrorKind}, }; -use crate::{ - prelude::{ - all_consuming, alt, delimited, double, many0, many1, map, map_parser, - multispace0, one_of, opt, pair, peek, preceded, recognize_float, rest, - separated_list0, separated_list1, separated_pair, tag, take_until, - take_while1, terminated, tuple, verify, Res, I128, I8, U8, - }, - reserved_keywords::check_reserved_keyword, +use crate::prelude::{ + all_consuming, alt, delimited, double, many0, many1, map, map_parser, + multispace0, one_of, opt, pair, peek, preceded, recognize_float, rest, + separated_list0, separated_list1, separated_pair, tag, take_until, + take_while1, terminated, tuple, verify, Res, I128, I8, U8, }; use super::string_parser::parse_escaped_string; -use adana_script_core::constants::{ - BREAK, DROP, ELSE, FOR, IF, IN, MULTILINE, NULL, RETURN, STRUCT, WHILE, +use adana_script_core::{ + constants::{ + BREAK, DROP, ELSE, FOR, IF, IN, MULTILINE, NULL, RETURN, STRUCT, WHILE, + }, + FORBIDDEN_VARIABLE_NAME, }; use adana_script_core::{BuiltInFunctionType, MathConstants, Operator, Value}; @@ -212,7 +212,7 @@ fn parse_variable_str(s: &str) -> Res<&str> { && s.chars().filter(|c| c == &'&').count() <= 1 }), verify(all_consuming(allowed_values), |s: &str| { - !check_reserved_keyword(&[s]) + !default_check_reserved_keywords(&[s]) }), )(s) } @@ -874,3 +874,8 @@ pub fn parse_instructions(instructions: &str) -> Res> { opt(comments), )(instructions) } +fn default_check_reserved_keywords(aliases: &[&str]) -> bool { + FORBIDDEN_VARIABLE_NAME + .iter() + .any(|c| aliases.iter().any(|al| al.eq_ignore_ascii_case(c))) +} diff --git a/adana-script/src/prelude.rs b/adana-script/src/prelude.rs new file mode 100644 index 0000000..8e279f5 --- /dev/null +++ b/adana-script/src/prelude.rs @@ -0,0 +1,20 @@ +pub use nom::{ + branch::alt, + bytes::complete::{tag, take_until, take_while1}, + character::complete::{ + i128 as I128, i8 as I8, multispace0, one_of, u8 as U8, + }, + combinator::{all_consuming, map, map_parser, opt, peek, rest, verify}, + multi::{many0, many1, separated_list0, separated_list1}, + number::complete::{double, recognize_float}, + sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, + IResult, +}; + +pub use anyhow::Context; + +pub type Res<'a, T> = IResult<&'a str, T>; + +pub use std::collections::BTreeMap; + +//pub use serde::{Deserialize, Serialize}; diff --git a/src/adana_script/require_dynamic_lib.rs b/adana-script/src/require_dynamic_lib.rs similarity index 100% rename from src/adana_script/require_dynamic_lib.rs rename to adana-script/src/require_dynamic_lib.rs diff --git a/src/adana_script/string_parser.rs b/adana-script/src/string_parser.rs similarity index 100% rename from src/adana_script/string_parser.rs rename to adana-script/src/string_parser.rs diff --git a/src/adana_script/tests/bitwise.rs b/adana-script/src/tests/bitwise.rs similarity index 96% rename from src/adana_script/tests/bitwise.rs rename to adana-script/src/tests/bitwise.rs index 53aeaae..84f6069 100644 --- a/src/adana_script/tests/bitwise.rs +++ b/adana-script/src/tests/bitwise.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; -use crate::adana_script::compute; +use crate::compute; #[test] fn bitwise_or_test() { @@ -95,7 +95,7 @@ fn test_left_shift() { let r = compute(r#"0 << 0"#, &mut ctx, "N/A").unwrap(); assert_eq!(r, Primitive::Int(0)); // FIXME probably need to use a library for this - // let r = compute(r#"127 <<135"#, &mut ctx, "N/A").unwrap(); + // let r = compute(r#"127 <<135"#, &mut ctx, "N/A", ).unwrap(); // assert_eq!(r, Primitive::Int((127u64 << 135u64) as i128)); let r = compute(r#"127<<9"#, &mut ctx, "N/A").unwrap(); assert_eq!(r, Primitive::Int(127 << 9)); @@ -118,7 +118,7 @@ fn test_right_shift() { let r = compute(r#"0 >> 0"#, &mut ctx, "N/A").unwrap(); assert_eq!(r, Primitive::Int(0)); // FIXME probably need to use a library for this - // let r = compute(r#"127 >>135"#, &mut ctx, "N/A").unwrap(); + // let r = compute(r#"127 >>135"#, &mut ctx, "N/A", ).unwrap(); // assert_eq!(r, Primitive::Int((127u64 >> 135u64) as i128)); let r = compute(r#"127>>9"#, &mut ctx, "N/A").unwrap(); assert_eq!(r, Primitive::Int(127 >> 9)); diff --git a/src/adana_script/tests/builtin.rs b/adana-script/src/tests/builtin.rs similarity index 86% rename from src/adana_script/tests/builtin.rs rename to adana-script/src/tests/builtin.rs index 3399dbf..e4a3829 100644 --- a/src/adana_script/tests/builtin.rs +++ b/adana-script/src/tests/builtin.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::Primitive; #[test] fn test_builtin_to_int() { @@ -93,42 +93,42 @@ fn test_type_of() { ); assert_eq!( Primitive::String("int".to_string()), - compute(r#"type_of(x)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(x)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("double".to_string()), - compute(r#"type_of(y)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(y)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("function".to_string()), - compute(r#"type_of(z)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(z)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("error".to_string()), - compute(r#"type_of(a)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(a)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("array".to_string()), - compute(r#"type_of(b)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(b)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("bool".to_string()), - compute(r#"type_of(c)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(c)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("string".to_string()), - compute(r#"type_of(d)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(d)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("unit".to_string()), - compute(r#"type_of(e)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(e)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("!".to_string()), - compute(r#"type_of(f)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(f)"#, &mut ctx, "N/A",).unwrap() ); assert_eq!( Primitive::String("int".to_string()), - compute(r#"type_of(g)"#, &mut ctx, "N/A").unwrap() + compute(r#"type_of(g)"#, &mut ctx, "N/A",).unwrap() ); } diff --git a/src/adana_script/tests/dynload.rs b/adana-script/src/tests/dynload.rs similarity index 98% rename from src/adana_script/tests/dynload.rs rename to adana-script/src/tests/dynload.rs index af57613..8985505 100644 --- a/src/adana_script/tests/dynload.rs +++ b/adana-script/src/tests/dynload.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; use serial_test::serial; -use crate::adana_script::compute; +use crate::compute; #[test] #[serial] diff --git a/src/adana_script/tests/examples.rs b/adana-script/src/tests/examples.rs similarity index 90% rename from src/adana_script/tests/examples.rs rename to adana-script/src/tests/examples.rs index b4ba9ac..56d3c89 100644 --- a/src/adana_script/tests/examples.rs +++ b/adana-script/src/tests/examples.rs @@ -1,12 +1,12 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::Primitive::*; #[test] fn test_example1() { let mut ctx = BTreeMap::new(); - let expr = include_str!("../../../examples/example1.adana"); + let expr = include_str!("../../examples/example1.adana"); let res = compute(expr, &mut ctx, "N/A").unwrap(); @@ -57,11 +57,11 @@ fn test_example1() { #[test] fn test_example2() { let mut ctx = BTreeMap::new(); - let expr = include_str!("../../../examples/example2.adana"); + let expr = include_str!("../../examples/example2.adana"); let res = compute(expr, &mut ctx, "N/A").unwrap(); assert_eq!(res, Array(vec![Int(15), Int(1), Int(11), Int(22)])); assert_eq!( - compute("fun([1])", &mut ctx, "N/A").unwrap(), + compute("fun([1])", &mut ctx, "N/A",).unwrap(), Array(vec![U8(0)]) ); } diff --git a/src/adana_script/tests/foreach.rs b/adana-script/src/tests/foreach.rs similarity index 99% rename from src/adana_script/tests/foreach.rs rename to adana-script/src/tests/foreach.rs index 83991f1..4f9a265 100644 --- a/src/adana_script/tests/foreach.rs +++ b/adana-script/src/tests/foreach.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::Primitive; #[test] @@ -20,7 +20,7 @@ fn simple_foreach() { #[test] fn simple_foreach_string() { - use crate::Primitive::{Array, String}; + use Primitive::{Array, String}; let expr = r#" arr = "Salut le monde j'espère que vous allez bien" total = 0 diff --git a/src/adana_script/tests/funct.rs b/adana-script/src/tests/funct.rs similarity index 99% rename from src/adana_script/tests/funct.rs rename to adana-script/src/tests/funct.rs index 75b8e38..675b453 100644 --- a/src/adana_script/tests/funct.rs +++ b/adana-script/src/tests/funct.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::{primitive::Primitive, Operator, Value}; #[test] diff --git a/src/adana_script/tests/misc.rs b/adana-script/src/tests/misc.rs similarity index 98% rename from src/adana_script/tests/misc.rs rename to adana-script/src/tests/misc.rs index 83e6ec9..64f332b 100644 --- a/src/adana_script/tests/misc.rs +++ b/adana-script/src/tests/misc.rs @@ -1,8 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::parser::parse_instructions as parse_var_expr; +use crate::parser::parse_instructions as parse_var_expr; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::{primitive::Primitive, Operator::*, Value}; #[test] #[should_panic(expected = "invalid expression!")] @@ -132,7 +132,7 @@ fn test_modulo() { compute( "2 * (9 *(5-(1 /2.) ) )² -1 / 5. * 8 - 4 %4", &mut ctx, - "N/A" + "N/A", ) .unwrap() ); @@ -141,7 +141,7 @@ fn test_modulo() { compute( " 2* (9 *(5-(1 /2.) ))² %2 -1 /5. * 8 - 4 %4", &mut ctx, - "N/A" + "N/A", ) .unwrap() ); @@ -157,12 +157,12 @@ fn test_compute() { ); assert_eq!( Primitive::Double(3274.9), - compute("y = 2* (9*(5-(1/2.)))² -1 / 5. * 8 - 4", &mut ctx, "N/A") + compute("y = 2* (9*(5-(1/2.)))² -1 / 5. * 8 - 4", &mut ctx, "N/A",) .unwrap() ); assert_eq!( Primitive::Double(-670.9548307564088), - compute("z = 78/5.-4.5*(9+7^2.5)-12*4+1-8/3.*4-5", &mut ctx, "N/A") + compute("z = 78/5.-4.5*(9+7^2.5)-12*4+1-8/3.*4-5", &mut ctx, "N/A",) .unwrap() ); assert_eq!( @@ -311,7 +311,7 @@ fn test_fn_log() { ); assert_eq!( Primitive::Double(7.906912331577292), - compute("log(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A") + compute("log(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A",) .unwrap() ); } @@ -329,7 +329,7 @@ fn test_fn_ln() { ); assert_eq!( Primitive::Double(18.206338466300664), - compute("ln(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A") + compute("ln(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A",) .unwrap() ); } @@ -362,7 +362,7 @@ fn test_fn_cos() { ); assert_eq!( Primitive::Double(-0.509464138414531), - compute("cos(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A") + compute("cos(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A",) .unwrap() ); } @@ -380,7 +380,7 @@ fn test_fn_tan() { ); assert_eq!( Primitive::Double(-1.6890136606017243), - compute("tan(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A") + compute("tan(abs(-2*(3/4.-12%5 +7^9) --6/12.*4))", &mut ctx, "N/A",) .unwrap() ); } @@ -390,7 +390,7 @@ fn test_extra() { let mut ctx = BTreeMap::new(); assert_eq!( Primitive::Double(44721.45950030539), - compute("sqrt((2*10^9-5*abs(8/9.))) + abs(1/10.)", &mut ctx, "N/A") + compute("sqrt((2*10^9-5*abs(8/9.))) + abs(1/10.)", &mut ctx, "N/A",) .unwrap() ); @@ -406,7 +406,7 @@ fn test_extra() { } ", &mut ctx, - "N/A" + "N/A", ) .unwrap() ); @@ -423,7 +423,7 @@ fn test_extra() { ", &mut ctx, - "N/A" + "N/A", ) .unwrap() ); @@ -440,7 +440,7 @@ fn test_extra() { ", &mut ctx, - "N/A" + "N/A", ) .unwrap() ); diff --git a/src/adana_script/tests/mod.rs b/adana-script/src/tests/mod.rs similarity index 100% rename from src/adana_script/tests/mod.rs rename to adana-script/src/tests/mod.rs diff --git a/src/adana_script/tests/opassign.rs b/adana-script/src/tests/opassign.rs similarity index 97% rename from src/adana_script/tests/opassign.rs rename to adana-script/src/tests/opassign.rs index 039fe4b..cdcd1ae 100644 --- a/src/adana_script/tests/opassign.rs +++ b/adana-script/src/tests/opassign.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; -use crate::adana_script::compute; +use crate::compute; #[test] fn test_op_assign_add() { diff --git a/src/adana_script/tests/range.rs b/adana-script/src/tests/range.rs similarity index 99% rename from src/adana_script/tests/range.rs rename to adana-script/src/tests/range.rs index 7ed2f8c..20c74fb 100644 --- a/src/adana_script/tests/range.rs +++ b/adana-script/src/tests/range.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::Primitive; #[test] fn simple_foreach_range() { diff --git a/src/adana_script/tests/strings.rs b/adana-script/src/tests/strings.rs similarity index 99% rename from src/adana_script/tests/strings.rs rename to adana-script/src/tests/strings.rs index 1ff0cae..d47b16a 100644 --- a/src/adana_script/tests/strings.rs +++ b/adana-script/src/tests/strings.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::Primitive; #[test] diff --git a/src/adana_script/tests/struc.rs b/adana-script/src/tests/struc.rs similarity index 99% rename from src/adana_script/tests/struc.rs rename to adana-script/src/tests/struc.rs index eb33b6e..05499f8 100644 --- a/src/adana_script/tests/struc.rs +++ b/adana-script/src/tests/struc.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use serial_test::serial; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::{primitive::Primitive, Value}; #[test] diff --git a/src/adana_script/tests/test_array.rs b/adana-script/src/tests/test_array.rs similarity index 99% rename from src/adana_script/tests/test_array.rs rename to adana-script/src/tests/test_array.rs index b2256ba..39191df 100644 --- a/src/adana_script/tests/test_array.rs +++ b/adana-script/src/tests/test_array.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use serial_test::serial; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::{ Array as Arr, Primitive::{self, Array, Bool, Double, Int, String as Str, I8, U8}, diff --git a/src/adana_script/tests/test_chaining.rs b/adana-script/src/tests/test_chaining.rs similarity index 99% rename from src/adana_script/tests/test_chaining.rs rename to adana-script/src/tests/test_chaining.rs index 04baf59..cff924b 100644 --- a/src/adana_script/tests/test_chaining.rs +++ b/adana-script/src/tests/test_chaining.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::compute; +use crate::compute; use adana_script_core::primitive::Primitive; #[test] fn complex_struct_array() { diff --git a/src/adana_script/tests/test_drop.rs b/adana-script/src/tests/test_drop.rs similarity index 98% rename from src/adana_script/tests/test_drop.rs rename to adana-script/src/tests/test_drop.rs index 9aea4a6..1c966c2 100644 --- a/src/adana_script/tests/test_drop.rs +++ b/adana-script/src/tests/test_drop.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use adana_script_core::{primitive::Primitive, BuiltInFunctionType, Value}; -use crate::adana_script::compute; +use crate::compute; #[test] fn test_drop_arr_access() { diff --git a/src/adana_script/tests/test_parser.rs b/adana-script/src/tests/test_parser.rs similarity index 99% rename from src/adana_script/tests/test_parser.rs rename to adana-script/src/tests/test_parser.rs index b41b8ab..cf15390 100644 --- a/src/adana_script/tests/test_parser.rs +++ b/adana-script/src/tests/test_parser.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use crate::adana_script::parser::parse_instructions; +use crate::parser::parse_instructions; use adana_script_core::{ BuiltInFunctionType, Operator, Value::{ diff --git a/src/adana_script/tests/test_reference.rs b/adana-script/src/tests/test_reference.rs similarity index 98% rename from src/adana_script/tests/test_reference.rs rename to adana-script/src/tests/test_reference.rs index 804ea4c..a3b9bf3 100644 --- a/src/adana_script/tests/test_reference.rs +++ b/adana-script/src/tests/test_reference.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; -use crate::adana_script::compute; +use crate::compute; #[test] fn test_simple() { diff --git a/src/adana_script/tests/test_scope_ctx.rs b/adana-script/src/tests/test_scope_ctx.rs similarity index 99% rename from src/adana_script/tests/test_scope_ctx.rs rename to adana-script/src/tests/test_scope_ctx.rs index 7fc676d..17b2d1b 100644 --- a/src/adana_script/tests/test_scope_ctx.rs +++ b/adana-script/src/tests/test_scope_ctx.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; -use crate::adana_script::compute; +use crate::compute; #[test] fn test_if_scope_simple() { diff --git a/src/adana_script/tests/tests_file.rs b/adana-script/src/tests/tests_file.rs similarity index 99% rename from src/adana_script/tests/tests_file.rs rename to adana-script/src/tests/tests_file.rs index 2a738d1..c9f87d8 100644 --- a/src/adana_script/tests/tests_file.rs +++ b/adana-script/src/tests/tests_file.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; use serial_test::serial; -use crate::adana_script::compute; +use crate::compute; #[test] #[serial] diff --git a/src/adana_script/tests/unused.rs b/adana-script/src/tests/unused.rs similarity index 99% rename from src/adana_script/tests/unused.rs rename to adana-script/src/tests/unused.rs index c41ddb7..60761fb 100644 --- a/src/adana_script/tests/unused.rs +++ b/adana-script/src/tests/unused.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use adana_script_core::primitive::Primitive; -use crate::adana_script::compute; +use crate::compute; #[test] fn test_simple_unused_array() { diff --git a/adana-shell/Cargo.toml b/adana-shell/Cargo.toml new file mode 100644 index 0000000..9d8666b --- /dev/null +++ b/adana-shell/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "adana" +version.workspace = true +authors.workspace = true +description.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +exclude.workspace = true + +[dependencies] +anyhow.workspace = true +dirs.workspace = true +ctrlc.workspace = true +rustyline.workspace = true +rustyline-derive.workspace = true +nu-ansi-term.workspace = true +env_logger.workspace = true +log.workspace = true +adana-script-core.workspace = true +adana-cache-command.workspace = true +adana-db.workspace = true +adana-script.workspace = true diff --git a/src/args.rs b/adana-shell/src/args.rs similarity index 100% rename from src/args.rs rename to adana-shell/src/args.rs diff --git a/src/editor.rs b/adana-shell/src/editor.rs similarity index 100% rename from src/editor.rs rename to adana-shell/src/editor.rs diff --git a/src/main.rs b/adana-shell/src/main.rs similarity index 94% rename from src/main.rs rename to adana-shell/src/main.rs index 7cdeb38..eb81601 100644 --- a/src/main.rs +++ b/adana-shell/src/main.rs @@ -1,35 +1,34 @@ -mod adana_script; mod args; -mod cache_command; -mod db; mod editor; -mod prelude; -mod reserved_keywords; +use adana_cache_command::{clear_terminal, get_default_cache, process_command}; +use adana_db::{Config, Db, DbOp}; +use adana_script::compute; use adana_script_core::primitive::Primitive; use anyhow::Context; use args::*; -use db::DbOp; use log::debug; +use nu_ansi_term::Color::LightBlue; +use nu_ansi_term::Style; use rustyline::error::ReadlineError; +use std::collections::BTreeMap; use std::{ borrow::Cow, path::{Path, PathBuf}, }; -use prelude::{colors::LightBlue, colors::Style, BTreeMap}; - -use crate::{ - adana_script::compute, - cache_command::{clear_terminal, get_default_cache, process_command}, - db::{Config, Db}, - prelude::get_path_to_shared_libraries, -}; - const VERSION: &str = env!("CARGO_PKG_VERSION"); const RUST_VERSION: &str = std::env!("CARGO_PKG_RUST_VERSION"); const PKG_NAME: &str = env!("CARGO_PKG_NAME"); +const SHARED_LIB_DIR: &str = ".libs_adana"; + +fn get_path_to_shared_libraries() -> Option { + dirs::data_dir().or_else(dirs::home_dir).map(|mut pb| { + pb.push(PathBuf::from(SHARED_LIB_DIR)); + pb + }) +} fn main() -> anyhow::Result<()> { env_logger::init(); diff --git a/release-only-bump.sh b/release-only-bump.sh new file mode 100644 index 0000000..f26bd53 --- /dev/null +++ b/release-only-bump.sh @@ -0,0 +1 @@ +cargo release --no-publish --no-tag --no-push --dependent-version upgrade --execute $1 diff --git a/src/prelude.rs b/src/prelude.rs deleted file mode 100644 index 541f7b4..0000000 --- a/src/prelude.rs +++ /dev/null @@ -1,48 +0,0 @@ -pub use nom::{ - branch::alt, - bytes::complete::{ - tag, tag_no_case, take_till1, take_until, take_until1, take_while, - take_while1, - }, - character::complete::{ - i128 as I128, i8 as I8, multispace0, multispace1, one_of, space1, - u8 as U8, - }, - combinator::{ - all_consuming, cut, map, map_parser, opt, peek, rest, verify, - }, - multi::{many0, many1, separated_list0, separated_list1}, - number::complete::{double, recognize_float}, - sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, - IResult, Parser, -}; - -pub use anyhow::Context; - -pub use log::*; -pub use std::hash::Hash; - -pub use std::process::{Command, Stdio}; - -pub type Res<'a, T> = IResult<&'a str, T>; - -pub use std::sync::Arc; - -pub use std::ops::Deref; -pub use std::sync::{Mutex, MutexGuard}; -pub use std::{collections::BTreeMap, fs::File, io::BufReader, path::PathBuf}; - -pub mod colors { - pub use nu_ansi_term::Color::*; - pub use nu_ansi_term::Style; -} -pub use serde::{Deserialize, Serialize}; - -pub const SHARED_LIB_DIR: &str = ".libs_adana"; - -pub fn get_path_to_shared_libraries() -> Option { - dirs::data_dir().or_else(dirs::home_dir).map(|mut pb| { - pb.push(PathBuf::from(SHARED_LIB_DIR)); - pb - }) -} diff --git a/src/reserved_keywords.rs b/src/reserved_keywords.rs deleted file mode 100644 index 5ea2e53..0000000 --- a/src/reserved_keywords.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::cache_command::CacheCommand; - -use adana_script_core::{constants::*, Operator}; -pub const CACHE_COMMAND_DOC: &[(&[&str], &str)] = CacheCommand::doc(); - -pub const FORBIDDEN_VARIABLE_NAME: &[&str] = &[ - TRUE, - FALSE, - TAU, - IF, - PI, - PRINT_LN, - PRINT, - LENGTH, - EULER_NUMBER, - ABS, - LOG, - TO_INT, - TO_DOUBLE, - TO_HEX, - TO_BINARY, - TO_STRING, - EVAL, - TO_BOOL, - SQRT, - BREAK, - NULL, - FOR, - IN, - DROP, - //READ_LINES, - RETURN, - LN, - SIN, - COS, - TYPE_OF, - TAN, - INCLUDE, - WHILE, - ELSE, - REQUIRE, - MULTILINE, - STRUCT, - Operator::Add.as_str(), - Operator::Subtr.as_str(), - Operator::Div.as_str(), - Operator::Mult.as_str(), - Operator::Pow.as_str(), - Operator::Pow2.as_str(), - Operator::Pow3.as_str(), - Operator::Not.as_str(), - Operator::Mod.as_str(), - Operator::Less.as_str(), - Operator::Greater.as_str(), - Operator::LessOrEqual.as_str(), - Operator::GreaterOrEqual.as_str(), - Operator::Equal.as_str(), - Operator::NotEqual.as_str(), - Operator::And.as_str(), - Operator::Or.as_str(), - Operator::BitwiseNot.as_str(), - Operator::BitwiseAnd.as_str(), - Operator::BitwiseOr.as_str(), - Operator::BitwiseXor.as_str(), - Operator::BitwiseLShift.as_str(), - Operator::BitwiseRShift.as_str(), -]; - -pub fn check_reserved_keyword(aliases: &[&str]) -> bool { - CACHE_COMMAND_DOC - .iter() - .flat_map(|c| c.0.iter()) - .chain(FORBIDDEN_VARIABLE_NAME.iter()) - .any(|c| aliases.iter().any(|al| al.eq_ignore_ascii_case(c))) -}