Diffstat (limited to 'src/exec.rs')
| -rw-r--r-- | src/exec.rs | 131 |
1 files changed, 111 insertions, 20 deletions
diff --git a/src/exec.rs b/src/exec.rs index 1627082..80ab7fb 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -5,6 +5,8 @@ use crate::parser::{ util::Spanner, }; use chumsky::span::{SimpleSpan, Span as _}; +use itertools::Itertools; +use std::mem::take; use std::{ collections::HashMap, fmt::Display, @@ -34,7 +36,7 @@ impl Argc { } } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum Array { Array(Vec<Array>), Int(Vec<i128>), @@ -48,6 +50,12 @@ impl Array { Array::Float(_) => "float", } } + 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))), + }) + } } macro_rules! each { @@ -207,7 +215,7 @@ impl Array { } } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum Val<'s> { Array(Array), Lambda(Λ<'s>), @@ -326,10 +334,9 @@ impl<'s, 'v> Context<'s, 'v> { } } pub fn exec(x: Spanned<Λ<'_>>, code: &str) { - crate::ui::display_execution( - exec_lambda(x, &mut Context::default(), &mut Stack::new()), - code, - ); + 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 { @@ -446,6 +453,10 @@ fn x() { ); 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<Argc> for Argc { @@ -466,15 +477,19 @@ impl Add<Argc> for Argc { fn size_fn<'s>(f: &Function<'s>) -> Argc { use Function::*; match f { - Index | Add | Mul | Div | Xor | Mod | Pow | Eq | Ne | BitAnd | Or | Ge | Le | Lt | Gt => { - Argc::takes(2).into(1) - } + 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), 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), Flip => Argc::takes(2).into(2), Dup => Argc::takes(1).into(2), Zap => Argc::takes(1).into(0), - Mask => Argc::takes(2).into(1), + Array(None) => { + Argc::takes(5 /*all */).into(1) + } + Array(Some(NumberΛ::Number(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) @@ -556,7 +571,6 @@ fn exec_lambda<'s>( } } } - println!("{stack:?}"); Ok(()) } @@ -775,6 +789,8 @@ impl<'s> Function<'s> { 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!(-), @@ -810,8 +826,8 @@ impl<'s> Function<'s> { Self::Flip => { let x = pop!(); let y = pop!(); - stack.push(y); stack.push(x); + stack.push(y); } Self::And(x, y) => { let xargs = x.argc(); @@ -830,13 +846,13 @@ impl<'s> Function<'s> { stack.extend(x); stack.extend(y); } - Self::Both(x) => { - let xargs = x.argc(); + Self::Both(λ) => { + let xargs = λ.argc(); let mut a = Stack::of(stack.take(xargs.input)); - exec_lambda(x.clone(), &mut Context::inherits(c), &mut a)?; + exec_lambda(λ.clone(), &mut Context::inherits(c), &mut a)?; let mut b = Stack::of(stack.take(xargs.input)); - exec_lambda(x, &mut Context::inherits(c), &mut b)?; + exec_lambda(λ, &mut Context::inherits(c), &mut b)?; stack.extend(b.take(xargs.output)); stack.extend(a.take(xargs.output)); @@ -871,10 +887,7 @@ impl<'s> Function<'s> { stack.extend(a.drain(..)); } Self::Index => { - let index = pop!().assert_array(span)?.try_map(|x, s| match x { - Array::Int(x) => Ok(x), - x => Err(Error::ef(span, "array[int]", x.ty().spun(s))), - })?; + let index = pop!().assert_array(span)?.assert_int(span)?; let array = pop!().assert_array(span)?; let out = each!( array.inner, @@ -920,6 +933,84 @@ impl<'s> Function<'s> { .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::<Result<Vec<_>>>()?, + )?) + .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() != + } _ => (), } Ok(()) |