~tim/natalie

ref: f5a482b5ccd757b3cd29779e40922a6db95e541a natalie/include/natalie/class_value.hpp -rw-r--r-- 1.6 KiB
f5a482b5Tim Morgan Add Method#owner and Class#singleton_class? 2 months ago
                                                                                
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
#pragma once

#include <assert.h>

#include "natalie/block.hpp"
#include "natalie/env.hpp"
#include "natalie/forward.hpp"
#include "natalie/global_env.hpp"
#include "natalie/macros.hpp"
#include "natalie/module_value.hpp"
#include "natalie/value.hpp"

namespace Natalie {

struct ClassValue : ModuleValue {
    ClassValue(Env *env)
        : ClassValue { env, env->Object()->const_fetch(env, "Class")->as_class() } { }

    ClassValue(Env *env, ClassValue *klass)
        : ModuleValue { env, Value::Type::Class, klass } { }

    ClassValue *subclass(Env *, const char * = nullptr);
    ClassValue *subclass(Env *, const char *, Type);

    static ClassValue *bootstrap_class_class(Env *);
    static ClassValue *bootstrap_basic_object(Env *, ClassValue *);

    Type object_type() { return m_object_type; }

    ValuePtr initialize(Env *, ValuePtr, Block *);

    static ValuePtr new_method(Env *env, ValuePtr superclass, Block *block) {
        if (superclass) {
            if (!superclass->is_class()) {
                env->raise("TypeError", "superclass must be a Class (%s given)", superclass->klass()->class_name());
            }
        } else {
            superclass = env->Object();
        }
        ValuePtr klass = superclass->as_class()->subclass(env);
        if (block) {
            block->set_self(klass);
            NAT_RUN_BLOCK_AND_POSSIBLY_BREAK(env, block, 0, nullptr, nullptr);
        }
        return klass;
    }

    bool is_singleton() { return m_is_singleton; }
    void set_is_singleton(bool is_singleton) { m_is_singleton = is_singleton; }

private:
    Type m_object_type { Type::Object };
    bool m_is_singleton { false };
};

}