use std::{ collections::HashMap, rc::Rc, hash::Hash, fmt::{Display, Debug}, ops::{Add, Neg, Not, Sub, Div, Mul, BitOr, BitAnd, BitXor, Shl, Shr}, cmp::Ordering, cell::RefCell, fs::File }; use crate::iter; use num_complex::Complex64; use num_rational::Rational64; use regex::Regex; use crate::{ast::{Expr, BinaryOp, UnaryOp}, chunk::Function, Result, gc::Gc}; pub type InlineList = Vec; pub type InlineMatrix = (usize, usize, Vec); pub type InlineTable = Vec<(Expr, Expr)>; #[derive(Debug)] pub struct Error(String); impl Display for self::Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl std::error::Error for self::Error {} macro_rules! error { ($($arg:tt)*) => { Err(self::Error(format!($($arg)*)).into()) }; } impl From<&str> for Value { fn from(value: &str) -> Self { Value::String(value.into()) } } impl Debug for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use Value as V; match self { V::Nil => write!(f, "[Nil]"), V::Bool(b) => write!(f, "[Bool {b}]"), V::Int(i) => write!(f, "[Int {i}]"), V::Float(vf) => write!(f, "[Float {vf}]"), V::Ratio(r) => write!(f, "[Ratio {r}]"), V::Complex(c) => write!(f, "[Complex {c}]"), V::Regex(r) => write!(f, "[Regex /{r}/]"), V::String(s) => write!(f, "[String '{s}']"), V::List(l) => write!(f, "[List {}]", l.len()), V::Matrix(m) => write!(f, "[Matirx {}x{}]", m.domain, m.codomain), V::Table(t) => write!(f, "[Table {}]", t.0.len()), V::Function(vf) => write!(f, "[Function {}]", vf.name), V::Range(r) => write!(f, "[Range {:?}..{:?}]", r.0, r.1), V::Iter(_) => write!(f, "[Iterator]"), V::Error(_) => write!(f, "[Error]"), V::File(_) => write!(f, "[File]"), } } } impl Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use Value as V; let red; let green; let yellow; let blue; let pink; let cyan; let clear; if f.alternate() { red = "\x1b[31m"; green = "\x1b[32m"; yellow = "\x1b[33m"; blue = "\x1b[34m"; pink = "\x1b[35m"; cyan = "\x1b[36m"; clear = "\x1b[0m"; } else { red = ""; green = ""; yellow = ""; blue = ""; pink = ""; cyan = ""; clear = ""; } match self { V::Nil => {write!(f, "{blue}nil{clear}")?;}, V::Bool(b) => {write!(f, "{yellow}{b}{clear}")?;}, V::Int(i) => {write!(f, "{yellow}{i}{clear}")?;}, V::Float(l) => {write!(f, "{yellow}{l}{clear}")?;}, V::Ratio(r) => {write!(f, "{yellow}{r}{clear}")?;}, V::Complex(c) => {write!(f, "{yellow}{c}{clear}")?;}, V::Regex(r) => {write!(f, "/{red}{r}{clear}/")?;}, V::String(s) => { if f.alternate() { write!(f, "{green}'{s}'{clear}")?; } else { write!(f, "{s}")?; } } V::List(l) => { write!(f, "[")?; for (i, el) in l.iter().enumerate() { if i != 0 { write!(f, " ")?; } if f.alternate() { write!(f, "{el:#}")?; } else { write!(f, "{el}")?; } } write!(f, "]")?; }, V::Matrix(m) => { if f.alternate() { write!(f, "{m:#}")?; } else { write!(f, "{m}")?; } }, V::Table(t) => { write!(f, "{{")?; for (i, (key, val)) in t.0.iter().enumerate() { if i != 0 { write!(f, ", ")?; } if f.alternate() { write!(f, "{key:#} = {val:#}")?; } else { write!(f, "{key} = {val}")?; } } write!(f, "}}")?; }, V::Function(fun) => { use crate::chunk::InnerFunction as F; match fun.fun { F::Compiled(_) => write!(f, "{cyan}[Function {}]{clear}", fun.name)?, F::Native(_) => write!(f, "{cyan}[Builtin {}]{clear}", fun.name)?, }; }, V::Range(r) => { if f.alternate() { write!(f, "{:#}..{:#}", r.0, r.1)?; } else { write!(f, "{}..{}", r.0, r.1)?; } } V::Iter(_) => {write!(f, "{pink}[Iterator]{clear}")?;}, V::File(_) => {write!(f, "{pink}[File]{clear}")?;}, V::Error(e) => {write!(f, "{red}{e}{clear}")?;}, }; Ok(()) } } impl Value { pub fn can_hash(&self) -> Result<()> { use Value::*; match self { Nil => {}, Bool(_) => {}, Int(_) => {}, Ratio(_) => {}, Regex(_) => {}, String(_) => {} List(l) => { for val in l.iter() { val.can_hash()?; } } Matrix(m) => { for val in m.values.iter() { val.can_hash()?; } }, _ => return error!("cannot hash {self:?}") } Ok(()) } pub fn is_zero(&self) -> bool { use Value as V; match self { V::Int(i) => *i == 0, V::Float(f) => *f == 0.0 || *f == -0.0, V::Ratio(r) => *r.numer() == 0, _ => false, } } } impl Value { pub fn val_cmp(&self, other: &Self) -> Result { self.partial_cmp(other) .map_or_else(|| error!("cannot compare: {self:?} and {other:?}"), Ok) } fn index_single(&self, index: &Value) -> Result { use Value as V; match (self, index) { (V::Table(t), index) => { Ok(t.get(index)?.unwrap_or(&Value::Nil).clone()) }, (V::List(l), V::Int(i)) => { if *i < 0 || *i as usize >= l.len() { return error!("{i} out of bounds for {self:?}") } Ok(l[*i as usize].clone()) }, (V::Matrix(m), V::Int(i)) => { if *i < 0 || *i as usize >= m.values.len() { return error!("{i} out of bounds for {self:?}") } Ok(m.values[*i as usize].clone()) }, _ => return error!("{index:?} cant index {self:?}") } } fn index_multiple(&self, indexes: &Vec) -> Result { use Value as V; match self { V::List(..) => { let mut ret = Vec::new(); for index in indexes { let res = self.index_single(index)?; ret.push(res); } Ok(V::List(ret.into())) } V::Table(..) => { let mut ret = ValueMap::new(); for index in indexes { let res = self.index_single(index)?; ret.insert(index.clone(), res)?; } Ok(V::Table(ret.into())) } V::Matrix(m) => { let err = || error!("{self:?} can be index by [Int] or [Int;Int]"); if indexes.len() != 2 { return err() } let lhs = indexes[0].clone(); let rhs = indexes[1].clone(); match (lhs, rhs) { (V::Nil, V::Nil) => { Ok(V::Matrix(m.clone_inside())) }, (V::Int(row), V::Nil) => { let Some((_, row)) = m.rows().enumerate().filter(|(idx, _)| *idx as i64 == row).next() else { return err(); }; let row: Vec = row.into_iter().map(|e| e.clone()).collect(); Ok(V::Matrix(Matrix::new(row.len(), 1, row).into())) }, (V::Nil, V::Int(col)) => { let Some((_, col)) = m.cols().enumerate().filter(|(idx, _)| *idx as i64 == col).next() else { return err(); }; let col: Vec = col.into_iter().map(|e| e.clone()).collect(); Ok(V::Matrix(Matrix::new(1, col.len(), col).into())) }, (V::Int(row), V::Int(col)) => { if row < 0 || col < 0 { return err(); } m.get(row as usize, col as usize) } _ => return err() } } _ => return error!("cannot index {self:?}") } } pub fn index(&self, index: &Vec) -> Result { if index.len() == 0 { Ok(self.clone_inside()) } else if index.len() == 1 { self.index_single(&index[0]) } else { self.index_multiple(index) } } fn store_index_single(&mut self, index: &Value, store: Value) -> Result<()> { use Value as V; let err = format!("{self:?}"); match (self, index) { (V::Table(t), index) => { t.insert(index.clone(), store) }, (V::List(l), V::Int(i)) => { if *i < 0 || *i as usize >= l.len() { return error!("{i} out of bounds for {err}") } l[*i as usize] = store; Ok(()) }, (V::Matrix(m), V::Int(i)) => { if *i < 0 || *i as usize >= m.values.len() { return error!("{i} out of bounds for {err}") } m.values[*i as usize] = store; Ok(()) }, _ => return error!("{index:?} cant index {err}") } } fn store_index_multiple(&mut self, indexes: &Vec, store: Value) -> Result<()> { use Value as V; match self { V::List(..) => { for index in indexes { self.store_index_single(index, store.clone())?; } Ok(()) } V::Table(..) => { for index in indexes { self.store_index_single(index, store.clone())?; } Ok(()) } _ => return error!("cannot index {self:?}") } } pub fn store_index(&mut self, index: &Vec, store: Value) -> Result<()> { if index.len() == 0 { Ok(()) } else if index.len() == 1 { self.store_index_single(&index[0], store) } else { self.store_index_multiple(index, store) } } pub fn store_field_access(&mut self, ident: &str, val: Value) -> Result<()> { use Value as V; match self { V::Table(t) => { let key = V::String(Rc::from(ident)); Ok(t.insert(key, val)?) }, _ => return error!("cannot field access assign {self:?}") } } pub fn field_access(&self, ident: &str) -> Result { use Value as V; match self { V::Table(t) => { let key = V::String(Rc::from(ident)); Ok(t.get(&key)?.unwrap_or(&V::Nil).clone()) }, _ => return error!("cannot field access {self:?}") } } pub fn binary_op(op: BinaryOp, lhs: Value, rhs: Value) -> Result { use BinaryOp::*; match op { Add => lhs + rhs, Subtract => lhs - rhs, Multiply => lhs * rhs, Divide => lhs / rhs, Modulo => lhs.modulo(rhs), Power => lhs.pow(rhs), BitwiseAnd => lhs & rhs, BitwiseOr => lhs | rhs, BitwiseXor => lhs ^ rhs, BitwiseShiftLeft => lhs << rhs, BitwiseShiftRight => lhs >> rhs, Equals => Ok(Self::Bool(lhs == rhs)), NotEquals => Ok(Self::Bool(lhs != rhs)), GreaterEquals => Ok(Self::Bool(lhs >= rhs)), LessEquals => Ok(Self::Bool(lhs <= rhs)), GreaterThan => Ok(Self::Bool(lhs > rhs)), LessThan => Ok(Self::Bool(lhs < rhs)), Range | RangeEq => { let Value::Int(lhs) = lhs else { return error!("range can only take [Int]'s") }; let Value::Int(rhs) = rhs else { return error!("range can only take [Int]'s") }; Ok(Self::Range(Rc::new((lhs, rhs, op == RangeEq)))) }, } } pub fn unary_op(op: UnaryOp, val: Value) -> Value { use UnaryOp::*; match op { Negate => -val, Not => Self::Bool(!val), } } } impl Neg for Value { type Output = Value; fn neg(self) -> Self::Output { use Value::*; match self { Bool(b) => Bool(!b), Int(i) => Int(-i), Float(f) => Float(-f), Ratio(r) => Ratio(-r), Complex(c) => Complex(-c), _ => return Float(f64::NAN) } } } impl Not for Value { type Output = bool; fn not(self) -> Self::Output { use Value as V; match self { V::Nil => true, V::Bool(b) => !b, V::Int(i) => i == 0, V::Float(f) => f == 0.0, V::Ratio(r) => *(r.numer()) == 0 || *(r.denom()) == 0, V::Complex(c) => !c.is_normal(), V::Regex(_) => false, V::List(_) => false, V::Matrix(_) => false, V::Table(_) => false, V::String(s) => s.as_ref() == "", V::Function(_) => false, V::Iter(_) => false, V::Range(_) => false, V::File(_) => false, V::Error(_) => false, } } } impl Value { pub fn into_iter_fn(self) -> Result> { let Value::Iter(iter) = self.into_iter()? else { return error!("bypassed iter check") }; Ok(iter) } pub fn into_iter(self) -> Result { use Value as V; Ok(match self { V::Iter(..) => self, V::List(l) => { let iter = RefCell::new(l.into_inner().into_iter()); iter!(move |_,_| { match iter.borrow_mut().next() { Some(v) => Ok(v), None => Ok(V::Nil), } }) }, V::Range(r) => { let r = (*r).clone(); let lhs = RefCell::new(r.0); let rhs = r.1; iter!(move |_,_| { let val = *lhs.borrow(); let next = *lhs.borrow() + 1; if (!r.2 && *lhs.borrow() < rhs) || (r.2 && *lhs.borrow() <= rhs) { *lhs.borrow_mut() = next; return Ok(Value::Int(val)) } Ok(Value::Nil) }) }, V::Function(f) => { if f.arity > 0 || f.variadic { return error!("iterator functions cannot be varadic or take arguments") } V::Iter(f) }, val => return error!("cannot turn {val:?} into an iterator") }) } } fn dot(lhs: Vec<&Value>, rhs: Vec<&Value>) -> Result { let len = lhs.len(); let mut res = Value::Int(0); for i in 0..len { let val = (lhs[i].clone() * rhs[i].clone())?; res = (res + val)?; } Ok(res) }