Amo/src/ir/value.rs

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),
))
}
}
}