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