Skip to content

HTTPS clone URL

Subversion checkout URL

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