-rw-r--r--Cargo.lock186
-rw-r--r--Cargo.toml17
-rw-r--r--LICENSE21
-rw-r--r--README.md15
-rw-r--r--rust-toolchain.toml2
-rw-r--r--src/array.rs18
-rw-r--r--src/exec.rs25
-rw-r--r--src/exec/python.rs3
-rw-r--r--src/lexer.rs231
-rw-r--r--src/main.rs4
-rw-r--r--src/parser.rs2
-rw-r--r--src/parser/fun.rs127
-rw-r--r--src/parser/types.rs3
-rw-r--r--src/parser/util.rs6
14 files changed, 270 insertions, 390 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 235abb2..208f70c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -13,35 +13,9 @@ dependencies = [
[[package]]
name = "allocator-api2"
-version = "0.2.16"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
-
-[[package]]
-name = "anstream"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
-dependencies = [
- "utf8parse",
-]
+checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "beef"
@@ -52,7 +26,7 @@ checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
[[package]]
name = "chumsky"
version = "0.13.0"
-source = "git+https://codeberg.org/zesterer/chumsky#ba2122d298639b9ecbf3289392b90dae70a4b0ef"
+source = "git+https://codeberg.org/zesterer/chumsky?rev=ba2122d298639b9ecbf3289392b90dae70a4b0ef#ba2122d298639b9ecbf3289392b90dae70a4b0ef"
dependencies = [
"hashbrown",
"unicode-ident",
@@ -62,7 +36,7 @@ dependencies = [
[[package]]
name = "codespan-reporting"
version = "0.13.1"
-source = "git+https://github.com/brendanzab/codespan#b56329354ce0ecbe4afe7c85f7b76417678a5ef8"
+source = "git+https://github.com/brendanzab/codespan?rev=b563293#b56329354ce0ecbe4afe7c85f7b76417678a5ef8"
dependencies = [
"serde",
"termcolor",
@@ -82,9 +56,9 @@ dependencies = [
[[package]]
name = "either"
-version = "1.13.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
[[package]]
name = "equivalent"
@@ -100,15 +74,15 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
-version = "0.1.4"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "hashbrown"
-version = "0.15.2"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
@@ -139,10 +113,7 @@ dependencies = [
"codespan-reporting",
"comat",
"itertools",
- "lerr",
"logos",
- "match_deref",
- "paste",
"pyo3",
"regex",
"tinyvec",
@@ -156,21 +127,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
-name = "lerr"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "318b7599710150e42b2d34f3582d047d3896de30c5d74c197d9b88a185a042b4"
-dependencies = [
- "anstream",
- "comat",
- "unicode-width",
-]
-
-[[package]]
name = "libc"
-version = "0.2.170"
+version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "logos"
@@ -207,17 +167,6 @@ dependencies = [
]
[[package]]
-name = "match_deref"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6653e44fdfe194f0276ecec9460aff0dfbe621f87097984d1816bd62ec626a53"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
name = "memchr"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -230,16 +179,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
-name = "paste"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
-
-[[package]]
name = "portable-atomic"
-version = "1.11.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
[[package]]
name = "proc-macro2"
@@ -392,17 +335,6 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
@@ -467,100 +399,36 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-segmentation"
-version = "1.12.0"
+version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
[[package]]
name = "unicode-width"
-version = "0.1.11"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
-
-[[package]]
-name = "utf8parse"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "winapi-util"
-version = "0.1.9"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
-name = "windows-sys"
-version = "0.59.0"
+name = "windows-link"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets",
-]
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
-name = "windows-targets"
-version = "0.52.6"
+name = "windows-sys"
+version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows-link",
]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/Cargo.toml b/Cargo.toml
index ab2e7c3..091513c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,25 +1,28 @@
[package]
+license = "MIT"
+description = "small interpreted stack-based array programming language"
name = "kale"
version = "0.1.0"
edition = "2024"
-
+authors = ["bendn <[email protected]>"]
+repository = "https://git.bendn.org/kale"
+categories = ["compilers", "parser-implementations"]
+keywords = ["stack", "language", "array"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-
-chumsky = { git = "https://codeberg.org/zesterer/chumsky", hash="ba2122d298639b9ecbf3289392b90dae70a4b0ef", features = [
+chumsky = { git = "https://codeberg.org/zesterer/chumsky", rev = "ba2122d298639b9ecbf3289392b90dae70a4b0ef", features = [
"nightly",
], default-features = false }
beef = "0.5.2"
logos = "0.15.1"
tinyvec = { version = "1.12.0", features = ["alloc"] }
comat = "0.1.3"
-lerr = "0.1.5"
-match_deref = "0.1.2"
-paste = "1.0.15"
regex = "1.13.1"
itertools = "0.14.0"
-codespan-reporting = { git = "https://github.com/brendanzab/codespan", version = "0.13.1" }
+codespan-reporting = { git = "https://github.com/brendanzab/codespan", rev = "b563293" }
umath = "0.0.7"
pyo3 = "0.29.2"
+[package.metadata.docs.rs]
+rustdoc-args = ["--generate-link-to-definition"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8c33164
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 bendn
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..92f2e1b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# `kale`
+
+kale is a stack based left-to-right interpreted array programming language
+
+this means every value is immediately pushed to the stack
+and every function will pop items off of the stack
+there are a few functions for stack manipulation.
+
+kale operates with a inferred "type"ing system, as in each function declares it's "signature" (items popped off stack -> items pushed to stack) and it goes from there
+
+most arithmetic / basic operations is pervasive, meaning that when running an operation over an array, it will compare them by each individual value.
+
+so when comparing arrays to arrays you get an array of booleans; same for arrays and values. comparing a value to a value you will get a single value.
+
+comparisons are reversed, for intuition sake.
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000..5d56faf
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly"
diff --git a/src/array.rs b/src/array.rs
deleted file mode 100644
index ec6d021..0000000
--- a/src/array.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use std::any::Any;
-
-use tinyvec::TinyVec;
-struct Array {
- shape: Shape,
- data: Vec<Box<dyn Any>>,
-}
-struct Shape {
- dims: TinyVec<[usize; 3]>,
-}
-
-impl Shape {
- pub fn scalar() -> Self {
- Shape {
- dims: TinyVec::new(),
- }
- }
-}
diff --git a/src/exec.rs b/src/exec.rs
index f94c757..07aba67 100644
--- a/src/exec.rs
+++ b/src/exec.rs
@@ -4,12 +4,11 @@ use std::fmt::Display;
use std::hash::Hash;
use std::iter::{once, successors};
use std::mem::take;
-use std::ops::{Add, Deref, DerefMut, Index};
+use std::ops::{Add, Deref, DerefMut};
mod python;
use chumsky::span::{SimpleSpan, Span as _};
use itertools::chain;
-use crate::parser::fun::Function;
use crate::parser::types::{Span, *};
use crate::parser::util::Spanner;
#[derive(Clone, Copy, PartialEq, Default, Eq, Hash, PartialOrd, Ord)]
@@ -1098,25 +1097,25 @@ impl<'s> Function<'s> {
Self::First => {
let array = pop!().assert_array(span)?;
stack.push(
- each!(array.inner, |x| Ok(Val::from(x.get(0).cloned().ok_or_else(|| {
- Error {
- name: format!("array is empty"),
- message: "here".to_string().spun(span),
- ..Default::default()
- }
- })?)), Vec<_> => Result<Val>)?.spun(span),
+ Val::from(array.get(0).ok_or_else(|| Error {
+ name: format!("array is empty"),
+ message: "here".to_string().spun(span),
+ ..Default::default()
+ })?)
+ .spun(span),
);
}
Self::Last => {
let array = pop!().assert_array(span)?;
stack.push(
- each!(array.inner, |x| Ok(Val::from(x.get(x.len()-1).cloned().ok_or_else(|| {
- Error {
+ Val::from(array.get(array.len() - 1).ok_or_else(
+ || Error {
name: format!("array is empty"),
message: "here".to_string().spun(span),
..Default::default()
- }
- })?)), Vec<_> => Result<Val>)?.spun(span),
+ },
+ )?)
+ .spun(span),
);
}
Self::Index => {
diff --git a/src/exec/python.rs b/src/exec/python.rs
index 6690fa6..8f7ddad 100644
--- a/src/exec/python.rs
+++ b/src/exec/python.rs
@@ -127,9 +127,10 @@ pub fn exec<'s>(
let x = locals.get_item("s").unwrap().unwrap();
let x = x.cast::<PyList>().unwrap();
let n = x.len();
+ assert_eq!(n, argc.output);
stack.extend(
x.into_iter()
- .skip(n.saturating_sub(argc.output))
+ // .skip(n.saturating_sub(argc.output))
.map(|x| x.extract::<Val<'_>>().map(|x| x.spun(span)))
.try_collect::<Vec<_>>()
.map_err(|_| Error::lazy(code.span, "nooo"))?,
diff --git a/src/lexer.rs b/src/lexer.rs
index 3b05d8a..103b88d 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -1,17 +1,30 @@
+#![allow(unexpected_cfgs, rustdoc::invalid_rust_codeblocks)]
use std::sync::LazyLock;
use beef::lean::Cow;
use chumsky::span::{SimpleSpan, Span};
use logos::{Lexer as RealLexer, Logos, SpannedIter};
use regex::Regex;
+
+use crate::exec::Argc;
+use crate::parser::types::{Λ, *};
static EMOJI: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"[\p{Emoji}&&[^0-9]]").unwrap());
+
macro_rules! tokens {
- ($($z:literal $( | $y:literal)? => $v:ident,)+) => {
+ ($(
+ $(#[$attr:ident = $attrval:expr])*
+ $z:literal $( | $y:literal)? => $v:ident $($eq:literal @)? $(_ $expr:tt)?,)+
+ //&
+
+ //$(
+ //$(#[$fattr:ident = $fattrval:expr])*
+ //$fname:ident $expr:tt),* $(,)?
+ ) => {
#[derive(Logos, Debug, PartialEq, Clone)]
#[logos(skip r"[\n\s]+")]
#[allow(dead_code)]
- pub(crate) enum Token<'strings> {
+ pub enum Token<'strings> {
#[regex("/[^\n/]+/?", priority = 8)]
Comment(&'strings str),
#[regex(r"[0-9]+", |lex| lex.slice().parse().ok())]
@@ -26,7 +39,7 @@ macro_rules! tokens {
#[regex(r"'.'", |lex| lex.slice().as_bytes()[1] as char)]
Char(char),
// todo ignore alot
- #[regex(r"[^\s\(\)\[\]\{\}⎬0-9λ'\-←→=≢≡+×\|*√<\-¯∧∨⊻÷%]", priority = 7, callback = |lex| {
+ #[regex(r"[^\s\(\)\[\]\{\}⎬0-9@'\-←→=≢≡+×\|*√<\-¯∧∨⊻÷%]", priority = 7, callback = |lex| {
EMOJI.is_match(lex.slice())
.then_some(logos::Filter::Skip)
.unwrap_or(logos::Filter::Emit(lex.slice()))
@@ -42,11 +55,27 @@ macro_rules! tokens {
#[token("}", chr::<'}'>)]
ClosingBracket(char),
- $(#[token($z, priority = 8)] $(#[token($y, priority = 8)])? $v,)+
+ $(
+ $(#[$attr = $attrval])*
+ $(#[doc = concat!("link", stringify!($eq), " [`Function::" , stringify!($v), "`]\n")])?
+ #[doc=concat!("character: `", $z, "`")]
+ #[token($z, priority = 8)]
+ $(#[token($y, priority = 8)])?
+ $v,)+
Unknown,
}
-
+ impl <'s> Function<'s> {
+ pub(crate) fn basic() -> crate::parser::util::parser![Self] {
+ use chumsky::Parser;
+ chumsky::select! {
+ Token::Zap => Self::Zap(None),
+ Token::ClosingBracket('}') => Self::Setify,
+ Token::Ident(x) => Self::Ident(x),
+ $($(Token::$v => {stringify!($eq); Self::$v },)?)+
+ }.labelled("token")
+ }
+ }
impl std::fmt::Display for Token<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
@@ -62,72 +91,146 @@ macro_rules! tokens {
}
}
}
+
+#[derive(Debug, Clone)]
+pub enum Function<'s> {
+ #[doc(hidden)]
+ Setify,
+ #[allow(dead_code)]
+ #[doc(hidden)]
+ If { then: Λ<'s>, or: Λ<'s> },
+ #[doc(hidden)]
+ Ident(&'s str),
+ #[doc(hidden)]
+ Define(&'s str),
+ // $($(#[$fattr = $fattrval])* $fname $expr,)*
+ $(
+ $(#[$attr = $attrval])*
+ $(#[doc = concat!("<h1>", $z, "</h1>")] #[cfg(not(target_family = $eq))] $v,)?
+ $(#[doc = concat!("<h1>", $z, "</h1>")] $v $expr,)?
+ )+
+ /// [n = drops n items.
+ ///
+ /// <h1>[</h1>
+ Take(u64),
+}
+
}
}
tokens! {
"λ" => Lambda,
- "⎦" => ArrayN,
+ /// Create an array from n items off the stack:
+ /// ```
+ /// 1 2 3 4 ⎦4
+ /// ```
+ /// Produces an array of [1, 2, 3, 4]
+ "⎦" => Array _ (Option<u64>),
"→" => Place,
- "≡" => Eq,
- "≣" => Matches,
- "≢" => Ne,
- "+" => Add,
- "-" => Sub,
- "×" => Mul,
- "ⁿ" => Pow,
- "<" => Lt,
- ">" => Gt,
- "≤" => Le,
- "≥" => Ge,
- "÷" => Div,
- "%" => Mod,
- "∧" => BitAnd,
- "∨" => Or,
- "⊕" => Xor,
- "∈" => In,
-
- "!" => Not,
- "¯" => Neg,
- "√" => Sqrt,
-
- "^" => Dup,
- "&" => And,
- "|" => Both,
- "🔀" => Flip,
- "⤵️" => Zap,
-
- "⬇️" => With,
- "⬆" => Merge,
- "⏫" => Range,
- "🪪" => Type,
- "📏" => Length,
- "👩‍👩‍👧‍👧" => Group,
- "📂" => Open,
- "⏪" => Shl,
- "⏩" => Shr,
- "❎" => Del,
- "📶" => Sort,
- "🔓" => Mask,
- "🔒" => Index,
- "#️⃣🗺" => HashMap,
- "≣#️⃣" => Get,
- "∅" => Set,
- "💽" => Append,
- "⬅️" => First,
- "➡" => Last,
- "↘️" => Reduce,
- "↖" => Scan,
- "⏭️" => Fold,
- "🗺" => Map,
+ /// Array contains.
+ "∈" => In "0" @,
+
+
+ /// Duplicates the top value of the stack.
+ "^" => Dup "0" @,
+ /// Runs n functions on the same values in the stack, pulling y items where y is the maximum arguments of any of the functions.
+ "&" => And _ (Vec<Spanned<Λ<'s>>>),
+ /// Runs one function n times, with new stack items every time, where n is the number of instances of this symbol.
+ /// ```kale
+ /// 1 2 3 4 +|
+ /// / results in 7 3
+ /// ```
+ "|" => Both _ (Spanned<Λ<'s>>, usize),
+ /// Flips the top two values on the stack.
+ "🔀" => Flip "0" @,
+ /// Zaps the top value on the stack, or the nth value, if followed by a number.
+ "⤵️" | "⤵" => Zap _ (Option<u64>),
+ /// Pops an array off of the stack to use it as a stack.
+ "⬇️" | "⬇" => With _ (Spanned<Λ<'s>>),
+ /// Pops a number, creates an array from 0-n
+ "⏫" => Range "0" @,
+ // "🪪" => Type "0" @,
+ /// Pops an array, gets the length.
+ "📏" => Length "0" @,
+ /// Groups an array by a mask, grouping by the ones in the mask array.
+ /// ```kale
+ /// 5⏫^2≢👩‍👩‍👧‍👧
+ /// ```
+ /// Would split by two, producing [0, 1] and [3, 4].
+ "👩‍👩‍👧‍👧" => Group "0" @,
+ /// Pops a string, opens that file, producing an array of utf8 integers.
+ "📂" => Open "0" @,
+ "⏪" => Shl "0" @,
+ "⏩" => Shr "0" @,
+ /// Takes an array, index, removes the element in the array at that index.
+ "❎" => Del "0" @,
+ /// Sorts an array.
+ "📶" => Sort "0" @,
+ /// Given an array, and a mask, masks the array by the mask.
+ /// In other words, picks only the values for which are one in the mask.
+ /// ```
+ /// 10⏫^5<
+ /// 🔓
+ /// ```
+ /// Produces [0, 1, 2, 3, 4],
+ "🔓" => Mask "0" @,
+ /// Given an array of indexes, and an array, indexes the array by those indices.
+ "🔒" => Index "0" @,
+ "#️⃣🗺" => HashMap "0" @,
+ "≣#️⃣" => IndexHashMap "0" @,
+ "∅" => EmptySet "0" @,
+ /// Places a value in an array.
+ "💽" => Append "0" @,
+ /// Get first item in array.
+ "⬅️" | "⬅" => First "0" @,
+ /// Get last item in array.
+ "➡️" | "➡" => Last "0" @,
+ /// Reduce an array by a function.
+ "↘️" | "↘" => Reduce _ (Spanned<Λ<'s>>),
+ /// Scan an array by a function. So it reduces, keeping the product.
+ "↖️" | "↖" => Scan _ (Spanned<Λ<'s>>),
+ /// Fold an array by a function (note that the accumulator is taken after the array).
+ "⏭️" | "⏭" => Fold _ (Spanned<Λ<'s>>),
+ /// Map an array by a function.
+ "🗺" => Map _ (Spanned<Λ<'s>>),
"🐋" => If,
"🐬" => EagerIf,
- "🇳🇿" => Zip,
- "🪟" => Windows,
- "🧐" => Debug,
- "." => Identity,
- "🐍" => Python,
+ /// Zip two arrays together.
+ "🇳🇿" => Zip "0" @,
+ /// Get the windows of an array.
+ "🪟" => Windows "0" @,
+ /// Debugs the stack at the current point in time.
+ "🧐" => Debug "0" @,
+ /// Takes one value, pushes one value.
+ "." => Identity "0" @,
+ /// Invoke python. Requires specifying the signature. In python land, the executor will be able to access a `s` variable, containing the stack. If the python does not satisfy the signature, an error will occur.
+ /// ```
+ /// 5 "s.append(s.pop()+1)"🐍1 → 1
+ /// ```
+ /// Produces six.
+ "🐍" => Python _ (Argc),
+
+
+ "≡" => Eq "0" @,
+ "≣" => Matches "0" @,
+ "≢" => Ne "0" @,
+ "+" => Add "0" @,
+ "-" => Sub "0" @,
+ "×" => Mul "0" @,
+ "ⁿ" => Pow "0" @,
+ "<" => Lt "0" @,
+ ">" => Gt "0" @,
+ "≤" => Le "0" @,
+ "≥" => Ge "0" @,
+ "÷" => Div "0" @,
+ "%" => Mod "0" @,
+ "∧" => BitAnd "0" @,
+ "∨" => Or "0" @,
+ "⊕" => Xor "0" @,
+ "!" => Not "0" @,
+ "¯" => Neg "0" @,
+ "√" => Sqrt "0" @,
}
pub fn lex(s: &str) -> Lexer<'_> {
@@ -141,7 +244,7 @@ fn chr<'src, const CHR: char>(
) -> Result<char, ()> {
Ok(CHR)
}
-pub(crate) struct Lexer<'s> {
+pub struct Lexer<'s> {
inner: SpannedIter<'s, Token<'s>>,
}
@@ -161,7 +264,7 @@ impl<'s> Iterator for Lexer<'s> {
fn lexer() {
let lex = lex(r#""1abc25hriwm4"
/ { str → int } /
- line ← λ (
+ line ← "0" @(
'0'>🔎'9'<🔎
'9'-
/ modifiers are placed in front /
diff --git a/src/main.rs b/src/main.rs
index a417450..06cf9a2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+#![doc = include_str!("../README.md")]
#![feature(
yeet_expr,
iter_intersperse,
@@ -7,11 +8,12 @@
impl_trait_in_bindings,
arbitrary_self_types
)]
-mod array;
+
mod exec;
mod lexer;
mod parser;
mod ui;
+pub use lexer::Function;
fn main() {
let x =
std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap();
diff --git a/src/parser.rs b/src/parser.rs
index 0e96c69..b416695 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -9,8 +9,6 @@ pub mod util;
use types::{Spanned, *};
use util::*;
-use self::fun::Function;
-
impl<'s> Value<'s> {
pub fn parse() -> parser![Spanned<Self>] {
select! {
diff --git a/src/parser/fun.rs b/src/parser/fun.rs
index 6222687..8989664 100644
--- a/src/parser/fun.rs
+++ b/src/parser/fun.rs
@@ -6,74 +6,8 @@ use super::util::*;
use crate::exec::Argc;
use crate::lexer::Token;
-#[derive(Debug, Clone)]
-pub enum Function<'s> {
- Both(Spanned<Λ<'s>>, usize),
- And(Vec<Spanned<Λ<'s>>>),
- Take(u64),
- If { then: Λ<'s>, or: Λ<'s> },
- Array(Option<u64>),
- Append,
- Map(Spanned<Λ<'s>>),
- Dup,
- Flip,
- Python(Argc),
- Matches,
- Eq,
- // Reverse,
- Zap(Option<u64>),
- Del,
- Debug,
- Add,
- Sub,
- IndexHashMap,
- Not,
- Mul,
- Windows,
- Pow,
- Type,
- Ne,
- Merge,
- Sqrt,
- Lt,
- Gt,
- Ge,
- Le,
- Shl,
- Shr,
- Neg,
- BitAnd,
- Length,
- Or,
- Xor,
- Div,
- Fold(Spanned<Λ<'s>>),
- Mod,
- Index,
- Mask,
- Group,
- Split,
- Open,
- First,
- Last,
- Reduce(Spanned<Λ<'s>>),
- Scan(Spanned<Λ<'s>>),
- Range,
- With(Spanned<Λ<'s>>),
- HashMap,
- Call,
- Sort,
- Zip,
- Identity,
- EmptySet,
- In,
- Setify,
- Ident(&'s str),
- Define(&'s str),
-}
-
impl<'s> Λ<'s> {
- pub fn parse(
+ pub(crate) fn parse(
exp: parser![Spanned<Expr<'s>>],
) -> parser![Spanned<Self>] {
exp.repeated()
@@ -85,62 +19,11 @@ impl<'s> Λ<'s> {
}
impl<'s> Function<'s> {
- pub fn parse(λ: parser![Λ<'s>]) -> parser![Self] {
+ pub(crate) fn parse(λ: parser![Λ<'s>]) -> parser![Self] {
use Function::*;
- let basic = select! {
- Token::Dup => Dup,
- Token::Debug => Debug,
- Token::Flip => Flip,
- // Token::Reverse => Reverse,
- Token::Zap => Zap(None),
- Token::Add => Add,
- Token::ClosingBracket('}') => Setify,
- Token::Set => EmptySet,
- Token::Identity => Identity,
- Token::Del => Del,
- Token::HashMap => HashMap,
- Token::Get => IndexHashMap,
- Token::Sub => Sub,
- Token::Windows => Windows,
- Token::Mul => Mul,
- Token::Pow => Pow,
- Token::Sqrt => Sqrt,
- Token::Lt => Lt,
- Token::Not => Not,
- Token::In => In,
- Token::Index => Index,
- Token::Merge => Merge,
- Token::Shl => Shl,
- Token::Group => Group,
- Token::Shr => Shr,
- Token::Append => Append,
- Token::Neg => Neg,
- Token::Eq => Eq,
- Token::Gt => Gt,
- Token::Ge => Ge,
- Token::Length => Length,
- Token::Range => Range,
- Token::Le => Le,
- Token::BitAnd => BitAnd,
- Token::Or => Or,
- Token::Xor => Xor,
- Token::Sort => Sort,
- Token::Zip => Zip,
- Token::Div => Div,
- Token::Mod => Mod,
- Token::Open => Open,
- Token::Mask => Mask,
- Token::First => First,
- Token::Ne => Ne,
- Token::Type => Type,
- Token::Matches => Matches,
- Token::Last => Last,
- Token::Ident(x) => Ident(x),
- }
- .labelled("token");
let fn_param = choice((
- basic
+ Self::basic()
.map_with(|x, e| {
Λ::of(vec![Expr::Function(x).spun(e.span())])
})
@@ -212,7 +95,7 @@ impl<'s> Function<'s> {
.then(t![int])
.map(|(a, b)| Python(Argc::takes(a as _).into(b as _))),
choice((
- just(Token::ArrayN)
+ just(Token::Array)
.ignore_then(t![int].map(|x| Array(Some(x)))),
t![']'].map(|_| Array(None)),
))
@@ -235,7 +118,7 @@ impl<'s> Function<'s> {
.labelled("if")
.boxed(),
t![->].ignore_then(t![ident]).map(Define).labelled("def"),
- basic,
+ Self::basic(),
))
.boxed()
.labelled("function")
diff --git a/src/parser/types.rs b/src/parser/types.rs
index 43a34dc..1373399 100644
--- a/src/parser/types.rs
+++ b/src/parser/types.rs
@@ -7,6 +7,7 @@ use chumsky::input::{MappedInput, Stream};
use chumsky::prelude::*;
use crate::exec::Argc;
+pub use crate::lexer::Function;
use crate::lexer::Token;
use crate::parser::util::Spanner;
pub type Span = SimpleSpan<usize>;
@@ -105,7 +106,7 @@ impl std::fmt::Debug for Expr<'_> {
#[derive(Clone)]
pub enum Expr<'s> {
- Function(super::fun::Function<'s>),
+ Function(Function<'s>),
Value(Value<'s>),
}
diff --git a/src/parser/util.rs b/src/parser/util.rs
index 7802fbc..3624116 100644
--- a/src/parser/util.rs
+++ b/src/parser/util.rs
@@ -55,7 +55,7 @@ macro_rules! t {
}
macro_rules! parser {
($t:ty) => {
- impl Parser<'s, crate::parser::types::Input<'s>, $t, extra::Err<Error<'s>>> + Clone + 's
+ impl chumsky::Parser<'s, crate::parser::types::Input<'s>, $t, chumsky::extra::Err<$crate::parser::types::Error<'s>>> + Clone + 's
}
}
@@ -77,7 +77,9 @@ macro_rules! spanned {
}
use chumsky::input::MapExtra;
-pub(crate) use {parser, spanned, t};
+pub(crate) use parser;
+pub(crate) use spanned;
+pub(crate) use t;
pub trait Unit<T> {
fn empty(&self) -> T;