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
use std::{fmt, ops::Deref};

use fmt::Debug;

use crate::{
    class::{ClassKind, ClassRef},
    impl_class,
    memory::MemoryLayout,
    type_context::TypeContext,
    ObjectPayload, ObjectProperties, Type,
};

/// Marks objects that have a class
///
/// Every object payload has to implement this trait.
pub trait HasClass {
    /// Returns all properties that belong to this class
    fn create_properties(ctx: &TypeContext) -> ObjectProperties
    where
        Self: Sized;

    /// Returns the static class that belongs to this Object
    fn static_class(ctx: &TypeContext) -> ClassRef
    where
        Self: Sized;
}

/// The class of a value.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ObjClass {
    pub class: ClassRef,
}

impl_class! {ObjClass, Type::Type, {
    CmpEq => |this: &ObjClass, other: &ObjClass| -> bool {
        this == other
    }
}}

impl ObjClass {
    pub fn new(value: ClassRef) -> Self {
        ObjClass { class: value }
    }
}

impl Deref for ObjClass {
    type Target = ClassRef;

    fn deref(&self) -> &Self::Target {
        &self.class
    }
}

impl From<ClassRef> for ObjClass {
    fn from(value: ClassRef) -> Self {
        ObjClass::new(value)
    }
}

impl ObjectPayload for ObjClass {
    fn memory_layout(&self) -> &MemoryLayout {
        &MemoryLayout::Unsized
    }

    // A bit hacky way to get members functions (etc.) from structs
    fn get_property(
        &self,
        _ctx: &TypeContext,
        ident: &debris_common::Ident,
    ) -> Option<crate::ObjectRef> {
        match &self.class.kind {
            ClassKind::Struct(strukt) | ClassKind::StructValue(strukt) => strukt
                .namespace
                .get()
                .and_then(|map| map.get(ident).cloned()),
            ClassKind::Tuple(_)
            | ClassKind::TupleValue(_)
            | ClassKind::Function(_)
            | ClassKind::Type(_) => None,
        }
    }
}

impl fmt::Display for ObjClass {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.class, f)
    }
}