Changeset 439 for EcnlProtoTool/trunk/mruby-2.1.1/src/proc.c
- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-2.1.1
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-2.1.1/src/proc.c
r331 r439 10 10 #include <mruby/opcode.h> 11 11 12 static mrb_code call_iseq[] = {13 MKOP_A(OP_CALL, 0),12 static const mrb_code call_iseq[] = { 13 OP_CALL, 14 14 }; 15 15 16 struct RProc 16 struct RProc* 17 17 mrb_proc_new(mrb_state *mrb, mrb_irep *irep) 18 18 { … … 21 21 22 22 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); 23 p->target_class = 0;24 23 if (ci) { 25 if (ci->proc) 26 p->target_class = ci->proc->target_class; 27 if (!p->target_class) 28 p->target_class = ci->target_class; 24 struct RClass *tc = NULL; 25 26 if (ci->proc) { 27 tc = MRB_PROC_TARGET_CLASS(ci->proc); 28 } 29 if (tc == NULL) { 30 tc = ci->target_class; 31 } 32 p->upper = ci->proc; 33 p->e.target_class = tc; 29 34 } 30 35 p->body.irep = irep; 31 p->env = 0;32 36 mrb_irep_incref(mrb, irep); 33 37 … … 36 40 37 41 static struct REnv* 38 env_new(mrb_state *mrb, int nlocals)42 env_new(mrb_state *mrb, mrb_int nlocals) 39 43 { 40 44 struct REnv *e; 41 42 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env); 43 MRB_SET_ENV_STACK_LEN(e, nlocals); 44 e->cxt.c = mrb->c; 45 e->cioff = mrb->c->ci - mrb->c->cibase; 45 mrb_callinfo *ci = mrb->c->ci; 46 int bidx; 47 48 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL); 49 MRB_ENV_SET_STACK_LEN(e, nlocals); 50 bidx = ci->argc; 51 if (ci->argc < 0) bidx = 2; 52 else bidx += 1; 53 MRB_ENV_SET_BIDX(e, bidx); 54 e->mid = ci->mid; 46 55 e->stack = mrb->c->stack; 56 e->cxt = mrb->c; 47 57 48 58 return e; … … 50 60 51 61 static void 52 closure_setup(mrb_state *mrb, struct RProc *p, int nlocals) 53 { 54 struct REnv *e; 55 56 if (!mrb->c->ci->env) { 57 e = env_new(mrb, nlocals); 58 mrb->c->ci->env = e; 59 } 60 else { 61 e = mrb->c->ci->env; 62 } 63 p->env = e; 64 mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env); 65 } 66 67 struct RProc * 62 closure_setup(mrb_state *mrb, struct RProc *p) 63 { 64 mrb_callinfo *ci = mrb->c->ci; 65 struct RProc *up = p->upper; 66 struct REnv *e = NULL; 67 68 if (ci && ci->env) { 69 e = ci->env; 70 } 71 else if (up) { 72 struct RClass *tc = MRB_PROC_TARGET_CLASS(p); 73 74 e = env_new(mrb, up->body.irep->nlocals); 75 ci->env = e; 76 if (tc) { 77 e->c = tc; 78 mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc); 79 } 80 if (MRB_PROC_ENV_P(up) && MRB_PROC_ENV(up)->cxt == NULL) { 81 e->mid = MRB_PROC_ENV(up)->mid; 82 } 83 } 84 if (e) { 85 p->e.env = e; 86 p->flags |= MRB_PROC_ENVSET; 87 mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e); 88 } 89 } 90 91 struct RProc* 68 92 mrb_closure_new(mrb_state *mrb, mrb_irep *irep) 69 93 { 70 94 struct RProc *p = mrb_proc_new(mrb, irep); 71 95 72 closure_setup(mrb, p , mrb->c->ci->proc->body.irep->nlocals);96 closure_setup(mrb, p); 73 97 return p; 74 98 } 75 99 76 MRB_API struct RProc 100 MRB_API struct RProc* 77 101 mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func) 78 102 { … … 81 105 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); 82 106 p->body.func = func; 83 p->flags |= MRB_PROC_CFUNC; 84 p->env = 0; 107 p->flags |= MRB_PROC_CFUNC_FL; 108 p->upper = 0; 109 p->e.target_class = 0; 85 110 86 111 return p; 87 112 } 88 113 89 MRB_API struct RProc 114 MRB_API struct RProc* 90 115 mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv) 91 116 { … … 94 119 int i; 95 120 96 p->env = e = env_new(mrb, argc); 97 mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env); 121 p->e.env = e = env_new(mrb, argc); 122 p->flags |= MRB_PROC_ENVSET; 123 mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e); 98 124 MRB_ENV_UNSHARE_STACK(e); 99 125 e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); … … 111 137 } 112 138 113 MRB_API struct RProc 139 MRB_API struct RProc* 114 140 mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals) 115 141 { … … 121 147 { 122 148 struct RProc *p = mrb->c->ci->proc; 123 struct REnv *e = p->env;124 125 if (! MRB_PROC_CFUNC_P(p)) {149 struct REnv *e; 150 151 if (!p || !MRB_PROC_CFUNC_P(p)) { 126 152 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc."); 127 153 } 154 e = MRB_PROC_ENV(p); 128 155 if (!e) { 129 156 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv."); 130 157 } 131 158 if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) { 132 mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: % S (expected: 0 <= index < %S)",133 mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e)));159 mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %i (expected: 0 <= index < %i)", 160 idx, MRB_ENV_STACK_LEN(e)); 134 161 } 135 162 … … 140 167 mrb_proc_copy(struct RProc *a, struct RProc *b) 141 168 { 169 if (a->body.irep) { 170 /* already initialized proc */ 171 return; 172 } 142 173 a->flags = b->flags; 143 174 a->body = b->body; … … 145 176 a->body.irep->refcnt++; 146 177 } 147 a->target_class = b->target_class; 148 a->env = b->env; 178 a->upper = b->upper; 179 a->e.env = b->e.env; 180 /* a->e.target_class = a->e.target_class; */ 149 181 } 150 182 … … 156 188 struct RProc *p; 157 189 158 mrb_get_args(mrb, "&", &blk); 159 if (mrb_nil_p(blk)) { 160 /* Calling Proc.new without a block is not implemented yet */ 161 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); 162 } 190 /* Calling Proc.new without a block is not implemented yet */ 191 mrb_get_args(mrb, "&!", &blk); 163 192 p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class)); 164 193 mrb_proc_copy(p, mrb_proc_ptr(blk)); 165 194 proc = mrb_obj_value(p); 166 mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, blk); 195 mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, proc); 196 if (!MRB_PROC_STRICT_P(p) && 197 mrb->c->ci > mrb->c->cibase && MRB_PROC_ENV(p) == mrb->c->ci[-1].env) { 198 p->flags |= MRB_PROC_ORPHAN; 199 } 167 200 return proc; 168 201 } … … 174 207 175 208 mrb_get_args(mrb, "o", &proc); 176 if ( mrb_type(proc) != MRB_TT_PROC) {209 if (!mrb_proc_p(proc)) { 177 210 mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); 178 211 } … … 181 214 } 182 215 183 int184 mrb_proc_cfunc_p(struct RProc *p)185 {186 return MRB_PROC_CFUNC_P(p);187 }188 189 mrb_value190 mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)191 {192 return (p->body.func)(mrb, self);193 }194 195 216 /* 15.2.17.4.2 */ 196 217 static mrb_value 197 mrb_proc_arity(mrb_state *mrb, mrb_value self) 198 { 199 struct RProc *p = mrb_proc_ptr(self); 200 struct mrb_irep *irep; 201 mrb_code *iseq; 202 mrb_aspec aspec; 203 int ma, op, ra, pa, arity; 204 205 if (MRB_PROC_CFUNC_P(p)) { 206 /* TODO cfunc aspec not implemented yet */ 207 return mrb_fixnum_value(-1); 208 } 209 210 irep = p->body.irep; 211 if (!irep) { 212 return mrb_fixnum_value(0); 213 } 214 215 iseq = irep->iseq; 216 /* arity is depend on OP_ENTER */ 217 if (GET_OPCODE(*iseq) != OP_ENTER) { 218 return mrb_fixnum_value(0); 219 } 220 221 aspec = GETARG_Ax(*iseq); 222 ma = MRB_ASPEC_REQ(aspec); 223 op = MRB_ASPEC_OPT(aspec); 224 ra = MRB_ASPEC_REST(aspec); 225 pa = MRB_ASPEC_POST(aspec); 226 arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa; 227 228 return mrb_fixnum_value(arity); 218 proc_arity(mrb_state *mrb, mrb_value self) 219 { 220 return mrb_fixnum_value(mrb_proc_arity(mrb_proc_ptr(self))); 229 221 } 230 222 … … 248 240 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); 249 241 } 250 if ( mrb_type(blk) != MRB_TT_PROC) {242 if (!mrb_proc_p(blk)) { 251 243 mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); 252 244 } … … 261 253 } 262 254 255 mrb_int 256 mrb_proc_arity(const struct RProc *p) 257 { 258 struct mrb_irep *irep; 259 const mrb_code *pc; 260 mrb_aspec aspec; 261 int ma, op, ra, pa, arity; 262 263 if (MRB_PROC_CFUNC_P(p)) { 264 /* TODO cfunc aspec not implemented yet */ 265 return -1; 266 } 267 268 irep = p->body.irep; 269 if (!irep) { 270 return 0; 271 } 272 273 pc = irep->iseq; 274 /* arity is depend on OP_ENTER */ 275 if (*pc != OP_ENTER) { 276 return 0; 277 } 278 279 aspec = PEEK_W(pc+1); 280 ma = MRB_ASPEC_REQ(aspec); 281 op = MRB_ASPEC_OPT(aspec); 282 ra = MRB_ASPEC_REST(aspec); 283 pa = MRB_ASPEC_POST(aspec); 284 arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa; 285 286 return arity; 287 } 288 263 289 void 264 290 mrb_init_proc(mrb_state *mrb) 265 291 { 266 struct RProc *m; 292 struct RProc *p; 293 mrb_method_t m; 267 294 mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); 268 295 static const mrb_irep mrb_irep_zero = { 0 }; … … 274 301 call_irep->nregs = 2; /* receiver and block */ 275 302 276 mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_ ANY());303 mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); 277 304 mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); 278 mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); 279 280 m = mrb_proc_new(mrb, call_irep); 305 mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE()); 306 307 p = mrb_proc_new(mrb, call_irep); 308 MRB_METHOD_FROM_PROC(m, p); 281 309 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m); 282 310 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m); 283 311 284 mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE() ); /* 15.3.1.2.6 */285 mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE() ); /* 15.3.1.3.27 */286 } 312 mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.2.6 */ 313 mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.3.27 */ 314 }
Note:
See TracChangeset
for help on using the changeset viewer.