Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 830 lines (745 sloc) 20.427 kb
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1 /* -*-c-*- */
2 /*
3 * This file is included by vm_eval.c
4 */
5
6 static ID __send__, object_id;
7 static ID removed, singleton_removed, undefined, singleton_undefined;
8 static ID eqq, each, aref, aset, match, missing;
9 static ID added, singleton_added;
10
11 void
12 rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
13 {
14 // TODO
15 return;
16 }
17
18 void
19 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
20 {
21 // TODO
22 #if 0
23 Check_Type(klass, T_CLASS);
24 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
25 NOEX_PUBLIC);
26 #endif
27 }
28
29 void
30 rb_undef_alloc_func(VALUE klass)
31 {
32 // TODO
33 #if 0
34 Check_Type(klass, T_CLASS);
35 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
36 #endif
37 }
38
39 rb_alloc_func_t
40 rb_get_alloc_func(VALUE klass)
41 {
42 NODE *n;
43 Check_Type(klass, T_CLASS);
44 n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
45 if (!n) return 0;
46 if (nd_type(n) != NODE_METHOD) return 0;
47 n = n->nd_body;
48 if (nd_type(n) != NODE_CFUNC) return 0;
49 return (rb_alloc_func_t)n->nd_cfnc;
50 }
51
52 static NODE *
53 search_method(VALUE klass, ID id, VALUE *klassp)
54 {
55 NODE *node;
56 if (klass == 0) {
57 return NULL;
58 }
59 node = rb_method_node(klass, id);
60 if (node != NULL) {
61 if (klassp != NULL) { /* TODO honour klassp */
62 *klassp = klass;
63 }
64 }
65 return node;
66 }
67
68 /*
69 * search method body (NODE_METHOD)
70 * with : klass and id
71 * without : method cache
72 *
73 * if you need method node with method cache, use
74 * rb_method_node()
75 */
76 NODE *
77 rb_get_method_body(VALUE klass, ID id, ID *idp)
78 {
79 return search_method(klass, id, NULL);
80 }
81
82 NODE *
83 rb_method_node(VALUE klass, ID id)
84 {
3c2c617 disable rb_method_node() for now because it's wrongly implemented
Laurent Sansonetti authored
85 return NULL;
86 #if 0 // TODO
9c1d230 committing experimental branch content
Laurent Sansonetti authored
87 NODE *node = rb_objc_method_node(klass, id, NULL, NULL);
88 if (node == NULL && id != ID_ALLOCATOR) {
89 const char *id_str = rb_id2name(id);
90 size_t slen = strlen(id_str);
91
92 if (strcmp(id_str, "retain") == 0
93 || strcmp(id_str, "release") == 0
94 || strcmp(id_str, "zone") == 0) {
95 char buf[100];
96 snprintf(buf, sizeof buf, "__rb_%s__", id_str);
97 return rb_method_node(klass, rb_intern(buf));
98 }
99 else {
100 if (id_str[slen - 1] == ':') {
101 return NULL;
102 }
103 else {
104 char buf[100];
105 snprintf(buf, sizeof buf, "%s:", id_str);
106 return rb_method_node(klass, rb_intern(buf));
107 }
108 }
109 }
110 return node;
3c2c617 disable rb_method_node() for now because it's wrongly implemented
Laurent Sansonetti authored
111 #endif
9c1d230 committing experimental branch content
Laurent Sansonetti authored
112 }
113
114 static void
115 remove_method(VALUE klass, ID mid)
116 {
117 if (klass == rb_cObject) {
118 rb_secure(4);
119 }
120 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
121 rb_raise(rb_eSecurityError, "Insecure: can't remove method");
122 }
e732379 moved the removed_method code to the VM + fixed undef_method callbacks
Laurent Sansonetti authored
123 if (OBJ_FROZEN(klass)) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
124 rb_error_frozen("class/module");
e732379 moved the removed_method code to the VM + fixed undef_method callbacks
Laurent Sansonetti authored
125 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
126 if (mid == object_id || mid == __send__ || mid == idInitialize) {
127 rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
128 }
129
e732379 moved the removed_method code to the VM + fixed undef_method callbacks
Laurent Sansonetti authored
130 rb_vm_remove_method((Class)klass, mid);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
131 }
132
133 void
134 rb_remove_method(VALUE klass, const char *name)
135 {
136 remove_method(klass, rb_intern(name));
137 }
138
139 /*
140 * call-seq:
141 * remove_method(symbol) => self
142 *
143 * Removes the method identified by _symbol_ from the current
144 * class. For an example, see <code>Module.undef_method</code>.
145 */
146
147 static VALUE
148 rb_mod_remove_method(VALUE mod, SEL sel, int argc, VALUE *argv)
149 {
e732379 moved the removed_method code to the VM + fixed undef_method callbacks
Laurent Sansonetti authored
150 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
151 remove_method(mod, rb_to_id(argv[i]));
152 }
153 return mod;
154 }
155
156 #undef rb_disable_super
157 #undef rb_enable_super
158
159 void
160 rb_disable_super(VALUE klass, const char *name)
161 {
162 /* obsolete - no use */
163 }
164
165 void
166 rb_enable_super(VALUE klass, const char *name)
167 {
168 rb_warning("rb_enable_super() is obsolete");
169 }
170
171 void rb_print_undef(VALUE, ID, int);
172
173 static void
174 rb_export_method(VALUE klass, ID name, ID noex)
175 {
69ef419 added AOT compilation support for method definitions and constants
Laurent Sansonetti authored
176 rb_vm_method_node_t *node;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
177 SEL sel;
178
179 if (klass == rb_cObject) {
180 rb_secure(4);
181 }
182
183 if (!rb_vm_lookup_method2((Class)klass, name, &sel, NULL, &node)) {
184 if (TYPE(klass) != T_MODULE
185 || !rb_vm_lookup_method2((Class)rb_cObject, name, &sel, NULL, &node)) {
186 rb_print_undef(klass, name, 0);
187 }
188 }
189
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
190 if (node == NULL) {
191 rb_raise(rb_eRuntimeError,
192 "can't change visibility of non Ruby method `%s'",
193 sel_getName(sel));
194 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
195
846054c when changing the visibility of a method that is included in classes,…
Laurent Sansonetti authored
196 long flags = 0;
197 switch (noex) {
198 case NOEX_PRIVATE:
199 flags |= VM_METHOD_PRIVATE;
200 break;
201
202 case NOEX_PROTECTED:
203 flags |= VM_METHOD_PROTECTED;
204 break;
205
206 default:
207 break;
208 }
209
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
210 VALUE sklass = RCLASS_SUPER(klass);
211 if (sklass != 0) {
212 Method m = class_getInstanceMethod((Class)sklass, sel);
213 if (m != NULL && method_getImplementation(m) == node->objc_imp) {
214 // The method actually exists on a superclass, we need to duplicate
846054c when changing the visibility of a method that is included in classes,…
Laurent Sansonetti authored
215 // it to the current class.
216 rb_vm_define_method2((Class)klass, sel, node, flags, false);
217 return;
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
218 }
219 }
220
846054c when changing the visibility of a method that is included in classes,…
Laurent Sansonetti authored
221 node->flags |= flags;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
222 }
223
224 int
225 rb_method_boundp(VALUE klass, ID id, int ex)
226 {
227 NODE *method;
228
229 if ((method = rb_method_node(klass, id)) != 0) {
230 if (ex && (method->nd_noex & NOEX_PRIVATE)) {
231 return Qfalse;
232 }
233 return Qtrue;
234 }
235 return Qfalse;
236 }
237
238 void
239 rb_attr(VALUE klass, ID id, int read, int write, int ex)
240 {
241 if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
242 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
243 }
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
244 const char *name = rb_id2name(id);
245 if (name == NULL) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
246 rb_raise(rb_eArgError, "argument needs to be symbol or string");
247 }
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
248 rb_vm_define_attr((Class)klass, name, read, write);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
249 if (write) {
250 rb_objc_define_kvo_setter(klass, id);
251 }
252 }
253
254 void
255 rb_undef(VALUE klass, ID id)
256 {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
257 if (klass == rb_cObject) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
258 rb_secure(4);
259 }
260 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
261 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
262 rb_id2name(id));
9c1d230 committing experimental branch content
Laurent Sansonetti authored
263 }
264 rb_frozen_class_p(klass);
265 if (id == object_id || id == __send__ || id == idInitialize) {
266 rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
267 }
268
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
269 rb_vm_undef_method((Class)klass, id, true);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
270 }
271
272 /*
273 * call-seq:
274 * undef_method(symbol) => self
275 *
276 * Prevents the current class from responding to calls to the named
277 * method. Contrast this with <code>remove_method</code>, which deletes
278 * the method from the particular class; Ruby will still search
279 * superclasses and mixed-in modules for a possible receiver.
280 *
281 * class Parent
282 * def hello
283 * puts "In parent"
284 * end
285 * end
286 * class Child < Parent
287 * def hello
288 * puts "In child"
289 * end
290 * end
291 *
292 *
293 * c = Child.new
294 * c.hello
295 *
296 *
297 * class Child
298 * remove_method :hello # remove from child, still in parent
299 * end
300 * c.hello
301 *
302 *
303 * class Child
304 * undef_method :hello # prevent any calls to 'hello'
305 * end
306 * c.hello
307 *
308 * <em>produces:</em>
309 *
310 * In child
311 * In parent
312 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
313 */
314
315 static VALUE
316 rb_mod_undef_method(VALUE mod, SEL sel, int argc, VALUE *argv)
317 {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
318 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
319 rb_undef(mod, rb_to_id(argv[i]));
320 }
321 return mod;
322 }
323
324 /*
325 * call-seq:
326 * mod.method_defined?(symbol) => true or false
327 *
328 * Returns +true+ if the named method is defined by
329 * _mod_ (or its included modules and, if _mod_ is a class,
330 * its ancestors). Public and protected methods are matched.
331 *
332 * module A
333 * def method1() end
334 * end
335 * class B
336 * def method2() end
337 * end
338 * class C < B
339 * include A
340 * def method3() end
341 * end
342 *
343 * A.method_defined? :method1 #=> true
344 * C.method_defined? "method1" #=> true
345 * C.method_defined? "method2" #=> true
346 * C.method_defined? "method3" #=> true
347 * C.method_defined? "method4" #=> false
348 */
349
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
350 static bool
351 rb_obj_respond_to2(VALUE obj, VALUE klass, ID id, bool priv, bool check_override)
352 {
353 const char *id_name = rb_id2name(id);
354 SEL sel = sel_registerName(id_name);
355 if (!rb_vm_respond_to2(obj, klass, sel, priv, check_override)) {
356 char buf[100];
357 snprintf(buf, sizeof buf, "%s:", id_name);
358 sel = sel_registerName(buf);
359 return rb_vm_respond_to2(obj, klass, sel, priv, check_override);
360 }
361 return true;
362 }
363
9c1d230 committing experimental branch content
Laurent Sansonetti authored
364 static VALUE
365 rb_mod_method_defined(VALUE mod, SEL sel, VALUE mid)
366 {
914ab2b fixed Module#method_defined?
Laurent Sansonetti authored
367 ID id = rb_to_id(mid);
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
368 return rb_obj_respond_to2(Qnil, mod, id, true, false) ? Qtrue : Qfalse;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
369 }
370
371 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
372
373 /*
374 * call-seq:
375 * mod.public_method_defined?(symbol) => true or false
376 *
377 * Returns +true+ if the named public method is defined by
378 * _mod_ (or its included modules and, if _mod_ is a class,
379 * its ancestors).
380 *
381 * module A
382 * def method1() end
383 * end
384 * class B
385 * protected
386 * def method2() end
387 * end
388 * class C < B
389 * include A
390 * def method3() end
391 * end
392 *
393 * A.method_defined? :method1 #=> true
394 * C.public_method_defined? "method1" #=> true
395 * C.public_method_defined? "method2" #=> false
396 * C.method_defined? "method2" #=> true
397 */
398
399 static VALUE
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
400 check_method_visibility(VALUE mod, ID id, int visi)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
401 {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
402 rb_vm_method_node_t *node;
403 if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
404 if (node != NULL) {
405 if (node->flags & rb_vm_noex_flag(visi)) {
406 return Qtrue;
407 }
408 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
409 }
410 return Qfalse;
411 }
412
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
413 static VALUE
414 rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid)
415 {
416 ID id = rb_to_id(mid);
417 return check_method_visibility(mod, id, NOEX_PUBLIC);
418 }
419
9c1d230 committing experimental branch content
Laurent Sansonetti authored
420 /*
421 * call-seq:
422 * mod.private_method_defined?(symbol) => true or false
423 *
424 * Returns +true+ if the named private method is defined by
425 * _ mod_ (or its included modules and, if _mod_ is a class,
426 * its ancestors).
427 *
428 * module A
429 * def method1() end
430 * end
431 * class B
432 * private
433 * def method2() end
434 * end
435 * class C < B
436 * include A
437 * def method3() end
438 * end
439 *
440 * A.method_defined? :method1 #=> true
441 * C.private_method_defined? "method1" #=> false
442 * C.private_method_defined? "method2" #=> true
443 * C.method_defined? "method2" #=> false
444 */
445
446 static VALUE
447 rb_mod_private_method_defined(VALUE mod, SEL sel, VALUE mid)
448 {
449 ID id = rb_to_id(mid);
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
450 return check_method_visibility(mod, id, NOEX_PRIVATE);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
451 }
452
453 /*
454 * call-seq:
455 * mod.protected_method_defined?(symbol) => true or false
456 *
457 * Returns +true+ if the named protected method is defined
458 * by _mod_ (or its included modules and, if _mod_ is a
459 * class, its ancestors).
460 *
461 * module A
462 * def method1() end
463 * end
464 * class B
465 * protected
466 * def method2() end
467 * end
468 * class C < B
469 * include A
470 * def method3() end
471 * end
472 *
473 * A.method_defined? :method1 #=> true
474 * C.protected_method_defined? "method1" #=> false
475 * C.protected_method_defined? "method2" #=> true
476 * C.method_defined? "method2" #=> true
477 */
478
479 static VALUE
480 rb_mod_protected_method_defined(VALUE mod, SEL sel, VALUE mid)
481 {
482 ID id = rb_to_id(mid);
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
483 return check_method_visibility(mod, id, NOEX_PROTECTED);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
484 }
485
486 void
487 rb_alias(VALUE klass, ID name, ID def)
488 {
489 rb_vm_alias(klass, name, def);
490 }
491
492 /*
493 * call-seq:
494 * alias_method(new_name, old_name) => self
495 *
496 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
497 * be used to retain access to methods that are overridden.
498 *
499 * module Mod
500 * alias_method :orig_exit, :exit
501 * def exit(code=0)
502 * puts "Exiting with code #{code}"
503 * orig_exit(code)
504 * end
505 * end
506 * include Mod
507 * exit(99)
508 *
509 * <em>produces:</em>
510 *
511 * Exiting with code 99
512 */
513
514 static VALUE
515 rb_mod_alias_method(VALUE mod, SEL sel, VALUE newname, VALUE oldname)
516 {
517 rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
518 return mod;
519 }
520
521 static void
522 secure_visibility(VALUE self)
523 {
524 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
525 rb_raise(rb_eSecurityError,
526 "Insecure: can't change method visibility");
527 }
528 }
529
530 static void
531 set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
532 {
533 secure_visibility(self);
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
534 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
535 rb_export_method(self, rb_to_id(argv[i]), ex);
536 }
537 }
538
539 /*
540 * call-seq:
541 * public => self
542 * public(symbol, ...) => self
543 *
544 * With no arguments, sets the default visibility for subsequently
545 * defined methods to public. With arguments, sets the named methods to
546 * have public visibility.
547 */
548
549 static VALUE
550 rb_mod_public(VALUE module, SEL sel, int argc, VALUE *argv)
551 {
552 secure_visibility(module);
553 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
554 rb_vm_set_current_scope(module, SCOPE_PUBLIC);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
555 }
556 else {
557 set_method_visibility(module, argc, argv, NOEX_PUBLIC);
558 }
559 return module;
560 }
561
562 /*
563 * call-seq:
564 * protected => self
565 * protected(symbol, ...) => self
566 *
567 * With no arguments, sets the default visibility for subsequently
568 * defined methods to protected. With arguments, sets the named methods
569 * to have protected visibility.
570 */
571
572 static VALUE
573 rb_mod_protected(VALUE module, SEL sel, int argc, VALUE *argv)
574 {
575 secure_visibility(module);
576 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
577 rb_vm_set_current_scope(module, SCOPE_PROTECTED);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
578 }
579 else {
580 set_method_visibility(module, argc, argv, NOEX_PROTECTED);
581 }
582 return module;
583 }
584
585 /*
586 * call-seq:
587 * private => self
588 * private(symbol, ...) => self
589 *
590 * With no arguments, sets the default visibility for subsequently
591 * defined methods to private. With arguments, sets the named methods
592 * to have private visibility.
593 *
594 * module Mod
595 * def a() end
596 * def b() end
597 * private
598 * def c() end
599 * private :a
600 * end
601 * Mod.private_instance_methods #=> [:a, :c]
602 */
603
604 static VALUE
605 rb_mod_private(VALUE module, SEL sel, int argc, VALUE *argv)
606 {
607 secure_visibility(module);
608 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
609 rb_vm_set_current_scope(module, SCOPE_PRIVATE);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
610 }
611 else {
612 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
613 }
614 return module;
615 }
616
617 /*
618 * call-seq:
619 * mod.public_class_method(symbol, ...) => mod
620 *
621 * Makes a list of existing class methods public.
622 */
623
624 static VALUE
625 rb_mod_public_method(VALUE obj, SEL sel, int argc, VALUE *argv)
626 {
627 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
628 return obj;
629 }
630
631 /*
632 * call-seq:
633 * mod.private_class_method(symbol, ...) => mod
634 *
635 * Makes existing class methods private. Often used to hide the default
636 * constructor <code>new</code>.
637 *
638 * class SimpleSingleton # Not thread safe
639 * private_class_method :new
640 * def SimpleSingleton.create(*args, &block)
641 * @me = new(*args, &block) if ! @me
642 * @me
643 * end
644 * end
645 */
646
647 static VALUE
648 rb_mod_private_method(VALUE obj, SEL sel, int argc, VALUE *argv)
649 {
650 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
651 return obj;
652 }
653
654 /*
655 * call-seq:
656 * public
657 * public(symbol, ...)
658 *
659 * With no arguments, sets the default visibility for subsequently
660 * defined methods to public. With arguments, sets the named methods to
661 * have public visibility.
662 */
663
664 static VALUE
665 top_public(VALUE recv, SEL sel, int argc, VALUE *argv)
666 {
667 return rb_mod_public(rb_cObject, 0, argc, argv);
668 }
669
670 static VALUE
671 top_private(VALUE recv, SEL sel, int argc, VALUE *argv)
672 {
673 return rb_mod_private(rb_cObject, 0, argc, argv);
674 }
675
676 /*
677 * call-seq:
678 * module_function(symbol, ...) => self
679 *
680 * Creates module functions for the named methods. These functions may
681 * be called with the module as a receiver, and also become available
682 * as instance methods to classes that mix in the module. Module
683 * functions are copies of the original, and so may be changed
684 * independently. The instance-method versions are made private. If
685 * used with no arguments, subsequently defined methods become module
686 * functions.
687 *
688 * module Mod
689 * def one
690 * "This is one"
691 * end
692 * module_function :one
693 * end
694 * class Cls
695 * include Mod
696 * def callOne
697 * one
698 * end
699 * end
700 * Mod.one #=> "This is one"
701 * c = Cls.new
702 * c.callOne #=> "This is one"
703 * module Mod
704 * def one
705 * "This is the new one"
706 * end
707 * end
708 * Mod.one #=> "This is one"
709 * c.callOne #=> "This is the new one"
710 */
711
712 static VALUE
713 rb_mod_modfunc(VALUE module, SEL sel, int argc, VALUE *argv)
714 {
715 if (TYPE(module) != T_MODULE) {
716 rb_raise(rb_eTypeError, "module_function must be called for modules");
717 }
718
719 secure_visibility(module);
720 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
721 rb_vm_set_current_scope(module, SCOPE_MODULE_FUNC);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
722 return module;
723 }
724
725 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
726
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
727 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
728 ID id = rb_to_id(argv[i]);
729 IMP imp;
69ef419 added AOT compilation support for method definitions and constants
Laurent Sansonetti authored
730 rb_vm_method_node_t *node;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
731 SEL sel;
732
733 if (!rb_vm_lookup_method2((Class)module, id, &sel, &imp, &node)) {
734 // Methods are checked in set_method_visibility().
735 rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
736 }
737
846054c when changing the visibility of a method that is included in classes,…
Laurent Sansonetti authored
738 rb_vm_define_method2(*(Class *)module, sel, node, -1, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
739 }
740
741 return module;
742 }
743
744 /*
745 * call-seq:
746 * obj.respond_to?(symbol, include_private=false) => true or false
747 *
748 * Returns +true+> if _obj_ responds to the given
749 * method. Private methods are included in the search only if the
750 * optional second parameter evaluates to +true+.
751 */
752
914ab2b fixed Module#method_defined?
Laurent Sansonetti authored
753 bool
28db598 make sure Kernel#respond_to? doesn't call itself stupid^Wrecursively
Laurent Sansonetti authored
754 rb_obj_respond_to(VALUE obj, ID id, bool priv)
755 {
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
756 return rb_obj_respond_to2(obj, Qnil, id, priv, true);
28db598 make sure Kernel#respond_to? doesn't call itself stupid^Wrecursively
Laurent Sansonetti authored
757 }
758
759 bool
9c1d230 committing experimental branch content
Laurent Sansonetti authored
760 rb_respond_to(VALUE obj, ID id)
761 {
28db598 make sure Kernel#respond_to? doesn't call itself stupid^Wrecursively
Laurent Sansonetti authored
762 return rb_obj_respond_to(obj, id, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
763 }
764
765 /*
766 * call-seq:
767 * obj.respond_to?(symbol, include_private=false) => true or false
768 *
769 * Returns +true+> if _obj_ responds to the given
770 * method. Private methods are included in the search only if the
771 * optional second parameter evaluates to +true+.
772 */
773
774 static VALUE
775 obj_respond_to(VALUE obj, SEL sel, int argc, VALUE *argv)
776 {
777 VALUE mid, priv;
778 ID id;
779
780 rb_scan_args(argc, argv, "11", &mid, &priv);
781 id = rb_to_id(mid);
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
782 return rb_obj_respond_to2(obj, Qnil, id, RTEST(priv), false) ? Qtrue : Qfalse;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
783 }
784
785 IMP basic_respond_to_imp = NULL;
786
787 void
788 Init_eval_method(void)
789 {
790 rb_objc_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
791 basic_respond_to_imp = class_getMethodImplementation((Class)rb_mKernel, selRespondTo);
792 //basic_respond_to = rb_method_node(rb_cObject, idRespond_to);
793 //rb_register_mark_object((VALUE)basic_respond_to);
794
795 rb_objc_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
796 rb_objc_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
797 rb_objc_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
798 rb_objc_define_private_method(rb_cModule, "public", rb_mod_public, -1);
799 rb_objc_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
800 rb_objc_define_private_method(rb_cModule, "private", rb_mod_private, -1);
801 rb_objc_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
802
803 rb_objc_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
804 rb_objc_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
805 rb_objc_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
806 rb_objc_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
807 rb_objc_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
808 rb_objc_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
809
810 VALUE cTopLevel = *(VALUE *)rb_vm_top_self();
811 rb_objc_define_method(cTopLevel, "public", top_public, -1);
812 rb_objc_define_method(cTopLevel, "private", top_private, -1);
813
814 object_id = rb_intern("object_id");
815 __send__ = rb_intern("__send__");
816 eqq = rb_intern("===");
817 each = rb_intern("each");
818 aref = rb_intern("[]");
819 aset = rb_intern("[]=");
820 match = rb_intern("=~");
821 missing = rb_intern("method_missing");
822 added = rb_intern("method_added");
823 singleton_added = rb_intern("singleton_method_added");
824 removed = rb_intern("method_removed");
825 singleton_removed = rb_intern("singleton_method_removed");
826 undefined = rb_intern("method_undefined");
827 singleton_undefined = rb_intern("singleton_method_undefined");
828 }
829
Something went wrong with that request. Please try again.