1 /**********************************************************************
6 created at: Sat May 24 16:02:32 JST 2008
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "ruby/ruby.h"
15 #include "ruby/node.h"
18 #include "vm_method.c"
20 static inline VALUE
method_missing(VALUE obj
, ID id
, int argc
, const VALUE
*argv
, int call_status
);
21 static inline VALUE
rb_vm_set_finish_env(rb_thread_t
* th
);
22 static inline VALUE
vm_yield_with_cref(rb_thread_t
*th
, int argc
, const VALUE
*argv
, const NODE
*cref
);
23 static inline VALUE
vm_yield(rb_thread_t
*th
, int argc
, const VALUE
*argv
);
24 static inline VALUE
vm_backtrace(rb_thread_t
*th
, int lev
);
25 static NODE
*vm_cref_push(rb_thread_t
*th
, VALUE klass
, int noex
);
26 static VALUE
vm_eval_body(rb_thread_t
*th
);
27 static void vm_set_eval_stack(rb_thread_t
* th
, VALUE iseqval
, const NODE
*cref
);
30 vm_call0(rb_thread_t
* th
, VALUE klass
, VALUE recv
, VALUE id
, ID oid
,
31 int argc
, const VALUE
*argv
, const NODE
*body
, int nosuper
)
34 rb_block_t
*blockptr
= 0;
36 if (0) printf("id: %s, nd: %s, argc: %d, passed: %p\n",
37 rb_id2name(id
), ruby_node_name(nd_type(body
)),
38 argc
, th
->passed_block
);
40 if (th
->passed_block
) {
41 blockptr
= th
->passed_block
;
44 switch (nd_type(body
)) {
45 case RUBY_VM_METHOD_NODE
:{
46 rb_control_frame_t
*reg_cfp
;
47 VALUE iseqval
= (VALUE
)body
->nd_body
;
50 rb_vm_set_finish_env(th
);
53 CHECK_STACK_OVERFLOW(reg_cfp
, argc
+ 1);
55 *reg_cfp
->sp
++ = recv
;
56 for (i
= 0; i
< argc
; i
++) {
57 *reg_cfp
->sp
++ = argv
[i
];
60 vm_setup_method(th
, reg_cfp
, argc
, blockptr
, 0, iseqval
, recv
, klass
);
61 val
= vm_eval_body(th
);
65 EXEC_EVENT_HOOK(th
, RUBY_EVENT_C_CALL
, recv
, id
, klass
);
67 rb_control_frame_t
*reg_cfp
= th
->cfp
;
68 rb_control_frame_t
*cfp
=
69 vm_push_frame(th
, 0, VM_FRAME_MAGIC_CFUNC
,
70 recv
, (VALUE
)blockptr
, 0, reg_cfp
->sp
, 0, 1);
73 cfp
->method_class
= klass
;
75 val
= call_cfunc(body
->nd_cfnc
, recv
, body
->nd_argc
, argc
, argv
);
77 if (reg_cfp
!= th
->cfp
+ 1) {
80 rb_bug("cfp consistency error - call0");
85 EXEC_EVENT_HOOK(th
, RUBY_EVENT_C_RETURN
, recv
, id
, klass
);
90 rb_raise(rb_eArgError
, "wrong number of arguments (%d for 1)", argc
);
92 val
= rb_ivar_set(recv
, body
->nd_vid
, argv
[0]);
97 rb_raise(rb_eArgError
, "wrong number of arguments (%d for 0)",
100 val
= rb_attr_get(recv
, body
->nd_vid
);
104 val
= vm_call_bmethod(th
, id
, body
->nd_cval
,
105 recv
, klass
, argc
, (VALUE
*)argv
, blockptr
);
109 rb_bug("unsupported: vm_call0(%s)", ruby_node_name(nd_type(body
)));
111 RUBY_VM_CHECK_INTS();
116 rb_vm_call(rb_thread_t
* th
, VALUE klass
, VALUE recv
, VALUE id
, ID oid
,
117 int argc
, const VALUE
*argv
, const NODE
*body
, int nosuper
)
119 return vm_call0(th
, klass
, recv
, id
, oid
, argc
, argv
, body
, nosuper
);
123 vm_call_super(rb_thread_t
* const th
, const int argc
, const VALUE
* const argv
)
125 VALUE recv
= th
->cfp
->self
;
129 rb_control_frame_t
*cfp
= th
->cfp
;
132 klass
= cfp
->method_class
;
133 klass
= RCLASS_SUPER(klass
);
136 klass
= vm_search_normal_superclass(cfp
->method_class
, recv
);
142 rb_bug("vm_call_super: should not be reached");
145 body
= rb_method_node(klass
, id
); /* this returns NODE_METHOD */
148 body
= body
->nd_body
;
151 VALUE
*argv_m
, result
, argv_ary
= 0;
153 argv_m
= ALLOCA_N(VALUE
, argc
+1);
156 argv_ary
= rb_ary_tmp_new(argc
+1);
157 argv_m
= RARRAY_PTR(argv_ary
);
159 MEMCPY(argv_m
+ 1, argv
, VALUE
, argc
);
160 argv_m
[0] = ID2SYM(id
);
161 th
->method_missing_reason
= 0;
162 th
->passed_block
= 0;
163 result
= rb_funcall2(recv
, idMethodMissing
, argc
+ 1, argv_m
);
164 if (argv_ary
) rb_ary_clear(argv_ary
);
168 return vm_call0(th
, klass
, recv
, id
, id
, argc
, argv
, body
, CALL_SUPER
);
172 rb_call_super(int argc
, const VALUE
*argv
)
175 return vm_call_super(GET_THREAD(), argc
, argv
);
181 rb_thread_t
*th
= GET_THREAD();
183 if (!rb_thread_raised_p(th
, RAISED_STACKOVERFLOW
) && ruby_stack_check()) {
184 rb_thread_raised_set(th
, RAISED_STACKOVERFLOW
);
185 rb_exc_raise(sysstack_error
);
190 rb_call0(VALUE klass
, VALUE recv
, ID mid
, int argc
, const VALUE
*argv
,
191 int scope
, VALUE self
)
196 struct cache_entry
*ent
;
197 rb_thread_t
*th
= GET_THREAD();
200 rb_raise(rb_eNotImpError
,
201 "method `%s' called on terminated object (%p)",
202 rb_id2name(mid
), (void *)recv
);
204 /* is it in the method cache? */
205 ent
= cache
+ EXPR1(klass
, mid
);
207 if (ent
->mid
== mid
&& ent
->klass
== klass
) {
209 return method_missing(recv
, mid
, argc
, argv
,
210 scope
== 2 ? NOEX_VCALL
: 0);
212 noex
= ent
->method
->nd_noex
;
213 klass
= ent
->method
->nd_clss
;
214 body
= ent
->method
->nd_body
;
216 else if ((method
= rb_get_method_body(klass
, id
, &id
)) != 0) {
217 noex
= method
->nd_noex
;
218 klass
= method
->nd_clss
;
219 body
= method
->nd_body
;
223 return method_missing(recv
, mid
, argc
, argv
, NOEX_SUPER
);
225 return method_missing(recv
, mid
, argc
, argv
,
226 scope
== 2 ? NOEX_VCALL
: 0);
230 if (mid
!= missing
) {
231 /* receiver specified form for private method */
232 if (UNLIKELY(noex
)) {
233 if (((noex
& NOEX_MASK
) & NOEX_PRIVATE
) && scope
== 0) {
234 return method_missing(recv
, mid
, argc
, argv
, NOEX_PRIVATE
);
237 /* self must be kind of a specified form for protected method */
238 if (((noex
& NOEX_MASK
) & NOEX_PROTECTED
) && scope
== 0) {
239 VALUE defined_class
= klass
;
241 if (TYPE(defined_class
) == T_ICLASS
) {
242 defined_class
= RBASIC(defined_class
)->klass
;
245 if (self
== Qundef
) {
246 self
= th
->cfp
->self
;
248 if (!rb_obj_is_kind_of(self
, rb_class_real(defined_class
))) {
249 return method_missing(recv
, mid
, argc
, argv
, NOEX_PROTECTED
);
253 if (NOEX_SAFE(noex
) > th
->safe_level
) {
254 rb_raise(rb_eSecurityError
, "calling insecure method: %s", rb_id2name(mid
));
260 return vm_call0(th
, klass
, recv
, mid
, id
, argc
, argv
, body
, noex
& NOEX_NOSUPER
);
264 rb_call(VALUE klass
, VALUE recv
, ID mid
, int argc
, const VALUE
*argv
, int scope
)
266 return rb_call0(klass
, recv
, mid
, argc
, argv
, scope
, Qundef
);
271 * obj.method_missing(symbol [, *args] ) => result
273 * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
274 * <i>symbol</i> is the symbol for the method called, and <i>args</i>
275 * are any arguments that were passed to it. By default, the interpreter
276 * raises an error when this method is called. However, it is possible
277 * to override the method to provide more dynamic behavior.
278 * If it is decided that a particular method should not be handled, then
279 * <i>super</i> should be called, so that ancestors can pick up the
281 * The example below creates
282 * a class <code>Roman</code>, which responds to methods with names
283 * consisting of roman numerals, returning the corresponding integer
287 * def romanToInt(str)
290 * def method_missing(methId)
291 * str = methId.id2name
303 rb_method_missing(int argc
, const VALUE
*argv
, VALUE obj
)
306 VALUE exc
= rb_eNoMethodError
;
307 const char *format
= 0;
308 rb_thread_t
*th
= GET_THREAD();
309 int last_call_status
= th
->method_missing_reason
;
310 if (argc
== 0 || !SYMBOL_P(argv
[0])) {
311 rb_raise(rb_eArgError
, "no id given");
316 id
= SYM2ID(argv
[0]);
318 if (last_call_status
& NOEX_PRIVATE
) {
319 format
= "private method `%s' called for %s";
321 else if (last_call_status
& NOEX_PROTECTED
) {
322 format
= "protected method `%s' called for %s";
324 else if (last_call_status
& NOEX_VCALL
) {
325 format
= "undefined local variable or method `%s' for %s";
328 else if (last_call_status
& NOEX_SUPER
) {
329 format
= "super: no superclass method `%s' for %s";
332 format
= "undefined method `%s' for %s";
338 args
[n
++] = rb_funcall(rb_const_get(exc
, rb_intern("message")), '!',
339 3, rb_str_new2(format
), obj
, argv
[0]);
341 if (exc
== rb_eNoMethodError
) {
342 args
[n
++] = rb_ary_new4(argc
- 1, argv
+ 1);
344 exc
= rb_class_new_instance(n
, args
, exc
);
346 th
->cfp
= RUBY_VM_PREVIOUS_CONTROL_FRAME(th
->cfp
);
350 return Qnil
; /* not reached */
354 method_missing(VALUE obj
, ID id
, int argc
, const VALUE
*argv
, int call_status
)
357 GET_THREAD()->method_missing_reason
= call_status
;
360 rb_method_missing(argc
, argv
, obj
);
362 else if (id
== ID_ALLOCATOR
) {
363 rb_raise(rb_eTypeError
, "allocator undefined for %s",
367 nargv
= ALLOCA_N(VALUE
, argc
+ 1);
368 nargv
[0] = ID2SYM(id
);
369 MEMCPY(nargv
+ 1, argv
, VALUE
, argc
);
371 return rb_funcall2(obj
, missing
, argc
+ 1, nargv
);
375 rb_apply(VALUE recv
, ID mid
, VALUE args
)
380 argc
= RARRAY_LEN(args
); /* Assigns LONG, but argc is INT */
381 argv
= ALLOCA_N(VALUE
, argc
);
382 MEMCPY(argv
, RARRAY_PTR(args
), VALUE
, argc
);
383 return rb_call(CLASS_OF(recv
), recv
, mid
, argc
, argv
, CALL_FCALL
);
387 rb_funcall(VALUE recv
, ID mid
, int n
, ...)
396 argv
= ALLOCA_N(VALUE
, n
);
398 for (i
= 0; i
< n
; i
++) {
399 argv
[i
] = va_arg(ar
, VALUE
);
406 return rb_call(CLASS_OF(recv
), recv
, mid
, n
, argv
, CALL_FCALL
);
410 rb_funcall2(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
)
412 return rb_call(CLASS_OF(recv
), recv
, mid
, argc
, argv
, CALL_FCALL
);
416 rb_funcall3(VALUE recv
, ID mid
, int argc
, const VALUE
*argv
)
418 return rb_call(CLASS_OF(recv
), recv
, mid
, argc
, argv
, CALL_PUBLIC
);
422 send_internal(int argc
, VALUE
*argv
, VALUE recv
, int scope
)
425 VALUE self
= RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp
)->self
;
426 rb_thread_t
*th
= GET_THREAD();
429 rb_raise(rb_eArgError
, "no method name given");
432 vid
= *argv
++; argc
--;
433 PASS_PASSED_BLOCK_TH(th
);
435 return rb_call0(CLASS_OF(recv
), recv
, rb_to_id(vid
), argc
, argv
, scope
, self
);
440 * obj.send(symbol [, args...]) => obj
441 * obj.__send__(symbol [, args...]) => obj
443 * Invokes the method identified by _symbol_, passing it any
444 * arguments specified. You can use <code>__send__</code> if the name
445 * +send+ clashes with an existing method in _obj_.
449 * "Hello " + args.join(' ')
453 * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
457 rb_f_send(int argc
, VALUE
*argv
, VALUE recv
)
459 return send_internal(argc
, argv
, recv
, NOEX_NOSUPER
| NOEX_PRIVATE
);
464 * obj.public_send(symbol [, args...]) => obj
466 * Invokes the method identified by _symbol_, passing it any
467 * arguments specified. Unlike send, public_send calls public
470 * 1.public_send(:puts, "hello") # causes NoMethodError
474 rb_f_public_send(int argc
, VALUE
*argv
, VALUE recv
)
476 return send_internal(argc
, argv
, recv
, NOEX_PUBLIC
);
482 rb_yield_0(int argc
, const VALUE
* argv
)
484 return vm_yield(GET_THREAD(), argc
, argv
);
491 return rb_yield_0(0, 0);
494 return rb_yield_0(1, &val
);
499 rb_yield_values(int n
, ...)
502 return rb_yield_0(0, 0);
508 argv
= ALLOCA_N(VALUE
, n
);
510 va_init_list(args
, n
);
511 for (i
=0; i
<n
; i
++) {
512 argv
[i
] = va_arg(args
, VALUE
);
516 return rb_yield_0(n
, argv
);
521 rb_yield_values2(int argc
, const VALUE
*argv
)
523 return rb_yield_0(argc
, argv
);
527 rb_yield_splat(VALUE values
)
529 VALUE tmp
= rb_check_array_type(values
);
532 rb_raise(rb_eArgError
, "not an array");
534 v
= rb_yield_0(RARRAY_LEN(tmp
), RARRAY_PTR(tmp
));
551 * Repeatedly executes the block.
556 * break if !line or line =~ /^qQ/
560 * StopIteration raised in the block breaks the loop.
566 rb_rescue2(loop_i
, (VALUE
)0, 0, 0, rb_eStopIteration
, (VALUE
)0);
567 return Qnil
; /* dummy */
571 rb_iterate(VALUE (* it_proc
) (VALUE
), VALUE data1
,
572 VALUE (* bl_proc
) (ANYARGS
), VALUE data2
)
575 volatile VALUE retval
= Qnil
;
576 NODE
*node
= NEW_IFUNC(bl_proc
, data2
);
577 rb_thread_t
*th
= GET_THREAD();
578 rb_control_frame_t
*cfp
= th
->cfp
;
581 state
= TH_EXEC_TAG();
585 rb_block_t
*blockptr
= RUBY_VM_GET_BLOCK_PTR_IN_CFP(th
->cfp
);
586 blockptr
->iseq
= (void *)node
;
588 th
->passed_block
= blockptr
;
590 retval
= (*it_proc
) (data1
);
593 VALUE err
= th
->errinfo
;
594 if (state
== TAG_BREAK
) {
595 VALUE
*escape_dfp
= GET_THROWOBJ_CATCH_POINT(err
);
596 VALUE
*cdfp
= cfp
->dfp
;
598 if (cdfp
== escape_dfp
) {
605 /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
608 else if (state
== TAG_RETRY
) {
609 VALUE
*escape_dfp
= GET_THROWOBJ_CATCH_POINT(err
);
610 VALUE
*cdfp
= cfp
->dfp
;
612 if (cdfp
== escape_dfp
) {
627 TH_JUMP_TAG(th
, state
);
632 struct iter_method_arg
{
640 iterate_method(VALUE obj
)
642 const struct iter_method_arg
* arg
=
643 (struct iter_method_arg
*) obj
;
645 return rb_call(CLASS_OF(arg
->obj
), arg
->obj
, arg
->mid
,
646 arg
->argc
, arg
->argv
, CALL_FCALL
);
650 rb_block_call(VALUE obj
, ID mid
, int argc
, VALUE
* argv
,
651 VALUE (*bl_proc
) (ANYARGS
), VALUE data2
)
653 struct iter_method_arg arg
;
659 return rb_iterate(iterate_method
, (VALUE
)&arg
, bl_proc
, data2
);
665 return rb_call(CLASS_OF(obj
), obj
, idEach
, 0, 0, CALL_FCALL
);
669 eval_string_with_cref(VALUE self
, VALUE src
, VALUE scope
, NODE
*cref
, const char *file
, int line
)
672 VALUE result
= Qundef
;
674 rb_binding_t
*bind
= 0;
675 rb_thread_t
*th
= GET_THREAD();
676 rb_env_t
*env
= NULL
;
678 volatile int parse_in_eval
;
679 volatile int mild_compile_error
;
682 file
= rb_sourcefile();
683 line
= rb_sourceline();
686 parse_in_eval
= th
->parse_in_eval
;
687 mild_compile_error
= th
->mild_compile_error
;
689 if ((state
= EXEC_TAG()) == 0) {
691 volatile VALUE iseqval
;
694 if (rb_obj_is_kind_of(scope
, rb_cBinding
)) {
695 GetBindingPtr(scope
, bind
);
699 rb_raise(rb_eTypeError
,
700 "wrong argument type %s (expected Binding)",
701 rb_obj_classname(scope
));
703 GetEnvPtr(envval
, env
);
704 th
->base_block
= &env
->block
;
707 rb_control_frame_t
*cfp
= vm_get_ruby_level_caller_cfp(th
, th
->cfp
);
710 block
= *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp
);
711 th
->base_block
= &block
;
712 th
->base_block
->self
= self
;
713 th
->base_block
->iseq
= cfp
->iseq
; /* TODO */
716 rb_raise(rb_eRuntimeError
, "Can't eval on top of Fiber or Thread");
722 th
->mild_compile_error
++;
723 iseqval
= rb_iseq_compile(src
, rb_str_new2(file
), INT2FIX(line
));
724 th
->mild_compile_error
--;
727 vm_set_eval_stack(th
, iseqval
, cref
);
730 if (0) { /* for debug */
731 extern VALUE
ruby_iseq_disasm(VALUE
);
732 printf("%s\n", RSTRING_PTR(ruby_iseq_disasm(iseqval
)));
736 GetISeqPtr(iseqval
, iseq
);
737 if (bind
&& iseq
->local_size
> 0) {
738 bind
->env
= vm_make_env_object(th
, th
->cfp
);
742 CHECK_STACK_OVERFLOW(th
->cfp
, iseq
->stack_max
);
743 result
= vm_eval_body(th
);
746 th
->mild_compile_error
= mild_compile_error
;
747 th
->parse_in_eval
= parse_in_eval
;
750 if (state
== TAG_RAISE
) {
751 VALUE errinfo
= th
->errinfo
;
752 if (strcmp(file
, "(eval)") == 0) {
753 VALUE mesg
, errat
, bt2
;
754 extern VALUE
rb_get_backtrace(VALUE info
);
756 errat
= rb_get_backtrace(errinfo
);
757 mesg
= rb_attr_get(errinfo
, rb_intern("mesg"));
758 if (!NIL_P(errat
) && TYPE(errat
) == T_ARRAY
&&
759 (bt2
= vm_backtrace(th
, -2), RARRAY_LEN(bt2
) > 0)) {
760 if (!NIL_P(mesg
) && TYPE(mesg
) == T_STRING
&& !RSTRING_LEN(mesg
)) {
761 rb_str_update(mesg
, 0, 0, rb_str_new2(": "));
762 rb_str_update(mesg
, 0, 0, RARRAY_PTR(errat
)[0]);
764 RARRAY_PTR(errat
)[0] = RARRAY_PTR(bt2
)[0];
767 rb_exc_raise(errinfo
);
775 eval_string(VALUE self
, VALUE src
, VALUE scope
, const char *file
, int line
)
777 return eval_string_with_cref(self
, src
, scope
, 0, file
, line
);
782 * eval(string [, binding [, filename [,lineno]]]) => obj
784 * Evaluates the Ruby expression(s) in <em>string</em>. If
785 * <em>binding</em> is given, the evaluation is performed in its
786 * context. The binding may be a <code>Binding</code> object or a
787 * <code>Proc</code> object. If the optional <em>filename</em> and
788 * <em>lineno</em> parameters are present, they will be used when
789 * reporting syntax errors.
791 * def getBinding(str)
795 * eval "str + ' Fred'" #=> "hello Fred"
796 * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
800 rb_f_eval(int argc
, VALUE
*argv
, VALUE self
)
802 VALUE src
, scope
, vfile
, vline
;
803 const char *file
= "(eval)";
806 rb_scan_args(argc
, argv
, "13", &src
, &scope
, &vfile
, &vline
);
807 if (rb_safe_level() >= 4) {
809 if (!NIL_P(scope
) && !OBJ_TAINTED(scope
)) {
810 rb_raise(rb_eSecurityError
,
811 "Insecure: can't modify trusted binding");
815 SafeStringValue(src
);
821 line
= NUM2INT(vline
);
825 file
= RSTRING_PTR(vfile
);
826 return eval_string(self
, src
, scope
, file
, line
);
830 rb_eval_string(const char *str
)
832 return eval_string(rb_vm_top_self(), rb_str_new2(str
), Qnil
, "(eval)", 1);
836 rb_eval_string_protect(const char *str
, int *state
)
838 return rb_protect((VALUE (*)(VALUE
))rb_eval_string
, (VALUE
)str
, state
);
842 rb_eval_string_wrap(const char *str
, int *state
)
845 rb_thread_t
*th
= GET_THREAD();
846 VALUE self
= th
->top_self
;
847 VALUE wrapper
= th
->top_wrapper
;
850 th
->top_wrapper
= rb_module_new();
851 th
->top_self
= rb_obj_clone(rb_vm_top_self());
852 rb_extend_object(th
->top_self
, th
->top_wrapper
);
854 val
= rb_eval_string_protect(str
, &status
);
857 th
->top_wrapper
= wrapper
;
869 rb_eval_cmd(VALUE cmd
, VALUE arg
, int level
)
872 VALUE val
= Qnil
; /* OK */
873 volatile int safe
= rb_safe_level();
875 if (OBJ_TAINTED(cmd
)) {
879 if (TYPE(cmd
) != T_STRING
) {
881 rb_set_safe_level_force(level
);
882 if ((state
= EXEC_TAG()) == 0) {
883 val
= rb_funcall2(cmd
, rb_intern("call"), RARRAY_LEN(arg
),
888 rb_set_safe_level_force(safe
);
896 if ((state
= EXEC_TAG()) == 0) {
897 val
= eval_string(rb_vm_top_self(), cmd
, Qnil
, 0, 0);
901 rb_set_safe_level_force(safe
);
902 if (state
) vm_jump_tag_but_local_jump(state
, val
);
906 /* block eval under the class/module context */
909 yield_under(VALUE under
, VALUE self
, VALUE values
)
911 rb_thread_t
*th
= GET_THREAD();
912 rb_block_t block
, *blockptr
;
913 NODE
*cref
= vm_cref_push(th
, under
, NOEX_PUBLIC
);
915 if ((blockptr
= GC_GUARDED_PTR_REF(th
->cfp
->lfp
[0])) != 0) {
918 th
->cfp
->lfp
[0] = GC_GUARDED_PTR(&block
);
921 if (values
== Qundef
) {
922 return vm_yield_with_cref(th
, 0, 0, cref
);
925 return vm_yield_with_cref(th
, RARRAY_LEN(values
), RARRAY_PTR(values
), cref
);
929 /* string eval under the class/module context */
931 eval_under(VALUE under
, VALUE self
, VALUE src
, const char *file
, int line
)
933 NODE
*cref
= vm_cref_push(GET_THREAD(), under
, NOEX_PUBLIC
);
935 if (rb_safe_level() >= 4) {
939 SafeStringValue(src
);
942 return eval_string_with_cref(self
, src
, Qnil
, cref
, file
, line
);
946 specific_eval(int argc
, VALUE
*argv
, VALUE klass
, VALUE self
)
948 if (rb_block_given_p()) {
950 rb_raise(rb_eArgError
, "wrong number of arguments (%d for 0)", argc
);
952 return yield_under(klass
, self
, Qundef
);
955 const char *file
= "(eval)";
959 rb_raise(rb_eArgError
, "block not supplied");
962 if (rb_safe_level() >= 4) {
963 StringValue(argv
[0]);
966 SafeStringValue(argv
[0]);
969 const char *name
= rb_id2name(rb_frame_callee());
970 rb_raise(rb_eArgError
,
971 "wrong number of arguments: %s(src) or %s{..}",
975 line
= NUM2INT(argv
[2]);
977 file
= StringValuePtr(argv
[1]);
980 return eval_under(klass
, self
, argv
[0], file
, line
);
986 * obj.instance_eval(string [, filename [, lineno]] ) => obj
987 * obj.instance_eval {| | block } => obj
989 * Evaluates a string containing Ruby source code, or the given block,
990 * within the context of the receiver (_obj_). In order to set the
991 * context, the variable +self+ is set to _obj_ while
992 * the code is executing, giving the code access to _obj_'s
993 * instance variables. In the version of <code>instance_eval</code>
994 * that takes a +String+, the optional second and third
995 * parameters supply a filename and starting line number that are used
996 * when reporting compilation errors.
998 * class KlassWithSecret
1003 * k = KlassWithSecret.new
1004 * k.instance_eval { @secret } #=> 99
1008 rb_obj_instance_eval(int argc
, VALUE
*argv
, VALUE self
)
1012 if (SPECIAL_CONST_P(self
)) {
1016 klass
= rb_singleton_class(self
);
1018 return specific_eval(argc
, argv
, klass
, self
);
1023 * obj.instance_exec(arg...) {|var...| block } => obj
1025 * Executes the given block within the context of the receiver
1026 * (_obj_). In order to set the context, the variable +self+ is set
1027 * to _obj_ while the code is executing, giving the code access to
1028 * _obj_'s instance variables. Arguments are passed as block parameters.
1030 * class KlassWithSecret
1035 * k = KlassWithSecret.new
1036 * k.instance_exec(5) {|x| @secret+x } #=> 104
1040 rb_obj_instance_exec(int argc
, VALUE
*argv
, VALUE self
)
1044 if (SPECIAL_CONST_P(self
)) {
1048 klass
= rb_singleton_class(self
);
1050 return yield_under(klass
, self
, rb_ary_new4(argc
, argv
));
1055 * mod.class_eval(string [, filename [, lineno]]) => obj
1056 * mod.module_eval {|| block } => obj
1058 * Evaluates the string or block in the context of _mod_. This can
1059 * be used to add methods to a class. <code>module_eval</code> returns
1060 * the result of evaluating its argument. The optional _filename_
1061 * and _lineno_ parameters set the text for error messages.
1065 * a = %q{def hello() "Hello there!" end}
1066 * Thing.module_eval(a)
1067 * puts Thing.new.hello()
1068 * Thing.module_eval("invalid code", "dummy", 123)
1070 * <em>produces:</em>
1073 * dummy:123:in `module_eval': undefined local variable
1074 * or method `code' for Thing:Class
1078 rb_mod_module_eval(int argc
, VALUE
*argv
, VALUE mod
)
1080 return specific_eval(argc
, argv
, mod
, mod
);
1085 * mod.module_exec(arg...) {|var...| block } => obj
1086 * mod.class_exec(arg...) {|var...| block } => obj
1088 * Evaluates the given block in the context of the class/module.
1089 * The method defined in the block will belong to the receiver.
1094 * def hello() "Hello there!" end
1096 * puts Thing.new.hello()
1098 * <em>produces:</em>
1104 rb_mod_module_exec(int argc
, VALUE
*argv
, VALUE mod
)
1106 return yield_under(mod
, mod
, rb_ary_new4(argc
, argv
));
1109 NORETURN(static VALUE rb_f_throw
_((int, VALUE
*)));
1113 * throw(symbol [, obj])
1115 * Transfers control to the end of the active +catch+ block
1116 * waiting for _symbol_. Raises +NameError+ if there
1117 * is no +catch+ block for the symbol. The optional second
1118 * parameter supplies a return value for the +catch+ block,
1119 * which otherwise defaults to +nil+. For examples, see
1120 * <code>Kernel::catch</code>.
1124 rb_f_throw(int argc
, VALUE
*argv
)
1127 rb_thread_t
*th
= GET_THREAD();
1128 struct rb_vm_tag
*tt
= th
->tag
;
1130 rb_scan_args(argc
, argv
, "11", &tag
, &value
);
1132 if (tt
->tag
== tag
) {
1139 VALUE desc
= rb_inspect(tag
);
1140 rb_raise(rb_eArgError
, "uncaught throw %s", RSTRING_PTR(desc
));
1142 rb_trap_restore_mask();
1143 th
->errinfo
= NEW_THROW_OBJECT(tag
, 0, TAG_THROW
);
1145 JUMP_TAG(TAG_THROW
);
1147 return Qnil
; /* not reached */
1152 rb_throw(const char *tag
, VALUE val
)
1156 argv
[0] = ID2SYM(rb_intern(tag
));
1158 rb_f_throw(2, argv
);
1162 rb_throw_obj(VALUE tag
, VALUE val
)
1168 rb_f_throw(2, argv
);
1173 * catch(symbol) {| | block } > obj
1175 * +catch+ executes its block. If a +throw+ is
1176 * executed, Ruby searches up its stack for a +catch+ block
1177 * with a tag corresponding to the +throw+'s
1178 * _symbol_. If found, that block is terminated, and
1179 * +catch+ returns the value given to +throw+. If
1180 * +throw+ is not called, the block terminates normally, and
1181 * the value of +catch+ is the value of the last expression
1182 * evaluated. +catch+ expressions may be nested, and the
1183 * +throw+ call need not be in lexical scope.
1187 * throw :done if n <= 0
1192 * catch(:done) { routine(3) }
1194 * <em>produces:</em>
1203 rb_f_catch(int argc
, VALUE
*argv
)
1207 VALUE val
= Qnil
; /* OK */
1208 rb_thread_t
*th
= GET_THREAD();
1209 rb_control_frame_t
*saved_cfp
= th
->cfp
;
1212 tag
= rb_obj_alloc(rb_cObject
);
1215 rb_scan_args(argc
, argv
, "01", &tag
);
1221 if ((state
= EXEC_TAG()) == 0) {
1222 val
= rb_yield_0(1, &tag
);
1224 else if (state
== TAG_THROW
&& RNODE(th
->errinfo
)->u1
.value
== tag
) {
1225 th
->cfp
= saved_cfp
;
1226 val
= th
->tag
->retval
;
1238 catch_null_i(VALUE dmy
)
1240 return rb_funcall(Qnil
, rb_intern("catch"), 0, 0);
1246 return rb_funcall(Qnil
, rb_intern("catch"), 1, tag
);
1250 rb_catch(const char *tag
, VALUE (*func
)(), VALUE data
)
1253 return rb_iterate(catch_null_i
, 0, func
, data
);
1255 return rb_iterate(catch_i
, ID2SYM(rb_intern(tag
)), func
, data
);
1259 rb_catch_obj(VALUE tag
, VALUE (*func
)(), VALUE data
)
1261 return rb_iterate((VALUE (*)_((VALUE
)))catch_i
, tag
, func
, data
);
1266 * caller(start=1) => array
1268 * Returns the current execution stack---an array containing strings in
1269 * the form ``<em>file:line</em>'' or ``<em>file:line: in
1270 * `method'</em>''. The optional _start_ parameter
1271 * determines the number of initial stack entries to omit from the
1283 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
1284 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
1285 * c(2) #=> ["prog:8:in `c'", "prog:12"]
1286 * c(3) #=> ["prog:13"]
1290 rb_f_caller(int argc
, VALUE
*argv
)
1295 rb_scan_args(argc
, argv
, "01", &level
);
1300 lev
= NUM2INT(level
);
1302 rb_raise(rb_eArgError
, "negative level (%d)", lev
);
1304 return vm_backtrace(GET_THREAD(), lev
);
1313 ary
= vm_backtrace(GET_THREAD(), -1);
1314 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
1315 printf("\tfrom %s\n", RSTRING_PTR(RARRAY_PTR(ary
)[i
]));
1320 rb_make_backtrace(void)
1322 return vm_backtrace(GET_THREAD(), -1);
1328 rb_define_global_function("catch", rb_f_catch
, -1);
1329 rb_define_global_function("throw", rb_f_throw
, -1);
1331 rb_define_global_function("loop", rb_f_loop
, 0);
1333 rb_define_method(rb_cBasicObject
, "instance_eval", rb_obj_instance_eval
, -1);
1334 rb_define_method(rb_cBasicObject
, "instance_exec", rb_obj_instance_exec
, -1);
1335 rb_define_private_method(rb_cBasicObject
, "method_missing", rb_method_missing
, -1);
1337 rb_define_method(rb_cBasicObject
, "__send__", rb_f_send
, -1);
1338 rb_define_method(rb_mKernel
, "send", rb_f_send
, -1);
1339 rb_define_method(rb_mKernel
, "public_send", rb_f_public_send
, -1);
1341 rb_define_method(rb_cModule
, "module_exec", rb_mod_module_exec
, -1);
1342 rb_define_method(rb_cModule
, "class_exec", rb_mod_module_exec
, -1);
1344 rb_define_global_function("caller", rb_f_caller
, -1);