76 lines
1.8 KiB
Rust
76 lines
1.8 KiB
Rust
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<Identifier>, LinkedList<Expr>),
|
|
Structural(Identifier, Vec<Value>),
|
|
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::<Vec<_>>()
|
|
.join(", "),
|
|
exprs.into_iter()
|
|
.map(|e| format!("\n\t{e}"))
|
|
.collect::<String>(),
|
|
),
|
|
Self::Structural(_, _) => todo!(),
|
|
Self::Type(typ) => typ.fmt(f),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryInto<usize> for &Value {
|
|
type Error = EvaluateError;
|
|
|
|
fn try_into(self) -> Result<usize, EvaluateError> {
|
|
if let Value::Int(v) = self {
|
|
Ok(*v)
|
|
} else {
|
|
Err(EvaluateError::TypeMismatch(
|
|
discriminant(&Value::Int(0)),
|
|
discriminant(&self),
|
|
))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryInto<bool> for &Value {
|
|
type Error = EvaluateError;
|
|
|
|
fn try_into(self) -> Result<bool, EvaluateError> {
|
|
if let Value::Int(v) = self {
|
|
Ok(*v != 0)
|
|
} else {
|
|
Err(EvaluateError::TypeMismatch(
|
|
discriminant(&Value::Int(0)),
|
|
discriminant(&self),
|
|
))
|
|
}
|
|
}
|
|
}
|