add readme
| -rw-r--r-- | Cargo.lock | 186 | ||||
| -rw-r--r-- | Cargo.toml | 17 | ||||
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | README.md | 15 | ||||
| -rw-r--r-- | rust-toolchain.toml | 2 | ||||
| -rw-r--r-- | src/array.rs | 18 | ||||
| -rw-r--r-- | src/exec.rs | 25 | ||||
| -rw-r--r-- | src/exec/python.rs | 3 | ||||
| -rw-r--r-- | src/lexer.rs | 231 | ||||
| -rw-r--r-- | src/main.rs | 4 | ||||
| -rw-r--r-- | src/parser.rs | 2 | ||||
| -rw-r--r-- | src/parser/fun.rs | 127 | ||||
| -rw-r--r-- | src/parser/types.rs | 3 | ||||
| -rw-r--r-- | src/parser/util.rs | 6 |
14 files changed, 270 insertions, 390 deletions
@@ -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" @@ -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"] @@ -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; |