forked from macournoyer/tinyrb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass.c
138 lines (115 loc) · 3.49 KB
/
class.c
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "tr.h"
#include "internal.h"
#define TR_INIT_MODULE(M) \
(M)->name = name; \
(M)->methods = kh_init(OBJ); \
(M)->meta = 0
/* included module proxy */
OBJ TrIModule_new(VM, OBJ module, OBJ super) {
TrModule *m = TR_CMODULE(module);
TrModule *im = TR_INIT_CORE_OBJECT(Module);
im->name = m->name;
im->methods = m->methods;
im->super = super;
return (OBJ)im;
}
/* module */
OBJ TrModule_new(VM, OBJ name) {
TrModule *m = TR_INIT_CORE_OBJECT(Module);
TR_INIT_MODULE(m);
return (OBJ)m;
}
OBJ TrModule_instance_method(VM, OBJ self, OBJ name) {
TrClass *class = TR_CCLASS(self);
while (class) {
OBJ method = TR_KH_GET(class->methods, name);
if (method) return method;
class = (TrClass *)class->super;
}
return TR_NIL;
}
OBJ TrModule_add_method(VM, OBJ self, OBJ name, OBJ method) {
TrClass *m = TR_CMODULE(self);
TR_KH_SET(m->methods, name, method);
TR_CMETHOD(method)->name = name;
return method;
}
OBJ TrModule_alias_method(VM, OBJ self, OBJ new_name, OBJ old_name) {
return TrModule_add_method(vm, self, new_name, TrModule_instance_method(vm, self, old_name));
}
OBJ TrModule_include(VM, OBJ self, OBJ mod) {
TrClass *class = TR_CCLASS(self);
class->super = TrIModule_new(vm, mod, class->super);
return mod;
}
static OBJ TrModule_name(VM, OBJ self) {
return TR_CMODULE(self)->name;
}
void TrModule_init(VM) {
OBJ c = TR_INIT_CORE_CLASS(Module, Object);
tr_def(c, "name", TrModule_name, 0);
tr_def(c, "include", TrModule_include, 1);
tr_def(c, "instance_method", TrModule_instance_method, 1);
tr_def(c, "alias_method", TrModule_alias_method, 2);
tr_def(c, "to_s", TrModule_name, 0);
}
/* class */
OBJ TrClass_new(VM, OBJ name, OBJ super) {
TrClass *c = TR_INIT_CORE_OBJECT(Class);
TR_INIT_MODULE(c);
/* if VM is booting, those might not be set */
if (super && TR_CCLASS(super)->class) c->class = TrMetaClass_new(vm, TR_CCLASS(super)->class);
c->super = super;
return (OBJ)c;
}
OBJ TrClass_allocate(VM, OBJ self) {
TrObject *o = TR_INIT_CORE_OBJECT(Object);
o->class = self;
return (OBJ)o;
}
OBJ TrClass_superclass(VM, OBJ self) {
OBJ super = TR_CCLASS(self)->super;
while (super && !TR_IS_A(super, Class))
super = TR_CCLASS(super)->super;
return super;
}
void TrClass_init(VM) {
OBJ c = TR_INIT_CORE_CLASS(Class, Module);
tr_def(c, "superclass", TrClass_superclass, 0);
tr_def(c, "allocate", TrClass_allocate, 0);
}
/* metaclass */
OBJ TrMetaClass_new(VM, OBJ super) {
TrClass *c = TR_CCLASS(super);
OBJ name = tr_sprintf(vm, "Class:%s", TR_STR_PTR(c->name));
name = tr_intern(TR_STR_PTR(name)); /* symbolize */
TrClass *mc = (TrClass *)TrClass_new(vm, name, 0);
mc->super = super;
mc->meta = 1;
return (OBJ)mc;
}
/* method */
OBJ TrMethod_new(VM, TrFunc *func, OBJ data, int arity) {
TrMethod *m = TR_INIT_CORE_OBJECT(Method);
m->func = func;
m->data = data;
m->arity = arity;
return (OBJ)m;
}
OBJ TrMethod_name(VM, OBJ self) { UNUSED(vm); return TR_CMETHOD(self)->name; }
OBJ TrMethod_arity(VM, OBJ self) { UNUSED(vm); return TR_INT2FIX(TR_CMETHOD(self)->arity); }
OBJ TrMethod_dump(VM, OBJ self) {
TrMethod *m = TR_CMETHOD(self);
if (m->name) printf("<Method '%s':%p>\n", TR_STR_PTR(m->name), m);
if (m->data)
TrBlock_dump(vm, (TrBlock*)m->data);
else
printf("<CFunction:%p>\n", m->func);
return TR_NIL;
}
void TrMethod_init(VM) {
OBJ c = TR_INIT_CORE_CLASS(Method, Object);
tr_def(c, "name", TrMethod_name, 0);
tr_def(c, "arity", TrMethod_arity, 0);
tr_def(c, "dump", TrMethod_dump, 0);
}