2022-09-15 04:01:57 +00:00
|
|
|
use std::{rc::Rc, collections::HashMap, ops::*, fmt, cmp::Ordering, cell::RefCell, hash::Hash};
|
2022-09-06 13:52:29 +00:00
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
use num_traits::{Zero, ToPrimitive, Pow};
|
2022-09-07 20:11:51 +00:00
|
|
|
|
2022-09-17 03:06:49 +00:00
|
|
|
use crate::{RuntimeError, eval::{eval_stmt, Unwind, eval_expr}, expr::Stmt, env::{EnvRef, Environment}};
|
2022-09-09 20:08:40 +00:00
|
|
|
|
|
|
|
pub type Rational = num_rational::Ratio<i64>;
|
|
|
|
pub type Complex = num_complex::Complex64;
|
2022-09-17 15:17:22 +00:00
|
|
|
pub type ClosureData = Rc<RefCell<Vec<Value>>>;
|
|
|
|
pub type ClosureIterData = Rc<RefCell<Vec<CIterator>>>;
|
2022-09-09 20:08:40 +00:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
2022-09-14 15:16:53 +00:00
|
|
|
pub enum Func {
|
|
|
|
Func {
|
|
|
|
name: Option<Rc<str>>,
|
|
|
|
args: Vec<Rc<str>>,
|
|
|
|
env: EnvRef,
|
2022-09-17 15:17:22 +00:00
|
|
|
func: Box<Stmt>,
|
2022-09-14 15:16:53 +00:00
|
|
|
},
|
|
|
|
Builtin {
|
|
|
|
name: Rc<str>,
|
2022-09-16 20:05:28 +00:00
|
|
|
func: fn(Vec<Value>) -> Result<Value, RuntimeError>,
|
|
|
|
arg_count: usize,
|
|
|
|
},
|
|
|
|
BuiltinClosure {
|
2022-09-17 15:17:22 +00:00
|
|
|
func: fn(Vec<Value>, ClosureData, ClosureIterData) -> Result<Value, RuntimeError>,
|
|
|
|
data: ClosureData,
|
|
|
|
iter_data: ClosureIterData,
|
2022-09-16 20:05:28 +00:00
|
|
|
arg_count: usize,
|
2022-09-17 14:54:56 +00:00
|
|
|
},
|
|
|
|
Partial {
|
|
|
|
inner: Box<Func>,
|
|
|
|
filled_args: Vec<Value>,
|
2022-09-14 15:16:53 +00:00
|
|
|
}
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2022-09-14 15:16:53 +00:00
|
|
|
impl fmt::Debug for Func {
|
2022-09-09 20:08:40 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2022-09-14 15:16:53 +00:00
|
|
|
match self {
|
|
|
|
Self::Func { name, args, .. }
|
|
|
|
=> f.debug_struct("Func::Func")
|
|
|
|
.field("name", name)
|
|
|
|
.field("args", args)
|
|
|
|
.finish_non_exhaustive(),
|
|
|
|
Self::Builtin { name, arg_count, .. }
|
|
|
|
=> f.debug_struct("Func::Builtin")
|
|
|
|
.field("name", name)
|
|
|
|
.field("arg_count", arg_count)
|
|
|
|
.finish_non_exhaustive(),
|
2022-09-16 20:05:28 +00:00
|
|
|
Self::BuiltinClosure { arg_count, data, .. }
|
|
|
|
=> f.debug_struct("Func::BuiltinClosure")
|
|
|
|
.field("arg_count", arg_count)
|
|
|
|
.field("data", data)
|
|
|
|
.finish_non_exhaustive(),
|
2022-09-17 14:54:56 +00:00
|
|
|
Self::Partial { inner, filled_args }
|
|
|
|
=> f.debug_struct("Func::Partial")
|
|
|
|
.field("inner", inner)
|
|
|
|
.field("filled_args", filled_args)
|
|
|
|
.finish(),
|
2022-09-14 15:16:53 +00:00
|
|
|
}
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
2022-09-14 15:16:53 +00:00
|
|
|
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2022-09-14 15:16:53 +00:00
|
|
|
impl Func {
|
|
|
|
pub fn arg_count(&self) -> usize {
|
|
|
|
match self {
|
|
|
|
Self::Builtin { arg_count, .. } => *arg_count,
|
2022-09-16 20:05:28 +00:00
|
|
|
Self::BuiltinClosure { arg_count, .. } => *arg_count,
|
|
|
|
Self::Func { args, .. } => args.len(),
|
2022-09-17 14:54:56 +00:00
|
|
|
Self::Partial { inner, filled_args } => inner.arg_count() - filled_args.len(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(&self) -> Option<&str> {
|
|
|
|
match self {
|
|
|
|
Self::Builtin { name, .. } => Some(name.as_ref()),
|
|
|
|
Self::BuiltinClosure { .. } => None,
|
|
|
|
Self::Func { name, .. } => name.as_ref().map(|s| s.as_ref()),
|
|
|
|
Self::Partial { inner, .. } => inner.name()
|
2022-09-14 15:16:53 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-13 17:31:29 +00:00
|
|
|
|
2022-09-17 14:54:56 +00:00
|
|
|
pub fn call(&self, mut arg_values: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-14 15:16:53 +00:00
|
|
|
match arg_values.len().cmp(&self.arg_count()) {
|
|
|
|
Ordering::Equal => match self {
|
|
|
|
Self::Builtin { func, .. }
|
2022-09-16 20:05:28 +00:00
|
|
|
=> func(arg_values),
|
|
|
|
Self::BuiltinClosure { func, data, iter_data, .. }
|
|
|
|
=> func(arg_values, data.clone(), iter_data.clone()),
|
|
|
|
Self::Func { args, func, env, .. } => {
|
2022-09-14 15:16:53 +00:00
|
|
|
let mut env = Environment::extend(env.clone());
|
|
|
|
for (k, v) in args.iter().zip(arg_values.iter()) {
|
|
|
|
env.declare(k.clone(), v.clone());
|
|
|
|
}
|
2022-09-17 15:17:22 +00:00
|
|
|
match func.as_ref() {
|
2022-09-16 20:05:28 +00:00
|
|
|
Stmt::Expr { expr } => eval_expr(expr, env.wrap()),
|
|
|
|
stmt => match eval_stmt(stmt, env.wrap()) {
|
|
|
|
Ok(()) => Ok(Value::Nil),
|
|
|
|
Err(Unwind::Return{ value, .. }) => Ok(value),
|
|
|
|
Err(e) => Err(e.as_error()),
|
|
|
|
}
|
|
|
|
|
2022-09-14 15:16:53 +00:00
|
|
|
}
|
2022-09-17 14:54:56 +00:00
|
|
|
},
|
|
|
|
Self::Partial { inner, filled_args } => {
|
|
|
|
let mut filled_args = filled_args.clone();
|
|
|
|
filled_args.append(&mut arg_values);
|
|
|
|
inner.call(filled_args)
|
2022-09-14 15:16:53 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-17 14:54:56 +00:00
|
|
|
Ordering::Less => {
|
|
|
|
Ok(Value::Func(Func::Partial { inner: Box::new(self.clone()), filled_args: arg_values }))
|
|
|
|
},
|
2022-09-16 20:05:28 +00:00
|
|
|
Ordering::Greater => Err(RuntimeError::new_incomplete(
|
|
|
|
format!("Too many arguments for function: expected {}, got {}", self.arg_count(), arg_values.len())
|
2022-09-14 15:16:53 +00:00
|
|
|
))
|
2022-09-13 17:31:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 04:01:57 +00:00
|
|
|
impl Hash for Func {
|
|
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
|
|
match self {
|
|
|
|
Self::Builtin { name, arg_count, func } => {
|
|
|
|
name.hash(state);
|
|
|
|
arg_count.hash(state);
|
|
|
|
func.hash(state);
|
|
|
|
},
|
|
|
|
Self::Func { name, args, .. } => {
|
|
|
|
name.hash(state);
|
|
|
|
args.hash(state);
|
2022-09-16 20:05:28 +00:00
|
|
|
},
|
|
|
|
Self::BuiltinClosure { arg_count, data, .. } => {
|
|
|
|
arg_count.hash(state);
|
|
|
|
data.borrow().hash(state);
|
2022-09-17 14:54:56 +00:00
|
|
|
},
|
|
|
|
Self::Partial { inner, filled_args } => {
|
|
|
|
filled_args.hash(state);
|
|
|
|
inner.hash(state);
|
2022-09-15 04:01:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
pub enum CIterator {
|
|
|
|
// precondition: value must be len()able
|
|
|
|
Indexable{ value: Value, idx: i64 },
|
|
|
|
Func(Func)
|
2022-09-14 15:16:53 +00:00
|
|
|
}
|
2022-09-13 17:31:29 +00:00
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
impl Iterator for CIterator {
|
|
|
|
type Item = Result<Value, RuntimeError>;
|
2022-09-14 15:16:53 +00:00
|
|
|
|
2022-09-13 17:31:29 +00:00
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2022-09-14 15:16:53 +00:00
|
|
|
match self {
|
2022-09-16 20:05:28 +00:00
|
|
|
Self::Indexable{ value, ref mut idx } => {
|
|
|
|
if *idx >= value.len().unwrap() as i64 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let result = value.index(&Value::Int(*idx)).unwrap();
|
|
|
|
*idx += 1;
|
|
|
|
Some(Ok(result))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Self::Func(f) => match f.call(vec![]) {
|
2022-09-14 15:16:53 +00:00
|
|
|
Ok(Value::Nil) => None,
|
2022-09-16 20:05:28 +00:00
|
|
|
x => Some(x)
|
2022-09-14 15:16:53 +00:00
|
|
|
},
|
2022-09-13 17:31:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-09 20:08:40 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct Data {
|
|
|
|
pub ty: usize,
|
|
|
|
// TODO user-defined data types
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct Type {
|
|
|
|
pub name: Rc<str>,
|
|
|
|
pub id: usize
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum Value {
|
|
|
|
Nil,
|
|
|
|
Type(usize),
|
|
|
|
Int(i64), Float(f64), Complex(Complex), Rational(Rational),
|
|
|
|
Bool(bool),
|
|
|
|
Char(char),
|
|
|
|
String(Rc<str>),
|
2022-09-15 04:01:57 +00:00
|
|
|
List(Rc<RefCell<Vec<Value>>>),
|
|
|
|
Map(Rc<RefCell<HashMap<Value,Value>>>),
|
2022-09-12 20:53:04 +00:00
|
|
|
Func(Func),
|
2022-09-09 20:08:40 +00:00
|
|
|
Data(Data),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Value {
|
|
|
|
pub fn truthy(&self) -> bool {
|
|
|
|
use Value::*;
|
|
|
|
match self {
|
|
|
|
Bool(false) | Nil | Int(0) => false,
|
|
|
|
Float(f) => *f != 0.0,
|
|
|
|
Complex(z) => !z.is_zero(),
|
|
|
|
Rational(r) => !r.is_zero(),
|
|
|
|
String(s) => !s.len() == 0,
|
2022-09-10 21:19:23 +00:00
|
|
|
List(l) => !l.borrow().len() == 0,
|
2022-09-15 04:01:57 +00:00
|
|
|
Map(m) => !m.borrow().len() == 0,
|
2022-09-16 20:05:28 +00:00
|
|
|
Char(c) => *c != '\0',
|
2022-09-09 20:08:40 +00:00
|
|
|
_ => true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-17 15:17:22 +00:00
|
|
|
pub fn iter(&self) -> Result<CIterator, String> {
|
2022-09-09 20:08:40 +00:00
|
|
|
match self {
|
2022-09-16 20:05:28 +00:00
|
|
|
Value::String(_) | Value::List(_)
|
|
|
|
=> Ok(CIterator::Indexable { value: self.clone(), idx: 0 }),
|
2022-09-13 17:31:29 +00:00
|
|
|
Value::Func(f) => {
|
2022-09-14 15:16:53 +00:00
|
|
|
if f.arg_count() == 0 {
|
2022-09-16 20:05:28 +00:00
|
|
|
Ok(CIterator::Func(f.clone()))
|
2022-09-13 17:31:29 +00:00
|
|
|
} else {
|
|
|
|
Err("Only zero-argument functions can be used as iterators".into())
|
|
|
|
}
|
|
|
|
},
|
2022-09-11 17:02:18 +00:00
|
|
|
v => Err(format!("{:?} is not iterable", v))
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-16 20:05:28 +00:00
|
|
|
pub fn call(&self, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
2022-09-14 15:16:53 +00:00
|
|
|
if let Value::Func(f) = self {
|
2022-09-16 20:05:28 +00:00
|
|
|
f.call(args)
|
2022-09-14 15:16:53 +00:00
|
|
|
} else {
|
2022-09-16 20:05:28 +00:00
|
|
|
Err(RuntimeError::new_incomplete("Cannot call"))
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn to_string(&self) -> Rc<str> {
|
|
|
|
match self {
|
|
|
|
Self::Nil => Rc::from("nil"),
|
|
|
|
Self::Bool(b) => Rc::from(b.to_string()),
|
|
|
|
Self::Int(n) => Rc::from(n.to_string()),
|
|
|
|
Self::Float(f) => Rc::from(f.to_string()),
|
|
|
|
Self::Rational(r) => Rc::from(r.to_string()),
|
|
|
|
Self::Complex(z) => Rc::from(z.to_string()),
|
|
|
|
Self::Char(c) => Rc::from(c.to_string()),
|
|
|
|
Self::String(s) => s.clone(),
|
|
|
|
Self::List(l) => Rc::from(format!("{:?}", l)), // TODO fix
|
|
|
|
Self::Map(m) => Rc::from(format!("{:?}", m)), // TODO fix
|
|
|
|
Self::Type(_) => todo!(),
|
2022-09-14 15:16:53 +00:00
|
|
|
Self::Func(Func::Builtin { name, func, .. }) => Rc::from(format!("<builtin fn {} at {:?}>", name, *func as *const ())),
|
2022-09-16 20:05:28 +00:00
|
|
|
Self::Func(Func::BuiltinClosure { func, .. }) => Rc::from(format!("<builtin anonymous fn at {:?}>", *func as *const ())),
|
2022-09-17 14:54:56 +00:00
|
|
|
Self::Func(f @ Func::Partial { .. }) => match f.name() {
|
|
|
|
Some(name) => Rc::from(format!("<partial of fn {}>", name)),
|
|
|
|
None => Rc::from("<partial of anonymous fn>"),
|
|
|
|
}
|
2022-09-14 15:16:53 +00:00
|
|
|
Self::Func(Func::Func { name, .. }) => match name {
|
2022-09-12 20:53:04 +00:00
|
|
|
Some(name) => Rc::from(format!("<fn {}>", name)),
|
|
|
|
None => Rc::from("<anonymous fn>"),
|
|
|
|
},
|
2022-09-09 20:08:40 +00:00
|
|
|
Self::Data(_) => todo!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn repr(&self) -> Rc<str> {
|
|
|
|
match self {
|
2022-09-17 03:06:49 +00:00
|
|
|
Self::Float(f) => Rc::from(format!("{:?}",f)),
|
|
|
|
Self::Rational(r) => Rc::from(r.numer().to_string() + "//" + &r.denom().to_string()),
|
2022-09-09 20:08:40 +00:00
|
|
|
Self::Char(c) => Rc::from(format!("'{}'", c)), // TODO escaping
|
|
|
|
Self::String(s) => Rc::from(format!("\"{}\"", s)), // TODO escaping
|
2022-09-10 21:19:23 +00:00
|
|
|
Self::List(l) => Rc::from(format!("{:?}", l.borrow())), // TODO fix
|
2022-09-09 20:08:40 +00:00
|
|
|
Self::Map(m) => Rc::from(format!("{:?}", m)), // TODO fix
|
2022-09-17 03:06:49 +00:00
|
|
|
_ => self.to_string(),
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-10 21:19:23 +00:00
|
|
|
|
|
|
|
pub fn index(&self, idx: &Value) -> Result<Value, String> {
|
|
|
|
match self {
|
|
|
|
Self::String(s) => match idx {
|
|
|
|
Value::Int(i) if *i >= 0 => s.chars().nth(*i as usize)
|
|
|
|
.ok_or_else(|| format!("String index {} out of bounds for length {}", i, s.chars().count()))
|
2022-09-11 17:02:18 +00:00
|
|
|
.map(Value::Char),
|
2022-09-10 21:19:23 +00:00
|
|
|
Value::Int(i) => Err(format!("String index {} cannot be negative", i)),
|
|
|
|
_ => Err(format!("Cannot index {:?} with {:?}", self, idx))
|
|
|
|
},
|
|
|
|
Self::List(l) => match idx {
|
|
|
|
Value::Int(i) if *i >= 0 => l.borrow().get(*i as usize)
|
|
|
|
.ok_or_else(|| format!("List index {} out of bounds for length {}", i, l.borrow().len()))
|
|
|
|
.map(|v| v.clone()),
|
|
|
|
Value::Int(i) => Err(format!("List index {} cannot be negative", i)),
|
|
|
|
_ => Err(format!("Cannot index {:?} with {:?}", self, idx))
|
|
|
|
}
|
2022-09-15 04:01:57 +00:00
|
|
|
Self::Map(m) => m.borrow().get(idx).cloned().ok_or_else(|| format!("Map does not contain key {:?}", idx)),
|
2022-09-10 21:19:23 +00:00
|
|
|
v => Err(format!("Cannot index into {:?}", v))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn assign_index(&self, idx: &Value, value: Value) -> Result<(), String> {
|
|
|
|
match self {
|
|
|
|
Self::List(l) => match idx {
|
|
|
|
Value::Int(i) if *i >= 0 && (*i as usize) < l.borrow().len() => {
|
|
|
|
l.borrow_mut()[*i as usize] = value;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
Value::Int(i) if *i >= 0 => Err(format!("List index {} out of bounds for length {}", i, l.borrow().len())),
|
|
|
|
Value::Int(i) => Err(format!("List index {} cannot be negative", i)),
|
|
|
|
_ => Err(format!("Cannot index {:?} with {:?}", self, idx))
|
|
|
|
}
|
2022-09-15 04:01:57 +00:00
|
|
|
Self::Map(m) => {
|
|
|
|
m.borrow_mut().insert(idx.clone(), value);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
v => Err(format!("Cannot assign to index in {:?}", v))
|
2022-09-10 21:19:23 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-16 20:05:28 +00:00
|
|
|
|
|
|
|
pub fn len(&self) -> Result<usize, String> {
|
|
|
|
match self {
|
|
|
|
Value::String(s) => Ok(s.len()),
|
|
|
|
Value::List(l) => Ok(l.borrow().len()),
|
|
|
|
Value::Map(m) => Ok(m.borrow().len()),
|
2022-09-17 15:17:22 +00:00
|
|
|
v => Err(format!("{:?} has no length", v))
|
2022-09-16 20:05:28 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-17 03:06:49 +00:00
|
|
|
|
|
|
|
pub fn fracdiv(&self, other: &Value) -> Result<Value, String> {
|
|
|
|
use Value::*;
|
|
|
|
match (self, other) {
|
|
|
|
(Int(_), Int(b)) if *b == 0 => Err("Integer division by zero".into()),
|
|
|
|
(Rational(_), Int(b)) if *b == 0 => Err("Rational division by zero".into()),
|
|
|
|
(Int(_), Rational(b)) if b.is_zero() => Err("Rational division by zero".into()),
|
|
|
|
(Rational(_), Rational(b)) if b.is_zero() => Err("Rational division by zero".into()),
|
|
|
|
(Int(a), Int(b)) => Ok(Value::from(crate::value::Rational::new(*a, *b))),
|
|
|
|
(Rational(a), Int(b)) => Ok(Value::from(a/b)),
|
|
|
|
(Int(a), Rational(b)) => Ok(Value::from(b.recip()*a)),
|
|
|
|
(Rational(a), Rational(b)) => Ok(Value::from(a/b)),
|
|
|
|
(x,y) => Err(format!("Unsupported operation 'fracdiv' between {:?} and {:?}", x, y))
|
|
|
|
}
|
|
|
|
}
|
2022-09-09 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2022-09-17 15:17:22 +00:00
|
|
|
#[allow(clippy::ptr_eq)] // provided fix does not work
|
2022-09-09 20:08:40 +00:00
|
|
|
impl PartialEq for Value {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
match (self, other) {
|
|
|
|
(Self::Nil, Self::Nil) => true,
|
|
|
|
(Self::Type(a), Self::Type(b)) => a == b,
|
|
|
|
|
|
|
|
(Self::Int(a), Self::Int(b)) => a == b,
|
|
|
|
(Self::Rational(a), Self::Int(b)) => *a == Rational::from(*b),
|
|
|
|
(Self::Int(a), Self::Rational(b)) => Rational::from(*a) == *b,
|
|
|
|
(Self::Rational(a), Self::Rational(b)) => a == b,
|
|
|
|
(Self::Float(a), Self::Int(b)) => *a == *b as f64,
|
|
|
|
(Self::Int(a), Self::Float(b)) => *a as f64 == *b,
|
|
|
|
(Self::Float(a), Self::Rational(b)) => *a == b.to_f64().unwrap(),
|
|
|
|
(Self::Rational(a), Self::Float(b)) => a.to_f64().unwrap() == *b,
|
|
|
|
(Self::Float(a), Self::Float(b)) => a == b,
|
|
|
|
|
|
|
|
(Self::Complex(a), Self::Int(b)) => *a == Complex::from(*b as f64),
|
|
|
|
(Self::Int(a), Self::Complex(b)) => Complex::from(*a as f64) == *b,
|
|
|
|
(Self::Complex(a), Self::Rational(b)) => *a == Complex::from(b.to_f64().unwrap()),
|
|
|
|
(Self::Rational(a), Self::Complex(b)) => Complex::from(a.to_f64().unwrap()) == *b,
|
|
|
|
(Self::Complex(a), Self::Float(b)) => *a == Complex::from(*b),
|
|
|
|
(Self::Float(a), Self::Complex(b)) => Complex::from(*a) == *b,
|
|
|
|
(Self::Complex(a), Self::Complex(b)) => a == b,
|
|
|
|
|
|
|
|
(Self::Bool(a), Self::Bool(b)) => a == b,
|
|
|
|
(Self::Char(a), Self::Char(b)) => a == b,
|
|
|
|
(Self::String(a), Self::String(b)) => a == b,
|
|
|
|
(Self::List(a), Self::List(b)) => a == b,
|
2022-09-15 04:01:57 +00:00
|
|
|
(Self::Map(a), Self::Map(b)) => {
|
|
|
|
// prevent double borrow
|
|
|
|
if a.as_ref().as_ptr() == b.as_ref().as_ptr() { return true }
|
|
|
|
if a.borrow().len() != b.borrow().len() { return false }
|
|
|
|
for (k, v1) in a.borrow().iter() {
|
|
|
|
let bb = b.borrow();
|
|
|
|
let v2 = bb.get(k);
|
|
|
|
if v2 != Some(v1) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2022-09-17 15:17:22 +00:00
|
|
|
true
|
2022-09-15 04:01:57 +00:00
|
|
|
}
|
2022-09-14 15:16:53 +00:00
|
|
|
(Self::Func(f1), Self::Func(f2)) => match (f1, f2) {
|
|
|
|
(
|
|
|
|
Func::Builtin { func: f1, arg_count: c1, .. },
|
|
|
|
Func::Builtin { func: f2, arg_count: c2, .. }
|
|
|
|
) => (*f1 as *const ()) == (*f2 as *const ()) && c1 == c2,
|
|
|
|
_ => false
|
|
|
|
}
|
2022-09-09 20:08:40 +00:00
|
|
|
(Self::Data(_), Self::Data(_)) => todo!("Can't compare data yet"),
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 04:01:57 +00:00
|
|
|
impl Eq for Value {}
|
|
|
|
|
2022-09-09 20:08:40 +00:00
|
|
|
impl PartialOrd for Value {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
if self == other {
|
|
|
|
return Some(Ordering::Equal)
|
|
|
|
}
|
|
|
|
match (self, other) {
|
|
|
|
(Self::Int(a), Self::Int(b)) => a.partial_cmp(b),
|
|
|
|
(Self::Int(a), Self::Float(b)) => (*a as f64).partial_cmp(b),
|
|
|
|
(Self::Float(a), Self::Int(b)) => a.partial_cmp(&(*b as f64)),
|
|
|
|
(Self::Float(a), Self::Float(b)) => a.partial_cmp(b),
|
|
|
|
(Self::Int(a), Self::Rational(b)) => Rational::from(*a).partial_cmp(b),
|
|
|
|
(Self::Rational(a), Self::Int(b)) => a.partial_cmp(&Rational::from(*b)),
|
|
|
|
(Self::Float(a), Self::Rational(b)) => a.partial_cmp(&b.to_f64().unwrap()),
|
|
|
|
(Self::Rational(a), Self::Float(b)) => a.to_f64().unwrap().partial_cmp(b),
|
|
|
|
(Self::Rational(a), Self::Rational(b)) => a.partial_cmp(b),
|
|
|
|
|
|
|
|
(Self::Char(a), Self::Char(b)) => a.partial_cmp(b),
|
|
|
|
(Self::String(a), Self::String(b)) => a.partial_cmp(b),
|
|
|
|
(Self::List(a), Self::List(b)) => a.partial_cmp(b),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-06 13:52:29 +00:00
|
|
|
|
2022-09-15 04:01:57 +00:00
|
|
|
fn hash_f64<H: std::hash::Hasher>(f: f64, state: &mut H) {
|
|
|
|
if f.is_nan() {
|
|
|
|
"NaN".hash(state)
|
|
|
|
} else if f == 0.0 {
|
|
|
|
"0.0".hash(state)
|
|
|
|
} else if f.is_infinite() {
|
|
|
|
if f > 0.0 {
|
|
|
|
"+inf".hash(state)
|
|
|
|
} else{
|
|
|
|
"-inf".hash(state)
|
|
|
|
}
|
|
|
|
} else{
|
2022-09-17 15:17:22 +00:00
|
|
|
f.to_bits().hash(state);
|
2022-09-15 04:01:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Hash for Value {
|
|
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
|
|
match self {
|
|
|
|
Self::Nil => "nil".hash(state),
|
|
|
|
Self::Type(_) => todo!(),
|
|
|
|
Self::Int(i) => i.hash(state),
|
|
|
|
Self::Float(f) => hash_f64(*f, state),
|
|
|
|
Self::Complex(z) => { hash_f64(z.re, state); hash_f64(z.im, state); }
|
|
|
|
Self::Rational(r) => { r.numer().hash(state); r.denom().hash(state); }
|
|
|
|
Self::Bool(b) => b.hash(state),
|
|
|
|
Self::Char(c) => c.hash(state),
|
|
|
|
Self::String(s) => s.hash(state),
|
|
|
|
Self::List(l) => l.borrow().hash(state),
|
|
|
|
Self::Map(_) => todo!(),
|
|
|
|
Self::Func(f) => f.hash(state),
|
|
|
|
Self::Data(_) => todo!(),
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-06 13:52:29 +00:00
|
|
|
macro_rules! value_from {
|
|
|
|
($variant:ident, $($kind:ty)*) => {
|
|
|
|
$(
|
|
|
|
impl From<$kind> for Value {
|
|
|
|
fn from(x: $kind) -> Self {
|
|
|
|
Self::$variant(x.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-09-10 21:19:23 +00:00
|
|
|
impl From<Vec<Value>> for Value {
|
|
|
|
fn from(x: Vec<Value>) -> Self {
|
|
|
|
Self::List(RefCell::new(x).into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 04:01:57 +00:00
|
|
|
impl From<HashMap<Value,Value>> for Value {
|
|
|
|
fn from(x: HashMap<Value,Value>) -> Self {
|
|
|
|
Self::Map(RefCell::new(x).into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-10 21:19:23 +00:00
|
|
|
value_from!(Int, u8 u16 u32 i8 i16 i32 i64);
|
|
|
|
value_from!(Float, f32 f64);
|
|
|
|
value_from!(Complex, Complex);
|
|
|
|
value_from!(Rational, Rational);
|
|
|
|
value_from!(Bool, bool);
|
|
|
|
value_from!(String, String Rc<str>);
|
|
|
|
value_from!(List, RefCell<Vec<Value>>);
|
|
|
|
value_from!(Char, char);
|
2022-09-15 04:01:57 +00:00
|
|
|
value_from!(Map, RefCell<HashMap<Value,Value>>);
|
2022-09-10 21:19:23 +00:00
|
|
|
|
|
|
|
|
2022-09-06 13:52:29 +00:00
|
|
|
macro_rules! impl_numeric_op {
|
|
|
|
($optrait:ty, $fnname:ident, { $($bonus:tt)* }) => {
|
|
|
|
impl $optrait for &Value {
|
|
|
|
type Output = Result<Value, String>;
|
|
|
|
fn $fnname(self, other: Self) -> Self::Output {
|
|
|
|
use Value::*;
|
|
|
|
const RATIO_CAST_FAIL: &'static str = "Failed to cast Rational to Float";
|
|
|
|
match (self, other) {
|
2022-09-16 20:05:28 +00:00
|
|
|
$($bonus)*
|
2022-09-06 13:52:29 +00:00
|
|
|
(Int(a), Int(b)) => Ok(a.$fnname(b).into()),
|
|
|
|
(Rational(a), Int(b)) => Ok(a.$fnname(b).into()),
|
|
|
|
(Int(a), Rational(b)) => Ok(self::Rational::from(*a).$fnname(b).into()),
|
2022-09-09 20:08:40 +00:00
|
|
|
(Rational(a), Rational(b)) => Ok(a.$fnname(b).into()),
|
2022-09-06 13:52:29 +00:00
|
|
|
(Float(a), Int(b)) => Ok(a.$fnname(*b as f64).into()),
|
|
|
|
(Int(a), Float(b)) => Ok((*a as f64).$fnname(b).into()),
|
|
|
|
(Float(a), Rational(b)) => Ok(a.$fnname(b.to_f64().ok_or(RATIO_CAST_FAIL)?).into()),
|
|
|
|
(Rational(a), Float(b)) => Ok(a.to_f64().ok_or(RATIO_CAST_FAIL)?.$fnname(b).into()),
|
|
|
|
(Float(a), Float(b)) => Ok(a.$fnname(b).into()),
|
|
|
|
(Int(a), Complex(b)) => Ok(self::Complex::from(*a as f64).$fnname(b).into()),
|
|
|
|
(Complex(a), Int(b)) => Ok(a.$fnname(self::Complex::from(*b as f64)).into()),
|
|
|
|
(Float(a), Complex(b)) => Ok(self::Complex::from(a).$fnname(b).into()),
|
|
|
|
(Complex(a), Float(b)) => Ok(a.$fnname(self::Complex::from(b)).into()),
|
|
|
|
(Rational(a), Complex(b)) => Ok(self::Complex::from(a.to_f64().ok_or(RATIO_CAST_FAIL)?).$fnname(b).into()),
|
|
|
|
(Complex(a), Rational(b)) => Ok(a.$fnname(self::Complex::from(b.to_f64().ok_or(RATIO_CAST_FAIL)?)).into()),
|
|
|
|
(Complex(a), Complex(b)) => Ok(a.$fnname(b).into()),
|
|
|
|
(lhs, rhs) => Err(format!("Unsupported operation '{}' between {:?} and {:?}", stringify!($fnname), lhs, rhs))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-10 21:19:23 +00:00
|
|
|
impl Neg for Value {
|
|
|
|
type Output = Result<Value, String>;
|
|
|
|
fn neg(self) -> Self::Output {
|
|
|
|
match self {
|
|
|
|
Value::Int(a) => Ok(Value::Int(-a)),
|
2022-09-15 04:01:57 +00:00
|
|
|
Value::Float(a) => Ok(Value::Float(-a)),
|
|
|
|
Value::Rational(a) => Ok(Value::Rational(-a)),
|
|
|
|
Value::Complex(a) => Ok(Value::Complex(-a)),
|
2022-09-10 21:19:23 +00:00
|
|
|
_ => Err(format!("Unsupported operation 'neg' on {:?}", self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-06 13:52:29 +00:00
|
|
|
|
|
|
|
impl_numeric_op!(Add, add, {
|
|
|
|
(String(a), String(b)) => Ok(((**a).to_owned() + b).into()),
|
2022-09-07 22:10:43 +00:00
|
|
|
(String(a), Char(c)) => {
|
|
|
|
let mut s = (**a).to_owned();
|
|
|
|
s.push(*c);
|
|
|
|
Ok(s.into())
|
|
|
|
},
|
|
|
|
(Char(c), String(a)) => Ok((c.to_string() + a).into()),
|
|
|
|
(Char(c1), Char(c2)) => {
|
|
|
|
let mut s = c1.to_string();
|
|
|
|
s.push(*c2);
|
|
|
|
Ok(s.into())
|
|
|
|
}
|
2022-09-06 13:52:29 +00:00
|
|
|
(List(a), List(b)) => {
|
2022-09-11 05:14:54 +00:00
|
|
|
let a = (**a).clone();
|
2022-09-10 21:19:23 +00:00
|
|
|
a.borrow_mut().append(&mut (**b).borrow().clone());
|
2022-09-06 13:52:29 +00:00
|
|
|
Ok(a.into())
|
|
|
|
},
|
|
|
|
});
|
|
|
|
impl_numeric_op!(Sub, sub, {});
|
2022-09-10 21:19:23 +00:00
|
|
|
impl_numeric_op!(Mul, mul, {
|
|
|
|
(String(a), Int(b)) | (Int(b), String(a))
|
|
|
|
=> Ok(Value::from(a.chars().cycle().take(a.chars().count()*(*b as usize)).collect::<std::string::String>())),
|
|
|
|
(List(a), Int(b)) | (Int(b), List(a))
|
|
|
|
=> Ok(Value::from(a.borrow().iter().cycle().take(a.borrow().len()*(*b as usize)).cloned().collect::<Vec<Value>>())),
|
|
|
|
});
|
2022-09-16 20:05:28 +00:00
|
|
|
impl_numeric_op!(Div, div, {
|
|
|
|
(Int(_), Int(b)) if *b == 0 => Err("Integer division by zero".into()),
|
|
|
|
(Rational(_), Int(b)) if *b == 0 => Err("Rational division by zero".into()),
|
|
|
|
(Int(_), Rational(b)) if b.is_zero() => Err("Rational division by zero".into()),
|
|
|
|
(Rational(_), Rational(b)) if b.is_zero() => Err("Rational division by zero".into()),
|
|
|
|
});
|
|
|
|
impl_numeric_op!(Rem, rem, {
|
|
|
|
(Int(_), Int(b)) if *b == 0 => Err("Integer modulo by zero".into()),
|
|
|
|
(Rational(_), Int(b)) if *b == 0 => Err("Rational modulo by zero".into()),
|
|
|
|
(Int(_), Rational(b)) if b.is_zero() => Err("Rational modulo by zero".into()),
|
|
|
|
(Rational(_), Rational(b)) if b.is_zero() => Err("Rational modulo by zero".into()),
|
|
|
|
});
|
|
|
|
|
|
|
|
impl Pow<&Value> for &Value {
|
|
|
|
type Output = Result<Value, String>;
|
|
|
|
|
|
|
|
fn pow(self, other: &Value) -> Self::Output {
|
|
|
|
use Value::*;
|
2022-09-17 15:17:22 +00:00
|
|
|
const RATIO_CAST_FAIL: &str = "Failed to convert rational to float";
|
2022-09-16 20:05:28 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Int(a), Int(b)) => match b {
|
|
|
|
x if *x < 0 => Err(format!("Cannot raise integer {:?} to negative integer exponent {:?}", a, b)),
|
|
|
|
x if *x > (u32::MAX as i64) => Err(format!("Integer exponent {:?} too large", x)),
|
|
|
|
_ => Ok(Value::from(a.pow(*b as u32)))
|
|
|
|
},
|
|
|
|
(Rational(a), Int(b)) => match b {
|
|
|
|
x if *x > (i32::MAX as i64) => Err(format!("Integer exponent {:?} too large", x)),
|
|
|
|
x if *x < (i32::MIN as i64) => Err(format!("Integer exponent {:?} too small", x)),
|
|
|
|
_ => Ok(Value::from(a.pow(*b as i32)))
|
|
|
|
},
|
|
|
|
(Int(_), Rational(_)) => Err("Cannot raise integer to rational exponent".into()),
|
|
|
|
(Rational(_), Rational(_)) => Err("Cannot raise rational to rational exponent".into()),
|
|
|
|
(Float(a), Int(b)) => Ok(a.pow(*b as f64).into()),
|
|
|
|
(Int(a), Float(b)) => Ok((*a as f64).pow(b).into()),
|
|
|
|
(Float(a), Rational(b)) => Ok(a.pow(b.to_f64().ok_or(RATIO_CAST_FAIL)?).into()),
|
|
|
|
(Rational(a), Float(b)) => Ok(a.to_f64().ok_or(RATIO_CAST_FAIL)?.pow(b).into()),
|
|
|
|
(Float(a), Float(b)) => Ok(a.pow(b).into()),
|
|
|
|
(Int(a), Complex(b)) => Ok(self::Complex::from(*a as f64).pow(b).into()),
|
|
|
|
(Complex(a), Int(b)) => Ok(a.pow(self::Complex::from(*b as f64)).into()),
|
|
|
|
(Float(a), Complex(b)) => Ok(self::Complex::from(a).pow(b).into()),
|
|
|
|
(Complex(a), Float(b)) => Ok(a.pow(self::Complex::from(b)).into()),
|
|
|
|
(Rational(a), Complex(b)) => Ok(self::Complex::from(a.to_f64().ok_or(RATIO_CAST_FAIL)?).pow(b).into()),
|
|
|
|
(Complex(a), Rational(b)) => Ok(a.pow(self::Complex::from(b.to_f64().ok_or(RATIO_CAST_FAIL)?)).into()),
|
|
|
|
(Complex(a), Complex(b)) => Ok(a.pow(b).into()),
|
|
|
|
(lhs, rhs) => Err(format!("Unsupported operation 'pow' between {:?} and {:?}", lhs, rhs))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|