Skip to content

HTTPS clone URL

Subversion checkout URL

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