1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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;

// 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_echo(&self) -> ExecResult<StringValue> {
        Ok(StringValue::from(static_symbol!("nil")))
    }
}


// Marker type - kind of like scheme's symbols -- currently unused
#[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_echo(&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_echo(&self) -> ExecResult<StringValue> {
        // TODO cache this in the signature struct?
        let result = format!(
            "<{} at {:#X}>", self.signature().fmt_name(), Gc::as_id(self),
        );
        
        Ok(StringValue::new_uninterned(result))
    }
}


// Errors

impl MetaObject for Gc<RuntimeError> {
    fn type_tag(&self) -> Type { Type::Error }
    
    fn fmt_echo(&self) -> ExecResult<StringValue> {
        Ok(self.kind().name())
    }
}


/// Trait for custom data
pub trait UserData: Any + GcTrace + MetaObject {
    fn type_tag(&self) -> Type { Type::UserData }
}