Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 798 lines (701 sloc) 19.114 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"
cb65416 the great schism, part I
Laurent Sansonetti authored
17 #include "vm.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
18 #include "objc.h"
19 #include "id.h"
20
21 #include "vm_method.c"
22
23 static inline VALUE
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
24 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope,
25 bool pass_current_block)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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 }
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
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);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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);
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
97 return rb_call(recv, mid, argc, argv, CALL_FCALL, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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 }
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
120 return rb_call(recv, mid, n, argv, CALL_FCALL, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
121 }
122
123 VALUE
124 rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
125 {
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
126 return rb_call(recv, mid, argc, argv, CALL_FCALL, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
127 }
128
129 VALUE
130 rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
131 {
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
132 return rb_call(recv, mid, argc, argv, CALL_PUBLIC, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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--;
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
145 return rb_call(recv, rb_to_id(vid), argc, argv, scope, true);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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 {
10ef9b1 testing thread cancelability is all loops wasn't a bright idea
Laurent Sansonetti authored
251 int count = 0;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
252 for (;;) {
253 rb_yield(Qundef);
254 RETURN_IF_BROKEN();
a2e495b @vincentisambart fixed some of Laurent's strange code ;)
vincentisambart authored
255 if (++count >= 100) {
10ef9b1 testing thread cancelability is all loops wasn't a bright idea
Laurent Sansonetti authored
256 TEST_THREAD_CANCEL();
257 count = 0;
258 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
259 }
260 return Qnil;
261 }
262
263 /*
264 * call-seq:
265 * loop {|| block }
266 *
267 * Repeatedly executes the block.
268 *
269 * loop do
270 * print "Input: "
271 * line = gets
272 * break if !line or line =~ /^qQ/
273 * # ...
274 * end
275 *
276 * StopIteration raised in the block breaks the loop.
277 */
278
279 static VALUE
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
280 rb_f_loop(VALUE rcv, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
281 {
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
282 RETURN_ENUMERATOR(rcv, 0, 0);
5c8cd3f fixed the return value of #loop (in case of break)
Laurent Sansonetti authored
283 return rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
284 }
285
286 VALUE
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
287 rb_objc_block_call(VALUE obj, SEL sel, void *cache, int argc, VALUE *argv,
38a26b8 implemented NODE_IFUNC-type blocks
Laurent Sansonetti authored
288 VALUE (*bl_proc) (ANYARGS), VALUE data2)
289 {
2c54dbd AOT compiler: added support for blocks
Laurent Sansonetti authored
290 rb_vm_block_t *b = rb_vm_create_block((IMP)bl_proc, obj, data2);
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
291 if (cache == NULL) {
292 cache = rb_vm_get_call_cache(sel);
293 }
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
294 return rb_vm_call_with_cache2(cache, b, obj, 0, sel, argc, argv);
38a26b8 implemented NODE_IFUNC-type blocks
Laurent Sansonetti authored
295 }
296
297 VALUE
298 rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv,
9c1d230 committing experimental branch content
Laurent Sansonetti authored
299 VALUE (*bl_proc) (ANYARGS), VALUE data2)
300 {
38a26b8 implemented NODE_IFUNC-type blocks
Laurent Sansonetti authored
301 SEL sel;
302 if (argc == 0) {
303 sel = sel_registerName(rb_id2name(mid));
304 }
305 else {
306 char buf[100];
307 snprintf(buf, sizeof buf, "%s:", rb_id2name(mid));
308 sel = sel_registerName(buf);
309 }
8a23329 do not stack blocks since this doesn't go well with the ruby semantics
Laurent Sansonetti authored
310 return rb_objc_block_call(obj, sel, NULL, argc, argv, bl_proc, data2);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
311 }
312
313 VALUE
314 rb_each(VALUE obj)
315 {
f357c64 a new implementation for storing active blocks in the VM which fixes …
Laurent Sansonetti authored
316 return rb_call(obj, idEach, 0, 0, CALL_FCALL, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
317 }
318
319 static VALUE
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
320 eval_string(VALUE self, VALUE klass, VALUE src, VALUE scope, const char *file,
321 const int line)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
322 {
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
323 rb_vm_binding_t *b = NULL;
324 if (scope != Qnil) {
325 if (!rb_obj_is_kind_of(scope, rb_cBinding)) {
326 rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)",
327 rb_obj_classname(scope));
328 }
329 b = (rb_vm_binding_t *)DATA_PTR(scope);
330 }
331
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
332 bool old_parse_in_eval = rb_vm_parse_in_eval();
333 rb_vm_set_parse_in_eval(true);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
334 if (b != NULL) {
335 // Binding must be added because the parser needs it.
336 rb_vm_add_binding(b);
337 }
338
9c1d230 committing experimental branch content
Laurent Sansonetti authored
339 NODE *node = rb_compile_string(file, src, line);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
340
341 if (b != NULL) {
342 // We remove the binding now but we still pass it to the VM, which
343 // will use it for compilation.
344 rb_vm_pop_binding();
345 }
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
346 rb_vm_set_parse_in_eval(old_parse_in_eval);
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
347
22ef83c let's raise SyntaxError exceptions when there is a parsing error inst…
Laurent Sansonetti authored
348 if (node == NULL) {
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
349 VALUE exc = rb_vm_current_exception();
350 if (exc != Qnil) {
7c968bd fixing more exceptions bugs
Laurent Sansonetti authored
351 rb_vm_raise_current_exception();
40717ca do not print syntax error messages while parsing code within eval
Laurent Sansonetti authored
352 }
353 else {
354 rb_raise(rb_eSyntaxError, "compile error");
355 }
22ef83c let's raise SyntaxError exceptions when there is a parsing error inst…
Laurent Sansonetti authored
356 }
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
357
ab4212c experiment with the LLVM interpreter for #eval (disabled for now)
Laurent Sansonetti authored
358 return rb_vm_run_under(klass, self, file, node, b, true);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
359 }
360
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
361 static VALUE
362 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
363 {
90a3eb6 implemented module_function as a scope + fixed a couple of eval-relat…
Laurent Sansonetti authored
364 VALUE retval;
365
366 // XXX: not exception-safe
367 const long old_version = RCLASS_VERSION(klass);
368
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
369 if (rb_block_given_p()) {
370 if (argc > 0) {
90a3eb6 implemented module_function as a scope + fixed a couple of eval-relat…
Laurent Sansonetti authored
371 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
372 argc);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
373 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-relat…
Laurent Sansonetti authored
374 rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
375 retval = rb_vm_yield_under(klass, self, 0, NULL);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
376 }
377 else {
4fcff25 implemented #instance_eval with a string + disabled the inline #eval …
Laurent Sansonetti authored
378 const char *file = "(eval)";
379 int line = 1;
380
381 if (argc == 0) {
382 rb_raise(rb_eArgError, "block not supplied");
383 }
384 if (rb_safe_level() >= 4) {
385 StringValue(argv[0]);
386 }
387 else {
388 SafeStringValue(argv[0]);
389 }
390 if (argc > 3) {
391 const char *name = rb_id2name(rb_frame_callee());
392 rb_raise(rb_eArgError,
393 "wrong number of arguments: %s(src) or %s{..}",
394 name, name);
395 }
396 if (argc > 2) {
397 line = NUM2INT(argv[2]);
398 }
399 if (argc > 1) {
400 file = StringValuePtr(argv[1]);
401 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-relat…
Laurent Sansonetti authored
402 rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
403 retval = eval_string(self, klass, argv[0], Qnil, file, line);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
404 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-relat…
Laurent Sansonetti authored
405
406 RCLASS_SET_VERSION(klass, old_version);
407
408 return retval;
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
409 }
410
9c1d230 committing experimental branch content
Laurent Sansonetti authored
411 /*
412 * call-seq:
413 * eval(string [, binding [, filename [,lineno]]]) => obj
414 *
415 * Evaluates the Ruby expression(s) in <em>string</em>. If
416 * <em>binding</em> is given, the evaluation is performed in its
417 * context. The binding may be a <code>Binding</code> object or a
418 * <code>Proc</code> object. If the optional <em>filename</em> and
419 * <em>lineno</em> parameters are present, they will be used when
420 * reporting syntax errors.
421 *
422 * def getBinding(str)
423 * return binding
424 * end
425 * str = "hello"
426 * eval "str + ' Fred'" #=> "hello Fred"
427 * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
428 */
429
430 VALUE
431 rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv)
432 {
433 VALUE src, scope, vfile, vline;
434 const char *file = "(eval)";
435 int line = 1;
436
437 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
438 if (rb_safe_level() >= 4) {
439 StringValue(src);
440 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
441 rb_raise(rb_eSecurityError,
442 "Insecure: can't modify trusted binding");
443 }
444 }
445 else {
446 SafeStringValue(src);
447 }
448 if (argc >= 3) {
449 StringValue(vfile);
450 }
451 if (argc >= 4) {
452 line = NUM2INT(vline);
453 }
454 if (!NIL_P(vfile)) {
455 file = RSTRING_PTR(vfile);
456 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-relat…
Laurent Sansonetti authored
457 VALUE klass;
458 switch (TYPE(self)) {
459 case T_CLASS:
460 case T_MODULE:
461 klass = self;
462 break;
463 default:
464 klass = 0;
465 break;
466 }
467 return eval_string(self, klass, src, scope, file, line);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
468 }
469
470 VALUE
471 rb_eval_string(const char *str)
472 {
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impl…
Laurent Sansonetti authored
473 return eval_string(rb_vm_top_self(), 0, rb_str_new2(str), Qnil, "(eval)", 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
474 }
475
476 VALUE
477 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
478 {
479 VALUE val = Qnil; /* OK */
480 volatile int safe = rb_safe_level();
481
482 if (OBJ_TAINTED(cmd)) {
483 level = 4;
484 }
485
486 if (TYPE(cmd) != T_STRING) {
487 rb_set_safe_level_force(level);
488 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
489 RARRAY_PTR(arg));
490 rb_set_safe_level_force(safe);
491 return val;
492 }
493
4fcff25 implemented #instance_eval with a string + disabled the inline #eval …
Laurent Sansonetti authored
494 val = eval_string(0, rb_vm_top_self(), cmd, Qnil, 0, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
495 rb_set_safe_level_force(safe);
496 return val;
497 }
498
499 /*
500 * call-seq:
501 * obj.instance_eval(string [, filename [, lineno]] ) => obj
502 * obj.instance_eval {| | block } => obj
503 *
504 * Evaluates a string containing Ruby source code, or the given block,
505 * within the context of the receiver (_obj_). In order to set the
506 * context, the variable +self+ is set to _obj_ while
507 * the code is executing, giving the code access to _obj_'s
508 * instance variables. In the version of <code>instance_eval</code>
509 * that takes a +String+, the optional second and third
510 * parameters supply a filename and starting line number that are used
511 * when reporting compilation errors.
512 *
513 * class KlassWithSecret
514 * def initialize
515 * @secret = 99
516 * end
517 * end
518 * k = KlassWithSecret.new
519 * k.instance_eval { @secret } #=> 99
520 */
521
522 static VALUE
523 rb_obj_instance_eval(VALUE self, SEL sel, int argc, VALUE *argv)
524 {
525 VALUE klass;
526
527 if (SPECIAL_CONST_P(self)) {
de8126f appropriately toggle the VM current class when #module_eval/#class_ev…
Laurent Sansonetti authored
528 klass = 0;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
529 }
530 else {
9590d40 fixing and adding several missing ruby method features
Laurent Sansonetti authored
531 klass = rb_singleton_class(self);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
532 }
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
533 return specific_eval(argc, argv, klass, self);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
534 }
535
536 /*
537 * call-seq:
538 * obj.instance_exec(arg...) {|var...| block } => obj
539 *
540 * Executes the given block within the context of the receiver
541 * (_obj_). In order to set the context, the variable +self+ is set
542 * to _obj_ while the code is executing, giving the code access to
543 * _obj_'s instance variables. Arguments are passed as block parameters.
544 *
545 * class KlassWithSecret
546 * def initialize
547 * @secret = 99
548 * end
549 * end
550 * k = KlassWithSecret.new
551 * k.instance_exec(5) {|x| @secret+x } #=> 104
552 */
553
554 static VALUE
555 rb_obj_instance_exec(VALUE self, SEL sel, int argc, VALUE *argv)
556 {
557 VALUE klass;
558
559 if (SPECIAL_CONST_P(self)) {
ae48953 fixed singleton class definition, when passing a non-Array object as …
Laurent Sansonetti authored
560 klass = 0;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
561 }
562 else {
563 klass = rb_singleton_class(self);
564 }
12a1d67 fixing bugs in instance_eval & friends + fixed some specs so that the…
Laurent Sansonetti authored
565 if (!rb_block_given_p()) {
566 rb_raise(rb_eLocalJumpError, "no block given");
567 }
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
568 return rb_vm_yield_under(klass, self, argc, argv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
569 }
570
571 /*
572 * call-seq:
573 * mod.class_eval(string [, filename [, lineno]]) => obj
574 * mod.module_eval {|| block } => obj
575 *
576 * Evaluates the string or block in the context of _mod_. This can
577 * be used to add methods to a class. <code>module_eval</code> returns
578 * the result of evaluating its argument. The optional _filename_
579 * and _lineno_ parameters set the text for error messages.
580 *
581 * class Thing
582 * end
583 * a = %q{def hello() "Hello there!" end}
584 * Thing.module_eval(a)
585 * puts Thing.new.hello()
586 * Thing.module_eval("invalid code", "dummy", 123)
587 *
588 * <em>produces:</em>
589 *
590 * Hello there!
591 * dummy:123:in `module_eval': undefined local variable
592 * or method `code' for Thing:Class
593 */
594
595 VALUE
596 rb_mod_module_eval(VALUE mod, SEL sel, int argc, VALUE *argv)
597 {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
598 return specific_eval(argc, argv, mod, mod);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
599 }
600
601 /*
602 * call-seq:
603 * mod.module_exec(arg...) {|var...| block } => obj
604 * mod.class_exec(arg...) {|var...| block } => obj
605 *
606 * Evaluates the given block in the context of the class/module.
607 * The method defined in the block will belong to the receiver.
608 *
609 * class Thing
610 * end
611 * Thing.class_exec{
612 * def hello() "Hello there!" end
613 * }
614 * puts Thing.new.hello()
615 *
616 * <em>produces:</em>
617 *
618 * Hello there!
619 */
620
621 VALUE
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
622 rb_mod_module_exec(VALUE mod, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
623 {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eva…
Laurent Sansonetti authored
624 return rb_vm_yield_under(mod, mod, argc, argv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
625 }
626
627 /*
628 * call-seq:
629 * throw(symbol [, obj])
630 *
631 * Transfers control to the end of the active +catch+ block
632 * waiting for _symbol_. Raises +NameError+ if there
633 * is no +catch+ block for the symbol. The optional second
634 * parameter supplies a return value for the +catch+ block,
635 * which otherwise defaults to +nil+. For examples, see
636 * <code>Kernel::catch</code>.
637 */
638
639 static VALUE
640 rb_f_throw(VALUE rcv, SEL sel, int argc, VALUE *argv)
641 {
755b464 implemented catch/throw
Laurent Sansonetti authored
642 VALUE tag, value;
643
644 rb_scan_args(argc, argv, "11", &tag, &value);
645
646 return rb_vm_throw(tag, value);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
647 }
648
649 void
650 rb_throw(const char *tag, VALUE val)
651 {
652 VALUE argv[2];
653
654 argv[0] = ID2SYM(rb_intern(tag));
655 argv[1] = val;
656 rb_f_throw(Qnil, 0, 2, argv);
657 }
658
659 void
660 rb_throw_obj(VALUE tag, VALUE val)
661 {
662 VALUE argv[2];
663
664 argv[0] = tag;
665 argv[1] = val;
666 rb_f_throw(Qnil, 0, 2, argv);
667 }
668
669 /*
670 * call-seq:
671 * catch(symbol) {| | block } > obj
672 *
673 * +catch+ executes its block. If a +throw+ is
674 * executed, Ruby searches up its stack for a +catch+ block
675 * with a tag corresponding to the +throw+'s
676 * _symbol_. If found, that block is terminated, and
677 * +catch+ returns the value given to +throw+. If
678 * +throw+ is not called, the block terminates normally, and
679 * the value of +catch+ is the value of the last expression
680 * evaluated. +catch+ expressions may be nested, and the
681 * +throw+ call need not be in lexical scope.
682 *
683 * def routine(n)
684 * puts n
685 * throw :done if n <= 0
686 * routine(n-1)
687 * end
688 *
689 *
690 * catch(:done) { routine(3) }
691 *
692 * <em>produces:</em>
693 *
694 * 3
695 * 2
696 * 1
697 * 0
698 */
699
700 static VALUE
755b464 implemented catch/throw
Laurent Sansonetti authored
701 rb_f_catch(VALUE rcv, SEL sel, VALUE tag)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
702 {
755b464 implemented catch/throw
Laurent Sansonetti authored
703 return rb_vm_catch(tag);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
704 }
705
706 /*
707 * call-seq:
708 * caller(start=1) => array
709 *
710 * Returns the current execution stack---an array containing strings in
711 * the form ``<em>file:line</em>'' or ``<em>file:line: in
712 * `method'</em>''. The optional _start_ parameter
713 * determines the number of initial stack entries to omit from the
714 * result.
715 *
716 * def a(skip)
717 * caller(skip)
718 * end
719 * def b(skip)
720 * a(skip)
721 * end
722 * def c(skip)
723 * b(skip)
724 * end
725 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
726 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
727 * c(2) #=> ["prog:8:in `c'", "prog:12"]
728 * c(3) #=> ["prog:13"]
729 */
730
731 static VALUE
732 rb_f_caller(VALUE klass, SEL sel, int argc, VALUE *argv)
733 {
734 VALUE level;
735 int lev;
736
737 rb_scan_args(argc, argv, "01", &level);
738
739 if (NIL_P(level)) {
740 lev = 1;
741 }
742 else {
743 lev = NUM2INT(level);
744 }
745
746 if (lev < 0) {
747 rb_raise(rb_eArgError, "negative level (%d)", lev);
748 }
749
750 return rb_vm_backtrace(lev);
751 }
752
753 void
754 rb_backtrace(void)
755 {
756 long i, count;
757 VALUE ary;
758
759 ary = rb_vm_backtrace(-1);
760 for (i = 0, count = RARRAY_LEN(ary); i < count; i++) {
761 printf("\tfrom %s\n", RSTRING_PTR(RARRAY_AT(ary, i)));
762 }
763 }
764
765 VALUE
766 rb_make_backtrace(void)
767 {
768 return rb_vm_backtrace(-1);
769 }
770
771 void
772 Init_vm_eval(void)
773 {
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
774 rb_objc_define_module_function(rb_mKernel, "catch", rb_f_catch, 1);
775 rb_objc_define_module_function(rb_mKernel, "throw", rb_f_throw, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
776
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
777 rb_objc_define_module_function(rb_mKernel, "loop", rb_f_loop, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
778
779 rb_objc_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1);
780 rb_objc_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
781 rb_objc_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
782 rb_objc_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
783
784 rb_objc_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
785 rb_objc_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
786 rb_objc_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
787 rb_objc_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
788
789 rb_objc_define_method(rb_mKernel, "send", rb_f_send, -1);
790 rb_objc_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
791
792 rb_objc_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
793 rb_objc_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
794
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
795 rb_objc_define_module_function(rb_mKernel, "caller", rb_f_caller, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
796 }
797
Something went wrong with that request. Please try again.