Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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