From 30d94536a9fb1b59f6752ecb4954e9a84bf57fb9 Mon Sep 17 00:00:00 2001 From: rus07tam Date: Wed, 6 May 2026 12:21:06 +0300 Subject: [PATCH] release 0.1.0 --- .gitignore | 3 + Cargo.lock | 1217 +++++++++++++++++++++++++++++++++ Cargo.toml | 40 ++ LICENSE | 24 + README.md | 329 +++++++++ benchmarks/bench.ps1 | 17 + benchmarks/bench.sh | 18 + benchmarks/case1/main.owa | 8 + benchmarks/case1/main.py | 9 + benchmarks/case1/no_owu.owa | 8 + benchmarks/case1/result.md | 5 + flake.lock | 175 +++++ flake.nix | 48 ++ modules/core/assert.owa | 17 + modules/core/ast.owa | 10 + modules/core/branch.owa | 12 + modules/core/cmp.owa | 25 + modules/core/error.owa | 22 + modules/core/ffi.owa | 32 + modules/core/lambda.owa | 8 + modules/core/loop.owa | 23 + modules/core/main.owa | 25 + modules/core/math.owa | 14 + modules/core/scope.owa | 22 + modules/core/test.owa | 16 + modules/core/tests/bool.owa | 38 + modules/core/tests/cmp.owa | 41 ++ modules/core/tests/loop.owa | 42 ++ modules/core/tests/main.owa | 14 + modules/core/tests/map.owa | 83 +++ modules/core/tests/math.owa | 40 ++ modules/core/tests/null.owa | 8 + modules/core/tests/option.owa | 33 + modules/core/tests/scope.owa | 78 +++ modules/core/tests/set.owa | 44 ++ modules/core/tests/str.owa | 67 ++ modules/core/tests/types.owa | 53 ++ modules/core/tests/vec.owa | 91 +++ modules/core/types/bool.owa | 23 + modules/core/types/main.owa | 39 ++ modules/core/types/map.owa | 94 +++ modules/core/types/null.owa | 5 + modules/core/types/option.owa | 26 + modules/core/types/set.owa | 60 ++ modules/core/types/str.owa | 76 ++ modules/core/types/struct.owa | 22 + modules/core/types/vec.owa | 301 ++++++++ modules/owu/cli/main.owa | 19 + modules/owu/cli/run.owa | 43 ++ modules/owu/main.owa | 15 + modules/std/main.owa | 6 + modules/std/path.owa | 222 ++++++ modules/std/platform.owa | 55 ++ modules/std/tests/main.owa | 3 + modules/std/tests/path.owa | 286 ++++++++ src/builtins/ast.rs | 14 + src/builtins/cond.rs | 97 +++ src/builtins/errors.rs | 83 +++ src/builtins/ffi.rs | 299 ++++++++ src/builtins/flow.rs | 51 ++ src/builtins/map.rs | 14 + src/builtins/math.rs | 83 +++ src/builtins/mod.rs | 324 +++++++++ src/builtins/platform.rs | 19 + src/builtins/set.rs | 47 ++ src/builtins/str.rs | 48 ++ src/builtins/vec.rs | 66 ++ src/core/callable.rs | 234 +++++++ src/core/error.rs | 207 ++++++ src/core/interpreter.rs | 492 +++++++++++++ src/core/mod.rs | 12 + src/core/scope.rs | 77 +++ src/core/special_names.rs | 23 + src/core/value.rs | 347 ++++++++++ src/lib.rs | 18 + src/main.rs | 51 ++ src/parser/annotation.rs | 37 + src/parser/ast.rs | 353 ++++++++++ src/parser/call.rs | 29 + src/parser/keyword.rs | 14 + src/parser/lambda.rs | 30 + src/parser/map.rs | 39 ++ src/parser/mod.rs | 163 +++++ src/parser/number.rs | 170 +++++ src/parser/quote.rs | 24 + src/parser/set.rs | 29 + src/parser/string.rs | 96 +++ src/parser/symbol.rs | 22 + src/parser/unquote.rs | 27 + src/parser/vector.rs | 29 + 90 files changed, 7722 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 benchmarks/bench.ps1 create mode 100644 benchmarks/bench.sh create mode 100644 benchmarks/case1/main.owa create mode 100644 benchmarks/case1/main.py create mode 100644 benchmarks/case1/no_owu.owa create mode 100644 benchmarks/case1/result.md create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 modules/core/assert.owa create mode 100644 modules/core/ast.owa create mode 100644 modules/core/branch.owa create mode 100644 modules/core/cmp.owa create mode 100644 modules/core/error.owa create mode 100644 modules/core/ffi.owa create mode 100644 modules/core/lambda.owa create mode 100644 modules/core/loop.owa create mode 100644 modules/core/main.owa create mode 100644 modules/core/math.owa create mode 100644 modules/core/scope.owa create mode 100644 modules/core/test.owa create mode 100644 modules/core/tests/bool.owa create mode 100644 modules/core/tests/cmp.owa create mode 100644 modules/core/tests/loop.owa create mode 100644 modules/core/tests/main.owa create mode 100644 modules/core/tests/map.owa create mode 100644 modules/core/tests/math.owa create mode 100644 modules/core/tests/null.owa create mode 100644 modules/core/tests/option.owa create mode 100644 modules/core/tests/scope.owa create mode 100644 modules/core/tests/set.owa create mode 100644 modules/core/tests/str.owa create mode 100644 modules/core/tests/types.owa create mode 100644 modules/core/tests/vec.owa create mode 100644 modules/core/types/bool.owa create mode 100644 modules/core/types/main.owa create mode 100644 modules/core/types/map.owa create mode 100644 modules/core/types/null.owa create mode 100644 modules/core/types/option.owa create mode 100644 modules/core/types/set.owa create mode 100644 modules/core/types/str.owa create mode 100644 modules/core/types/struct.owa create mode 100644 modules/core/types/vec.owa create mode 100644 modules/owu/cli/main.owa create mode 100644 modules/owu/cli/run.owa create mode 100644 modules/owu/main.owa create mode 100644 modules/std/main.owa create mode 100644 modules/std/path.owa create mode 100644 modules/std/platform.owa create mode 100644 modules/std/tests/main.owa create mode 100644 modules/std/tests/path.owa create mode 100644 src/builtins/ast.rs create mode 100644 src/builtins/cond.rs create mode 100644 src/builtins/errors.rs create mode 100644 src/builtins/ffi.rs create mode 100644 src/builtins/flow.rs create mode 100644 src/builtins/map.rs create mode 100644 src/builtins/math.rs create mode 100644 src/builtins/mod.rs create mode 100644 src/builtins/platform.rs create mode 100644 src/builtins/set.rs create mode 100644 src/builtins/str.rs create mode 100644 src/builtins/vec.rs create mode 100644 src/core/callable.rs create mode 100644 src/core/error.rs create mode 100644 src/core/interpreter.rs create mode 100644 src/core/mod.rs create mode 100644 src/core/scope.rs create mode 100644 src/core/special_names.rs create mode 100644 src/core/value.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/parser/annotation.rs create mode 100644 src/parser/ast.rs create mode 100644 src/parser/call.rs create mode 100644 src/parser/keyword.rs create mode 100644 src/parser/lambda.rs create mode 100644 src/parser/map.rs create mode 100644 src/parser/mod.rs create mode 100644 src/parser/number.rs create mode 100644 src/parser/quote.rs create mode 100644 src/parser/set.rs create mode 100644 src/parser/string.rs create mode 100644 src/parser/symbol.rs create mode 100644 src/parser/unquote.rs create mode 100644 src/parser/vector.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ecf409a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +.vscode +.envrc \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..89fe3a9 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1217 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "archery" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e0a5f99dfebb87bb342d0f53bb92c81842e100bbb915223e38349580e5441d" +dependencies = [ + "triomphe", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags", + "crossterm_winapi", + "derive_more", + "document-features", + "mio", + "parking_lot", + "rustix", + "serde", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "js-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "libffi" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0498fe5655f857803e156523e644dcdcdc3b3c7edda42ea2afdae2e09b2db87b" +dependencies = [ + "libc", + "libffi-sys", +] + +[[package]] +name = "libffi-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d4f1d4ce15091955144350b75db16a96d4a63728500122706fb4d29a26afbb" +dependencies = [ + "cc", +] + +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "owa-rs" +version = "0.1.0" +dependencies = [ + "archery", + "clap", + "dirs", + "educe", + "libffi", + "libloading", + "nom", + "num-traits", + "ordered-float", + "paste", + "reedline", + "rpds", + "test-case", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "reedline" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2066729dce9fecd28d1c6850a159ee68719130f149b22467c362353e16994e90" +dependencies = [ + "chrono", + "crossterm", + "fd-lock", + "itertools", + "nu-ansi-term", + "serde", + "strip-ansi-escapes", + "strum", + "thiserror", + "unicase", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "rpds" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e75f485e819d4d3015e6c0d55d02a4fd3db47c1993d9e603e0361fba2bffb34" +dependencies = [ + "archery", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "test-case" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" +dependencies = [ + "test-case-macros", +] + +[[package]] +name = "test-case-core" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "test-case-macros" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "test-case-core", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "triomphe" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f03d9c5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "owa-rs" +version = "0.1.0" +edition = "2024" +repository = "https://git.ruject.fun/RuJect/owa-rs" +description = "A Lisp-like programming language implemented in Rust" +license = "Unlicense" +readme = "README.md" +categories = ["compilers", "parsing", "development-tools", "data-structures"] +keywords = [ + "owa", + "lisp", + "s-expression", + "language", + "interpreter", + "functional", + "persistent", + "immutable", + "ast", + "parser", + "runtime", + "rpds", +] + +[dependencies] +archery = "1.2.2" +clap = { version = "4.6.1", features = ["derive"] } +dirs = "6.0.0" +educe = "0.6.0" +libffi = "5.1.0" +libloading = "0.9.0" +nom = "8.0.0" +num-traits = "0.2.19" +ordered-float = { version = "5.3.0", features = ["std"] } +paste = "1.0.15" +reedline = "0.47.0" +rpds = "1.2.0" +test-case = "3.3.1" +tracing = { version = "0.1.44", features = ["release_max_level_off"] } +tracing-subscriber = "0.3.23" \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/README.md b/README.md new file mode 100644 index 0000000..149faa7 --- /dev/null +++ b/README.md @@ -0,0 +1,329 @@ +# OWA-RS + +A Lisp-inspired programming language written in Rust. This is a personal learning project, so expect rough edges and experimental design. + +## Content + +- [OWA-RS](#owa-rs) + - [Content](#content) + - [Overview](#overview) + - [Syntax 📝](#syntax-) + - [Literals](#literals) + - [Collections](#collections) + - [Special Forms](#special-forms) + - [Comments](#comments) + - [Annotations](#annotations) + - [Example](#example) + - [Quick Start 🛠️](#quick-start-️) + - [Requirements](#requirements) + - [Build](#build) + - [Run a file](#run-a-file) + - [Run directly without owu](#run-directly-without-owu) + - [Flags](#flags) + - [Architecture 🏗️](#architecture-️) + - [Rust core](#rust-core) + - [Modular standard library](#modular-standard-library) + - [Built-in API 🔧](#built-in-api-) + - [Core operations](#core-operations) + - [Built-in namespaces](#built-in-namespaces) + - [Standard Library 📚](#standard-library-) + - [Core Library (`modules/core/`)](#core-library-modulescore) + - [Standard Library (`modules/std/`)](#standard-library-modulesstd) + - [owu (`modules/owu/`)](#owu-modulesowu) + - [Performance ⚡](#performance-) + - [Examples 🌟](#examples-) + - [Hello World](#hello-world) + - [Using Functions from Core](#using-functions-from-core) + - [Working with Collections](#working-with-collections) + - [Development 🛠️](#development-️) + - [Running Tests](#running-tests) + - [Building Documentation](#building-documentation) + - [TODOs 📋](#todos-) + - [High Priority](#high-priority) + - [Medium Priority](#medium-priority) + - [Lower Priority](#lower-priority) + - [Completed](#completed) + - [Contributing 🤝](#contributing-) + - [License 📄](#license-) + +## Overview + +OWA-RS is designed as a lightweight Lisp-like interpreter with: + +- a small Rust runtime, +- a modular standard library, +- a simple CLI wrapper (owu), +- persistent immutable collections via `rpds`. + +> ⚠️ This is a **personal project** for learning and experimentation. It's my very first Rust project, so expect some rough edges. Use at your own risk! + +## Syntax 📝 + +OWA-RS uses a familiar Lisp-style syntax with nested expressions. + +### Literals + +- Integers: `42`, `-7` +- Floats: `3.14`, `-0.5` +- Strings: `"hello world"` +- Keywords: `:key`, `:value` +- Symbols: `variable-name`, `function?` + +### Collections + +- Lists / Calls: `(function arg1 arg2)` +- Vectors: `[1 2 3]` +- Maps: `{:key "value" :other 42}` +- Sets: `#{"a" "b" "c"}` + +### Special Forms + +- Lambdas: `(lambda [args] body)` +- Macros: `(macro [args] body)` +- Quotes: `'expression` +- Unquotes: `$expression` + +### Comments + +Comments start with `;;` and continue to the end of the line. + +### Annotations + +Annotations are placed in angle brackets (`value`) and can contain any value that will be computedduring linting (⚠️ currently not implemented). + +### Example + +```owa +(seq + ;; Define a function + (def greet (lambda [name] + (str.concat "Hello, " name "!"))) + + ;; Call it + (trace (greet "World"))) +``` + +## Quick Start 🛠️ + +### Requirements + +- Rust 1.70+ (for building from source) +- Cargo + +### Build + +```bash +git clone https://github.com/RuJect/owa-rs.git +cd owa-rs +cargo build --release +``` + +### Run a file + +```bash +./target/release/owa-rs run hello.owa +``` + +### Run directly without owu + +```bash +./target/release/owa-rs --no-owu hello.owa +``` + +### Flags + +When running via owu, these flags are available: + +- `--no-builtins`: skip Rust built-ins +- `--no-core`: skip loading core library +- `--no-std`: skip loading standard library +- `--debug`: enable debug mode +- `--test`: run in test mode + +## Architecture 🏗️ + +OWA-RS follows a **Parse → Interpret** pipeline with modular design: + +### Rust core + +- `src/parser/`: source code → AST +- `src/core/interpreter.rs`: evaluates AST nodes +- `src/core/scope.rs`: manages variables and closures +- `src/builtins/`: runtime primitives and host operations + +### Modular standard library + +- `modules/core/`: core language utilities, types, math, error handling, loops, tests +- `modules/std/`: higher-level helpers such as `path` and `platform` +- `modules/owu/`: command-line interface and `run` command support + +The runtime stays intentionally small, while higher-level language features live in library code. + +## Built-in API 🔧 + +OWA-RS follows a **minimalist principle** for Rust built-ins: the runtime only implements fundamental primitives and avoids domain/application logic. The result is a small, focused runtime with powerful libraries built on top. + +### Core operations + +- Language: `def`, `lambda`, `macro`, `seq`, `trace`, `apply`, `lookup`, `include` +- Scope: `scope`, `set!`, `unset!`, `exec` +- Type inspection: `typeof`, `cmp` +- Flow: `return`, `break`, `continue` (via `flow` namespace) +- Errors: `throw`, `catch` (via `errors` namespace) + +### Built-in namespaces + +- `math`: arithmetic and numeric helpers +- `str`: string construction and serialization +- `vec`: vector creation and folding +- `map`: maps and lookup +- `set`: set operations +- `cond`: conditional helpers like `if-eq` and `match` +- `platform`: environment, CLI parsing, debug flags + +## Standard Library 📚 + +The standard library is organized in modules: + +### Core Library (`modules/core/`) + +Essential functionality available by default when running through owu: + +- `assert.owa`: Assertion utilities for testing +- `types/`: Type checking and predicates, including: + - `main.owa`: Core type utilities and predicates + - `bool.owa`, `str.owa`, `vec.owa`, `map.owa`, `set.owa`, `null.owa`, `option.owa`: Type-specific operations +- `cmp.owa`: Comparison operations +- `math.owa`: Arithmetic operations +- `error.owa`: Error handling +- `loop.owa`: Looping constructs +- `test.owa`: Testing framework + +### Standard Library (`modules/std/`) + +Additional utilities: + +- `platform.owa`: Platform-specific operations + +### owu (`modules/owu/`) + +The OWA Utility tool: + +- `cli/`: Command-line interface framework +- `cli/run.owa`: The `run` command handler + +## Performance ⚡ + +OWA-RS is a tree-walking interpreter with reasonable performance for its simplicity. Rust's persistent data structures (via rpds) provide efficient immutable collections. + +For performance-critical workloads, consider: + +- Writing hot paths in Rust as built-ins +- Avoiding deeply nested function calls +- Using tail recursion where possible + +See `benchmarks/` for sample performance characteristics. + +## Examples 🌟 + +### Hello World + +```owa +(trace "Hello, OWA-RS!") +``` + +### Using Functions from Core + +```owa +(def fib (lambda [n] + (if (>= n 2) + (+ (fib (- n 1)) (fib (- n 2))) + n))) + +(trace (fib 10)) +``` + +Run with: `./target/release/owa-rs run fib.owa` + +### Working with Collections + +```owa +(def numbers [1 2 3 4 5]) +(trace (vec.len numbers)) +(trace (vec.first numbers)) + +(def config {:name "OWA" :version "0.1.0"}) +(trace (map.get config :name)) +``` + +## Development 🛠️ + +### Running Tests + +The core library has a built-in testing framework: + +```bash +./target/release/owa-rs run --test modules/core/tests/main.owa +``` + +### Building Documentation + +To understand the codebase: + +- `src/core/interpreter.rs` - Main evaluation logic +- `src/builtins/` - Rust built-in implementations +- `modules/core/` - OWA standard library code +- `modules/owu/cli/` - Command-line interface implementation + +## TODOs 📋 + +### High Priority + +- [ ] Add proper error reporting with location information +- [ ] Improve debugging/tracing utilities +- [ ] Add REPL mode for interactive development +- [ ] Implement tail call optimization + +### Medium Priority + +- [ ] Pattern matching enhancements +- [x] Destructuring in set!/def +- [ ] More comprehensive std library +- [ ] Package manager / module repository +- [ ] Performance profiling tools + +### Lower Priority + +- [ ] Concurrency support +- [x] FFI (Foreign Function Interface) +- [ ] File system operations (fs module) +- [ ] Random number generation +- [ ] Compilation to bytecode +- [ ] Lint phase + +### Completed + +- [x] Annotations +- [x] Separate core and std libraries +- [x] CLI framework with commands +- [x] Testing framework +- [x] Error handling macros + +## Contributing 🤝 + +This is a learning project exploring language design and implementation. Contributions are welcome! + +Areas where help is appreciated: + +- Standard library expansion +- Bug fixes and optimizations +- Documentation and examples +- Testing and benchmarking + +## License 📄 + +Unlicense License - see LICENSE file. + +--- + +Made with ❤️ and lots of ☕ as a Rust learning project! diff --git a/benchmarks/bench.ps1 b/benchmarks/bench.ps1 new file mode 100644 index 0000000..b8c4653 --- /dev/null +++ b/benchmarks/bench.ps1 @@ -0,0 +1,17 @@ +$fileDirname = $PSScriptRoot +$owaCmd = ".\target\release\owa-rs.exe" + +for ($i = 1; $i -le 1; $i++) { + $pythonFile = "$fileDirname/case$i/main.py" + $owaFile = "$fileDirname/case$i/main.owa" + $noOwuFile = "$fileDirname/case$i/no_owu.owa" + Write-Host "Running case #$i" + hyperfine ` + --warmup 5 ` + --min-runs 50 ` + --show-output ` + --export-markdown "$fileDirname/case$i/result.md" ` + "python3.14 $pythonFile" ` + "$owaCmd run $owaFile" ` + "$owaCmd --no-owu $noOwuFile" +} diff --git a/benchmarks/bench.sh b/benchmarks/bench.sh new file mode 100644 index 0000000..e736a62 --- /dev/null +++ b/benchmarks/bench.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh +file_dirname="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +owa_cmd="./target/release/owa-rs" + +for i in $(seq 1 1); do + python_file="${file_dirname}/case${i}/main.py" + owa_file="${file_dirname}/case${i}/main.owa" + no_owu_file="${file_dirname}/case${i}/no_owu.owa" + echo "Running case #${i}" + hyperfine \ + --warmup 5 \ + --min-runs 50 \ + --show-output \ + --export-markdown "${file_dirname}/case${i}/result.md" \ + "python3 $python_file" \ + "$owa_cmd run $owa_file" \ + "$owa_cmd --no-owu $no_owu_file" +done \ No newline at end of file diff --git a/benchmarks/case1/main.owa b/benchmarks/case1/main.owa new file mode 100644 index 0000000..7106c31 --- /dev/null +++ b/benchmarks/case1/main.owa @@ -0,0 +1,8 @@ +(seq + (def fib (lambda [n] + (match n + (0 0) + (1 1) + (_ (+ (this (- n 1)) (this (- n 2))))))) + (trace (fib 12)) +) \ No newline at end of file diff --git a/benchmarks/case1/main.py b/benchmarks/case1/main.py new file mode 100644 index 0000000..0cc8d2e --- /dev/null +++ b/benchmarks/case1/main.py @@ -0,0 +1,9 @@ +def fib(n): + if n == 0: + return 0 + if n == 1: + return 1 + return fib(n - 1) + fib(n - 2) + + +print(fib(12)) diff --git a/benchmarks/case1/no_owu.owa b/benchmarks/case1/no_owu.owa new file mode 100644 index 0000000..fda9726 --- /dev/null +++ b/benchmarks/case1/no_owu.owa @@ -0,0 +1,8 @@ +(builtins.seq + (builtins.def fib (builtins.lambda [n] + (builtins.cond.match n + (0 0) + (1 1) + (_ (builtins.math.add (this (builtins.math.sub n 1)) (this (builtins.math.sub n 2))))))) + (builtins.trace (fib 12)) +) \ No newline at end of file diff --git a/benchmarks/case1/result.md b/benchmarks/case1/result.md new file mode 100644 index 0000000..bb7373d --- /dev/null +++ b/benchmarks/case1/result.md @@ -0,0 +1,5 @@ +| Command | Mean [ms] | Min [ms] | Max [ms] | Relative | +|:---|---:|---:|---:|---:| +| `python3.14 D:\Tools\Projects\owa-rs\benchmarks/case1/main.py` | 40.5 ± 0.7 | 39.5 | 43.1 | 2.38 ± 0.36 | +| `.\target\release\owa-rs.exe run D:\Tools\Projects\owa-rs\benchmarks/case1/main.owa` | 53.3 ± 1.2 | 51.5 | 57.6 | 3.14 ± 0.48 | +| `.\target\release\owa-rs.exe --no-owu D:\Tools\Projects\owa-rs\benchmarks/case1/no_owu.owa` | 17.0 ± 2.6 | 15.3 | 37.5 | 1.00 | diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..012fb16 --- /dev/null +++ b/flake.lock @@ -0,0 +1,175 @@ +{ + "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1776497206, + "narHash": "sha256-Em+RSdFnwyyKPGUBFtQYtVjm+1UvIc9gOR91Y22zlzg=", + "owner": "nix-community", + "repo": "fenix", + "rev": "df2295365fb081fe0745449762a771290782c22d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "fenix_2": { + "inputs": { + "nixpkgs": [ + "naersk", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src_2" + }, + "locked": { + "lastModified": 1752475459, + "narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=", + "owner": "nix-community", + "repo": "fenix", + "rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "naersk": { + "inputs": { + "fenix": "fenix_2", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1776200608, + "narHash": "sha256-broZ6RFQr4Fv0wT73gGmzNX14A43TmTFF8g4wDKlNss=", + "owner": "nix-community", + "repo": "naersk", + "rev": "8b23250ab45c2a38cd91031aee26478ca4d0a28e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1752077645, + "narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "be9e214982e20b8310878ac2baa063a961c1bdf6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1776169885, + "narHash": "sha256-l/iNYDZ4bGOAFQY2q8y5OAfBBtrDAaPuRQqWaFHVRXM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4bd9165a9165d7b5e33ae57f3eecbcb28fb231c9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "fenix": "fenix", + "flake-utils": "flake-utils", + "naersk": "naersk", + "nixpkgs": "nixpkgs_2" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1776441750, + "narHash": "sha256-1rVfG+mj8R4ze+lSYCa4iAv7FzrB03Cprtxmd1MfZak=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "251df518d73abb5c5d573c4d5d266a3edae9ca5a", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_2": { + "flake": false, + "locked": { + "lastModified": 1752428706, + "narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "591e3b7624be97e4443ea7b5542c191311aa141d", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..0240bb6 --- /dev/null +++ b/flake.nix @@ -0,0 +1,48 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + flake-utils.url = "github:numtide/flake-utils"; + naersk.url = "github:nix-community/naersk"; + }; + + outputs = { + nixpkgs, + fenix, + flake-utils, + naersk, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = (import nixpkgs) { + inherit system; + overlays = [fenix.overlays.default]; + }; + naersk' = pkgs.callPackage naersk {}; + in { + defaultPackage = naersk'.buildPackage { + src = ./.; + }; + + devShell = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + hyperfine + python3 + alejandra + rust-analyzer + (pkgs.fenix.stable.withComponents [ + "cargo" + "clippy" + "rust-src" + "rustc" + "rustfmt" + ]) + ]; + }; + } + ); +} diff --git a/modules/core/assert.owa b/modules/core/assert.owa new file mode 100644 index 0000000..2cd641e --- /dev/null +++ b/modules/core/assert.owa @@ -0,0 +1,17 @@ +(namespace assert + (defmacro ok! [] (if (bool.and $%&) + :true + (throw! "assertion failed"))) + + (defmacro not! [] (if (bool.and $%&) + (throw! "assertion failed") + :true)) + + (defmacro eq! [] (if-eq $(%&) + :true + (throw! "assertion failed"))) + + (defmacro nq! [] (if-eq $(%&) + (throw! "assertion failed") + :true)) +) \ No newline at end of file diff --git a/modules/core/ast.owa b/modules/core/ast.owa new file mode 100644 index 0000000..e72ad3d --- /dev/null +++ b/modules/core/ast.owa @@ -0,0 +1,10 @@ +(namespace ast + (defmacro pack! [v] + (builtins.ast.pack $v)) + + (defmacro value! [v] + (map.get (ast.pack! $v) :data)) + + (defmacro type! [v] + (map.get (ast.pack! $v) :type)) +) \ No newline at end of file diff --git a/modules/core/branch.owa b/modules/core/branch.owa new file mode 100644 index 0000000..e37a141 --- /dev/null +++ b/modules/core/branch.owa @@ -0,0 +1,12 @@ +(seq + ;; builtins + (def if-eq builtins.cond.if_eq) + (def match builtins.cond.match) + (def if-has builtins.cond.if_has) + + (defmacro if [cond then] + (if-eq (:false $cond) (seq $%&) (seq $then))) + + (defmacro unless [cond then] + (if-eq (:false $cond) (seq $then) (seq $%&))) +) \ No newline at end of file diff --git a/modules/core/cmp.owa b/modules/core/cmp.owa new file mode 100644 index 0000000..a1b99a8 --- /dev/null +++ b/modules/core/cmp.owa @@ -0,0 +1,25 @@ +(seq + (defmacro eq? [] + (if-eq ($%%) :true :false)) + (defmacro nq? [] + (if-eq ($%%) :false :true)) + + (fn cmp [left right] + (match (builtins.cmp left right) + (-1 :less) + (0 :equal) + (1 :greater))) + + + (fn lt? [left right] + (eq? (cmp left right) :less)) + + (fn lte? [left right] + (bool.or (lt? left right) (eq? left right))) + + (fn gt? [left right] + (eq? (cmp left right) :greater)) + + (fn gte? [left right] + (bool.or (gt? left right) (eq? left right))) +) \ No newline at end of file diff --git a/modules/core/error.owa b/modules/core/error.owa new file mode 100644 index 0000000..c9dddd4 --- /dev/null +++ b/modules/core/error.owa @@ -0,0 +1,22 @@ +(seq + (fn throw! [] + (throw.runtime_error! (str.join "" %%))) + (fn panic! [v] + (throw.panic! v)) + (fn unreachable! [] + (throw! "Reached unreachable code")) + (fn not_implemented! [] + (throw! "Not implemented")) + (def try builtins.errors.try) + + (defmacro catch [pattern then] + (lambda [msg type] (if-eq (type $pattern) + $then + :null))) + + (namespace throw + (def panic! builtins.errors.throw_panic) + (def type_error! builtins.errors.throw_type_error) + (def arity_error! builtins.errors.throw_arity_error) + (def runtime_error! builtins.errors.throw_runtime_error) + )) \ No newline at end of file diff --git a/modules/core/ffi.owa b/modules/core/ffi.owa new file mode 100644 index 0000000..563644f --- /dev/null +++ b/modules/core/ffi.owa @@ -0,0 +1,32 @@ +(namespace ffi + (def unload builtins.ffi.unload) + + (def ctypes [ + :i8 :i16 :i32 :i64 + :u8 :u16 :u32 :u64 + :f32 :f64 + :ptr + :str + ]) + + (defmacro extern [name libname] + (namespace $name + (builtins.ffi.load $libname) + (fn call [symbol signature args] + (builtins.ffi.call $libname symbol signature args) + ) + ) + ) + + (defmacro native [name libname] + (namespace $name + (builtins.ffi.load $libname) + (defmacro fn [name symbol args ret] + (def '$name #(builtins.ffi.call $libname '$symbol ['$args '$ret] %&)) + ) + $%& + ) + ) + + (extern ucrtbase "ucrtbase.dll") +) diff --git a/modules/core/lambda.owa b/modules/core/lambda.owa new file mode 100644 index 0000000..d25023a --- /dev/null +++ b/modules/core/lambda.owa @@ -0,0 +1,8 @@ +(seq + ;; builtins + (def apply builtins.apply) + (def lambda builtins.lambda) + + (defmacro fn [name params body] + (def $name (lambda $params $body))) +) \ No newline at end of file diff --git a/modules/core/loop.owa b/modules/core/loop.owa new file mode 100644 index 0000000..62b0251 --- /dev/null +++ b/modules/core/loop.owa @@ -0,0 +1,23 @@ +(seq + (def break builtins.flow.break) + (def continue builtins.flow.continue) + (def loop builtins.flow.loop) + + (defmacro return [] + (builtins.flow.return $%% null)) + + (defmacro while [cond] (loop + (if (eq? $cond :false) (break) :null) + $%&)) + + (defmacro do-while [cond] (loop + $%& + (if (eq? $cond :false) (break) :null))) + + (defmacro for [var iter] (vec.map + (lambda [x] (seq + (def $var x) + $%&)) + (vec.from $iter) + )) +) diff --git a/modules/core/main.owa b/modules/core/main.owa new file mode 100644 index 0000000..fd68654 --- /dev/null +++ b/modules/core/main.owa @@ -0,0 +1,25 @@ +(builtins.seq + (builtins.def include builtins.include) + + (include "scope") + (include "branch") + (include "lambda") + + (def exec builtins.exec) + (def trace builtins.trace) + (def typeof builtins.typeof) + + (fn identity [x] x) + + (include "types") + (include "assert") + (include "ast") + (include "cmp") + (include "error") + (include "ffi") + (include "loop") + (include "math") + (include "test") + + (test.space "core" (include "tests/main")) +) diff --git a/modules/core/math.owa b/modules/core/math.owa new file mode 100644 index 0000000..7d045de --- /dev/null +++ b/modules/core/math.owa @@ -0,0 +1,14 @@ +(seq + (def + builtins.math.add) + (def - builtins.math.sub) + (def * builtins.math.mul) + (def / builtins.math.div) + (def % builtins.math.mod) + (def ** builtins.math.pow) + + (fn ++ [x] + (+ x 1)) + + (fn -- [x] + (- x 1)) +) \ No newline at end of file diff --git a/modules/core/scope.owa b/modules/core/scope.owa new file mode 100644 index 0000000..e4945e0 --- /dev/null +++ b/modules/core/scope.owa @@ -0,0 +1,22 @@ +(builtins.seq + ;; builtins + (builtins.def def builtins.def) + (def lookup builtins.lookup) + (def set! builtins.set!) + (def scope builtins.scope) + + ;; macro + (def macro builtins.macro) + (def defmacro (macro [name params body] + (def $name (macro $params $body)))) + + ;; flow + (defmacro seq [] + (builtins.seq :null $%&)) + (defmacro namespace [name] (def $name (scope $%&))) + + ;; other + (defmacro mut! [v fn] (seq + (set! (ast.value! $v) ($fn $v $%&))) + ) +) \ No newline at end of file diff --git a/modules/core/test.owa b/modules/core/test.owa new file mode 100644 index 0000000..af392d7 --- /dev/null +++ b/modules/core/test.owa @@ -0,0 +1,16 @@ +(namespace test + (def target (lookup __test__ null)) + + (defmacro if-target [then] + (if-eq (test.target null) :null (seq $%%))) + + (defmacro case [name] (test.if-target + (builtins.errors.try + (scope $%& (trace "Running test \"" $name "\": OK ✅")) + #(trace "Running test \"" $name "\": FAILED ❌ (" %2 ": " %1 ")")))) + + (defmacro space [name] (if + (bool.or (eq? test.target $name) (eq? test.target ".")) + (namespace $name (seq $%&)) + )) +) \ No newline at end of file diff --git a/modules/core/tests/bool.owa b/modules/core/tests/bool.owa new file mode 100644 index 0000000..28053f8 --- /dev/null +++ b/modules/core/tests/bool.owa @@ -0,0 +1,38 @@ +(namespace tests.bool + (test.case "bool.bool?" + (assert.ok! (bool? true)) + (assert.ok! (bool? false)) + (assert.not! (bool? 1)) + ) + + (test.case "bool.not" + (assert.eq! (bool.not true) false) + (assert.eq! (bool.not false) true) + ) + + (test.case "bool.and" + (assert.ok! (bool.and true true)) + (assert.not! (bool.and true false)) + (assert.not! (bool.and false true)) + (assert.not! (bool.and false false)) + ) + + (test.case "bool.or" + (assert.ok! (bool.or true true)) + (assert.ok! (bool.or true false)) + (assert.ok! (bool.or false true)) + (assert.not! (bool.or false false)) + ) + + (test.case "bool.nand" + (assert.not! (bool.nand true true)) + (assert.ok! (bool.nand true false)) + (assert.ok! (bool.nand false true)) + (assert.ok! (bool.nand false false)) + ) + + (test.case "bool.new" + (assert.eq! (bool.new true) true) + (assert.eq! (bool.new false) false) + ) +) diff --git a/modules/core/tests/cmp.owa b/modules/core/tests/cmp.owa new file mode 100644 index 0000000..02dc157 --- /dev/null +++ b/modules/core/tests/cmp.owa @@ -0,0 +1,41 @@ +(namespace tests.cmp + (test.case "cmp.eq?" + (assert.ok! (eq? 1 1)) + (assert.not! (eq? 1 2)) + ) + + (test.case "cmp.nq?" + (assert.ok! (nq? 1 2)) + (assert.not! (nq? 1 1)) + ) + + (test.case "cmp.cmp" + (assert.eq! (cmp 1 2) :less) + (assert.eq! (cmp 2 1) :greater) + (assert.eq! (cmp 1 1) :equal) + ) + + (test.case "cmp.lt?" + (assert.ok! (lt? 1 2)) + (assert.not! (lt? 2 1)) + (assert.not! (lt? 1 1)) + ) + + (test.case "cmp.lte?" + (assert.ok! (lte? 1 2)) + (assert.ok! (lte? 1 1)) + (assert.not! (lte? 2 1)) + ) + + (test.case "cmp.gt?" + (assert.ok! (gt? 2 1)) + (assert.not! (gt? 1 2)) + (assert.not! (gt? 1 1)) + ) + + (test.case "cmp.gte?" + (assert.ok! (gte? 2 1)) + (assert.ok! (gte? 1 1)) + (assert.not! (gte? 1 2)) + ) +) diff --git a/modules/core/tests/loop.owa b/modules/core/tests/loop.owa new file mode 100644 index 0000000..d8732b1 --- /dev/null +++ b/modules/core/tests/loop.owa @@ -0,0 +1,42 @@ +(namespace tests.loop + (test.case "while.basic-true" + (def counter 0) + (while (eq? counter 0) + (set! counter 1)) + (assert.eq! counter 1) + ) + + (test.case "while.condition-false" + (def counter 5) + (while (lt? counter 0) + (set! counter (+ counter 1))) + (assert.eq! counter 5) + ) + + (test.case "while.counting-loop" + (def n 0) + (while (lt? n 10) + (set! n (+ n 1))) + (assert.eq! n 10) + ) + + (test.case "while.loop-condition-reached" + (def i 0) + (while (lt? i 5) + (set! i (+ i 1))) + (assert.eq! i 5) + ) + + (test.case "while.nested" + (def outer 0) + (def inner 0) + (def total 0) + (while (lt? outer 3) + (set! inner 0) + (while (lt? inner 2) + (set! total (+ total 1)) + (set! inner (+ inner 1))) + (set! outer (+ outer 1))) + (assert.eq! total 6) + ) +) diff --git a/modules/core/tests/main.owa b/modules/core/tests/main.owa new file mode 100644 index 0000000..93984f4 --- /dev/null +++ b/modules/core/tests/main.owa @@ -0,0 +1,14 @@ +(seq + (include "vec") + (include "str") + (include "set") + (include "map") + (include "bool") + (include "option") + (include "scope") + (include "null") + (include "cmp") + (include "math") + (include "types") + (include "loop") +) diff --git a/modules/core/tests/map.owa b/modules/core/tests/map.owa new file mode 100644 index 0000000..7b267dc --- /dev/null +++ b/modules/core/tests/map.owa @@ -0,0 +1,83 @@ +(namespace tests.map + (test.case "map.len" + (assert.eq! (map.len (map.new)) 0) + ) + + (test.case "map.empty?" + (assert.ok! (map.empty? (map.new))) + ) + + (test.case "map.is-empty?" + (assert.ok! (map.is-empty? (map.new))) + ) + + (test.case "map.get" + (seq + (def m (map.new :a 1 :b 2)) + (assert.eq! (map.get m :a) 1) + (assert.eq! (map.get m :b) 2) + (assert.eq! (map.get m :c) null) + ) + ) + + (test.case "map.put" + (seq + (def m (map.new :a 1)) + (def m2 (map.put m :b 2)) + (assert.eq! (map.len m2) 2) + (assert.eq! (map.get m2 :b) 2) + ) + ) + + (test.case "map.has-key?" + (seq + (def m (map.new :a 1 :b 2)) + (assert.ok! (map.has-key? m :a)) + (assert.not! (map.has-key? m :c)) + ) + ) + + (test.case "map.has-value?" + (seq + (def m (map.new :a 1 :b 2)) + (assert.ok! (map.has-value? m 1)) + (assert.not! (map.has-value? m 5)) + ) + ) + + (test.case "map.keys" + (seq + (def m (map.new :a 1 :b 2)) + (def ks (map.keys m)) + (assert.eq! (vec.len ks) 2) + ) + ) + + (test.case "map.values" + (seq + (def m (map.new :a 1 :b 2)) + (def vs (map.values m)) + (assert.eq! (vec.len vs) 2) + ) + ) + + (test.case "map.merge" + (seq + (def m1 (map.new :a 1 :b 2)) + (def m2 (map.new :b 20 :c 3)) + (def m3 (map.merge m1 m2)) + (assert.eq! (map.get m3 :a) 1) + (assert.eq! (map.get m3 :b) 20) + (assert.eq! (map.get m3 :c) 3) + ) + ) + + (test.case "map.dissoc" + (seq + (def m (map.new :a 1 :b 2 :c 3)) + (def m2 (map.dissoc m :b)) + (assert.eq! (map.len m2) 2) + (assert.not! (map.has-key? m2 :b)) + ) + ) +) diff --git a/modules/core/tests/math.owa b/modules/core/tests/math.owa new file mode 100644 index 0000000..176e564 --- /dev/null +++ b/modules/core/tests/math.owa @@ -0,0 +1,40 @@ +(namespace tests.math + (test.case "math.add" + (assert.eq! (+ 1 2) 3) + (assert.eq! (+ 0 0) 0) + ) + + (test.case "math.sub" + (assert.eq! (- 5 3) 2) + (assert.eq! (- 1 1) 0) + ) + + (test.case "math.mul" + (assert.eq! (* 3 4) 12) + (assert.eq! (* 0 5) 0) + ) + + (test.case "math.div" + (assert.eq! (/ 10 2) 5) + ) + + (test.case "math.mod" + (assert.eq! (% 10 3) 1) + (assert.eq! (% 5 5) 0) + ) + + (test.case "math.pow" + (assert.eq! (** 2 3) 8) + (assert.eq! (** 5 2) 25) + ) + + (test.case "math.++" + (assert.eq! (++ 5) 6) + (assert.eq! (++ 0) 1) + ) + + (test.case "math.--" + (assert.eq! (-- 5) 4) + (assert.eq! (-- 0) -1) + ) +) diff --git a/modules/core/tests/null.owa b/modules/core/tests/null.owa new file mode 100644 index 0000000..a2b9d5b --- /dev/null +++ b/modules/core/tests/null.owa @@ -0,0 +1,8 @@ +(namespace tests.null + (test.case "null.null?" + (assert.ok! (null? null)) + (assert.ok! (null? :nil)) + (assert.not! (null? 0)) + (assert.not! (null? false)) + ) +) diff --git a/modules/core/tests/option.owa b/modules/core/tests/option.owa new file mode 100644 index 0000000..7bd52f8 --- /dev/null +++ b/modules/core/tests/option.owa @@ -0,0 +1,33 @@ +(namespace tests.option + (test.case "option.ok" + (seq + (def opt (option.ok 42)) + (assert.ok! (option.ok? opt)) + (assert.eq! (vec.get opt 1) 42) + ) + ) + + (test.case "option.err" + (seq + (def opt (option.err "error")) + (assert.ok! (option.err? opt)) + (assert.eq! (vec.get opt 1) "error") + ) + ) + + (test.case "option.ok?" + (assert.ok! (option.ok? (option.ok 1))) + (assert.not! (option.ok? (option.err "x"))) + ) + + (test.case "option.err?" + (assert.ok! (option.err? (option.err "x"))) + (assert.not! (option.err? (option.ok 1))) + ) + + (test.case "option.option?" + (assert.ok! (option? (option.ok 1))) + (assert.ok! (option? (option.err "x"))) + (assert.not! (option? [1 2])) + ) +) diff --git a/modules/core/tests/scope.owa b/modules/core/tests/scope.owa new file mode 100644 index 0000000..2f36890 --- /dev/null +++ b/modules/core/tests/scope.owa @@ -0,0 +1,78 @@ +(namespace tests.scopes + (test.case "def" + (def x 1) + (assert.eq! x 1) + + (def [y z] [1 2]) + (assert.eq! y 1) + (assert.eq! z 2) + ) + + (test.case "def bounded" + (def x 1) + (try + (def x 2) + (catch :Panic (return)) + ) + (unreachable!) + ) + + (test.case "set!" + (def [x y] [1 1]) + (set! x 2) + (assert.eq! x 2) + + (set! [x y] [3 4]) + (assert.eq! x 3) + (assert.eq! y 4) + ) + + (test.case "set! unbounded" + (try + (set! x 2) + (catch :UnboundVariable (return)) + ) + (unreachable!) + ) + + (test.case "lookup" + (def x 1) + (assert.eq! (lookup x null) 1) + (assert.eq! (lookup y null) null) + ) + + (test.case "inheritance" + (scope + (def x 1) + (scope + (assert.eq! x 1) + (set! x 2) + ) + (assert.eq! x 2) + ) + ) + + (test.case "shadowing" + (scope + (def x 100) + (scope + (def x 1) + ) + (assert.eq! x 100) + ) + (assert.eq! (lookup x null) null) + ) + + (test.case "leakage" + (scope (def x 1)) + (assert.eq! (lookup x null) null) + + (scope (def y 2)) + (assert.eq! (lookup y null) null) + + (scope + (scope (def z 1)) + (assert.eq! (lookup z null) null) + ) + ) +) diff --git a/modules/core/tests/set.owa b/modules/core/tests/set.owa new file mode 100644 index 0000000..440f991 --- /dev/null +++ b/modules/core/tests/set.owa @@ -0,0 +1,44 @@ +(namespace tests.set + (test.case "set.empty?" + (assert.ok! (set.empty? (set.new))) + (assert.not! (set.empty? (set.new 1))) + ) + + (test.case "set.len" + (assert.eq! (set.len (set.new)) 0) + (assert.eq! (set.len (set.new 1)) 1) + (assert.eq! (set.len (set.new 1 2 3)) 3) + ) + + (test.case "set.has" + (assert.ok! (set.has (set.new 1 2 3) 2)) + (assert.not! (set.has (set.new 1 2 3) 5)) + ) + + (test.case "set.add" + (assert.ok! (set.has (set.add (set.new 1 2) 3) 3)) + (assert.eq! (set.len (set.add (set.new 1 2) 3)) 3) + ) + + (test.case "set.remove" + (assert.not! (set.has (set.remove (set.new 1 2 3) 2) 2)) + (assert.eq! (set.len (set.remove (set.new 1 2 3) 2)) 2) + ) + + (test.case "set.union" + (assert.eq! (set.len (set.union (set.new 1 2) (set.new 2 3))) 3) + (assert.ok! (set.has (set.union (set.new 1 2) (set.new 2 3)) 1)) + (assert.ok! (set.has (set.union (set.new 1 2) (set.new 2 3)) 3)) + ) + + (test.case "set.intersection" + (assert.eq! (set.len (set.intersection (set.new 1 2 3) (set.new 2 3 4))) 2) + (assert.ok! (set.has (set.intersection (set.new 1 2 3) (set.new 2 3 4)) 2)) + (assert.ok! (set.has (set.intersection (set.new 1 2 3) (set.new 2 3 4)) 3)) + ) + + (test.case "set.difference" + (assert.eq! (set.len (set.difference (set.new 1 2 3) (set.new 2 3))) 1) + (assert.ok! (set.has (set.difference (set.new 1 2 3) (set.new 2 3)) 1)) + ) +) \ No newline at end of file diff --git a/modules/core/tests/str.owa b/modules/core/tests/str.owa new file mode 100644 index 0000000..7388a99 --- /dev/null +++ b/modules/core/tests/str.owa @@ -0,0 +1,67 @@ +(namespace tests.str + (test.case "str.len" + (assert.eq! (str.len "") 0) + (assert.eq! (str.len "hello") 5) + ) + + (test.case "str.empty?" + (assert.ok! (str.empty? "")) + (assert.not! (str.empty? "a")) + ) + + (test.case "str.is-empty?" + (assert.ok! (str.is-empty? "")) + (assert.not! (str.is-empty? "a")) + ) + + (test.case "str.first" + (assert.eq! (str.first "hello") "h") + ) + + (test.case "str.last" + (assert.eq! (str.last "hello") "o") + ) + + (test.case "str.concat" + (assert.eq! (str.concat "hello" " " "world") "hello world") + ) + + (test.case "str.substring" + (assert.eq! (str.substring "hello" 0 3) "hel") + (assert.eq! (str.substring "hello" 1 4) "ell") + ) + + (test.case "str.take" + (assert.eq! (str.take "hello" 3) "hel") + ) + + (test.case "str.drop" + (assert.eq! (str.drop "hello" 2) "llo") + ) + + (test.case "str.reverse" + (assert.eq! (str.reverse "hello") "olleh") + ) + + (test.case "str.starts-with?" + (assert.ok! (str.starts-with? "hello" "hel")) + (assert.not! (str.starts-with? "hello" "xyz")) + ) + + (test.case "str.ends-with?" + (assert.ok! (str.ends-with? "hello" "lo")) + (assert.not! (str.ends-with? "hello" "xyz")) + ) + + (test.case "str.split" + (assert.eq! (str.split "hello world" " ") ["hello" "world"]) + (assert.eq! (str.split "hello world" "w") ["hello " "orld"]) + (assert.eq! (str.split "hello world" "x") ["hello world"]) + ) + + (test.case "str.join" + (assert.eq! (str.join " " ["hello" "world"]) "hello world") + (assert.eq! (str.join "w" ["hello " "orld"]) "hello world") + (assert.eq! (str.join "x" ["hello world"]) "hello world") + ) +) diff --git a/modules/core/tests/types.owa b/modules/core/tests/types.owa new file mode 100644 index 0000000..9142923 --- /dev/null +++ b/modules/core/tests/types.owa @@ -0,0 +1,53 @@ +(namespace tests.types + (test.case "types.is?" + (assert.ok! (is? 42 :int)) + (assert.ok! (is? "hello" :str)) + (assert.ok! (is? [] :vec)) + (assert.not! (is? 42 :str)) + ) + + (test.case "types.guard" + (seq + (def int-guard (guard :int)) + (assert.ok! (int-guard 42)) + (assert.not! (int-guard "42")) + ) + ) + + (test.case "types.kw?" + (assert.ok! (kw? :keyword)) + (assert.not! (kw? "not-keyword")) + ) + + (test.case "types.type?" + (assert.ok! (type? :int)) + (assert.ok! (type? :str)) + (assert.not! (type? :unknown)) + ) + + (test.case "types.str?" + (assert.ok! (str? "hello")) + (assert.not! (str? 42)) + ) + + (test.case "types.vec?" + (assert.ok! (vec? [])) + (assert.ok! (vec? [1 2 3])) + (assert.not! (vec? 42)) + ) + + (test.case "types.bool?" + (assert.ok! (bool? true)) + (assert.ok! (bool? false)) + (assert.not! (bool? 1)) + ) + + (test.case "types.null?" + (assert.ok! (null? null)) + (assert.not! (null? 0)) + ) + + (test.case "types.map.is?" + (assert.ok! (map.is? (map.new))) + ) +) diff --git a/modules/core/tests/vec.owa b/modules/core/tests/vec.owa new file mode 100644 index 0000000..28e31c4 --- /dev/null +++ b/modules/core/tests/vec.owa @@ -0,0 +1,91 @@ +(namespace tests.vec + (test.case "vec.empty?" + (assert.ok! (vec.empty? [])) + (assert.not! (vec.empty? [1])) + ) + + (test.case "vec.len" + (assert.eq! (vec.len []) 0) + (assert.eq! (vec.len [1]) 1) + (assert.eq! (vec.len [1 2 3]) 3) + ) + + (test.case "vec.first" + (assert.eq! (vec.first [1 2 3]) 1) + (assert.eq! (vec.first ["a"]) "a") + ) + + (test.case "vec.last" + (assert.eq! (vec.last [1 2 3]) 3) + (assert.eq! (vec.last ["x"]) "x") + ) + + (test.case "vec.get" + (assert.eq! (vec.get [10 20 30] 0) 10) + (assert.eq! (vec.get [10 20 30] 1) 20) + (assert.eq! (vec.get [10 20 30] 2) 30) + ) + + (test.case "vec.map" + (assert.eq! + (vec.map (lambda [x _] (+ x 1)) [1 2 3]) + [2 3 4]) + ) + + (test.case "vec.filter" + (assert.eq! + (vec.filter (lambda [x _] (gt? x 1)) [1 2 3]) + [2 3]) + ) + + (test.case "vec.has" + (assert.ok! (vec.has [1 2 3] 2)) + (assert.not! (vec.has [1 2 3] 5)) + ) + + (test.case "vec.includes?" + (assert.ok! (vec.includes? [1 2 3] 2)) + (assert.not! (vec.includes? [1 2 3] 5)) + ) + + (test.case "vec.find" + (assert.eq! + (vec.find (lambda [x _] (gt? x 2)) [1 2 3 4]) + 3) + ) + + (test.case "vec.reverse" + (assert.eq! (vec.reverse [1 2 3]) [3 2 1]) + ) + + (test.case "vec.take" + (assert.eq! (vec.take [1 2 3 4 5] 3) [1 2 3]) + ) + + (test.case "vec.drop" + (assert.eq! (vec.drop [1 2 3 4 5] 2) [3 4 5]) + ) + + (test.case "vec.uniq" + (assert.eq! (vec.uniq [1 2 2 3 3 3]) [1 2 3]) + ) + + (test.case "vec.every?" + (assert.ok! (vec.every? (lambda [x _] (gt? x 0)) [1 2 3])) + (assert.not! (vec.every? (lambda [x _] (gt? x 1)) [1 2 3])) + ) + + (test.case "vec.some?" + (assert.ok! (vec.some? (lambda [x _] (gt? x 2)) [1 2 3])) + (assert.not! (vec.some? (lambda [x _] (gt? x 5)) [1 2 3])) + ) + + (test.case "vec.count" + (assert.eq! (vec.count (lambda [x _] (gt? x 1)) [1 2 3]) 2) + ) + + (test.case "vec.sum" + (assert.eq! (vec.sum [1 2 3]) 6) + (assert.eq! (vec.sum []) 0) + ) +) diff --git a/modules/core/types/bool.owa b/modules/core/types/bool.owa new file mode 100644 index 0000000..94a88a0 --- /dev/null +++ b/modules/core/types/bool.owa @@ -0,0 +1,23 @@ +(seq + (def true :true) + (def false :false) + (fn bool? [x] + (bool.or (eq? x true) (eq? x false))) + + (namespace bool + (fn new [x] + (eq? x true)) + (def __call__ new) + + (defmacro or [] + (if-eq (false $%%) false true)) + + (defmacro and [] + (if-has false ($%%) false true)) + + (defmacro nand [] + (if-has false ($%%) true false)) + + (fn not [x] + (if-eq (x true) false true)) + )) diff --git a/modules/core/types/main.owa b/modules/core/types/main.owa new file mode 100644 index 0000000..0e3b226 --- /dev/null +++ b/modules/core/types/main.owa @@ -0,0 +1,39 @@ +(seq + (def types [ + :symbol + :keyword + :str + :float + :int + :vec + :call + :set + :map + :quote + :lambda + :macro + ]) + + (fn is? [x type] + (eq? (typeof x) type)) + (fn guard [type] + (lambda [x] (is? x type))) + + (def kw? (guard :keyword)) + (def kw builtins.str.kw) + + (include "bool") + (include "map") + (include "null") + (include "option") + (include "set") + (include "str") + (include "struct") + (include "vec") + + (def vec? (guard :vec)) + (def map? (guard :map)) + + (fn type? [x] + (vec.has types x)) +) \ No newline at end of file diff --git a/modules/core/types/map.owa b/modules/core/types/map.owa new file mode 100644 index 0000000..8792960 --- /dev/null +++ b/modules/core/types/map.owa @@ -0,0 +1,94 @@ +(namespace map + (def type :map) + (def is? (guard type)) + (def new builtins.map.new) + (def __call__ new) + + (fn keys [m] + (vec.map #(vec.first %1) (vec.from m))) + + (fn values [m] + (vec.map #(vec.last %1) (vec.from m))) + + (fn len [m] + (vec.len (vec.from m))) + + (fn empty? [m] + (eq? (len m) 0)) + + (fn is-empty? [m] + (empty? m)) + + (fn get [m key] + (vec.fold + (lambda [result pair _] + (if (eq? (vec.get pair 0) key) + (vec.get pair 1) + result)) + null + (vec.from m))) + + (fn put [m key value] + (apply apply new (vec.from m) [[key value]])) + + (fn assoc [m key value] + (put m key value)) + + (fn dissoc [m key] + (apply apply new (vec.filter + (lambda [pair _] (nq? + (vec.get pair 0) + key + )) + (vec.from m)) + )) + + (fn has-key? [m key] + (if (null? (get m key)) + false + true)) + + (fn has-value? [m value] + (vec.fold + (lambda [result pair _] + (seq + (def k (vec.get pair 0)) + (def v (vec.get pair 1)) + (bool.or result (eq? v value)))) + false + (vec.from m))) + + (fn map [callback m] + (apply new (vec.apply-flat (vec.map + (lambda [pair _] + (seq + (def k (vec.get pair 0)) + (def v (vec.get pair 1)) + (def new-v (callback v k)) + [k new-v])) + (vec.from m))))) + + (fn filter [callback m] + (apply new (vec.apply-flat (vec.filter + (lambda [pair _] + (seq + (def k (vec.get pair 0)) + (def v (vec.get pair 1)) + (callback v k))) + (vec.from m))))) + + (fn merge [m1 m2] + (apply apply new (vec.from m1) (vec.from m2))) + + (fn merge-all [] + (vec.fold + (lambda [acc m _] + (merge acc m)) + (new) + %%)) + + (fn conj [m other] + (if (map.is? other) + (merge m other) + m)) +) \ No newline at end of file diff --git a/modules/core/types/null.owa b/modules/core/types/null.owa new file mode 100644 index 0000000..2db4848 --- /dev/null +++ b/modules/core/types/null.owa @@ -0,0 +1,5 @@ +(seq + (def null :null) + (fn null? [x] + (bool.or (eq? x null) (eq? x :nil))) +) \ No newline at end of file diff --git a/modules/core/types/option.owa b/modules/core/types/option.owa new file mode 100644 index 0000000..422521d --- /dev/null +++ b/modules/core/types/option.owa @@ -0,0 +1,26 @@ +(seq + (namespace option + (fn ok