Diffstat (limited to 'src/exec.rs')
| -rw-r--r-- | src/exec.rs | 737 |
1 files changed, 509 insertions, 228 deletions
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(()) |