use core::fmt; use std::{collections::LinkedList, mem::discriminant}; use super::{expr::{Expr, evaluate}, Identifier, evaluation::{EvaluateError, ValueBindings, self}, types::Type}; #[derive(Clone, Debug)] pub enum Value { Int(usize), String(String), Function(Vec, LinkedList), Structural(Identifier, Vec), Type(Type), } impl Value { /// Converts a zero-arg function into its result pub fn simplify(self, bindings: &ValueBindings) -> evaluation::Result { match self { Value::Function(args, value) if args.is_empty() => evaluate(value, bindings.nested_scope()), other => Ok(other), } } } impl fmt::Display for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Int(v) => write!(f, "{}", v), Self::String(val) => write!(f, "\"{val}\""), Self::Function(args, exprs) => write!(f, "function({}):{}", args.into_iter() .map(|a| a.to_string()) .collect::>() .join(", "), exprs.into_iter() .map(|e| format!("\n\t{e}")) .collect::(), ), Self::Structural(_, _) => todo!(), Self::Type(typ) => typ.fmt(f), } } } impl TryInto for &Value { type Error = EvaluateError; fn try_into(self) -> Result { if let Value::Int(v) = self { Ok(*v) } else { Err(EvaluateError::TypeMismatch( discriminant(&Value::Int(0)), discriminant(&self), )) } } } impl TryInto for &Value { type Error = EvaluateError; fn try_into(self) -> Result { if let Value::Int(v) = self { Ok(*v != 0) } else { Err(EvaluateError::TypeMismatch( discriminant(&Value::Int(0)), discriminant(&self), )) } } }