use std::collections::{BTreeSet, HashMap, HashSet}; use std::ffi::CString; use std::fmt::Display; use std::hash::Hash; use std::iter::{once, successors}; use std::mem::take; use std::ops::{Add, Deref, DerefMut}; mod python; 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, } impl std::fmt::Debug for Argc { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}.{}", self.input, self.output) } } type Result = std::result::Result; impl Argc { pub fn takes(input: usize) -> Self { Self { input, output: 0 } } pub fn produces(output: usize) -> Self { Self { input: 0, output } } pub fn into(self, output: usize) -> Self { Self { output, ..self } } } #[derive(Clone, PartialEq)] pub enum Array { Array(Vec), Int(Vec), Float(Vec), } impl Hash for Array { fn hash(&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(_) => "ℤ", Array::Float(_) => "ℝ", } } fn assert_int( self: Spanned, span: Span, ) -> Result>> { self.try_map(|x, s| match x { Array::Int(x) => Ok(x), x => Err(Error::ef(span, "array[int]", x.ty().spun(s))), }) } } macro_rules! each { ($y:expr,$x:expr,$in:ty => $into: ty) => { match $y { Array::Int(x) => annote::<$in, $into>($x)(x), Array::Float(x) => annote::<$in, $into>($x)(x), Array::Array(x) => annote::<$in, $into>($x)(x), } }; } 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 windows(self, size: usize) -> Array { each!(self, |x| Array::Array( x.windows(size).map(|x| Array::from(x.to_vec())).collect(), ), Vec<_> => Array) } fn remove(&mut self, n: usize) { each!(self, |x| { x.remove(n); }, &mut Vec<_> => ()) } fn iter(&self) -> Box> + '_> { 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)) } } } } impl std::fmt::Debug for Array { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Array(x) => write!(f, "a{x:#?}"), Self::Int(x) => write!(f, "i{x:#?}"), Self::Float(x) => write!(f, "f{x:#?}"), } } } impl From> for Array { fn from(value: Vec) -> Self { Array::Int(value) } } impl From> for Array { fn from(value: Vec) -> Self { Array::Float(value) } } impl From> for Array { fn from(value: Vec) -> Self { Array::Array(value) } } impl Array { #[track_caller] fn new_unchecked<'s>(value: impl Iterator>) -> Self { let mut v = value.peekable(); let Some(inner) = v.peek() else { return Array::Int(vec![]); }; match inner { Val::Map(_) | Val::Set(_) => panic!(), Val::Array(_) => Array::Array( v.into_iter() .map(|x| match x { Val::Array(x) => x, _ => panic!(), }) .collect(), ), Val::Float(_) => Array::Float( v.into_iter() .map(|x| match x { Val::Float(x) => x, _ => panic!(), }) .collect(), ), Val::Int(_) => Array::Int( v.into_iter() .map(|x| match x { Val::Int(x) => x, _ => panic!(), }) .collect(), ), Val::Lambda(_) => panic!(), } } fn of<'s>( entire: Span, value: impl Iterator>>, ) -> Result { 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), )), }) .collect::>()?, ), Val::Float(_) => Array::Float( v.into_iter() .map(|x| match x.inner { Val::Float(x) => Ok(x), _ => Err(Error::ef( entire, "ℝ", x.ty().spun(x.span), )), }) .collect::>()?, ), Val::Int(_) => Array::Int( v.into_iter() .map(|x| match x.inner { Val::Int(x) => Ok(x), _ => Err(Error::ef( entire, "ℤ", x.ty().spun(x.span), )), }) .collect::>()?, ), Val::Lambda(_) => { return Err(Error::ef( entire, "ℤ | array | ℝ", "λ".spun(*span), )); } }) } fn new(entire: Span, value: Vec>>) -> Result { 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>>; impl Eq for Val<'_> {} impl Hash for Val<'_> { fn hash(&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>; impl<'s> Val<'s> { fn assert_array( self: Spanned>, span: Span, ) -> Result> { match self.inner { Self::Array(x) => Ok(x.spun(self.span)), x => Err(Error::ef(span, "array", x.ty().spun(self.span))), } } fn assert_utf8( self: Spanned>, span: Span, ) -> Result> { self.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()) }) } x => Err(Error::ef(span, "array", x.ty().spun(s))), }) } fn assert_map( self: Spanned>, span: Span, ) -> Result>> { 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>, span: Span, ) -> Result>> { 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>, span: Span, ) -> Result> { 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(_) => "ℝ", Self::Int(_) => "ℤ", Self::Lambda(..) => "λ", } } } impl From for Val<'_> { fn from(value: f64) -> Self { Self::Float(value) } } impl From for Val<'_> { fn from(value: i128) -> Self { Self::Int(value) } } impl From for Val<'_> { fn from(value: bool) -> Self { Self::Int(value as i128) } } 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}"), Self::Float(x) => write!(f, "{x}"), } } } pub struct Context<'s, 'v> { pub inherits: Option<&'v Context<'s, 'v>>, pub variables: HashMap<&'s str, Spanned>>, } impl<'s, 'v> Default for Context<'s, 'v> { fn default() -> Self { Self { inherits: None, variables: Default::default(), } } } impl<'s, 'v> Context<'s, 'v> { fn all(&self) -> impl Iterator { successors(Some(&*self), |x| x.inherits) } fn inherits(x: &'v Context<'s, 'v>) -> Self { Self { inherits: Some(x), variables: Default::default(), } } } 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, ); println!("{s:?}"); } impl std::fmt::Debug for Stack<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "{:#?}", self.cur()) } } #[derive(Clone)] pub struct Stack<'s>(Vec>>>); impl<'s> Stack<'s> { fn new() -> Self { Self(Vec::from([Vec::with_capacity(200)])) } fn pop_nth(&mut self, x: usize) -> Option>> { let n = self.len().checked_sub(x + 1)?; Some(self.remove(n)) } #[track_caller] fn take( &mut self, take: usize, ) -> impl Iterator>> + ExactSizeIterator { let n = self.len(); self.drain(n.saturating_sub(take)..) } pub fn of(x: impl Iterator>>) -> Self { Self(vec![x.collect()]) } pub fn push(&mut self, x: Spanned>) { self.curr().push(x); } pub fn curr(&mut self) -> &mut Vec>> { self.0.last_mut().unwrap() } pub fn cur(&self) -> &[Spanned>] { self.0.last().unwrap() } } impl<'s> Deref for Stack<'s> { type Target = Vec>>; fn deref(&self) -> &Self::Target { self.0.last().unwrap() } } impl<'s> DerefMut for Stack<'s> { fn deref_mut(&mut self) -> &mut Self::Target { self.curr() } } #[derive(Debug)] pub struct Error { pub name: String, pub message: Spanned, pub labels: Vec>, pub notes: Vec, } impl Default for Error { fn default() -> Self { Self { name: Default::default(), message: String::default().spun(Span::new((), 0..0)), labels: Default::default(), notes: Default::default(), } } } 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(), message: "empty stack".to_string().spun(span), labels: vec![], notes: vec![], } } pub fn ef( span: Span, expected: impl Display, found: Spanned, ) -> 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), notes: vec![], } } } trait Annotate { fn label(self, message: Spanned>) -> Self; fn note(self, message: impl Into) -> Self; } impl Annotate for Error { fn label(mut self, message: Spanned>) -> Self { self.labels.push(message.map(|x| x.into())); self } fn note(mut self, message: impl Into) -> Self { self.notes.push(message.into()); self } } impl Annotate for Result { fn label(self, message: Spanned>) -> Self { self.map_err(|x| x.label(message)) } fn note(self, message: impl Into) -> Self { self.map_err(|x| x.note(message)) } } #[test] fn x() { assert!( 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_eq!( crate::parser::parse_s( "'0'-^9≤🔓0 1¯⎦2🔒(10×+)⬇️", crate::parser::top() ) .argc(), Argc::takes(1).into(1) ); } impl Add for Argc { type Output = Self; fn add(mut self, rhs: Argc) -> Self { match self.output.checked_sub(rhs.input) { Some(x) => self.output = x + rhs.output, // borrow inputs None => { self.input += rhs.input - self.output; self.output = rhs.output; } } self } } fn size_fn<'s>(f: &Function<'s>) -> Argc { use Function::*; match f { Matches | Windows | IndexHashMap | HashMap | Append | Del | Fold(_) | Mask | Group | Index | Sub | Add | Mul | Div | Xor | Mod | Pow | Eq | Ne | BitAnd | Or | Ge | Le | Lt | Gt | In => { Argc::takes(2).into(1) } Python(x) => *x, &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) } Length | 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), Define(_) | 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(x)) => Argc::takes(*x as _).into(1), // With => Argc::takes(1).into(), And(all) => { Argc::takes(all.iter().map(|x| x.argc().input).max().unwrap()) .into(all.iter().map(|x| x.argc().output).sum()) } Both(x, n) => { Argc::takes(x.argc().input * n).into(x.argc().output * n) } Ident(_) => Argc::takes(0).into(1), EmptySet => Argc::takes(0).into(1), _ => Argc { input: 0, output: 0, }, } } fn size_expr<'s>(x: &Expr<'s>) -> Argc { match x { Expr::Function(function) => size_fn(function), Expr::Value(_) => Argc::produces(1), } } fn normalize_index(x: i128, size: usize) -> usize { match x { ..0 => (size as i128 + x) as usize, _ => x as usize, } } impl<'s> Λ<'s> { pub fn sized(x: &[Spanned>]) -> 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) }) } } fn exec_lambda<'s>( x: Spanned<Λ<'s>>, c: &mut Context<'s, '_>, stack: &mut Stack<'s>, ) -> Result<()> { let (x, upper) = x.raw(); for elem in x.0 { let (elem, span) = elem.raw(); match elem { Expr::Function(x) => match x { Function::Ident(x) => { let (x, span) = c.all() .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); }) .clone() .raw(); match x { 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))?, ); } x => x.spun(span).execute(c, stack)?, }, Expr::Value(x) => { stack.push( 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::Lambda(x) => Val::Lambda(x), } .spun(span), ); } } } Ok(()) } fn pervasive_binop<'a>( span: SimpleSpan, a: &Spanned>, b: &Spanned>, map: impl Fn(&Val<'a>, &Val<'a>) -> Result> + Copy, ) -> Result> { match (&a.inner, &b.inner) { (Val::Array(x), Val::Array(y)) => { if x.len() != y.len() { return Err(Error { name: "argument length mismatch".to_string(), message: "for this function".to_string().spun(span), labels: vec![], notes: vec![], } .label("first argument".spun(a.span)) .label("second argument".spun(b.span))); } if x.ty() != y.ty() { return Err(Error { name: "array type mismatch".to_string(), 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), ); } 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)) }) .collect::>() .and_then(|x| Array::new(span, x)) .map(Val::Array) } (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)) }) .collect::>() .and_then(|x| Array::new(span, x)) .map(Val::Array), (x, y) => map(x, y), } } fn pervasive_unop<'s>( Spanned { inner: x, span }: Spanned>, f: impl Fn(Val<'s>) -> Result> + Copy, ) -> Result> { match x { Val::Array(x) => x .iter() .map(|x| { match x { x @ Val::Array(_) => pervasive_unop(x.spun(span), f), x => f(x), } .map(|x| x.spun(span)) }) .collect::>() .and_then(|x| Array::new(span, x)) .map(Val::Array), x => f(x), } } impl<'s> Function<'s> { pub fn execute( self: Spanned, c: &Context<'s, '_>, stack: &mut Stack<'s>, ) -> Result<()> { let (x, span) = self.raw(); macro_rules! pop { () => { stack.pop().ok_or(Error::stack_empty(span))? }; } macro_rules! concrete_ab { ($x:tt) => { concrete_ab!(|a, b| a $x b) }; ($a: expr) => {{ let b_ = stack .pop() .ok_or(Error::stack_empty(span, ))?; let a_ = stack .pop() .ok_or(Error::stack_empty(span).label( "got second argument from here".spun(b_.span()), ))?; stack.push(pervasive_binop( span, &a_, &b_, |a, b| { match (a, b) { (Val::Float(x), Val::Int(y)) | (Val::Int(y), Val::Float(x)) => Ok(Val::from(($a)(x, &(*y as f64)))), (Val::Int(x), Val::Int(y)) => Ok(Val::from(($a)(x, y))), (Val::Float(x), Val::Float(y)) => Ok(Val::from(($a)(x, y))), (x, Val::Float(_) | Val::Int(_)) => Err(Error::ef(span, "expected number", x.ty().spun(a_.span()))), (Val::Float(_) | Val::Int(_), x) => Err(Error::ef(span, "expected number", x.ty().spun(b_.span()))), _ => unreachable!(), } }, )?.spun(span)); }}; } 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()), ))?; stack.push( 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!(), } })? .spun(span), ) }}; } macro_rules! unary_num { ($x:tt) => {{ let x = stack .pop() .ok_or(Error::stack_empty(span))?; let Val::Int(x) = x.inner else { return Err(Error::ef(span, "ℤ", x.ty().spun(x.span()))); }; stack.push(Val::Int($x x).spun(span)); }}; } macro_rules! unary { ($x:tt) => { unary!(|x| $x x) }; ($x:expr) => {{ let x = pop!(); let xspan = x.span(); stack.push( pervasive_unop(x, |x| { Ok(match x { Val::Int(x) => Val::Int(annotate::($x)(&x)), Val::Float(x) => Val::Float(annotate::($x)(&x)), _ => { return Err(Error::ef(span, "number", x.ty().spun(xspan))); } }) })? .spun(span), ); }}; } trait Help { fn pow(&self, other: &Self) -> Self; fn rem(&self, other: &Self) -> Self; fn sqrt(&self) -> Self; } impl Help for i128 { fn pow(&self, other: &Self) -> Self { i128::pow(*self, (*other).try_into().expect("please no")) } fn rem(&self, other: &Self) -> Self { self.rem_euclid(*other) } fn sqrt(&self) -> Self { self.isqrt() } } impl Help for f64 { fn pow(&self, other: &Self) -> Self { self.powf(*other) } fn rem(&self, other: &Self) -> Self { self.rem_euclid(*other) } fn sqrt(&self) -> Self { f64::sqrt(*self) } } match x { Self::Add => concrete_ab!(+), Self::Sub => concrete_ab!(-), Self::Mul => concrete_ab!(*), 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::Or => number_ab!(|a, b| a | b), Self::Xor => number_ab!(|a, b| a ^ b), Self::Lt => concrete_ab!(<), Self::Gt => concrete_ab!(>), Self::Le => concrete_ab!(<=), Self::Eq => concrete_ab!(==), Self::Ne => concrete_ab!(!=), Self::Ge => concrete_ab!(>=), Self::Not => unary_num!(!), Self::Neg => unary!(-), Self::Sqrt => unary!(Help::sqrt), Self::Array(Some(x)) => { 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)) } Self::Array(None) => { let drained = Array::of(span, stack.drain(..))?; stack.push(Val::Array(drained).spun(span)); } Self::Dup => { let x = pop!().clone(); stack.push(x.clone()); stack.push(x); } 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(λ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(λ, n) => { let λargs = λ.argc(); 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), )); }; if a.len() != m.len() { return Err(Error { name: "argument length mismatch".to_string(), message: "for this function" .to_string() .spun(span), labels: vec![], notes: vec![], } .label("first argument".spun(a.span)) .label("second argument".spun(mask.span))); } stack.push( Val::Array(Array::new_unchecked( 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))); exec_lambda(λ, &mut Context::inherits(c), &mut a)?; stack.extend(a.drain(..)); } Self::Index => { let index = pop!().assert_array(span)?.assert_int(span)?; let array = pop!().assert_array(span)?; let out = each!( array.inner, |x| index .iter() .map(|y| x.get(normalize_index(*y, x.len())).cloned().ok_or_else(|| { Error { name: format!( "index ({y}) out of bounds for arra of length {}", x.len() ), message: "here".to_string().spun(span), ..Default::default() } .label("index from".spun(index.span)) .label("array from".spun(array.span)) })) .collect::>>().map(Array::from).map(Val::Array), Vec<_> => Result )?; stack.push(out.spun(span)); } Self::Open => { let x = pop!().assert_utf8(span)?; 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()) })? .into_iter() .map(|x| x as i128) .collect(), )) .spun(x.span), ); } // like mask but separating Self::Group => { let elem = pop!().assert_array(span)?.assert_int(span)?; let array = pop!().assert_array(span)?; if elem.len() != array.len() { return Err(Error { name: "argument length mismatch".to_string(), message: "for this function" .to_string() .spun(span), labels: vec![], notes: vec![], } .label("first argument".spun(elem.span)) .label("second argument".spun(array.span))); } stack.push( Val::Array(each!(array.inner, |a| { let mut chunked = Vec::with_capacity(32); let mut chunk = Vec::with_capacity(32); for (e, x) in elem.iter().copied().zip(a) { if e == 1 { chunk.push(x); } else if !chunk.is_empty() { chunked.push(Array::from(take(&mut chunk))); } } if !chunk.is_empty() { chunked.push(Array::from(take(&mut chunk))); } Array::Array(chunked) }, Vec<_> => Array)) .spun(span), ); } 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) }), ..Default::default() }); } let x = pop!().assert_array(span)?; let s = Stack::of( stack.take(λ.argc().input.saturating_sub(1)), ); stack.push( Val::Array(Array::new( span, x.iter() .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") }, ) }) .collect::>>()?, )?) .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); assert!(λ.argc().input >= 2); if λ.argc().input == 2 { stack.push( 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) })? .unwrap() .spun(span), ); } // vec![1, 2].iter().reduce(|x, y| {}); // if λ.argc() != } Self::Debug => { println!("stack: {:?} @ {span}", stack); } Self::Fold(λ) => { let a = pop!().assert_array(span)?; assert!(λ.argc().input >= 2); let input = λ.argc().input - 1; assert!(λ.argc().output == input); let accumulator = stack.take(input).collect::>(); 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 = pop!(); 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::(), ) .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), ); } Self::Windows => { let size = pop!().assert_int(span)?; let array = pop!().assert_array(span)?; stack.push(array.map(|x| { Val::Array(x.windows(size.inner.try_into().unwrap())) })); } Self::Matches => { let a = pop!().assert_array(span)?; let b = pop!().assert_array(span)?; stack.push(Val::Int((a == b) as i128).spun(span)); } Self::Python(x) => { let input = pop!() .assert_utf8(span)? .try_map(|x, _| { let mut x = x.into_bytes(); x.push(0); CString::from_vec_with_nul(x) }) .map_err(|_| Error::lazy(span, "nooo has nul"))?; python::exec(span, input, stack, x, c)?; } Self::In => { let elem = pop!().assert_array(span)?; let item = pop!(); stack.push( Val::Int(elem.iter().find(|x| *x == *item).is_some() as i128) .spun(span), ); } _ => (), } Ok(()) } } fn annotate<'a, T>(f: impl FnOnce(&T) -> T) -> impl FnOnce(&T) -> T { f } fn annote<'a, T, U>(f: impl FnOnce(T) -> U) -> impl FnOnce(T) -> U { f }