Skip to content

HTTPS clone URL

Subversion checkout URL

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