diff --git a/.gitignore b/.gitignore index 600e41b..1c2b160 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ /mers/target /mers/Cargo.lock +/mers_lib/target +/mers_lib/Cargo.lock +/mers_old/target +/mers_old/Cargo.lock /mers_libs/*/target /mers_libs/*/Cargo.lock /build_scripts/nu_plugin_mers diff --git a/README.md b/README.md index a72f58a..e3aa52e 100755 --- a/README.md +++ b/README.md @@ -1,302 +1,54 @@ -# mers ![build status](https://github.com/Dummi26/mers/actions/workflows/rust.yml/badge.svg) +# mers -Mers is a simple and reliable programming language. +Mers is getting a rewrite! -While mers can already be used right now, -many things about it will still change - -at least until 1.0.0 is released. -For serious projects, this probably -isn't the language you should be using. +This means that this README isn't complete, +many things will change, +and the docs/ are for a completely different language. -## Why mers? +## why mers? -### it doesn't crash +### Simplicity -If your program starts, **it won't crash**. -The only exceptions to this are -the builtin `exit()` function, which can exit with a nonzero exit code -and the builtin `assume` functions, similar to Rust's `unwrap()`. +Mers aims to be very simple, as in, having very few "special" things. +But this means that many things you may be familiar with simply don't exist in mers, +because they aren't actually needed. +This includes: -This is because **errors in mers are values**, -and the compiler forces you to handle them. +**Exceptions**, because errors in mers are values just like any other. +A function to read a UTF-8 text file from disk could have a return type like `String/IOError/UTF8DecodeError`, +which tells you exactly what errors can happen and also forces you to handle them (see later for mers' type-system). -### type system +**Loops**, because, as it turns out, a function which takes an iterable and a function can do this just fine. +Javascript has `forEach`, Rust `for_each`, C# `Each`, and Java has `forEach`. +At first, it seemed stupid to have a function that does the same thing a `for` or `foreach` loop can already do, +but if a function can do the job, why do we even need a special language construct to do this for us? +To keep it simple, mers doesn't have any loops except for `loop`. +`loop` simply repeats until the inner expression returns `(T)`, which causes loop to return `T`. -In mers, a type can consist of multiple types: +**Breaks** aren't necessary, since this can be achieved using iterator magic or by returning `(T)` in a `loop`. +It is also similar to `goto`, because it makes control flow less obvious, so it had to go. -``` -// bool -half := true -// float/int -number := if half { 0.5 } else { 1 } +The same control flow obfuscation issue exists for **returns**, so these also aren't a thing. +A function simply returns the value created by its expression. -// some math functions that work with int and float -fn absolute_value(num int/float) { - if num >= 0 { num } else { 0 - num } -} -fn difference(a int/float, b int/float) { - absolute_value(a - b) -} +**Functions** do exist, but they have one key difference: They take exactly one argument. Always. +Why? Because we don't need anything else. +A function with no arguments now takes an empty tuple `()`, +a function with two arguments now takes a two-length tuple `(a, b)`, +a function with either zero, one, or three arguments now takes a `()/(a)/(a, b, c)`, +and a function with n args takes a list, or a list as part of a tuple, or an optional list via `()/`. -debug(difference(0.2, 2)) // float: 1.8 -// although difference can work with floats, since we only give it ints, it also returns an int. -// this is known at compile time. -debug(difference(20, 5)) // int: 15 -``` +### Types -With this, you can write code like you would in dynamically typed languages: +Mers is built around a type-system where a value could be one of multiple types. +This is basically what dynamic typing allows you to do: -``` -user_input := if true { "some text input" } else { 19 } -``` + x := if condition { 12 } else { "something went wrong" } -But you get the compile-time checks you love from statically typed ones: +This would be valid code. +However, in mers, the compiler still tracks all the types in your program, +and it will catch every possible crash before the program even runs: +If we tried to use `x` as an Int, the compiler would complain since it might be a string. -``` -if user_input >= min_age { - println("welcome!") -} -``` - -Because `user_input` could be a string, the code above won't compile. - -### it's simple - -Almost everything in mers is built around this type system. -This eliminates many concepts you may be familiar with: - -#### instead of null or exceptions, just add `[]` or the error(s) to the return type - -``` -// returns `[]` instead of dividing by zero -fn div_checked(a int, b int) -> int/[] { - if b != 0 { - a / b - } else { - [] - } -} - -// returns the file content as a string. -// if the file can't be read, returns IoError and an error message. -// if the file's contents weren't Utf8, return NotUtf8 and the file's bytes. -fn load_file_as_string(path string) -> string/IoError(string)/NotUtf8([int ...]) {} -``` - -#### structs are nothing more than tuples - -``` -// define our type named Person -type Person [int, string] - -// function to get (but not set) the person's birth year -fn birth_year(self Person) self.0 - -// function to get or set the person's name -fn name(self Person/&Person) self.1 - -person := [1999, "Ryan"] - -// Get the values -person.name() // Ryan -person.birth_year() // 1999 - -// Change the name -&person.name() = "James" -// or: name(&person) = "James" -person.name() // James - -// This doesn't compile: -// &person.birth_year() = 1998 -``` - -#### enums are already part of the type system - -``` -type DirectoryEntry File(string)/Dir(string)/Link(DirectoryEntry) -``` - -#### return and break - -Most people agree that `goto` statements are usually a bad idea. -But `return` and `break` have similar issues, although less severe: - -**they create weird control flow:** - -Maybe you want to see how long a function takes to execute, so -you add a `println` to the end - just to see absolutely no output. -Now you might think the function is stuck in an infinite loop somewhere, -although it just returned before it ever got to your println. -This can be annoying. If we remove `return` statements, -it becomes way easier to tell when code will or won't be executed. - -**return is exclusive to functions, break to loops** - -With mers, whenever possible, concepts in the language should work on *statements*. - -An example of this are type annotations: - -``` -fn half(num int) -> int { num / 2 } -``` - -The `-> int` indicates that this function returns an int. -Actually, it indicates that the statement following it returns an int. -This obviously means the function will also return an int, -but since this syntax isn't specifically made for functions, -we can use it anywhere we want: - -``` -num := -> int { 4 + 5 } -half(-> int { double * 2}) -``` - -**So how do we return values then?** -Simple! - -``` -// a function is just another statement -fn return_int() 4 + 5 - -// a block returns whatever its last statement returns, -fn return_string() { - a := "start" - b := "end" - a + " " + b -} - -// this returns string/[], because there is no else -if condition() { - "some value" -} - -// this returns string/int -if condition() { - "some value" -} else { - 12 -} -``` - -Most returns should be relatively intuitive, -although some special ones (like loops) -use matching (see docs/intro) - -### it has references - -To explain why this is necessary, -let's look at examples from other languages. - -Here is some JavaScript: - -```js -function doSmth(list) { - list[0] = 0 -} -function modify(num) { - num = 0 -} -list = [1] -num = 1 -doSmth(list) -modify(num) -console.log(list) // [ 0 ] -console.log(num) // 1 -``` - -The same thing in Go: - -```go -package main -import "fmt" - -func doSmth(list []int) { - list[0] = 0 -} -func modify(num int) { - num = 0 -} -func main() { - list := []int{1} - num := 1 - doSmth(list) - modify(num) - fmt.Println(list) // [0] - fmt.Println(num) // 1 -} -``` - -In both cases, the function was able to modify the list's contents, -but unable to change the number to a different value. -This is not just inconsistent, it's also not always what you wanted to do: - -- i passed the list by value, how could the function change the inner value? -- the function is called `modify`, why can't it modify the value? - + In Go, we could use references to make this work - but that just makes the list example even more annoying, since we don't need a reference to change the inner value. - -So, let's look at mers: - -``` -fn doSmth(list [int ...]) { - &list.get(0).assume1() = 0 -} -fn modify(num &int) { - num = 0 -} -list := [1 ...] -num := 1 -doSmth(list) -modify(&num) -debug(list) // [1 ...] -debug(num) // 0 -``` - -The list is unchanged, but the number was changed by `modify`, -because it was explicitly passed as a reference `&int`. -**Unless you pass a reference, the value you passed will not be changed.** - -### compile-time execution via macros - -``` -// at compile-time, runs primes.mers to find the first few prime numbers -primes := !(mers "primes.mers") - -// at compile-time, runs the code to create a string -// containing 256 '-'s -long_string := !(mers { - str := "-" - loop { - str = str + str - if str.len() >= 256 { - str - } - } -}) -``` - -## How mers? - -There are prebuilt binaries in `build_scripts/`. - -Mers is written in Rust. If you have `cargo`, you can also use the build script in `build_scripts/` to build it yourself. - -Now, create a new text file (or choose one from the examples) and run it: `mers `. - -## Known Issues (only major ones) - -### Multithreading - -If a function is called from two threads, all local variables of that function are shared. -This doesn't affect builtin functions, and since functions usually don't take long to execute, -the chance of anyone encountering this is low, but it's something to be aware of. -It's a simple fix in theory, but a lot of work to implement, which is why the bug isn't fixed yet. - -## Docs - -[intro](docs/intro.md) - -[syntax cheat sheet](docs/syntax_cheat_sheet.md) - -[builtins](docs/builtins.md) - -[statements](docs/statements.md) +(note: type-checks aren't implemented since the rewrite is just barely functional, but they will be there and fully working soon) diff --git a/README_old.md b/README_old.md new file mode 100755 index 0000000..a72f58a --- /dev/null +++ b/README_old.md @@ -0,0 +1,302 @@ +# mers ![build status](https://github.com/Dummi26/mers/actions/workflows/rust.yml/badge.svg) + +Mers is a simple and reliable programming language. + +While mers can already be used right now, +many things about it will still change - +at least until 1.0.0 is released. +For serious projects, this probably +isn't the language you should be using. + +## Why mers? + +### it doesn't crash + +If your program starts, **it won't crash**. +The only exceptions to this are +the builtin `exit()` function, which can exit with a nonzero exit code +and the builtin `assume` functions, similar to Rust's `unwrap()`. + +This is because **errors in mers are values**, +and the compiler forces you to handle them. + +### type system + +In mers, a type can consist of multiple types: + +``` +// bool +half := true +// float/int +number := if half { 0.5 } else { 1 } + +// some math functions that work with int and float +fn absolute_value(num int/float) { + if num >= 0 { num } else { 0 - num } +} +fn difference(a int/float, b int/float) { + absolute_value(a - b) +} + +debug(difference(0.2, 2)) // float: 1.8 +// although difference can work with floats, since we only give it ints, it also returns an int. +// this is known at compile time. +debug(difference(20, 5)) // int: 15 +``` + +With this, you can write code like you would in dynamically typed languages: + +``` +user_input := if true { "some text input" } else { 19 } +``` + +But you get the compile-time checks you love from statically typed ones: + +``` +if user_input >= min_age { + println("welcome!") +} +``` + +Because `user_input` could be a string, the code above won't compile. + +### it's simple + +Almost everything in mers is built around this type system. +This eliminates many concepts you may be familiar with: + +#### instead of null or exceptions, just add `[]` or the error(s) to the return type + +``` +// returns `[]` instead of dividing by zero +fn div_checked(a int, b int) -> int/[] { + if b != 0 { + a / b + } else { + [] + } +} + +// returns the file content as a string. +// if the file can't be read, returns IoError and an error message. +// if the file's contents weren't Utf8, return NotUtf8 and the file's bytes. +fn load_file_as_string(path string) -> string/IoError(string)/NotUtf8([int ...]) {} +``` + +#### structs are nothing more than tuples + +``` +// define our type named Person +type Person [int, string] + +// function to get (but not set) the person's birth year +fn birth_year(self Person) self.0 + +// function to get or set the person's name +fn name(self Person/&Person) self.1 + +person := [1999, "Ryan"] + +// Get the values +person.name() // Ryan +person.birth_year() // 1999 + +// Change the name +&person.name() = "James" +// or: name(&person) = "James" +person.name() // James + +// This doesn't compile: +// &person.birth_year() = 1998 +``` + +#### enums are already part of the type system + +``` +type DirectoryEntry File(string)/Dir(string)/Link(DirectoryEntry) +``` + +#### return and break + +Most people agree that `goto` statements are usually a bad idea. +But `return` and `break` have similar issues, although less severe: + +**they create weird control flow:** + +Maybe you want to see how long a function takes to execute, so +you add a `println` to the end - just to see absolutely no output. +Now you might think the function is stuck in an infinite loop somewhere, +although it just returned before it ever got to your println. +This can be annoying. If we remove `return` statements, +it becomes way easier to tell when code will or won't be executed. + +**return is exclusive to functions, break to loops** + +With mers, whenever possible, concepts in the language should work on *statements*. + +An example of this are type annotations: + +``` +fn half(num int) -> int { num / 2 } +``` + +The `-> int` indicates that this function returns an int. +Actually, it indicates that the statement following it returns an int. +This obviously means the function will also return an int, +but since this syntax isn't specifically made for functions, +we can use it anywhere we want: + +``` +num := -> int { 4 + 5 } +half(-> int { double * 2}) +``` + +**So how do we return values then?** +Simple! + +``` +// a function is just another statement +fn return_int() 4 + 5 + +// a block returns whatever its last statement returns, +fn return_string() { + a := "start" + b := "end" + a + " " + b +} + +// this returns string/[], because there is no else +if condition() { + "some value" +} + +// this returns string/int +if condition() { + "some value" +} else { + 12 +} +``` + +Most returns should be relatively intuitive, +although some special ones (like loops) +use matching (see docs/intro) + +### it has references + +To explain why this is necessary, +let's look at examples from other languages. + +Here is some JavaScript: + +```js +function doSmth(list) { + list[0] = 0 +} +function modify(num) { + num = 0 +} +list = [1] +num = 1 +doSmth(list) +modify(num) +console.log(list) // [ 0 ] +console.log(num) // 1 +``` + +The same thing in Go: + +```go +package main +import "fmt" + +func doSmth(list []int) { + list[0] = 0 +} +func modify(num int) { + num = 0 +} +func main() { + list := []int{1} + num := 1 + doSmth(list) + modify(num) + fmt.Println(list) // [0] + fmt.Println(num) // 1 +} +``` + +In both cases, the function was able to modify the list's contents, +but unable to change the number to a different value. +This is not just inconsistent, it's also not always what you wanted to do: + +- i passed the list by value, how could the function change the inner value? +- the function is called `modify`, why can't it modify the value? + + In Go, we could use references to make this work - but that just makes the list example even more annoying, since we don't need a reference to change the inner value. + +So, let's look at mers: + +``` +fn doSmth(list [int ...]) { + &list.get(0).assume1() = 0 +} +fn modify(num &int) { + num = 0 +} +list := [1 ...] +num := 1 +doSmth(list) +modify(&num) +debug(list) // [1 ...] +debug(num) // 0 +``` + +The list is unchanged, but the number was changed by `modify`, +because it was explicitly passed as a reference `&int`. +**Unless you pass a reference, the value you passed will not be changed.** + +### compile-time execution via macros + +``` +// at compile-time, runs primes.mers to find the first few prime numbers +primes := !(mers "primes.mers") + +// at compile-time, runs the code to create a string +// containing 256 '-'s +long_string := !(mers { + str := "-" + loop { + str = str + str + if str.len() >= 256 { + str + } + } +}) +``` + +## How mers? + +There are prebuilt binaries in `build_scripts/`. + +Mers is written in Rust. If you have `cargo`, you can also use the build script in `build_scripts/` to build it yourself. + +Now, create a new text file (or choose one from the examples) and run it: `mers `. + +## Known Issues (only major ones) + +### Multithreading + +If a function is called from two threads, all local variables of that function are shared. +This doesn't affect builtin functions, and since functions usually don't take long to execute, +the chance of anyone encountering this is low, but it's something to be aware of. +It's a simple fix in theory, but a lot of work to implement, which is why the bug isn't fixed yet. + +## Docs + +[intro](docs/intro.md) + +[syntax cheat sheet](docs/syntax_cheat_sheet.md) + +[builtins](docs/builtins.md) + +[statements](docs/statements.md) diff --git a/build_scripts/mers b/build_scripts/mers index be75827..1c31c8d 100755 Binary files a/build_scripts/mers and b/build_scripts/mers differ diff --git a/mers/Cargo.lock b/mers/Cargo.lock index 0e6882e..3e3741b 100755 --- a/mers/Cargo.lock +++ b/mers/Cargo.lock @@ -3,114 +3,59 @@ version = 3 [[package]] -name = "ahash" -version = "0.7.6" +name = "anstream" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" dependencies = [ - "getrandom", - "once_cell", - "version_check", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", ] [[package]] -name = "ahash" -version = "0.8.3" +name = "anstyle" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ - "cfg-if", - "once_cell", - "version_check", + "utf8parse", ] [[package]] -name = "aho-corasick" -version = "0.7.20" +name = "anstyle-query" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "memchr", + "windows-sys", ] [[package]] -name = "android_system_properties" -version = "0.1.5" +name = "anstyle-wincon" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ - "libc", + "anstyle", + "windows-sys", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" -version = "1.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bumpalo" -version = "3.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" - -[[package]] -name = "byte-unit" -version = "4.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da78b32057b8fdfc352504708feeba7216dcd65a2c9ab02978cbd288d1279b6c" -dependencies = [ - "serde", - "utf8-width", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cc" @@ -119,209 +64,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] -name = "cfg-if" +name = "clap" +version = "4.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-integer", - "num-traits", - "serde", - "time", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "chrono-humanize" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e" -dependencies = [ - "chrono", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "colorize" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc17e449bc7854c50b943d113a98bc0e01dc6585d2c66eaa09ca645ebd8a7e62" - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" -dependencies = [ - "winapi", -] - -[[package]] -name = "ctor" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b" -dependencies = [ - "quote", - "syn 2.0.15", -] - -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "edit" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c562aa71f7bc691fde4c6bf5f93ae5a5298b617c2eb44c76c87832299a17fbb4" -dependencies = [ - "tempfile", - "which", -] - -[[package]] -name = "either" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - -[[package]] -name = "erased-serde" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" -dependencies = [ - "serde", -] +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "errno" @@ -331,7 +118,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -344,86 +131,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fancy-regex" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" -dependencies = [ - "bit-set", - "regex", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "filetime" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", -] - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "getrandom" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "ghost" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77ac7b51b8e6313251737fcef4b1c01a2ea102bde68415b62c0ee9268fec357" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.3", -] - [[package]] name = "heck" version = "0.4.1" @@ -432,894 +139,104 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "iana-time-zone" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" -dependencies = [ - "cxx", - "cxx-build", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "inventory" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7741301a6d6a9b28ce77c0fb77a4eb116b6bc8f3bef09923f7743d059c4157d3" -dependencies = [ - "ctor", - "ghost", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", + "hermit-abi", "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "is_ci" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" - -[[package]] -name = "itoa" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" - -[[package]] -name = "js-sys" -version = "0.3.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kqueue" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" -dependencies = [ - "bitflags", - "libc", + "windows-sys", ] [[package]] name = "libc" -version = "0.2.141" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" - -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.3.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "lru" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03f1160296536f10c833a82dca22267d5486734230d47bf00bf435885814ba1e" -dependencies = [ - "hashbrown 0.13.2", -] - -[[package]] -name = "lscolors" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a9df1d1fb6d9e92fa043e9eb9a3ecf6892c7b542bae5137cd1e419e40aa8bf" -dependencies = [ - "nu-ansi-term", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "mers" -version = "0.2.3" +version = "0.1.0" dependencies = [ - "colorize", - "edit", - "notify", - "nu-plugin", - "nu-protocol", - "regex", - "static_assertions", + "clap", + "mers_lib", ] [[package]] -name = "miette" -version = "5.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a992891d5579caa9efd8e601f82e30a1caa79a27a5db075dde30ecb9eab357" -dependencies = [ - "is-terminal", - "miette-derive", - "once_cell", - "owo-colors", - "supports-color", - "supports-hyperlinks", - "supports-unicode", - "terminal_size", - "textwrap", - "thiserror", - "unicode-width", -] - -[[package]] -name = "miette-derive" -version = "5.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c65c625186a9bcce6699394bee511e1b1aec689aa7e3be1bf4e996e75834153" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "mio" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", -] - -[[package]] -name = "notify" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" -dependencies = [ - "bitflags", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "mio", - "walkdir", - "windows-sys 0.42.0", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df031e117bca634c262e9bd3173776844b6c17a90b3741c9163663b4385af76" -dependencies = [ - "windows-sys 0.45.0", -] - -[[package]] -name = "nu-engine" -version = "0.79.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455c2a146f423a98e94d5e040ef8203c175c6490b72c24cc44772af13bc92514" -dependencies = [ - "chrono", - "nu-glob", - "nu-path", - "nu-protocol", - "nu-utils", - "serde", - "sysinfo", -] - -[[package]] -name = "nu-glob" -version = "0.79.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34b6c41c483b7495817f45d54d8424fc26e5299361613219525d5e4dc208148" - -[[package]] -name = "nu-path" -version = "0.79.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fd966d2ca1e2a42465bdcee76e18826834ee58c321bd5124421843bc25b680" -dependencies = [ - "dirs-next", - "omnipath", - "pwd", -] - -[[package]] -name = "nu-plugin" -version = "0.79.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb0b0dad67069d1d4697d1033ce1cd427b8408107dc27522b1b89446f551aad" -dependencies = [ - "bincode", - "nu-engine", - "nu-protocol", - "rmp", - "rmp-serde", - "serde", - "serde_json", -] - -[[package]] -name = "nu-protocol" -version = "0.79.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239c539e019a3e74b7222febbd1d18ab89be817540e91375d8c05a5156589b67" -dependencies = [ - "byte-unit", - "chrono", - "chrono-humanize", - "fancy-regex", - "indexmap", - "lru", - "miette", - "nu-utils", - "num-format", - "serde", - "serde_json", - "strum", - "strum_macros", - "sys-locale", - "thiserror", - "typetag", -] - -[[package]] -name = "nu-utils" -version = "0.79.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9477ebed0389c3224143466b084e10b0b615b5d6930f55a80d2aee3447b62ffc" -dependencies = [ - "crossterm_winapi", - "log", - "lscolors", - "num-format", - "strip-ansi-escapes", - "sys-locale", -] - -[[package]] -name = "num-format" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" -dependencies = [ - "arrayvec 0.7.2", - "itoa", -] - -[[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-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - -[[package]] -name = "omnipath" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68432e1692e9b974a51efd452485db50f92827fe0931d16721ad867633a571b6" +name = "mers_lib" +version = "0.3.0" [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" - -[[package]] -name = "owo-colors" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" - -[[package]] -name = "paste" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] -[[package]] -name = "pwd" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c71c0c79b9701efe4e1e4b563b2016dd4ee789eb99badcb09d61ac4b92e4a2" -dependencies = [ - "libc", - "thiserror", -] - [[package]] name = "quote" -version = "1.0.26" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "rmp" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - [[package]] name = "rustix" -version = "0.37.11" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ "bitflags", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] -name = "rustversion" -version = "1.0.12" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" - -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - -[[package]] -name = "serde" -version = "1.0.160" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.160" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "smawk" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strip-ansi-escapes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" -dependencies = [ - "vte", -] - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "supports-color" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354" -dependencies = [ - "is-terminal", - "is_ci", -] - -[[package]] -name = "supports-hyperlinks" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" -dependencies = [ - "is-terminal", -] - -[[package]] -name = "supports-unicode" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" -dependencies = [ - "is-terminal", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sys-locale" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0b9eefabb91675082b41eb94c3ecd91af7656caee3fb4961a07c0ec8c7ca6f" -dependencies = [ - "libc", - "windows-sys 0.45.0", -] - -[[package]] -name = "sysinfo" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2f3ca6693feb29a89724516f016488e9aafc7f37264f898593ee4b942f31b" -dependencies = [ - "cfg-if", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi", -] - -[[package]] -name = "tempfile" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys 0.45.0", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "textwrap" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" -dependencies = [ - "smawk", - "unicode-linebreak", - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "typetag" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6898cc6f6a32698cc3e14d5632a14d2b23ed9f7b11e6b8e05ce685990acc22" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] - -[[package]] -name = "typetag-impl" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3e1c30cedd24fc597f7d37a721efdbdc2b1acae012c1ef1218f4c7c2c0f3e7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" - -[[package]] -name = "unicode-linebreak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" -dependencies = [ - "hashbrown 0.12.3", - "regex", -] - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "utf8-width" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "utf8parse" @@ -1327,301 +244,66 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "vte" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" -dependencies = [ - "arrayvec 0.5.2", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" - -[[package]] -name = "which" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" -dependencies = [ - "either", - "libc", - "once_cell", -] - -[[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-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[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" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/mers/Cargo.toml b/mers/Cargo.toml index 94b6469..f0673a3 100755 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,26 +1,10 @@ [package] name = "mers" -version = "0.2.3" +version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[lib] -name = "mers_libs" -path = "src/lib.rs" - [dependencies] -edit = "0.1.4" -notify = "5.1.0" -regex = "1.7.2" -static_assertions = "1.1.0" -nu-plugin = { version = "0.79.0", optional = true } -nu-protocol = { version = "0.79.0", features = ["plugin"], optional = true } -colorize = "0.1.0" - -[features] -# default = ["nushell_plugin"] -nushell_plugin = ["dep:nu-plugin", "dep:nu-protocol"] - -[profile.nushellplugin] -inherits = "release" +mers_lib = { path = "../mers_lib" } +clap = { version = "4.3.19", features = ["derive"] } diff --git a/mers/src/main.rs b/mers/src/main.rs index a50a190..fb073d7 100755 --- a/mers/src/main.rs +++ b/mers/src/main.rs @@ -1,245 +1,53 @@ -use lang::global_info::ColorFormatMode; -use lang::global_info::GlobalScriptInfo; -use lang::global_info::LogKind; -use lang::val_data::VDataEnum; -use lang::val_type::VSingleType; +use clap::{Parser, Subcommand, ValueEnum}; +use mers_lib::prelude_compile::*; +use std::{fmt::Display, fs, path::PathBuf}; -use crate::lang::fmtgs::FormatGs; - -mod interactive_mode; -mod lang; -mod libs; -#[cfg(feature = "nushell_plugin")] -mod nushell_plugin; -mod parsing; -mod pathutil; -mod tutor; - -fn main() { - #[cfg(not(feature = "nushell_plugin"))] - normal_main(); - #[cfg(feature = "nushell_plugin")] - nushell_plugin::main(); +#[derive(Parser)] +struct Args { + #[arg(long, value_enum, default_value_t = Configs::Std)] + config: Configs, + #[command(subcommand)] + command: Command, } - -fn normal_main() { - let args: Vec<_> = std::env::args().skip(1).collect(); - let mut info = GlobalScriptInfo::default(); - let mut run = true; - let mut args_to_skip = 2; - let mut file = match args.len() { - 0 => { - println!("no arguments, use -h for help"); - std::process::exit(100); - } - _ => { - if args[0].trim_start().starts_with("-") { - let mut execute = false; - let mut print_version = false; - let mut verbose = false; - let mut verbose_args = String::new(); - let mut interactive = 0; - let mut interactive_use_new_terminal = false; - let mut teachme = false; - let mut prev_char = None; - let mut advanced = false; - for ch in args[0][1..].chars() { - if !advanced { - if ch == '+' { - advanced = true; - continue; - } - match ch { - 'h' => { - eprintln!("~~~~ mers help ~~~~"); - eprintln!(); - eprintln!(" ~~ cli ~~"); - eprintln!("Mers has the following cli options:"); - eprintln!("-h shows this Help message"); - eprintln!("-e - mers will treat the run argument as code to be Executed rather than a file path"); - eprintln!(" mers -e 'println(\"Hello, World!\")'"); - eprintln!( - "-c - mers will Check the code for errors, but won't run it" - ); - eprintln!("-f - mers will Format the code and print it. useful if you suspect the parser might be misinterpreting your code"); - eprintln!( - "+c - use Colors in the output to better visualize things" - ); - eprintln!("+C - don't use colors (opposite of +c, redundant since this is the default)"); - eprintln!("-v - mers will be more Verbose"); - eprintln!("+???+ - customize what mers is verbose about and how - bad syntax, barely useful, don't use it until it gets improved (TODO!)"); - eprintln!("-i - launches an Interactive session to play around with (opens your editor and runs code on each file save)"); - eprintln!("+t - spawns a new terminal for the editor (if you use a terminal editors, add +t)"); - eprintln!(" mers -i+t"); - eprintln!("-t - launches the Tutor, which will attempt to Teach you the basics of the language"); - eprintln!(); - eprintln!(" ~~ getting started ~~"); - eprintln!("mers doesn't need a specific structure for directories, just create a UTF-8 text file, write code, and run it:"); - eprintln!(" echo 'println(\"Hello, World!\")' > hello.mers"); - eprintln!(" mers hello.mers"); - return; - } - 'e' => execute = true, - 'v' => verbose = true, - 'c' => run = false, - 'f' => { - run = false; - info.log.after_parse.stderr = true; - } - 'V' => print_version = true, - 'i' => interactive += 1, - 't' => teachme = true, - ch => { - eprintln!("Ignoring -{ch}. (unknown char)"); - continue; - } - } - prev_char = Some(ch); - } else { - advanced = false; - if let Some(prev_char) = prev_char { - match prev_char { - 'i' => match ch { - 't' => interactive_use_new_terminal = true, - _ => eprintln!("Ignoring i+{ch}. (unknown adv char)"), - }, - 'v' => { - if ch != '+' { - advanced = true; - verbose_args.push(ch); - } - } - 'f' => match ch { - 'c' => info.formatter.mode = ColorFormatMode::Colorize, - 'C' => info.formatter.mode = ColorFormatMode::Plain, - _ => eprintln!("Ignoring f+{ch}. (unknown adv char)"), - }, - _ => (), - } - } else { - eprintln!( - "Ignoring advanced args because there was no previous argument." - ); - } - } - } - if print_version { - println!( - "mers {}", - option_env!("CARGO_PKG_VERSION") - .unwrap_or("[[ version unknown: no CARGO_PKG_VERSION ]]") - ); - return; - } - if teachme { - tutor::start(false); - return; - } - if verbose { - if verbose_args.is_empty() { - fn f() -> LogKind { - LogKind { - stderr: true, - log: true, - } - } - info.log.vtype_fits_in = f(); - info.log.vsingletype_fits_in = f(); - } else { - fn kind(val: Option<&str>) -> LogKind { - match val { - Some("stderr") => LogKind { - stderr: true, - ..Default::default() - }, - Some("log") => LogKind { - log: true, - ..Default::default() - }, - Some("log+stderr" | "stderr+log") => LogKind { - stderr: true, - log: true, - ..Default::default() - }, - _ => LogKind { - stderr: true, - ..Default::default() - }, - } - } - for verbose_arg in verbose_args.split(',') { - let (arg, val) = match verbose_arg.split_once('=') { - Some((left, right)) => (left, Some(right)), - None => (verbose_arg, None), - }; - match arg { - "vtype_fits_in" => info.log.vtype_fits_in = kind(val), - "vsingletype_fits_in" => info.log.vsingletype_fits_in = kind(val), - _ => eprintln!("Warn: -v+ unknown arg '{arg}'."), - } - } - } - } - if interactive > 0 { - match interactive { - _ => { - // basic: open file and watch for fs changes - interactive_mode::fs_watcher::playground(interactive_use_new_terminal) - .unwrap() - } - }; - return; - } else if execute { - parsing::file::File::new( - args.iter().skip(1).fold(String::new(), |mut s, v| { - if !s.is_empty() { - s.push(' '); - } - s.push_str(v); - s - }), - std::path::PathBuf::new(), - ) - } else { - args_to_skip += 1; - if let Some(file) = args.get(1) { - parsing::file::File::new( - std::fs::read_to_string(file).unwrap(), - file.into(), - ) - } else { - println!("nothing to do - missing arguments?"); - std::process::exit(101); - } - } - } else { - parsing::file::File::new( - std::fs::read_to_string(&args[0]).unwrap(), - args[0].as_str().into(), - ) - } - } - }; - info.main_fn_args = vec![( - "args".to_string(), - VSingleType::List(VSingleType::String.into()).to(), - )]; - match parsing::parse::parse_custom_info(&mut file, info) { - Ok(script) => { - if run { - script.run(vec![VDataEnum::List( - VSingleType::String.to(), - std::env::args() - .skip(args_to_skip) - .map(|v| VDataEnum::String(v).to()) - .collect(), - ) - .to()]); - } - } - Err(e) => { - println!("Couldn't compile:\n{}", e.with_file(&file)); - std::process::exit(99); +#[derive(Subcommand)] +enum Command { + Run { file: PathBuf }, + Exec { source: String }, +} +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] +enum Configs { + None, + Std, +} +impl Display for Configs { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::None => write!(f, "none"), + Self::Std => write!(f, "std"), + } + } +} + +fn main() { + let args = Args::parse(); + let config = match args.config { + Configs::None => Config::new(), + Configs::Std => Config::new().bundle_std(), + }; + let (mut info1, mut info2) = config.infos(); + match args.command { + Command::Run { file } => { + let str = fs::read_to_string(file).unwrap(); + let mut src = Source::new(str); + let parsed = parse(&mut src).unwrap(); + let run = parsed.compile(&mut info1, Default::default()).unwrap(); + run.run(&mut info2); + } + Command::Exec { source } => { + let mut src = Source::new(source); + let parsed = parse(&mut src).unwrap(); + let run = parsed.compile(&mut info1, Default::default()).unwrap(); + run.run(&mut info2); } } } diff --git a/mers/test.mers b/mers/test.mers new file mode 100755 index 0000000..1af4528 --- /dev/null +++ b/mers/test.mers @@ -0,0 +1,15 @@ +list := ( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, +); +iter := (list item -> { item.println 12 }).map +"---".println +list := iter.as_list +list.println diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml new file mode 100755 index 0000000..60d5552 --- /dev/null +++ b/mers_lib/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "mers_lib" +version = "0.3.0" +edition = "2021" diff --git a/mers_lib/doc.md b/mers_lib/doc.md new file mode 100755 index 0000000..64de77b --- /dev/null +++ b/mers_lib/doc.md @@ -0,0 +1,53 @@ +# mers documentation + +## parsing + +syntax: + +- `// ` +- `/* */` + +operators: +- ` := ` init +- ` = ` assign (`` must be a reference) +- `+` +- `-` +- `*` +- `/` +- `%` +- `&` +- `|` +- `&&` +- `||` + +keywords (must be between whitespace): + +- `if ` +- `else ` (after `if`) +- `loop ` +- `switch { }` +- ` -> ` +- `def <: for types, = for comptime> <_>` for compile-time stuff (types, macros, ...) + +## details + +### functions + +A function takes an argument and returns some data: + + func := input -> input + 2 + 3.func.println // 5 + (list, 0).get // first element + (val, match -> match.println, [] -> "doesn't match".println).match + +### switch + + switch { + + } + + switch something { + int num -> {"int: " + num}.println + float num -> {"float: " + num}.println + } + diff --git a/mers_lib/init_to.rs b/mers_lib/init_to.rs new file mode 100755 index 0000000..22d29c1 --- /dev/null +++ b/mers_lib/init_to.rs @@ -0,0 +1,15 @@ +use crate::data::Data; + +use super::MersStatement; + +pub struct InitTo { + pub target: Box, + pub source: Box, +} + +impl MersStatement for InitTo { + fn has_scope(&self) -> bool { + false + } + fn run(&self, info: &mut super::Info) -> Data {} +} diff --git a/mers_lib/src/data/bool.rs b/mers_lib/src/data/bool.rs new file mode 100755 index 0000000..827b217 --- /dev/null +++ b/mers_lib/src/data/bool.rs @@ -0,0 +1,47 @@ +use std::{any::Any, fmt::Display}; + +use super::{MersData, MersType}; + +#[derive(Debug, Clone)] +pub struct Bool(pub bool); + +impl MersData for Bool { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +#[derive(Debug)] +pub struct BoolT; +impl MersType for BoolT { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other.as_any().downcast_ref::().is_some() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Display for Bool { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/mers_lib/src/data/defs.rs b/mers_lib/src/data/defs.rs new file mode 100755 index 0000000..48b1571 --- /dev/null +++ b/mers_lib/src/data/defs.rs @@ -0,0 +1,13 @@ +use super::Data; + +pub fn assign(from: Data, target: &Data) { + let mut target = target.get_mut(); + if let Some(r) = target + .mut_any() + .downcast_mut::() + { + *r.0.get_mut() = from.get().clone(); + } else { + todo!("assignment to non-reference") + } +} diff --git a/mers_lib/src/data/float.rs b/mers_lib/src/data/float.rs new file mode 100755 index 0000000..81a0e92 --- /dev/null +++ b/mers_lib/src/data/float.rs @@ -0,0 +1,47 @@ +use std::{any::Any, fmt::Display}; + +use super::{MersData, MersType, Type}; + +#[derive(Debug, Clone)] +pub struct Float(pub f64); + +impl MersData for Float { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +#[derive(Debug)] +pub struct FloatT; +impl MersType for FloatT { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other.as_any().downcast_ref::().is_some() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Display for Float { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/mers_lib/src/data/function.rs b/mers_lib/src/data/function.rs new file mode 100755 index 0000000..788c385 --- /dev/null +++ b/mers_lib/src/data/function.rs @@ -0,0 +1,79 @@ +use std::{ + any::Any, + fmt::{Debug, Display}, + sync::Arc, +}; + +use crate::program::{self, run::Info}; + +use super::{Data, MersData, MersType, Type}; + +#[derive(Clone)] +pub struct Function { + pub info: Info, + pub out: Arc Option>, + pub run: Arc Data>, +} +impl Function { + pub fn with_info(&self, info: program::run::Info) -> Self { + Self { + info, + out: Arc::clone(&self.out), + run: Arc::clone(&self.run), + } + } + pub fn run(&self, arg: Data) -> Data { + (self.run)(arg, &mut self.info.clone()) + } +} + +impl MersData for Function { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +pub struct FunctionT(Arc Option>); +impl MersType for FunctionT { + fn is_same_type_as(&self, _other: &dyn MersType) -> bool { + false + } + fn is_included_in_single(&self, _target: &dyn MersType) -> bool { + false + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Debug for Function { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Function") + } +} +impl Debug for FunctionT { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "FunctionT") + } +} + +impl Display for Function { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "") + } +} diff --git a/mers_lib/src/data/int.rs b/mers_lib/src/data/int.rs new file mode 100755 index 0000000..9f1200f --- /dev/null +++ b/mers_lib/src/data/int.rs @@ -0,0 +1,47 @@ +use std::{any::Any, fmt::Display}; + +use super::{MersData, MersType, Type}; + +#[derive(Debug, Clone)] +pub struct Int(pub isize); + +impl MersData for Int { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +#[derive(Debug)] +pub struct IntT; +impl MersType for IntT { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other.as_any().downcast_ref::().is_some() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Display for Int { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/mers_lib/src/data/mod.rs b/mers_lib/src/data/mod.rs new file mode 100755 index 0000000..9398989 --- /dev/null +++ b/mers_lib/src/data/mod.rs @@ -0,0 +1,155 @@ +use std::{ + any::Any, + fmt::{Debug, Display}, + sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; + +pub mod bool; +pub mod float; +pub mod function; +pub mod int; +pub mod reference; +pub mod string; +pub mod tuple; + +pub mod defs; + +pub trait MersData: Any + Debug + Display { + fn matches(&self) -> Option { + None + } + fn iterable(&self) -> Option>> { + None + } + /// By default, uses `iterable` to get an iterator and `nth` to retrieve the nth element. + /// Should have a custom implementation for better performance on most types + fn get(&self, i: usize) -> Option { + self.iterable()?.nth(i) + } + fn clone(&self) -> Box; + fn as_any(&self) -> &dyn Any; + fn mut_any(&mut self) -> &mut dyn Any; + fn to_any(self) -> Box; +} + +pub trait MersType: Any + Debug { + /// If Some((_, false)) is returned, data of this type could match. If it matches, it matches with the type. + /// If Some((_, true)) is returned, data of this type will always match with the type. + fn matches(&self) -> Option<(Type, bool)> { + None + } + /// If Some(T), calling `iterable` on the MersData this MersType belongs to + /// Should return Some(I), where I is an Iterator which only returns items of type T. + fn iterable(&self) -> Option { + None + } + /// If Some(T), calling `get` on data of this type may return T, but it might also return None. + /// By default, this returns the same thing as `iterable`, since this is also the default implementation for `MersData::get`. + fn get(&self) -> Option { + self.iterable() + } + /// If self and other are different types (`other.as_any().downcast_ref::().is_none()`), + /// this *must* return false. + fn is_same_type_as(&self, other: &dyn MersType) -> bool; + /// This doesn't handle the case where target is Type (is_included_in handles it) + fn is_included_in_single(&self, target: &dyn MersType) -> bool; + fn is_included_in(&self, target: &dyn MersType) -> bool { + if let Some(target) = target.as_any().downcast_ref::() { + target + .types + .iter() + .any(|t| self.is_included_in_single(t.as_ref())) + } else { + self.is_included_in_single(target) + } + } + fn as_any(&self) -> &dyn Any; + fn mut_any(&mut self) -> &mut dyn Any; + fn to_any(self) -> Box; +} + +#[derive(Debug)] +pub struct Data { + pub data: Arc>>, +} +impl Data { + pub fn new(data: T) -> Self { + Self::new_boxed(Box::new(data)) + } + pub fn new_boxed(data: Box) -> Self { + Self { + data: Arc::new(RwLock::new(data)), + } + } + pub fn empty_tuple() -> Self { + Self::new(tuple::Tuple(vec![])) + } + pub fn one_tuple(v: Self) -> Self { + Self::new(tuple::Tuple(vec![v])) + } + pub fn get(&self) -> RwLockReadGuard> { + self.data.read().unwrap() + } + pub fn get_mut(&self) -> RwLockWriteGuard> { + self.data.write().unwrap() + } +} +impl Clone for Data { + fn clone(&self) -> Self { + // todo!("clone for data - requires CoW"); + Self { + data: Arc::clone(&self.data), + } + } +} + +#[derive(Clone, Debug)] +pub struct Type { + // TODO: Maybe make sure this is always sorted by (recursive?!?) TypeId, + // that way is_same_type_as can work more efficiently (cuz good code but also branch prediction) + types: Vec>, +} +impl Type { + pub fn new(t: T) -> Self { + Self { + types: vec![Arc::new(t)], + } + } + pub fn newm(types: Vec>) -> Self { + Self { types } + } + pub fn empty_tuple() -> Self { + Self::new(tuple::TupleT(vec![])) + } + pub fn add(&mut self, new: Box) { + todo!() + } +} + +// PROBLEM: +// [int, int]/[int, string]/[string, int]/[string, string] +// is the same type as [int/string, int/string], +// but [int, int]/[int, string]/[string int] isn't. +// somehow, we need to merge these into the simplest form (same outer type, inner types differ) +// before we can implement `Type` +// idea: pick all the ones with the same first type: [int, int]/[int, string] and [string, int]/[string, string] +// then repeat with the second type if possible (here not, but for longer tuples, probably?) +// merge the last existing type in all the collections until we reach the first type again or the last types aren't equal anymore (how to check????) + +impl MersType for Type { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + todo!() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + todo!() + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} diff --git a/mers_lib/src/data/reference.rs b/mers_lib/src/data/reference.rs new file mode 100755 index 0000000..b026203 --- /dev/null +++ b/mers_lib/src/data/reference.rs @@ -0,0 +1,51 @@ +use std::{any::Any, fmt::Display, sync::Mutex}; + +use super::{Data, MersData, MersType, Type}; + +#[derive(Debug, Clone)] +pub struct Reference(pub Data); + +impl MersData for Reference { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +#[derive(Debug)] +pub struct ReferenceT(pub Type); +impl MersType for ReferenceT { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + if let Some(o) = other.as_any().downcast_ref::() { + self.0.is_same_type_as(&o.0) + } else { + false + } + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Display for Reference { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "&{}", self.0.get()) + } +} diff --git a/mers_lib/src/data/string.rs b/mers_lib/src/data/string.rs new file mode 100755 index 0000000..fb4d4bc --- /dev/null +++ b/mers_lib/src/data/string.rs @@ -0,0 +1,47 @@ +use std::{any::Any, fmt::Display}; + +use super::{MersData, MersType, Type}; + +#[derive(Debug, Clone)] +pub struct String(pub std::string::String); + +impl MersData for String { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +#[derive(Debug)] +pub struct StringT; +impl MersType for StringT { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other.as_any().downcast_ref::().is_some() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Display for String { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/mers_lib/src/data/tuple.rs b/mers_lib/src/data/tuple.rs new file mode 100755 index 0000000..0c197a5 --- /dev/null +++ b/mers_lib/src/data/tuple.rs @@ -0,0 +1,92 @@ +use std::{any::Any, fmt::Display}; + +use super::{Data, MersData, MersType, Type}; + +#[derive(Debug, Clone)] +pub struct Tuple(pub Vec); + +impl Tuple { + pub fn len(&self) -> usize { + self.0.len() + } + pub fn get(&self, i: usize) -> Option<&Data> { + self.0.get(i) + } +} + +impl MersData for Tuple { + fn matches(&self) -> Option { + if let Some(d) = self.0.first() { + if self.0.len() == 1 { + Some(d.clone()) + } else { + None + } + } else { + None + } + } + fn iterable(&self) -> Option>> { + Some(Box::new(self.0.clone().into_iter())) + } + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +#[derive(Debug)] +pub struct TupleT(pub Vec); +impl MersType for TupleT { + fn matches(&self) -> Option<(Type, bool)> { + if let Some(d) = self.0.first() { + if self.0.len() == 1 { + Some((d.clone(), true)) + } else { + None + } + } else { + None + } + } + fn iterable(&self) -> Option { + Some(todo!("joine types")) + } + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other.as_any().downcast_ref::().is_some() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} + +impl Display for Tuple { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(")?; + for (i, c) in self.0.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{}", c.get())?; + } + write!(f, ")")?; + Ok(()) + } +} diff --git a/mers_lib/src/info/mod.rs b/mers_lib/src/info/mod.rs new file mode 100755 index 0000000..feb822c --- /dev/null +++ b/mers_lib/src/info/mod.rs @@ -0,0 +1,58 @@ +use std::fmt::Debug; + +#[derive(Clone, Debug)] +pub struct Info { + pub scopes: Vec, +} + +impl Info { + /// Returns self, but completely empty (even without globals). + /// Only use this if you assume this Info will never be used. + pub fn neverused() -> Self { + Self { scopes: vec![] } + } +} + +pub trait Local: Default + Debug { + type VariableIdentifier; + type VariableData; + // type TypesIdentifier; + // type TypesType; + fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData); + fn get_var(&self, id: &Self::VariableIdentifier) -> Option<&Self::VariableData>; + fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData>; + // fn add_type(&mut self, id: Self::TypesIdentifier, new_type: Self::TypesType); + // fn get_type(&self, id: Self::TypesIdentifier) -> Option<&Self::TypesType>; +} + +impl Info { + pub fn create_scope(&mut self) { + self.scopes.push(L::default()) + } + /// WARNING: can remove the last scope, which can cause some other functions to panic. Use ONLY after a create_scope() + pub fn end_scope(&mut self) { + self.scopes.pop(); + } +} + +impl Local for Info { + type VariableIdentifier = L::VariableIdentifier; + type VariableData = L::VariableData; + fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) { + self.scopes.last_mut().unwrap().init_var(id, value) + } + fn get_var(&self, id: &Self::VariableIdentifier) -> Option<&Self::VariableData> { + self.scopes.iter().find_map(|l| l.get_var(id)) + } + fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> { + self.scopes.iter_mut().find_map(|l| l.get_var_mut(id)) + } +} + +impl Default for Info { + fn default() -> Self { + Self { + scopes: vec![L::default()], + } + } +} diff --git a/mers_lib/src/lib.rs b/mers_lib/src/lib.rs new file mode 100755 index 0000000..a496ab7 --- /dev/null +++ b/mers_lib/src/lib.rs @@ -0,0 +1,12 @@ +pub mod data; +pub mod info; +pub mod parsing; +pub mod program; + +pub mod prelude_compile { + pub use crate::parsing::parse; + pub use crate::parsing::Source; + pub use crate::program::configs::Config; + pub use crate::program::parsed::MersStatement as ParsedMersStatement; + pub use crate::program::run::MersStatement as RunMersStatement; +} diff --git a/mers_lib/src/parsing/errors.rs b/mers_lib/src/parsing/errors.rs new file mode 100755 index 0000000..e69de29 diff --git a/mers_lib/src/parsing/mod.rs b/mers_lib/src/parsing/mod.rs new file mode 100755 index 0000000..e9860f8 --- /dev/null +++ b/mers_lib/src/parsing/mod.rs @@ -0,0 +1,156 @@ +use std::sync::Arc; + +use crate::{ + info::Info, + program::{self, parsed::CompInfo}, +}; + +pub mod errors; +pub mod statements; +pub mod types; + +pub fn parse(src: &mut Source) -> Result, ()> { + Ok(Box::new(statements::parse_block(src)?)) +} + +pub struct Source { + src: String, + i: usize, + sections: Vec, +} +impl Source { + pub fn new(src: String) -> Self { + Self { + src, + i: 0, + sections: vec![], + } + } + + pub fn skip_whitespace(&mut self) { + if let Some(i) = self.src[self.i..].char_indices().find_map(|(i, ch)| { + if !ch.is_whitespace() { + Some(i) + } else { + None + } + }) { + self.i += i; + } else { + self.i = self.src.len(); + } + } + + fn end_sections(&mut self) { + let pos = self.get_pos(); + for section in self.sections.iter_mut() { + section.checked_end(pos); + } + } + + pub fn peek_char(&self) -> Option { + self.src[self.i..].chars().next() + } + pub fn next_char(&mut self) -> Option { + self.end_sections(); + let ch = self.src[self.i..].chars().next()?; + self.i += ch.len_utf8(); + Some(ch) + } + fn word_splitter(ch: char) -> bool { + ch.is_whitespace() || ".,;)}".contains(ch) + } + pub fn peek_word(&self) -> &str { + self.src[self.i..] + .split(Self::word_splitter) + .next() + .unwrap_or("") + } + pub fn next_word(&mut self) -> &str { + self.end_sections(); + let word = self.src[self.i..] + .split(Self::word_splitter) + .next() + .unwrap_or(""); + self.i += word.len(); + word + } + pub fn peek_line(&self) -> &str { + self.src[self.i..].lines().next().unwrap_or("") + } + pub fn next_line(&mut self) -> &str { + self.end_sections(); + let line = self.src[self.i..].lines().next().unwrap_or(""); + self.i += line.len(); + line + } + + pub fn get_pos(&self) -> SourcePos { + SourcePos(self.i) + } + pub fn set_pos(&mut self, new: SourcePos) { + self.i = new.0 + } + + /// Returns a SectionMarker which, when dropped, indicates the end of this section. + /// Useful for debugging the parser. + pub fn section_begin(&mut self, section: String) -> Arc { + #[cfg(debug_assertions)] + println!("Section begin: {}", §ion); + let arc = Arc::new(section); + self.sections.push(SectionMarker { + section: Arc::clone(&arc), + start: self.get_pos(), + end: None, + }); + arc + } + pub fn sections(&self) -> &Vec { + &self.sections + } +} + +impl Drop for Source { + fn drop(&mut self) { + self.end_sections() + } +} + +/// Returned from Source::begin(), this indicates that parsing of +/// a certain section has not yet finished. +/// Once this is dropped, a section is considered done. +pub struct SectionMarker { + section: Arc, + start: SourcePos, + end: Option, +} +impl SectionMarker { + pub fn section(&self) -> &str { + &self.section + } + pub fn start(&self) -> &SourcePos { + &self.start + } + pub fn end(&self) -> &Option { + &self.end + } + /// If this is the only remaining SectionMarker for this section, + /// this method sets its `end` property. + fn checked_end(&mut self, end: SourcePos) { + if self.end.is_none() { + if Arc::strong_count(&self.section) == 1 { + self.end = Some(end); + #[cfg(debug_assertions)] + println!("Section end : {}", &self.section); + } + } + } +} + +#[derive(Clone, Copy)] +pub struct SourcePos(usize); +impl SourcePos { + fn diff(&self, rhs: &Self) -> usize { + rhs.0 - self.0 + } +} diff --git a/mers_lib/src/parsing/statements.rs b/mers_lib/src/parsing/statements.rs new file mode 100755 index 0000000..e678504 --- /dev/null +++ b/mers_lib/src/parsing/statements.rs @@ -0,0 +1,199 @@ +use std::sync::Arc; + +use super::Source; +use crate::{ + data::{self, Data}, + program::{self, parsed::MersStatement}, +}; + +pub fn parse(src: &mut Source) -> Result>, ()> { + src.section_begin("statement".to_string()); + let mut first = if let Some(s) = parse_no_chain(src)? { + s + } else { + return Ok(None); + }; + src.skip_whitespace(); + match src.peek_word() { + ":=" => { + src.next_word(); + first = Box::new(program::parsed::init_to::InitTo { + target: first, + source: parse(src)?.expect("todo"), + }); + } + "=" => { + src.next_word(); + first = Box::new(program::parsed::assign_to::AssignTo { + target: first, + source: parse(src)?.expect("todo"), + }); + } + "->" => { + src.next_word(); + first = Box::new(program::parsed::function::Function { + arg: first, + run: parse(src)?.expect("err: bad eof, fn needs some statement"), + }); + } + _ => loop { + src.skip_whitespace(); + if let Some('.') = src.peek_char() { + src.next_char(); + let chained = parse_no_chain(src)?.expect("err: EOF instead of chain"); + first = Box::new(program::parsed::chain::Chain { first, chained }); + } else { + break; + } + }, + } + if matches!(src.peek_char(), Some(',' | ';')) { + src.next_char(); + } + Ok(Some(first)) +} +/// Assumes the { has already been parsed +pub fn parse_block(src: &mut Source) -> Result { + Ok(program::parsed::block::Block { + statements: parse_multiple(src, '}')?, + }) +} +pub fn parse_tuple(src: &mut Source) -> Result { + Ok(program::parsed::tuple::Tuple { + elems: parse_multiple(src, ')')?, + }) +} +pub fn parse_multiple(src: &mut Source, end: char) -> Result>, ()> { + src.section_begin("block".to_string()); + let mut statements = vec![]; + loop { + src.skip_whitespace(); + if matches!(src.peek_char(), Some(e) if e == end) { + src.next_char(); + break; + } else if let Some(s) = parse(src)? { + statements.push(s); + } else { + // EOF + break; + } + } + Ok(statements) +} +pub fn parse_no_chain( + src: &mut Source, +) -> Result>, ()> { + src.section_begin("statement no chain".to_string()); + src.skip_whitespace(); + match src.peek_char() { + Some('{') => { + src.next_char(); + return Ok(Some(Box::new(parse_block(src)?))); + } + Some('(') => { + src.next_char(); + return Ok(Some(Box::new(parse_tuple(src)?))); + } + Some('"') => { + src.section_begin("string literal".to_string()); + src.next_char(); + let mut s = String::new(); + loop { + if let Some(ch) = src.next_char() { + if ch == '\\' { + s.push(match src.next_char() { + Some('\\') => '\\', + Some('r') => '\r', + Some('n') => '\n', + Some('t') => '\t', + Some(o) => todo!("err: unknown backslash escape '\\{o}'"), + None => todo!("err: eof in backslash escape"), + }); + } else if ch == '"' { + break; + } else { + s.push(ch); + } + } else { + todo!("err: eof in string") + } + } + return Ok(Some(Box::new(program::parsed::value::Value(Data::new( + crate::data::string::String(s), + ))))); + } + _ => {} + } + Ok(Some(match src.next_word() { + "if" => { + src.section_begin("if".to_string()); + Box::new(program::parsed::r#if::If { + condition: parse(src)?.expect("err: EOF instead of condition"), + on_true: parse(src)?.expect("err: EOF instead of on_true"), + on_false: { + src.skip_whitespace(); + if src.peek_word() == "else" { + src.section_begin("else".to_string()); + src.next_word(); + Some(parse(src)?.expect("err: EOF instead of on_false after else")) + } else { + None + } + }, + }) + } + "loop" => { + src.section_begin("loop".to_string()); + Box::new(program::parsed::r#loop::Loop { + inner: parse(src)?.expect("err: EOF instead of inner statement after loop"), + }) + } + "switch" => { + src.section_begin("loop".to_string()); + todo!() + } + "true" => Box::new(program::parsed::value::Value(Data::new( + crate::data::bool::Bool(true), + ))), + "false" => Box::new(program::parsed::value::Value(Data::new( + crate::data::bool::Bool(false), + ))), + "" => return Ok(None), + o => { + let o = o.to_string(); + src.section_begin("literals, variables, and other non-keyword things".to_string()); + if let Ok(n) = o.parse() { + if src.peek_char() == Some('.') { + let here = src.get_pos(); + src.next_char(); + if let Ok(num) = format!("{o}.{}", src.next_word()).parse() { + Box::new(program::parsed::value::Value(Data::new( + crate::data::float::Float(num), + ))) + } else { + src.set_pos(here); + Box::new(program::parsed::value::Value(Data::new( + crate::data::int::Int(n), + ))) + } + } else { + Box::new(program::parsed::value::Value(Data::new( + crate::data::int::Int(n), + ))) + } + } else { + if let Some('&') = o.chars().next() { + Box::new(program::parsed::variable::Variable { + is_ref: true, + var: o[1..].to_string(), + }) + } else { + Box::new(program::parsed::variable::Variable { + is_ref: false, + var: o.to_string(), + }) + } + } + } + })) +} diff --git a/mers_lib/src/parsing/types.rs b/mers_lib/src/parsing/types.rs new file mode 100755 index 0000000..f548d02 --- /dev/null +++ b/mers_lib/src/parsing/types.rs @@ -0,0 +1,51 @@ +use super::Source; + +/// multiple types are represented as a `Vec`. +pub enum ParsedType { + Tuple(Vec>), + Type(String), +} + +fn parse_single_type(src: &mut Source) -> Result { + src.section_begin("parse single type".to_string()); + src.skip_whitespace(); + Ok(match src.peek_char() { + // Tuple + Some('(') => { + src.next_char(); + src.section_begin("parse tuple's inner types".to_string()); + let mut inner = vec![]; + loop { + match src.peek_char() { + Some(')') => { + src.next_char(); + break; + } + Some(',') => { + src.next_char(); + } + _ => todo!("err: bad char in tuple inner type"), + } + inner.push(parse_type(src)?); + } + ParsedType::Tuple(inner) + } + Some(_) => ParsedType::Type(src.next_word().to_lowercase()), + None => todo!(), + }) +} + +fn parse_type(src: &mut Source) -> Result, ()> { + src.section_begin("parse single type".to_string()); + let mut types = vec![]; + loop { + types.push(parse_single_type(src)?); + src.skip_whitespace(); + if let Some('/') = src.peek_char() { + continue; + } else { + break; + } + } + Ok(types) +} diff --git a/mers_lib/src/program/configs/mod.rs b/mers_lib/src/program/configs/mod.rs new file mode 100755 index 0000000..5f1a7ff --- /dev/null +++ b/mers_lib/src/program/configs/mod.rs @@ -0,0 +1,198 @@ +use std::sync::Arc; + +use crate::{ + data::{self, Data, Type}, + info::Local, + program, +}; + +mod with_command_running; +mod with_iters; +mod with_list; + +/// Usage: create an empty Config using Config::new(), use the methods to customize it, then get the Infos using Config::infos() +/// bundle_* for bundles (combines multiple groups or even bundles) +/// with_* for usage-oriented groups +/// add_* to add custom things +/// +/// For doc-comments: +/// Description +/// `bundle_std()` +/// `type` - description +/// `var: type` - description +pub struct Config { + globals: usize, + info_parsed: super::parsed::Info, + info_run: super::run::Info, +} + +impl Config { + pub fn new() -> Self { + Self { + globals: 0, + info_parsed: Default::default(), + info_run: Default::default(), + } + } + + /// standard utilitis used in many programs + /// `bundle_base()` + /// `with_list()` + /// `with_command_running()` + pub fn bundle_std(self) -> Self { + self.with_command_running().with_list().bundle_base() + } + /// base utilities used in most programs + /// `with_prints()` + /// `with_math()` + /// `with_get()` + /// `with_iters()` + pub fn bundle_base(self) -> Self { + self.with_iters().with_get().with_math().with_prints() + } + + /// `println: fn` prints to stdout and adds a newline to the end + /// `print: fn` prints to stdout + /// `eprintln: fn` prints to stderr and adds a newline to the end + /// `eprint: fn` prints to stderr + /// `debug: fn` debug-prints any value + pub fn with_prints(self) -> Self { + self.add_var( + "debug".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + eprintln!("{:#?}", a.get()); + Data::empty_tuple() + }), + }), + ) + .add_var( + "eprint".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + eprint!("{}", a.get()); + Data::empty_tuple() + }), + }), + ) + .add_var( + "eprintln".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + eprintln!("{}", a.get()); + Data::empty_tuple() + }), + }), + ) + .add_var( + "print".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + print!("{}", a.get()); + Data::empty_tuple() + }), + }), + ) + .add_var( + "println".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + println!("{}", a.get()); + Data::empty_tuple() + }), + }), + ) + } + /// `sum: fn` returns the sum of all the numbers in the tuple + pub fn with_math(self) -> Self { + self.add_var( + "sum".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(tuple) = a.get().as_any().downcast_ref::() { + let mut sumi = 0; + let mut sumf = 0.0; + let mut usef = false; + for val in &tuple.0 { + if let Some(i) = val.get().as_any().downcast_ref::() { + sumi += i.0; + } else if let Some(i) = + val.get().as_any().downcast_ref::() + { + sumf += i.0; + usef = true; + } + } + if usef { + Data::new(data::float::Float(sumi as f64 + sumf)) + } else { + Data::new(data::int::Int(sumi)) + } + } else { + unreachable!("sum called on non-tuple") + } + }), + }), + ) + } + /// `get: fn` is used to retrieve elements from collections + pub fn with_get(self) -> Self { + self.add_var( + "get".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(tuple) = a.get().as_any().downcast_ref::() { + if let (Some(v), Some(i)) = (tuple.get(0), tuple.get(1)) { + if let Some(i) = i.get().as_any().downcast_ref::() { + if let Ok(i) = i.0.try_into() { + if let Some(v) = v.get().get(i) { + Data::one_tuple(v) + } else { + Data::empty_tuple() + } + } else { + Data::empty_tuple() + } + } else { + unreachable!("get called with non-int index") + } + } else { + unreachable!("get called on tuple with len < 2") + } + } else { + unreachable!("get called on non-tuple, arg must be (_, index)") + } + }), + }), + ) + } + + pub fn add_var(mut self, name: String, val: Data) -> Self { + self.info_parsed.scopes[0].init_var(name, (0, self.globals)); + self.info_run.scopes[0].init_var(self.globals, val); + self.globals += 1; + self + } + pub fn add_type(mut self, name: String, t: Type) -> Self { + // TODO! needed for type syntax in the parser, everything else probably(?) works already + self + } + + pub fn infos(self) -> (super::parsed::Info, super::run::Info) { + (self.info_parsed, self.info_run) + } +} diff --git a/mers_lib/src/program/configs/with_command_running.rs b/mers_lib/src/program/configs/with_command_running.rs new file mode 100755 index 0000000..91c5ebd --- /dev/null +++ b/mers_lib/src/program/configs/with_command_running.rs @@ -0,0 +1,104 @@ +use std::{fmt::Display, process::Command, sync::Arc}; + +use crate::{ + data::{self, Data, MersData, MersType}, + program, +}; + +use super::Config; + +impl Config { + /// adds utilities to run commands installed on the system and get their output. + /// `run_command: fn` runs a command with arguments. + /// Args: (cmd, args) where cmd is a string and args is an Iterable over strings + /// `RunCommandError` holds the error if the command can't be executed + pub fn with_command_running(self) -> Self { + self.add_var( + "run_command".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(cmd) = a.get().as_any().downcast_ref::() { + if let (Some(cmd), Some(args)) = (cmd.get(0), cmd.get(1)) { + if let (Some(cmd), Some(args)) = ( + cmd.get().as_any().downcast_ref::(), + args.get().iterable(), + ) { + match Command::new(&cmd.0) + .args(args.map(|v| v.get().to_string())) + .output() + { + Ok(output) => { + let status = if let Some(code) = output.status.code() { + Data::new(data::int::Int(code as _)) + } else { + Data::empty_tuple() + }; + let stdout = + String::from_utf8_lossy(&output.stdout).into_owned(); + let stderr = + String::from_utf8_lossy(&output.stderr).into_owned(); + Data::new(data::tuple::Tuple(vec![ + status, + Data::new(data::string::String(stdout)), + Data::new(data::string::String(stderr)), + ])) + } + Err(e) => Data::new(RunCommandError(e.to_string())), + } + } else { + unreachable!("run_command called with arguments other than (String, ).") + } + } else { + unreachable!("run_command called with too few arguments") + } + } else { + unreachable!("run_command called with non-tuple argument") + } + }), + }), + ) + } +} + +#[derive(Clone, Debug)] +pub struct RunCommandError(String); +#[derive(Debug)] +pub struct RunCommandErrorT; +impl MersData for RunCommandError { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} +impl MersType for RunCommandErrorT { + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other.as_any().downcast_ref::().is_some() + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} +impl Display for RunCommandError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "RunCommandError: {}", self.0) + } +} diff --git a/mers_lib/src/program/configs/with_iters.rs b/mers_lib/src/program/configs/with_iters.rs new file mode 100755 index 0000000..f04daa4 --- /dev/null +++ b/mers_lib/src/program/configs/with_iters.rs @@ -0,0 +1,175 @@ +use std::{fmt::Display, sync::Arc}; + +use crate::{ + data::{self, Data, MersData}, + program, +}; + +use super::Config; + +impl Config { + /// Adds functions to deal with iterables + /// `iter: fn` executes a function once for each element of the iterable + pub fn with_iters(self) -> Self { + self.add_var( + "iter".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(tuple) = a.get().as_any().downcast_ref::() { + if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { + if let (Some(iter), Some(f)) = ( + v.get().iterable(), + f.get().as_any().downcast_ref::(), + ) { + for v in iter { + f.run(v); + } + Data::empty_tuple() + } else { + unreachable!( + "iter called on tuple not containing iterable and function" + ) + } + } else { + unreachable!("iter called on tuple with len < 2") + } + } else { + unreachable!("iter called on non-tuple") + } + }), + }), + ) + .add_var( + "map".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(tuple) = a.get().as_any().downcast_ref::() { + if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { + if let Some(f) = + f.get().as_any().downcast_ref::() + { + Data::new(Iter(Iters::Map(Clone::clone(f)), v.clone())) + } else { + unreachable!("iter called on tuple not containing function") + } + } else { + unreachable!("iter called on tuple with len < 2") + } + } else { + unreachable!("iter called on non-tuple") + } + }), + }), + ) + .add_var( + "filter".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(tuple) = a.get().as_any().downcast_ref::() { + if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { + if let Some(f) = + f.get().as_any().downcast_ref::() + { + Data::new(Iter(Iters::Filter(Clone::clone(f)), v.clone())) + } else { + unreachable!("iter called on tuple not containing function") + } + } else { + unreachable!("iter called on tuple with len < 2") + } + } else { + unreachable!("iter called on non-tuple") + } + }), + }), + ) + .add_var( + "filter_map".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(tuple) = a.get().as_any().downcast_ref::() { + if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { + if let Some(f) = + f.get().as_any().downcast_ref::() + { + Data::new(Iter(Iters::FilterMap(Clone::clone(f)), v.clone())) + } else { + unreachable!("iter called on tuple not containing function") + } + } else { + unreachable!("iter called on tuple with len < 2") + } + } else { + unreachable!("iter called on non-tuple") + } + }), + }), + ) + } +} + +#[derive(Clone, Debug)] +pub enum Iters { + Map(data::function::Function), + Filter(data::function::Function), + FilterMap(data::function::Function), +} +#[derive(Clone, Debug)] +pub struct Iter(Iters, Data); +#[derive(Clone, Debug)] +pub struct IterT(Iters); +impl MersData for Iter { + fn iterable(&self) -> Option>> { + Some(match &self.0 { + Iters::Map(f) => { + let f = Clone::clone(f); + Box::new(self.1.get().iterable()?.map(move |v| f.run(v))) + } + Iters::Filter(f) => { + let f = Clone::clone(f); + Box::new(self.1.get().iterable()?.filter(move |v| { + f.run(v.clone()) + .get() + .as_any() + .downcast_ref::() + .is_some_and(|b| b.0) + })) + } + Iters::FilterMap(f) => { + let f = Clone::clone(f); + Box::new( + self.1 + .get() + .iterable()? + .filter_map(move |v| f.run(v).get().matches()), + ) + } + _ => todo!(), + }) + } + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} +impl Display for Iter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "") + } +} diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs new file mode 100755 index 0000000..1c8c954 --- /dev/null +++ b/mers_lib/src/program/configs/with_list.rs @@ -0,0 +1,90 @@ +use std::{fmt::Display, sync::Arc}; + +use crate::{ + data::{self, Data, MersData, MersType, Type}, + program, +}; + +use super::Config; + +impl Config { + /// Adds a simple list type + /// `List` can store a variable number of items + /// `as_list: fn` turns a tuple into a list + pub fn with_list(self) -> Self { + // TODO: Type with generics + self.add_type("List".to_string(), Type::new(ListT(Type::empty_tuple()))) + .add_var( + "as_list".to_string(), + Data::new(data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_a| todo!()), + run: Arc::new(|a, _i| { + if let Some(i) = a.get().iterable() { + Data::new(List(i.collect())) + } else { + unreachable!("as_list called on non-iterable") + } + }), + }), + ) + } +} + +#[derive(Clone, Debug)] +pub struct List(Vec); +#[derive(Debug)] +pub struct ListT(Type); +impl MersData for List { + fn iterable(&self) -> Option>> { + Some(Box::new(self.0.clone().into_iter())) + } + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} +impl MersType for ListT { + fn iterable(&self) -> Option { + Some(self.0.clone()) + } + fn is_same_type_as(&self, other: &dyn MersType) -> bool { + other + .as_any() + .downcast_ref::() + .is_some_and(|v| self.0.is_same_type_as(&v.0)) + } + fn is_included_in_single(&self, target: &dyn MersType) -> bool { + self.is_same_type_as(target) + } + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} +impl Display for List { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[")?; + for (i, c) in self.0.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{}", c.get())?; + } + write!(f, "]")?; + Ok(()) + } +} diff --git a/mers_lib/src/program/mod.rs b/mers_lib/src/program/mod.rs new file mode 100755 index 0000000..63801d1 --- /dev/null +++ b/mers_lib/src/program/mod.rs @@ -0,0 +1,3 @@ +pub mod configs; +pub mod parsed; +pub mod run; diff --git a/mers_lib/src/program/parsed/assign_to.rs b/mers_lib/src/program/parsed/assign_to.rs new file mode 100755 index 0000000..17d27d7 --- /dev/null +++ b/mers_lib/src/program/parsed/assign_to.rs @@ -0,0 +1,25 @@ +use crate::{info::Local, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct AssignTo { + pub target: Box, + pub source: Box, +} + +impl MersStatement for AssignTo { + fn has_scope(&self) -> bool { + false + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + mut comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::assign_to::AssignTo { + target: self.target.compile(info, comp)?, + source: self.source.compile(info, comp)?, + })) + } +} diff --git a/mers_lib/src/program/parsed/block.rs b/mers_lib/src/program/parsed/block.rs new file mode 100755 index 0000000..c7407e3 --- /dev/null +++ b/mers_lib/src/program/parsed/block.rs @@ -0,0 +1,26 @@ +use crate::{info, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Block { + pub statements: Vec>, +} +impl MersStatement for Block { + fn has_scope(&self) -> bool { + true + } + fn compile_custom( + &self, + info: &mut info::Info, + comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::block::Block { + statements: self + .statements + .iter() + .map(|v| v.compile(info, comp)) + .collect::, _>>()?, + })) + } +} diff --git a/mers_lib/src/program/parsed/chain.rs b/mers_lib/src/program/parsed/chain.rs new file mode 100755 index 0000000..4236866 --- /dev/null +++ b/mers_lib/src/program/parsed/chain.rs @@ -0,0 +1,24 @@ +use crate::{info, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Chain { + pub first: Box, + pub chained: Box, +} +impl MersStatement for Chain { + fn has_scope(&self) -> bool { + false + } + fn compile_custom( + &self, + info: &mut info::Info, + comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::chain::Chain { + first: self.first.compile(info, comp)?, + chained: self.chained.compile(info, comp)?, + })) + } +} diff --git a/mers_lib/src/program/parsed/function.rs b/mers_lib/src/program/parsed/function.rs new file mode 100755 index 0000000..4cb60bf --- /dev/null +++ b/mers_lib/src/program/parsed/function.rs @@ -0,0 +1,42 @@ +use std::sync::Arc; + +use crate::{ + data::{self, Data}, + info::Local, + program, +}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Function { + pub arg: Box, + pub run: Box, +} + +impl MersStatement for Function { + fn has_scope(&self) -> bool { + // TODO: what??? + false + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + mut comp: CompInfo, + ) -> Result, String> { + comp.is_init = true; + let arg = self.arg.compile(info, comp)?; + comp.is_init = false; + let run = self.run.compile(info, comp)?; + Ok(Box::new(program::run::function::Function { + func_no_info: data::function::Function { + info: program::run::Info::neverused(), + out: Arc::new(|_i| todo!()), + run: Arc::new(move |i, info| { + data::defs::assign(i, &arg.run(info)); + run.run(info) + }), + }, + })) + } +} diff --git a/mers_lib/src/program/parsed/if.rs b/mers_lib/src/program/parsed/if.rs new file mode 100755 index 0000000..958368f --- /dev/null +++ b/mers_lib/src/program/parsed/if.rs @@ -0,0 +1,31 @@ +use crate::program; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct If { + pub condition: Box, + pub on_true: Box, + pub on_false: Option>, +} + +impl MersStatement for If { + fn has_scope(&self) -> bool { + true + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::r#if::If { + condition: self.condition.compile(info, comp)?, + on_true: self.condition.compile(info, comp)?, + on_false: if let Some(v) = &self.on_false { + Some(v.compile(info, comp)?) + } else { + None + }, + })) + } +} diff --git a/mers_lib/src/program/parsed/init_to.rs b/mers_lib/src/program/parsed/init_to.rs new file mode 100755 index 0000000..71519a1 --- /dev/null +++ b/mers_lib/src/program/parsed/init_to.rs @@ -0,0 +1,29 @@ +use crate::{info::Local, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct InitTo { + pub target: Box, + pub source: Box, +} + +impl MersStatement for InitTo { + fn has_scope(&self) -> bool { + false + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + mut comp: CompInfo, + ) -> Result, String> { + comp.is_init = true; + let target = self.target.compile(info, comp)?; + comp.is_init = false; + let source = self.source.compile(info, comp)?; + Ok(Box::new(program::run::assign_to::AssignTo { + target, + source, + })) + } +} diff --git a/mers_lib/src/program/parsed/loop.rs b/mers_lib/src/program/parsed/loop.rs new file mode 100755 index 0000000..e8b42db --- /dev/null +++ b/mers_lib/src/program/parsed/loop.rs @@ -0,0 +1,23 @@ +use crate::program; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Loop { + pub inner: Box, +} + +impl MersStatement for Loop { + fn has_scope(&self) -> bool { + true + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::r#loop::Loop { + inner: self.inner.compile(info, comp)?, + })) + } +} diff --git a/mers_lib/src/program/parsed/mod.rs b/mers_lib/src/program/parsed/mod.rs new file mode 100755 index 0000000..fe9ded7 --- /dev/null +++ b/mers_lib/src/program/parsed/mod.rs @@ -0,0 +1,68 @@ +use std::{collections::HashMap, fmt::Debug}; + +use crate::info; + +pub mod assign_to; +pub mod block; +pub mod chain; +pub mod function; +pub mod r#if; +pub mod init_to; +pub mod r#loop; +pub mod switch; +pub mod tuple; +pub mod value; +pub mod variable; + +pub trait MersStatement: Debug { + fn has_scope(&self) -> bool; + fn compile_custom( + &self, + info: &mut Info, + comp: CompInfo, + ) -> Result, String>; + fn compile( + &self, + info: &mut Info, + comp: CompInfo, + ) -> Result, String> { + if self.has_scope() { + info.create_scope(); + } + let o = self.compile_custom(info, comp); + if self.has_scope() { + info.end_scope(); + } + o + } +} + +#[derive(Clone, Copy)] +pub struct CompInfo { + is_init: bool, +} +impl Default for CompInfo { + fn default() -> Self { + Self { is_init: false } + } +} + +pub type Info = info::Info; + +#[derive(Default, Clone, Debug)] +pub struct Local { + vars: HashMap, +} +impl info::Local for Local { + type VariableIdentifier = String; + type VariableData = (usize, usize); + fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) { + self.vars.insert(id, value); + } + fn get_var(&self, id: &Self::VariableIdentifier) -> Option<&Self::VariableData> { + self.vars.get(id) + } + fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> { + self.vars.get_mut(id) + } +} diff --git a/mers_lib/src/program/parsed/switch.rs b/mers_lib/src/program/parsed/switch.rs new file mode 100755 index 0000000..c654260 --- /dev/null +++ b/mers_lib/src/program/parsed/switch.rs @@ -0,0 +1,27 @@ +use crate::data::Type; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Switch { + source: Box, + arms: Vec, +} + +#[derive(Debug)] +pub struct SwitchArm { + requires_type: Type, +} + +impl MersStatement for Switch { + fn has_scope(&self) -> bool { + true + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + comp: CompInfo, + ) -> Result, String> { + todo!() + } +} diff --git a/mers_lib/src/program/parsed/tuple.rs b/mers_lib/src/program/parsed/tuple.rs new file mode 100755 index 0000000..29b35c6 --- /dev/null +++ b/mers_lib/src/program/parsed/tuple.rs @@ -0,0 +1,26 @@ +use crate::{info, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Tuple { + pub elems: Vec>, +} +impl MersStatement for Tuple { + fn has_scope(&self) -> bool { + false + } + fn compile_custom( + &self, + info: &mut info::Info, + comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::tuple::Tuple { + elems: self + .elems + .iter() + .map(|v| v.compile(info, comp)) + .collect::, _>>()?, + })) + } +} diff --git a/mers_lib/src/program/parsed/value.rs b/mers_lib/src/program/parsed/value.rs new file mode 100755 index 0000000..80f5cf8 --- /dev/null +++ b/mers_lib/src/program/parsed/value.rs @@ -0,0 +1,21 @@ +use crate::{data::Data, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Value(pub Data); + +impl MersStatement for Value { + fn has_scope(&self) -> bool { + false + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + comp: CompInfo, + ) -> Result, String> { + Ok(Box::new(program::run::value::Value { + val: self.0.clone(), + })) + } +} diff --git a/mers_lib/src/program/parsed/variable.rs b/mers_lib/src/program/parsed/variable.rs new file mode 100755 index 0000000..9fd8cc1 --- /dev/null +++ b/mers_lib/src/program/parsed/variable.rs @@ -0,0 +1,38 @@ +use crate::{info::Local, program}; + +use super::{CompInfo, MersStatement}; + +#[derive(Debug)] +pub struct Variable { + pub is_ref: bool, + pub var: String, +} + +impl MersStatement for Variable { + fn has_scope(&self) -> bool { + false + } + fn compile_custom( + &self, + info: &mut crate::info::Info, + comp: CompInfo, + ) -> Result, String> { + if comp.is_init { + info.init_var( + self.var.clone(), + ( + info.scopes.len() - 1, + info.scopes.last().unwrap().vars.len(), + ), + ) + } + Ok(Box::new(program::run::variable::Variable { + is_ref: comp.is_init || self.is_ref, + var: if let Some(v) = info.get_var(&self.var) { + *v + } else { + return Err(format!("No variable named '{}' found!", self.var)); + }, + })) + } +} diff --git a/mers_lib/src/program/run/assign_to.rs b/mers_lib/src/program/run/assign_to.rs new file mode 100755 index 0000000..4d8c1a4 --- /dev/null +++ b/mers_lib/src/program/run/assign_to.rs @@ -0,0 +1,21 @@ +use crate::data; + +use super::MersStatement; + +#[derive(Debug)] +pub struct AssignTo { + pub target: Box, + pub source: Box, +} + +impl MersStatement for AssignTo { + fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + let source = self.source.run(info); + let target = self.target.run(info); + data::defs::assign(source, &target); + target + } + fn has_scope(&self) -> bool { + false + } +} diff --git a/mers_lib/src/program/run/block.rs b/mers_lib/src/program/run/block.rs new file mode 100755 index 0000000..6b5181b --- /dev/null +++ b/mers_lib/src/program/run/block.rs @@ -0,0 +1,20 @@ +use std::sync::Arc; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Block { + pub statements: Vec>, +} +impl MersStatement for Block { + fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + self.statements + .iter() + .map(|s| s.run(info)) + .last() + .unwrap_or_else(|| crate::data::Data::new(crate::data::tuple::Tuple(vec![]))) + } + fn has_scope(&self) -> bool { + true + } +} diff --git a/mers_lib/src/program/run/chain.rs b/mers_lib/src/program/run/chain.rs new file mode 100755 index 0000000..cf42d76 --- /dev/null +++ b/mers_lib/src/program/run/chain.rs @@ -0,0 +1,26 @@ +use std::{any::Any, sync::Arc}; + +use crate::data::{function::Function, Data}; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Chain { + pub first: Box, + pub chained: Box, +} +impl MersStatement for Chain { + fn run_custom(&self, info: &mut super::Info) -> Data { + let f = self.first.run(info); + let c = self.chained.run(info); + let c = c.get(); + if let Some(func) = c.as_any().downcast_ref::() { + func.run(f) + } else { + todo!("err: not a function"); + } + } + fn has_scope(&self) -> bool { + false + } +} diff --git a/mers_lib/src/program/run/function.rs b/mers_lib/src/program/run/function.rs new file mode 100755 index 0000000..51b5974 --- /dev/null +++ b/mers_lib/src/program/run/function.rs @@ -0,0 +1,17 @@ +use crate::data::{self, Data, MersData}; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Function { + pub func_no_info: data::function::Function, +} + +impl MersStatement for Function { + fn has_scope(&self) -> bool { + false + } + fn run_custom(&self, info: &mut super::Info) -> Data { + Data::new(self.func_no_info.with_info(info.clone())) + } +} diff --git a/mers_lib/src/program/run/if.rs b/mers_lib/src/program/run/if.rs new file mode 100755 index 0000000..2e54544 --- /dev/null +++ b/mers_lib/src/program/run/if.rs @@ -0,0 +1,18 @@ +use super::MersStatement; + +#[derive(Debug)] +pub struct If { + pub condition: Box, + pub on_true: Box, + pub on_false: Option>, +} + +impl MersStatement for If { + fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + self.condition.run(info); + todo!("what now?") + } + fn has_scope(&self) -> bool { + true + } +} diff --git a/mers_lib/src/program/run/loop.rs b/mers_lib/src/program/run/loop.rs new file mode 100755 index 0000000..9286d43 --- /dev/null +++ b/mers_lib/src/program/run/loop.rs @@ -0,0 +1,21 @@ +use crate::data::MersData; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Loop { + pub inner: Box, +} + +impl MersStatement for Loop { + fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + loop { + if let Some(break_val) = self.inner.run(info).get().matches() { + break break_val; + } + } + } + fn has_scope(&self) -> bool { + true + } +} diff --git a/mers_lib/src/program/run/mod.rs b/mers_lib/src/program/run/mod.rs new file mode 100755 index 0000000..52cc226 --- /dev/null +++ b/mers_lib/src/program/run/mod.rs @@ -0,0 +1,63 @@ +use std::sync::Arc; + +use crate::{ + data::{self, Data, Type}, + info, +}; + +pub mod assign_to; +pub mod block; +pub mod chain; +pub mod function; +pub mod r#if; +pub mod r#loop; +pub mod switch; +pub mod tuple; +pub mod value; +pub mod variable; + +pub trait MersStatement: std::fmt::Debug { + fn run_custom(&self, info: &mut Info) -> Data; + /// if true, local variables etc. will be contained inside their own scope. + fn has_scope(&self) -> bool; + // fn outputs(&self) -> Type; + fn run(&self, info: &mut Info) -> Data { + if self.has_scope() { + info.create_scope(); + } + let o = self.run_custom(info); + if self.has_scope() { + info.end_scope(); + } + o + } +} + +pub type Info = info::Info; + +#[derive(Default, Clone, Debug)] +pub struct Local { + vars: Vec, +} +impl info::Local for Local { + type VariableIdentifier = usize; + type VariableData = Data; + fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) { + while self.vars.len() <= id { + self.vars.push(Data::new(data::bool::Bool(false))); + } + self.vars[id] = value; + } + fn get_var(&self, id: &Self::VariableIdentifier) -> Option<&Self::VariableData> { + match self.vars.get(*id) { + Some(v) => Some(v), + None => None, + } + } + fn get_var_mut(&mut self, id: &Self::VariableIdentifier) -> Option<&mut Self::VariableData> { + match self.vars.get_mut(*id) { + Some(v) => Some(v), + None => None, + } + } +} diff --git a/mers_lib/src/program/run/switch.rs b/mers_lib/src/program/run/switch.rs new file mode 100755 index 0000000..4ffc43b --- /dev/null +++ b/mers_lib/src/program/run/switch.rs @@ -0,0 +1,23 @@ +use crate::data::Type; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Switch { + source: Box, + arms: Vec, +} + +#[derive(Debug)] +pub struct SwitchArm { + requires_type: Type, +} + +impl MersStatement for Switch { + fn has_scope(&self) -> bool { + true + } + fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + todo!("switch") + } +} diff --git a/mers_lib/src/program/run/tuple.rs b/mers_lib/src/program/run/tuple.rs new file mode 100755 index 0000000..d4d6eb1 --- /dev/null +++ b/mers_lib/src/program/run/tuple.rs @@ -0,0 +1,18 @@ +use crate::data::{self, Data}; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Tuple { + pub elems: Vec>, +} +impl MersStatement for Tuple { + fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + Data::new(data::tuple::Tuple( + self.elems.iter().map(|s| s.run(info)).collect(), + )) + } + fn has_scope(&self) -> bool { + false + } +} diff --git a/mers_lib/src/program/run/value.rs b/mers_lib/src/program/run/value.rs new file mode 100755 index 0000000..2724c81 --- /dev/null +++ b/mers_lib/src/program/run/value.rs @@ -0,0 +1,17 @@ +use crate::data::{Data, MersData}; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Value { + pub val: Data, +} + +impl MersStatement for Value { + fn has_scope(&self) -> bool { + false + } + fn run_custom(&self, info: &mut super::Info) -> Data { + self.val.clone() + } +} diff --git a/mers_lib/src/program/run/variable.rs b/mers_lib/src/program/run/variable.rs new file mode 100755 index 0000000..14dc9e9 --- /dev/null +++ b/mers_lib/src/program/run/variable.rs @@ -0,0 +1,30 @@ +use crate::data::{self, Data}; + +use super::MersStatement; + +#[derive(Debug)] +pub struct Variable { + pub is_ref: bool, + pub var: (usize, usize), +} + +impl MersStatement for Variable { + fn has_scope(&self) -> bool { + false + } + fn run_custom(&self, info: &mut super::Info) -> Data { + while info.scopes[self.var.0].vars.len() <= self.var.1 { + info.scopes[self.var.0] + .vars + .push(Data::new(data::bool::Bool(false))); + } + if self.is_ref { + Data::new(data::reference::Reference( + info.scopes[self.var.0].vars[self.var.1].clone(), + )) + } else { + // Full-Clones! + Data::new_boxed(info.scopes[self.var.0].vars[self.var.1].get().clone()) + } + } +} diff --git a/mers_old/Cargo.toml b/mers_old/Cargo.toml new file mode 100755 index 0000000..94b6469 --- /dev/null +++ b/mers_old/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "mers" +version = "0.2.3" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "mers_libs" +path = "src/lib.rs" + +[dependencies] +edit = "0.1.4" +notify = "5.1.0" +regex = "1.7.2" +static_assertions = "1.1.0" +nu-plugin = { version = "0.79.0", optional = true } +nu-protocol = { version = "0.79.0", features = ["plugin"], optional = true } +colorize = "0.1.0" + +[features] +# default = ["nushell_plugin"] +nushell_plugin = ["dep:nu-plugin", "dep:nu-protocol"] + +[profile.nushellplugin] +inherits = "release" diff --git a/mers/src/inlib/mod.rs b/mers_old/src/inlib/mod.rs similarity index 100% rename from mers/src/inlib/mod.rs rename to mers_old/src/inlib/mod.rs diff --git a/mers/src/interactive_mode.rs b/mers_old/src/interactive_mode.rs similarity index 100% rename from mers/src/interactive_mode.rs rename to mers_old/src/interactive_mode.rs diff --git a/mers/src/lang/builtins.rs b/mers_old/src/lang/builtins.rs similarity index 99% rename from mers/src/lang/builtins.rs rename to mers_old/src/lang/builtins.rs index fba5ba5..0931379 100755 --- a/mers/src/lang/builtins.rs +++ b/mers_old/src/lang/builtins.rs @@ -1463,12 +1463,12 @@ impl BuiltinFunction { } }), Self::Insert => args[0].run(info).operate_on_data_mut(|v| { - args[1].run(info).operate_on_data_immut(|i| { + args[2].run(info).operate_on_data_immut(|i| { // TODO: find out why the fuck this helps if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (v, i) { v.operate_on_data_mut(|v| { if let VDataEnum::List(_, v) = v { - v.insert(*i as _, args[2].run(info)); + v.insert(*i as _, args[1].run(info)); } }); VDataEnum::Tuple(vec![]).to() diff --git a/mers/src/lang/code_macro.rs b/mers_old/src/lang/code_macro.rs similarity index 100% rename from mers/src/lang/code_macro.rs rename to mers_old/src/lang/code_macro.rs diff --git a/mers/src/lang/code_parsed.rs b/mers_old/src/lang/code_parsed.rs similarity index 100% rename from mers/src/lang/code_parsed.rs rename to mers_old/src/lang/code_parsed.rs diff --git a/mers/src/lang/code_runnable.rs b/mers_old/src/lang/code_runnable.rs similarity index 100% rename from mers/src/lang/code_runnable.rs rename to mers_old/src/lang/code_runnable.rs diff --git a/mers/src/lang/fmtgs.rs b/mers_old/src/lang/fmtgs.rs similarity index 100% rename from mers/src/lang/fmtgs.rs rename to mers_old/src/lang/fmtgs.rs diff --git a/mers/src/lang/global_info.rs b/mers_old/src/lang/global_info.rs similarity index 100% rename from mers/src/lang/global_info.rs rename to mers_old/src/lang/global_info.rs diff --git a/mers/src/lang/mod.rs b/mers_old/src/lang/mod.rs similarity index 100% rename from mers/src/lang/mod.rs rename to mers_old/src/lang/mod.rs diff --git a/mers/src/lang/to_runnable.rs b/mers_old/src/lang/to_runnable.rs similarity index 100% rename from mers/src/lang/to_runnable.rs rename to mers_old/src/lang/to_runnable.rs diff --git a/mers/src/lang/val_data.rs b/mers_old/src/lang/val_data.rs similarity index 100% rename from mers/src/lang/val_data.rs rename to mers_old/src/lang/val_data.rs diff --git a/mers/src/lang/val_type.rs b/mers_old/src/lang/val_type.rs similarity index 100% rename from mers/src/lang/val_type.rs rename to mers_old/src/lang/val_type.rs diff --git a/mers/src/lib.rs b/mers_old/src/lib.rs similarity index 100% rename from mers/src/lib.rs rename to mers_old/src/lib.rs diff --git a/mers/src/libs/comms.rs b/mers_old/src/libs/comms.rs similarity index 100% rename from mers/src/libs/comms.rs rename to mers_old/src/libs/comms.rs diff --git a/mers/src/libs/mod.rs b/mers_old/src/libs/mod.rs similarity index 100% rename from mers/src/libs/mod.rs rename to mers_old/src/libs/mod.rs diff --git a/mers_old/src/main.rs b/mers_old/src/main.rs new file mode 100755 index 0000000..a50a190 --- /dev/null +++ b/mers_old/src/main.rs @@ -0,0 +1,245 @@ +use lang::global_info::ColorFormatMode; +use lang::global_info::GlobalScriptInfo; +use lang::global_info::LogKind; +use lang::val_data::VDataEnum; +use lang::val_type::VSingleType; + +use crate::lang::fmtgs::FormatGs; + +mod interactive_mode; +mod lang; +mod libs; +#[cfg(feature = "nushell_plugin")] +mod nushell_plugin; +mod parsing; +mod pathutil; +mod tutor; + +fn main() { + #[cfg(not(feature = "nushell_plugin"))] + normal_main(); + #[cfg(feature = "nushell_plugin")] + nushell_plugin::main(); +} + +fn normal_main() { + let args: Vec<_> = std::env::args().skip(1).collect(); + let mut info = GlobalScriptInfo::default(); + let mut run = true; + let mut args_to_skip = 2; + let mut file = match args.len() { + 0 => { + println!("no arguments, use -h for help"); + std::process::exit(100); + } + _ => { + if args[0].trim_start().starts_with("-") { + let mut execute = false; + let mut print_version = false; + let mut verbose = false; + let mut verbose_args = String::new(); + let mut interactive = 0; + let mut interactive_use_new_terminal = false; + let mut teachme = false; + let mut prev_char = None; + let mut advanced = false; + for ch in args[0][1..].chars() { + if !advanced { + if ch == '+' { + advanced = true; + continue; + } + match ch { + 'h' => { + eprintln!("~~~~ mers help ~~~~"); + eprintln!(); + eprintln!(" ~~ cli ~~"); + eprintln!("Mers has the following cli options:"); + eprintln!("-h shows this Help message"); + eprintln!("-e - mers will treat the run argument as code to be Executed rather than a file path"); + eprintln!(" mers -e 'println(\"Hello, World!\")'"); + eprintln!( + "-c - mers will Check the code for errors, but won't run it" + ); + eprintln!("-f - mers will Format the code and print it. useful if you suspect the parser might be misinterpreting your code"); + eprintln!( + "+c - use Colors in the output to better visualize things" + ); + eprintln!("+C - don't use colors (opposite of +c, redundant since this is the default)"); + eprintln!("-v - mers will be more Verbose"); + eprintln!("+???+ - customize what mers is verbose about and how - bad syntax, barely useful, don't use it until it gets improved (TODO!)"); + eprintln!("-i - launches an Interactive session to play around with (opens your editor and runs code on each file save)"); + eprintln!("+t - spawns a new terminal for the editor (if you use a terminal editors, add +t)"); + eprintln!(" mers -i+t"); + eprintln!("-t - launches the Tutor, which will attempt to Teach you the basics of the language"); + eprintln!(); + eprintln!(" ~~ getting started ~~"); + eprintln!("mers doesn't need a specific structure for directories, just create a UTF-8 text file, write code, and run it:"); + eprintln!(" echo 'println(\"Hello, World!\")' > hello.mers"); + eprintln!(" mers hello.mers"); + return; + } + 'e' => execute = true, + 'v' => verbose = true, + 'c' => run = false, + 'f' => { + run = false; + info.log.after_parse.stderr = true; + } + 'V' => print_version = true, + 'i' => interactive += 1, + 't' => teachme = true, + ch => { + eprintln!("Ignoring -{ch}. (unknown char)"); + continue; + } + } + prev_char = Some(ch); + } else { + advanced = false; + if let Some(prev_char) = prev_char { + match prev_char { + 'i' => match ch { + 't' => interactive_use_new_terminal = true, + _ => eprintln!("Ignoring i+{ch}. (unknown adv char)"), + }, + 'v' => { + if ch != '+' { + advanced = true; + verbose_args.push(ch); + } + } + 'f' => match ch { + 'c' => info.formatter.mode = ColorFormatMode::Colorize, + 'C' => info.formatter.mode = ColorFormatMode::Plain, + _ => eprintln!("Ignoring f+{ch}. (unknown adv char)"), + }, + _ => (), + } + } else { + eprintln!( + "Ignoring advanced args because there was no previous argument." + ); + } + } + } + if print_version { + println!( + "mers {}", + option_env!("CARGO_PKG_VERSION") + .unwrap_or("[[ version unknown: no CARGO_PKG_VERSION ]]") + ); + return; + } + if teachme { + tutor::start(false); + return; + } + if verbose { + if verbose_args.is_empty() { + fn f() -> LogKind { + LogKind { + stderr: true, + log: true, + } + } + info.log.vtype_fits_in = f(); + info.log.vsingletype_fits_in = f(); + } else { + fn kind(val: Option<&str>) -> LogKind { + match val { + Some("stderr") => LogKind { + stderr: true, + ..Default::default() + }, + Some("log") => LogKind { + log: true, + ..Default::default() + }, + Some("log+stderr" | "stderr+log") => LogKind { + stderr: true, + log: true, + ..Default::default() + }, + _ => LogKind { + stderr: true, + ..Default::default() + }, + } + } + for verbose_arg in verbose_args.split(',') { + let (arg, val) = match verbose_arg.split_once('=') { + Some((left, right)) => (left, Some(right)), + None => (verbose_arg, None), + }; + match arg { + "vtype_fits_in" => info.log.vtype_fits_in = kind(val), + "vsingletype_fits_in" => info.log.vsingletype_fits_in = kind(val), + _ => eprintln!("Warn: -v+ unknown arg '{arg}'."), + } + } + } + } + if interactive > 0 { + match interactive { + _ => { + // basic: open file and watch for fs changes + interactive_mode::fs_watcher::playground(interactive_use_new_terminal) + .unwrap() + } + }; + return; + } else if execute { + parsing::file::File::new( + args.iter().skip(1).fold(String::new(), |mut s, v| { + if !s.is_empty() { + s.push(' '); + } + s.push_str(v); + s + }), + std::path::PathBuf::new(), + ) + } else { + args_to_skip += 1; + if let Some(file) = args.get(1) { + parsing::file::File::new( + std::fs::read_to_string(file).unwrap(), + file.into(), + ) + } else { + println!("nothing to do - missing arguments?"); + std::process::exit(101); + } + } + } else { + parsing::file::File::new( + std::fs::read_to_string(&args[0]).unwrap(), + args[0].as_str().into(), + ) + } + } + }; + info.main_fn_args = vec![( + "args".to_string(), + VSingleType::List(VSingleType::String.into()).to(), + )]; + match parsing::parse::parse_custom_info(&mut file, info) { + Ok(script) => { + if run { + script.run(vec![VDataEnum::List( + VSingleType::String.to(), + std::env::args() + .skip(args_to_skip) + .map(|v| VDataEnum::String(v).to()) + .collect(), + ) + .to()]); + } + } + Err(e) => { + println!("Couldn't compile:\n{}", e.with_file(&file)); + std::process::exit(99); + } + } +} diff --git a/mers/src/nushell_plugin.rs b/mers_old/src/nushell_plugin.rs similarity index 100% rename from mers/src/nushell_plugin.rs rename to mers_old/src/nushell_plugin.rs diff --git a/mers/src/parsing/file.rs b/mers_old/src/parsing/file.rs similarity index 100% rename from mers/src/parsing/file.rs rename to mers_old/src/parsing/file.rs diff --git a/mers/src/parsing/mod.rs b/mers_old/src/parsing/mod.rs similarity index 100% rename from mers/src/parsing/mod.rs rename to mers_old/src/parsing/mod.rs diff --git a/mers/src/parsing/parse.rs b/mers_old/src/parsing/parse.rs similarity index 100% rename from mers/src/parsing/parse.rs rename to mers_old/src/parsing/parse.rs diff --git a/mers/src/pathutil.rs b/mers_old/src/pathutil.rs similarity index 100% rename from mers/src/pathutil.rs rename to mers_old/src/pathutil.rs diff --git a/mers/src/tutor/base_comments.rs b/mers_old/src/tutor/base_comments.rs similarity index 100% rename from mers/src/tutor/base_comments.rs rename to mers_old/src/tutor/base_comments.rs diff --git a/mers/src/tutor/base_functions.rs b/mers_old/src/tutor/base_functions.rs similarity index 100% rename from mers/src/tutor/base_functions.rs rename to mers_old/src/tutor/base_functions.rs diff --git a/mers/src/tutor/base_return.rs b/mers_old/src/tutor/base_return.rs similarity index 100% rename from mers/src/tutor/base_return.rs rename to mers_old/src/tutor/base_return.rs diff --git a/mers/src/tutor/base_types.rs b/mers_old/src/tutor/base_types.rs similarity index 100% rename from mers/src/tutor/base_types.rs rename to mers_old/src/tutor/base_types.rs diff --git a/mers/src/tutor/base_values.rs b/mers_old/src/tutor/base_values.rs similarity index 100% rename from mers/src/tutor/base_values.rs rename to mers_old/src/tutor/base_values.rs diff --git a/mers/src/tutor/base_variables.rs b/mers_old/src/tutor/base_variables.rs similarity index 100% rename from mers/src/tutor/base_variables.rs rename to mers_old/src/tutor/base_variables.rs diff --git a/mers/src/tutor/error_handling.rs b/mers_old/src/tutor/error_handling.rs similarity index 100% rename from mers/src/tutor/error_handling.rs rename to mers_old/src/tutor/error_handling.rs diff --git a/mers/src/tutor/menu.rs b/mers_old/src/tutor/menu.rs similarity index 100% rename from mers/src/tutor/menu.rs rename to mers_old/src/tutor/menu.rs diff --git a/mers/src/tutor/mod.rs b/mers_old/src/tutor/mod.rs similarity index 100% rename from mers/src/tutor/mod.rs rename to mers_old/src/tutor/mod.rs diff --git a/mers/tests/destructuring_assignment.mers b/mers_old/tests/destructuring_assignment.mers similarity index 100% rename from mers/tests/destructuring_assignment.mers rename to mers_old/tests/destructuring_assignment.mers diff --git a/mers/tests/force_output_type.mers b/mers_old/tests/force_output_type.mers similarity index 100% rename from mers/tests/force_output_type.mers rename to mers_old/tests/force_output_type.mers diff --git a/mers/tests/functions_double_definitions.mers b/mers_old/tests/functions_double_definitions.mers similarity index 100% rename from mers/tests/functions_double_definitions.mers rename to mers_old/tests/functions_double_definitions.mers diff --git a/mers/tests/get_ref.mers b/mers_old/tests/get_ref.mers similarity index 100% rename from mers/tests/get_ref.mers rename to mers_old/tests/get_ref.mers diff --git a/mers/tests/lib_comms.rs b/mers_old/tests/lib_comms.rs similarity index 100% rename from mers/tests/lib_comms.rs rename to mers_old/tests/lib_comms.rs diff --git a/mers/tests/macro.mers b/mers_old/tests/macro.mers similarity index 100% rename from mers/tests/macro.mers rename to mers_old/tests/macro.mers diff --git a/mers/tests/modify_variable.mers b/mers_old/tests/modify_variable.mers similarity index 100% rename from mers/tests/modify_variable.mers rename to mers_old/tests/modify_variable.mers diff --git a/mers/tests/my_macro.mers b/mers_old/tests/my_macro.mers similarity index 100% rename from mers/tests/my_macro.mers rename to mers_old/tests/my_macro.mers diff --git a/mers/tests/return_true.mers b/mers_old/tests/return_true.mers similarity index 100% rename from mers/tests/return_true.mers rename to mers_old/tests/return_true.mers diff --git a/mers/tests/test_in_mers.rs b/mers_old/tests/test_in_mers.rs similarity index 100% rename from mers/tests/test_in_mers.rs rename to mers_old/tests/test_in_mers.rs diff --git a/mers/tests/thread_NOCHECK_ONLY_COMPILE.mers b/mers_old/tests/thread_NOCHECK_ONLY_COMPILE.mers similarity index 100% rename from mers/tests/thread_NOCHECK_ONLY_COMPILE.mers rename to mers_old/tests/thread_NOCHECK_ONLY_COMPILE.mers