Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 766 lines (674 sloc) 18.348 kB
9c1d230 committing experimental branch content
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 #include "roxor.h"
18 #include "objc.h"
19 #include "id.h"
20
21 #include "vm_method.c"
22
23 static inline VALUE
24 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
25 {
26 SEL sel;
27 if (mid == ID_ALLOCATOR) {
28 sel = selAlloc;
29 }
30 else {
31 const char *midstr = rb_id2name(mid);
32 if (argc > 0 && midstr[strlen(midstr) - 1] != ':') {
33 char buf[100];
34 snprintf(buf, sizeof buf, "%s:", midstr);
35 sel = sel_registerName(buf);
36 }
37 else {
38 sel = sel_registerName(midstr);
39 }
40 }
41 return rb_vm_call(recv, sel, argc, argv, false);
42 }
43
44 /*
45 * call-seq:
46 * obj.method_missing(symbol [, *args] ) => result
47 *
48 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
49 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
50 * are any arguments that were passed to it. By default, the interpreter
51 * raises an error when this method is called. However, it is possible
52 * to override the method to provide more dynamic behavior.
53 * If it is decided that a particular method should not be handled, then
54 * <i>super</i> should be called, so that ancestors can pick up the
55 * missing method.
56 * The example below creates
57 * a class <code>Roman</code>, which responds to methods with names
58 * consisting of roman numerals, returning the corresponding integer
59 * values.
60 *
61 * class Roman
62 * def romanToInt(str)
63 * # ...
64 * end
65 * def method_missing(methId)
66 * str = methId.id2name
67 * romanToInt(str)
68 * end
69 * end
70 *
71 * r = Roman.new
72 * r.iv #=> 4
73 * r.xxiii #=> 23
74 * r.mm #=> 2000
75 */
76
77 static VALUE
78 rb_method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv)
79 {
80 return rb_vm_method_missing(obj, argc, argv);
81 }
82
83 VALUE
84 rb_apply(VALUE recv, ID mid, VALUE args)
85 {
86 int argc;
87 VALUE *argv;
88
89 argc = RARRAY_LEN(args); /* Assigns LONG, but argc is INT */
90 argv = ALLOCA_N(VALUE, argc);
91 MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
92 return rb_call(/*CLASS_OF(recv),*/ recv, mid, argc, argv, CALL_FCALL);
93 }
94
95 VALUE
96 rb_funcall(VALUE recv, ID mid, int n, ...)
97 {
98 VALUE *argv;
99 va_list ar;
100 va_start(ar, n);
101
102 if (n > 0) {
103 long i;
104
105 argv = ALLOCA_N(VALUE, n);
106
107 for (i = 0; i < n; i++) {
108 argv[i] = va_arg(ar, VALUE);
109 }
110 va_end(ar);
111 }
112 else {
113 argv = 0;
114 }
115 return rb_call(recv, mid, n, argv, CALL_FCALL);
116 }
117
118 VALUE
119 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
120 {
121 return rb_call(recv, mid, argc, argv, CALL_FCALL);
122 }
123
124 VALUE
125 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
126 {
127 return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
128 }
129
130 static VALUE
131 send_internal(int argc, VALUE *argv, VALUE recv, int scope)
132 {
133 VALUE vid;
134
135 if (argc == 0) {
136 rb_raise(rb_eArgError, "no method name given");
137 }
138
139 vid = *argv++; argc--;
140 return rb_call(recv, rb_to_id(vid), argc, argv, scope);
141 }
142
143 /*
144 * call-seq:
145 * obj.send(symbol [, args...]) => obj
146 * obj.__send__(symbol [, args...]) => obj
147 *
148 * Invokes the method identified by _symbol_, passing it any
149 * arguments specified. You can use <code>__send__</code> if the name
150 * +send+ clashes with an existing method in _obj_.
151 *
152 * class Klass
153 * def hello(*args)
154 * "Hello " + args.join(' ')
155 * end
156 * end
157 * k = Klass.new
158 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
159 */
160
161 static VALUE
162 rb_f_send(VALUE recv, SEL sel, int argc, VALUE *argv)
163 {
164 return send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE);
165 }
166
167 /*
168 * call-seq:
169 * obj.public_send(symbol [, args...]) => obj
170 *
171 * Invokes the method identified by _symbol_, passing it any
172 * arguments specified. Unlike send, public_send calls public
173 * methods only.
174 *
175 * 1.public_send(:puts, "hello") # causes NoMethodError
176 */
177
178 static VALUE
179 rb_f_public_send(VALUE recv, SEL sel, int argc, VALUE *argv)
180 {
181 return send_internal(argc, argv, recv, NOEX_PUBLIC);
182 }
183
184 /* yield */
185
186 static inline VALUE
187 rb_yield_0(int argc, const VALUE * argv)
188 {
189 return rb_vm_yield(argc, argv);
190 }
191
192 VALUE
193 rb_yield(VALUE val)
194 {
195 if (val == Qundef) {
196 return rb_yield_0(0, 0);
197 }
198 else {
199 return rb_yield_0(1, &val);
200 }
201 }
202
203 VALUE
204 rb_yield_values(int n, ...)
205 {
206 if (n == 0) {
207 return rb_yield_0(0, 0);
208 }
209 else {
210 int i;
211 VALUE *argv;
212 va_list args;
213 argv = ALLOCA_N(VALUE, n);
214
215 va_start(args, n);
216 for (i=0; i<n; i++) {
217 argv[i] = va_arg(args, VALUE);
218 }
219 va_end(args);
220
221 return rb_yield_0(n, argv);
222 }
223 }
224
225 VALUE
226 rb_yield_values2(int argc, const VALUE *argv)
227 {
228 return rb_yield_0(argc, argv);
229 }
230
231 VALUE
232 rb_yield_splat(VALUE values)
233 {
234 VALUE tmp = rb_check_array_type(values);
235 volatile VALUE v;
236 if (NIL_P(tmp)) {
237 rb_raise(rb_eArgError, "not an array");
238 }
239 v = rb_yield_0(RARRAY_LEN(tmp), RARRAY_PTR(tmp));
240 return v;
241 }
242
243 static VALUE
244 loop_i(void)
245 {
246 for (;;) {
247 rb_yield(Qundef);
248 RETURN_IF_BROKEN();
249 }
250 return Qnil;
251 }
252
253 /*
254 * call-seq:
255 * loop {|| block }
256 *
257 * Repeatedly executes the block.
258 *
259 * loop do
260 * print "Input: "
261 * line = gets
262 * break if !line or line =~ /^qQ/
263 * # ...
264 * end
265 *
266 * StopIteration raised in the block breaks the loop.
267 */
268
269 static VALUE
270 rb_f_loop(VALUE klass, SEL sel)
271 {
5c8cd3f fixed the return value of #loop (in case of break)
Laurent Sansonetti authored
272 return rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
273 }
274
275 VALUE
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
276 rb_objc_block_call(VALUE obj, SEL sel, void *cache, int argc, VALUE *argv,
38a26b8 implemented NODE_IFUNC-type blocks
Laurent Sansonetti authored
277 VALUE (*bl_proc) (ANYARGS), VALUE data2)
278 {
279 NODE *node = NEW_IFUNC(bl_proc, data2);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
280 rb_vm_block_t *b = rb_vm_prepare_block(NULL, node, obj, 0, 0);
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
281 rb_vm_change_current_block(b);
282 if (cache == NULL) {
283 cache = rb_vm_get_call_cache(sel);
284 }
364fc04 more block fixes
Laurent Sansonetti authored
285 VALUE val = rb_vm_call_with_cache2(cache, obj, 0, sel, argc, argv);
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
286 rb_vm_restore_current_block();
38a26b8 implemented NODE_IFUNC-type blocks
Laurent Sansonetti authored
287 return val;
288 }
289
290 VALUE
291 rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv,
9c1d230 committing experimental branch content
Laurent Sansonetti authored
292 VALUE (*bl_proc) (ANYARGS), VALUE data2)
293 {
38a26b8 implemented NODE_IFUNC-type blocks
Laurent Sansonetti authored
294 SEL sel;
295 if (argc == 0) {
296 sel = sel_registerName(rb_id2name(mid));
297 }
298 else {
299 char buf[100];
300 snprintf(buf, sizeof buf, "%s:", rb_id2name(mid));
301 sel = sel_registerName(buf);
302 }
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
303 return rb_objc_block_call(obj, sel, NULL, argc, argv, bl_proc, data2);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
304 }
305
306 VALUE
307 rb_each(VALUE obj)
308 {
309 return rb_call(obj, idEach, 0, 0, CALL_FCALL);
310 }
311
312 static VALUE
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
313 eval_string(VALUE self, VALUE klass, VALUE src, VALUE scope, const char *file,
314 const int line)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
315 {
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
316 rb_vm_binding_t *b = NULL;
317 if (scope != Qnil) {
318 if (!rb_obj_is_kind_of(scope, rb_cBinding)) {
319 rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)",
320 rb_obj_classname(scope));
321 }
322 b = (rb_vm_binding_t *)DATA_PTR(scope);
323 }
324
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
325 bool old_parse_in_eval = rb_vm_parse_in_eval();
326 rb_vm_set_parse_in_eval(true);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
327 if (b != NULL) {
328 // Binding must be added because the parser needs it.
329 rb_vm_add_binding(b);
330 }
331
9c1d230 committing experimental branch content
Laurent Sansonetti authored
332 NODE *node = rb_compile_string(file, src, line);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
333
334 if (b != NULL) {
335 // We remove the binding now but we still pass it to the VM, which
336 // will use it for compilation.
337 rb_vm_pop_binding();
338 }
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
339 rb_vm_set_parse_in_eval(old_parse_in_eval);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
340
22ef83c let's raise SyntaxError exceptions when there is a parsing error inst…
Laurent Sansonetti authored
341 if (node == NULL) {
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
342 VALUE exc = rb_vm_current_exception();
343 if (exc != Qnil) {
344 rb_exc_raise(exc);
345 }
346 else {
347 rb_raise(rb_eSyntaxError, "compile error");
348 }
22ef83c let's raise SyntaxError exceptions when there is a parsing error inst…
Laurent Sansonetti authored
349 }
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
350
ab4212c experiment with the LLVM interpreter for #eval (disabled for now)
Laurent Sansonetti authored
351 return rb_vm_run_under(klass, self, file, node, b, true);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
352 }
353
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
354 static VALUE
355 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
356 {
357 if (rb_block_given_p()) {
358 if (argc > 0) {
359 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
360 }
361 return rb_vm_yield_under(klass, self, 0, NULL);
362 }
363 else {
4fcff25 implemented #instance_eval with a string + disabled the inline #eval …
Laurent Sansonetti authored
364 const char *file = "(eval)";
365 int line = 1;
366
367 if (argc == 0) {
368 rb_raise(rb_eArgError, "block not supplied");
369 }
370 if (rb_safe_level() >= 4) {
371 StringValue(argv[0]);
372 }
373 else {
374 SafeStringValue(argv[0]);
375 }
376 if (argc > 3) {
377 const char *name = rb_id2name(rb_frame_callee());
378 rb_raise(rb_eArgError,
379 "wrong number of arguments: %s(src) or %s{..}",
380 name, name);
381 }
382 if (argc > 2) {
383 line = NUM2INT(argv[2]);
384 }
385 if (argc > 1) {
386 file = StringValuePtr(argv[1]);
387 }
388 return eval_string(self, klass, argv[0], Qnil, file, line);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
389 }
390 }
391
9c1d230 committing experimental branch content
Laurent Sansonetti authored
392 /*
393 * call-seq:
394 * eval(string [, binding [, filename [,lineno]]]) => obj
395 *
396 * Evaluates the Ruby expression(s) in <em>string</em>. If
397 * <em>binding</em> is given, the evaluation is performed in its
398 * context. The binding may be a <code>Binding</code> object or a
399 * <code>Proc</code> object. If the optional <em>filename</em> and
400 * <em>lineno</em> parameters are present, they will be used when
401 * reporting syntax errors.
402 *
403 * def getBinding(str)
404 * return binding
405 * end
406 * str = "hello"
407 * eval "str + ' Fred'" #=> "hello Fred"
408 * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
409 */
410
411 VALUE
412 rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv)
413 {
414 VALUE src, scope, vfile, vline;
415 const char *file = "(eval)";
416 int line = 1;
417
418 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
419 if (rb_safe_level() >= 4) {
420 StringValue(src);
421 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
422 rb_raise(rb_eSecurityError,
423 "Insecure: can't modify trusted binding");
424 }
425 }
426 else {
427 SafeStringValue(src);
428 }
429 if (argc >= 3) {
430 StringValue(vfile);
431 }
432 if (argc >= 4) {
433 line = NUM2INT(vline);
434 }
435 if (!NIL_P(vfile)) {
436 file = RSTRING_PTR(vfile);
437 }
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
438 return eval_string(self, 0, src, scope, file, line);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
439 }
440
441 VALUE
442 rb_eval_string(const char *str)
443 {
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
444 return eval_string(rb_vm_top_self(), 0, rb_str_new2(str), Qnil, "(eval)", 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
445 }
446
447 VALUE
448 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
449 {
450 VALUE val = Qnil; /* OK */
451 volatile int safe = rb_safe_level();
452
453 if (OBJ_TAINTED(cmd)) {
454 level = 4;
455 }
456
457 if (TYPE(cmd) != T_STRING) {
458 rb_set_safe_level_force(level);
459 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
460 RARRAY_PTR(arg));
461 rb_set_safe_level_force(safe);
462 return val;
463 }
464
4fcff25 implemented #instance_eval with a string + disabled the inline #eval …
Laurent Sansonetti authored
465 val = eval_string(0, rb_vm_top_self(), cmd, Qnil, 0, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
466 rb_set_safe_level_force(safe);
467 return val;
468 }
469
470 /*
471 * call-seq:
472 * obj.instance_eval(string [, filename [, lineno]] ) => obj
473 * obj.instance_eval {| | block } => obj
474 *
475 * Evaluates a string containing Ruby source code, or the given block,
476 * within the context of the receiver (_obj_). In order to set the
477 * context, the variable +self+ is set to _obj_ while
478 * the code is executing, giving the code access to _obj_'s
479 * instance variables. In the version of <code>instance_eval</code>
480 * that takes a +String+, the optional second and third
481 * parameters supply a filename and starting line number that are used
482 * when reporting compilation errors.
483 *
484 * class KlassWithSecret
485 * def initialize
486 * @secret = 99
487 * end
488 * end
489 * k = KlassWithSecret.new
490 * k.instance_eval { @secret } #=> 99
491 */
492
493 static VALUE
494 rb_obj_instance_eval(VALUE self, SEL sel, int argc, VALUE *argv)
495 {
496 VALUE klass;
497
498 if (SPECIAL_CONST_P(self)) {
499 klass = Qnil;
500 }
501 else {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
502 klass = CLASS_OF(self);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
503 }
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
504 return specific_eval(argc, argv, klass, self);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
505 }
506
507 /*
508 * call-seq:
509 * obj.instance_exec(arg...) {|var...| block } => obj
510 *
511 * Executes the given block within the context of the receiver
512 * (_obj_). In order to set the context, the variable +self+ is set
513 * to _obj_ while the code is executing, giving the code access to
514 * _obj_'s instance variables. Arguments are passed as block parameters.
515 *
516 * class KlassWithSecret
517 * def initialize
518 * @secret = 99
519 * end
520 * end
521 * k = KlassWithSecret.new
522 * k.instance_exec(5) {|x| @secret+x } #=> 104
523 */
524
525 static VALUE
526 rb_obj_instance_exec(VALUE self, SEL sel, int argc, VALUE *argv)
527 {
528 VALUE klass;
529
530 if (SPECIAL_CONST_P(self)) {
ae48953 fixed singleton class definition, when passing a non-Array object as …
Laurent Sansonetti authored
531 klass = 0;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
532 }
533 else {
534 klass = rb_singleton_class(self);
535 }
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
536 return rb_vm_yield_under(klass, self, argc, argv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
537 }
538
539 /*
540 * call-seq:
541 * mod.class_eval(string [, filename [, lineno]]) => obj
542 * mod.module_eval {|| block } => obj
543 *
544 * Evaluates the string or block in the context of _mod_. This can
545 * be used to add methods to a class. <code>module_eval</code> returns
546 * the result of evaluating its argument. The optional _filename_
547 * and _lineno_ parameters set the text for error messages.
548 *
549 * class Thing
550 * end
551 * a = %q{def hello() "Hello there!" end}
552 * Thing.module_eval(a)
553 * puts Thing.new.hello()
554 * Thing.module_eval("invalid code", "dummy", 123)
555 *
556 * <em>produces:</em>
557 *
558 * Hello there!
559 * dummy:123:in `module_eval': undefined local variable
560 * or method `code' for Thing:Class
561 */
562
563 VALUE
564 rb_mod_module_eval(VALUE mod, SEL sel, int argc, VALUE *argv)
565 {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
566 return specific_eval(argc, argv, mod, mod);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
567 }
568
569 /*
570 * call-seq:
571 * mod.module_exec(arg...) {|var...| block } => obj
572 * mod.class_exec(arg...) {|var...| block } => obj
573 *
574 * Evaluates the given block in the context of the class/module.
575 * The method defined in the block will belong to the receiver.
576 *
577 * class Thing
578 * end
579 * Thing.class_exec{
580 * def hello() "Hello there!" end
581 * }
582 * puts Thing.new.hello()
583 *
584 * <em>produces:</em>
585 *
586 * Hello there!
587 */
588
589 VALUE
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
590 rb_mod_module_exec(VALUE mod, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
591 {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
592 return rb_vm_yield_under(mod, mod, argc, argv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
593 }
594
595 /*
596 * call-seq:
597 * throw(symbol [, obj])
598 *
599 * Transfers control to the end of the active +catch+ block
600 * waiting for _symbol_. Raises +NameError+ if there
601 * is no +catch+ block for the symbol. The optional second
602 * parameter supplies a return value for the +catch+ block,
603 * which otherwise defaults to +nil+. For examples, see
604 * <code>Kernel::catch</code>.
605 */
606
607 static VALUE
608 rb_f_throw(VALUE rcv, SEL sel, int argc, VALUE *argv)
609 {
755b464 implemented catch/throw
Laurent Sansonetti authored
610 VALUE tag, value;
611
612 rb_scan_args(argc, argv, "11", &tag, &value);
613
614 return rb_vm_throw(tag, value);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
615 }
616
617 void
618 rb_throw(const char *tag, VALUE val)
619 {
620 VALUE argv[2];
621
622 argv[0] = ID2SYM(rb_intern(tag));
623 argv[1] = val;
624 rb_f_throw(Qnil, 0, 2, argv);
625 }
626
627 void
628 rb_throw_obj(VALUE tag, VALUE val)
629 {
630 VALUE argv[2];
631
632 argv[0] = tag;
633 argv[1] = val;
634 rb_f_throw(Qnil, 0, 2, argv);
635 }
636
637 /*
638 * call-seq:
639 * catch(symbol) {| | block } > obj
640 *
641 * +catch+ executes its block. If a +throw+ is
642 * executed, Ruby searches up its stack for a +catch+ block
643 * with a tag corresponding to the +throw+'s
644 * _symbol_. If found, that block is terminated, and
645 * +catch+ returns the value given to +throw+. If
646 * +throw+ is not called, the block terminates normally, and
647 * the value of +catch+ is the value of the last expression
648 * evaluated. +catch+ expressions may be nested, and the
649 * +throw+ call need not be in lexical scope.
650 *
651 * def routine(n)
652 * puts n
653 * throw :done if n <= 0
654 * routine(n-1)
655 * end
656 *
657 *
658 * catch(:done) { routine(3) }
659 *
660 * <em>produces:</em>
661 *
662 * 3
663 * 2
664 * 1
665 * 0
666 */
667
668 static VALUE
755b464 implemented catch/throw
Laurent Sansonetti authored
669 rb_f_catch(VALUE rcv, SEL sel, VALUE tag)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
670 {
755b464 implemented catch/throw
Laurent Sansonetti authored
671 return rb_vm_catch(tag);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
672 }
673
674 /*
675 * call-seq:
676 * caller(start=1) => array
677 *
678 * Returns the current execution stack---an array containing strings in
679 * the form ``<em>file:line</em>'' or ``<em>file:line: in
680 * `method'</em>''. The optional _start_ parameter
681 * determines the number of initial stack entries to omit from the
682 * result.
683 *
684 * def a(skip)
685 * caller(skip)
686 * end
687 * def b(skip)
688 * a(skip)
689 * end
690 * def c(skip)
691 * b(skip)
692 * end
693 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
694 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
695 * c(2) #=> ["prog:8:in `c'", "prog:12"]
696 * c(3) #=> ["prog:13"]
697 */
698
699 static VALUE
700 rb_f_caller(VALUE klass, SEL sel, int argc, VALUE *argv)
701 {
702 VALUE level;
703 int lev;
704
705 rb_scan_args(argc, argv, "01", &level);
706
707 if (NIL_P(level)) {
708 lev = 1;
709 }
710 else {
711 lev = NUM2INT(level);
712 }
713
714 if (lev < 0) {
715 rb_raise(rb_eArgError, "negative level (%d)", lev);
716 }
717
718 return rb_vm_backtrace(lev);
719 }
720
721 void
722 rb_backtrace(void)
723 {
724 long i, count;
725 VALUE ary;
726
727 ary = rb_vm_backtrace(-1);
728 for (i = 0, count = RARRAY_LEN(ary); i < count; i++) {
729 printf("\tfrom %s\n", RSTRING_PTR(RARRAY_AT(ary, i)));
730 }
731 }
732
733 VALUE
734 rb_make_backtrace(void)
735 {
736 return rb_vm_backtrace(-1);
737 }
738
739 void
740 Init_vm_eval(void)
741 {
755b464 implemented catch/throw
Laurent Sansonetti authored
742 rb_objc_define_method(rb_mKernel, "catch", rb_f_catch, 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
743 rb_objc_define_method(rb_mKernel, "throw", rb_f_throw, -1);
744
745 rb_objc_define_method(rb_mKernel, "loop", rb_f_loop, 0);
746
747 rb_objc_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1);
748 rb_objc_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
749 rb_objc_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
750 rb_objc_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
751
752 rb_objc_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
753 rb_objc_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
754 rb_objc_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
755 rb_objc_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
756
757 rb_objc_define_method(rb_mKernel, "send", rb_f_send, -1);
758 rb_objc_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
759
760 rb_objc_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
761 rb_objc_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
762
763 rb_objc_define_method(rb_mKernel, "caller", rb_f_caller, -1);
764 }
765
Something went wrong with that request. Please try again.