use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
Int(i64),
Float(f64),
Str(String),
Bool(bool),
Bytes(Vec<u8>),
None,
List(Vec<Value>),
Dict(HashMap<String, Value>),
Optional(Option<Box<Value>>),
Promise(PromiseState),
Result(Result<Box<Value>, Box<Value>>),
#[serde(skip)]
Function {
params: Vec<String>,
body: Vec<u8>, },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PromiseState {
Pending,
Resolved(Box<Value>),
Rejected(String),
}
impl Value {
pub fn get_type(&self) -> crate::Type {
use crate::Type;
match self {
Value::Int(_) => Type::Int,
Value::Float(_) => Type::Float,
Value::Str(_) => Type::Str,
Value::Bool(_) => Type::Bool,
Value::Bytes(_) => Type::Bytes,
Value::None => Type::Unit,
Value::List(items) => {
let inner = items.first().map(|v| v.get_type()).unwrap_or(Type::Unknown);
Type::List(Box::new(inner))
}
Value::Dict(map) => {
let value_type = map
.values()
.next()
.map(|v| v.get_type())
.unwrap_or(Type::Unknown);
Type::Dict(Box::new(Type::Str), Box::new(value_type))
}
Value::Optional(opt) => {
let inner = opt.as_ref().map(|v| v.get_type()).unwrap_or(Type::Unknown);
Type::Optional(Box::new(inner))
}
Value::Promise(_) => Type::Promise(Box::new(Type::Unknown)),
Value::Result(res) => match res {
Ok(v) => Type::Result(Box::new(v.get_type()), Box::new(Type::Unknown)),
Err(e) => Type::Result(Box::new(Type::Unknown), Box::new(e.get_type())),
},
Value::Function { params, .. } => Type::Function {
params: params
.iter()
.map(|name| (name.clone(), Type::Unknown))
.collect(),
return_type: Box::new(Type::Unknown),
},
}
}
pub fn is_truthy(&self) -> bool {
match self {
Value::Bool(b) => *b,
Value::None => false,
Value::Int(i) => *i != 0,
Value::Float(f) => *f != 0.0,
Value::Str(s) => !s.is_empty(),
Value::List(l) => !l.is_empty(),
Value::Dict(d) => !d.is_empty(),
Value::Bytes(b) => !b.is_empty(),
Value::Optional(opt) => opt.is_some(),
_ => true,
}
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Value::Int(i) => write!(f, "{i}"),
Value::Float(fl) => write!(f, "{fl}"),
Value::Str(s) => write!(f, "\"{s}\""),
Value::Bool(b) => write!(f, "{b}"),
Value::Bytes(b) => write!(f, "bytes({})", b.len()),
Value::None => write!(f, "None"),
Value::List(items) => {
write!(f, "[")?;
for (i, item) in items.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{item}")?;
}
write!(f, "]")
}
Value::Dict(map) => {
write!(f, "{{")?;
for (i, (k, v)) in map.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "\"{k}\": {v}")?;
}
write!(f, "}}")
}
Value::Optional(opt) => match opt {
Some(v) => write!(f, "Some({v})"),
None => write!(f, "None"),
},
Value::Promise(state) => match state {
PromiseState::Pending => write!(f, "Promise<pending>"),
PromiseState::Resolved(v) => write!(f, "Promise<resolved: {v}>"),
PromiseState::Rejected(e) => write!(f, "Promise<rejected: {e}>")
},
Value::Result(res) => match res {
Ok(v) => write!(f, "Ok({v})"),
Err(e) => write!(f, "Err({e})"),
},
Value::Function { params, .. } => {
write!(f, "function({})", params.join(", "))
}
}
}
}