Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1311 lines (1180 sloc) 31.031 kb
511dc44 initial import
Laurent Sansonetti authored
1 /* -*-c-*- */
2 /*
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
3 * This file is included by vm_eval.c
511dc44 initial import
Laurent Sansonetti authored
4 */
5
6 #define CACHE_SIZE 0x800
7 #define CACHE_MASK 0x7ff
8 #define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
9
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
10 static void rb_vm_check_redefinition_opt_method(const NODE *node);
11
12 static ID __send__, object_id;
13 static ID removed, singleton_removed, undefined, singleton_undefined;
14 static ID eqq, each, aref, aset, match, missing;
15 static ID added, singleton_added;
16
511dc44 initial import
Laurent Sansonetti authored
17 struct cache_entry { /* method hash table. */
18 ID mid; /* method's id */
19 ID mid0; /* method's original id */
20 VALUE klass; /* receiver's class */
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
21 VALUE oklass; /* original's class */
511dc44 initial import
Laurent Sansonetti authored
22 NODE *method;
23 };
24
25 static struct cache_entry cache[CACHE_SIZE];
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
26 #define ruby_running (GET_VM()->running)
27 /* int ruby_running = 0; */
9808f45 do not call method_added if enable_method_added is false (for better per...
Laurent Sansonetti authored
28 VALUE enable_method_added;
511dc44 initial import
Laurent Sansonetti authored
29
30 void
31 rb_clear_cache(void)
32 {
33 struct cache_entry *ent, *end;
34
35 rb_vm_change_state();
36
37 if (!ruby_running)
38 return;
39 ent = cache;
40 end = ent + CACHE_SIZE;
41 while (ent < end) {
42 ent->mid = 0;
43 ent++;
44 }
45 }
46
47 static void
48 rb_clear_cache_for_undef(VALUE klass, ID id)
49 {
50 struct cache_entry *ent, *end;
51
52 rb_vm_change_state();
53
54 if (!ruby_running)
55 return;
56 ent = cache;
57 end = ent + CACHE_SIZE;
58 while (ent < end) {
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
59 if (ent->oklass == klass && ent->mid == id) {
511dc44 initial import
Laurent Sansonetti authored
60 ent->mid = 0;
61 }
62 ent++;
63 }
64 }
65
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
66 #if !WITH_OBJC
511dc44 initial import
Laurent Sansonetti authored
67 static void
68 rb_clear_cache_by_id(ID id)
69 {
70 struct cache_entry *ent, *end;
71
72 rb_vm_change_state();
73
74 if (!ruby_running)
75 return;
76 ent = cache;
77 end = ent + CACHE_SIZE;
78 while (ent < end) {
79 if (ent->mid == id) {
80 ent->mid = 0;
81 }
82 ent++;
83 }
84 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
85 #endif
511dc44 initial import
Laurent Sansonetti authored
86
87 void
88 rb_clear_cache_by_class(VALUE klass)
89 {
90 struct cache_entry *ent, *end;
91
92 rb_vm_change_state();
93
94 if (!ruby_running)
95 return;
96 ent = cache;
97 end = ent + CACHE_SIZE;
98 while (ent < end) {
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
99 if (ent->klass == klass || ent->oklass == klass) {
511dc44 initial import
Laurent Sansonetti authored
100 ent->mid = 0;
101 }
102 ent++;
103 }
104 }
105
106 void
107 rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
108 {
109 NODE *body;
110
111 if (NIL_P(klass) || klass == 0) {
112 klass = rb_cObject;
113 }
114 if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
115 rb_raise(rb_eSecurityError, "Insecure: can't define method");
116 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
117 if (!RCLASS_SINGLETON(klass) &&
511dc44 initial import
Laurent Sansonetti authored
118 node && nd_type(node) != NODE_ZSUPER &&
119 (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
120 noex = NOEX_PRIVATE | noex;
121 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
122 else if (RCLASS_SINGLETON(klass) && node
511dc44 initial import
Laurent Sansonetti authored
123 && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
124 rb_warn
125 ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
126 rb_class2name(rb_iv_get(klass, "__attached__")));
127 mid = ID_ALLOCATOR;
128 }
129 if (OBJ_FROZEN(klass)) {
130 rb_error_frozen("class/module");
131 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
132 #if !WITH_OBJC
511dc44 initial import
Laurent Sansonetti authored
133 rb_clear_cache_by_id(mid);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
134 #endif
511dc44 initial import
Laurent Sansonetti authored
135
136 /*
137 * NODE_METHOD (NEW_METHOD(body, klass, vis)):
138 * nd_body : method body // (2) // mark
139 * nd_clss : klass // (1) // mark
140 * nd_noex : visibility // (3)
141 *
142 * NODE_FBODY (NEW_FBODY(method, alias)):
143 * nd_body : method (NODE_METHOD) // (2) // mark
144 * nd_oid : original id // (1)
145 * nd_cnt : alias count // (3)
146 */
147 if (node) {
148 body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
149 }
150 else {
151 body = 0;
152 }
153
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
154 #if !WITH_OBJC // TODO
511dc44 initial import
Laurent Sansonetti authored
155 {
156 /* check re-definition */
157 st_data_t data;
158 NODE *old_node;
159
160 if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
161 old_node = (NODE *)data;
162 if (old_node) {
163 if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
164 rb_vm_check_redefinition_opt_method(old_node);
165 }
166 if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
167 rb_warning("method redefined; discarding old %s", rb_id2name(mid));
168 }
169 }
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
170 }
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
171 if (klass == rb_cObject && node && mid == idInitialize) {
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
172 rb_warn("redefining Object#initialize may cause infinite loop");
511dc44 initial import
Laurent Sansonetti authored
173 }
174
175 if (mid == object_id || mid == __send__) {
176 if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
177 rb_warn("redefining `%s' may cause serious problem",
178 rb_id2name(mid));
179 }
180 }
181 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
182 #endif
511dc44 initial import
Laurent Sansonetti authored
183
184 #if WITH_OBJC
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
185 rb_objc_register_ruby_method(klass, mid, body != NULL ? body->nd_body : NULL);
186 #else
187 st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
511dc44 initial import
Laurent Sansonetti authored
188 #endif
189
9808f45 do not call method_added if enable_method_added is false (for better per...
Laurent Sansonetti authored
190 if (node && mid != ID_ALLOCATOR && ruby_running && enable_method_added == Qtrue) {
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
191 if (RCLASS_SINGLETON(klass)) {
511dc44 initial import
Laurent Sansonetti authored
192 rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
193 ID2SYM(mid));
194 }
195 else {
196 rb_funcall(klass, added, 1, ID2SYM(mid));
197 }
198 }
199 }
200
201 void
202 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
203 {
204 Check_Type(klass, T_CLASS);
205 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
206 NOEX_PUBLIC);
511dc44 initial import
Laurent Sansonetti authored
207 }
208
209 void
210 rb_undef_alloc_func(VALUE klass)
211 {
212 Check_Type(klass, T_CLASS);
213 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
214 }
215
216 rb_alloc_func_t
217 rb_get_alloc_func(VALUE klass)
218 {
219 NODE *n;
220 Check_Type(klass, T_CLASS);
221 n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
222 if (!n) return 0;
223 if (nd_type(n) != NODE_METHOD) return 0;
224 n = n->nd_body;
225 if (nd_type(n) != NODE_CFUNC) return 0;
226 return (rb_alloc_func_t)n->nd_cfnc;
227 }
228
229 static NODE *
230 search_method(VALUE klass, ID id, VALUE *klassp)
231 {
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
232 #if WITH_OBJC
233 NODE *node;
234 if (klass == 0)
235 return NULL;
236 node = rb_method_node(klass, id);
237 if (node != NULL) {
238 if (klassp != NULL) /* TODO honour klassp */
239 *klassp = klass;
240 }
241 return node;
242 #else
511dc44 initial import
Laurent Sansonetti authored
243 st_data_t body;
244
245 if (!klass) {
246 return 0;
247 }
248
249 while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
250 klass = RCLASS_SUPER(klass);
251 if (!klass)
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
252 return 0;
511dc44 initial import
Laurent Sansonetti authored
253 }
254
255 if (klassp) {
256 *klassp = klass;
257 }
258
259 return (NODE *)body;
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
260 #endif
511dc44 initial import
Laurent Sansonetti authored
261 }
262
263 /*
264 * search method body (NODE_METHOD)
265 * with : klass and id
266 * without : method cache
267 *
268 * if you need method node with method cache, use
269 * rb_method_node()
270 */
271 NODE *
272 rb_get_method_body(VALUE klass, ID id, ID *idp)
273 {
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
274 #if WITH_OBJC
275 return search_method(klass, id, NULL);
276 #else
511dc44 initial import
Laurent Sansonetti authored
277 NODE *volatile fbody, *body;
278 NODE *method;
279
280 if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
281 /* store empty info in cache */
282 struct cache_entry *ent;
283 ent = cache + EXPR1(klass, id);
284 ent->klass = klass;
285 ent->mid = ent->mid0 = id;
286 ent->method = 0;
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
287 ent->oklass = 0;
511dc44 initial import
Laurent Sansonetti authored
288 return 0;
289 }
290
291 method = fbody->nd_body;
292
293 if (ruby_running) {
294 /* store in cache */
295 struct cache_entry *ent;
296 ent = cache + EXPR1(klass, id);
297 ent->klass = klass;
298 ent->mid = id;
299 ent->mid0 = fbody->nd_oid;
300 ent->method = body = method;
d31a74f synchronized with ruby trunk r15665
Laurent Sansonetti authored
301 ent->oklass = method->nd_clss;
511dc44 initial import
Laurent Sansonetti authored
302 }
303 else {
304 body = method;
305 }
306
307 if (idp) {
308 *idp = fbody->nd_oid;
309 }
310
311 return body;
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
312 #endif
511dc44 initial import
Laurent Sansonetti authored
313 }
314
315 NODE *
316 rb_method_node(VALUE klass, ID id)
317 {
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
318 #if WITH_OBJC
319 NODE *node = rb_objc_method_node(klass, id, NULL, NULL);
320 if (node == NULL && id != ID_ALLOCATOR) {
321 const char *id_str = rb_id2name(id);
322 size_t slen = strlen(id_str);
323
324 if (strcmp(id_str, "retain") == 0
325 || strcmp(id_str, "release") == 0
326 || strcmp(id_str, "zone") == 0) {
327 char buf[100];
328 snprintf(buf, sizeof buf, "__rb_%s__", id_str);
329 return rb_method_node(klass, rb_intern(buf));
330 }
331 else {
332 if (id_str[slen - 1] == ':') {
333 return NULL;
334 }
335 else {
336 char buf[100];
337 snprintf(buf, sizeof buf, "%s:", id_str);
338 return rb_method_node(klass, rb_intern(buf));
339 }
340 }
341 }
342 return node;
343 #else
511dc44 initial import
Laurent Sansonetti authored
344 struct cache_entry *ent;
345
346 ent = cache + EXPR1(klass, id);
347 if (ent->mid == id && ent->klass == klass && ent->method) {
348 return ent->method;
349 }
350
351 return rb_get_method_body(klass, id, 0);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
352 #endif
511dc44 initial import
Laurent Sansonetti authored
353 }
354
355 static void
356 remove_method(VALUE klass, ID mid)
357 {
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
358 #if !WITH_OBJC
511dc44 initial import
Laurent Sansonetti authored
359 st_data_t data;
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
360 #endif
511dc44 initial import
Laurent Sansonetti authored
361 NODE *body = 0;
362
363 if (klass == rb_cObject) {
364 rb_secure(4);
365 }
366 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
367 rb_raise(rb_eSecurityError, "Insecure: can't remove method");
368 }
369 if (OBJ_FROZEN(klass))
370 rb_error_frozen("class/module");
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
371 if (mid == object_id || mid == __send__ || mid == idInitialize) {
511dc44 initial import
Laurent Sansonetti authored
372 rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
373 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
374 #if WITH_OBJC
f8ce513 implement #remove_method
Laurent Sansonetti authored
375 SEL sel;
376 Method m;
377
378 sel = sel_registerName(rb_id2name(mid));
379 m = class_getInstanceMethod((Class)klass, sel);
380 if (m == NULL) {
381 char buf[100];
382 size_t len = strlen((char *)sel);
383 if (((char *)sel)[len - 1] != ':') {
384 snprintf(buf, sizeof buf, "%s:", (char *)sel);
385 sel = sel_registerName(buf);
386 m = class_getInstanceMethod((Class)klass, sel);
387 }
388 }
389 if (m == NULL) {
390 rb_name_error(mid, "method `%s' not defined in %s",
391 rb_id2name(mid), rb_class2name(klass));
392 }
393 if (rb_objc_method_node3(method_getImplementation(m)) == NULL) {
394 rb_warn("removing pure Objective-C method `%s' may cause serious problem", rb_id2name(mid));
395 }
396 method_setImplementation(m, NULL);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
397 #else
511dc44 initial import
Laurent Sansonetti authored
398 if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
399 body = (NODE *)data;
400 if (!body || !body->nd_body) body = 0;
401 else {
402 st_delete(RCLASS_M_TBL(klass), &mid, &data);
403 }
404 }
405 if (!body) {
406 rb_name_error(mid, "method `%s' not defined in %s",
407 rb_id2name(mid), rb_class2name(klass));
408 }
f8ce513 implement #remove_method
Laurent Sansonetti authored
409 #endif
511dc44 initial import
Laurent Sansonetti authored
410
411 if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
412 rb_vm_check_redefinition_opt_method(body);
413 }
414
415 rb_clear_cache_for_undef(klass, mid);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
416 if (RCLASS_SINGLETON(klass)) {
511dc44 initial import
Laurent Sansonetti authored
417 rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
418 ID2SYM(mid));
419 }
420 else {
421 rb_funcall(klass, removed, 1, ID2SYM(mid));
422 }
423 }
424
425 void
426 rb_remove_method(VALUE klass, const char *name)
427 {
428 remove_method(klass, rb_intern(name));
429 }
430
431 /*
432 * call-seq:
433 * remove_method(symbol) => self
434 *
435 * Removes the method identified by _symbol_ from the current
436 * class. For an example, see <code>Module.undef_method</code>.
437 */
438
439 static VALUE
440 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
441 {
442 int i;
443
444 for (i = 0; i < argc; i++) {
445 remove_method(mod, rb_to_id(argv[i]));
446 }
447 return mod;
448 }
449
450 #undef rb_disable_super
451 #undef rb_enable_super
452
453 void
454 rb_disable_super(VALUE klass, const char *name)
455 {
456 /* obsolete - no use */
457 }
458
459 void
460 rb_enable_super(VALUE klass, const char *name)
461 {
462 rb_warning("rb_enable_super() is obsolete");
463 }
464
465 static void
466 rb_export_method(VALUE klass, ID name, ID noex)
467 {
468 NODE *fbody;
469 VALUE origin;
470
471 if (klass == rb_cObject) {
472 rb_secure(4);
473 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
474 #if WITH_OBJC
475 fbody = rb_method_node(klass, name);
476 if (fbody == NULL && TYPE(klass) == T_MODULE) {
477 fbody = rb_method_node(rb_cObject, name);
478 origin = rb_method_node(rb_cObject, name) == fbody
479 ? rb_cObject : klass;
480 }
481 else {
d5d7d5e fixed a bug when trying to change a Kernel method visibility
Laurent Sansonetti authored
482 if (klass == rb_mKernel) {
483 // This is a special case, since Kernel inherits of NSObject, and that
484 // Kernel is mixed into NSObject.
485 origin = rb_mKernel;
486 }
487 else {
488 origin = rb_method_node(RCLASS_SUPER(klass), name) == fbody
489 ? RCLASS_SUPER(klass) : klass;
490 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
491 }
492 if (fbody == NULL) {
493 rb_print_undef(klass, name, 0);
494 }
495 if (fbody->nd_noex != noex) {
496 if (nd_type(fbody->nd_body) == NODE_CFUNC) {
497 rb_vm_check_redefinition_opt_method(fbody);
498 }
499 if (klass == origin) {
500 fbody->nd_noex = noex;
501 }
502 else {
503 rb_add_method(klass, name, NEW_ZSUPER(), noex);
504 }
505 }
506 #else
511dc44 initial import
Laurent Sansonetti authored
507 fbody = search_method(klass, name, &origin);
508 if (!fbody && TYPE(klass) == T_MODULE) {
509 fbody = search_method(rb_cObject, name, &origin);
510 }
511 if (!fbody || !fbody->nd_body) {
512 rb_print_undef(klass, name, 0);
513 }
514 if (fbody->nd_body->nd_noex != noex) {
515 if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) {
516 rb_vm_check_redefinition_opt_method(fbody);
517 }
518 if (klass == origin) {
519 fbody->nd_body->nd_noex = noex;
520 }
521 else {
522 rb_add_method(klass, name, NEW_ZSUPER(), noex);
523 }
524 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
525 #endif
511dc44 initial import
Laurent Sansonetti authored
526 }
527
528 int
529 rb_method_boundp(VALUE klass, ID id, int ex)
530 {
531 NODE *method;
532
533 if ((method = rb_method_node(klass, id)) != 0) {
534 if (ex && (method->nd_noex & NOEX_PRIVATE)) {
535 return Qfalse;
536 }
537 return Qtrue;
538 }
539 return Qfalse;
540 }
541
542 void
543 rb_attr(VALUE klass, ID id, int read, int write, int ex)
544 {
545 const char *name;
546 ID attriv;
547 int noex;
548
549 if (!ex) {
550 noex = NOEX_PUBLIC;
551 }
552 else {
553 if (SCOPE_TEST(NOEX_PRIVATE)) {
554 noex = NOEX_PRIVATE;
555 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
556 "attribute accessor as module_function" :
557 "private attribute?");
558 }
559 else if (SCOPE_TEST(NOEX_PROTECTED)) {
560 noex = NOEX_PROTECTED;
561 }
562 else {
563 noex = NOEX_PUBLIC;
564 }
565 }
566
567 if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
568 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
569 }
570 name = rb_id2name(id);
571 if (!name) {
572 rb_raise(rb_eArgError, "argument needs to be symbol or string");
573 }
574 attriv = rb_intern_str(rb_sprintf("@%s", name));
575 if (read) {
576 rb_add_method(klass, id, NEW_IVAR(attriv), noex);
577 }
578 if (write) {
579 rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
510f2e9 fix for #40
Laurent Sansonetti authored
580 #if WITH_OBJC
581 rb_objc_define_kvo_setter(klass, id);
582 #endif
511dc44 initial import
Laurent Sansonetti authored
583 }
584 }
585
586 void
587 rb_undef(VALUE klass, ID id)
588 {
589 VALUE origin;
590 NODE *body;
591
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
592 if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
511dc44 initial import
Laurent Sansonetti authored
593 rb_secure(4);
594 }
595 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
596 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
597 rb_id2name(id));
598 }
599 rb_frozen_class_p(klass);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
600 if (id == object_id || id == __send__ || id == idInitialize) {
511dc44 initial import
Laurent Sansonetti authored
601 rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
602 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
603 /* TODO: warn if a very important method of NSObject is undefined
604 * by default, pure objc methods are not exposed by introspections API
605 */
511dc44 initial import
Laurent Sansonetti authored
606 body = search_method(klass, id, &origin);
607 if (!body || !body->nd_body) {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
608 const char *s0 = " class";
511dc44 initial import
Laurent Sansonetti authored
609 VALUE c = klass;
610
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
611 if (RCLASS_SINGLETON(c)) {
511dc44 initial import
Laurent Sansonetti authored
612 VALUE obj = rb_iv_get(klass, "__attached__");
613
614 switch (TYPE(obj)) {
615 case T_MODULE:
616 case T_CLASS:
617 c = obj;
618 s0 = "";
619 }
620 }
621 else if (TYPE(c) == T_MODULE) {
622 s0 = " module";
623 }
624 rb_name_error(id, "undefined method `%s' for%s `%s'",
625 rb_id2name(id), s0, rb_class2name(c));
626 }
627
628 rb_add_method(klass, id, 0, NOEX_PUBLIC);
629
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
630 if (RCLASS_SINGLETON(klass)) {
511dc44 initial import
Laurent Sansonetti authored
631 rb_funcall(rb_iv_get(klass, "__attached__"),
632 singleton_undefined, 1, ID2SYM(id));
633 }
634 else {
635 rb_funcall(klass, undefined, 1, ID2SYM(id));
636 }
637 }
638
639 /*
640 * call-seq:
641 * undef_method(symbol) => self
642 *
643 * Prevents the current class from responding to calls to the named
644 * method. Contrast this with <code>remove_method</code>, which deletes
645 * the method from the particular class; Ruby will still search
646 * superclasses and mixed-in modules for a possible receiver.
647 *
648 * class Parent
649 * def hello
650 * puts "In parent"
651 * end
652 * end
653 * class Child < Parent
654 * def hello
655 * puts "In child"
656 * end
657 * end
658 *
659 *
660 * c = Child.new
661 * c.hello
662 *
663 *
664 * class Child
665 * remove_method :hello # remove from child, still in parent
666 * end
667 * c.hello
668 *
669 *
670 * class Child
671 * undef_method :hello # prevent any calls to 'hello'
672 * end
673 * c.hello
674 *
675 * <em>produces:</em>
676 *
677 * In child
678 * In parent
679 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
680 */
681
682 static VALUE
683 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
684 {
685 int i;
686 for (i = 0; i < argc; i++) {
687 rb_undef(mod, rb_to_id(argv[i]));
688 }
689 return mod;
690 }
691
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
692 /*
693 * call-seq:
694 * mod.method_defined?(symbol) => true or false
695 *
696 * Returns +true+ if the named method is defined by
697 * _mod_ (or its included modules and, if _mod_ is a class,
698 * its ancestors). Public and protected methods are matched.
699 *
700 * module A
701 * def method1() end
702 * end
703 * class B
704 * def method2() end
705 * end
706 * class C < B
707 * include A
708 * def method3() end
709 * end
710 *
711 * A.method_defined? :method1 #=> true
712 * C.method_defined? "method1" #=> true
713 * C.method_defined? "method2" #=> true
714 * C.method_defined? "method3" #=> true
715 * C.method_defined? "method4" #=> false
716 */
717
718 static VALUE
719 rb_mod_method_defined(VALUE mod, VALUE mid)
720 {
721 return rb_method_boundp(mod, rb_to_id(mid), 1);
722 }
723
724 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
725
726 /*
727 * call-seq:
728 * mod.public_method_defined?(symbol) => true or false
729 *
730 * Returns +true+ if the named public method is defined by
731 * _mod_ (or its included modules and, if _mod_ is a class,
732 * its ancestors).
733 *
734 * module A
735 * def method1() end
736 * end
737 * class B
738 * protected
739 * def method2() end
740 * end
741 * class C < B
742 * include A
743 * def method3() end
744 * end
745 *
746 * A.method_defined? :method1 #=> true
747 * C.public_method_defined? "method1" #=> true
748 * C.public_method_defined? "method2" #=> false
749 * C.method_defined? "method2" #=> true
750 */
751
752 static VALUE
753 rb_mod_public_method_defined(VALUE mod, VALUE mid)
754 {
755 ID id = rb_to_id(mid);
756 NODE *method;
757
758 method = rb_method_node(mod, id);
759 if (method) {
760 if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
761 return Qtrue;
762 }
763 return Qfalse;
764 }
765
766 /*
767 * call-seq:
768 * mod.private_method_defined?(symbol) => true or false
769 *
770 * Returns +true+ if the named private method is defined by
771 * _ mod_ (or its included modules and, if _mod_ is a class,
772 * its ancestors).
773 *
774 * module A
775 * def method1() end
776 * end
777 * class B
778 * private
779 * def method2() end
780 * end
781 * class C < B
782 * include A
783 * def method3() end
784 * end
785 *
786 * A.method_defined? :method1 #=> true
787 * C.private_method_defined? "method1" #=> false
788 * C.private_method_defined? "method2" #=> true
789 * C.method_defined? "method2" #=> false
790 */
791
792 static VALUE
793 rb_mod_private_method_defined(VALUE mod, VALUE mid)
794 {
795 ID id = rb_to_id(mid);
796 NODE *method;
797
798 method = rb_method_node(mod, id);
799 if (method) {
800 if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
801 return Qtrue;
802 }
803 return Qfalse;
804 }
805
806 /*
807 * call-seq:
808 * mod.protected_method_defined?(symbol) => true or false
809 *
810 * Returns +true+ if the named protected method is defined
811 * by _mod_ (or its included modules and, if _mod_ is a
812 * class, its ancestors).
813 *
814 * module A
815 * def method1() end
816 * end
817 * class B
818 * protected
819 * def method2() end
820 * end
821 * class C < B
822 * include A
823 * def method3() end
824 * end
825 *
826 * A.method_defined? :method1 #=> true
827 * C.protected_method_defined? "method1" #=> false
828 * C.protected_method_defined? "method2" #=> true
829 * C.method_defined? "method2" #=> true
830 */
831
832 static VALUE
833 rb_mod_protected_method_defined(VALUE mod, VALUE mid)
834 {
835 ID id = rb_to_id(mid);
836 NODE *method;
837
838 method = rb_method_node(mod, id);
839 if (method) {
840 if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
841 return Qtrue;
842 }
843 return Qfalse;
844 }
845
511dc44 initial import
Laurent Sansonetti authored
846 void
847 rb_alias(VALUE klass, ID name, ID def)
848 {
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
849 #if !WITH_OBJC
511dc44 initial import
Laurent Sansonetti authored
850 NODE *orig_fbody, *node;
851 st_data_t data;
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
852 #endif
853 VALUE singleton = 0;
511dc44 initial import
Laurent Sansonetti authored
854
855 rb_frozen_class_p(klass);
856 if (klass == rb_cObject) {
857 rb_secure(4);
858 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
859 #if WITH_OBJC
860 if (RCLASS_SINGLETON(klass)) {
861 singleton = rb_iv_get(klass, "__attached__");
862 }
863 rb_objc_alias(klass, name, def);
864 #else
511dc44 initial import
Laurent Sansonetti authored
865 orig_fbody = search_method(klass, def, 0);
866 if (!orig_fbody || !orig_fbody->nd_body) {
867 if (TYPE(klass) == T_MODULE) {
868 orig_fbody = search_method(rb_cObject, def, 0);
869 }
870 }
871 if (!orig_fbody || !orig_fbody->nd_body) {
872 rb_print_undef(klass, def, 0);
873 }
874 if (FL_TEST(klass, FL_SINGLETON)) {
875 singleton = rb_iv_get(klass, "__attached__");
876 }
877
878 orig_fbody->nd_cnt++;
879
880 if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
881 node = (NODE *)data;
882 if (node) {
883 if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
884 rb_warning("discarding old %s", rb_id2name(name));
885 }
886 if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
887 rb_vm_check_redefinition_opt_method(node);
888 }
889 }
890 }
891
892 st_insert(RCLASS_M_TBL(klass), name,
893 (st_data_t) NEW_FBODY(
894 NEW_METHOD(orig_fbody->nd_body->nd_body,
895 orig_fbody->nd_body->nd_clss,
896 NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
897
898 rb_clear_cache_by_id(name);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
899 #endif
511dc44 initial import
Laurent Sansonetti authored
900
901 if (!ruby_running) return;
902
903 if (singleton) {
904 rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
905 }
906 else {
907 rb_funcall(klass, added, 1, ID2SYM(name));
908 }
909 }
910
911 /*
912 * call-seq:
913 * alias_method(new_name, old_name) => self
914 *
915 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
916 * be used to retain access to methods that are overridden.
917 *
918 * module Mod
919 * alias_method :orig_exit, :exit
920 * def exit(code=0)
921 * puts "Exiting with code #{code}"
922 * orig_exit(code)
923 * end
924 * end
925 * include Mod
926 * exit(99)
927 *
928 * <em>produces:</em>
929 *
930 * Exiting with code 99
931 */
932
933 static VALUE
934 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
935 {
936 rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
937 return mod;
938 }
939
940 static void
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
941 secure_visibility(VALUE self)
942 {
943 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
944 rb_raise(rb_eSecurityError,
945 "Insecure: can't change method visibility");
946 }
947 }
948
949 static void
950 set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
951 {
952 int i;
953 secure_visibility(self);
954 for (i = 0; i < argc; i++) {
955 rb_export_method(self, rb_to_id(argv[i]), ex);
956 }
957 rb_clear_cache_by_class(self);
958 }
959
960 /*
961 * call-seq:
962 * public => self
963 * public(symbol, ...) => self
964 *
965 * With no arguments, sets the default visibility for subsequently
966 * defined methods to public. With arguments, sets the named methods to
967 * have public visibility.
968 */
969
970 static VALUE
971 rb_mod_public(int argc, VALUE *argv, VALUE module)
972 {
973 secure_visibility(module);
974 if (argc == 0) {
975 SCOPE_SET(NOEX_PUBLIC);
976 }
977 else {
978 set_method_visibility(module, argc, argv, NOEX_PUBLIC);
979 }
980 return module;
981 }
982
983 /*
984 * call-seq:
985 * protected => self
986 * protected(symbol, ...) => self
987 *
988 * With no arguments, sets the default visibility for subsequently
989 * defined methods to protected. With arguments, sets the named methods
990 * to have protected visibility.
991 */
992
993 static VALUE
994 rb_mod_protected(int argc, VALUE *argv, VALUE module)
995 {
996 secure_visibility(module);
997 if (argc == 0) {
998 SCOPE_SET(NOEX_PROTECTED);
999 }
1000 else {
1001 set_method_visibility(module, argc, argv, NOEX_PROTECTED);
1002 }
1003 return module;
1004 }
1005
1006 /*
1007 * call-seq:
1008 * private => self
1009 * private(symbol, ...) => self
1010 *
1011 * With no arguments, sets the default visibility for subsequently
1012 * defined methods to private. With arguments, sets the named methods
1013 * to have private visibility.
1014 *
1015 * module Mod
1016 * def a() end
1017 * def b() end
1018 * private
1019 * def c() end
1020 * private :a
1021 * end
1022 * Mod.private_instance_methods #=> [:a, :c]
1023 */
1024
1025 static VALUE
1026 rb_mod_private(int argc, VALUE *argv, VALUE module)
1027 {
1028 secure_visibility(module);
1029 if (argc == 0) {
1030 SCOPE_SET(NOEX_PRIVATE);
1031 }
1032 else {
1033 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
1034 }
1035 return module;
1036 }
1037
1038 /*
1039 * call-seq:
1040 * mod.public_class_method(symbol, ...) => mod
1041 *
1042 * Makes a list of existing class methods public.
1043 */
1044
1045 static VALUE
1046 rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
1047 {
1048 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
1049 return obj;
1050 }
1051
1052 /*
1053 * call-seq:
1054 * mod.private_class_method(symbol, ...) => mod
1055 *
1056 * Makes existing class methods private. Often used to hide the default
1057 * constructor <code>new</code>.
1058 *
1059 * class SimpleSingleton # Not thread safe
1060 * private_class_method :new
1061 * def SimpleSingleton.create(*args, &block)
1062 * @me = new(*args, &block) if ! @me
1063 * @me
1064 * end
1065 * end
1066 */
1067
1068 static VALUE
1069 rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
1070 {
1071 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
1072 return obj;
1073 }
1074
1075 /*
1076 * call-seq:
1077 * public
1078 * public(symbol, ...)
1079 *
1080 * With no arguments, sets the default visibility for subsequently
1081 * defined methods to public. With arguments, sets the named methods to
1082 * have public visibility.
1083 */
1084
1085 static VALUE
1086 top_public(int argc, VALUE *argv)
1087 {
1088 return rb_mod_public(argc, argv, rb_cObject);
1089 }
1090
1091 static VALUE
1092 top_private(int argc, VALUE *argv)
1093 {
1094 return rb_mod_private(argc, argv, rb_cObject);
1095 }
1096
1097 /*
1098 * call-seq:
1099 * module_function(symbol, ...) => self
1100 *
1101 * Creates module functions for the named methods. These functions may
1102 * be called with the module as a receiver, and also become available
1103 * as instance methods to classes that mix in the module. Module
1104 * functions are copies of the original, and so may be changed
1105 * independently. The instance-method versions are made private. If
1106 * used with no arguments, subsequently defined methods become module
1107 * functions.
1108 *
1109 * module Mod
1110 * def one
1111 * "This is one"
1112 * end
1113 * module_function :one
1114 * end
1115 * class Cls
1116 * include Mod
1117 * def callOne
1118 * one
1119 * end
1120 * end
1121 * Mod.one #=> "This is one"
1122 * c = Cls.new
1123 * c.callOne #=> "This is one"
1124 * module Mod
1125 * def one
1126 * "This is the new one"
1127 * end
1128 * end
1129 * Mod.one #=> "This is one"
1130 * c.callOne #=> "This is the new one"
1131 */
1132
1133 static VALUE
1134 rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
1135 {
1136 int i;
1137 ID id;
1138 NODE *fbody;
1139
1140 if (TYPE(module) != T_MODULE) {
1141 rb_raise(rb_eTypeError, "module_function must be called for modules");
1142 }
1143
1144 secure_visibility(module);
1145 if (argc == 0) {
1146 SCOPE_SET(NOEX_MODFUNC);
1147 return module;
1148 }
1149
1150 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
1151
1152 for (i = 0; i < argc; i++) {
1153 VALUE m = module;
1154
1155 id = rb_to_id(argv[i]);
1156 for (;;) {
1157 fbody = search_method(m, id, &m);
1158 if (fbody == 0) {
1159 fbody = search_method(rb_cObject, id, &m);
1160 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
1161 #if WITH_OBJC
1162 if (fbody == 0) {
1163 rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
1164 }
1165 if (nd_type(fbody->nd_body) != NODE_ZSUPER) {
1166 break; /* normal case: need not to follow 'super' link */
1167 }
1168 #else
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1169 if (fbody == 0 || fbody->nd_body == 0) {
1170 rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
1171 }
1172 if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
1173 break; /* normal case: need not to follow 'super' link */
1174 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
1175 #endif
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1176 m = RCLASS_SUPER(m);
1177 if (!m)
1178 break;
1179 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
1180 #if WITH_OBJC
1181 rb_add_method(rb_singleton_class(module), id, fbody->nd_body,
1182 NOEX_PUBLIC);
1183 #else
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1184 rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
1185 NOEX_PUBLIC);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
1186 #endif
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1187 }
1188 return module;
1189 }
1190
1191 /*
1192 * call-seq:
1193 * obj.respond_to?(symbol, include_private=false) => true or false
1194 *
1195 * Returns +true+> if _obj_ responds to the given
1196 * method. Private methods are included in the search only if the
1197 * optional second parameter evaluates to +true+.
1198 */
1199
1200 static NODE *basic_respond_to = 0;
1201
1202 int
1203 rb_obj_respond_to(VALUE obj, ID id, int priv)
1204 {
1205 VALUE klass = CLASS_OF(obj);
0e19798 passing more tests
Laurent Sansonetti authored
1206 #if WITH_OBJC
1207 IMP imp;
1208 static SEL sel_respondTo = 0;
1209 if (sel_respondTo == 0)
1210 sel_respondTo = sel_registerName("respond_to?:");
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1211
0e19798 passing more tests
Laurent Sansonetti authored
1212 if (rb_objc_method_node2(klass, sel_respondTo, NULL) == basic_respond_to) {
dc79458 fixed respond_to? to respond to objc methods, also honor the priv argume...
Laurent Sansonetti authored
1213 NODE *method;
1214
1215 method = rb_objc_method_node(klass, id, &imp, NULL);
1216 if (method != NULL && priv == 0 && (method->nd_noex & NOEX_PRIVATE))
1217 return false;
0e19798 passing more tests
Laurent Sansonetti authored
1218 return imp != NULL;
1219 }
1220 #else
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1221 if (rb_method_node(klass, idRespond_to) == basic_respond_to) {
1222 return rb_method_boundp(klass, id, !priv);
1223 }
0e19798 passing more tests
Laurent Sansonetti authored
1224 #endif
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1225 else {
1226 VALUE args[2];
1227 int n = 0;
1228 args[n++] = ID2SYM(id);
1229 if (priv)
1230 args[n++] = Qtrue;
1231 return RTEST(rb_funcall2(obj, idRespond_to, n, args));
1232 }
1233 }
1234
1235 int
1236 rb_respond_to(VALUE obj, ID id)
1237 {
1238 return rb_obj_respond_to(obj, id, Qfalse);
1239 }
1240
1241 /*
1242 * call-seq:
1243 * obj.respond_to?(symbol, include_private=false) => true or false
1244 *
1245 * Returns +true+> if _obj_ responds to the given
1246 * method. Private methods are included in the search only if the
1247 * optional second parameter evaluates to +true+.
1248 */
1249
1250 static VALUE
1251 obj_respond_to(int argc, VALUE *argv, VALUE obj)
1252 {
1253 VALUE mid, priv;
1254 ID id;
1255
1256 rb_scan_args(argc, argv, "11", &mid, &priv);
1257 id = rb_to_id(mid);
dc79458 fixed respond_to? to respond to objc methods, also honor the priv argume...
Laurent Sansonetti authored
1258 #if WITH_OBJC
1259 return rb_obj_respond_to(obj, id, RTEST(priv)) ? Qtrue : Qfalse;
1260 #else
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1261 if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
1262 return Qtrue;
1263 }
dc79458 fixed respond_to? to respond to objc methods, also honor the priv argume...
Laurent Sansonetti authored
1264 #endif
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1265 return Qfalse;
1266 }
1267
1268 void
511dc44 initial import
Laurent Sansonetti authored
1269 Init_eval_method(void)
1270 {
9808f45 do not call method_added if enable_method_added is false (for better per...
Laurent Sansonetti authored
1271 enable_method_added = Qtrue;
1272
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1273 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
1274 basic_respond_to = rb_method_node(rb_cObject, idRespond_to);
1275 rb_register_mark_object((VALUE)basic_respond_to);
1276
511dc44 initial import
Laurent Sansonetti authored
1277 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
1278 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
1279 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1280 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
1281 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
1282 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
1283 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
1284
1285 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
1286 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
1287 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
1288 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
1289 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
1290 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
1291
1292 rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
1293 rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);
1294
1295 object_id = rb_intern("object_id");
1296 __send__ = rb_intern("__send__");
1297 eqq = rb_intern("===");
1298 each = rb_intern("each");
1299 aref = rb_intern("[]");
1300 aset = rb_intern("[]=");
1301 match = rb_intern("=~");
1302 missing = rb_intern("method_missing");
1303 added = rb_intern("method_added");
1304 singleton_added = rb_intern("singleton_method_added");
1305 removed = rb_intern("method_removed");
1306 singleton_removed = rb_intern("singleton_method_removed");
1307 undefined = rb_intern("method_undefined");
1308 singleton_undefined = rb_intern("singleton_method_undefined");
511dc44 initial import
Laurent Sansonetti authored
1309 }
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1310
Something went wrong with that request. Please try again.