1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13: #include "ruby/ruby.h"
14: #include "ruby/signal.h"
15: #include "ruby/node.h"
16: #include "ruby/st.h"
17: #include <ctype.h>
18:
19: extern st_table *rb_class_tbl;
20:
21: static VALUE
22: class_alloc(VALUE flags, VALUE klass)
23: {
24: rb_classext_t *ext = ALLOC(rb_classext_t);
25: NEWOBJ(obj, struct RClass);
26: OBJSETUP(obj, klass, flags);
27: obj->ptr = ext;
28: RCLASS_IV_TBL(obj) = 0;
29: RCLASS_M_TBL(obj) = 0;
30: RCLASS_SUPER(obj) = 0;
31: RCLASS_IV_INDEX_TBL(obj) = 0;
32: return (VALUE)obj;
33: }
34:
35: VALUE
36: rb_class_boot(VALUE super)
37: {
38: VALUE klass = class_alloc(T_CLASS, rb_cClass);
39:
40: RCLASS_SUPER(klass) = super;
41: RCLASS_M_TBL(klass) = st_init_numtable();
42:
43: OBJ_INFECT(klass, super);
44: return (VALUE)klass;
45: }
46:
47: void
48: rb_check_inheritable(VALUE super)
49: {
50: if (TYPE(super) != T_CLASS) {
51: rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
52: rb_obj_classname(super));
53: }
54: if (RBASIC(super)->flags & FL_SINGLETON) {
55: rb_raise(rb_eTypeError, "can't make subclass of singleton class");
56: }
57: }
58:
59: VALUE
60: rb_class_new(VALUE super)
61: {
62: Check_Type(super, T_CLASS);
63: rb_check_inheritable(super);
64: if (super == rb_cClass) {
65: rb_raise(rb_eTypeError, "can't make subclass of Class");
66: }
67: return rb_class_boot(super);
68: }
69:
70: struct clone_method_data {
71: st_table *tbl;
72: VALUE klass;
73: };
74:
75: static int
76: clone_method(ID mid, NODE *body, struct clone_method_data *data)
77: {
78: if (body == 0) {
79: st_insert(data->tbl, mid, 0);
80: }
81: else {
82: st_insert(data->tbl, mid,
83: (st_data_t)
84: NEW_FBODY(
85: NEW_METHOD(body->nd_body->nd_body,
86: data->klass,
87: body->nd_body->nd_noex),
88: 0));
89: }
90: return ST_CONTINUE;
91: }
92:
93:
94: VALUE
95: rb_mod_init_copy(VALUE clone, VALUE orig)
96: {
97: rb_obj_init_copy(clone, orig);
98: if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
99: RBASIC(clone)->klass = rb_singleton_class_clone(orig);
100: }
101: RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
102: if (RCLASS_IV_TBL(orig)) {
103: ID id;
104:
105: RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig));
106: id = rb_intern("__classpath__");
107: st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0);
108: id = rb_intern("__classid__");
109: st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0);
110: }
111: if (RCLASS_M_TBL(orig)) {
112: struct clone_method_data data;
113: data.tbl = RCLASS_M_TBL(clone) = st_init_numtable();
114: data.klass = clone;
115: st_foreach(RCLASS_M_TBL(orig), clone_method,
116: (st_data_t)&data);
117: }
118:
119: return clone;
120: }
121:
122:
123: VALUE
124: rb_class_init_copy(VALUE clone, VALUE orig)
125: {
126: if (RCLASS_SUPER(clone) != 0) {
127: rb_raise(rb_eTypeError, "already initialized class");
128: }
129: if (FL_TEST(orig, FL_SINGLETON)) {
130: rb_raise(rb_eTypeError, "can't copy singleton class");
131: }
132: return rb_mod_init_copy(clone, orig);
133: }
134:
135: VALUE
136: rb_singleton_class_clone(VALUE obj)
137: {
138: VALUE klass = RBASIC(obj)->klass;
139:
140: if (!FL_TEST(klass, FL_SINGLETON))
141: return klass;
142: else {
143: struct clone_method_data data;
144:
145: VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
146:
147: if (BUILTIN_TYPE(obj) == T_CLASS) {
148: RBASIC(clone)->klass = (VALUE)clone;
149: }
150: else {
151: RBASIC(clone)->klass = rb_singleton_class_clone(klass);
152: }
153:
154: RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
155: if (RCLASS_IV_TBL(klass)) {
156: RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
157: }
158: RCLASS_M_TBL(clone) = st_init_numtable();
159: data.tbl = RCLASS_M_TBL(clone);
160: data.klass = (VALUE)clone;
161: st_foreach(RCLASS_M_TBL(klass), clone_method,
162: (st_data_t)&data);
163: rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
164: FL_SET(clone, FL_SINGLETON);
165: return (VALUE)clone;
166: }
167: }
168:
169: void
170: rb_singleton_class_attached(VALUE klass, VALUE obj)
171: {
172: if (FL_TEST(klass, FL_SINGLETON)) {
173: if (!RCLASS_IV_TBL(klass)) {
174: RCLASS_IV_TBL(klass) = st_init_numtable();
175: }
176: st_insert(RCLASS_IV_TBL(klass), rb_intern("__attached__"), obj);
177: }
178: }
179:
180: VALUE
181: rb_make_metaclass(VALUE obj, VALUE super)
182: {
183: if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
184: return RBASIC(obj)->klass = rb_cClass;
185: }
186: else {
187: VALUE metasuper;
188: VALUE klass = rb_class_boot(super);
189:
190: FL_SET(klass, FL_SINGLETON);
191: RBASIC(obj)->klass = klass;
192: rb_singleton_class_attached(klass, obj);
193:
194: metasuper = RBASIC(rb_class_real(super))->klass;
195:
196: if (metasuper) {
197: RBASIC(klass)->klass = metasuper;
198: }
199: return klass;
200: }
201: }
202:
203: VALUE
204: rb_define_class_id(ID id, VALUE super)
205: {
206: VALUE klass;
207:
208: if (!super) super = rb_cObject;
209: klass = rb_class_new(super);
210: rb_make_metaclass(klass, RBASIC(super)->klass);
211:
212: return klass;
213: }
214:
215: VALUE
216: rb_class_inherited(VALUE super, VALUE klass)
217: {
218: if (!super) super = rb_cObject;
219: return rb_funcall(super, rb_intern("inherited"), 1, klass);
220: }
221:
222: VALUE
223: rb_define_class(const char *name, VALUE super)
224: {
225: VALUE klass;
226: ID id;
227:
228: id = rb_intern(name);
229: if (rb_const_defined(rb_cObject, id)) {
230: klass = rb_const_get(rb_cObject, id);
231: if (TYPE(klass) != T_CLASS) {
232: rb_raise(rb_eTypeError, "%s is not a class", name);
233: }
234: if (rb_class_real(RCLASS_SUPER(klass)) != super) {
235: rb_name_error(id, "%s is already defined", name);
236: }
237: return klass;
238: }
239: if (!super) {
240: rb_warn("no super class for `%s', Object assumed", name);
241: }
242: klass = rb_define_class_id(id, super);
243: st_add_direct(rb_class_tbl, id, klass);
244: rb_name_class(klass, id);
245: rb_const_set(rb_cObject, id, klass);
246: rb_class_inherited(super, klass);
247:
248: return klass;
249: }
250:
251: VALUE
252: rb_define_class_under(VALUE outer, const char *name, VALUE super)
253: {
254: VALUE klass;
255: ID id;
256:
257: id = rb_intern(name);
258: if (rb_const_defined_at(outer, id)) {
259: klass = rb_const_get_at(outer, id);
260: if (TYPE(klass) != T_CLASS) {
261: rb_raise(rb_eTypeError, "%s is not a class", name);
262: }
263: if (rb_class_real(RCLASS_SUPER(klass)) != super) {
264: rb_name_error(id, "%s is already defined", name);
265: }
266: return klass;
267: }
268: if (!super) {
269: rb_warn("no super class for `%s::%s', Object assumed",
270: rb_class2name(outer), name);
271: }
272: klass = rb_define_class_id(id, super);
273: rb_set_class_path(klass, outer, name);
274: rb_const_set(outer, id, klass);
275: rb_class_inherited(super, klass);
276:
277: return klass;
278: }
279:
280: VALUE
281: rb_module_new(void)
282: {
283: VALUE mdl = class_alloc(T_MODULE, rb_cModule);
284:
285: RCLASS_M_TBL(mdl) = st_init_numtable();
286:
287: return (VALUE)mdl;
288: }
289:
290: VALUE
291: rb_define_module_id(ID id)
292: {
293: VALUE mdl;
294:
295: mdl = rb_module_new();
296: rb_name_class(mdl, id);
297:
298: return mdl;
299: }
300:
301: VALUE
302: rb_define_module(const char *name)
303: {
304: VALUE module;
305: ID id;
306:
307: id = rb_intern(name);
308: if (rb_const_defined(rb_cObject, id)) {
309: module = rb_const_get(rb_cObject, id);
310: if (TYPE(module) == T_MODULE)
311: return module;
312: rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
313: }
314: module = rb_define_module_id(id);
315: st_add_direct(rb_class_tbl, id, module);
316: rb_const_set(rb_cObject, id, module);
317:
318: return module;
319: }
320:
321: VALUE
322: rb_define_module_under(VALUE outer, const char *name)
323: {
324: VALUE module;
325: ID id;
326:
327: id = rb_intern(name);
328: if (rb_const_defined_at(outer, id)) {
329: module = rb_const_get_at(outer, id);
330: if (TYPE(module) == T_MODULE)
331: return module;
332: rb_raise(rb_eTypeError, "%s::%s is not a module",
333: rb_class2name(outer), rb_obj_classname(module));
334: }
335: module = rb_define_module_id(id);
336: rb_const_set(outer, id, module);
337: rb_set_class_path(module, outer, name);
338:
339: return module;
340: }
341:
342: static VALUE
343: include_class_new(VALUE module, VALUE super)
344: {
345: VALUE klass = class_alloc(T_ICLASS, rb_cClass);
346:
347: if (BUILTIN_TYPE(module) == T_ICLASS) {
348: module = RBASIC(module)->klass;
349: }
350: if (!RCLASS_IV_TBL(module)) {
351: RCLASS_IV_TBL(module) = st_init_numtable();
352: }
353: RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
354: RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
355: RCLASS_SUPER(klass) = super;
356: if (TYPE(module) == T_ICLASS) {
357: RBASIC(klass)->klass = RBASIC(module)->klass;
358: }
359: else {
360: RBASIC(klass)->klass = module;
361: }
362: OBJ_INFECT(klass, module);
363: OBJ_INFECT(klass, super);
364:
365: return (VALUE)klass;
366: }
367:
368: void
369: rb_include_module(VALUE klass, VALUE module)
370: {
371: VALUE p, c;
372: int changed = 0;
373:
374: rb_frozen_class_p(klass);
375: if (!OBJ_TAINTED(klass)) {
376: rb_secure(4);
377: }
378:
379: if (TYPE(module) != T_MODULE) {
380: Check_Type(module, T_MODULE);
381: }
382:
383: OBJ_INFECT(klass, module);
384: c = klass;
385: while (module) {
386: int superclass_seen = Qfalse;
387:
388: if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
389: rb_raise(rb_eArgError, "cyclic include detected");
390:
391: for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
392: switch (BUILTIN_TYPE(p)) {
393: case T_ICLASS:
394: if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
395: if (!superclass_seen) {
396: c = p;
397: }
398: goto skip;
399: }
400: break;
401: case T_CLASS:
402: superclass_seen = Qtrue;
403: break;
404: }
405: }
406: c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
407: changed = 1;
408: skip:
409: module = RCLASS_SUPER(module);
410: }
411: if (changed) rb_clear_cache();
412: }
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
428:
429:
430:
431: VALUE
432: rb_mod_included_modules(VALUE mod)
433: {
434: VALUE ary = rb_ary_new();
435: VALUE p;
436:
437: for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
438: if (BUILTIN_TYPE(p) == T_ICLASS) {
439: rb_ary_push(ary, RBASIC(p)->klass);
440: }
441: }
442: return ary;
443: }
444:
445:
446:
447:
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459:
460:
461:
462:
463:
464: VALUE
465: rb_mod_include_p(VALUE mod, VALUE mod2)
466: {
467: VALUE p;
468:
469: Check_Type(mod2, T_MODULE);
470: for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
471: if (BUILTIN_TYPE(p) == T_ICLASS) {
472: if (RBASIC(p)->klass == mod2) return Qtrue;
473: }
474: }
475: return Qfalse;
476: }
477:
478:
479:
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494: VALUE
495: rb_mod_ancestors(VALUE mod)
496: {
497: VALUE p, ary = rb_ary_new();
498:
499: for (p = mod; p; p = RCLASS_SUPER(p)) {
500: if (FL_TEST(p, FL_SINGLETON))
501: continue;
502: if (BUILTIN_TYPE(p) == T_ICLASS) {
503: rb_ary_push(ary, RBASIC(p)->klass);
504: }
505: else {
506: rb_ary_push(ary, p);
507: }
508: }
509: return ary;
510: }
511:
512: #define VISI(x) ((x)&NOEX_MASK)
513: #define VISI_CHECK(x,f) (VISI(x) == (f))
514:
515: static int
516: ins_methods_push(ID name, long type, VALUE ary, long visi)
517: {
518: if (type == -1) return ST_CONTINUE;
519:
520: switch (visi) {
521: case NOEX_PRIVATE:
522: case NOEX_PROTECTED:
523: case NOEX_PUBLIC:
524: visi = (type == visi);
525: break;
526: default:
527: visi = (type != NOEX_PRIVATE);
528: break;
529: }
530: if (visi) {
531: rb_ary_push(ary, ID2SYM(name));
532: }
533: return ST_CONTINUE;
534: }
535:
536: static int
537: ins_methods_i(ID name, long type, VALUE ary)
538: {
539: return ins_methods_push(name, type, ary, -1);
540: }
541:
542: static int
543: ins_methods_prot_i(ID name, long type, VALUE ary)
544: {
545: return ins_methods_push(name, type, ary, NOEX_PROTECTED);
546: }
547:
548: static int
549: ins_methods_priv_i(ID name, long type, VALUE ary)
550: {
551: return ins_methods_push(name, type, ary, NOEX_PRIVATE);
552: }
553:
554: static int
555: ins_methods_pub_i(ID name, long type, VALUE ary)
556: {
557: return ins_methods_push(name, type, ary, NOEX_PUBLIC);
558: }
559:
560: static int
561: method_entry(ID key, NODE *body, st_table *list)
562: {
563: long type;
564:
565: if (key == ID_ALLOCATOR) {
566: return ST_CONTINUE;
567: }
568:
569: if (!st_lookup(list, key, 0)) {
570: if (body ==0 || !body->nd_body->nd_body) {
571: type = -1;
572: }
573: else {
574: type = VISI(body->nd_body->nd_noex);
575: }
576: st_add_direct(list, key, type);
577: }
578: return ST_CONTINUE;
579: }
580:
581: static VALUE
582: class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, long, VALUE))
583: {
584: VALUE ary;
585: int recur;
586: st_table *list;
587:
588: if (argc == 0) {
589: recur = Qtrue;
590: }
591: else {
592: VALUE r;
593: rb_scan_args(argc, argv, "01", &r);
594: recur = RTEST(r);
595: }
596:
597: list = st_init_numtable();
598: for (; mod; mod = RCLASS_SUPER(mod)) {
599: st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list);
600: if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
601: if (FL_TEST(mod, FL_SINGLETON)) continue;
602: if (!recur) break;
603: }
604: ary = rb_ary_new();
605: st_foreach(list, func, ary);
606: st_free_table(list);
607:
608: return ary;
609: }
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629:
630:
631:
632:
633:
634:
635:
636:
637:
638: <