Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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