Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1404 lines (1221 sloc) 33.472 kb
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1 /**********************************************************************
2
3 vm_eval.c -
4
5 $Author: nobu $
6 created at: Sat May 24 16:02:32 JST 2008
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12 **********************************************************************/
13
14 #include "ruby/ruby.h"
15 #include "ruby/node.h"
16 #include "ruby/st.h"
17
18 #include "vm_method.c"
19
20 static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
21 static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
22 static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
23 static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
24 static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
25 static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex);
26 static VALUE vm_eval_body(rb_thread_t *th);
27 static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
28
29 static inline VALUE
30 vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
31 int argc, const VALUE *argv, const NODE *body, int nosuper)
32 {
33 VALUE val;
34 rb_block_t *blockptr = 0;
35
36 if (0) printf("id: %s, nd: %s, argc: %d, passed: %p\n",
37 rb_id2name(id), ruby_node_name(nd_type(body)),
38 argc, th->passed_block);
39
40 if (th->passed_block) {
41 blockptr = th->passed_block;
42 th->passed_block = 0;
43 }
44 switch (nd_type(body)) {
45 case RUBY_VM_METHOD_NODE:{
46 rb_control_frame_t *reg_cfp;
47 VALUE iseqval = (VALUE)body->nd_body;
48 int i;
49
50 rb_vm_set_finish_env(th);
51 reg_cfp = th->cfp;
52
53 CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
54
55 *reg_cfp->sp++ = recv;
56 for (i = 0; i < argc; i++) {
57 *reg_cfp->sp++ = argv[i];
58 }
59
60 vm_setup_method(th, reg_cfp, argc, blockptr, 0, iseqval, recv, klass);
61 val = vm_eval_body(th);
62 break;
63 }
64 case NODE_CFUNC: {
65 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
66 {
67 rb_control_frame_t *reg_cfp = th->cfp;
68 rb_control_frame_t *cfp =
69 vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
70 recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
71
72 cfp->method_id = id;
73 cfp->method_class = klass;
74
75 val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
76
77 if (reg_cfp != th->cfp + 1) {
78 SDR2(reg_cfp);
79 SDR2(th->cfp-5);
80 rb_bug("cfp consistency error - call0");
81 th->cfp = reg_cfp;
82 }
83 vm_pop_frame(th);
84 }
85 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
86 break;
87 }
88 case NODE_ATTRSET:{
89 if (argc != 1) {
90 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
91 }
92 val = rb_ivar_set(recv, body->nd_vid, argv[0]);
93 break;
94 }
95 case NODE_IVAR: {
96 if (argc != 0) {
97 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
98 argc);
99 }
100 val = rb_attr_get(recv, body->nd_vid);
101 break;
102 }
103 case NODE_BMETHOD:{
104 val = vm_call_bmethod(th, id, body->nd_cval,
105 recv, klass, argc, (VALUE *)argv, blockptr);
106 break;
107 }
108 default:
109 rb_bug("unsupported: vm_call0(%s)", ruby_node_name(nd_type(body)));
110 }
111 RUBY_VM_CHECK_INTS();
112 return val;
113 }
114
115 VALUE
116 rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
117 int argc, const VALUE *argv, const NODE *body, int nosuper)
118 {
119 return vm_call0(th, klass, recv, id, oid, argc, argv, body, nosuper);
120 }
121
122 static inline VALUE
123 vm_call_super(rb_thread_t * const th, const int argc, const VALUE * const argv)
124 {
125 VALUE recv = th->cfp->self;
126 VALUE klass;
127 ID id;
128 NODE *body;
129 rb_control_frame_t *cfp = th->cfp;
130
131 if (!cfp->iseq) {
132 klass = cfp->method_class;
133 klass = RCLASS_SUPER(klass);
134
135 if (klass == 0) {
335ed79 forgot to commit these too
Laurent Sansonetti authored
136 klass = vm_search_normal_superclass(cfp->method_class, recv, cfp->method_id);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
137 }
138
139 id = cfp->method_id;
140 }
141 else {
142 rb_bug("vm_call_super: should not be reached");
143 }
144
2dd3cc0 fixed rb_call_super(), used in StringIO
Laurent Sansonetti authored
145 #if WITH_OBJC
146 SEL sel;
147 IMP imp;
148
149 if (argc == 0) {
150 const char *id_str;
151 size_t id_str_len;
152
153 id_str = rb_id2name(id);
154 id_str_len = strlen(id_str);
155 if (id_str[id_str_len - 1] == ':') {
156 char buf[100];
157 strncpy(buf, id_str, sizeof buf);
158 buf[MIN(sizeof buf, id_str_len - 1)] = '\0';
159 id = rb_intern(buf);
160 }
161 }
162
163 body = rb_objc_method_node(klass, id, &imp, &sel);
164 if (body != NULL) {
165 body = body->nd_body;
166 return vm_call0(th, klass, recv, id, id, argc, argv, body, CALL_SUPER);
167 }
168 else if (imp != NULL) {
169 struct rb_objc_method_sig sig;
170 Method m;
171
172 m = class_getInstanceMethod((Class)klass, sel);
173 assert(m != NULL);
174 sig.argc = method_getNumberOfArguments(m);
175 sig.types = method_getTypeEncoding(m);
176 return rb_objc_call2(recv, klass, sel, imp, &sig, NULL, argc, (VALUE *)argv);
177 }
178 else {
179 dp(recv);
180 dp(klass);
181 dpi(id);
182 rb_bug("vm_call_super: not found");
183 }
184 #else
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
185 body = rb_method_node(klass, id); /* this returns NODE_METHOD */
186
187 if (body) {
188 body = body->nd_body;
189 }
190 else {
191 dp(recv);
192 dp(klass);
193 dpi(id);
194 rb_bug("vm_call_super: not found");
195 }
196
197 return vm_call0(th, klass, recv, id, id, argc, argv, body, CALL_SUPER);
2dd3cc0 fixed rb_call_super(), used in StringIO
Laurent Sansonetti authored
198 #endif
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
199 }
200
201 VALUE
202 rb_call_super(int argc, const VALUE *argv)
203 {
204 PASS_PASSED_BLOCK();
205 return vm_call_super(GET_THREAD(), argc, argv);
206 }
207
208 static inline void
209 stack_check(void)
210 {
211 rb_thread_t *th = GET_THREAD();
212
213 if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
214 rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
215 rb_exc_raise(sysstack_error);
216 }
217 }
218
219 static inline VALUE
220 rb_call0(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv,
221 int scope, VALUE self)
222 {
223 NODE *body, *method;
224 int noex;
225 ID id = mid;
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
226 #if !WITH_OBJC
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
227 struct cache_entry *ent;
228 #endif
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
229 rb_thread_t *th = GET_THREAD();
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
230
231 if (!klass) {
232 rb_raise(rb_eNotImpError,
233 "method `%s' called on terminated object (%p)",
234 rb_id2name(mid), (void *)recv);
235 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
236
237 #if WITH_OBJC
238 IMP imp;
239 SEL sel;
240
241 if (argc > 0 && mid != ID_ALLOCATOR) {
242 const char *mid_str;
243 char buf[100];
244 size_t len;
245
246 mid_str = rb_id2name(mid);
247 len = strlen(mid_str);
248 if (mid_str[len - 1] != ':') {
249 snprintf(buf, sizeof buf, "%s:", mid_str);
250 mid = rb_intern(buf);
251 }
252 }
253
254 method = rb_objc_method_node(klass, mid, &imp, &sel);
255
256 if (imp != NULL && method == NULL)
257 return rb_objc_call(recv, sel, argc, (VALUE *)argv);
258
259 DLOG("RCALL", "%c[<%s %p> %s] node=%p", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)sel, method);
260
261 if (method == NULL) {
5db564c correct missing_scope, so that a rb_funcall() call that throws NoMethodE...
Laurent Sansonetti authored
262 int missing_scope = scope == 2 ? NOEX_VCALL : scope == 3 ? NOEX_SUPER : 0;
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
263 return method_missing(recv, mid, argc, argv, missing_scope);
264 }
265 else {
266 noex = method->nd_noex;
267 klass = method->nd_clss;
268 body = method->nd_body;
269 }
270 #else
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
271 /* is it in the method cache? */
272 ent = cache + EXPR1(klass, mid);
273
274 if (ent->mid == mid && ent->klass == klass) {
275 if (!ent->method) {
276 return method_missing(recv, mid, argc, argv,
277 scope == 2 ? NOEX_VCALL : 0);
278 }
279 id = ent->mid0;
280 noex = ent->method->nd_noex;
281 klass = ent->method->nd_clss;
282 body = ent->method->nd_body;
283 }
284 else if ((method = rb_get_method_body(klass, id, &id)) != 0) {
285 noex = method->nd_noex;
286 klass = method->nd_clss;
287 body = method->nd_body;
288 }
289 else {
290 if (scope == 3) {
291 return method_missing(recv, mid, argc, argv, NOEX_SUPER);
292 }
293 return method_missing(recv, mid, argc, argv,
294 scope == 2 ? NOEX_VCALL : 0);
295 }
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
296 #endif
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
297
298 if (mid != missing) {
299 /* receiver specified form for private method */
300 if (UNLIKELY(noex)) {
301 if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == 0) {
302 return method_missing(recv, mid, argc, argv, NOEX_PRIVATE);
303 }
304
305 /* self must be kind of a specified form for protected method */
306 if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == 0) {
307 VALUE defined_class = klass;
308
309 if (TYPE(defined_class) == T_ICLASS) {
310 defined_class = RBASIC(defined_class)->klass;
311 }
312
313 if (self == Qundef) {
314 self = th->cfp->self;
315 }
316 if (!rb_obj_is_kind_of(self, rb_class_real(defined_class))) {
317 return method_missing(recv, mid, argc, argv, NOEX_PROTECTED);
318 }
319 }
320
321 if (NOEX_SAFE(noex) > th->safe_level) {
322 rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(mid));
323 }
324 }
325 }
326
327 stack_check();
328 return vm_call0(th, klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER);
329 }
330
331 static inline VALUE
332 rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
333 {
334 return rb_call0(klass, recv, mid, argc, argv, scope, Qundef);
335 }
336
337 /*
338 * call-seq:
339 * obj.method_missing(symbol [, *args] ) => result
340 *
341 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
342 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
343 * are any arguments that were passed to it. By default, the interpreter
344 * raises an error when this method is called. However, it is possible
345 * to override the method to provide more dynamic behavior.
346 * If it is decided that a particular method should not be handled, then
347 * <i>super</i> should be called, so that ancestors can pick up the
348 * missing method.
349 * The example below creates
350 * a class <code>Roman</code>, which responds to methods with names
351 * consisting of roman numerals, returning the corresponding integer
352 * values.
353 *
354 * class Roman
355 * def romanToInt(str)
356 * # ...
357 * end
358 * def method_missing(methId)
359 * str = methId.id2name
360 * romanToInt(str)
361 * end
362 * end
363 *
364 * r = Roman.new
365 * r.iv #=> 4
366 * r.xxiii #=> 23
367 * r.mm #=> 2000
368 */
369
370 static VALUE
371 rb_method_missing(int argc, const VALUE *argv, VALUE obj)
372 {
373 ID id;
374 VALUE exc = rb_eNoMethodError;
375 const char *format = 0;
376 rb_thread_t *th = GET_THREAD();
377 int last_call_status = th->method_missing_reason;
378 if (argc == 0 || !SYMBOL_P(argv[0])) {
379 rb_raise(rb_eArgError, "no id given");
380 }
381
382 stack_check();
383
384 id = SYM2ID(argv[0]);
385
386 if (last_call_status & NOEX_PRIVATE) {
387 format = "private method `%s' called for %s";
388 }
389 else if (last_call_status & NOEX_PROTECTED) {
390 format = "protected method `%s' called for %s";
391 }
392 else if (last_call_status & NOEX_VCALL) {
393 format = "undefined local variable or method `%s' for %s";
394 exc = rb_eNameError;
395 }
396 else if (last_call_status & NOEX_SUPER) {
397 format = "super: no superclass method `%s' for %s";
398 }
399 if (!format) {
400 format = "undefined method `%s' for %s";
401 }
402
403 {
404 int n = 0;
405 VALUE args[3];
406 args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
407 3, rb_str_new2(format), obj, argv[0]);
408 args[n++] = argv[0];
409 if (exc == rb_eNoMethodError) {
410 args[n++] = rb_ary_new4(argc - 1, argv + 1);
411 }
412 exc = rb_class_new_instance(n, args, exc);
413
414 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
415 rb_exc_raise(exc);
416 }
417
418 return Qnil; /* not reached */
419 }
420
421 static inline VALUE
422 method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
423 {
424 VALUE *nargv;
425 GET_THREAD()->method_missing_reason = call_status;
426
427 if (id == missing) {
428 rb_method_missing(argc, argv, obj);
429 }
430 else if (id == ID_ALLOCATOR) {
431 rb_raise(rb_eTypeError, "allocator undefined for %s",
432 rb_class2name(obj));
433 }
434
435 nargv = ALLOCA_N(VALUE, argc + 1);
436 nargv[0] = ID2SYM(id);
437 MEMCPY(nargv + 1, argv, VALUE, argc);
438
439 return rb_funcall2(obj, missing, argc + 1, nargv);
440 }
441
442 VALUE
443 rb_apply(VALUE recv, ID mid, VALUE args)
444 {
445 int argc;
446 VALUE *argv;
447
448 argc = RARRAY_LEN(args); /* Assigns LONG, but argc is INT */
449 argv = ALLOCA_N(VALUE, argc);
450 MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
451 return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
452 }
453
454 VALUE
455 rb_funcall(VALUE recv, ID mid, int n, ...)
456 {
457 VALUE *argv;
458 va_list ar;
459 va_init_list(ar, n);
460
461 if (n > 0) {
462 long i;
463
464 argv = ALLOCA_N(VALUE, n);
465
466 for (i = 0; i < n; i++) {
467 argv[i] = va_arg(ar, VALUE);
468 }
469 va_end(ar);
470 }
471 else {
472 argv = 0;
473 }
474 return rb_call(CLASS_OF(recv), recv, mid, n, argv, CALL_FCALL);
475 }
476
477 VALUE
478 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
479 {
480 return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
481 }
482
483 VALUE
484 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
485 {
486 return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_PUBLIC);
487 }
488
489 static VALUE
490 send_internal(int argc, VALUE *argv, VALUE recv, int scope)
491 {
492 VALUE vid;
493 VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
494
495 if (argc == 0) {
496 rb_raise(rb_eArgError, "no method name given");
497 }
498
499 vid = *argv++; argc--;
500 PASS_PASSED_BLOCK();
501 return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
502 }
503
504 /*
505 * call-seq:
506 * obj.send(symbol [, args...]) => obj
507 * obj.__send__(symbol [, args...]) => obj
508 *
509 * Invokes the method identified by _symbol_, passing it any
510 * arguments specified. You can use <code>__send__</code> if the name
511 * +send+ clashes with an existing method in _obj_.
512 *
513 * class Klass
514 * def hello(*args)
515 * "Hello " + args.join(' ')
516 * end
517 * end
518 * k = Klass.new
519 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
520 */
521
522 VALUE
523 rb_f_send(int argc, VALUE *argv, VALUE recv)
524 {
525 return send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE);
526 }
527
528 /*
529 * call-seq:
530 * obj.public_send(symbol [, args...]) => obj
531 *
532 * Invokes the method identified by _symbol_, passing it any
533 * arguments specified. Unlike send, public_send calls public
534 * methods only.
535 *
536 * 1.public_send(:puts, "hello") # causes NoMethodError
537 */
538
539 VALUE
540 rb_f_public_send(int argc, VALUE *argv, VALUE recv)
541 {
542 return send_internal(argc, argv, recv, NOEX_PUBLIC);
543 }
544
545 /* yield */
546
547 static inline VALUE
548 rb_yield_0(int argc, const VALUE * argv)
549 {
550 return vm_yield(GET_THREAD(), argc, argv);
551 }
552
553 VALUE
554 rb_yield(VALUE val)
555 {
556 if (val == Qundef) {
557 return rb_yield_0(0, 0);
558 }
559 else {
560 return rb_yield_0(1, &val);
561 }
562 }
563
564 VALUE
565 rb_yield_values(int n, ...)
566 {
567 if (n == 0) {
568 return rb_yield_0(0, 0);
569 }
570 else {
571 int i;
572 VALUE *argv;
573 va_list args;
574 argv = ALLOCA_N(VALUE, n);
575
576 va_init_list(args, n);
577 for (i=0; i<n; i++) {
578 argv[i] = va_arg(args, VALUE);
579 }
580 va_end(args);
581
582 return rb_yield_0(n, argv);
583 }
584 }
585
586 VALUE
587 rb_yield_values2(int argc, const VALUE *argv)
588 {
589 return rb_yield_0(argc, argv);
590 }
591
592 VALUE
593 rb_yield_splat(VALUE values)
594 {
595 VALUE tmp = rb_check_array_type(values);
596 volatile VALUE v;
597 if (NIL_P(tmp)) {
598 rb_raise(rb_eArgError, "not an array");
599 }
600 v = rb_yield_0(RARRAY_LEN(tmp), RARRAY_PTR(tmp));
601 return v;
602 }
603
604 static VALUE
605 loop_i(void)
606 {
607 for (;;) {
608 rb_yield_0(0, 0);
609 }
610 return Qnil;
611 }
612
613 /*
614 * call-seq:
615 * loop {|| block }
616 *
617 * Repeatedly executes the block.
618 *
619 * loop do
620 * print "Input: "
621 * line = gets
622 * break if !line or line =~ /^qQ/
623 * # ...
624 * end
625 *
626 * StopIteration raised in the block breaks the loop.
627 */
628
629 static VALUE
630 rb_f_loop(void)
631 {
632 rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
633 return Qnil; /* dummy */
634 }
635
636 VALUE
637 rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
638 VALUE (* bl_proc) (ANYARGS), VALUE data2)
639 {
640 int state;
641 volatile VALUE retval = Qnil;
642 NODE *node = NEW_IFUNC(bl_proc, data2);
643 rb_thread_t *th = GET_THREAD();
644 rb_control_frame_t *cfp = th->cfp;
645
646 TH_PUSH_TAG(th);
647 state = TH_EXEC_TAG();
648 if (state == 0) {
649 iter_retry:
650 {
651 rb_block_t *blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
662c14c adding more missing write barriers
Laurent Sansonetti authored
652 GC_WB(&blockptr->iseq, (void *)node);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
653 blockptr->proc = 0;
654 th->passed_block = blockptr;
655 }
656 retval = (*it_proc) (data1);
657 }
658 else {
659 VALUE err = th->errinfo;
660 if (state == TAG_BREAK) {
661 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
662 VALUE *cdfp = cfp->dfp;
663
664 if (cdfp == escape_dfp) {
665 state = 0;
666 th->state = 0;
667 th->errinfo = Qnil;
668 th->cfp = cfp;
669 }
670 else{
671 /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
672 }
673 }
674 else if (state == TAG_RETRY) {
675 VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
676 VALUE *cdfp = cfp->dfp;
677
678 if (cdfp == escape_dfp) {
679 state = 0;
680 th->state = 0;
681 th->errinfo = Qnil;
682 th->cfp = cfp;
683 goto iter_retry;
684 }
685 }
686 }
687 TH_POP_TAG();
688
689 switch (state) {
690 case 0:
691 break;
692 default:
693 TH_JUMP_TAG(th, state);
694 }
695 return retval;
696 }
697
698 struct iter_method_arg {
699 VALUE obj;
700 ID mid;
701 int argc;
702 VALUE *argv;
703 };
704
705 static VALUE
706 iterate_method(VALUE obj)
707 {
708 const struct iter_method_arg * arg =
709 (struct iter_method_arg *) obj;
710
711 return rb_call(CLASS_OF(arg->obj), arg->obj, arg->mid,
712 arg->argc, arg->argv, CALL_FCALL);
713 }
714
715 VALUE
716 rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
717 VALUE (*bl_proc) (ANYARGS), VALUE data2)
718 {
719 struct iter_method_arg arg;
720
721 arg.obj = obj;
722 arg.mid = mid;
723 arg.argc = argc;
724 arg.argv = argv;
725 return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
726 }
727
728 VALUE
729 rb_each(VALUE obj)
730 {
731 return rb_call(CLASS_OF(obj), obj, idEach, 0, 0, CALL_FCALL);
732 }
733
734 static VALUE
735 eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line)
736 {
737 int state;
738 VALUE result = Qundef;
739 VALUE envval;
740 rb_binding_t *bind = 0;
741 rb_thread_t *th = GET_THREAD();
742 rb_env_t *env = NULL;
743 rb_block_t block;
744
745 if (file == 0) {
746 file = rb_sourcefile();
747 line = rb_sourceline();
748 }
749
750 PUSH_TAG();
751 if ((state = EXEC_TAG()) == 0) {
752 rb_iseq_t *iseq;
753 volatile VALUE iseqval;
754
755 if (scope != Qnil) {
756 if (rb_obj_is_kind_of(scope, rb_cBinding)) {
757 GetBindingPtr(scope, bind);
758 envval = bind->env;
759 }
760 else {
761 rb_raise(rb_eTypeError,
762 "wrong argument type %s (expected Binding)",
763 rb_obj_classname(scope));
764 }
765 GetEnvPtr(envval, env);
766 th->base_block = &env->block;
767 }
768 else {
769 rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
770 block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
771 th->base_block = &block;
772 th->base_block->self = self;
773 th->base_block->iseq = cfp->iseq; /* TODO */
774 }
775
776 /* make eval iseq */
777 th->parse_in_eval++;
778 iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
779 th->parse_in_eval--;
780
781 vm_set_eval_stack(th, iseqval, cref);
782 th->base_block = 0;
783
784 if (0) { /* for debug */
785 extern VALUE ruby_iseq_disasm(VALUE);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_CPTR...
Laurent Sansonetti authored
786 printf("%s\n", RSTRING_PTR(ruby_iseq_disasm(iseqval)));
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
787 }
788
789 /* save new env */
790 GetISeqPtr(iseqval, iseq);
791 if (bind && iseq->local_size > 0) {
792 bind->env = vm_make_env_object(th, th->cfp);
793 }
794
795 /* kick */
796 CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
797 result = vm_eval_body(th);
798 }
799 POP_TAG();
800
801 if (state) {
802 if (state == TAG_RAISE) {
803 VALUE errinfo = th->errinfo;
804 if (strcmp(file, "(eval)") == 0) {
805 VALUE mesg, errat, bt2;
806 extern VALUE rb_get_backtrace(VALUE info);
807
808 errat = rb_get_backtrace(errinfo);
809 mesg = rb_attr_get(errinfo, rb_intern("mesg"));
810 if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
811 (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_CPTR...
Laurent Sansonetti authored
812 if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
813 rb_str_update(mesg, 0, 0, rb_str_new2(": "));
814 rb_str_update(mesg, 0, 0, RARRAY_AT(errat, 0));
815 }
816 rb_ary_store(errat, 0, RARRAY_AT(bt2, 0));
817 }
818 }
819 rb_exc_raise(errinfo);
820 }
821 JUMP_TAG(state);
822 }
823 return result;
824 }
825
826 static VALUE
827 eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
828 {
829 return eval_string_with_cref(self, src, scope, 0, file, line);
830 }
831
832 /*
833 * call-seq:
834 * eval(string [, binding [, filename [,lineno]]]) => obj
835 *
836 * Evaluates the Ruby expression(s) in <em>string</em>. If
837 * <em>binding</em> is given, the evaluation is performed in its
838 * context. The binding may be a <code>Binding</code> object or a
839 * <code>Proc</code> object. If the optional <em>filename</em> and
840 * <em>lineno</em> parameters are present, they will be used when
841 * reporting syntax errors.
842 *
843 * def getBinding(str)
844 * return binding
845 * end
846 * str = "hello"
847 * eval "str + ' Fred'" #=> "hello Fred"
848 * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
849 */
850
851 VALUE
852 rb_f_eval(int argc, VALUE *argv, VALUE self)
853 {
854 VALUE src, scope, vfile, vline;
855 const char *file = "(eval)";
856 int line = 1;
857
858 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
859 if (rb_safe_level() >= 4) {
860 StringValue(src);
861 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
862 rb_raise(rb_eSecurityError,
863 "Insecure: can't modify trusted binding");
864 }
865 }
866 else {
867 SafeStringValue(src);
868 }
869 if (argc >= 3) {
870 StringValue(vfile);
871 }
872 if (argc >= 4) {
873 line = NUM2INT(vline);
874 }
875
876 if (!NIL_P(vfile))
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_CPTR...
Laurent Sansonetti authored
877 file = RSTRING_PTR(vfile);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
878 return eval_string(self, src, scope, file, line);
879 }
880
881 VALUE
882 rb_eval_string(const char *str)
883 {
884 return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
885 }
886
887 VALUE
888 rb_eval_string_protect(const char *str, int *state)
889 {
890 return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
891 }
892
893 VALUE
894 rb_eval_string_wrap(const char *str, int *state)
895 {
896 int status;
897 rb_thread_t *th = GET_THREAD();
898 VALUE self = th->top_self;
899 VALUE wrapper = th->top_wrapper;
900 VALUE val;
901
902 th->top_wrapper = rb_module_new();
903 th->top_self = rb_obj_clone(rb_vm_top_self());
904 rb_extend_object(th->top_self, th->top_wrapper);
905
906 val = rb_eval_string_protect(str, &status);
907
908 th->top_self = self;
909 th->top_wrapper = wrapper;
910
911 if (state) {
912 *state = status;
913 }
914 else if (status) {
915 JUMP_TAG(status);
916 }
917 return val;
918 }
919
920 VALUE
921 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
922 {
923 int state;
924 VALUE val = Qnil; /* OK */
925 volatile int safe = rb_safe_level();
926
927 if (OBJ_TAINTED(cmd)) {
928 level = 4;
929 }
930
931 if (TYPE(cmd) != T_STRING) {
932 PUSH_TAG();
933 rb_set_safe_level_force(level);
934 if ((state = EXEC_TAG()) == 0) {
935 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
936 RARRAY_PTR(arg));
937 }
938 POP_TAG();
939
940 rb_set_safe_level_force(safe);
941
942 if (state)
943 JUMP_TAG(state);
944 return val;
945 }
946
947 PUSH_TAG();
948 if ((state = EXEC_TAG()) == 0) {
949 val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
950 }
951 POP_TAG();
952
953 rb_set_safe_level_force(safe);
954 if (state) vm_jump_tag_but_local_jump(state, val);
955 return val;
956 }
957
958 /* block eval under the class/module context */
959
960 static VALUE
961 yield_under(VALUE under, VALUE self, VALUE values)
962 {
963 rb_thread_t *th = GET_THREAD();
964 rb_block_t block, *blockptr;
965 NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC);
966
967 if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
968 block = *blockptr;
969 block.self = self;
970 th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
971 }
972
973 if (values == Qundef) {
974 return vm_yield_with_cref(th, 0, 0, cref);
975 }
976 else {
977 return vm_yield_with_cref(th, RARRAY_LEN(values), RARRAY_PTR(values), cref);
978 }
979 }
980
981 /* string eval under the class/module context */
982 static VALUE
983 eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
984 {
985 NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC);
986
987 if (rb_safe_level() >= 4) {
988 StringValue(src);
989 }
990 else {
991 SafeStringValue(src);
992 }
993
994 return eval_string_with_cref(self, src, Qnil, cref, file, line);
995 }
996
997 static VALUE
998 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
999 {
1000 if (rb_block_given_p()) {
1001 if (argc > 0) {
1002 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
1003 }
1004 return yield_under(klass, self, Qundef);
1005 }
1006 else {
1007 const char *file = "(eval)";
1008 int line = 1;
1009
1010 if (argc == 0) {
1011 rb_raise(rb_eArgError, "block not supplied");
1012 }
1013 else {
1014 if (rb_safe_level() >= 4) {
1015 StringValue(argv[0]);
1016 }
1017 else {
1018 SafeStringValue(argv[0]);
1019 }
1020 if (argc > 3) {
1021 const char *name = rb_id2name(rb_frame_callee());
1022 rb_raise(rb_eArgError,
1023 "wrong number of arguments: %s(src) or %s{..}",
1024 name, name);
1025 }
1026 if (argc > 2)
1027 line = NUM2INT(argv[2]);
1028 if (argc > 1) {
1029 file = StringValuePtr(argv[1]);
1030 }
1031 }
1032 return eval_under(klass, self, argv[0], file, line);
1033 }
1034 }
1035
1036 /*
1037 * call-seq:
1038 * obj.instance_eval(string [, filename [, lineno]] ) => obj
1039 * obj.instance_eval {| | block } => obj
1040 *
1041 * Evaluates a string containing Ruby source code, or the given block,
1042 * within the context of the receiver (_obj_). In order to set the
1043 * context, the variable +self+ is set to _obj_ while
1044 * the code is executing, giving the code access to _obj_'s
1045 * instance variables. In the version of <code>instance_eval</code>
1046 * that takes a +String+, the optional second and third
1047 * parameters supply a filename and starting line number that are used
1048 * when reporting compilation errors.
1049 *
1050 * class KlassWithSecret
1051 * def initialize
1052 * @secret = 99
1053 * end
1054 * end
1055 * k = KlassWithSecret.new
1056 * k.instance_eval { @secret } #=> 99
1057 */
1058
1059 VALUE
1060 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
1061 {
1062 VALUE klass;
1063
1064 if (SPECIAL_CONST_P(self)) {
1065 klass = Qnil;
1066 }
1067 else {
1068 klass = rb_singleton_class(self);
1069 }
1070 return specific_eval(argc, argv, klass, self);
1071 }
1072
1073 /*
1074 * call-seq:
1075 * obj.instance_exec(arg...) {|var...| block } => obj
1076 *
1077 * Executes the given block within the context of the receiver
1078 * (_obj_). In order to set the context, the variable +self+ is set
1079 * to _obj_ while the code is executing, giving the code access to
1080 * _obj_'s instance variables. Arguments are passed as block parameters.
1081 *
1082 * class KlassWithSecret
1083 * def initialize
1084 * @secret = 99
1085 * end
1086 * end
1087 * k = KlassWithSecret.new
1088 * k.instance_exec(5) {|x| @secret+x } #=> 104
1089 */
1090
1091 VALUE
1092 rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
1093 {
1094 VALUE klass;
1095
1096 if (SPECIAL_CONST_P(self)) {
1097 klass = Qnil;
1098 }
1099 else {
1100 klass = rb_singleton_class(self);
1101 }
1102 return yield_under(klass, self, rb_ary_new4(argc, argv));
1103 }
1104
1105 /*
1106 * call-seq:
1107 * mod.class_eval(string [, filename [, lineno]]) => obj
1108 * mod.module_eval {|| block } => obj
1109 *
1110 * Evaluates the string or block in the context of _mod_. This can
1111 * be used to add methods to a class. <code>module_eval</code> returns
1112 * the result of evaluating its argument. The optional _filename_
1113 * and _lineno_ parameters set the text for error messages.
1114 *
1115 * class Thing
1116 * end
1117 * a = %q{def hello() "Hello there!" end}
1118 * Thing.module_eval(a)
1119 * puts Thing.new.hello()
1120 * Thing.module_eval("invalid code", "dummy", 123)
1121 *
1122 * <em>produces:</em>
1123 *
1124 * Hello there!
1125 * dummy:123:in `module_eval': undefined local variable
1126 * or method `code' for Thing:Class
1127 */
1128
1129 VALUE
1130 rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
1131 {
1132 return specific_eval(argc, argv, mod, mod);
1133 }
1134
1135 /*
1136 * call-seq:
1137 * mod.module_exec(arg...) {|var...| block } => obj
1138 * mod.class_exec(arg...) {|var...| block } => obj
1139 *
1140 * Evaluates the given block in the context of the class/module.
1141 * The method defined in the block will belong to the receiver.
1142 *
1143 * class Thing
1144 * end
1145 * Thing.class_exec{
1146 * def hello() "Hello there!" end
1147 * }
1148 * puts Thing.new.hello()
1149 *
1150 * <em>produces:</em>
1151 *
1152 * Hello there!
1153 */
1154
1155 VALUE
1156 rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
1157 {
1158 return yield_under(mod, mod, rb_ary_new4(argc, argv));
1159 }
1160
1161 NORETURN(static VALUE rb_f_throw _((int, VALUE *)));
1162
1163 /*
1164 * call-seq:
1165 * throw(symbol [, obj])
1166 *
1167 * Transfers control to the end of the active +catch+ block
1168 * waiting for _symbol_. Raises +NameError+ if there
1169 * is no +catch+ block for the symbol. The optional second
1170 * parameter supplies a return value for the +catch+ block,
1171 * which otherwise defaults to +nil+. For examples, see
1172 * <code>Kernel::catch</code>.
1173 */
1174
1175 static VALUE
1176 rb_f_throw(int argc, VALUE *argv)
1177 {
1178 VALUE tag, value;
1179 rb_thread_t *th = GET_THREAD();
1180 struct rb_vm_tag *tt = th->tag;
1181
1182 rb_scan_args(argc, argv, "11", &tag, &value);
1183 while (tt) {
1184 if (tt->tag == tag) {
1185 tt->retval = value;
1186 break;
1187 }
1188 tt = tt->prev;
1189 }
1190 if (!tt) {
1191 VALUE desc = rb_inspect(tag);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_CPTR...
Laurent Sansonetti authored
1192 rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_PTR(desc));
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1193 }
1194 rb_trap_restore_mask();
6043d94 more missing wb, yeepee
Laurent Sansonetti authored
1195 GC_WB(&th->errinfo, NEW_THROW_OBJECT(tag, 0, TAG_THROW));
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1196
1197 JUMP_TAG(TAG_THROW);
1198 #ifndef __GNUC__
1199 return Qnil; /* not reached */
1200 #endif
1201 }
1202
1203 void
1204 rb_throw(const char *tag, VALUE val)
1205 {
1206 VALUE argv[2];
1207
1208 argv[0] = ID2SYM(rb_intern(tag));
1209 argv[1] = val;
1210 rb_f_throw(2, argv);
1211 }
1212
1213 void
1214 rb_throw_obj(VALUE tag, VALUE val)
1215 {
1216 VALUE argv[2];
1217
1218 argv[0] = tag;
1219 argv[1] = val;
1220 rb_f_throw(2, argv);
1221 }
1222
1223 /*
1224 * call-seq:
1225 * catch(symbol) {| | block } > obj
1226 *
1227 * +catch+ executes its block. If a +throw+ is
1228 * executed, Ruby searches up its stack for a +catch+ block
1229 * with a tag corresponding to the +throw+'s
1230 * _symbol_. If found, that block is terminated, and
1231 * +catch+ returns the value given to +throw+. If
1232 * +throw+ is not called, the block terminates normally, and
1233 * the value of +catch+ is the value of the last expression
1234 * evaluated. +catch+ expressions may be nested, and the
1235 * +throw+ call need not be in lexical scope.
1236 *
1237 * def routine(n)
1238 * puts n
1239 * throw :done if n <= 0
1240 * routine(n-1)
1241 * end
1242 *
1243 *
1244 * catch(:done) { routine(3) }
1245 *
1246 * <em>produces:</em>
1247 *
1248 * 3
1249 * 2
1250 * 1
1251 * 0
1252 */
1253
1254 static VALUE
1255 rb_f_catch(int argc, VALUE *argv)
1256 {
1257 VALUE tag;
1258 int state;
1259 VALUE val = Qnil; /* OK */
1260 rb_thread_t *th = GET_THREAD();
1261 rb_control_frame_t *saved_cfp = th->cfp;
1262
1263 if (argc == 0) {
1264 tag = rb_obj_alloc(rb_cObject);
1265 }
1266 else {
1267 rb_scan_args(argc, argv, "01", &tag);
1268 }
1269 PUSH_TAG();
1270
1271 th->tag->tag = tag;
1272
1273 if ((state = EXEC_TAG()) == 0) {
1274 val = rb_yield_0(1, &tag);
1275 }
1276 else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
1277 th->cfp = saved_cfp;
1278 val = th->tag->retval;
1279 th->errinfo = Qnil;
1280 state = 0;
1281 }
1282 POP_TAG();
1283 if (state)
1284 JUMP_TAG(state);
1285
1286 return val;
1287 }
1288
1289 static VALUE
1290 catch_null_i(VALUE dmy)
1291 {
1292 return rb_funcall(Qnil, rb_intern("catch"), 0, 0);
1293 }
1294
1295 static VALUE
1296 catch_i(VALUE tag)
1297 {
1298 return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
1299 }
1300
1301 VALUE
1302 rb_catch(const char *tag, VALUE (*func)(), VALUE data)
1303 {
1304 if (!tag) {
1305 return rb_iterate(catch_null_i, 0, func, data);
1306 }
1307 return rb_iterate(catch_i, ID2SYM(rb_intern(tag)), func, data);
1308 }
1309
1310 VALUE
1311 rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
1312 {
1313 return rb_iterate((VALUE (*)_((VALUE)))catch_i, tag, func, data);
1314 }
1315
1316 /*
1317 * call-seq:
1318 * caller(start=1) => array
1319 *
1320 * Returns the current execution stack---an array containing strings in
1321 * the form ``<em>file:line</em>'' or ``<em>file:line: in
1322 * `method'</em>''. The optional _start_ parameter
1323 * determines the number of initial stack entries to omit from the
1324 * result.
1325 *
1326 * def a(skip)
1327 * caller(skip)
1328 * end
1329 * def b(skip)
1330 * a(skip)
1331 * end
1332 * def c(skip)
1333 * b(skip)
1334 * end
1335 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
1336 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
1337 * c(2) #=> ["prog:8:in `c'", "prog:12"]
1338 * c(3) #=> ["prog:13"]
1339 */
1340
1341 static VALUE
1342 rb_f_caller(int argc, VALUE *argv)
1343 {
1344 VALUE level;
1345 int lev;
1346
1347 rb_scan_args(argc, argv, "01", &level);
1348
1349 if (NIL_P(level))
1350 lev = 1;
1351 else
1352 lev = NUM2INT(level);
1353 if (lev < 0)
1354 rb_raise(rb_eArgError, "negative level (%d)", lev);
1355
1356 return vm_backtrace(GET_THREAD(), lev);
1357 }
1358
1359 void
1360 rb_backtrace(void)
1361 {
1362 long i;
1363 VALUE ary;
1364
1365 ary = vm_backtrace(GET_THREAD(), -1);
1366 for (i = 0; i < RARRAY_LEN(ary); i++) {
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_CPTR...
Laurent Sansonetti authored
1367 printf("\tfrom %s\n", RSTRING_PTR(RARRAY_AT(ary, i)));
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1368 }
1369 }
1370
1371 VALUE
1372 rb_make_backtrace(void)
1373 {
1374 return vm_backtrace(GET_THREAD(), -1);
1375 }
1376
1377 void
1378 Init_vm_eval(void)
1379 {
1380 rb_define_global_function("catch", rb_f_catch, -1);
1381 rb_define_global_function("throw", rb_f_throw, -1);
1382
1383 rb_define_global_function("loop", rb_f_loop, 0);
1384
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
1385 rb_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1);
1386 rb_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
1387 rb_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
1388 rb_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
da85a43 fixes for #121, #117 and #52
Laurent Sansonetti authored
1389
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1390 rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
1391 rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
1392 rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
1393 rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
4a2b903 merging lrz_unstable branch
Laurent Sansonetti authored
1394
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
1395 rb_define_method(rb_mKernel, "send", rb_f_send, -1);
1396 rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
1397
1398 rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
1399 rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
1400
1401 rb_define_global_function("caller", rb_f_caller, -1);
1402 }
1403
Something went wrong with that request. Please try again.