* transcode.c (rb_cEncodingConverter): new class Encoding::Converter.
[ruby-svn.git] / vm_method.c
blobb9940a72304ffc2fa29dc056bb52f9b7fc4e02f2
1 /* -*-c-*- */
2 /*
3 * This file is included by vm_eval.c
4 */
6 #define CACHE_SIZE 0x800
7 #define CACHE_MASK 0x7ff
8 #define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
10 static void rb_vm_check_redefinition_opt_method(const NODE *node);
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;
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 */
21 VALUE oklass; /* original's class */
22 NODE *method;
25 static struct cache_entry cache[CACHE_SIZE];
26 #define ruby_running (GET_VM()->running)
27 /* int ruby_running = 0; */
29 void
30 rb_clear_cache(void)
32 struct cache_entry *ent, *end;
34 rb_vm_change_state();
36 if (!ruby_running)
37 return;
38 ent = cache;
39 end = ent + CACHE_SIZE;
40 while (ent < end) {
41 ent->mid = 0;
42 ent++;
46 static void
47 rb_clear_cache_for_undef(VALUE klass, ID id)
49 struct cache_entry *ent, *end;
51 rb_vm_change_state();
53 if (!ruby_running)
54 return;
55 ent = cache;
56 end = ent + CACHE_SIZE;
57 while (ent < end) {
58 if (ent->oklass == klass && ent->mid == id) {
59 ent->mid = 0;
61 ent++;
65 static void
66 rb_clear_cache_by_id(ID id)
68 struct cache_entry *ent, *end;
70 rb_vm_change_state();
72 if (!ruby_running)
73 return;
74 ent = cache;
75 end = ent + CACHE_SIZE;
76 while (ent < end) {
77 if (ent->mid == id) {
78 ent->mid = 0;
80 ent++;
84 void
85 rb_clear_cache_by_class(VALUE klass)
87 struct cache_entry *ent, *end;
89 rb_vm_change_state();
91 if (!ruby_running)
92 return;
93 ent = cache;
94 end = ent + CACHE_SIZE;
95 while (ent < end) {
96 if (ent->klass == klass || ent->oklass == klass) {
97 ent->mid = 0;
99 ent++;
103 void
104 rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
106 NODE *body;
108 if (NIL_P(klass)) {
109 klass = rb_cObject;
111 if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
112 rb_raise(rb_eSecurityError, "Insecure: can't define method");
114 if (!FL_TEST(klass, FL_SINGLETON) &&
115 node && nd_type(node) != NODE_ZSUPER &&
116 (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
117 noex = NOEX_PRIVATE | noex;
119 else if (FL_TEST(klass, FL_SINGLETON) && node
120 && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
121 rb_warn
122 ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
123 rb_class2name(rb_iv_get(klass, "__attached__")));
124 mid = ID_ALLOCATOR;
126 if (OBJ_FROZEN(klass)) {
127 rb_error_frozen("class/module");
129 rb_clear_cache_by_id(mid);
132 * NODE_METHOD (NEW_METHOD(body, klass, vis)):
133 * nd_body : method body // (2) // mark
134 * nd_clss : klass // (1) // mark
135 * nd_noex : visibility // (3)
137 * NODE_FBODY (NEW_FBODY(method, alias)):
138 * nd_body : method (NODE_METHOD) // (2) // mark
139 * nd_oid : original id // (1)
140 * nd_cnt : alias count // (3)
142 if (node) {
143 body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
145 else {
146 body = 0;
150 /* check re-definition */
151 st_data_t data;
152 NODE *old_node;
154 if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
155 old_node = (NODE *)data;
156 if (old_node) {
157 if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
158 rb_vm_check_redefinition_opt_method(old_node);
160 if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
161 rb_warning("method redefined; discarding old %s", rb_id2name(mid));
165 if (klass == rb_cObject && node && mid == idInitialize) {
166 rb_warn("redefining Object#initialize may cause infinite loop");
169 if (mid == object_id || mid == __send__) {
170 if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
171 rb_warn("redefining `%s' may cause serious problem",
172 rb_id2name(mid));
177 st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
179 if (node && mid != ID_ALLOCATOR && ruby_running) {
180 if (FL_TEST(klass, FL_SINGLETON)) {
181 rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
182 ID2SYM(mid));
184 else {
185 rb_funcall(klass, added, 1, ID2SYM(mid));
190 void
191 rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
193 Check_Type(klass, T_CLASS);
194 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
195 NOEX_PRIVATE);
198 void
199 rb_undef_alloc_func(VALUE klass)
201 Check_Type(klass, T_CLASS);
202 rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
205 rb_alloc_func_t
206 rb_get_alloc_func(VALUE klass)
208 NODE *n;
209 Check_Type(klass, T_CLASS);
210 n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
211 if (!n) return 0;
212 if (nd_type(n) != NODE_METHOD) return 0;
213 n = n->nd_body;
214 if (nd_type(n) != NODE_CFUNC) return 0;
215 return (rb_alloc_func_t)n->nd_cfnc;
218 static NODE *
219 search_method(VALUE klass, ID id, VALUE *klassp)
221 st_data_t body;
223 if (!klass) {
224 return 0;
227 while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
228 klass = RCLASS_SUPER(klass);
229 if (!klass)
230 return 0;
233 if (klassp) {
234 *klassp = klass;
237 return (NODE *)body;
241 * search method body (NODE_METHOD)
242 * with : klass and id
243 * without : method cache
245 * if you need method node with method cache, use
246 * rb_method_node()
248 NODE *
249 rb_get_method_body(VALUE klass, ID id, ID *idp)
251 NODE *volatile fbody, *body;
252 NODE *method;
254 if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
255 /* store empty info in cache */
256 struct cache_entry *ent;
257 ent = cache + EXPR1(klass, id);
258 ent->klass = klass;
259 ent->mid = ent->mid0 = id;
260 ent->method = 0;
261 ent->oklass = 0;
262 return 0;
265 method = fbody->nd_body;
267 if (ruby_running) {
268 /* store in cache */
269 struct cache_entry *ent;
270 ent = cache + EXPR1(klass, id);
271 ent->klass = klass;
272 ent->mid = id;
273 ent->mid0 = fbody->nd_oid;
274 ent->method = body = method;
275 ent->oklass = method->nd_clss;
277 else {
278 body = method;
281 if (idp) {
282 *idp = fbody->nd_oid;
285 return body;
288 NODE *
289 rb_method_node(VALUE klass, ID id)
291 struct cache_entry *ent;
293 ent = cache + EXPR1(klass, id);
294 if (ent->mid == id && ent->klass == klass && ent->method) {
295 return ent->method;
298 return rb_get_method_body(klass, id, 0);
301 static void
302 remove_method(VALUE klass, ID mid)
304 st_data_t data;
305 NODE *body = 0;
307 if (klass == rb_cObject) {
308 rb_secure(4);
310 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
311 rb_raise(rb_eSecurityError, "Insecure: can't remove method");
313 if (OBJ_FROZEN(klass))
314 rb_error_frozen("class/module");
315 if (mid == object_id || mid == __send__ || mid == idInitialize) {
316 rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
318 if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
319 body = (NODE *)data;
320 if (!body || !body->nd_body) body = 0;
321 else {
322 st_delete(RCLASS_M_TBL(klass), &mid, &data);
325 if (!body) {
326 rb_name_error(mid, "method `%s' not defined in %s",
327 rb_id2name(mid), rb_class2name(klass));
330 if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
331 rb_vm_check_redefinition_opt_method(body);
334 rb_clear_cache_for_undef(klass, mid);
335 if (FL_TEST(klass, FL_SINGLETON)) {
336 rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
337 ID2SYM(mid));
339 else {
340 rb_funcall(klass, removed, 1, ID2SYM(mid));
344 void
345 rb_remove_method(VALUE klass, const char *name)
347 remove_method(klass, rb_intern(name));
351 * call-seq:
352 * remove_method(symbol) => self
354 * Removes the method identified by _symbol_ from the current
355 * class. For an example, see <code>Module.undef_method</code>.
358 static VALUE
359 rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
361 int i;
363 for (i = 0; i < argc; i++) {
364 remove_method(mod, rb_to_id(argv[i]));
366 return mod;
369 #undef rb_disable_super
370 #undef rb_enable_super
372 void
373 rb_disable_super(VALUE klass, const char *name)
375 /* obsolete - no use */
378 void
379 rb_enable_super(VALUE klass, const char *name)
381 rb_warning("rb_enable_super() is obsolete");
384 static void
385 rb_export_method(VALUE klass, ID name, ID noex)
387 NODE *fbody;
388 VALUE origin;
390 if (klass == rb_cObject) {
391 rb_secure(4);
393 fbody = search_method(klass, name, &origin);
394 if (!fbody && TYPE(klass) == T_MODULE) {
395 fbody = search_method(rb_cObject, name, &origin);
397 if (!fbody || !fbody->nd_body) {
398 rb_print_undef(klass, name, 0);
400 if (fbody->nd_body->nd_noex != noex) {
401 if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) {
402 rb_vm_check_redefinition_opt_method(fbody);
404 if (klass == origin) {
405 fbody->nd_body->nd_noex = noex;
407 else {
408 rb_add_method(klass, name, NEW_ZSUPER(), noex);
414 rb_method_boundp(VALUE klass, ID id, int ex)
416 NODE *method;
418 if ((method = rb_method_node(klass, id)) != 0) {
419 if (ex && (method->nd_noex & NOEX_PRIVATE)) {
420 return Qfalse;
422 return Qtrue;
424 return Qfalse;
427 void
428 rb_attr(VALUE klass, ID id, int read, int write, int ex)
430 const char *name;
431 ID attriv;
432 int noex;
434 if (!ex) {
435 noex = NOEX_PUBLIC;
437 else {
438 if (SCOPE_TEST(NOEX_PRIVATE)) {
439 noex = NOEX_PRIVATE;
440 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
441 "attribute accessor as module_function" :
442 "private attribute?");
444 else if (SCOPE_TEST(NOEX_PROTECTED)) {
445 noex = NOEX_PROTECTED;
447 else {
448 noex = NOEX_PUBLIC;
452 if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
453 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
455 name = rb_id2name(id);
456 if (!name) {
457 rb_raise(rb_eArgError, "argument needs to be symbol or string");
459 attriv = rb_intern_str(rb_sprintf("@%s", name));
460 if (read) {
461 rb_add_method(klass, id, NEW_IVAR(attriv), noex);
463 if (write) {
464 rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
468 void
469 rb_undef(VALUE klass, ID id)
471 VALUE origin;
472 NODE *body;
474 if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
475 rb_secure(4);
477 if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
478 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
479 rb_id2name(id));
481 rb_frozen_class_p(klass);
482 if (id == object_id || id == __send__ || id == idInitialize) {
483 rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
485 body = search_method(klass, id, &origin);
486 if (!body || !body->nd_body) {
487 const char *s0 = " class";
488 VALUE c = klass;
490 if (FL_TEST(c, FL_SINGLETON)) {
491 VALUE obj = rb_iv_get(klass, "__attached__");
493 switch (TYPE(obj)) {
494 case T_MODULE:
495 case T_CLASS:
496 c = obj;
497 s0 = "";
500 else if (TYPE(c) == T_MODULE) {
501 s0 = " module";
503 rb_name_error(id, "undefined method `%s' for%s `%s'",
504 rb_id2name(id), s0, rb_class2name(c));
507 rb_add_method(klass, id, 0, NOEX_PUBLIC);
509 if (FL_TEST(klass, FL_SINGLETON)) {
510 rb_funcall(rb_iv_get(klass, "__attached__"),
511 singleton_undefined, 1, ID2SYM(id));
513 else {
514 rb_funcall(klass, undefined, 1, ID2SYM(id));
519 * call-seq:
520 * undef_method(symbol) => self
522 * Prevents the current class from responding to calls to the named
523 * method. Contrast this with <code>remove_method</code>, which deletes
524 * the method from the particular class; Ruby will still search
525 * superclasses and mixed-in modules for a possible receiver.
527 * class Parent
528 * def hello
529 * puts "In parent"
530 * end
531 * end
532 * class Child < Parent
533 * def hello
534 * puts "In child"
535 * end
536 * end
539 * c = Child.new
540 * c.hello
543 * class Child
544 * remove_method :hello # remove from child, still in parent
545 * end
546 * c.hello
549 * class Child
550 * undef_method :hello # prevent any calls to 'hello'
551 * end
552 * c.hello
554 * <em>produces:</em>
556 * In child
557 * In parent
558 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
561 static VALUE
562 rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
564 int i;
565 for (i = 0; i < argc; i++) {
566 rb_undef(mod, rb_to_id(argv[i]));
568 return mod;
572 * call-seq:
573 * mod.method_defined?(symbol) => true or false
575 * Returns +true+ if the named method is defined by
576 * _mod_ (or its included modules and, if _mod_ is a class,
577 * its ancestors). Public and protected methods are matched.
579 * module A
580 * def method1() end
581 * end
582 * class B
583 * def method2() end
584 * end
585 * class C < B
586 * include A
587 * def method3() end
588 * end
590 * A.method_defined? :method1 #=> true
591 * C.method_defined? "method1" #=> true
592 * C.method_defined? "method2" #=> true
593 * C.method_defined? "method3" #=> true
594 * C.method_defined? "method4" #=> false
597 static VALUE
598 rb_mod_method_defined(VALUE mod, VALUE mid)
600 return rb_method_boundp(mod, rb_to_id(mid), 1);
603 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
606 * call-seq:
607 * mod.public_method_defined?(symbol) => true or false
609 * Returns +true+ if the named public method is defined by
610 * _mod_ (or its included modules and, if _mod_ is a class,
611 * its ancestors).
613 * module A
614 * def method1() end
615 * end
616 * class B
617 * protected
618 * def method2() end
619 * end
620 * class C < B
621 * include A
622 * def method3() end
623 * end
625 * A.method_defined? :method1 #=> true
626 * C.public_method_defined? "method1" #=> true
627 * C.public_method_defined? "method2" #=> false
628 * C.method_defined? "method2" #=> true
631 static VALUE
632 rb_mod_public_method_defined(VALUE mod, VALUE mid)
634 ID id = rb_to_id(mid);
635 NODE *method;
637 method = rb_method_node(mod, id);
638 if (method) {
639 if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
640 return Qtrue;
642 return Qfalse;
646 * call-seq:
647 * mod.private_method_defined?(symbol) => true or false
649 * Returns +true+ if the named private method is defined by
650 * _ mod_ (or its included modules and, if _mod_ is a class,
651 * its ancestors).
653 * module A
654 * def method1() end
655 * end
656 * class B
657 * private
658 * def method2() end
659 * end
660 * class C < B
661 * include A
662 * def method3() end
663 * end
665 * A.method_defined? :method1 #=> true
666 * C.private_method_defined? "method1" #=> false
667 * C.private_method_defined? "method2" #=> true
668 * C.method_defined? "method2" #=> false
671 static VALUE
672 rb_mod_private_method_defined(VALUE mod, VALUE mid)
674 ID id = rb_to_id(mid);
675 NODE *method;
677 method = rb_method_node(mod, id);
678 if (method) {
679 if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
680 return Qtrue;
682 return Qfalse;
686 * call-seq:
687 * mod.protected_method_defined?(symbol) => true or false
689 * Returns +true+ if the named protected method is defined
690 * by _mod_ (or its included modules and, if _mod_ is a
691 * class, its ancestors).
693 * module A
694 * def method1() end
695 * end
696 * class B
697 * protected
698 * def method2() end
699 * end
700 * class C < B
701 * include A
702 * def method3() end
703 * end
705 * A.method_defined? :method1 #=> true
706 * C.protected_method_defined? "method1" #=> false
707 * C.protected_method_defined? "method2" #=> true
708 * C.method_defined? "method2" #=> true
711 static VALUE
712 rb_mod_protected_method_defined(VALUE mod, VALUE mid)
714 ID id = rb_to_id(mid);
715 NODE *method;
717 method = rb_method_node(mod, id);
718 if (method) {
719 if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
720 return Qtrue;
722 return Qfalse;
725 void
726 rb_alias(VALUE klass, ID name, ID def)
728 NODE *orig_fbody, *node;
729 VALUE singleton = 0;
730 st_data_t data;
732 rb_frozen_class_p(klass);
733 if (klass == rb_cObject) {
734 rb_secure(4);
736 orig_fbody = search_method(klass, def, 0);
737 if (!orig_fbody || !orig_fbody->nd_body) {
738 if (TYPE(klass) == T_MODULE) {
739 orig_fbody = search_method(rb_cObject, def, 0);
742 if (!orig_fbody || !orig_fbody->nd_body) {
743 rb_print_undef(klass, def, 0);
745 if (FL_TEST(klass, FL_SINGLETON)) {
746 singleton = rb_iv_get(klass, "__attached__");
749 orig_fbody->nd_cnt++;
751 if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
752 node = (NODE *)data;
753 if (node) {
754 if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
755 rb_warning("discarding old %s", rb_id2name(name));
757 if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
758 rb_vm_check_redefinition_opt_method(node);
763 st_insert(RCLASS_M_TBL(klass), name,
764 (st_data_t) NEW_FBODY(
765 NEW_METHOD(orig_fbody->nd_body->nd_body,
766 orig_fbody->nd_body->nd_clss,
767 NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
769 rb_clear_cache_by_id(name);
771 if (!ruby_running) return;
773 if (singleton) {
774 rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
776 else {
777 rb_funcall(klass, added, 1, ID2SYM(name));
782 * call-seq:
783 * alias_method(new_name, old_name) => self
785 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
786 * be used to retain access to methods that are overridden.
788 * module Mod
789 * alias_method :orig_exit, :exit
790 * def exit(code=0)
791 * puts "Exiting with code #{code}"
792 * orig_exit(code)
793 * end
794 * end
795 * include Mod
796 * exit(99)
798 * <em>produces:</em>
800 * Exiting with code 99
803 static VALUE
804 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
806 rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
807 return mod;
810 static void
811 secure_visibility(VALUE self)
813 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
814 rb_raise(rb_eSecurityError,
815 "Insecure: can't change method visibility");
819 static void
820 set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
822 int i;
823 secure_visibility(self);
824 for (i = 0; i < argc; i++) {
825 rb_export_method(self, rb_to_id(argv[i]), ex);
827 rb_clear_cache_by_class(self);
831 * call-seq:
832 * public => self
833 * public(symbol, ...) => self
835 * With no arguments, sets the default visibility for subsequently
836 * defined methods to public. With arguments, sets the named methods to
837 * have public visibility.
840 static VALUE
841 rb_mod_public(int argc, VALUE *argv, VALUE module)
843 secure_visibility(module);
844 if (argc == 0) {
845 SCOPE_SET(NOEX_PUBLIC);
847 else {
848 set_method_visibility(module, argc, argv, NOEX_PUBLIC);
850 return module;
854 * call-seq:
855 * protected => self
856 * protected(symbol, ...) => self
858 * With no arguments, sets the default visibility for subsequently
859 * defined methods to protected. With arguments, sets the named methods
860 * to have protected visibility.
863 static VALUE
864 rb_mod_protected(int argc, VALUE *argv, VALUE module)
866 secure_visibility(module);
867 if (argc == 0) {
868 SCOPE_SET(NOEX_PROTECTED);
870 else {
871 set_method_visibility(module, argc, argv, NOEX_PROTECTED);
873 return module;
877 * call-seq:
878 * private => self
879 * private(symbol, ...) => self
881 * With no arguments, sets the default visibility for subsequently
882 * defined methods to private. With arguments, sets the named methods
883 * to have private visibility.
885 * module Mod
886 * def a() end
887 * def b() end
888 * private
889 * def c() end
890 * private :a
891 * end
892 * Mod.private_instance_methods #=> [:a, :c]
895 static VALUE
896 rb_mod_private(int argc, VALUE *argv, VALUE module)
898 secure_visibility(module);
899 if (argc == 0) {
900 SCOPE_SET(NOEX_PRIVATE);
902 else {
903 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
905 return module;
909 * call-seq:
910 * mod.public_class_method(symbol, ...) => mod
912 * Makes a list of existing class methods public.
915 static VALUE
916 rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
918 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
919 return obj;
923 * call-seq:
924 * mod.private_class_method(symbol, ...) => mod
926 * Makes existing class methods private. Often used to hide the default
927 * constructor <code>new</code>.
929 * class SimpleSingleton # Not thread safe
930 * private_class_method :new
931 * def SimpleSingleton.create(*args, &block)
932 * @me = new(*args, &block) if ! @me
933 * @me
934 * end
935 * end
938 static VALUE
939 rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
941 set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
942 return obj;
946 * call-seq:
947 * public
948 * public(symbol, ...)
950 * With no arguments, sets the default visibility for subsequently
951 * defined methods to public. With arguments, sets the named methods to
952 * have public visibility.
955 static VALUE
956 top_public(int argc, VALUE *argv)
958 return rb_mod_public(argc, argv, rb_cObject);
961 static VALUE
962 top_private(int argc, VALUE *argv)
964 return rb_mod_private(argc, argv, rb_cObject);
968 * call-seq:
969 * module_function(symbol, ...) => self
971 * Creates module functions for the named methods. These functions may
972 * be called with the module as a receiver, and also become available
973 * as instance methods to classes that mix in the module. Module
974 * functions are copies of the original, and so may be changed
975 * independently. The instance-method versions are made private. If
976 * used with no arguments, subsequently defined methods become module
977 * functions.
979 * module Mod
980 * def one
981 * "This is one"
982 * end
983 * module_function :one
984 * end
985 * class Cls
986 * include Mod
987 * def callOne
988 * one
989 * end
990 * end
991 * Mod.one #=> "This is one"
992 * c = Cls.new
993 * c.callOne #=> "This is one"
994 * module Mod
995 * def one
996 * "This is the new one"
997 * end
998 * end
999 * Mod.one #=> "This is one"
1000 * c.callOne #=> "This is the new one"
1003 static VALUE
1004 rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
1006 int i;
1007 ID id;
1008 NODE *fbody;
1010 if (TYPE(module) != T_MODULE) {
1011 rb_raise(rb_eTypeError, "module_function must be called for modules");
1014 secure_visibility(module);
1015 if (argc == 0) {
1016 SCOPE_SET(NOEX_MODFUNC);
1017 return module;
1020 set_method_visibility(module, argc, argv, NOEX_PRIVATE);
1022 for (i = 0; i < argc; i++) {
1023 VALUE m = module;
1025 id = rb_to_id(argv[i]);
1026 for (;;) {
1027 fbody = search_method(m, id, &m);
1028 if (fbody == 0) {
1029 fbody = search_method(rb_cObject, id, &m);
1031 if (fbody == 0 || fbody->nd_body == 0) {
1032 rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
1034 if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
1035 break; /* normal case: need not to follow 'super' link */
1037 m = RCLASS_SUPER(m);
1038 if (!m)
1039 break;
1041 rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
1042 NOEX_PUBLIC);
1044 return module;
1048 rb_method_basic_definition_p(VALUE klass, ID id)
1050 NODE *node = rb_method_node(klass, id);
1051 if (node && (node->nd_noex & NOEX_BASIC))
1052 return 1;
1053 return 0;
1057 * call-seq:
1058 * obj.respond_to?(symbol, include_private=false) => true or false
1060 * Returns +true+> if _obj_ responds to the given
1061 * method. Private methods are included in the search only if the
1062 * optional second parameter evaluates to +true+.
1066 rb_obj_respond_to(VALUE obj, ID id, int priv)
1068 VALUE klass = CLASS_OF(obj);
1070 if (rb_method_basic_definition_p(klass, idRespond_to)) {
1071 return rb_method_boundp(klass, id, !priv);
1073 else {
1074 VALUE args[2];
1075 int n = 0;
1076 args[n++] = ID2SYM(id);
1077 if (priv)
1078 args[n++] = Qtrue;
1079 return RTEST(rb_funcall2(obj, idRespond_to, n, args));
1084 rb_respond_to(VALUE obj, ID id)
1086 return rb_obj_respond_to(obj, id, Qfalse);
1090 * call-seq:
1091 * obj.respond_to?(symbol, include_private=false) => true or false
1093 * Returns +true+> if _obj_ responds to the given
1094 * method. Private methods are included in the search only if the
1095 * optional second parameter evaluates to +true+.
1098 static VALUE
1099 obj_respond_to(int argc, VALUE *argv, VALUE obj)
1101 VALUE mid, priv;
1102 ID id;
1104 rb_scan_args(argc, argv, "11", &mid, &priv);
1105 id = rb_to_id(mid);
1106 if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
1107 return Qtrue;
1109 return Qfalse;
1112 void
1113 Init_eval_method(void)
1115 #undef rb_intern
1117 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
1119 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
1120 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
1121 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
1122 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
1123 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
1124 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
1125 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
1127 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
1128 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
1129 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
1130 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
1131 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
1132 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
1134 rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
1135 rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);
1137 object_id = rb_intern("object_id");
1138 __send__ = rb_intern("__send__");
1139 eqq = rb_intern("===");
1140 each = rb_intern("each");
1141 aref = rb_intern("[]");
1142 aset = rb_intern("[]=");
1143 match = rb_intern("=~");
1144 missing = rb_intern("method_missing");
1145 added = rb_intern("method_added");
1146 singleton_added = rb_intern("singleton_method_added");
1147 removed = rb_intern("method_removed");
1148 singleton_removed = rb_intern("singleton_method_removed");
1149 undefined = rb_intern("method_undefined");
1150 singleton_undefined = rb_intern("singleton_method_undefined");