bendn 2024-02-04
parent 244748f · commit 2bee12f
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--src/lexer.rs18
-rw-r--r--src/parser.rs10
-rw-r--r--src/parser/fun.rs100
-rw-r--r--src/parser/types.rs7
-rw-r--r--src/parser/util.rs2
-rw-r--r--src/stackd15
-rw-r--r--stackd26
9 files changed, 151 insertions, 35 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c918e5a..4833c23 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -104,6 +104,7 @@ dependencies = [
"lerr",
"logos",
"match_deref",
+ "paste",
"tinyvec",
]
@@ -168,6 +169,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
+name = "paste"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+
+[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index d1a4e37..3b200c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,3 +16,4 @@ tinyvec = { version = "1.6.0", features = ["alloc"] }
comat = "0.1.3"
lerr = "0.1.5"
match_deref = "0.1.1"
+paste = "1.0.14"
diff --git a/src/lexer.rs b/src/lexer.rs
index 559a9d7..d4d1476 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -22,9 +22,8 @@ macro_rules! tokens {
#[regex(r"'.'", |lex| lex.slice().as_bytes()[1] as char)]
Char(char),
// todo ignore alot
- #[regex(r"[^\s\(\)\[\]\{\}0-9Ξ»'\-←→=πŸ’πŸ˜πŸ΄πŸˆβ†–β€΅οΈ+Γ—*βˆšβ‰ <≀>β‰₯βͺ⏩\-¯∧∨⊻÷%πŸ”ŽπŸš§β¬…βž‘β­οΈβž‘οΈβ†˜οΈπŸ‹πŸ³][^\(\)\[\]\{\}λ←→='πŸ’πŸ˜πŸ΄πŸˆβ†–β€΅οΈ+Γ—*βˆšβ‰ <≀>β‰₯βͺ⏩¯∧∨⊻÷%πŸ”ŽπŸš§β¬…βž‘β­οΈβž‘οΈβ†˜οΈπŸ‹πŸ³\s]*", priority = 7)]
+ #[regex(r"[^\s\(\)\[\]\{\}0-9Ξ»'\-←→=β‰’β‰‘πŸ’πŸ¦†βœŠπŸͺ£πŸ”“πŸ˜πŸ΄πŸˆβ†–β€΅οΈβ˜ŽοΈπŸ”­+Γ—*βˆšβ‰ <≀>β‰₯βͺ⏩\-¯∧∨⊻÷%πŸ”ŽπŸš§β¬…βž‘β­οΈβž‘οΈβ†˜οΈπŸ‹πŸ³][^\(\)\[\]\{\}λ←→=≒≑'πŸ’πŸ˜πŸ΄βœŠπŸˆβ†–β€΅οΈ+πŸͺ£Γ—πŸ”“*βˆšπŸ¦†β‰ <≀>β‰₯β˜ŽοΈπŸ”­βͺ⏩¯∧∨⊻÷%πŸ”ŽπŸš§β¬…βž‘β­οΈβž‘οΈβ†˜οΈπŸ‹πŸ³\s]*", priority = 7)]
Ident(&'strings str),
-
#[token("[", chr::<'['>)]
#[token("(", chr::<'('>)]
#[token("{", chr::<'{'>)]
@@ -58,18 +57,22 @@ tokens! {
"Ξ»" => Lambda,
"←" => Place,
"β†’" => Ret,
- "=" => Eq,
+ "≑" => Eq,
"🐒" => Dup,
"🐘" => Both,
"🍴" => Fork,
+ "πŸͺ£" => Gap,
+ "✊" => Hold,
"🐈" => Flip,
+ "πŸ¦†" => Duck,
"β†–" => Reverse,
- "‡️" => Pop,
+ "‡️" => Zap,
"+" => Add,
+ "-" => Sub,
"Γ—" => Mul,
"*" => Pow,
"√" => Sqrt,
- "β‰ " => Ne,
+ "β‰’" => Ne,
"<" => Lt,
"≀" => Le,
">" => Gt,
@@ -79,19 +82,20 @@ tokens! {
"Β―" => Neg,
"∧" => And,
"∨" => Or,
- "-" => Sub,
"⊻" => Xor,
"Γ·" => Div,
"%" => Mod,
- "πŸ”Ž" => Keep,
+ "πŸ”“" => Keep,
"🚧" => Split,
"β¬…" => First,
"➑" => Last,
"⏭️" => Each,
"➑️" => Reduce,
"β†˜οΈ" => ReduceStack,
+ "⬆️" => Range,
"πŸ‹" => If,
"🐳" => Else,
+ "☎️" => Call,
}
diff --git a/src/parser.rs b/src/parser.rs
index df5af22..8cee0ef 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -5,6 +5,7 @@ use chumsky::{
prelude::*,
Parser,
};
+mod fun;
mod util;
use types::*;
use util::*;
@@ -34,7 +35,7 @@ impl<'s> Expr<'s> {
choice((t![ident].map(Expr::Ident), val)).boxed()
});
- let Ξ» = t![Ξ»].ignore_then(expr.clone().delimited_by(t!['('], t![')']));
+ let Ξ» = Lambda::parse().map(Expr::Lambda);
let decl = t![ident]
.then_ignore(t![<-])
@@ -56,13 +57,18 @@ impl<'s> Expr<'s> {
then: Box::new(a),
or: Box::new(b.unwrap_or_else(|| Expr::Value(Value::Unit))),
})
- .labelled("if")
+ .labelled("πŸ‹")
.boxed();
choice((decl, r#if, inline_expr, Ξ»))
})
}
}
+#[test]
+fn parse_expr() {
+ dbg!(Expr::parse().parse(code("a ← Ξ» ( +- 🍴 )")).unwrap());
+}
+
pub fn stream(lexer: Lexer<'_>, len: usize) -> SpannedInput<Token<'_>, Span, Stream<Lexer<'_>>> {
Stream::from_iter(lexer).spanned((len..len).into())
}
diff --git a/src/parser/fun.rs b/src/parser/fun.rs
new file mode 100644
index 0000000..9dfd561
--- /dev/null
+++ b/src/parser/fun.rs
@@ -0,0 +1,100 @@
+use super::types::*;
+use super::util::*;
+use crate::lexer::Token;
+use chumsky::{prelude::*, Parser};
+
+#[derive(Debug, Clone)]
+pub enum Function<'s> {
+ Dup,
+ Both(Lambda<'s>, Lambda<'s>),
+ Fork(Lambda<'s>, Lambda<'s>),
+ Gap(Lambda<'s>),
+ Hold(Lambda<'s>),
+ Flip,
+ Duck(Lambda<'s>),
+ Reverse,
+ Zap,
+ Add,
+ Sub,
+ Mul,
+ Pow,
+ Sqrt,
+ Ne,
+ Lt,
+ Le,
+ Gt,
+ Ge,
+ Shl,
+ Shr,
+ Neg,
+ And,
+ Or,
+ Xor,
+ Div,
+ Mod,
+ Keep,
+ Split,
+ First,
+ Last,
+ Each(Lambda<'s>),
+ Reduce(Lambda<'s>),
+ ReduceStack(Lambda<'s>),
+ Range,
+ Call,
+}
+
+impl<'s> Lambda<'s> {
+ pub fn parse() -> parser![Self] {
+ t![Ξ»]
+ .ignore_then(
+ Expr::parse()
+ .repeated()
+ .collect()
+ .delimited_by(t!['('], t![')']),
+ )
+ .map(|x| Self(x))
+ }
+}
+
+impl<'s> Function<'s> {
+ pub fn parse() -> parser![Self] {
+ use Function::*;
+ let basic = select! {
+ Token::Dup => Dup,
+ Token::Flip => Flip,
+ Token::Reverse => Reverse,
+ Token::Zap => Zap,
+ Token::Add => Add,
+ Token::Sub => Sub,
+ Token::Mul => Mul,
+ Token::Pow => Pow,
+ Token::Sqrt => Sqrt,
+ Token::Ne => Ne,
+ Token::Lt => Lt,
+ Token::Le => Le,
+ Token::Gt => Gt,
+ Token::Ge => Ge,
+ Token::Shl => Shl,
+ Token::Shr => Shr,
+ Token::Neg => Neg,
+ Token::And => And,
+ Token::Or => Or,
+ Token::Xor => Xor,
+ Token::Div => Div,
+ Token::Mod => Mod,
+ Token::Keep => Keep,
+ Token::Split => Split,
+ Token::First => First,
+ Token::Last => Last,
+ };
+ macro_rules! two {
+ ($name:ident) => {
+ Lambda::parse()
+ .then(Lambda::parse())
+ .then_ignore(just(Token::$name))
+ .map(|(a, b)| $name(a, b))
+ };
+ }
+ choice((basic, two![Both], two![Fork]))
+ }
+}
diff --git a/src/parser/types.rs b/src/parser/types.rs
index 298b573..2385564 100644
--- a/src/parser/types.rs
+++ b/src/parser/types.rs
@@ -15,6 +15,9 @@ pub enum Ast<'s> {
Module(Vec<Expr<'s>>),
}
+#[derive(Clone, Debug)]
+pub struct Lambda<'s>(pub Vec<Expr<'s>>);
+
#[derive(Clone)]
pub enum Value<'s> {
Float(f64),
@@ -34,11 +37,13 @@ impl std::fmt::Debug for Value<'_> {
}
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub enum Expr<'s> {
NoOp,
+ Function(super::fun::Function<'s>),
Value(Value<'s>),
Ident(&'s str),
+ Lambda(Lambda<'s>),
Let {
name: &'s str,
rhs: Box<Expr<'s>>,
diff --git a/src/parser/util.rs b/src/parser/util.rs
index a4f1c71..60c242a 100644
--- a/src/parser/util.rs
+++ b/src/parser/util.rs
@@ -29,7 +29,7 @@ macro_rules! t {
just(Token::ThinArrow)
};
(()) => {
- just(Token::Unit)
+ just(Token::Call)
};
('(') => {
just(Token::OpeningBracket('('))
diff --git a/src/stackd b/src/stackd
deleted file mode 100644
index 8c48039..0000000
--- a/src/stackd
+++ /dev/null
@@ -1,15 +0,0 @@
-"1abc25hriwm4"
-// { str β†’ int }
-line ← Ξ» (
- '0'>πŸ”Ž'9'<πŸ”Ž
- '9'-
- // modifiers are placed in front
- πŸ˜β¬…βž‘
- 10Γ—+
-)
-
-πŸ’β‰ '\n'🚧
-// run function on all values, pushing to the stack
-⏭️line
-// reduce the stack
-β†˜οΈ+ \ No newline at end of file
diff --git a/stackd b/stackd
index 2ec05e9..71d34ac 100644
--- a/stackd
+++ b/stackd
@@ -1,18 +1,26 @@
"1abc25hriwm4"
+// usage: 0 🐒 λ(<5) λ(1+) 🐬☎️
+🐬 ← Ξ» (
+ / evaluate the condition /
+ Ξ»(🐒πŸͺ£β˜ŽοΈ)✊✊
+ πŸ‹ (
+ / evaluate the body /
+ 🐒☎️
+ / recurse /
+ 🐬☎️
+ )
+)
+
// { str β†’ int }
line ← Ξ» (
- '0'>πŸ”Ž'9'<πŸ”Ž
+ '0'>πŸ”“'9'<πŸ”“
'9'-
- // modifiers are placed in front
- πŸ˜β¬…βž‘
+ β¬…βž‘πŸ΄
10Γ—+
)
-πŸ’β‰ '\n'🚧
-// run function on all values, pushing to the stack
+πŸ’β‰’'\n'🚧
+/ run function on all values, pushing to the stack /
⏭️line
-// reduce the stack
+/ reduce the stack /
β†˜οΈ+
-
-// true πŸ‹ (+ 🐳 -)
-// if true { + } else { - } \ No newline at end of file