Diffstat (limited to 'src/exec.rs')
-rw-r--r--src/exec.rs737
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(())