Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 785 lines (697 sloc) 19.202 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 Mark Rada 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 typing ...
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 lot...
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 lot...
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
81 argc = RARRAY_LEN(args); /* Assigns LONG, but argc is INT */
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 lot...
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 Watson 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 lot...
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 lot...
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 lot...
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 Laurent Sansonetti fix a bug when returning a value using break inside #initialize would no...
lrz 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 if ...
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 if ...
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 }
dabee30 rb_yield is now inlined + improved GC_WB to not emit a write barrier if ...
Laurent Sansonetti authored
223 return rb_vm_yield(RARRAY_LEN(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 Vincent Isambart 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 lot...
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 Kouji Takao 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 Kouji Takao fixed below.
takaokouji authored
301 return rb_vm_eval_string(self, klass, src, binding, file, line,
302 should_push_outer);
68ac3fc Kouji Takao 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 Kouji Takao 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 Kouji Takao fixed below.
takaokouji authored
326
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
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-related ...
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_eval/m...
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-related ...
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_eval/m...
Laurent Sansonetti authored
339 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
340 rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
1274d86 Watson 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_eval/m...
Laurent Sansonetti authored
342 }
343 else {
4fcff25 implemented #instance_eval with a string + disabled the inline #eval opt...
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-related ...
Laurent Sansonetti authored
368 rb_vm_set_current_scope(klass, SCOPE_PUBLIC);
68ac3fc Kouji Takao 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_eval/m...
Laurent Sansonetti authored
370 }
90a3eb6 implemented module_function as a scope + fixed a couple of eval-related ...
Laurent Sansonetti authored
371
372 RCLASS_SET_VERSION(klass, old_version);
373
374 return retval;
1827cf4 experimental implementation of instance_eval/instance_exec/module_eval/m...
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-related ...
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-related ...
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-related ...
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 impleme...
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);
464 val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
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 Watson [fix #73] should not remove the method from special constant objects and...
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_eval/m...
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 Watson [fix #73] should not remove the method from special constant objects and...
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 they p...
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_eval/m...
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_eval/m...
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_eval/m...
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_eval/m...
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 Watson `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 Watson `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 Watson `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.