-
Notifications
You must be signed in to change notification settings - Fork 0
/
mult.c
214 lines (174 loc) · 5.42 KB
/
mult.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include <ruby.h>
#include "compat.h"
static VALUE cRubyTable;
typedef struct {
st_table* table;
} RubyTable;
/* return the actual class of an object */
static VALUE
global_get_class(VALUE self, VALUE klass) {
return CLASS_OF(klass);
}
static VALUE
global_set_class(VALUE self, VALUE klass, VALUE new_klass) {
KLASS_OF(klass) = new_klass;
return klass;
}
static VALUE
get_class(VALUE self) {
return CLASS_OF(self);
}
/* set the class of an object */
static VALUE
set_class(VALUE self, VALUE klass) {
KLASS_OF(self) = klass;
return klass;
}
/* get the actual super class of an object */
static VALUE
global_get_super(VALUE self, VALUE klass)
{
return RCLASS_SUPER(klass);
}
static VALUE
global_set_super(VALUE self, VALUE klass, VALUE sup)
{
return RCLASS_SUPER(klass) = sup;
}
static VALUE
get_super(VALUE self)
{
return RCLASS_SUPER(self);
}
/* set the super class of an object */
static VALUE
set_super(VALUE self, VALUE klass) {
RCLASS_SUPER(self) = klass;
return klass;
}
/* is the object a singleton class ? */
static VALUE
is_singleton(VALUE self, VALUE klass) {
return FL_TEST(self, FL_SINGLETON) ? Qtrue : Qfalse;
}
/* get a raw instance var */
static VALUE
global_get_ivar(VALUE self, VALUE klass, VALUE sym)
{
return rb_ivar_get(klass, rb_to_id(sym));
}
static VALUE
get_ivar(VALUE self, VALUE sym)
{
return rb_ivar_get(self, rb_to_id(sym));
}
/* set a raw instance var */
static VALUE
set_ivar(VALUE self, VALUE sym, VALUE val)
{
return rb_ivar_set(self, rb_to_id(sym), val);
}
static VALUE
global_set_ivar(VALUE self, VALUE klass, VALUE sym, VALUE val)
{
return rb_ivar_set(klass, rb_to_id(sym), val);
}
/* get the attached class if receiver is a singleton class */
static VALUE
get_attached(VALUE self)
{
if(FL_TEST(self, FL_SINGLETON))
return rb_iv_get(self, "__attached__");
else
return Qnil;
}
/* set the attached class if receiver is a singleton class */
static VALUE
set_attached(VALUE self, VALUE klass) {
if(FL_TEST(self, FL_SINGLETON)) {
rb_iv_set(self, "__attached__", klass);
return self;
}
else
return Qnil;
}
/* generate table get methods */
#define CREATE_GET_TBL_FUNC(func_name, table_type) \
static VALUE func_name(VALUE self) { \
RubyTable * tbl_struct = ALLOC(RubyTable); \
if (!table_type(self)) \
table_type(self) = st_init_numtable(); \
tbl_struct->table = table_type(self); \
return Data_Wrap_Struct(cRubyTable, 0, free, tbl_struct); \
}
/* generate table set methods */
#define CREATE_SET_TBL_FUNC(func_name, table_type) \
static VALUE \
func_name(VALUE self, VALUE rb_tbl) { \
Check_Type(rb_tbl, T_DATA); \
RubyTable * tbl_struct; \
Data_Get_Struct(rb_tbl, RubyTable, tbl_struct); \
table_type(self) = tbl_struct->table; \
rb_clear_cache(); \
return self; \
}
/* get the method table */
CREATE_GET_TBL_FUNC(get_m_tbl, RCLASS_M_TBL)
/* set the method table */
CREATE_SET_TBL_FUNC(set_m_tbl, RCLASS_M_TBL)
/* get the iv table */
CREATE_GET_TBL_FUNC(get_iv_tbl, RCLASS_IV_TBL)
/* set the iv table */
CREATE_SET_TBL_FUNC(set_iv_tbl, RCLASS_IV_TBL)
static VALUE
set_flags(VALUE self, VALUE flag)
{
Check_Type(flag, T_FIXNUM);
FL_SET(self, FIX2INT(flag));
return self;
}
static VALUE
get_flags(VALUE self)
{
return INT2FIX(RBASIC(self)->flags);
}
static VALUE
has_flag_p(VALUE self, VALUE flag)
{
Check_Type(flag, T_FIXNUM);
return FL_TEST(self, FIX2INT(flag)) ? Qtrue : Qfalse;
}
void
Init_mult() {
cRubyTable = rb_define_class("RubyTable", rb_cObject);
rb_define_method(rb_cObject, "RCLASS_GET", global_get_class, 1);
rb_define_method(rb_cObject, "RCLASS_SET", global_set_class, 2);
rb_define_method(rb_cObject, "actual_class", get_class, 0);
rb_define_method(rb_cObject, "actual_class=", set_class, 1);
rb_define_method(rb_cObject, "IVAR_GET", global_get_ivar, 2);
rb_define_method(rb_cObject, "IVAR_SET", global_set_ivar, 3);
rb_define_method(rb_cObject, "ivar_get", get_ivar, 1);
rb_define_method(rb_cObject, "ivar_set", set_ivar, 2);
rb_define_method(rb_cModule, "m_tbl", get_m_tbl, 0);
rb_define_method(rb_cModule, "m_tbl=", set_m_tbl, 1);
rb_define_method(rb_cModule, "iv_tbl", get_iv_tbl, 0);
rb_define_method(rb_cModule, "iv_tbl=", set_iv_tbl, 1);
rb_define_method(rb_cObject, "RCLASS_SUPER_GET", global_get_super, 1);
rb_define_method(rb_cObject, "RCLASS_SUPER_SET", get_super, 1);
rb_define_method(rb_cModule, "actual_super", get_super, 0);
rb_define_method(rb_cModule, "actual_super=", set_super, 1);
rb_define_method(rb_cClass, "is_singleton?", is_singleton, 0);
rb_define_method(rb_cClass, "attached", get_attached, 0);
rb_define_method(rb_cClass, "attached=", set_attached, 1);
rb_define_method(rb_cObject, "has_flag?", has_flag_p, 1);
rb_define_method(rb_cObject, "flags=", set_flags, 1);
rb_define_method(rb_cObject, "flags", get_flags, 0);
// constants
rb_define_const(rb_cObject, "T_CLASS", INT2FIX(T_CLASS));
rb_define_const(rb_cObject, "T_MODULE", INT2FIX(T_MODULE));
rb_define_const(rb_cObject, "T_OBJECT", INT2FIX(T_OBJECT));
rb_define_const(rb_cObject, "T_DATA", INT2FIX(T_DATA));
rb_define_const(rb_cObject, "T_ICLASS", INT2FIX(T_ICLASS));
rb_define_const(rb_cObject, "FL_FREEZE", INT2FIX(FL_FREEZE));
rb_define_const(rb_cObject, "FL_SINGLETON", INT2FIX(FL_SINGLETON));
}