From 90ef1f542d951a48ccbd850bfcc220eca55bc493 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 22 Sep 2023 23:54:09 -0500 Subject: [PATCH] lerox: Add lerox, a silly little combinator library --- Cargo.toml | 2 +- lerox/Cargo.toml | 10 ++++++++ lerox/src/lib.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ libconlang/Cargo.toml | 4 +++- 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 lerox/Cargo.toml create mode 100644 lerox/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 1d396ae..ddbd93a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["libconlang"] +members = ["libconlang", "lerox"] resolver = "2" [workspace.package] diff --git a/lerox/Cargo.toml b/lerox/Cargo.toml new file mode 100644 index 0000000..6ac8568 --- /dev/null +++ b/lerox/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "lerox" +authors.workspace = true +version.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] \ No newline at end of file diff --git a/lerox/src/lib.rs b/lerox/src/lib.rs new file mode 100644 index 0000000..95c60c9 --- /dev/null +++ b/lerox/src/lib.rs @@ -0,0 +1,53 @@ +//! Lerox is a stupid, simple combinator library, part of the Conlang project + +pub trait Combinable { + /// Evaluates the [Combinable], and returns whether it is alright + fn is_alright(&self) -> bool; + /// Makes this [Combinable] alright, somehow + fn alright(self) -> Self; +} + +pub trait Combinator: Combinable + Sized { + /// If self is alright, runs f(self) + fn and(self, f: impl Fn(Self) -> Self) -> Self { + match self.is_alright() { + true => f(self), + false => self, + } + } + + /// If self is not alright, runs f(self) + fn or(self, f: impl FnOnce(Self) -> Self) -> Self { + match self.is_alright() { + true => self, + false => f(self), + } + } + + /// Returns the result of running f on self, or if it fails, the original self + fn and_maybe(self, f: impl Fn(Self) -> Self) -> Self + where Self: Clone { + self.clone().and(f).or(|_| self) + } + + /// Returns the result of running f on self, or if it fails, runs g on self + fn and_either(self, f: impl Fn(Self) -> Self, g: impl Fn(Self) -> Self) -> Self + where Self: Clone { + self.clone().and(f).or(|_| g(self)) + } + + /// Repeats the function f on self until it fails + fn and_any(mut self, f: impl Fn(Self) -> Self) -> Self { + while self.is_alright() { + self = self.and(&f) + } + self.alright() + } + + /// Repeats the function f on self at least once, then until it fails. + fn and_many(self, f: impl Fn(Self) -> Self) -> Self { + self.and(&f).and_any(f) + } +} + +impl Combinator for C {} diff --git a/libconlang/Cargo.toml b/libconlang/Cargo.toml index 77e7773..36dfd20 100644 --- a/libconlang/Cargo.toml +++ b/libconlang/Cargo.toml @@ -1,9 +1,11 @@ [package] name = "conlang" +authors.workspace = true version.workspace = true edition.workspace = true -authors.workspace = true +license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lerox ={ path = "../lerox" } \ No newline at end of file