Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 840 lines (755 sloc) 20.64 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, ma...
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) {
d3eea39 when changing the visibility of a method and duplicating its entry in th...
Laurent Sansonetti authored
212 IMP imp;
213 rb_vm_method_node_t *snode;
214 if (rb_vm_lookup_method((Class)sklass, sel, &imp, &snode)
215 && imp == node->objc_imp) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
216 // The method actually exists on a superclass, we need to duplicate
d3eea39 when changing the visibility of a method and duplicating its entry in th...
Laurent Sansonetti authored
217 // it to the current class, keeping the same flags.
218 if (snode != NULL) {
219 if (snode->flags & VM_METHOD_EMPTY) {
220 flags |= VM_METHOD_EMPTY;
221 }
222 if (snode->flags & VM_METHOD_FBODY) {
223 flags |= VM_METHOD_FBODY;
224 }
225 }
846054c when changing the visibility of a method that is included in classes, ma...
Laurent Sansonetti authored
226 rb_vm_define_method2((Class)klass, sel, node, flags, false);
227 return;
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
228 }
229 }
230
846054c when changing the visibility of a method that is included in classes, ma...
Laurent Sansonetti authored
231 node->flags |= flags;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
232 }
233
234 int
235 rb_method_boundp(VALUE klass, ID id, int ex)
236 {
237 NODE *method;
238
239 if ((method = rb_method_node(klass, id)) != 0) {
240 if (ex && (method->nd_noex & NOEX_PRIVATE)) {
241 return Qfalse;
242 }
243 return Qtrue;
244 }
245 return Qfalse;
246 }
247
248 void
249 rb_attr(VALUE klass, ID id, int read, int write, int ex)
250 {
251 if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
252 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
253 }
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
254 const char *name = rb_id2name(id);
255 if (name == NULL) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
256 rb_raise(rb_eArgError, "argument needs to be symbol or string");
257 }
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
258 rb_vm_define_attr((Class)klass, name, read, write);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
259 if (write) {
260 rb_objc_define_kvo_setter(klass, id);
261 }
262 }
263
264 void
265 rb_undef(VALUE klass, ID id)
266 {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
267 if (klass == rb_cObject) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
268 rb_secure(4);
269 }
270 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
271 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
272 rb_id2name(id));
9c1d230 committing experimental branch content
Laurent Sansonetti authored
273 }
274 rb_frozen_class_p(klass);
275 if (id == object_id || id == __send__ || id == idInitialize) {
276 rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
277 }
278
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
279 rb_vm_undef_method((Class)klass, id, true);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
280 }
281
282 /*
283 * call-seq:
284 * undef_method(symbol) => self
285 *
286 * Prevents the current class from responding to calls to the named
287 * method. Contrast this with <code>remove_method</code>, which deletes
288 * the method from the particular class; Ruby will still search
289 * superclasses and mixed-in modules for a possible receiver.
290 *
291 * class Parent
292 * def hello
293 * puts "In parent"
294 * end
295 * end
296 * class Child < Parent
297 * def hello
298 * puts "In child"
299 * end
300 * end
301 *
302 *
303 * c = Child.new
304 * c.hello
305 *
306 *
307 * class Child
308 * remove_method :hello # remove from child, still in parent
309 * end
310 * c.hello
311 *
312 *
313 * class Child
314 * undef_method :hello # prevent any calls to 'hello'
315 * end
316 * c.hello
317 *
318 * <em>produces:</em>
319 *
320 * In child
321 * In parent
322 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
323 */
324
325 static VALUE
326 rb_mod_undef_method(VALUE mod, SEL sel, int argc, VALUE *argv)
327 {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
328 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
329 rb_undef(mod, rb_to_id(argv[i]));
330 }
331 return mod;
332 }
333
334 /*
335 * call-seq:
336 * mod.method_defined?(symbol) => true or false
337 *
338 * Returns +true+ if the named method is defined by
339 * _mod_ (or its included modules and, if _mod_ is a class,
340 * its ancestors). Public and protected methods are matched.
341 *
342 * module A
343 * def method1() end
344 * end
345 * class B
346 * def method2() end
347 * end
348 * class C < B
349 * include A
350 * def method3() end
351 * end
352 *
353 * A.method_defined? :method1 #=> true
354 * C.method_defined? "method1" #=> true
355 * C.method_defined? "method2" #=> true
356 * C.method_defined? "method3" #=> true
357 * C.method_defined? "method4" #=> false
358 */
359
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
360 static bool
361 rb_obj_respond_to2(VALUE obj, VALUE klass, ID id, bool priv, bool check_override)
362 {
363 const char *id_name = rb_id2name(id);
364 SEL sel = sel_registerName(id_name);
365 if (!rb_vm_respond_to2(obj, klass, sel, priv, check_override)) {
366 char buf[100];
367 snprintf(buf, sizeof buf, "%s:", id_name);
368 sel = sel_registerName(buf);
369 return rb_vm_respond_to2(obj, klass, sel, priv, check_override);
370 }
371 return true;
372 }
373
9c1d230 committing experimental branch content
Laurent Sansonetti authored
374 static VALUE
375 rb_mod_method_defined(VALUE mod, SEL sel, VALUE mid)
376 {
914ab2b fixed Module#method_defined?
Laurent Sansonetti authored
377 ID id = rb_to_id(mid);
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
378 return rb_obj_respond_to2(Qnil, mod, id, true, false) ? Qtrue : Qfalse;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
379 }
380
381 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
382
383 /*
384 * call-seq:
385 * mod.public_method_defined?(symbol) => true or false
386 *
387 * Returns +true+ if the named public method is defined by
388 * _mod_ (or its included modules and, if _mod_ is a class,
389 * its ancestors).
390 *
391 * module A
392 * def method1() end
393 * end
394 * class B
395 * protected
396 * def method2() end
397 * end
398 * class C < B
399 * include A
400 * def method3() end
401 * end
402 *
403 * A.method_defined? :method1 #=> true
404 * C.public_method_defined? "method1" #=> true
405 * C.public_method_defined? "method2" #=> false
406 * C.method_defined? "method2" #=> true
407 */
408
409 static VALUE
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
410 check_method_visibility(VALUE mod, ID id, int visi)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
411 {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
412 rb_vm_method_node_t *node;
413 if (rb_vm_lookup_method2((Class)mod, id, NULL, NULL, &node)) {
414 if (node != NULL) {
415 if (node->flags & rb_vm_noex_flag(visi)) {
416 return Qtrue;
417 }
418 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
419 }
420 return Qfalse;
421 }
422
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
423 static VALUE
424 rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid)
425 {
426 ID id = rb_to_id(mid);
427 return check_method_visibility(mod, id, NOEX_PUBLIC);
428 }
429
9c1d230 committing experimental branch content
Laurent Sansonetti authored
430 /*
431 * call-seq:
432 * mod.private_method_defined?(symbol) => true or false
433 *
434 * Returns +true+ if the named private method is defined by
435 * _ mod_ (or its included modules and, if _mod_ is a class,
436 * its ancestors).
437 *
438 * module A
439 * def method1() end
440 * end
441 * class B
442 * private
443 * def method2() end
444 * end
445 * class C < B
446 * include A
447 * def method3() end
448 * end
449 *
450 * A.method_defined? :method1 #=> true
451 * C.private_method_defined? "method1" #=> false
452 * C.private_method_defined? "method2" #=> true
453 * C.method_defined? "method2" #=> false
454 */
455
456 static VALUE
457 rb_mod_private_method_defined(VALUE mod, SEL sel, VALUE mid)
458 {
459 ID id = rb_to_id(mid);
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
460 return check_method_visibility(mod, id, NOEX_PRIVATE);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
461 }
462
463 /*
464 * call-seq:
465 * mod.protected_method_defined?(symbol) => true or false
466 *
467 * Returns +true+ if the named protected method is defined
468 * by _mod_ (or its included modules and, if _mod_ is a
469 * class, its ancestors).
470 *
471 * module A
472 * def method1() end
473 * end
474 * class B
475 * protected
476 * def method2() end
477 * end
478 * class C < B
479 * include A
480 * def method3() end
481 * end
482 *
483 * A.method_defined? :method1 #=> true
484 * C.protected_method_defined? "method1" #=> false
485 * C.protected_method_defined? "method2" #=> true
486 * C.method_defined? "method2" #=> true
487 */
488
489 static VALUE
490 rb_mod_protected_method_defined(VALUE mod, SEL sel, VALUE mid)
491 {
492 ID id = rb_to_id(mid);
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
493 return check_method_visibility(mod, id, NOEX_PROTECTED);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
494 }
495
496 void
497 rb_alias(VALUE klass, ID name, ID def)
498 {
499 rb_vm_alias(klass, name, def);
500 }
501
502 /*
503 * call-seq:
504 * alias_method(new_name, old_name) => self
505 *
506 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
507 * be used to retain access to methods that are overridden.
508 *
509 * module Mod
510 * alias_method :orig_exit, :exit
511 * def exit(code=0)
512 * puts "Exiting with code #{code}"
513 * orig_exit(code)
514 * end
515 * end
516 * include Mod
517 * exit(99)
518 *
519 * <em>produces:</em>
520 *
521 * Exiting with code 99
522 */
523
524 static VALUE
525 rb_mod_alias_method(VALUE mod, SEL sel, VALUE newname, VALUE oldname)
526 {
527 rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
528 return mod;
529 }
530
531 static void
532 secure_visibility(VALUE self)
533 {
534 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
535 rb_raise(rb_eSecurityError,
536 "Insecure: can't change method visibility");
537 }
538 }
539
540 static void
541 set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
542 {
543 secure_visibility(self);
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
544 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
545 rb_export_method(self, rb_to_id(argv[i]), ex);
546 }
547 }
548
549 /*
550 * call-seq:
551 * public => self
552 * public(symbol, ...) => self
553 *
554 * With no arguments, sets the default visibility for subsequently
555 * defined methods to public. With arguments, sets the named methods to
556 * have public visibility.
557 */
558
559 static VALUE
560 rb_mod_public(VALUE module, SEL sel, int argc, VALUE *argv)
561 {
562 secure_visibility(module);
563 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
564 rb_vm_set_current_scope(module, SCOPE_PUBLIC);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
565 }
566 else {
567 set_method_visibility(module, argc, argv, NOEX_PUBLIC);
568 }
569 return module;
570 }
571
572 /*
573 * call-seq:
574 * protected => self
575 * protected(symbol, ...) => self
576 *
577 * With no arguments, sets the default visibility for subsequently
578 * defined methods to protected. With arguments, sets the named methods
579 * to have protected visibility.
580 */
581
582 static VALUE
583 rb_mod_protected(VALUE module, SEL sel, int argc, VALUE *argv)
584 {
585 secure_visibility(module);
586 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
587 rb_vm_set_current_scope(module, SCOPE_PROTECTED);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
588 }
589 else {
590 set_method_visibility(module, argc, argv, NOEX_PROTECTED);
591 }
592 return module;
593 }
594
595 /*
596 * call-seq:
597 * private => self
598 * private(symbol, ...) => self
599 *
600 * With no arguments, sets the default visibility for subsequently
601 * defined methods to private. With arguments, sets the named methods
602 * to have private visibility.
603 *
604 * module Mod
605 * def a() end
606 * def b() end
607 * private
608 * def c() end
609 * private :a
610 * end
611 * Mod.private_instance_methods #=> [:a, :c]
612 */
613
614 static VALUE
615 rb_mod_private(VALUE module, SEL sel, int argc, VALUE *argv)
616 {
617 secure_visibility(module);
618 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
619 rb_vm_set_current_scope(module, SCOPE_PRIVATE);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
620 }
621 else {
622 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
623 }
624 return module;
625 }
626
627 /*
628 * call-seq:
629 * mod.public_class_method(symbol, ...) => mod
630 *
631 * Makes a list of existing class methods public.
632 */
633
634 static VALUE
635 rb_mod_public_method(VALUE obj, SEL sel, int argc, VALUE *argv)
636 {
637 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
638 return obj;
639 }
640
641 /*
642 * call-seq:
643 * mod.private_class_method(symbol, ...) => mod
644 *
645 * Makes existing class methods private. Often used to hide the default
646 * constructor <code>new</code>.
647 *
648 * class SimpleSingleton # Not thread safe
649 * private_class_method :new
650 * def SimpleSingleton.create(*args, &block)
651 * @me = new(*args, &block) if ! @me
652 * @me
653 * end
654 * end
655 */
656
657 static VALUE
658 rb_mod_private_method(VALUE obj, SEL sel, int argc, VALUE *argv)
659 {
660 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
661 return obj;
662 }
663
664 /*
665 * call-seq:
666 * public
667 * public(symbol, ...)
668 *
669 * With no arguments, sets the default visibility for subsequently
670 * defined methods to public. With arguments, sets the named methods to
671 * have public visibility.
672 */
673
674 static VALUE
675 top_public(VALUE recv, SEL sel, int argc, VALUE *argv)
676 {
677 return rb_mod_public(rb_cObject, 0, argc, argv);
678 }
679
680 static VALUE
681 top_private(VALUE recv, SEL sel, int argc, VALUE *argv)
682 {
683 return rb_mod_private(rb_cObject, 0, argc, argv);
684 }
685
686 /*
687 * call-seq:
688 * module_function(symbol, ...) => self
689 *
690 * Creates module functions for the named methods. These functions may
691 * be called with the module as a receiver, and also become available
692 * as instance methods to classes that mix in the module. Module
693 * functions are copies of the original, and so may be changed
694 * independently. The instance-method versions are made private. If
695 * used with no arguments, subsequently defined methods become module
696 * functions.
697 *
698 * module Mod
699 * def one
700 * "This is one"
701 * end
702 * module_function :one
703 * end
704 * class Cls
705 * include Mod
706 * def callOne
707 * one
708 * end
709 * end
710 * Mod.one #=> "This is one"
711 * c = Cls.new
712 * c.callOne #=> "This is one"
713 * module Mod
714 * def one
715 * "This is the new one"
716 * end
717 * end
718 * Mod.one #=> "This is one"
719 * c.callOne #=> "This is the new one"
720 */
721
722 static VALUE
723 rb_mod_modfunc(VALUE module, SEL sel, int argc, VALUE *argv)
724 {
725 if (TYPE(module) != T_MODULE) {
726 rb_raise(rb_eTypeError, "module_function must be called for modules");
727 }
728
729 secure_visibility(module);
730 if (argc == 0) {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
731 rb_vm_set_current_scope(module, SCOPE_MODULE_FUNC);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
732 return module;
733 }
734
735 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
736
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
737 for (int i = 0; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
738 ID id = rb_to_id(argv[i]);
739 IMP imp;
69ef419 added AOT compilation support for method definitions and constants
Laurent Sansonetti authored
740 rb_vm_method_node_t *node;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
741 SEL sel;
742
743 if (!rb_vm_lookup_method2((Class)module, id, &sel, &imp, &node)) {
744 // Methods are checked in set_method_visibility().
745 rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
746 }
747
846054c when changing the visibility of a method that is included in classes, ma...
Laurent Sansonetti authored
748 rb_vm_define_method2(*(Class *)module, sel, node, -1, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
749 }
750
751 return module;
752 }
753
754 /*
755 * call-seq:
756 * obj.respond_to?(symbol, include_private=false) => true or false
757 *
758 * Returns +true+> if _obj_ responds to the given
759 * method. Private methods are included in the search only if the
760 * optional second parameter evaluates to +true+.
761 */
762
914ab2b fixed Module#method_defined?
Laurent Sansonetti authored
763 bool
28db598 make sure Kernel#respond_to? doesn't call itself stupid^Wrecursively
Laurent Sansonetti authored
764 rb_obj_respond_to(VALUE obj, ID id, bool priv)
765 {
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
766 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
767 }
768
769 bool
9c1d230 committing experimental branch content
Laurent Sansonetti authored
770 rb_respond_to(VALUE obj, ID id)
771 {
28db598 make sure Kernel#respond_to? doesn't call itself stupid^Wrecursively
Laurent Sansonetti authored
772 return rb_obj_respond_to(obj, id, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
773 }
774
775 /*
776 * call-seq:
777 * obj.respond_to?(symbol, include_private=false) => true or false
778 *
779 * Returns +true+> if _obj_ responds to the given
780 * method. Private methods are included in the search only if the
781 * optional second parameter evaluates to +true+.
782 */
783
784 static VALUE
785 obj_respond_to(VALUE obj, SEL sel, int argc, VALUE *argv)
786 {
787 VALUE mid, priv;
788 ID id;
789
790 rb_scan_args(argc, argv, "11", &mid, &priv);
791 id = rb_to_id(mid);
9e76215 fixed Module#method_defined?
Laurent Sansonetti authored
792 return rb_obj_respond_to2(obj, Qnil, id, RTEST(priv), false) ? Qtrue : Qfalse;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
793 }
794
795 IMP basic_respond_to_imp = NULL;
796
797 void
798 Init_eval_method(void)
799 {
800 rb_objc_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
801 basic_respond_to_imp = class_getMethodImplementation((Class)rb_mKernel, selRespondTo);
802 //basic_respond_to = rb_method_node(rb_cObject, idRespond_to);
803 //rb_register_mark_object((VALUE)basic_respond_to);
804
805 rb_objc_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
806 rb_objc_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
807 rb_objc_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
808 rb_objc_define_private_method(rb_cModule, "public", rb_mod_public, -1);
809 rb_objc_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
810 rb_objc_define_private_method(rb_cModule, "private", rb_mod_private, -1);
811 rb_objc_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
812
813 rb_objc_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
814 rb_objc_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
815 rb_objc_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
816 rb_objc_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
817 rb_objc_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
818 rb_objc_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
819
820 VALUE cTopLevel = *(VALUE *)rb_vm_top_self();
821 rb_objc_define_method(cTopLevel, "public", top_public, -1);
822 rb_objc_define_method(cTopLevel, "private", top_private, -1);
823
824 object_id = rb_intern("object_id");
825 __send__ = rb_intern("__send__");
826 eqq = rb_intern("===");
827 each = rb_intern("each");
828 aref = rb_intern("[]");
829 aset = rb_intern("[]=");
830 match = rb_intern("=~");
831 missing = rb_intern("method_missing");
832 added = rb_intern("method_added");
833 singleton_added = rb_intern("singleton_method_added");
834 removed = rb_intern("method_removed");
835 singleton_removed = rb_intern("singleton_method_removed");
836 undefined = rb_intern("method_undefined");
837 singleton_undefined = rb_intern("singleton_method_undefined");
838 }
839
Something went wrong with that request. Please try again.