use crate::{Function, Machine, Ref};
use core::ops::{Add, Div, Mul, Not, Rem, Sub};
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::fmt::{Debug, Display, Error, Formatter};
#[derive(Clone, PartialEq, PartialOrd)]
pub enum Value {
String(String),
Number(f64),
List(Vec<Ref<Self>>),
Tree(BTreeMap<String, Ref<Self>>),
Function(Function<Machine, (), Machine>),
Error(String),
None,
}
impl Value {
pub fn number<N: Into<f64>>(n: N) -> Ref<Self> {
Ref::new(Self::Number(n.into()))
}
pub fn string<S: ToString>(s: S) -> Ref<Self> {
Ref::new(Self::String(s.to_string()))
}
pub fn list() -> Ref<Self> {
Ref::new(Self::List(Vec::new()))
}
pub fn tree() -> Ref<Self> {
Ref::new(Self::Tree(BTreeMap::new()))
}
pub fn function(f: impl 'static + Fn(&mut Machine) -> (), context: &Machine) -> Ref<Self> {
Ref::new(Self::Function(Function::new(
f,
context.clone().duplicate(),
)))
}
pub fn error<S: ToString>(s: S) -> Ref<Self> {
Ref::new(Self::Error(s.to_string()))
}
pub fn none() -> Ref<Self> {
Ref::new(Self::None)
}
pub fn copy(&self) -> Ref<Self> {
match self {
Self::List(l) => {
let mut list = vec![];
for item in l {
list.push(Ref::new((**item).clone()));
}
Ref::new(Self::List(list))
}
Self::Tree(l) => {
let mut map = BTreeMap::new();
for (name, item) in l {
map.insert(name.clone(), Ref::new((**item).clone()));
}
Ref::new(Self::Tree(map))
}
_ => Ref::new(self.clone()),
}
}
pub fn call(&self, machine: &mut Machine) {
if let Self::Function(f) = self {
let mut temp_machine = f.get_context().clone();
temp_machine.stack = machine.stack.clone();
f.call(&mut temp_machine);
machine.stack = temp_machine.stack;
}
}
pub fn call_global(&self, machine: &mut Machine) {
if let Self::Function(f) = self {
f.call(machine);
}
}
pub fn is_err(&self) -> bool {
match self {
Self::Error(_) => true,
_ => false,
}
}
pub fn index<S: ToString>(&mut self, s: S) -> Ref<Self> {
let key = s.to_string();
match self {
Self::String(s) => {
match key.parse::<usize>() {
Ok(n) => {
if s.len() > n {
Value::string(s.chars().nth(n).unwrap().to_string())
} else {
Self::error("String index out of bounds")
}
}
Err(_) => Self::error("Can't index string with non-integer"),
}
}
Self::Tree(t) => {
if !t.contains_key(&key) {
t.insert(key.clone(), Self::none());
}
Ref::clone(t.get(&key).unwrap())
}
Self::List(l) => {
match key.parse::<usize>() {
Ok(n) => {
if n >= l.len() {
l.reserve(n - l.len() + 1);
for _ in l.len()..=n {
l.push(Self::none());
}
}
Ref::clone(&l[n])
}
Err(_) => Self::error("Can't index list with non-integer"),
}
}
_ => Self::error("Can't index non-list or non-tree"),
}
}
}
impl Debug for Value {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self)
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match self {
Self::String(s) => write!(f, "{}", s),
Self::Number(n) => write!(f, "{}", n),
Self::List(l) => write!(f, "{:?}", l),
Self::Tree(t) => write!(f, "{:?}", t),
Self::Function(func) => write!(f, "{}", func),
Self::Error(s) => write!(f, "<Exception: '{}'>", s),
Self::None => write!(f, "None"),
}
}
}
impl From<Value> for bool {
fn from(v: Value) -> Self {
match v {
Value::String(s) => s != "",
Value::Number(n) => (if n < 0.0 { -n } else { n }) > 0.000_000_000_1,
Value::List(l) => !l.is_empty(),
Value::Tree(t) => !t.is_empty(),
Value::Function(_) => true,
Value::Error(_) => false,
Value::None => false,
}
}
}
impl From<Value> for String {
fn from(v: Value) -> Self {
match v {
Value::String(s) => s,
Value::Error(e) => e,
_ => String::from(""),
}
}
}
impl From<Value> for Function<Machine, (), Machine> {
fn from(v: Value) -> Self {
match v {
Value::Function(f) => f,
_ => Function::new(|_: &mut Machine| {}, Machine::new()),
}
}
}
impl From<Value> for Vec<Ref<Value>> {
fn from(v: Value) -> Self {
match v {
Value::List(l) => l,
_ => Vec::new(),
}
}
}
impl From<Value> for BTreeMap<String, Ref<Value>> {
fn from(v: Value) -> Self {
match v {
Value::Tree(t) => t,
_ => BTreeMap::new(),
}
}
}
impl From<Value> for f64 {
fn from(v: Value) -> Self {
match v {
Value::Number(n) => n,
_ => 0.0,
}
}
}
impl From<Value> for i32 {
fn from(v: Value) -> Self {
match v {
Value::Number(n) => n as i32,
_ => 0,
}
}
}
impl From<String> for Value {
fn from(s: String) -> Self {
Value::String(s)
}
}
impl From<&str> for Value {
fn from(s: &str) -> Self {
Value::String(s.to_string())
}
}
impl From<bool> for Value {
fn from(n: bool) -> Self {
Value::Number(f64::from(n as i32))
}
}
impl From<f64> for Value {
fn from(n: f64) -> Self {
Value::Number(n)
}
}
impl From<i32> for Value {
fn from(n: i32) -> Self {
Value::Number(f64::from(n))
}
}
impl From<Vec<Ref<Value>>> for Value {
fn from(l: Vec<Ref<Value>>) -> Self {
Value::List(l)
}
}
impl From<BTreeMap<String, Ref<Value>>> for Value {
fn from(t: BTreeMap<String, Ref<Value>>) -> Self {
Value::Tree(t)
}
}
impl From<Function<Machine, (), Machine>> for Value {
fn from(f: Function<Machine, (), Machine>) -> Self {
Value::Function(f)
}
}
impl Add<Value> for Value {
type Output = Value;
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::String(s1), Self::String(s2)) => Self::String(s1 + &s2),
(Self::Number(m), Self::Number(n)) => Self::Number(m + n),
(Self::List(mut l1), Self::List(l2)) => {
l1.extend(l2);
Self::List(l1)
}
(a, b) => Self::Error(format!("Could not add {} and {}", a, b)),
}
}
}
impl Sub<Value> for Value {
type Output = Value;
fn sub(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::Number(m), Self::Number(n)) => Self::Number(m - n),
(a, b) => Self::Error(format!("Could not subtract {} and {}", a, b)),
}
}
}
impl Mul<Value> for Value {
type Output = Value;
fn mul(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::String(s1), Self::Number(n)) => Self::String(s1.repeat(n as usize)),
(Self::Number(m), Self::Number(n)) => Self::Number(m * n),
(a, b) => Self::Error(format!("Could not multiply {} and {}", a, b)),
}
}
}
impl Div<Value> for Value {
type Output = Value;
fn div(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::Number(m), Self::Number(n)) => Self::Number(m / n),
(a, b) => Self::Error(format!("Could not divide {} and {}", a, b)),
}
}
}
impl Rem<Value> for Value {
type Output = Value;
fn rem(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Self::Number(m), Self::Number(n)) => Self::Number(m % n),
(a, b) => Self::Error(format!("Could not find the remainder of {} and {}", a, b)),
}
}
}
impl Not for Value {
type Output = Value;
fn not(self) -> Self::Output {
match self {
Self::Number(n) => match n as i32 {
0 => Self::Number(1.0),
_ => Self::Number(0.0),
},
a => Self::Error(format!("Could not negate {}", a)),
}
}
}