use core::any::Any;
use crate::runtime::Variant;
use crate::runtime::gc::{Gc, GcTrace};
use crate::runtime::function::{Call, Callable};
use crate::runtime::strings::{StringValue, StringSymbol, static_symbol};
use crate::runtime::types::{Type, MetaObject};
use crate::runtime::errors::{ExecResult, RuntimeError};
pub struct Nil;
impl MetaObject for Nil {
fn type_tag(&self) -> Type { Type::Nil }
fn as_bool(&self) -> ExecResult<bool> { Ok(false) }
fn cmp_eq(&self, other: &Variant) -> Option<ExecResult<bool>> {
match other {
Variant::Nil => Some(Ok(true)),
_ => None,
}
}
fn fmt_repr(&self) -> ExecResult<StringValue> {
Ok(StringValue::from(static_symbol!("nil")))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Marker {
id: StringSymbol,
}
impl Marker {
pub fn new(id: StringSymbol) -> Self {
Self { id }
}
}
impl MetaObject for Marker {
fn type_tag(&self) -> Type { Type::Marker }
fn cmp_eq(&self, other: &Variant) -> Option<ExecResult<bool>> {
match other {
Variant::Marker(other) => Some(Ok(self == other)),
_ => None,
}
}
fn type_name(&self) -> ExecResult<StringValue> {
Ok(StringValue::from(self.id))
}
fn fmt_repr(&self) -> ExecResult<StringValue> {
self.type_name()
}
}
impl<F> MetaObject for Gc<F> where F: GcTrace, Gc<F>: Callable {
fn type_tag(&self) -> Type { Type::Function }
fn invoke(&self, args: &[Variant]) -> Option<ExecResult<Call>> {
Some(self.checked_call(args))
}
fn cmp_eq(&self, other: &Variant) -> Option<ExecResult<bool>> {
match other {
Variant::Function(other) => Some(Ok(Gc::ptr_eq(self, other))),
Variant::NativeFunction(other) => Some(Ok(Gc::ptr_eq(self, other))),
_ => Some(Ok(false)),
}
}
fn fmt_repr(&self) -> ExecResult<StringValue> {
let result = format!(
"<{} at {:#X}>", self.signature().fmt_name(), Gc::as_id(self),
);
Ok(StringValue::new_uninterned(result))
}
}
impl MetaObject for Gc<RuntimeError> {
fn type_tag(&self) -> Type { Type::Error }
fn fmt_repr(&self) -> ExecResult<StringValue> {
Ok(self.kind().name())
}
}
pub trait UserData: Any + GcTrace + MetaObject {
fn type_tag(&self) -> Type { Type::UserData }
}