Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 772 lines (686 sloc) 18.98 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 typing ...
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 lot...
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 lot...
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 lot...
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 lot...
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 lot...
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 lot...
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 if (argc == 0) {
125 rb_raise(rb_eArgError, "no method name given");
126 }
636eed7 Laurent Sansonetti fix a bug when returning a value using break inside #initialize would no...
lrz authored
127 VALUE vid = *argv++;
128 argc--;
129 VALUE retval = rb_call(recv, rb_to_id(vid), argc, argv, scope, true);
130 RETURN_IF_BROKEN();
131 return retval;
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 if ...
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 if ...
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 if ...
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 Vincent Isambart 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 lot...
Laurent Sansonetti authored
281 return rb_call(obj, idEach, 0, 0, CALL_FCALL, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
282 }
283
57f584c when creating a binding, keep a reference to the top one
Laurent Sansonetti authored
284 #define GetBindingPtr(obj) ((rb_vm_binding_t *)DATA_PTR(obj))
285
cf73725 experimental debugger
Laurent Sansonetti authored
286 static VALUE
68ac3fc Kouji Takao fixed RoxorVM::pop_outer() leaks memory. (fixes #1267)
takaokouji authored
287 eval_string_with_should_push_outer(VALUE self, VALUE klass, VALUE src, VALUE scope,
288 const char *file, const int line, bool should_push_outer)
cf73725 experimental debugger
Laurent Sansonetti authored
289 {
290 rb_vm_binding_t *binding = NULL;
291 if (scope != Qnil) {
292 if (!rb_obj_is_kind_of(scope, rb_cBinding)) {
293 rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)",
294 rb_obj_classname(scope));
295 }
57f584c when creating a binding, keep a reference to the top one
Laurent Sansonetti authored
296 binding = GetBindingPtr(scope);
cf73725 experimental debugger
Laurent Sansonetti authored
297 }
68ac3fc Kouji Takao fixed RoxorVM::pop_outer() leaks memory. (fixes #1267)
takaokouji authored
298 return rb_vm_eval_string(self, klass, src, binding, file, line, should_push_outer);
299 }
300
301 static VALUE
302 eval_under(VALUE self, VALUE klass, VALUE src, VALUE scope, const char *file,
303 const int line)
304 {
305 if (rb_safe_level() >= 4) {
306 StringValue(src);
307 }
308 else {
309 SafeStringValue(src);
310 }
311 return eval_string_with_should_push_outer(self, klass, src, scope, file, line, true);
312 }
313
314 static VALUE
315 eval_string(VALUE self, VALUE klass, VALUE src, VALUE scope, const char *file,
316 const int line)
317 {
318 return eval_string_with_should_push_outer(self, klass, src, scope, file, line, false);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
319 }
320
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
321 static VALUE
322 specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
323 {
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
324 VALUE retval;
325
326 // XXX: not exception-safe
327 const long old_version = RCLASS_VERSION(klass);
328
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
329 if (rb_block_given_p()) {
330 if (argc > 0) {
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
331 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
332 argc);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
333 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
334 rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
335 retval = rb_vm_yield_under(klass, self, 0, NULL);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
336 }
337 else {
4fcff25 implemented #instance_eval with a string + disabled the inline #eval opt...
Laurent Sansonetti authored
338 const char *file = "(eval)";
339 int line = 1;
340
341 if (argc == 0) {
342 rb_raise(rb_eArgError, "block not supplied");
343 }
344 if (rb_safe_level() >= 4) {
345 StringValue(argv[0]);
346 }
347 else {
348 SafeStringValue(argv[0]);
349 }
350 if (argc > 3) {
351 const char *name = rb_id2name(rb_frame_callee());
352 rb_raise(rb_eArgError,
353 "wrong number of arguments: %s(src) or %s{..}",
354 name, name);
355 }
356 if (argc > 2) {
357 line = NUM2INT(argv[2]);
358 }
359 if (argc > 1) {
360 file = StringValuePtr(argv[1]);
361 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
362 rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
68ac3fc Kouji Takao fixed RoxorVM::pop_outer() leaks memory. (fixes #1267)
takaokouji authored
363 retval = eval_under(self, klass, argv[0], Qnil, file, line);
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
364 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
365
366 RCLASS_SET_VERSION(klass, old_version);
367
368 return retval;
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
369 }
370
9c1d230 committing experimental branch content
Laurent Sansonetti authored
371 /*
372 * call-seq:
373 * eval(string [, binding [, filename [,lineno]]]) => obj
374 *
375 * Evaluates the Ruby expression(s) in <em>string</em>. If
376 * <em>binding</em> is given, the evaluation is performed in its
377 * context. The binding may be a <code>Binding</code> object or a
378 * <code>Proc</code> object. If the optional <em>filename</em> and
379 * <em>lineno</em> parameters are present, they will be used when
380 * reporting syntax errors.
381 *
382 * def getBinding(str)
383 * return binding
384 * end
385 * str = "hello"
386 * eval "str + ' Fred'" #=> "hello Fred"
387 * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
388 */
389
390 VALUE
391 rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv)
392 {
393 VALUE src, scope, vfile, vline;
394 const char *file = "(eval)";
395 int line = 1;
396
397 rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
398 if (rb_safe_level() >= 4) {
399 StringValue(src);
400 if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
401 rb_raise(rb_eSecurityError,
402 "Insecure: can't modify trusted binding");
403 }
404 }
405 else {
406 SafeStringValue(src);
407 }
408 if (argc >= 3) {
409 StringValue(vfile);
410 }
411 if (argc >= 4) {
412 line = NUM2INT(vline);
413 }
414 if (!NIL_P(vfile)) {
415 file = RSTRING_PTR(vfile);
416 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
417 VALUE klass;
418 switch (TYPE(self)) {
419 case T_CLASS:
420 case T_MODULE:
421 klass = self;
422 break;
423 default:
e070527 revert r3589 because it breaks irb...
Laurent Sansonetti authored
424 klass = 0;
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
425 break;
426 }
57f584c when creating a binding, keep a reference to the top one
Laurent Sansonetti authored
427 #if 0
428 if (!NIL_P(scope)) {
429 rb_vm_binding_t *t = rb_vm_current_binding();
430 assert(t != NULL);
431 rb_vm_binding_t *tmp = rb_vm_create_binding(t->self,
432 t->block, GetBindingPtr(scope), 0, NULL, false);
433 GC_WB(&tmp->locals, t->locals);
434 scope = rb_binding_new_from_binding(tmp);
435 }
436 #endif
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
437 return eval_string(self, klass, src, scope, file, line);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
438 }
439
440 VALUE
441 rb_eval_string(const char *str)
442 {
084a52a a faster implementation of dvars + fixed eval bugs + preliminary impleme...
Laurent Sansonetti authored
443 return eval_string(rb_vm_top_self(), 0, rb_str_new2(str), Qnil, "(eval)", 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
444 }
445
446 VALUE
447 rb_eval_cmd(VALUE cmd, VALUE arg, int level)
448 {
449 VALUE val = Qnil; /* OK */
450 volatile int safe = rb_safe_level();
451
452 if (OBJ_TAINTED(cmd)) {
453 level = 4;
454 }
455
456 if (TYPE(cmd) != T_STRING) {
457 rb_set_safe_level_force(level);
458 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
459 RARRAY_PTR(arg));
460 rb_set_safe_level_force(safe);
461 return val;
462 }
463
6820000 - Fixed the call to eval_string() in rb_eval_cmd()
Thibault Martin-Lagardette authored
464 val = eval_string(0, rb_vm_top_self(), cmd, Qnil, "(eval)", 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
465 rb_set_safe_level_force(safe);
466 return val;
467 }
468
469 /*
470 * call-seq:
471 * obj.instance_eval(string [, filename [, lineno]] ) => obj
472 * obj.instance_eval {| | block } => obj
473 *
474 * Evaluates a string containing Ruby source code, or the given block,
475 * within the context of the receiver (_obj_). In order to set the
476 * context, the variable +self+ is set to _obj_ while
477 * the code is executing, giving the code access to _obj_'s
478 * instance variables. In the version of <code>instance_eval</code>
479 * that takes a +String+, the optional second and third
480 * parameters supply a filename and starting line number that are used
481 * when reporting compilation errors.
482 *
483 * class KlassWithSecret
484 * def initialize
485 * @secret = 99
486 * end
487 * end
488 * k = KlassWithSecret.new
489 * k.instance_eval { @secret } #=> 99
490 */
491
492 static VALUE
a8477de expose rb_obj_instance_eval() MRI API
Laurent Sansonetti authored
493 rb_obj_instance_eval_imp(VALUE self, SEL sel, VALUE top, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
494 {
495 VALUE klass;
496
a834a3e #instance_eval: don't attempt to create singleton classes on symbols
Laurent Sansonetti authored
497 if (SPECIAL_CONST_P(self) || CLASS_OF(self) == rb_cSymbol) {
ec68679 Watson rewrite 351ebd7 and 954a8c7 because they cause crash when refer to class...
Watson1978 authored
498 klass = 0;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
499 }
500 else {
a834a3e #instance_eval: don't attempt to create singleton classes on symbols
Laurent Sansonetti authored
501 klass = rb_singleton_class(self);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
502 }
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
503 return specific_eval(argc, argv, klass, self);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
504 }
505
a8477de expose rb_obj_instance_eval() MRI API
Laurent Sansonetti authored
506 VALUE
507 rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
508 {
509 // XXX: does not honor top context variable, so certain const lookups
510 // might fail.
511 return rb_obj_instance_eval_imp(self, 0, Qundef, argc, argv);
512 }
513
9c1d230 committing experimental branch content
Laurent Sansonetti authored
514 /*
515 * call-seq:
516 * obj.instance_exec(arg...) {|var...| block } => obj
517 *
518 * Executes the given block within the context of the receiver
519 * (_obj_). In order to set the context, the variable +self+ is set
520 * to _obj_ while the code is executing, giving the code access to
521 * _obj_'s instance variables. Arguments are passed as block parameters.
522 *
523 * class KlassWithSecret
524 * def initialize
525 * @secret = 99
526 * end
527 * end
528 * k = KlassWithSecret.new
529 * k.instance_exec(5) {|x| @secret+x } #=> 104
530 */
531
532 static VALUE
533 rb_obj_instance_exec(VALUE self, SEL sel, int argc, VALUE *argv)
534 {
535 VALUE klass;
536
537 if (SPECIAL_CONST_P(self)) {
ec68679 Watson rewrite 351ebd7 and 954a8c7 because they cause crash when refer to class...
Watson1978 authored
538 klass = 0;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
539 }
540 else {
541 klass = rb_singleton_class(self);
542 }
12a1d67 fixing bugs in instance_eval & friends + fixed some specs so that they p...
Laurent Sansonetti authored
543 if (!rb_block_given_p()) {
544 rb_raise(rb_eLocalJumpError, "no block given");
545 }
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
546 return rb_vm_yield_under(klass, self, argc, argv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
547 }
548
549 /*
550 * call-seq:
551 * mod.class_eval(string [, filename [, lineno]]) => obj
552 * mod.module_eval {|| block } => obj
553 *
554 * Evaluates the string or block in the context of _mod_. This can
555 * be used to add methods to a class. <code>module_eval</code> returns
556 * the result of evaluating its argument. The optional _filename_
557 * and _lineno_ parameters set the text for error messages.
558 *
559 * class Thing
560 * end
561 * a = %q{def hello() "Hello there!" end}
562 * Thing.module_eval(a)
563 * puts Thing.new.hello()
564 * Thing.module_eval("invalid code", "dummy", 123)
565 *
566 * <em>produces:</em>
567 *
568 * Hello there!
569 * dummy:123:in `module_eval': undefined local variable
570 * or method `code' for Thing:Class
571 */
572
573 VALUE
574 rb_mod_module_eval(VALUE mod, SEL sel, int argc, VALUE *argv)
575 {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
576 return specific_eval(argc, argv, mod, mod);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
577 }
578
579 /*
580 * call-seq:
581 * mod.module_exec(arg...) {|var...| block } => obj
582 * mod.class_exec(arg...) {|var...| block } => obj
583 *
584 * Evaluates the given block in the context of the class/module.
585 * The method defined in the block will belong to the receiver.
586 *
587 * class Thing
588 * end
589 * Thing.class_exec{
590 * def hello() "Hello there!" end
591 * }
592 * puts Thing.new.hello()
593 *
594 * <em>produces:</em>
595 *
596 * Hello there!
597 */
598
599 VALUE
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
600 rb_mod_module_exec(VALUE mod, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
601 {
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
Laurent Sansonetti authored
602 return rb_vm_yield_under(mod, mod, argc, argv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
603 }
604
605 /*
606 * call-seq:
607 * throw(symbol [, obj])
608 *
609 * Transfers control to the end of the active +catch+ block
610 * waiting for _symbol_. Raises +NameError+ if there
611 * is no +catch+ block for the symbol. The optional second
612 * parameter supplies a return value for the +catch+ block,
613 * which otherwise defaults to +nil+. For examples, see
614 * <code>Kernel::catch</code>.
615 */
616
617 static VALUE
618 rb_f_throw(VALUE rcv, SEL sel, int argc, VALUE *argv)
619 {
755b464 implemented catch/throw
Laurent Sansonetti authored
620 VALUE tag, value;
621
622 rb_scan_args(argc, argv, "11", &tag, &value);
623
624 return rb_vm_throw(tag, value);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
625 }
626
627 void
628 rb_throw(const char *tag, VALUE val)
629 {
630 VALUE argv[2];
631
632 argv[0] = ID2SYM(rb_intern(tag));
633 argv[1] = val;
634 rb_f_throw(Qnil, 0, 2, argv);
635 }
636
637 void
638 rb_throw_obj(VALUE tag, VALUE val)
639 {
640 VALUE argv[2];
641
642 argv[0] = tag;
643 argv[1] = val;
644 rb_f_throw(Qnil, 0, 2, argv);
645 }
646
647 /*
648 * call-seq:
649 * catch(symbol) {| | block } > obj
650 *
651 * +catch+ executes its block. If a +throw+ is
652 * executed, Ruby searches up its stack for a +catch+ block
653 * with a tag corresponding to the +throw+'s
654 * _symbol_. If found, that block is terminated, and
655 * +catch+ returns the value given to +throw+. If
656 * +throw+ is not called, the block terminates normally, and
657 * the value of +catch+ is the value of the last expression
658 * evaluated. +catch+ expressions may be nested, and the
659 * +throw+ call need not be in lexical scope.
660 *
661 * def routine(n)
662 * puts n
663 * throw :done if n <= 0
664 * routine(n-1)
665 * end
666 *
667 *
668 * catch(:done) { routine(3) }
669 *
670 * <em>produces:</em>
671 *
672 * 3
673 * 2
674 * 1
675 * 0
676 */
677
678 static VALUE
755b464 implemented catch/throw
Laurent Sansonetti authored
679 rb_f_catch(VALUE rcv, SEL sel, VALUE tag)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
680 {
755b464 implemented catch/throw
Laurent Sansonetti authored
681 return rb_vm_catch(tag);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
682 }
683
684 /*
685 * call-seq:
686 * caller(start=1) => array
687 *
688 * Returns the current execution stack---an array containing strings in
689 * the form ``<em>file:line</em>'' or ``<em>file:line: in
690 * `method'</em>''. The optional _start_ parameter
691 * determines the number of initial stack entries to omit from the
692 * result.
693 *
694 * def a(skip)
695 * caller(skip)
696 * end
697 * def b(skip)
698 * a(skip)
699 * end
700 * def c(skip)
701 * b(skip)
702 * end
703 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
704 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
705 * c(2) #=> ["prog:8:in `c'", "prog:12"]
706 * c(3) #=> ["prog:13"]
707 */
708
709 static VALUE
710 rb_f_caller(VALUE klass, SEL sel, int argc, VALUE *argv)
711 {
712 VALUE level;
713 rb_scan_args(argc, argv, "01", &level);
714
0849733 Kernel#caller: now honor the skip argument
Laurent Sansonetti authored
715 int lev;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
716 if (NIL_P(level)) {
717 lev = 1;
718 }
719 else {
720 lev = NUM2INT(level);
721 }
722
723 if (lev < 0) {
724 rb_raise(rb_eArgError, "negative level (%d)", lev);
725 }
726
0849733 Kernel#caller: now honor the skip argument
Laurent Sansonetti authored
727 return rb_vm_backtrace(lev);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
728 }
729
730 void
731 rb_backtrace(void)
732 {
0849733 Kernel#caller: now honor the skip argument
Laurent Sansonetti authored
733 VALUE ary = rb_vm_backtrace(0);
734 for (long i = 0, count = RARRAY_LEN(ary); i < count; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
735 printf("\tfrom %s\n", RSTRING_PTR(RARRAY_AT(ary, i)));
736 }
737 }
738
739 VALUE
740 rb_make_backtrace(void)
741 {
0849733 Kernel#caller: now honor the skip argument
Laurent Sansonetti authored
742 return rb_vm_backtrace(0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
743 }
744
745 void
746 Init_vm_eval(void)
747 {
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
748 rb_objc_define_module_function(rb_mKernel, "catch", rb_f_catch, 1);
749 rb_objc_define_module_function(rb_mKernel, "throw", rb_f_throw, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
750
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
751 rb_objc_define_module_function(rb_mKernel, "loop", rb_f_loop, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
752
a8477de expose rb_obj_instance_eval() MRI API
Laurent Sansonetti authored
753 rb_objc_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval_imp, -3);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
754 rb_objc_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
755 rb_objc_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
756 rb_objc_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
757
a8477de expose rb_obj_instance_eval() MRI API
Laurent Sansonetti authored
758 rb_objc_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval_imp, -3);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
759 rb_objc_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
760 rb_objc_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
761 rb_objc_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
762
763 rb_objc_define_method(rb_mKernel, "send", rb_f_send, -1);
764 rb_objc_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
765
766 rb_objc_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
767 rb_objc_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
768
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
769 rb_objc_define_module_function(rb_mKernel, "caller", rb_f_caller, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
770 }
771
Something went wrong with that request. Please try again.