static mrb_value method_call(mrb_state *mrb, mrb_value self) { mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@recv")); struct RClass *owner = mrb_class_ptr(mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner"))); mrb_int argc; mrb_value *argv, ret, block; mrb_sym orig_mid; mrb_get_args(mrb, "*&", &argv, &argc, &block); orig_mid = mrb->c->ci->mid; mrb->c->ci->mid = mrb_symbol(name); if (mrb_nil_p(proc)) { mrb_value missing_argv = mrb_ary_new_from_values(mrb, argc, argv); mrb_ary_unshift(mrb, missing_argv, name); ret = mrb_funcall_argv(mrb, recv, mrb_intern_lit(mrb, "method_missing"), argc + 1, RARRAY_PTR(missing_argv)); } else if (!mrb_nil_p(block)) { /* workaround since `mrb_yield_with_class` does not support passing block as parameter need new API that initializes `mrb->c->stack[argc+1]` with block passed by argument */ ret = mrb_funcall_with_block(mrb, recv, mrb_symbol(name), argc, argv, block); } else { ret = mrb_yield_with_class(mrb, proc, argc, argv, recv, owner); } mrb->c->ci->mid = orig_mid; return ret; }
static void* mrb_thread_func(void* data) { mrb_thread_context* context = (mrb_thread_context*) data; mrb_state* mrb = context->mrb; context->result = mrb_yield_with_class(mrb, mrb_obj_value(context->proc), context->argc, context->argv, mrb_nil_value(), mrb->object_class); context->alive = FALSE; return NULL; }
/* * call-seq: * Struct.new( [aString] [, aSym]+> ) -> StructClass * StructClass.new(arg, ...) -> obj * StructClass[arg, ...] -> obj * * Creates a new class, named by <i>aString</i>, containing accessor * methods for the given symbols. If the name <i>aString</i> is * omitted, an anonymous structure class will be created. Otherwise, * the name of this struct will appear as a constant in class * <code>Struct</code>, so it must be unique for all * <code>Struct</code>s in the system and should start with a capital * letter. Assigning a structure class to a constant effectively gives * the class the name of the constant. * * <code>Struct::new</code> returns a new <code>Class</code> object, * which can then be used to create specific instances of the new * structure. The number of actual parameters must be * less than or equal to the number of attributes defined for this * class; unset parameters default to <code>nil</code>. Passing too many * parameters will raise an <code>ArgumentError</code>. * * The remaining methods listed in this section (class and instance) * are defined for this generated class. * * # Create a structure with a name in Struct * Struct.new("Customer", :name, :address) #=> Struct::Customer * Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main"> * * # Create a structure named by its constant * Customer = Struct.new(:name, :address) #=> Customer * Customer.new("Dave", "123 Main") #=> #<struct Customer name="Dave", address="123 Main"> */ static mrb_value mrb_struct_s_def(mrb_state *mrb, mrb_value klass) { mrb_value name, rest; mrb_value *pargv; int argcnt; mrb_int i; mrb_value b, st; mrb_sym id; mrb_value *argv; int argc; name = mrb_nil_value(); rest = mrb_nil_value(); mrb_get_args(mrb, "*&", &argv, &argc, &b); if (argc == 0) { /* special case to avoid crash */ rest = mrb_ary_new(mrb); } else { if (argc > 0) name = argv[0]; if (argc > 1) rest = argv[1]; if (mrb_array_p(rest)) { if (!mrb_nil_p(name) && mrb_symbol_p(name)) { /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ mrb_ary_unshift(mrb, rest, name); name = mrb_nil_value(); } } else { pargv = &argv[1]; argcnt = argc-1; if (!mrb_nil_p(name) && mrb_symbol_p(name)) { /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ name = mrb_nil_value(); pargv = &argv[0]; argcnt++; } rest = mrb_ary_new_from_values(mrb, argcnt, pargv); } for (i=0; i<RARRAY_LEN(rest); i++) { id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]); RARRAY_PTR(rest)[i] = mrb_symbol_value(id); } } st = make_struct(mrb, name, rest, struct_class(mrb)); if (!mrb_nil_p(b)) { mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(klass)); } return st; }
static void load_mrb_file(mrb_state *mrb, mrb_value filepath) { char *fpath = RSTRING_PTR(filepath); int arena_idx; FILE *fp; mrb_irep *irep; { FILE *fp = fopen(fpath, "rb"); if (fp == NULL) { mrb_load_fail( mrb, mrb_str_new_cstr(mrb, fpath), "cannot load such file" ); return; } fclose(fp); } arena_idx = mrb_gc_arena_save(mrb); fp = fopen(fpath, "rb"); irep = mrb_read_irep_file(mrb, fp); fclose(fp); mrb_gc_arena_restore(mrb, arena_idx); if (irep) { struct RProc *proc; /* size_t i; for (i = sirep; i < mrb->irep_len; i++) { mrb->irep[i]->filename = mrb_string_value_ptr(mrb, filepath); } */ replace_stop_with_return(mrb, irep); proc = mrb_proc_new(mrb, irep); proc->target_class = mrb->object_class; arena_idx = mrb_gc_arena_save(mrb); mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class); mrb_gc_arena_restore(mrb, arena_idx); } else if (mrb->exc) { // fail to load longjmp(*(jmp_buf*)mrb->jmp, 1); } }
static void load_mrb_file(mrb_state *mrb, mrb_value filepath) { char *fpath = RSTRING_PTR(filepath); int ai; FILE *fp; mrb_irep *irep; fp = fopen(fpath, "rb"); if (fp == NULL) { mrb_load_fail( mrb, mrb_str_new_cstr(mrb, fpath), "cannot load such file" ); return; } ai = mrb_gc_arena_save(mrb); irep = mrb_read_irep_file(mrb, fp); fclose(fp); mrb_gc_arena_restore(mrb, ai); if (irep) { struct RProc *proc; /* size_t i; for (i = sirep; i < mrb->irep_len; i++) { mrb->irep[i]->filename = mrb_string_value_ptr(mrb, filepath); } */ #ifdef USE_MRUBY_OLD_BYTE_CODE replace_stop_with_return(mrb, irep); #endif proc = mrb_proc_new(mrb, irep); MRB_PROC_SET_TARGET_CLASS(proc, mrb->object_class); ai = mrb_gc_arena_save(mrb); mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class); mrb_gc_arena_restore(mrb, ai); } else if (mrb->exc) { // fail to load longjmp(*(jmp_buf*)mrb->jmp, 1); } }
static void* mrb_future_func(void* data) { mrb_value result; mrb_future_context *context = (mrb_future_context *) data; struct mrb_state *mrb = context->mrb; struct mrb_state *oldmrb = context->oldmrb; mrb_value self = context->self; result = mrb_yield_with_class(mrb, mrb_obj_value(context->proc), context->argc, context->argv, context->self, mrb_class(mrb, context->self)); mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "value"), result); mrb_iv_set(oldmrb, self, mrb_intern_cstr(oldmrb, "_state"), mrb_fixnum_value(FUTURE_FINISH)); return NULL; }
static void mrb_load_irep_data(mrb_state* mrb, const uint8_t* data) { int ai = mrb_gc_arena_save(mrb); mrb_irep *irep = mrb_read_irep(mrb,data); mrb_gc_arena_restore(mrb,ai); if (irep) { int ai; struct RProc *proc; replace_stop_with_return(mrb, irep); proc = mrb_proc_new(mrb, irep); proc->target_class = mrb->object_class; ai = mrb_gc_arena_save(mrb); mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class); mrb_gc_arena_restore(mrb, ai); } else if (mrb->exc) { // fail to load longjmp(*(jmp_buf*)mrb->jmp, 1); } }
/* * call-seq: * obj.instance_eval {| | block } -> obj * * Evaluates the given block,within the context of the receiver (_obj_). * In order to set the context, the variable +self+ is set to _obj_ while * the code is executing, giving the code access to _obj_'s * instance variables. In the version of <code>instance_eval</code> * that takes a +String+, the optional second and third * parameters supply a filename and starting line number that are used * when reporting compilation errors. * * class KlassWithSecret * def initialize * @secret = 99 * end * end * k = KlassWithSecret.new * k.instance_eval { @secret } #=> 99 */ static mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) { mrb_value a, b; mrb_value cv; struct RClass *c; if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); } switch (mrb_type(self)) { case MRB_TT_SYMBOL: case MRB_TT_FIXNUM: case MRB_TT_FLOAT: c = 0; break; default: cv = mrb_singleton_class(mrb, self); c = mrb_class_ptr(cv); break; } return mrb_yield_with_class(mrb, b, 0, 0, self, c); }