mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Mon Apr 13 05:20:15 2015 +0000
Revision:
1:8ccd1d494a4b
Parent:
0:158c61bb030f
- code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** proc.c - Proc class
mzta 0:158c61bb030f 3 **
mzta 0:158c61bb030f 4 ** See Copyright Notice in mruby.h
mzta 0:158c61bb030f 5 */
mzta 0:158c61bb030f 6
mzta 0:158c61bb030f 7 #include "mruby.h"
mzta 0:158c61bb030f 8 #include "mruby/class.h"
mzta 0:158c61bb030f 9 #include "mruby/proc.h"
mzta 0:158c61bb030f 10 #include "mruby/opcode.h"
mzta 0:158c61bb030f 11
mzta 0:158c61bb030f 12 static mrb_code call_iseq[] = {
mzta 0:158c61bb030f 13 MKOP_A(OP_CALL, 0),
mzta 0:158c61bb030f 14 };
mzta 0:158c61bb030f 15
mzta 0:158c61bb030f 16 struct RProc *
mzta 0:158c61bb030f 17 mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 18 {
mzta 0:158c61bb030f 19 struct RProc *p;
mzta 0:158c61bb030f 20 mrb_callinfo *ci = mrb->c->ci;
mzta 0:158c61bb030f 21
mzta 0:158c61bb030f 22 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
mzta 0:158c61bb030f 23 p->target_class = 0;
mzta 0:158c61bb030f 24 if (ci) {
mzta 0:158c61bb030f 25 if (ci->proc)
mzta 0:158c61bb030f 26 p->target_class = ci->proc->target_class;
mzta 0:158c61bb030f 27 if (!p->target_class)
mzta 0:158c61bb030f 28 p->target_class = ci->target_class;
mzta 0:158c61bb030f 29 }
mzta 0:158c61bb030f 30 p->body.irep = irep;
mzta 0:158c61bb030f 31 p->env = 0;
mzta 0:158c61bb030f 32 mrb_irep_incref(mrb, irep);
mzta 0:158c61bb030f 33
mzta 0:158c61bb030f 34 return p;
mzta 0:158c61bb030f 35 }
mzta 0:158c61bb030f 36
mzta 0:158c61bb030f 37 static struct REnv*
mzta 0:158c61bb030f 38 env_new(mrb_state *mrb, int nlocals)
mzta 0:158c61bb030f 39 {
mzta 0:158c61bb030f 40 struct REnv *e;
mzta 0:158c61bb030f 41
mzta 0:158c61bb030f 42 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
mzta 0:158c61bb030f 43 MRB_SET_ENV_STACK_LEN(e, nlocals);
mzta 0:158c61bb030f 44 e->mid = mrb->c->ci->mid;
mzta 0:158c61bb030f 45 e->cioff = mrb->c->ci - mrb->c->cibase;
mzta 0:158c61bb030f 46 e->stack = mrb->c->stack;
mzta 0:158c61bb030f 47
mzta 0:158c61bb030f 48 return e;
mzta 0:158c61bb030f 49 }
mzta 0:158c61bb030f 50
mzta 0:158c61bb030f 51 static void
mzta 0:158c61bb030f 52 closure_setup(mrb_state *mrb, struct RProc *p, int nlocals)
mzta 0:158c61bb030f 53 {
mzta 0:158c61bb030f 54 struct REnv *e;
mzta 0:158c61bb030f 55
mzta 0:158c61bb030f 56 if (!mrb->c->ci->env) {
mzta 0:158c61bb030f 57 e = env_new(mrb, nlocals);
mzta 0:158c61bb030f 58 mrb->c->ci->env = e;
mzta 0:158c61bb030f 59 }
mzta 0:158c61bb030f 60 else {
mzta 0:158c61bb030f 61 e = mrb->c->ci->env;
mzta 0:158c61bb030f 62 }
mzta 0:158c61bb030f 63 p->env = e;
mzta 0:158c61bb030f 64 }
mzta 0:158c61bb030f 65
mzta 0:158c61bb030f 66 struct RProc *
mzta 0:158c61bb030f 67 mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
mzta 0:158c61bb030f 68 {
mzta 0:158c61bb030f 69 struct RProc *p = mrb_proc_new(mrb, irep);
mzta 0:158c61bb030f 70
mzta 0:158c61bb030f 71 closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals);
mzta 0:158c61bb030f 72 return p;
mzta 0:158c61bb030f 73 }
mzta 0:158c61bb030f 74
mzta 0:158c61bb030f 75 MRB_API struct RProc *
mzta 0:158c61bb030f 76 mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
mzta 0:158c61bb030f 77 {
mzta 0:158c61bb030f 78 struct RProc *p;
mzta 0:158c61bb030f 79
mzta 0:158c61bb030f 80 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
mzta 0:158c61bb030f 81 p->body.func = func;
mzta 0:158c61bb030f 82 p->flags |= MRB_PROC_CFUNC;
mzta 0:158c61bb030f 83 p->env = 0;
mzta 0:158c61bb030f 84
mzta 0:158c61bb030f 85 return p;
mzta 0:158c61bb030f 86 }
mzta 0:158c61bb030f 87
mzta 0:158c61bb030f 88 MRB_API struct RProc *
mzta 0:158c61bb030f 89 mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv)
mzta 0:158c61bb030f 90 {
mzta 0:158c61bb030f 91 struct RProc *p = mrb_proc_new_cfunc(mrb, func);
mzta 0:158c61bb030f 92 struct REnv *e;
mzta 0:158c61bb030f 93 int i;
mzta 0:158c61bb030f 94
mzta 0:158c61bb030f 95 p->env = e = env_new(mrb, argc);
mzta 0:158c61bb030f 96 MRB_ENV_UNSHARE_STACK(e);
mzta 0:158c61bb030f 97 e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
mzta 0:158c61bb030f 98 if (argv) {
mzta 0:158c61bb030f 99 for (i = 0; i < argc; ++i) {
mzta 0:158c61bb030f 100 e->stack[i] = argv[i];
mzta 0:158c61bb030f 101 }
mzta 0:158c61bb030f 102 }
mzta 0:158c61bb030f 103 else {
mzta 0:158c61bb030f 104 for (i = 0; i < argc; ++i) {
mzta 0:158c61bb030f 105 SET_NIL_VALUE(e->stack[i]);
mzta 0:158c61bb030f 106 }
mzta 0:158c61bb030f 107 }
mzta 0:158c61bb030f 108 return p;
mzta 0:158c61bb030f 109 }
mzta 0:158c61bb030f 110
mzta 0:158c61bb030f 111 MRB_API struct RProc *
mzta 0:158c61bb030f 112 mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals)
mzta 0:158c61bb030f 113 {
mzta 0:158c61bb030f 114 return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL);
mzta 0:158c61bb030f 115 }
mzta 0:158c61bb030f 116
mzta 0:158c61bb030f 117 MRB_API mrb_value
mzta 0:158c61bb030f 118 mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
mzta 0:158c61bb030f 119 {
mzta 0:158c61bb030f 120 struct RProc *p = mrb->c->ci->proc;
mzta 0:158c61bb030f 121 struct REnv *e = p->env;
mzta 0:158c61bb030f 122
mzta 0:158c61bb030f 123 if (!MRB_PROC_CFUNC_P(p)) {
mzta 0:158c61bb030f 124 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc.");
mzta 0:158c61bb030f 125 }
mzta 0:158c61bb030f 126 if (!e) {
mzta 0:158c61bb030f 127 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
mzta 0:158c61bb030f 128 }
mzta 0:158c61bb030f 129 if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) {
mzta 0:158c61bb030f 130 mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)",
mzta 0:158c61bb030f 131 mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e)));
mzta 0:158c61bb030f 132 }
mzta 0:158c61bb030f 133
mzta 0:158c61bb030f 134 return e->stack[idx];
mzta 0:158c61bb030f 135 }
mzta 0:158c61bb030f 136
mzta 0:158c61bb030f 137 MRB_API void
mzta 0:158c61bb030f 138 mrb_proc_copy(struct RProc *a, struct RProc *b)
mzta 0:158c61bb030f 139 {
mzta 0:158c61bb030f 140 a->flags = b->flags;
mzta 0:158c61bb030f 141 a->body = b->body;
mzta 0:158c61bb030f 142 if (!MRB_PROC_CFUNC_P(a)) {
mzta 0:158c61bb030f 143 a->body.irep->refcnt++;
mzta 0:158c61bb030f 144 }
mzta 0:158c61bb030f 145 a->target_class = b->target_class;
mzta 0:158c61bb030f 146 a->env = b->env;
mzta 0:158c61bb030f 147 }
mzta 0:158c61bb030f 148
mzta 0:158c61bb030f 149 static mrb_value
mzta 0:158c61bb030f 150 mrb_proc_initialize(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 151 {
mzta 0:158c61bb030f 152 mrb_value blk;
mzta 0:158c61bb030f 153
mzta 0:158c61bb030f 154 mrb_get_args(mrb, "&", &blk);
mzta 0:158c61bb030f 155 if (mrb_nil_p(blk)) {
mzta 0:158c61bb030f 156 /* Calling Proc.new without a block is not implemented yet */
mzta 0:158c61bb030f 157 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
mzta 0:158c61bb030f 158 }
mzta 0:158c61bb030f 159 else {
mzta 0:158c61bb030f 160 mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(blk));
mzta 0:158c61bb030f 161 }
mzta 0:158c61bb030f 162 return self;
mzta 0:158c61bb030f 163 }
mzta 0:158c61bb030f 164
mzta 0:158c61bb030f 165 static mrb_value
mzta 0:158c61bb030f 166 mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 167 {
mzta 0:158c61bb030f 168 mrb_value proc;
mzta 0:158c61bb030f 169
mzta 0:158c61bb030f 170 mrb_get_args(mrb, "o", &proc);
mzta 0:158c61bb030f 171 if (mrb_type(proc) != MRB_TT_PROC) {
mzta 0:158c61bb030f 172 mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
mzta 0:158c61bb030f 173 }
mzta 0:158c61bb030f 174 mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc));
mzta 0:158c61bb030f 175 return self;
mzta 0:158c61bb030f 176 }
mzta 0:158c61bb030f 177
mzta 0:158c61bb030f 178 int
mzta 0:158c61bb030f 179 mrb_proc_cfunc_p(struct RProc *p)
mzta 0:158c61bb030f 180 {
mzta 0:158c61bb030f 181 return MRB_PROC_CFUNC_P(p);
mzta 0:158c61bb030f 182 }
mzta 0:158c61bb030f 183
mzta 0:158c61bb030f 184 mrb_value
mzta 0:158c61bb030f 185 mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)
mzta 0:158c61bb030f 186 {
mzta 0:158c61bb030f 187 return (p->body.func)(mrb, self);
mzta 0:158c61bb030f 188 }
mzta 0:158c61bb030f 189
mzta 0:158c61bb030f 190 mrb_code*
mzta 0:158c61bb030f 191 mrb_proc_iseq(mrb_state *mrb, struct RProc *p)
mzta 0:158c61bb030f 192 {
mzta 0:158c61bb030f 193 return p->body.irep->iseq;
mzta 0:158c61bb030f 194 }
mzta 0:158c61bb030f 195
mzta 0:158c61bb030f 196 /* 15.2.17.4.2 */
mzta 0:158c61bb030f 197 static mrb_value
mzta 0:158c61bb030f 198 mrb_proc_arity(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 199 {
mzta 0:158c61bb030f 200 struct RProc *p = mrb_proc_ptr(self);
mzta 0:158c61bb030f 201 mrb_code *iseq = mrb_proc_iseq(mrb, p);
mzta 0:158c61bb030f 202 mrb_aspec aspec;
mzta 0:158c61bb030f 203 int ma, ra, pa, arity;
mzta 0:158c61bb030f 204
mzta 0:158c61bb030f 205 if (MRB_PROC_CFUNC_P(p)) {
mzta 0:158c61bb030f 206 /* TODO cfunc aspec not implemented yet */
mzta 0:158c61bb030f 207 return mrb_fixnum_value(-1);
mzta 0:158c61bb030f 208 }
mzta 0:158c61bb030f 209
mzta 0:158c61bb030f 210 /* arity is depend on OP_ENTER */
mzta 0:158c61bb030f 211 if (GET_OPCODE(*iseq) != OP_ENTER) {
mzta 0:158c61bb030f 212 return mrb_fixnum_value(0);
mzta 0:158c61bb030f 213 }
mzta 0:158c61bb030f 214
mzta 0:158c61bb030f 215 aspec = GETARG_Ax(*iseq);
mzta 0:158c61bb030f 216 ma = MRB_ASPEC_REQ(aspec);
mzta 0:158c61bb030f 217 ra = MRB_ASPEC_REST(aspec);
mzta 0:158c61bb030f 218 pa = MRB_ASPEC_POST(aspec);
mzta 0:158c61bb030f 219 arity = ra ? -(ma + pa + 1) : ma + pa;
mzta 0:158c61bb030f 220
mzta 0:158c61bb030f 221 return mrb_fixnum_value(arity);
mzta 0:158c61bb030f 222 }
mzta 0:158c61bb030f 223
mzta 0:158c61bb030f 224 /* 15.3.1.2.6 */
mzta 0:158c61bb030f 225 /* 15.3.1.3.27 */
mzta 0:158c61bb030f 226 /*
mzta 0:158c61bb030f 227 * call-seq:
mzta 0:158c61bb030f 228 * lambda { |...| block } -> a_proc
mzta 0:158c61bb030f 229 *
mzta 0:158c61bb030f 230 * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
mzta 0:158c61bb030f 231 * check the number of parameters passed when called.
mzta 0:158c61bb030f 232 */
mzta 0:158c61bb030f 233 static mrb_value
mzta 0:158c61bb030f 234 proc_lambda(mrb_state *mrb, mrb_value self)
mzta 0:158c61bb030f 235 {
mzta 0:158c61bb030f 236 mrb_value blk;
mzta 0:158c61bb030f 237 struct RProc *p;
mzta 0:158c61bb030f 238
mzta 0:158c61bb030f 239 mrb_get_args(mrb, "&", &blk);
mzta 0:158c61bb030f 240 if (mrb_nil_p(blk)) {
mzta 0:158c61bb030f 241 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
mzta 0:158c61bb030f 242 }
mzta 0:158c61bb030f 243 p = mrb_proc_ptr(blk);
mzta 0:158c61bb030f 244 if (!MRB_PROC_STRICT_P(p)) {
mzta 0:158c61bb030f 245 struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c);
mzta 0:158c61bb030f 246 mrb_proc_copy(p2, p);
mzta 0:158c61bb030f 247 p2->flags |= MRB_PROC_STRICT;
mzta 0:158c61bb030f 248 return mrb_obj_value(p2);
mzta 0:158c61bb030f 249 }
mzta 0:158c61bb030f 250 return blk;
mzta 0:158c61bb030f 251 }
mzta 0:158c61bb030f 252
mzta 0:158c61bb030f 253 void
mzta 0:158c61bb030f 254 mrb_init_proc(mrb_state *mrb)
mzta 0:158c61bb030f 255 {
mzta 0:158c61bb030f 256 struct RProc *m;
mzta 0:158c61bb030f 257 mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
mzta 0:158c61bb030f 258 static const mrb_irep mrb_irep_zero = { 0 };
mzta 0:158c61bb030f 259
mzta 0:158c61bb030f 260 *call_irep = mrb_irep_zero;
mzta 0:158c61bb030f 261 call_irep->flags = MRB_ISEQ_NO_FREE;
mzta 0:158c61bb030f 262 call_irep->iseq = call_iseq;
mzta 0:158c61bb030f 263 call_irep->ilen = 1;
mzta 0:158c61bb030f 264
mzta 0:158c61bb030f 265 mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE());
mzta 0:158c61bb030f 266 mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
mzta 0:158c61bb030f 267 mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
mzta 0:158c61bb030f 268
mzta 0:158c61bb030f 269 m = mrb_proc_new(mrb, call_irep);
mzta 0:158c61bb030f 270 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
mzta 0:158c61bb030f 271 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
mzta 0:158c61bb030f 272
mzta 0:158c61bb030f 273 mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */
mzta 0:158c61bb030f 274 mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */
mzta 0:158c61bb030f 275 }
mzta 0:158c61bb030f 276