-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--rustfmt.toml3
-rw-r--r--src/array.rs1
-rw-r--r--src/exec.rs737
-rw-r--r--src/lexer.rs22
-rw-r--r--src/main.rs5
-rw-r--r--src/parser.rs10
-rw-r--r--src/parser/fun.rs90
-rw-r--r--src/parser/types.rs69
-rw-r--r--src/parser/util.rs11
-rw-r--r--src/ui.rs58
-rw-r--r--test2
13 files changed, 715 insertions, 301 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d385158..18041dc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -138,6 +138,7 @@ dependencies = [
"paste",
"regex",
"tinyvec",
+ "umath",
]
[[package]]
@@ -323,6 +324,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
+name = "umath"
+version = "0.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f74eb7957e3a63fa27bfa53c3d361e7ce3871e66f2518292a011eb8e2c00cc"
+
+[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 78233a5..6032259 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,3 +19,4 @@ paste = "1.0.14"
regex = "1.11.1"
itertools = "0.14.0"
codespan-reporting = { git = "https://github.com/brendanzab/codespan", version = "0.11.1" }
+umath = "0.0.7"
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..3a18f83
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,3 @@
+max_width = 75
+group_imports = "StdExternalCrate"
+imports_granularity = "Module"
diff --git a/src/array.rs b/src/array.rs
index 6297f6f..ec6d021 100644
--- a/src/array.rs
+++ b/src/array.rs
@@ -1,4 +1,5 @@
use std::any::Any;
+
use tinyvec::TinyVec;
struct Array {
shape: Shape,
diff --git a/src/exec.rs b/src/exec.rs
index 80ab7fb..0ede0b4 100644
--- a/src/exec.rs
+++ b/src/exec.rs
@@ -1,18 +1,16 @@
-use crate::parser::types::Span;
-use crate::parser::{
- fun::{Function, NumberΛ},
- types::*,
- util::Spanner,
-};
-use chumsky::span::{SimpleSpan, Span as _};
-use itertools::Itertools;
+use std::collections::{BTreeSet, HashMap, HashSet};
+use std::fmt::Display;
+use std::hash::Hash;
+use std::iter::once;
use std::mem::take;
-use std::{
- collections::HashMap,
- fmt::Display,
- ops::{Add, Deref, DerefMut},
-};
-#[derive(Clone, Copy, PartialEq, Default)]
+use std::ops::{Add, Deref, DerefMut};
+
+use chumsky::span::{SimpleSpan, Span as _};
+
+use crate::parser::fun::Function;
+use crate::parser::types::{Span, *};
+use crate::parser::util::Spanner;
+#[derive(Clone, Copy, PartialEq, Default, Eq, Hash, PartialOrd, Ord)]
pub struct Argc {
input: usize,
output: usize,
@@ -42,15 +40,34 @@ pub enum Array {
Int(Vec<i128>),
Float(Vec<f64>),
}
+impl Hash for Array {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ core::mem::discriminant(self).hash(state);
+ match self {
+ Array::Array(items) => items.hash(state),
+ Array::Int(items) => items.hash(state),
+ Array::Float(items) => {
+ items.len().hash(state);
+ for x in items {
+ (x + 0.0).to_bits().hash(state);
+ }
+ }
+ }
+ }
+}
+
impl Array {
fn ty(&self) -> &'static str {
match self {
Array::Array(_) => "array",
- Array::Int(_) => "int",
- Array::Float(_) => "float",
+ Array::Int(_) => "ℤ",
+ Array::Float(_) => "ℝ",
}
}
- fn assert_int(self: Spanned<Array>, span: Span) -> Result<Spanned<Vec<i128>>> {
+ fn assert_int(
+ self: Spanned<Array>,
+ span: Span,
+ ) -> Result<Spanned<Vec<i128>>> {
self.try_map(|x, s| match x {
Array::Int(x) => Ok(x),
x => Err(Error::ef(span, "array[int]", x.ty().spun(s))),
@@ -68,14 +85,33 @@ macro_rules! each {
};
}
impl Array {
+ fn sort(&mut self) {
+ match self {
+ Array::Int(x) => x.sort_unstable(),
+ Array::Float(x) => x.sort_by_key(|x| unsafe {
+ assert!(x == x && !x.is_infinite());
+ umath::FF64::new(*x)
+ }),
+ Array::Array(_) => panic!(),
+ };
+ }
fn len(&self) -> usize {
each!(self, |x| x.len(), &Vec<_> => usize)
}
+ fn remove(&mut self, n: usize) {
+ each!(self, |x| { x.remove(n); }, &mut Vec<_> => ())
+ }
fn iter(&self) -> Box<dyn Iterator<Item = Val<'static>> + '_> {
match self {
- Array::Array(items) => Box::new(items.iter().cloned().map(Val::Array)),
- Array::Int(items) => Box::new(items.iter().copied().map(Val::Int)),
- Array::Float(items) => Box::new(items.iter().copied().map(Val::Float)),
+ Array::Array(items) => {
+ Box::new(items.iter().cloned().map(Val::Array))
+ }
+ Array::Int(items) => {
+ Box::new(items.iter().copied().map(Val::Int))
+ }
+ Array::Float(items) => {
+ Box::new(items.iter().copied().map(Val::Float))
+ }
}
}
}
@@ -114,6 +150,7 @@ impl Array {
return Array::Int(vec![]);
};
match inner {
+ Val::Map(_) | Val::Set(_) => panic!(),
Val::Array(_) => Array::Array(
v.into_iter()
.map(|x| match x {
@@ -141,17 +178,31 @@ impl Array {
Val::Lambda(_) => panic!(),
}
}
- fn of<'s>(entire: Span, value: impl Iterator<Item = Spanned<Val<'s>>>) -> Result<Self> {
+ fn of<'s>(
+ entire: Span,
+ value: impl Iterator<Item = Spanned<Val<'s>>>,
+ ) -> Result<Self> {
let mut v = value.peekable();
let Some(Spanned { inner, span }) = v.peek() else {
return Ok(Array::Int(vec![]));
};
Ok(match inner {
+ Val::Set(_) | Val::Map(_) => {
+ return Err(Error::ef(
+ entire,
+ "array | ℝ | ℤ",
+ "container".spun(*span),
+ ));
+ }
Val::Array(_) => Array::Array(
v.into_iter()
.map(|x| match x.inner {
Val::Array(x) => Ok(x),
- _ => Err(Error::ef(entire, "array", x.ty().spun(x.span))),
+ _ => Err(Error::ef(
+ entire,
+ "array",
+ x.ty().spun(x.span),
+ )),
})
.collect::<Result<_>>()?,
),
@@ -159,7 +210,11 @@ impl Array {
v.into_iter()
.map(|x| match x.inner {
Val::Float(x) => Ok(x),
- _ => Err(Error::ef(entire, "float", x.ty().spun(x.span))),
+ _ => Err(Error::ef(
+ entire,
+ "ℝ",
+ x.ty().spun(x.span),
+ )),
})
.collect::<Result<_>>()?,
),
@@ -167,85 +222,104 @@ impl Array {
v.into_iter()
.map(|x| match x.inner {
Val::Int(x) => Ok(x),
- _ => Err(Error::ef(entire, "int", x.ty().spun(x.span))),
+ _ => Err(Error::ef(
+ entire,
+ "ℤ",
+ x.ty().spun(x.span),
+ )),
})
.collect::<Result<_>>()?,
),
Val::Lambda(_) => {
- return Err(Error::ef(entire, "int | array | float", "λ".spun(*span)));
+ return Err(Error::ef(
+ entire,
+ "ℤ | array | ℝ",
+ "λ".spun(*span),
+ ));
}
})
}
fn new(entire: Span, value: Vec<Spanned<Val<'_>>>) -> Result<Self> {
- let Some(Spanned { inner, span }) = value.first() else {
- return Ok(Array::Int(vec![]));
- };
- Ok(match inner {
- Val::Array(_) => Array::Array(
- value
- .into_iter()
- .map(|x| match x.inner {
- Val::Array(x) => Ok(x),
- _ => Err(Error::ef(entire, "array", x.ty().spun(x.span))),
- })
- .collect::<Result<_>>()?,
- ),
- Val::Float(_) => Array::Float(
- value
- .into_iter()
- .map(|x| match x.inner {
- Val::Float(x) => Ok(x),
- _ => Err(Error::ef(entire, "float", x.ty().spun(x.span))),
- })
- .collect::<Result<_>>()?,
- ),
- Val::Int(_) => Array::Int(
- value
- .into_iter()
- .map(|x| match x.inner {
- Val::Int(x) => Ok(x),
- _ => Err(Error::ef(entire, "int", x.ty().spun(x.span))),
- })
- .collect::<Result<_>>()?,
- ),
- Val::Lambda(_) => {
- return Err(Error::ef(entire, "int | array | float", "λ".spun(*span)));
- }
- })
+ Self::of(entire, value.into_iter())
}
}
#[derive(Clone, PartialEq)]
pub enum Val<'s> {
Array(Array),
+ Map(Map<'s>),
+ Set(Set<'s>),
Lambda(Λ<'s>),
Int(i128),
Float(f64),
}
-
+type Map<'s> = HashMap<Val<'s>, Val<'s>>;
+impl Eq for Val<'_> {}
+impl Hash for Val<'_> {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ core::mem::discriminant(self).hash(state);
+ match self {
+ Val::Map(x) => x.len().hash(state),
+ Val::Float(x) => (x + 0.0).to_bits().hash(state),
+ Val::Array(x) => x.hash(state),
+ Val::Set(x) => x.len().hash(state),
+ Val::Lambda(x) => x.hash(state),
+ Val::Int(x) => x.hash(state),
+ }
+ }
+}
+type Set<'s> = HashSet<Val<'s>>;
impl<'s> Val<'s> {
- fn assert_array(self: Spanned<Val<'s>>, span: Span) -> Result<Spanned<Array>> {
+ fn assert_array(
+ self: Spanned<Val<'s>>,
+ span: Span,
+ ) -> Result<Spanned<Array>> {
match self.inner {
Self::Array(x) => Ok(x.spun(self.span)),
x => Err(Error::ef(span, "array", x.ty().spun(self.span))),
}
}
+ fn assert_map(
+ self: Spanned<Val<'s>>,
+ span: Span,
+ ) -> Result<Spanned<Map<'s>>> {
+ match self.inner {
+ Self::Map(x) => Ok(x.spun(self.span)),
+ x => Err(Error::ef(span, "map", x.ty().spun(self.span))),
+ }
+ }
+
+ fn assert_set(
+ self: Spanned<Val<'s>>,
+ span: Span,
+ ) -> Result<Spanned<Set<'s>>> {
+ match self.inner {
+ Self::Set(x) => Ok(x.spun(self.span)),
+ x => Err(Error::ef(span, "set", x.ty().spun(self.span))),
+ }
+ }
+ fn assert_int(
+ self: Spanned<Val<'s>>,
+ span: Span,
+ ) -> Result<Spanned<i128>> {
+ match self.inner {
+ Self::Int(x) => Ok(x.spun(self.span)),
+ x => Err(Error::ef(span, "ℤ", x.ty().spun(self.span))),
+ }
+ }
+
fn ty(&self) -> &'static str {
match self {
+ Self::Map(_) => "map",
+ Self::Set(_) => "set",
Self::Array(_) => "array",
- Self::Float(_) => "float",
- Self::Int(_) => "int",
- Self::Lambda(..) => "lambda",
+ Self::Float(_) => "ℝ",
+ Self::Int(_) => "ℤ",
+ Self::Lambda(..) => "λ",
}
}
}
-#[derive(Clone, Debug)]
-pub enum ConcreteVal {
- Array(Vec<ConcreteVal>),
- Int(i128),
- Float(f64),
-}
impl From<f64> for Val<'_> {
fn from(value: f64) -> Self {
Self::Float(value)
@@ -264,45 +338,11 @@ impl From<bool> for Val<'_> {
}
}
-// impl ConcreteVal {
-// fn val(self) -> Val<'static> {
-// match self {
-// ConcreteVal::Array(x) => {
-// Val::Array(x.into_iter().map(ConcreteVal::val).collect::<Vec<_>>())
-// }
-// ConcreteVal::Int(x) => Val::Int(x),
-// ConcreteVal::Float(x) => Val::Float(x),
-// }
-// }
-// }
-
-impl<'s> Val<'s> {
- // pub fn concrete(self: Spanned<Self>, user: SimpleSpan) -> Result<Spanned<ConcreteVal>> {
- // let (x, span) = self.raw();
- // Ok(match x {
- // Val::Array(x) => ConcreteVal::Array(
- // x.into_iter()
- // .map(|x| x.spun(span).concrete(user).map(|x| x.inner))
- // .collect::<Result<Vec<_>, _>>()?,
- // ),
- // Val::Float(x) => ConcreteVal::Float(x),
- // Val::Int(x) => ConcreteVal::Int(x),
- // Val::Lambda(..) => {
- // return Err(Error {
- // name: "value not concrete (λ)".into(),
- // message: "concrete value required here".to_string().spun(user),
- // labels: vec!["created here".to_string().spun(span)],
- // notes: vec![],
- // });
- // }
- // }
- // .spun(span))
- // }
-}
-
impl std::fmt::Debug for Val<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
+ Self::Map(x) => x.fmt(f),
+ Self::Set(x) => x.fmt(f),
Self::Array(x) => x.fmt(f),
Self::Lambda(x) => x.fmt(f),
Self::Int(x) => write!(f, "{x}"),
@@ -335,7 +375,10 @@ impl<'s, 'v> Context<'s, 'v> {
}
pub fn exec(x: Spanned<Λ<'_>>, code: &str) {
let mut s = Stack::new();
- crate::ui::display_execution(exec_lambda(x, &mut Context::default(), &mut s), code);
+ crate::ui::display_execution(
+ exec_lambda(x, &mut Context::default(), &mut s),
+ code,
+ );
println!("{s:?}");
}
impl std::fmt::Debug for Stack<'_> {
@@ -350,7 +393,15 @@ impl<'s> Stack<'s> {
fn new() -> Self {
Self(Vec::from([Vec::with_capacity(200)]))
}
- fn take(&mut self, take: usize) -> impl Iterator<Item = Spanned<Val<'s>>> {
+ fn pop_nth(&mut self, x: usize) -> Option<Spanned<Val<'s>>> {
+ let n = self.len().checked_sub(x + 1)?;
+ Some(self.remove(n))
+ }
+ #[track_caller]
+ fn take(
+ &mut self,
+ take: usize,
+ ) -> impl Iterator<Item = Spanned<Val<'s>>> {
let n = self.len();
self.drain(n - take..)
}
@@ -360,9 +411,6 @@ impl<'s> Stack<'s> {
pub fn push(&mut self, x: Spanned<Val<'s>>) {
self.curr().push(x);
}
- pub fn pop(&mut self) -> Option<Spanned<Val<'s>>> {
- self.curr().pop()
- }
pub fn curr(&mut self) -> &mut Vec<Spanned<Val<'s>>> {
self.0.last_mut().unwrap()
}
@@ -404,6 +452,15 @@ impl Default for Error {
}
impl Error {
+ pub fn lazy(span: Span, message: impl Display) -> Self {
+ Error {
+ name: message.to_string(),
+ message: "here".to_string().spun(span),
+ labels: vec![],
+ notes: vec![],
+ }
+ }
+
pub fn stack_empty(span: Span) -> Self {
Error {
name: "stack empty".into(),
@@ -413,11 +470,19 @@ impl Error {
}
}
- pub fn ef(span: Span, expected: impl Display, found: Spanned<impl Display>) -> Self {
+ pub fn ef(
+ span: Span,
+ expected: impl Display,
+ found: Spanned<impl Display>,
+ ) -> Self {
Error {
name: "type mismatch".to_string(),
- labels: vec![format!("found {found}, not an {expected}").spun(found.span())],
- message: format!("expected {expected} found {found}").spun(span),
+ labels: vec![
+ format!("found {found}, not an {expected}")
+ .spun(found.span()),
+ ],
+ message: format!("expected {expected} found {found}")
+ .spun(span),
notes: vec![],
}
}
@@ -449,12 +514,23 @@ impl<T> Annotate for Result<T> {
#[test]
fn x() {
assert!(
- crate::parser::parse_s("5 + 1 2 ×", crate::parser::top()).argc() == Argc::takes(1).into(2)
+ crate::parser::parse_s("5 + 1 2 ×", crate::parser::top()).argc()
+ == Argc::takes(1).into(2)
+ );
+ assert!(
+ crate::parser::parse_s("¯", crate::parser::top()).argc()
+ == Argc::takes(1).into(1)
+ );
+ assert!(
+ crate::parser::parse_s("0≥", crate::parser::top()).argc()
+ == Argc::takes(1).into(1)
);
- assert!(crate::parser::parse_s("¯", crate::parser::top()).argc() == Argc::takes(1).into(1));
- assert!(crate::parser::parse_s("0≥", crate::parser::top()).argc() == Argc::takes(1).into(1));
assert_eq!(
- crate::parser::parse_s("'0'-^9≤🔓0 1¯⎦2🔒(10×+)⬇", crate::parser::top()).argc(),
+ crate::parser::parse_s(
+ "'0'-^9≤🔓0 1¯⎦2🔒(10×+)⬇️",
+ crate::parser::top()
+ )
+ .argc(),
Argc::takes(1).into(1)
);
}
@@ -477,24 +553,36 @@ impl Add<Argc> for Argc {
fn size_fn<'s>(f: &Function<'s>) -> Argc {
use Function::*;
match f {
- Mask | Group | Index | Sub | Add | Mul | Div | Xor | Mod | Pow | Eq | Ne | BitAnd | Or
- | Ge | Le | Lt | Gt => Argc::takes(2).into(1),
- Reduce(_) => Argc::takes(1).into(1),
+ IndexHashMap | HashMap | Append | Length | Del | Fold(_)
+ | Mask | Group | Index | Sub | Add | Mul | Div | Xor | Mod
+ | Pow | Eq | Ne | BitAnd | Or | Ge | Le | Lt | Gt => {
+ Argc::takes(2).into(1)
+ }
+ &Take(x) => Argc::takes(x as _).into(x as _),
With(x) => Argc::takes(1).into(x.argc().output),
- Map(x) => Argc::takes(1 + (x.argc().input.saturating_sub(1))).into(1),
- Open | Neg | Sqrt | Not => Argc::takes(1).into(1),
+ Map(x) => {
+ Argc::takes(1 + (x.argc().input.saturating_sub(1))).into(1)
+ }
+ Identity | Setify | Sort | Range | Reduce(_) | Open | Neg
+ | Sqrt | Not => Argc::takes(1).into(1),
Flip => Argc::takes(2).into(2),
Dup => Argc::takes(1).into(2),
- Zap => Argc::takes(1).into(0),
+ Zap(None) | Zap(Some(0)) => Argc::takes(1).into(0),
+ &Zap(Some(x)) => Argc::takes(x as _).into(x as usize - 1),
Array(None) => {
Argc::takes(5 /*all */).into(1)
}
- Array(Some(NumberΛ::Number(x))) => Argc::takes(*x as _).into(1),
+ Array(Some(x)) => Argc::takes(*x as _).into(1),
// With => Argc::takes(1).into(),
- And(a, b) => {
- Argc::takes(a.argc().input.max(b.argc().input)).into(a.argc().output + b.argc().output)
+ And(all) => {
+ Argc::takes(all.iter().map(|x| x.argc().input).max().unwrap())
+ .into(all.iter().map(|x| x.argc().output).sum())
}
- Both(x) => Argc::takes(x.argc().input * 2).into(x.argc().output * 2),
+ Both(x, n) => {
+ Argc::takes(x.argc().input * n).into(x.argc().output * n)
+ }
+ Ident(x) => Argc::takes(0).into(1),
+ EmptySet => Argc::takes(0).into(1),
_ => Argc {
input: 0,
output: 0,
@@ -518,8 +606,9 @@ impl<'s> Λ<'s> {
pub fn sized(x: &[Spanned<Expr<'s>>]) -> Argc {
// 5 + (borrows) 1 2 *
// { 0, 1 } -> { 1, 1 } -> { 1, 3 } -> { 1, 2 }
- x.iter()
- .fold(Argc::takes(0).into(0), |acc, x| acc + size_expr(&x.inner))
+ x.iter().fold(Argc::takes(0).into(0), |acc, x| {
+ acc + size_expr(&x.inner)
+ })
}
}
@@ -534,9 +623,8 @@ fn exec_lambda<'s>(
match elem {
Expr::Function(x) => match x {
Function::Ident(x) => {
- let (x, span) = c
- .variables
- .get(x)
+ let (x, span) = std::iter::successors(Some(&*c), |x| x.inherits)
+ .find_map(|c| c.variables.get(x))
.unwrap_or_else(|| {
println!("couldnt find definition for variable {x} at ast node {x:?}");
std::process::exit(1);
@@ -544,15 +632,19 @@ fn exec_lambda<'s>(
.clone()
.raw();
match x {
- Val::Lambda(x) => {
- exec_lambda(x.spun(span), &mut Context::inherits(c), stack)?
- }
+ Val::Lambda(x) => exec_lambda(
+ x.spun(span),
+ &mut Context::inherits(c),
+ stack,
+ )?,
x => stack.push(x.spun(span)),
}
}
Function::Define(x) => {
- c.variables
- .insert(x, stack.pop().ok_or(Error::stack_empty(span))?);
+ c.variables.insert(
+ x,
+ stack.pop().ok_or(Error::stack_empty(span))?,
+ );
}
x => x.spun(span).execute(c, stack)?,
},
@@ -561,9 +653,9 @@ fn exec_lambda<'s>(
match x {
Value::Int(x) => Val::Int(x as i128),
Value::Float(x) => Val::Float(x),
- Value::String(x) => {
- Val::Array(Array::Int(x.bytes().map(|x| x as i128).collect()))
- }
+ Value::String(x) => Val::Array(Array::Int(
+ x.bytes().map(|x| x as i128).collect(),
+ )),
Value::Lambda(x) => Val::Lambda(x),
}
.spun(span),
@@ -598,15 +690,26 @@ fn pervasive_binop<'a>(
message: "for this function".to_string().spun(span),
..Default::default()
})
- .label(format!("first argument of type {}", x.ty()).spun(a.span))
- .label(format!("second argument of type {}", y.ty()).spun(b.span));
+ .label(
+ format!("first argument of type {}", x.ty())
+ .spun(a.span),
+ )
+ .label(
+ format!("second argument of type {}", y.ty())
+ .spun(b.span),
+ );
}
x.iter()
.zip(y.iter())
.map(|(x, y)| {
- pervasive_binop(span, &x.spun(a.span), &y.spun(b.span), map)
- .map(|x| x.spun(span))
+ pervasive_binop(
+ span,
+ &x.spun(a.span),
+ &y.spun(b.span),
+ map,
+ )
+ .map(|x| x.spun(span))
})
.collect::<Result<_>>()
.and_then(|x| Array::new(span, x))
@@ -615,8 +718,13 @@ fn pervasive_binop<'a>(
(Val::Array(x), y) | (y, Val::Array(x)) => x
.iter()
.map(|x| {
- pervasive_binop(span, &x.spun(a.span), &y.clone().spun(b.span), map)
- .map(|x| x.spun(span))
+ pervasive_binop(
+ span,
+ &x.spun(a.span),
+ &y.clone().spun(b.span),
+ map,
+ )
+ .map(|x| x.spun(span))
})
.collect::<Result<_>>()
.and_then(|x| Array::new(span, x))
@@ -647,7 +755,11 @@ fn pervasive_unop<'s>(
}
impl<'s> Function<'s> {
- pub fn execute(self: Spanned<Self>, c: &Context<'s, '_>, stack: &mut Stack<'s>) -> Result<()> {
+ pub fn execute(
+ self: Spanned<Self>,
+ c: &Context<'s, '_>,
+ stack: &mut Stack<'s>,
+ ) -> Result<()> {
let (x, span) = self.raw();
macro_rules! pop {
() => {
@@ -690,23 +802,36 @@ impl<'s> Function<'s> {
macro_rules! number_ab {
($a:expr) => {{
let a_ = pop!();
- let b_ = stack.pop().ok_or(
- Error::stack_empty(span).label("got first argument from here".spun(a_.span())),
- )?;
+ let b_ =
+ stack.pop().ok_or(Error::stack_empty(span).label(
+ "got first argument from here".spun(a_.span()),
+ ))?;
stack.push(
- pervasive_binop(span, &a_, &b_, |a, b| match (a, b) {
- (Val::Float(_), Val::Float(_)) => {
- Err(Error::ef(span, "int", "float".spun(a_.span()))
- .label("float (not int)".spun(b_.span())))
- }
- (Val::Int(x), Val::Int(y)) => Ok(Val::from(($a)(x, y))),
- (x, Val::Int(_)) => {
- Err(Error::ef(span, "expected int", x.ty().spun(a_.span())))
- }
- (Val::Int(_), x) => {
- Err(Error::ef(span, "expected int", x.ty().spun(b_.span())))
+ pervasive_binop(span, &a_, &b_, |a, b| {
+ match (a, b) {
+ (Val::Float(_), Val::Float(_)) => {
+ Err(Error::ef(
+ span,
+ "ℤ",
+ "ℝ".spun(a_.span()),
+ )
+ .label("ℝ (not ℤ)".spun(b_.span())))
+ }
+ (Val::Int(x), Val::Int(y)) => {
+ Ok(Val::from(($a)(x, y)))
+ }
+ (x, Val::Int(_)) => Err(Error::ef(
+ span,
+ "expected ℤ",
+ x.ty().spun(a_.span()),
+ )),
+ (Val::Int(_), x) => Err(Error::ef(
+ span,
+ "expected ℤ",
+ x.ty().spun(b_.span()),
+ )),
+ _ => unreachable!(),
}
- _ => unreachable!(),
})?
.spun(span),
)
@@ -718,7 +843,7 @@ impl<'s> Function<'s> {
.pop()
.ok_or(Error::stack_empty(span))?;
let Val::Int(x) = x.inner else {
- return Err(Error::ef(span, "integer", x.ty().spun(x.span())));
+ return Err(Error::ef(span, "ℤ", x.ty().spun(x.span())));
};
stack.push(Val::Int($x x).spun(span));
}};
@@ -783,7 +908,9 @@ impl<'s> Function<'s> {
Self::Div => concrete_ab!(/),
Self::Mod => concrete_ab!(Help::rem),
Self::Pow => concrete_ab!(Help::pow),
- Self::BitAnd => number_ab!(|a, b| a & b),
+ Self::BitAnd => {
+ number_ab!(|a, b| a & b)
+ }
Self::Or => number_ab!(|a, b| a | b),
Self::Xor => number_ab!(|a, b| a ^ b),
Self::Lt => concrete_ab!(<),
@@ -796,22 +923,11 @@ impl<'s> Function<'s> {
Self::Neg => unary!(-),
Self::Sqrt => unary!(Help::sqrt),
Self::Array(Some(x)) => {
- let r = match x {
- NumberΛ::Number(x) => x as usize,
- NumberΛ::Λ(x) => {
- exec_lambda(x, &mut Context::inherits(c), stack)?;
- let (y, yspan) = pop!().raw();
- match y {
- Val::Int(x) => x as usize,
- z => {
- return Err(Error::ef(span, "int", z.ty().spun(yspan)));
- }
- }
- }
- };
+ let r = x as usize;
let r = stack.len() - r;
let result = stack.split_off(r);
- stack.push(Val::Array(Array::new(span, result)?).spun(span))
+ stack
+ .push(Val::Array(Array::new(span, result)?).spun(span))
}
Self::Array(None) => {
let drained = Array::of(span, stack.drain(..))?;
@@ -822,51 +938,63 @@ impl<'s> Function<'s> {
stack.push(x.clone());
stack.push(x);
}
- Self::Zap => drop(stack.pop()),
+ Self::Zap(None) => drop(stack.pop()),
+ Self::Zap(Some(x)) => {
+ stack.pop_nth(x as _).ok_or_else(|| {
+ Error::stack_empty(span).label(
+ format!("needed {x} had {}", stack.len())
+ .spun(span),
+ )
+ })?;
+ }
Self::Flip => {
let x = pop!();
let y = pop!();
stack.push(x);
stack.push(y);
}
- Self::And(x, y) => {
- let xargs = x.argc();
- let yargs = y.argc();
- let requires = yargs.input.max(xargs.input);
-
- let s = Stack::of(stack.take(requires));
- let mut a = s.clone();
- exec_lambda(x, &mut Context::inherits(c), &mut a)?;
- let x = a.take(xargs.output);
-
- let mut a = s.clone();
- exec_lambda(y, &mut Context::inherits(c), &mut a)?;
- let y = a.take(yargs.output);
-
- stack.extend(x);
- stack.extend(y);
+ Self::And(λs) => {
+ let x = size_fn(&Self::And(λs.clone()));
+ let s = Stack::of(stack.take(x.input));
+ for λ in λs {
+ let λargc = λ.argc();
+ let mut a = s.clone();
+ exec_lambda(λ, &mut Context::inherits(c), &mut a)?;
+ let x = a.take(λargc.output);
+ stack.extend(x);
+ }
}
- Self::Both(λ) => {
- let xargs = λ.argc();
- let mut a = Stack::of(stack.take(xargs.input));
- exec_lambda(λ.clone(), &mut Context::inherits(c), &mut a)?;
-
- let mut b = Stack::of(stack.take(xargs.input));
- exec_lambda(λ, &mut Context::inherits(c), &mut b)?;
-
- stack.extend(b.take(xargs.output));
- stack.extend(a.take(xargs.output));
+ Self::Both(λ, n) => {
+ let λargs = λ.argc();
+ dbg!(λargs.input);
+ let mut s = Stack::of(stack.take(λargs.input * n));
+ for _ in 0..n {
+ let mut a = Stack::of(s.take(λargs.input));
+ exec_lambda(
+ λ.clone(),
+ &mut Context::inherits(c),
+ &mut a,
+ )?;
+ stack.extend(a.take(λargs.output));
+ }
+ assert!(s.is_empty());
}
Self::Mask => {
let mask = pop!().assert_array(span)?;
let a = pop!().assert_array(span)?;
let Array::Int(m) = mask.inner else {
- return Err(Error::ef(span, "array[bit]", mask.ty().spun(mask.span)));
+ return Err(Error::ef(
+ span,
+ "array[bit]",
+ mask.ty().spun(mask.span),
+ ));
};
if a.len() != m.len() {
return Err(Error {
name: "argument length mismatch".to_string(),
- message: "for this function".to_string().spun(span),
+ message: "for this function"
+ .to_string()
+ .spun(span),
labels: vec![],
notes: vec![],
}
@@ -875,14 +1003,18 @@ impl<'s> Function<'s> {
}
stack.push(
Val::Array(Array::new_unchecked(
- a.iter().zip(m).filter(|(_, x)| *x == 1).map(|(x, _)| x),
+ a.iter()
+ .zip(m)
+ .filter(|(_, x)| *x == 1)
+ .map(|(x, _)| x),
))
.spun(span),
);
}
Self::With(λ) => {
let array = pop!().assert_array(span)?;
- let mut a = Stack::of(array.iter().map(|x| x.spun(array.span)));
+ let mut a =
+ Stack::of(array.iter().map(|x| x.spun(array.span)));
exec_lambda(λ, &mut Context::inherits(c), &mut a)?;
stack.extend(a.drain(..));
}
@@ -911,20 +1043,32 @@ impl<'s> Function<'s> {
stack.push(out.spun(span));
}
Self::Open => {
- let x = pop!().assert_array(span)?.try_map(|x, s| match x {
- Array::Int(x) => String::from_utf8(x.into_iter().map(|x| x as u8).collect())
+ let x = pop!().assert_array(span)?.try_map(
+ |x, s| match x {
+ Array::Int(x) => String::from_utf8(
+ x.into_iter().map(|x| x as u8).collect(),
+ )
.map_err(|e| {
- Error::ef(span, "valid utf8", "invalid utf8".spun(s))
- .note(e.utf8_error().to_string())
+ Error::ef(
+ span,
+ "valid utf8",
+ "invalid utf8".spun(s),
+ )
+ .note(e.utf8_error().to_string())
}),
- x => Err(Error::ef(span, "array", x.ty().spun(s))),
- })?;
+ x => Err(Error::ef(span, "array", x.ty().spun(s))),
+ },
+ )?;
stack.push(
Val::Array(Array::Int(
std::fs::read(&*x)
.map_err(|e| {
- Error::ef(span, "valid file", "invalid file".spun(x.span))
- .note(e.to_string())
+ Error::ef(
+ span,
+ "valid file",
+ "invalid file".spun(x.span),
+ )
+ .note(e.to_string())
})?
.into_iter()
.map(|x| x as i128)
@@ -940,7 +1084,9 @@ impl<'s> Function<'s> {
if elem.len() != array.len() {
return Err(Error {
name: "argument length mismatch".to_string(),
- message: "for this function".to_string().spun(span),
+ message: "for this function"
+ .to_string()
+ .spun(span),
labels: vec![],
notes: vec![],
}
@@ -969,13 +1115,18 @@ impl<'s> Function<'s> {
Self::Map(λ) => {
if λ.argc().output != 1 {
return Err(Error {
- name: "parameter to 🗺 does not return 1 value".to_string(),
- message: λ.map(|λ| format!("return {}", λ.argc().output)),
+ name: "parameter to 🗺 does not return 1 value"
+ .to_string(),
+ message: λ.map(|λ| {
+ format!("return {}", λ.argc().output)
+ }),
..Default::default()
});
}
let x = pop!().assert_array(span)?;
- let s = Stack::of(stack.take(λ.argc().input.saturating_sub(1)));
+ let s = Stack::of(
+ stack.take(λ.argc().input.saturating_sub(1)),
+ );
stack.push(
Val::Array(Array::new(
span,
@@ -983,14 +1134,31 @@ impl<'s> Function<'s> {
.map(|x| {
let mut stack = s.clone();
stack.push(x.spun(span));
- exec_lambda(λ.clone(), &mut Context::inherits(c), &mut stack)
- .map(|()| stack.pop().expect("calculations failed"))
+ exec_lambda(
+ λ.clone(),
+ &mut Context::inherits(c),
+ &mut stack,
+ )
+ .map(
+ |()| {
+ stack
+ .pop()
+ .expect("calculations failed")
+ },
+ )
})
.collect::<Result<Vec<_>>>()?,
)?)
.spun(span),
);
}
+ Self::Range => {
+ let n = pop!().assert_int(span)?;
+ stack.push(
+ Val::Array(Array::Int((0..n.inner).collect()))
+ .spun(span),
+ );
+ }
Self::Reduce(λ) => {
let a = pop!().assert_array(span)?;
assert!(λ.argc().output == 1);
@@ -1000,9 +1168,17 @@ impl<'s> Function<'s> {
a.iter()
.map(|x| -> Val<'s> { x })
.try_reduce(|x, y| {
- let mut s = Stack::of([x, y].into_iter().map(|y| y.spun(a.span)));
- exec_lambda(λ.clone(), &mut Context::inherits(c), &mut s)
- .map(|()| s.pop().unwrap().inner)
+ let mut s = Stack::of(
+ [x, y]
+ .into_iter()
+ .map(|y| y.spun(a.span)),
+ );
+ exec_lambda(
+ λ.clone(),
+ &mut Context::inherits(c),
+ &mut s,
+ )
+ .map(|()| s.pop().unwrap().inner)
})?
.unwrap()
.spun(span),
@@ -1011,6 +1187,111 @@ impl<'s> Function<'s> {
// vec![1, 2].iter().reduce(|x, y| {});
// if λ.argc() !=
}
+ Self::Debug => {
+ println!("stack: {:?} @ {span}", stack);
+ }
+ Self::Fold(λ) => {
+ let a = pop!().assert_array(span)?;
+ assert!(dbg!(λ.argc()).input >= 2);
+ let input = λ.argc().input - 1;
+ assert!(λ.argc().output == input);
+ let accumulator = stack.take(input).collect::<Vec<_>>();
+ stack.extend(a.iter().map(|x| -> Val<'s> { x }).try_fold(
+ accumulator,
+ |acc, x| {
+ let mut s = Stack::of(
+ acc.into_iter().chain(once(x.spun(span))),
+ );
+ // acc on bottom💽
+ exec_lambda(
+ λ.clone(),
+ &mut Context::inherits(c),
+ &mut s,
+ )
+ .map(|()| s.take(input).collect())
+ },
+ )?)
+ }
+ Self::Take(n) => {
+ let z = stack.len();
+ stack.drain(..z - n as usize).for_each(drop);
+ }
+ Self::Del => {
+ let n = pop!().assert_int(span)?;
+ let mut a = pop!().assert_array(span)?;
+ a.inner.remove(n.inner as usize);
+ stack.push(a.map(Val::Array));
+ }
+ Self::Sort => {
+ let mut a = pop!().assert_array(span)?;
+ a.sort();
+ stack.push(a.map(Val::Array));
+ }
+ Self::Setify => {
+ let x = pop!().assert_array(span)?;
+ stack.push(x.map(|x| {
+ Val::Set(Set::from_iter(
+ x.iter().map(|x| -> Val<'s> { x }),
+ ))
+ }));
+ }
+ Self::EmptySet => stack.push(Val::Set(Set::new()).spun(span)),
+ Self::Append => {
+ let element = pop!();
+ let container =
+ stack.last_mut().ok_or(Error::stack_empty(span))?;
+ match &mut container.inner {
+ Val::Array(x) => {}
+ Val::Set(x) => drop(x.insert(element.inner)),
+ y => {
+ return Err(Error::ef(
+ span,
+ "array | set",
+ y.ty().spun(container.span),
+ ));
+ }
+ }
+ }
+ Self::Length => {
+ let x = stack.last().ok_or(Error::stack_empty(span))?;
+ stack.push(
+ Val::Int(match &x.inner {
+ Val::Array(x) => x.len(),
+ Val::Set(x) => x.len(),
+ y => {
+ return Err(Error::ef(
+ span,
+ "array | set",
+ y.ty().spun(x.span),
+ ));
+ }
+ } as i128)
+ .spun(span),
+ );
+ }
+ Self::HashMap => {
+ let vals = pop!().assert_array(span)?;
+ let keys = pop!().assert_array(span)?;
+ if vals.len() != keys.len() {
+ return Err(Error::lazy(span, "bad"));
+ }
+ stack.push(
+ Val::Map(
+ keys.iter().zip(vals.iter()).collect::<Map>(),
+ )
+ .spun(span),
+ );
+ }
+ Self::IndexHashMap => {
+ let index = pop!();
+ let map = pop!().assert_map(span)?;
+ stack.push(
+ map.get(&index.inner)
+ .ok_or(Error::lazy(span, "indexfail"))?
+ .clone()
+ .spun(span),
+ );
+ }
_ => (),
}
Ok(())
diff --git a/src/lexer.rs b/src/lexer.rs
index 7ed17ff..ca025fb 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -1,9 +1,11 @@
+use std::sync::LazyLock;
+
use beef::lean::Cow;
use chumsky::span::{SimpleSpan, Span};
use logos::{Lexer as RealLexer, Logos, SpannedIter};
use regex::Regex;
-use std::sync::LazyLock;
-static EMOJI: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"[\p{Emoji}&&[^0-9]]").unwrap());
+static EMOJI: LazyLock<Regex> =
+ LazyLock::new(|| Regex::new(r"[\p{Emoji}&&[^0-9]]").unwrap());
macro_rules! tokens {
($($z:literal $( | $y:literal)? => $v:ident,)+) => {
#[derive(Logos, Debug, PartialEq, Clone)]
@@ -94,7 +96,7 @@ tokens! {
"🔀" => Flip,
"⤵️" => Zap,
- "⬇" => With,
+ "⬇️" => With,
"⬆" => Merge,
"⏫" => Range,
"🪪" => Type,
@@ -103,19 +105,25 @@ tokens! {
"📂" => Open,
"⏪" => Shl,
"⏩" => Shr,
+ "❎" => Del,
"📶" => Sort,
"🔓" => Mask,
"🔒" => Index,
+ "#️⃣🗺" => HashMap,
+ "≣#️⃣" => Get,
+ "∅" => Set,
+ "💽" => Append,
"🚧" => Split,
- "⬅" => First,
+ "⬅️" => First,
"➡" => Last,
"↘️" => Reduce,
+ "⏭️" => Fold,
"🗺" => Map,
"🐋" => If,
"🐬" => EagerIf,
"🇳🇿" => Zip,
"🧐" => Debug,
- "." => Call,
+ "." => Identity,
}
@@ -125,7 +133,9 @@ pub fn lex(s: &str) -> Lexer {
}
}
-fn chr<'src, const CHR: char>(_: &mut RealLexer<'src, Token<'src>>) -> Result<char, ()> {
+fn chr<'src, const CHR: char>(
+ _: &mut RealLexer<'src, Token<'src>>,
+) -> Result<char, ()> {
Ok(CHR)
}
pub struct Lexer<'s> {
diff --git a/src/main.rs b/src/main.rs
index a6ff986..d3c8336 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
#![feature(
+ let_chains,
try_trait_v2,
iter_intersperse,
iterator_try_reduce,
@@ -12,7 +13,9 @@ mod lexer;
mod parser;
mod ui;
fn main() {
- let x = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap();
+ let x =
+ std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap();
+ println!("{x}");
let y = parser::parse_s(&x, parser::top());
exec::exec(y, &x);
}
diff --git a/src/parser.rs b/src/parser.rs
index aa08688..76680d1 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,6 +1,9 @@
pub mod types;
+use chumsky::Parser;
+use chumsky::input::Stream;
+use chumsky::prelude::*;
+
use crate::lexer::{Lexer, Token};
-use chumsky::{Parser, input::Stream, prelude::*};
pub mod fun;
pub mod util;
use types::*;
@@ -24,7 +27,8 @@ impl<'s> Value<'s> {
impl<'s> Expr<'s> {
pub fn parse() -> parser![Spanned<Expr<'s>>] {
recursive(|expr| {
- let inline_expr: parser![Spanned<Expr>] = Value::parse().map(|x| x.map(Expr::Value));
+ let inline_expr: parser![Spanned<Expr>] =
+ Value::parse().map(|x| x.map(Expr::Value));
let λ = Λ::parse(expr.clone());
choice((
@@ -50,7 +54,7 @@ pub fn top<'s>() -> parser![Spanned<Λ<'s>>] {
#[test]
fn parse_expr() {
// parse_s("a ← λ ( +-🍴 )", Expr::parse());
- let src = r#"+↘️"#;
+ let src = r#"+↘"#;
println!(
"{:?}",
crate::lexer::lex(src).map(|x| x.0).collect::<Vec<_>>()
diff --git a/src/parser/fun.rs b/src/parser/fun.rs
index 70f1fc2..bdd750c 100644
--- a/src/parser/fun.rs
+++ b/src/parser/fun.rs
@@ -1,28 +1,29 @@
+use chumsky::Parser;
+use chumsky::prelude::*;
+
use super::types::*;
use super::util::*;
use crate::lexer::Token;
-use chumsky::{Parser, prelude::*};
-
-#[derive(Debug, Clone)]
-pub enum NumberΛ<'s> {
- Number(u64),
- Λ(Spanned<Λ<'s>>),
-}
#[derive(Debug, Clone)]
pub enum Function<'s> {
- Both(Spanned<Λ<'s>>),
- And(Spanned<Λ<'s>>, Spanned<Λ<'s>>),
+ Both(Spanned<Λ<'s>>, usize),
+ And(Vec<Spanned<Λ<'s>>>),
+ Take(u64),
If { then: Λ<'s>, or: Λ<'s> },
- Array(Option<NumberΛ<'s>>),
+ Array(Option<u64>),
+ Append,
Map(Spanned<Λ<'s>>),
Dup,
Flip,
Eq,
Reverse,
- Zap,
+ Zap(Option<u64>),
+ Del,
+ Debug,
Add,
Sub,
+ IndexHashMap,
Not,
Mul,
Pow,
@@ -42,6 +43,7 @@ pub enum Function<'s> {
Or,
Xor,
Div,
+ Fold(Spanned<Λ<'s>>),
Mod,
Index,
Mask,
@@ -53,15 +55,21 @@ pub enum Function<'s> {
Reduce(Spanned<Λ<'s>>),
Range,
With(Spanned<Λ<'s>>),
+ HashMap,
Call,
Sort,
Zip,
+ Identity,
+ EmptySet,
+ Setify,
Ident(&'s str),
Define(&'s str),
}
impl<'s> Λ<'s> {
- pub fn parse(exp: parser![Spanned<Expr<'s>>]) -> parser![Spanned<Self>] {
+ pub fn parse(
+ exp: parser![Spanned<Expr<'s>>],
+ ) -> parser![Spanned<Self>] {
exp.repeated()
.collect()
.delimited_by(t!['('], t![')'])
@@ -75,10 +83,17 @@ impl<'s> Function<'s> {
use Function::*;
let basic = select! {
Token::Dup => Dup,
+ Token::Debug => Debug,
Token::Flip => Flip,
// Token::Reverse => Reverse,
- Token::Zap => Zap,
+ 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::Mul => Mul,
Token::Pow => Pow,
@@ -90,6 +105,7 @@ impl<'s> Function<'s> {
Token::Shl => Shl,
Token::Group => Group,
Token::Shr => Shr,
+ Token::Append => Append,
Token::Neg => Neg,
Token::Eq => Eq,
Token::Gt => Gt,
@@ -117,7 +133,9 @@ impl<'s> Function<'s> {
let fn_param = choice((
basic
- .map_with(|x, e| Λ::of(vec![Expr::Function(x).spun(e.span())]))
+ .map_with(|x, e| {
+ Λ::of(vec![Expr::Function(x).spun(e.span())])
+ })
.labelled("function"),
λ.clone(),
))
@@ -145,21 +163,43 @@ impl<'s> Function<'s> {
};
}
choice((
- two![And],
- one![Both],
+ λ.clone()
+ .map_with(spanned!())
+ .then(
+ fn_param
+ .clone()
+ .map_with(spanned!())
+ .repeated()
+ .at_least(1)
+ .collect::<Vec<_>>(),
+ )
+ .then_ignore(just(Token::And))
+ .map(|(a, mut b)| {
+ b.insert(0, a);
+ And(b)
+ })
+ .boxed(),
+ fn_param
+ .clone()
+ .map_with(spanned!())
+ .then(
+ just(Token::Both)
+ .repeated()
+ .at_least(1)
+ .count()
+ .map(|x| x + 1),
+ )
+ .map(|(a, b)| Both(a, b))
+ .labelled("both"),
one![Reduce],
+ one![Fold],
one![Map],
one![With],
+ just(Token::Zap).ignore_then(t![int]).map(Some).map(Zap),
+ t!['['].ignore_then(t![int]).map(Take),
choice((
- just(Token::ArrayN).ignore_then(
- fn_param
- .clone()
- .map_with(spanned!())
- .map(NumberΛ::Λ)
- .or(select! { Token::Int(x) => NumberΛ::Number(x) })
- .map(Some)
- .map(Array),
- ),
+ just(Token::ArrayN)
+ .ignore_then(t![int].map(|x| Array(Some(x)))),
t![']'].map(|_| Array(None)),
))
.labelled("array")
diff --git a/src/parser/types.rs b/src/parser/types.rs
index f3bd7a3..6a2eed9 100644
--- a/src/parser/types.rs
+++ b/src/parser/types.rs
@@ -1,14 +1,16 @@
-use crate::parser::util::Spanner;
-use crate::{exec::Argc, lexer::Token};
+use std::collections::HashSet;
+use std::fmt::FormattingOptions;
+use std::hash::Hash;
+use std::ops::{Deref, DerefMut};
+
use beef::lean::Cow;
-use chumsky::{
- input::{MappedInput, Stream},
- prelude::*,
-};
-use std::{
- fmt::FormattingOptions,
- ops::{Deref, Try},
-};
+use chumsky::input::{MappedInput, Stream};
+use chumsky::prelude::*;
+use umath::FF64;
+
+use crate::exec::Argc;
+use crate::lexer::Token;
+use crate::parser::util::Spanner;
pub type Span = SimpleSpan<usize>;
pub type Error<'s> = Rich<'s, Token<'s>, Span>;
pub type Input<'s> = MappedInput<
@@ -20,6 +22,22 @@ pub type Input<'s> = MappedInput<
#[derive(Clone, Default)]
pub struct Λ<'s>(pub Vec<Spanned<Expr<'s>>>, Argc);
+impl Hash for Λ<'_> {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.1.hash(state);
+ }
+}
+impl PartialOrd for Λ<'_> {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl Ord for Λ<'_> {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.1.cmp(&other.1)
+ }
+}
+impl Eq for Λ<'_> {}
impl PartialEq for Λ<'_> {
fn eq(&self, other: &Self) -> bool {
self.1 == other.1
@@ -44,10 +62,12 @@ impl std::fmt::Debug for Λ<'_> {
f.write_fmt(format_args!("λ({x:?})"))
} else {
write!(f, "λ")?;
- f.with_options(*FormattingOptions::new().alternate(true))
- .debug_list()
- .entries(&self.0)
- .finish()
+ f.with_options(
+ *FormattingOptions::new().alternate(true),
+ )
+ .debug_list()
+ .entries(&self.0)
+ .finish()
}
}
}
@@ -67,7 +87,9 @@ impl std::fmt::Debug for Value<'_> {
match self {
Self::Float(x) => write!(f, "{x}"),
Self::Int(x) => write!(f, "{x}"),
- Self::String(x) => write!(f, "\"{x}\""),
+ Self::String(x) => {
+ write!(f, "\"{x}\"")
+ }
Self::Lambda(s) => s.fmt(f),
}
}
@@ -112,6 +134,12 @@ impl<T> Deref for Spanned<T> {
}
}
+impl<T> DerefMut for Spanned<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
+ }
+}
+
impl<T> Spanned<T> {
pub fn map<U>(self, f: impl Fn(T) -> U) -> Spanned<U> {
Spanned {
@@ -120,7 +148,10 @@ impl<T> Spanned<T> {
}
}
- pub fn try_map<U, E>(self, f: impl Fn(T, Span) -> Result<U, E>) -> Result<Spanned<U>, E> {
+ pub fn try_map<U, E>(
+ self,
+ f: impl Fn(T, Span) -> Result<U, E>,
+ ) -> Result<Spanned<U>, E> {
let Self { inner, span } = self;
f(inner, span).map(|x| x.spun(span))
}
@@ -178,7 +209,11 @@ impl std::fmt::Debug for Type<'_> {
f,
"{}",
std::iter::once("(".to_string())
- .chain(x.iter().map(|x| format!("{x:?}")).intersperse(", ".into()),)
+ .chain(
+ x.iter()
+ .map(|x| format!("{x:?}"))
+ .intersperse(", ".into()),
+ )
.chain([")".to_string()])
.reduce(|acc, x| acc + &x)
.unwrap()
diff --git a/src/parser/util.rs b/src/parser/util.rs
index d01d405..7802fbc 100644
--- a/src/parser/util.rs
+++ b/src/parser/util.rs
@@ -49,6 +49,9 @@ macro_rules! t {
('}') => {
just(Token::ClosingBracket('}'))
};
+ (int) => {
+ select! { Token::Int(x) => x }
+ };
}
macro_rules! parser {
($t:ty) => {
@@ -60,7 +63,9 @@ pub trait TakeSpan {
fn tspn<T>(&mut self, x: T) -> Spanned<T>;
}
-impl<'a, 'b> TakeSpan for MapExtra<'a, 'b, Input<'a>, chumsky::extra::Err<Error<'a>>> {
+impl<'a, 'b> TakeSpan
+ for MapExtra<'a, 'b, Input<'a>, chumsky::extra::Err<Error<'a>>>
+{
fn tspn<T>(&mut self, x: T) -> Spanned<T> {
Spanned::from((x, self.span()))
}
@@ -72,9 +77,7 @@ macro_rules! spanned {
}
use chumsky::input::MapExtra;
-pub(crate) use parser;
-pub(crate) use spanned;
-pub(crate) use t;
+pub(crate) use {parser, spanned, t};
pub trait Unit<T> {
fn empty(&self) -> T;
diff --git a/src/ui.rs b/src/ui.rs
index 54bb40c..2a11d6a 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -1,29 +1,38 @@
-use crate::exec::Error as ExecutionError;
-use crate::parser::types::Error;
use chumsky::error::RichReason;
-use codespan_reporting::diagnostic::LabelStyle::{self, Primary, Secondary};
+use codespan_reporting::diagnostic::LabelStyle::{
+ self, Primary, Secondary,
+};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFiles;
-use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
-
use codespan_reporting::term::Chars;
+use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use comat::cformat as cmt;
-pub fn display_execution<T>(x: Result<T, ExecutionError>, code: &str) -> T {
+use crate::exec::Error as ExecutionError;
+use crate::parser::types::Error;
+
+pub fn display_execution<T>(
+ x: Result<T, ExecutionError>,
+ code: &str,
+) -> T {
let e = match x {
Ok(x) => return x,
Err(e) => e,
};
let mut files = SimpleFiles::new();
files.add("x.kale", code);
- let mut d = Diagnostic::<usize>::new(codespan_reporting::diagnostic::Severity::Error)
- .with_message(e.name)
- .with_label(
- Label::new(LabelStyle::Primary, 0, e.message.span()).with_message(e.message.raw().0),
- );
+ let mut d = Diagnostic::<usize>::new(
+ codespan_reporting::diagnostic::Severity::Error,
+ )
+ .with_message(e.name)
+ .with_label(
+ Label::new(LabelStyle::Primary, 0, e.message.span())
+ .with_message(e.message.raw().0),
+ );
for label in e.labels {
d = d.with_label(
- Label::new(LabelStyle::Secondary, 0, label.span()).with_message(label.raw().0),
+ Label::new(LabelStyle::Secondary, 0, label.span())
+ .with_message(label.raw().0),
);
}
@@ -32,11 +41,20 @@ pub fn display_execution<T>(x: Result<T, ExecutionError>, code: &str) -> T {
let writer = StandardStream::stderr(ColorChoice::Always);
let mut config = codespan_reporting::term::Config::default();
config.chars = Chars::box_drawing();
- codespan_reporting::term::emit(&mut writer.lock(), &config, &files, &d).unwrap();
+ codespan_reporting::term::emit(
+ &mut writer.lock(),
+ &config,
+ &files,
+ &d,
+ )
+ .unwrap();
std::process::exit(2);
}
-pub fn display<T>(result: Result<T, Vec<Error>>, code: &str) -> Result<T, ()> {
+pub fn display<T>(
+ result: Result<T, Vec<Error>>,
+ code: &str,
+) -> Result<T, ()> {
let e = match result {
Ok(x) => return Ok(x),
Err(e) => e,
@@ -46,7 +64,9 @@ pub fn display<T>(result: Result<T, Vec<Error>>, code: &str) -> Result<T, ()> {
files.add("x.kale", code);
for e in e.into_iter().map(|e| e.map_token(|c| c.to_string())) {
- let mut d = Diagnostic::<usize>::new(codespan_reporting::diagnostic::Severity::Error);
+ let mut d = Diagnostic::<usize>::new(
+ codespan_reporting::diagnostic::Severity::Error,
+ );
// let mut o = lerr::Error::new(code);
d = d.with_label(Label {
style: Primary,
@@ -92,7 +112,13 @@ pub fn display<T>(result: Result<T, Vec<Error>>, code: &str) -> Result<T, ()> {
let writer = StandardStream::stderr(ColorChoice::Always);
let mut config = codespan_reporting::term::Config::default();
config.chars = Chars::box_drawing();
- codespan_reporting::term::emit(&mut writer.lock(), &config, &files, &d).unwrap();
+ codespan_reporting::term::emit(
+ &mut writer.lock(),
+ &config,
+ &files,
+ &d,
+ )
+ .unwrap();
}
Err(())
}
diff --git a/test b/test
index d0bf63d..09e89dd 100644
--- a/test
+++ b/test
@@ -1,3 +1,3 @@
"input.txt"📂
^10≢👩‍👩‍👧‍👧
-('0'-^9≤🔓0 1¯⎦2🔒(🔀10×+)⬇)🗺 +↘️ \ No newline at end of file
+('0'-^9≤🔓0 1¯⎦2🔒(🔀10×+)⬇️)🗺 +↘️ \ No newline at end of file