mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
proc.c
00001 /* 00002 ** proc.c - Proc class 00003 ** 00004 ** See Copyright Notice in mruby.h 00005 */ 00006 00007 #include "mruby.h" 00008 #include "mruby/class.h" 00009 #include "mruby/proc.h" 00010 #include "mruby/opcode.h" 00011 00012 static mrb_code call_iseq[] = { 00013 MKOP_A(OP_CALL, 0), 00014 }; 00015 00016 struct RProc * 00017 mrb_proc_new(mrb_state *mrb, mrb_irep *irep) 00018 { 00019 struct RProc *p; 00020 mrb_callinfo *ci = mrb->c->ci; 00021 00022 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); 00023 p->target_class = 0; 00024 if (ci) { 00025 if (ci->proc) 00026 p->target_class = ci->proc->target_class; 00027 if (!p->target_class) 00028 p->target_class = ci->target_class; 00029 } 00030 p->body.irep = irep; 00031 p->env = 0; 00032 mrb_irep_incref(mrb, irep); 00033 00034 return p; 00035 } 00036 00037 static struct REnv* 00038 env_new(mrb_state *mrb, int nlocals) 00039 { 00040 struct REnv *e; 00041 00042 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env); 00043 MRB_SET_ENV_STACK_LEN(e, nlocals); 00044 e->mid = mrb->c->ci->mid; 00045 e->cioff = mrb->c->ci - mrb->c->cibase; 00046 e->stack = mrb->c->stack; 00047 00048 return e; 00049 } 00050 00051 static void 00052 closure_setup(mrb_state *mrb, struct RProc *p, int nlocals) 00053 { 00054 struct REnv *e; 00055 00056 if (!mrb->c->ci->env) { 00057 e = env_new(mrb, nlocals); 00058 mrb->c->ci->env = e; 00059 } 00060 else { 00061 e = mrb->c->ci->env; 00062 } 00063 p->env = e; 00064 } 00065 00066 struct RProc * 00067 mrb_closure_new(mrb_state *mrb, mrb_irep *irep) 00068 { 00069 struct RProc *p = mrb_proc_new(mrb, irep); 00070 00071 closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals); 00072 return p; 00073 } 00074 00075 MRB_API struct RProc * 00076 mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func) 00077 { 00078 struct RProc *p; 00079 00080 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); 00081 p->body.func = func; 00082 p->flags |= MRB_PROC_CFUNC; 00083 p->env = 0; 00084 00085 return p; 00086 } 00087 00088 MRB_API struct RProc * 00089 mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv) 00090 { 00091 struct RProc *p = mrb_proc_new_cfunc(mrb, func); 00092 struct REnv *e; 00093 int i; 00094 00095 p->env = e = env_new(mrb, argc); 00096 MRB_ENV_UNSHARE_STACK(e); 00097 e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); 00098 if (argv) { 00099 for (i = 0; i < argc; ++i) { 00100 e->stack[i] = argv[i]; 00101 } 00102 } 00103 else { 00104 for (i = 0; i < argc; ++i) { 00105 SET_NIL_VALUE(e->stack[i]); 00106 } 00107 } 00108 return p; 00109 } 00110 00111 MRB_API struct RProc * 00112 mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals) 00113 { 00114 return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL); 00115 } 00116 00117 MRB_API mrb_value 00118 mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx) 00119 { 00120 struct RProc *p = mrb->c->ci->proc; 00121 struct REnv *e = p->env; 00122 00123 if (!MRB_PROC_CFUNC_P(p)) { 00124 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc."); 00125 } 00126 if (!e) { 00127 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv."); 00128 } 00129 if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) { 00130 mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)", 00131 mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e))); 00132 } 00133 00134 return e->stack[idx]; 00135 } 00136 00137 MRB_API void 00138 mrb_proc_copy(struct RProc *a, struct RProc *b) 00139 { 00140 a->flags = b->flags; 00141 a->body = b->body; 00142 if (!MRB_PROC_CFUNC_P(a)) { 00143 a->body.irep->refcnt++; 00144 } 00145 a->target_class = b->target_class; 00146 a->env = b->env; 00147 } 00148 00149 static mrb_value 00150 mrb_proc_initialize(mrb_state *mrb, mrb_value self) 00151 { 00152 mrb_value blk; 00153 00154 mrb_get_args(mrb, "&", &blk); 00155 if (mrb_nil_p(blk)) { 00156 /* Calling Proc.new without a block is not implemented yet */ 00157 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); 00158 } 00159 else { 00160 mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(blk)); 00161 } 00162 return self; 00163 } 00164 00165 static mrb_value 00166 mrb_proc_init_copy(mrb_state *mrb, mrb_value self) 00167 { 00168 mrb_value proc; 00169 00170 mrb_get_args(mrb, "o", &proc); 00171 if (mrb_type(proc) != MRB_TT_PROC) { 00172 mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); 00173 } 00174 mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc)); 00175 return self; 00176 } 00177 00178 int 00179 mrb_proc_cfunc_p(struct RProc *p) 00180 { 00181 return MRB_PROC_CFUNC_P(p); 00182 } 00183 00184 mrb_value 00185 mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self) 00186 { 00187 return (p->body.func)(mrb, self); 00188 } 00189 00190 mrb_code* 00191 mrb_proc_iseq(mrb_state *mrb, struct RProc *p) 00192 { 00193 return p->body.irep->iseq; 00194 } 00195 00196 /* 15.2.17.4.2 */ 00197 static mrb_value 00198 mrb_proc_arity(mrb_state *mrb, mrb_value self) 00199 { 00200 struct RProc *p = mrb_proc_ptr(self); 00201 mrb_code *iseq = mrb_proc_iseq(mrb, p); 00202 mrb_aspec aspec; 00203 int ma, ra, pa, arity; 00204 00205 if (MRB_PROC_CFUNC_P(p)) { 00206 /* TODO cfunc aspec not implemented yet */ 00207 return mrb_fixnum_value(-1); 00208 } 00209 00210 /* arity is depend on OP_ENTER */ 00211 if (GET_OPCODE(*iseq) != OP_ENTER) { 00212 return mrb_fixnum_value(0); 00213 } 00214 00215 aspec = GETARG_Ax(*iseq); 00216 ma = MRB_ASPEC_REQ(aspec); 00217 ra = MRB_ASPEC_REST(aspec); 00218 pa = MRB_ASPEC_POST(aspec); 00219 arity = ra ? -(ma + pa + 1) : ma + pa; 00220 00221 return mrb_fixnum_value(arity); 00222 } 00223 00224 /* 15.3.1.2.6 */ 00225 /* 15.3.1.3.27 */ 00226 /* 00227 * call-seq: 00228 * lambda { |...| block } -> a_proc 00229 * 00230 * Equivalent to <code>Proc.new</code>, except the resulting Proc objects 00231 * check the number of parameters passed when called. 00232 */ 00233 static mrb_value 00234 proc_lambda(mrb_state *mrb, mrb_value self) 00235 { 00236 mrb_value blk; 00237 struct RProc *p; 00238 00239 mrb_get_args(mrb, "&", &blk); 00240 if (mrb_nil_p(blk)) { 00241 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); 00242 } 00243 p = mrb_proc_ptr(blk); 00244 if (!MRB_PROC_STRICT_P(p)) { 00245 struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c); 00246 mrb_proc_copy(p2, p); 00247 p2->flags |= MRB_PROC_STRICT; 00248 return mrb_obj_value(p2); 00249 } 00250 return blk; 00251 } 00252 00253 void 00254 mrb_init_proc(mrb_state *mrb) 00255 { 00256 struct RProc *m; 00257 mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); 00258 static const mrb_irep mrb_irep_zero = { 0 }; 00259 00260 *call_irep = mrb_irep_zero; 00261 call_irep->flags = MRB_ISEQ_NO_FREE; 00262 call_irep->iseq = call_iseq; 00263 call_irep->ilen = 1; 00264 00265 mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE()); 00266 mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); 00267 mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); 00268 00269 m = mrb_proc_new(mrb, call_irep); 00270 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m); 00271 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m); 00272 00273 mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */ 00274 mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */ 00275 } 00276
Generated on Tue Jul 12 2022 18:00:35 by 1.7.2