static VALUE binding_dup(VALUE self) { VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *src, *dst; GetBindingPtr(self, src); GetBindingPtr(bindval, dst); dst->env = src->env; return bindval; }
static VALUE binding_dup(VALUE self, SEL sel) { VALUE bindval = binding_alloc(rb_cBinding); rb_vm_binding_t *src, *dst; GetBindingPtr(self, src); GetBindingPtr(bindval, dst); GC_WB(&dst->self, src->self); GC_WB(&dst->next, src->next); GC_WB(&dst->locals, src->locals); GC_WB(&dst->outer_stack, src->outer_stack); GC_WB(&dst->block, src->block); return bindval; }
VALUE rb_binding_new(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; GetBindingPtr(bindval, bind); GC_WB(&bind->env, vm_make_env_object(th, cfp)); return bindval; }
VALUE rb_binding_new(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th_get_ruby_level_cfp(th, th->cfp); VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; GetBindingPtr(bindval, bind); bind->env = th_make_env_object(th, cfp); bind->cref_stack = ruby_cref(); return bindval; }
VALUE rb_f_eval(VALUE self, SEL sel, int argc, VALUE *argv) { VALUE src, scope, vfile, vline; const char *file = "(eval)"; int line = 1; rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline); if (rb_safe_level() >= 4) { StringValue(src); if (!NIL_P(scope) && !OBJ_TAINTED(scope)) { rb_raise(rb_eSecurityError, "Insecure: can't modify trusted binding"); } } else { SafeStringValue(src); } if (argc >= 3) { StringValue(vfile); } if (argc >= 4) { line = NUM2INT(vline); } if (!NIL_P(vfile)) { file = RSTRING_PTR(vfile); } VALUE klass; switch (TYPE(self)) { case T_CLASS: case T_MODULE: klass = self; break; default: klass = 0; break; } #if 0 if (!NIL_P(scope)) { rb_vm_binding_t *t = rb_vm_current_binding(); assert(t != NULL); rb_vm_binding_t *tmp = rb_vm_create_binding(t->self, t->block, GetBindingPtr(scope), 0, NULL, false); GC_WB(&tmp->locals, t->locals); scope = rb_binding_new_from_binding(tmp); } #endif return eval_string(self, klass, src, scope, file, line); }
static VALUE eval_string_with_should_push_outer(VALUE self, VALUE klass, VALUE src, VALUE scope, const char *file, const int line, bool should_push_outer) { rb_vm_binding_t *binding = NULL; if (scope != Qnil) { if (!rb_obj_is_kind_of(scope, rb_cBinding)) { rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)", rb_obj_classname(scope)); } binding = GetBindingPtr(scope); } return rb_vm_eval_string(self, klass, src, binding, file, line, should_push_outer); }
VALUE rb_binding_new(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; if (cfp == 0) { rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber."); } GetBindingPtr(bindval, bind); bind->env = rb_vm_make_env_object(th, cfp); return bindval; }
/* * call-seq: * prc.binding => binding * * Returns the binding associated with <i>prc</i>. Note that * <code>Kernel#eval</code> accepts either a <code>Proc</code> or a * <code>Binding</code> object as its second parameter. * * def fred(param) * proc {} * end * * b = fred(99) * eval("param", b.binding) #=> 99 */ static VALUE proc_binding(VALUE self) { rb_proc_t *proc; VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; GetProcPtr(self, proc); GetBindingPtr(bindval, bind); if (TYPE(proc->block.iseq) == T_NODE) { rb_raise(rb_eArgError, "Can't create Binding from C level Proc"); } bind->env = proc->envval; return bindval; }
static void vm_set_main_stack(rb_thread_t *th, VALUE iseqval) { VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")); rb_binding_t *bind; rb_iseq_t *iseq; rb_env_t *env; GetBindingPtr(toplevel_binding, bind); GetEnvPtr(bind->env, env); th->base_block = &env->block; vm_set_eval_stack(th, iseqval, 0); th->base_block = 0; /* save binding */ GetISeqPtr(iseqval, iseq); if (bind && iseq->local_size > 0) { bind->env = rb_vm_make_env_object(th, th->cfp); } CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); }
static VALUE binding_of_caller(VALUE self, VALUE rb_level) { rb_thread_t *th; GetThreadPtr(rb_thread_current(), th); rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size); int level = FIX2INT(rb_level); // attempt to locate the nth parent control frame for (int i = 0; i < level; i++) { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); if (cfp >= limit_cfp) rb_raise(rb_eRuntimeError, "Invalid frame, gone beyond end of stack!"); // skip invalid frames if (!valid_frame_p(cfp, limit_cfp)) cfp = find_valid_frame(cfp, limit_cfp); } VALUE bindval = binding_alloc(rb_cBinding); rb_binding_t *bind; if (cfp == 0) rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber."); GetBindingPtr(bindval, bind); bind->env = rb_vm_make_env_object(th, cfp); bind->filename = cfp->iseq->filename; bind->line_no = rb_vm_get_sourceline(cfp); rb_iv_set(bindval, "@frame_type", frametype_name(cfp->flag)); rb_iv_set(bindval, "@frame_description", cfp->iseq->name); return bindval; }
/*RHO static*/ VALUE eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line) { int state; VALUE result = Qundef; VALUE envval; rb_binding_t *bind = 0; rb_thread_t *th = GET_THREAD(); rb_env_t *env = NULL; rb_block_t block; volatile int parse_in_eval; volatile int mild_compile_error; if (file == 0) { file = rb_sourcefile(); line = rb_sourceline(); } parse_in_eval = th->parse_in_eval; mild_compile_error = th->mild_compile_error; PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { rb_iseq_t *iseq; volatile VALUE iseqval; if (scope != Qnil) { if (rb_obj_is_kind_of(scope, rb_cBinding)) { GetBindingPtr(scope, bind); envval = bind->env; } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected Binding)", rb_obj_classname(scope)); } GetEnvPtr(envval, env); th->base_block = &env->block; } else { rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp != 0) { block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp); th->base_block = █ th->base_block->self = self; th->base_block->iseq = cfp->iseq; /* TODO */ } else { rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread"); } } //RHO if ( TYPE(src) != T_STRING ){ iseqval = src; }else //RHO { /* make eval iseq */ th->parse_in_eval++; th->mild_compile_error++; iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line)); th->mild_compile_error--; th->parse_in_eval--; } vm_set_eval_stack(th, iseqval, cref); th->base_block = 0; if (0) { /* for debug */ printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval))); } /* save new env */ GetISeqPtr(iseqval, iseq); if (bind && iseq->local_size > 0) { bind->env = rb_vm_make_env_object(th, th->cfp); } /* kick */ CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); result = vm_exec(th); } POP_TAG(); th->mild_compile_error = mild_compile_error; th->parse_in_eval = parse_in_eval; if (state) { if (state == TAG_RAISE) { VALUE errinfo = th->errinfo; if (strcmp(file, "(eval)") == 0) { VALUE mesg, errat, bt2; extern VALUE rb_get_backtrace(VALUE info); ID id_mesg; CONST_ID(id_mesg, "mesg"); errat = rb_get_backtrace(errinfo); mesg = rb_attr_get(errinfo, id_mesg); if (!NIL_P(errat) && TYPE(errat) == T_ARRAY && (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) { if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) { if (OBJ_FROZEN(mesg)) { VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2); rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg)); } else { rb_str_update(mesg, 0, 0, rb_str_new2(": ")); rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]); } } RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0]; } } rb_exc_raise(errinfo); } JUMP_TAG(state); } return result; }