use core::fmt;
use std::{iter::Zip, slice::IterMut, vec::IntoIter};
use crate::callable::core::Builtin;
#[derive(Debug, Clone)]
pub enum Expr {
Null,
NA,
Inf,
More,
Continue,
Break,
Ellipsis(Option<String>),
Missing,
Bool(bool),
Number(f64),
Integer(i32),
String(String),
Symbol(String),
List(ExprList),
Function(ExprList, Box<Expr>),
Call(Box<Expr>, ExprList),
Primitive(Box<dyn Builtin>),
}
impl PartialEq for Expr {
fn eq(&self, other: &Self) -> bool {
use Expr::*;
match (self, other) {
(Null, Null) => true,
(NA, NA) => true,
(Inf, Inf) => true,
(Continue, Continue) => true,
(Break, Break) => true,
(Ellipsis(l), Ellipsis(r)) => l == r,
(Missing, Missing) => true,
(Bool(l), Bool(r)) => l == r,
(Number(l), Number(r)) => l == r,
(Integer(l), Integer(r)) => l == r,
(String(l), String(r)) => l == r,
(Symbol(l), Symbol(r)) => l == r,
(List(l), List(r)) => l == r,
(Primitive(l), Primitive(r)) => l == r,
(Function(largs, lbody), Function(rargs, rbody)) => largs == rargs && lbody == rbody,
(Call(lwhat, largs), Call(rwhat, rargs)) => lwhat == rwhat && largs == rargs,
_ => false,
}
}
}
impl Expr {
pub fn as_primitive<T>(x: T) -> Self
where
T: Builtin + 'static,
{
Self::Primitive(Box::new(x))
}
pub fn new_primitive_call<T>(x: T, args: ExprList) -> Self
where
T: Builtin + 'static,
{
let p = Self::as_primitive(x);
Self::Call(Box::new(p), args)
}
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expr::Null => write!(f, "NULL"),
Expr::Missing => write!(f, ""),
Expr::Break => write!(f, "break"),
Expr::Continue => write!(f, "continue"),
Expr::Bool(true) => write!(f, "TRUE"),
Expr::Bool(false) => write!(f, "FALSE"),
Expr::Number(x) => write!(f, "{}", x),
Expr::Integer(x) => write!(f, "{}L", x),
Expr::String(x) => write!(f, "\"{}\"", x),
Expr::Symbol(x) => write!(f, "{}", x),
Expr::List(x) => write!(f, "{}", x),
Expr::Ellipsis(None) => write!(f, "..."),
Expr::Ellipsis(Some(s)) => write!(f, "..{s}"),
Expr::Call(what, args) => match &**what {
Expr::Primitive(p) => write!(f, "{}", p.rfmt_call(args)),
Expr::String(s) | Expr::Symbol(s) => write!(f, "{}({})", s, args),
rexpr => write!(f, "{}({})", rexpr, args),
},
Expr::Function(head, body) => write!(f, "function({}) {}", head, body),
Expr::Primitive(p) => write!(f, "Primitive(\"{}\")", p.rfmt()),
x => write!(f, "{:?}", x),
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ExprList {
pub keys: Vec<Option<String>>, pub values: Vec<Expr>,
}
impl ExprList {
pub fn push_named(&mut self, key: Option<String>, value: Expr) {
self.keys.push(key);
self.values.push(value);
}
}
impl fmt::Display for ExprList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let pairs: Vec<String> = self
.values
.iter()
.enumerate()
.map(|(i, v)| match (&self.keys[i], v) {
(Some(k), Expr::Missing) => k.to_string(),
(Some(k), _) => format!("{} = {}", k, v),
(None, v) => format!("{}", v),
})
.collect();
write!(f, "{}", pairs.join(", "))
}
}
impl IntoIterator for ExprList {
type Item = (Option<String>, Expr);
type IntoIter = <Zip<IntoIter<Option<String>>, IntoIter<Expr>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.keys.into_iter().zip(self.values)
}
}
impl<'a> IntoIterator for &'a mut ExprList {
type Item = (&'a mut Option<String>, &'a mut Expr);
type IntoIter = <Zip<IterMut<'a, Option<String>>, IterMut<'a, Expr>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.keys.iter_mut().zip(self.values.iter_mut())
}
}
impl FromIterator<(Option<String>, Expr)> for ExprList {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = (Option<String>, Expr)>,
{
let (keys, values) = iter.into_iter().unzip();
ExprList { keys, values }
}
}
impl FromIterator<Expr> for ExprList {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Expr>,
{
let values: Vec<Expr> = iter.into_iter().collect();
ExprList { keys: vec![None; values.len()], values }
}
}
impl ExprList {
pub fn new() -> ExprList {
ExprList { ..Default::default() }
}
pub fn get_named(&self, key: &String) -> Option<Expr> {
let first_name_index = self.keys.iter().rev().position(|i| i.as_ref() == Some(key));
match first_name_index {
Some(index) => self.values.get(index).cloned(),
_ => None,
}
}
pub fn get(&self, index: usize) -> Option<Expr> {
if index < self.values.len() {
Some(self.values[index].clone())
} else {
None
}
}
pub fn pop(&mut self) -> Option<(Option<String>, Expr)> {
if let Some(k) = self.keys.pop() {
if let Some(v) = self.values.pop() {
return Some((k, v));
}
}
None
}
pub fn push(&mut self, pair: (Option<String>, Expr)) {
let (key, value) = pair;
self.keys.push(key);
self.values.push(value);
}
pub fn append(&mut self, mut other: Self) -> &mut ExprList {
self.keys.append(&mut other.keys);
self.values.append(&mut other.values);
self
}
pub fn position_ellipsis(&self) -> Option<usize> {
self.values
.iter()
.position(|i| matches!(i, Expr::Ellipsis(_)))
}
pub fn pop_trailing(&mut self) -> ExprList {
if let Some(index) = self.position_ellipsis() {
let keys_trailing = self.keys.drain(index..self.keys.len()).collect();
let vals_trailing = self.values.drain(index..self.values.len()).collect();
ExprList { keys: keys_trailing, values: vals_trailing }
} else {
ExprList::new()
}
}
pub fn remove_named(&mut self, key: &str) -> Option<(Option<String>, Expr)> {
let first_named_index = self.keys.iter().position(|i| i == &Some(key.to_string()));
if let Some(index) = first_named_index {
Some((self.keys.remove(index), self.values.remove(index)))
} else {
None
}
}
pub fn remove(&mut self, index: usize) -> Option<(Option<String>, Expr)> {
if index < self.keys.len() {
Some((self.keys.remove(index), self.values.remove(index)))
} else {
None
}
}
pub fn insert_named(&mut self, key: String, value: Expr) -> usize {
if let Some(index) = self.keys.iter().position(|i| i == &Some(key.clone())) {
self.values[index] = value;
index
} else {
self.keys.push(Some(key.to_string()));
self.values.push(value);
self.values.len()
}
}
pub fn insert(&mut self, index: usize, value: Expr) -> usize {
if index < self.values.len() {
self.keys.insert(index, None);
self.values.insert(index, value);
index
} else {
let n = index - self.values.len();
self.keys.extend(vec![None; n + 1]);
self.values.extend(vec![Expr::Null; n]);
self.values.push(value);
index
}
}
pub fn binary_args(self) -> ((Option<String>, Expr), (Option<String>, Expr)) {
let mut argstream = self.into_iter();
let Some(lhs) = argstream.next() else {
unimplemented!()
};
let Some(rhs) = argstream.next() else {
unimplemented!()
};
(lhs, rhs)
}
pub fn unnamed_binary_args(self) -> (Expr, Expr) {
let mut argstream = self.into_iter();
let Some((_, lhs)) = argstream.next() else {
unimplemented!()
};
let Some((_, rhs)) = argstream.next() else {
unimplemented!()
};
(lhs, rhs)
}
pub fn unnamed_unary_arg(self) -> Expr {
let mut argstream = self.into_iter();
let Some((_, lhs)) = argstream.next() else {
unimplemented!()
};
lhs
}
pub fn as_formals(self) -> ExprList {
self.into_iter()
.map(|(k, v)| match (k, v) {
(None, Expr::Symbol(param)) => (Some(param.clone()), Expr::Missing),
other => other,
})
.collect()
}
pub fn len(&self) -> usize {
self.values.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl From<Vec<Expr>> for ExprList {
fn from(values: Vec<Expr>) -> Self {
ExprList { keys: vec![None; values.len()], values }
}
}
impl From<Expr> for ExprList {
fn from(value: Expr) -> Self {
ExprList { keys: vec![None], values: vec![value] }
}
}
impl From<Vec<(Option<String>, Expr)>> for ExprList {
fn from(values: Vec<(Option<String>, Expr)>) -> Self {
ExprList::from_iter(values)
}
}