checkpoint
| -rw-r--r-- | Cargo.lock | 7 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | rustfmt.toml | 3 | ||||
| -rw-r--r-- | src/array.rs | 1 | ||||
| -rw-r--r-- | src/exec.rs | 737 | ||||
| -rw-r--r-- | src/lexer.rs | 22 | ||||
| -rw-r--r-- | src/main.rs | 5 | ||||
| -rw-r--r-- | src/parser.rs | 10 | ||||
| -rw-r--r-- | src/parser/fun.rs | 90 | ||||
| -rw-r--r-- | src/parser/types.rs | 69 | ||||
| -rw-r--r-- | src/parser/util.rs | 11 | ||||
| -rw-r--r-- | src/ui.rs | 58 | ||||
| -rw-r--r-- | test | 2 |
13 files changed, 715 insertions, 301 deletions
@@ -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" @@ -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; @@ -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(()) } @@ -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 |