use crate::Interpreter;
use gcmodule::{Cc, Trace, Tracer};
use std::fmt;
use std::ops::Deref;
#[derive(Clone)]
pub struct Value<L: 'static> {
inner: Cc<Box<dyn AbstractValue<L>>>,
}
impl<L: Interpreter> Value<L> {
pub fn new<T: AbstractValue<L> + Sized>(value: T) -> Self {
let value: Box<dyn AbstractValue<L>> = Box::new(value);
Self {
inner: Cc::new(value),
}
}
pub fn downcast_ref<T: AbstractValue<L> + Sized>(&self) -> Option<&T> {
let inner: &dyn AbstractValue<L> = <Value<L> as Deref>::deref(self);
inner.as_any().and_then(|any| any.downcast_ref::<T>())
}
}
pub trait AbstractValue<L: Interpreter>: Trace + fmt::Display + fmt::Debug {
fn apply(&self, env: &L::Env, args: &[L::Expr]) -> Result<L::Value, L::Error> {
let _ = (env, args);
Err(format!("{:?} is not callable", self).into())
}
}
impl<L> Deref for Value<L> {
type Target = dyn AbstractValue<L>;
#[inline]
fn deref(&self) -> &Self::Target {
self.inner.deref().deref()
}
}
impl<L: 'static> Trace for Value<L> {
fn trace(&self, tracer: &mut Tracer) {
self.deref().trace(tracer)
}
}
impl<L: Interpreter> Trace for Box<dyn AbstractValue<L>> {
fn trace(&self, tracer: &mut Tracer) {
self.deref().trace(tracer)
}
}
impl<L: Interpreter> fmt::Display for Value<L> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
impl<L: Interpreter> fmt::Debug for Value<L> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}