mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
mbed-mruby
How to use
Class
src/vm.c@1:8ccd1d494a4b, 2015-04-13 (annotated)
- 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?
User | Revision | Line number | New contents of line |
---|---|---|---|
mzta | 0:158c61bb030f | 1 | /* |
mzta | 0:158c61bb030f | 2 | ** vm.c - virtual machine for mruby |
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 <stddef.h> |
mzta | 0:158c61bb030f | 8 | #include <stdarg.h> |
mzta | 0:158c61bb030f | 9 | #include <math.h> |
mzta | 0:158c61bb030f | 10 | #include "mruby.h" |
mzta | 0:158c61bb030f | 11 | #include "mruby/array.h" |
mzta | 0:158c61bb030f | 12 | #include "mruby/class.h" |
mzta | 0:158c61bb030f | 13 | #include "mruby/hash.h" |
mzta | 0:158c61bb030f | 14 | #include "mruby/irep.h" |
mzta | 0:158c61bb030f | 15 | #include "mruby/numeric.h" |
mzta | 0:158c61bb030f | 16 | #include "mruby/proc.h" |
mzta | 0:158c61bb030f | 17 | #include "mruby/range.h" |
mzta | 0:158c61bb030f | 18 | #include "mruby/string.h" |
mzta | 0:158c61bb030f | 19 | #include "mruby/variable.h" |
mzta | 0:158c61bb030f | 20 | #include "mruby/error.h" |
mzta | 0:158c61bb030f | 21 | #include "mruby/opcode.h" |
mzta | 0:158c61bb030f | 22 | #include "value_array.h" |
mzta | 0:158c61bb030f | 23 | #include "mrb_throw.h" |
mzta | 0:158c61bb030f | 24 | |
mzta | 0:158c61bb030f | 25 | #ifndef ENABLE_STDIO |
mzta | 0:158c61bb030f | 26 | #if defined(__cplusplus) |
mzta | 0:158c61bb030f | 27 | extern "C" { |
mzta | 0:158c61bb030f | 28 | #endif |
mzta | 0:158c61bb030f | 29 | void abort(void); |
mzta | 0:158c61bb030f | 30 | #if defined(__cplusplus) |
mzta | 0:158c61bb030f | 31 | } /* extern "C" { */ |
mzta | 0:158c61bb030f | 32 | #endif |
mzta | 0:158c61bb030f | 33 | #endif |
mzta | 0:158c61bb030f | 34 | |
mzta | 0:158c61bb030f | 35 | #define STACK_INIT_SIZE 128 |
mzta | 0:158c61bb030f | 36 | #define CALLINFO_INIT_SIZE 32 |
mzta | 0:158c61bb030f | 37 | |
mzta | 0:158c61bb030f | 38 | /* Define amount of linear stack growth. */ |
mzta | 0:158c61bb030f | 39 | #ifndef MRB_STACK_GROWTH |
mzta | 0:158c61bb030f | 40 | #define MRB_STACK_GROWTH 128 |
mzta | 0:158c61bb030f | 41 | #endif |
mzta | 0:158c61bb030f | 42 | |
mzta | 0:158c61bb030f | 43 | /* Maximum stack depth. Should be set lower on memory constrained systems. |
mzta | 0:158c61bb030f | 44 | The value below allows about 60000 recursive calls in the simplest case. */ |
mzta | 0:158c61bb030f | 45 | #ifndef MRB_STACK_MAX |
mzta | 0:158c61bb030f | 46 | #define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH) |
mzta | 0:158c61bb030f | 47 | #endif |
mzta | 0:158c61bb030f | 48 | |
mzta | 0:158c61bb030f | 49 | #ifdef VM_DEBUG |
mzta | 0:158c61bb030f | 50 | # define DEBUG(x) (x) |
mzta | 0:158c61bb030f | 51 | #else |
mzta | 0:158c61bb030f | 52 | # define DEBUG(x) |
mzta | 0:158c61bb030f | 53 | #endif |
mzta | 0:158c61bb030f | 54 | |
mzta | 0:158c61bb030f | 55 | #define ARENA_RESTORE(mrb,ai) (mrb)->arena_idx = (ai) |
mzta | 0:158c61bb030f | 56 | |
mzta | 0:158c61bb030f | 57 | static inline void |
mzta | 0:158c61bb030f | 58 | stack_clear(mrb_value *from, size_t count) |
mzta | 0:158c61bb030f | 59 | { |
mzta | 0:158c61bb030f | 60 | #ifndef MRB_NAN_BOXING |
mzta | 0:158c61bb030f | 61 | const mrb_value mrb_value_zero = { { 0 } }; |
mzta | 0:158c61bb030f | 62 | |
mzta | 0:158c61bb030f | 63 | while (count-- > 0) { |
mzta | 0:158c61bb030f | 64 | *from++ = mrb_value_zero; |
mzta | 0:158c61bb030f | 65 | } |
mzta | 0:158c61bb030f | 66 | #else |
mzta | 0:158c61bb030f | 67 | while (count-- > 0) { |
mzta | 0:158c61bb030f | 68 | SET_NIL_VALUE(*from); |
mzta | 0:158c61bb030f | 69 | from++; |
mzta | 0:158c61bb030f | 70 | } |
mzta | 0:158c61bb030f | 71 | #endif |
mzta | 0:158c61bb030f | 72 | } |
mzta | 0:158c61bb030f | 73 | |
mzta | 0:158c61bb030f | 74 | static inline void |
mzta | 0:158c61bb030f | 75 | stack_copy(mrb_value *dst, const mrb_value *src, size_t size) |
mzta | 0:158c61bb030f | 76 | { |
mzta | 0:158c61bb030f | 77 | while (size-- > 0) { |
mzta | 0:158c61bb030f | 78 | *dst++ = *src++; |
mzta | 0:158c61bb030f | 79 | } |
mzta | 0:158c61bb030f | 80 | } |
mzta | 0:158c61bb030f | 81 | |
mzta | 0:158c61bb030f | 82 | static void |
mzta | 0:158c61bb030f | 83 | stack_init(mrb_state *mrb) |
mzta | 0:158c61bb030f | 84 | { |
mzta | 0:158c61bb030f | 85 | struct mrb_context *c = mrb->c; |
mzta | 0:158c61bb030f | 86 | |
mzta | 0:158c61bb030f | 87 | /* mrb_assert(mrb->stack == NULL); */ |
mzta | 0:158c61bb030f | 88 | c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value)); |
mzta | 0:158c61bb030f | 89 | c->stend = c->stbase + STACK_INIT_SIZE; |
mzta | 0:158c61bb030f | 90 | c->stack = c->stbase; |
mzta | 0:158c61bb030f | 91 | |
mzta | 0:158c61bb030f | 92 | /* mrb_assert(ci == NULL); */ |
mzta | 0:158c61bb030f | 93 | c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo)); |
mzta | 0:158c61bb030f | 94 | c->ciend = c->cibase + CALLINFO_INIT_SIZE; |
mzta | 0:158c61bb030f | 95 | c->ci = c->cibase; |
mzta | 0:158c61bb030f | 96 | c->ci->target_class = mrb->object_class; |
mzta | 0:158c61bb030f | 97 | c->ci->stackent = c->stack; |
mzta | 0:158c61bb030f | 98 | } |
mzta | 0:158c61bb030f | 99 | |
mzta | 0:158c61bb030f | 100 | static inline void |
mzta | 0:158c61bb030f | 101 | envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) |
mzta | 0:158c61bb030f | 102 | { |
mzta | 0:158c61bb030f | 103 | mrb_callinfo *ci = mrb->c->cibase; |
mzta | 0:158c61bb030f | 104 | |
mzta | 0:158c61bb030f | 105 | if (newbase == oldbase) return; |
mzta | 0:158c61bb030f | 106 | while (ci <= mrb->c->ci) { |
mzta | 0:158c61bb030f | 107 | struct REnv *e = ci->env; |
mzta | 0:158c61bb030f | 108 | if (e && MRB_ENV_STACK_SHARED_P(e)) { |
mzta | 0:158c61bb030f | 109 | ptrdiff_t off = e->stack - oldbase; |
mzta | 0:158c61bb030f | 110 | |
mzta | 0:158c61bb030f | 111 | e->stack = newbase + off; |
mzta | 0:158c61bb030f | 112 | } |
mzta | 0:158c61bb030f | 113 | ci->stackent = newbase + (ci->stackent - oldbase); |
mzta | 0:158c61bb030f | 114 | ci++; |
mzta | 0:158c61bb030f | 115 | } |
mzta | 0:158c61bb030f | 116 | } |
mzta | 0:158c61bb030f | 117 | |
mzta | 0:158c61bb030f | 118 | static inline void |
mzta | 0:158c61bb030f | 119 | init_new_stack_space(mrb_state *mrb, int room, int keep) |
mzta | 0:158c61bb030f | 120 | { |
mzta | 0:158c61bb030f | 121 | if (room > keep) { |
mzta | 0:158c61bb030f | 122 | /* do not leave uninitialized malloc region */ |
mzta | 0:158c61bb030f | 123 | stack_clear(&(mrb->c->stack[keep]), room - keep); |
mzta | 0:158c61bb030f | 124 | } |
mzta | 0:158c61bb030f | 125 | } |
mzta | 0:158c61bb030f | 126 | |
mzta | 0:158c61bb030f | 127 | /** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */ |
mzta | 0:158c61bb030f | 128 | |
mzta | 0:158c61bb030f | 129 | static void |
mzta | 0:158c61bb030f | 130 | stack_extend_alloc(mrb_state *mrb, int room, int keep) |
mzta | 0:158c61bb030f | 131 | { |
mzta | 0:158c61bb030f | 132 | mrb_value *oldbase = mrb->c->stbase; |
mzta | 0:158c61bb030f | 133 | int size = mrb->c->stend - mrb->c->stbase; |
mzta | 0:158c61bb030f | 134 | int off = mrb->c->stack - mrb->c->stbase; |
mzta | 0:158c61bb030f | 135 | |
mzta | 0:158c61bb030f | 136 | #ifdef MRB_STACK_EXTEND_DOUBLING |
mzta | 0:158c61bb030f | 137 | if (room <= size) |
mzta | 0:158c61bb030f | 138 | size *= 2; |
mzta | 0:158c61bb030f | 139 | else |
mzta | 0:158c61bb030f | 140 | size += room; |
mzta | 0:158c61bb030f | 141 | #else |
mzta | 0:158c61bb030f | 142 | /* Use linear stack growth. |
mzta | 0:158c61bb030f | 143 | It is slightly slower than doubling the stack space, |
mzta | 0:158c61bb030f | 144 | but it saves memory on small devices. */ |
mzta | 0:158c61bb030f | 145 | if (room <= MRB_STACK_GROWTH) |
mzta | 0:158c61bb030f | 146 | size += MRB_STACK_GROWTH; |
mzta | 0:158c61bb030f | 147 | else |
mzta | 0:158c61bb030f | 148 | size += room; |
mzta | 0:158c61bb030f | 149 | #endif |
mzta | 0:158c61bb030f | 150 | |
mzta | 0:158c61bb030f | 151 | mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size); |
mzta | 0:158c61bb030f | 152 | mrb->c->stack = mrb->c->stbase + off; |
mzta | 0:158c61bb030f | 153 | mrb->c->stend = mrb->c->stbase + size; |
mzta | 0:158c61bb030f | 154 | envadjust(mrb, oldbase, mrb->c->stbase); |
mzta | 0:158c61bb030f | 155 | |
mzta | 0:158c61bb030f | 156 | /* Raise an exception if the new stack size will be too large, |
mzta | 0:158c61bb030f | 157 | to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ |
mzta | 0:158c61bb030f | 158 | if (size > MRB_STACK_MAX) { |
mzta | 0:158c61bb030f | 159 | init_new_stack_space(mrb, room, keep); |
mzta | 0:158c61bb030f | 160 | mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")"); |
mzta | 0:158c61bb030f | 161 | } |
mzta | 0:158c61bb030f | 162 | } |
mzta | 0:158c61bb030f | 163 | |
mzta | 0:158c61bb030f | 164 | static inline void |
mzta | 0:158c61bb030f | 165 | stack_extend(mrb_state *mrb, int room, int keep) |
mzta | 0:158c61bb030f | 166 | { |
mzta | 0:158c61bb030f | 167 | if (mrb->c->stack + room >= mrb->c->stend) { |
mzta | 0:158c61bb030f | 168 | stack_extend_alloc(mrb, room, keep); |
mzta | 0:158c61bb030f | 169 | } |
mzta | 0:158c61bb030f | 170 | init_new_stack_space(mrb, room, keep); |
mzta | 0:158c61bb030f | 171 | } |
mzta | 0:158c61bb030f | 172 | |
mzta | 0:158c61bb030f | 173 | static inline struct REnv* |
mzta | 0:158c61bb030f | 174 | uvenv(mrb_state *mrb, int up) |
mzta | 0:158c61bb030f | 175 | { |
mzta | 0:158c61bb030f | 176 | struct REnv *e = mrb->c->ci->proc->env; |
mzta | 0:158c61bb030f | 177 | |
mzta | 0:158c61bb030f | 178 | while (up--) { |
mzta | 0:158c61bb030f | 179 | if (!e) return NULL; |
mzta | 0:158c61bb030f | 180 | e = (struct REnv*)e->c; |
mzta | 0:158c61bb030f | 181 | } |
mzta | 0:158c61bb030f | 182 | return e; |
mzta | 0:158c61bb030f | 183 | } |
mzta | 0:158c61bb030f | 184 | |
mzta | 0:158c61bb030f | 185 | static inline mrb_bool |
mzta | 0:158c61bb030f | 186 | is_strict(mrb_state *mrb, struct REnv *e) |
mzta | 0:158c61bb030f | 187 | { |
mzta | 0:158c61bb030f | 188 | int cioff = e->cioff; |
mzta | 0:158c61bb030f | 189 | |
mzta | 0:158c61bb030f | 190 | if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc && |
mzta | 0:158c61bb030f | 191 | MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) { |
mzta | 0:158c61bb030f | 192 | return TRUE; |
mzta | 0:158c61bb030f | 193 | } |
mzta | 0:158c61bb030f | 194 | return FALSE; |
mzta | 0:158c61bb030f | 195 | } |
mzta | 0:158c61bb030f | 196 | |
mzta | 0:158c61bb030f | 197 | static inline struct REnv* |
mzta | 0:158c61bb030f | 198 | top_env(mrb_state *mrb, struct RProc *proc) |
mzta | 0:158c61bb030f | 199 | { |
mzta | 0:158c61bb030f | 200 | struct REnv *e = proc->env; |
mzta | 0:158c61bb030f | 201 | |
mzta | 0:158c61bb030f | 202 | if (is_strict(mrb, e)) return e; |
mzta | 0:158c61bb030f | 203 | while (e->c) { |
mzta | 0:158c61bb030f | 204 | e = (struct REnv*)e->c; |
mzta | 0:158c61bb030f | 205 | if (is_strict(mrb, e)) return e; |
mzta | 0:158c61bb030f | 206 | } |
mzta | 0:158c61bb030f | 207 | return e; |
mzta | 0:158c61bb030f | 208 | } |
mzta | 0:158c61bb030f | 209 | |
mzta | 0:158c61bb030f | 210 | #define CI_ACC_SKIP -1 |
mzta | 0:158c61bb030f | 211 | #define CI_ACC_DIRECT -2 |
mzta | 0:158c61bb030f | 212 | |
mzta | 0:158c61bb030f | 213 | static mrb_callinfo* |
mzta | 0:158c61bb030f | 214 | cipush(mrb_state *mrb) |
mzta | 0:158c61bb030f | 215 | { |
mzta | 0:158c61bb030f | 216 | struct mrb_context *c = mrb->c; |
mzta | 0:158c61bb030f | 217 | mrb_callinfo *ci = c->ci; |
mzta | 0:158c61bb030f | 218 | |
mzta | 0:158c61bb030f | 219 | int eidx = ci->eidx; |
mzta | 0:158c61bb030f | 220 | int ridx = ci->ridx; |
mzta | 0:158c61bb030f | 221 | |
mzta | 0:158c61bb030f | 222 | if (ci + 1 == c->ciend) { |
mzta | 0:158c61bb030f | 223 | size_t size = ci - c->cibase; |
mzta | 0:158c61bb030f | 224 | |
mzta | 0:158c61bb030f | 225 | c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2); |
mzta | 0:158c61bb030f | 226 | c->ci = c->cibase + size; |
mzta | 0:158c61bb030f | 227 | c->ciend = c->cibase + size * 2; |
mzta | 0:158c61bb030f | 228 | } |
mzta | 0:158c61bb030f | 229 | ci = ++c->ci; |
mzta | 0:158c61bb030f | 230 | ci->eidx = eidx; |
mzta | 0:158c61bb030f | 231 | ci->ridx = ridx; |
mzta | 0:158c61bb030f | 232 | ci->env = 0; |
mzta | 0:158c61bb030f | 233 | ci->pc = 0; |
mzta | 0:158c61bb030f | 234 | ci->err = 0; |
mzta | 0:158c61bb030f | 235 | ci->proc = 0; |
mzta | 0:158c61bb030f | 236 | |
mzta | 0:158c61bb030f | 237 | return ci; |
mzta | 0:158c61bb030f | 238 | } |
mzta | 0:158c61bb030f | 239 | |
mzta | 0:158c61bb030f | 240 | static void |
mzta | 0:158c61bb030f | 241 | cipop(mrb_state *mrb) |
mzta | 0:158c61bb030f | 242 | { |
mzta | 0:158c61bb030f | 243 | struct mrb_context *c = mrb->c; |
mzta | 0:158c61bb030f | 244 | |
mzta | 0:158c61bb030f | 245 | if (c->ci->env) { |
mzta | 0:158c61bb030f | 246 | struct REnv *e = c->ci->env; |
mzta | 0:158c61bb030f | 247 | size_t len = (size_t)MRB_ENV_STACK_LEN(e); |
mzta | 0:158c61bb030f | 248 | mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); |
mzta | 0:158c61bb030f | 249 | |
mzta | 0:158c61bb030f | 250 | MRB_ENV_UNSHARE_STACK(e); |
mzta | 0:158c61bb030f | 251 | if (len > 0) { |
mzta | 0:158c61bb030f | 252 | stack_copy(p, e->stack, len); |
mzta | 0:158c61bb030f | 253 | } |
mzta | 0:158c61bb030f | 254 | e->stack = p; |
mzta | 0:158c61bb030f | 255 | mrb_write_barrier(mrb, (struct RBasic *)e); |
mzta | 0:158c61bb030f | 256 | } |
mzta | 0:158c61bb030f | 257 | |
mzta | 0:158c61bb030f | 258 | c->ci--; |
mzta | 0:158c61bb030f | 259 | } |
mzta | 0:158c61bb030f | 260 | |
mzta | 0:158c61bb030f | 261 | static void |
mzta | 0:158c61bb030f | 262 | ecall(mrb_state *mrb, int i) |
mzta | 0:158c61bb030f | 263 | { |
mzta | 0:158c61bb030f | 264 | struct RProc *p; |
mzta | 0:158c61bb030f | 265 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 266 | mrb_value *self = mrb->c->stack; |
mzta | 0:158c61bb030f | 267 | struct RObject *exc; |
mzta | 0:158c61bb030f | 268 | |
mzta | 0:158c61bb030f | 269 | p = mrb->c->ensure[i]; |
mzta | 0:158c61bb030f | 270 | if (!p) return; |
mzta | 0:158c61bb030f | 271 | if (mrb->c->ci->eidx > i) |
mzta | 0:158c61bb030f | 272 | mrb->c->ci->eidx = i; |
mzta | 0:158c61bb030f | 273 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 274 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 275 | ci->mid = ci[-1].mid; |
mzta | 0:158c61bb030f | 276 | ci->acc = CI_ACC_SKIP; |
mzta | 0:158c61bb030f | 277 | ci->argc = 0; |
mzta | 0:158c61bb030f | 278 | ci->proc = p; |
mzta | 0:158c61bb030f | 279 | ci->nregs = p->body.irep->nregs; |
mzta | 0:158c61bb030f | 280 | ci->target_class = p->target_class; |
mzta | 0:158c61bb030f | 281 | mrb->c->stack = mrb->c->stack + ci[-1].nregs; |
mzta | 0:158c61bb030f | 282 | exc = mrb->exc; mrb->exc = 0; |
mzta | 0:158c61bb030f | 283 | mrb_run(mrb, p, *self); |
mzta | 0:158c61bb030f | 284 | mrb->c->ensure[i] = NULL; |
mzta | 0:158c61bb030f | 285 | if (!mrb->exc) mrb->exc = exc; |
mzta | 0:158c61bb030f | 286 | } |
mzta | 0:158c61bb030f | 287 | |
mzta | 0:158c61bb030f | 288 | #ifndef MRB_FUNCALL_ARGC_MAX |
mzta | 0:158c61bb030f | 289 | #define MRB_FUNCALL_ARGC_MAX 16 |
mzta | 0:158c61bb030f | 290 | #endif |
mzta | 0:158c61bb030f | 291 | |
mzta | 0:158c61bb030f | 292 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 293 | mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...) |
mzta | 0:158c61bb030f | 294 | { |
mzta | 0:158c61bb030f | 295 | mrb_value argv[MRB_FUNCALL_ARGC_MAX]; |
mzta | 0:158c61bb030f | 296 | va_list ap; |
mzta | 0:158c61bb030f | 297 | mrb_int i; |
mzta | 0:158c61bb030f | 298 | mrb_sym mid = mrb_intern_cstr(mrb, name); |
mzta | 0:158c61bb030f | 299 | |
mzta | 0:158c61bb030f | 300 | if (argc > MRB_FUNCALL_ARGC_MAX) { |
mzta | 0:158c61bb030f | 301 | mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")"); |
mzta | 0:158c61bb030f | 302 | } |
mzta | 0:158c61bb030f | 303 | |
mzta | 0:158c61bb030f | 304 | va_start(ap, argc); |
mzta | 0:158c61bb030f | 305 | for (i = 0; i < argc; i++) { |
mzta | 0:158c61bb030f | 306 | argv[i] = va_arg(ap, mrb_value); |
mzta | 0:158c61bb030f | 307 | } |
mzta | 0:158c61bb030f | 308 | va_end(ap); |
mzta | 0:158c61bb030f | 309 | return mrb_funcall_argv(mrb, self, mid, argc, argv); |
mzta | 0:158c61bb030f | 310 | } |
mzta | 0:158c61bb030f | 311 | |
mzta | 0:158c61bb030f | 312 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 313 | mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk) |
mzta | 0:158c61bb030f | 314 | { |
mzta | 0:158c61bb030f | 315 | mrb_value val; |
mzta | 0:158c61bb030f | 316 | |
mzta | 0:158c61bb030f | 317 | if (!mrb->jmp) { |
mzta | 0:158c61bb030f | 318 | struct mrb_jmpbuf c_jmp; |
mzta | 0:158c61bb030f | 319 | mrb_callinfo *old_ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 320 | |
mzta | 0:158c61bb030f | 321 | MRB_TRY(&c_jmp) { |
mzta | 0:158c61bb030f | 322 | mrb->jmp = &c_jmp; |
mzta | 0:158c61bb030f | 323 | /* recursive call */ |
mzta | 0:158c61bb030f | 324 | val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); |
mzta | 0:158c61bb030f | 325 | mrb->jmp = 0; |
mzta | 0:158c61bb030f | 326 | } |
mzta | 0:158c61bb030f | 327 | MRB_CATCH(&c_jmp) { /* error */ |
mzta | 0:158c61bb030f | 328 | while (old_ci != mrb->c->ci) { |
mzta | 0:158c61bb030f | 329 | mrb->c->stack = mrb->c->ci->stackent; |
mzta | 0:158c61bb030f | 330 | cipop(mrb); |
mzta | 0:158c61bb030f | 331 | } |
mzta | 0:158c61bb030f | 332 | mrb->jmp = 0; |
mzta | 0:158c61bb030f | 333 | val = mrb_obj_value(mrb->exc); |
mzta | 0:158c61bb030f | 334 | } |
mzta | 0:158c61bb030f | 335 | MRB_END_EXC(&c_jmp); |
mzta | 0:158c61bb030f | 336 | } |
mzta | 0:158c61bb030f | 337 | else { |
mzta | 0:158c61bb030f | 338 | struct RProc *p; |
mzta | 0:158c61bb030f | 339 | struct RClass *c; |
mzta | 0:158c61bb030f | 340 | mrb_sym undef = 0; |
mzta | 0:158c61bb030f | 341 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 342 | int n; |
mzta | 0:158c61bb030f | 343 | |
mzta | 0:158c61bb030f | 344 | if (!mrb->c->stack) { |
mzta | 0:158c61bb030f | 345 | stack_init(mrb); |
mzta | 0:158c61bb030f | 346 | } |
mzta | 0:158c61bb030f | 347 | n = mrb->c->ci->nregs; |
mzta | 0:158c61bb030f | 348 | if (argc < 0) { |
mzta | 0:158c61bb030f | 349 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc)); |
mzta | 0:158c61bb030f | 350 | } |
mzta | 0:158c61bb030f | 351 | c = mrb_class(mrb, self); |
mzta | 0:158c61bb030f | 352 | p = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 353 | if (!p) { |
mzta | 0:158c61bb030f | 354 | undef = mid; |
mzta | 0:158c61bb030f | 355 | mid = mrb_intern_lit(mrb, "method_missing"); |
mzta | 0:158c61bb030f | 356 | p = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 357 | n++; argc++; |
mzta | 0:158c61bb030f | 358 | } |
mzta | 0:158c61bb030f | 359 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 360 | ci->mid = mid; |
mzta | 0:158c61bb030f | 361 | ci->proc = p; |
mzta | 0:158c61bb030f | 362 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 363 | ci->argc = argc; |
mzta | 0:158c61bb030f | 364 | ci->target_class = c; |
mzta | 0:158c61bb030f | 365 | mrb->c->stack = mrb->c->stack + n; |
mzta | 0:158c61bb030f | 366 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 367 | ci->nregs = argc + 2; |
mzta | 0:158c61bb030f | 368 | stack_extend(mrb, ci->nregs, 0); |
mzta | 0:158c61bb030f | 369 | } |
mzta | 0:158c61bb030f | 370 | else { |
mzta | 0:158c61bb030f | 371 | ci->nregs = p->body.irep->nregs + n; |
mzta | 0:158c61bb030f | 372 | stack_extend(mrb, ci->nregs, argc+2); |
mzta | 0:158c61bb030f | 373 | } |
mzta | 0:158c61bb030f | 374 | mrb->c->stack[0] = self; |
mzta | 0:158c61bb030f | 375 | if (undef) { |
mzta | 0:158c61bb030f | 376 | mrb->c->stack[1] = mrb_symbol_value(undef); |
mzta | 0:158c61bb030f | 377 | if (argc > 1) { |
mzta | 0:158c61bb030f | 378 | stack_copy(mrb->c->stack+2, argv, argc-1); |
mzta | 0:158c61bb030f | 379 | } |
mzta | 0:158c61bb030f | 380 | } |
mzta | 0:158c61bb030f | 381 | else if (argc > 0) { |
mzta | 0:158c61bb030f | 382 | stack_copy(mrb->c->stack+1, argv, argc); |
mzta | 0:158c61bb030f | 383 | } |
mzta | 0:158c61bb030f | 384 | mrb->c->stack[argc+1] = blk; |
mzta | 0:158c61bb030f | 385 | |
mzta | 0:158c61bb030f | 386 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 387 | int ai = mrb_gc_arena_save(mrb); |
mzta | 0:158c61bb030f | 388 | |
mzta | 0:158c61bb030f | 389 | ci->acc = CI_ACC_DIRECT; |
mzta | 0:158c61bb030f | 390 | val = p->body.func(mrb, self); |
mzta | 0:158c61bb030f | 391 | mrb->c->stack = mrb->c->ci->stackent; |
mzta | 0:158c61bb030f | 392 | cipop(mrb); |
mzta | 0:158c61bb030f | 393 | mrb_gc_arena_restore(mrb, ai); |
mzta | 0:158c61bb030f | 394 | } |
mzta | 0:158c61bb030f | 395 | else { |
mzta | 0:158c61bb030f | 396 | ci->acc = CI_ACC_SKIP; |
mzta | 0:158c61bb030f | 397 | val = mrb_run(mrb, p, self); |
mzta | 0:158c61bb030f | 398 | } |
mzta | 0:158c61bb030f | 399 | } |
mzta | 0:158c61bb030f | 400 | mrb_gc_protect(mrb, val); |
mzta | 0:158c61bb030f | 401 | return val; |
mzta | 0:158c61bb030f | 402 | } |
mzta | 0:158c61bb030f | 403 | |
mzta | 0:158c61bb030f | 404 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 405 | mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv) |
mzta | 0:158c61bb030f | 406 | { |
mzta | 0:158c61bb030f | 407 | return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); |
mzta | 0:158c61bb030f | 408 | } |
mzta | 0:158c61bb030f | 409 | |
mzta | 0:158c61bb030f | 410 | /* 15.3.1.3.4 */ |
mzta | 0:158c61bb030f | 411 | /* 15.3.1.3.44 */ |
mzta | 0:158c61bb030f | 412 | /* |
mzta | 0:158c61bb030f | 413 | * call-seq: |
mzta | 0:158c61bb030f | 414 | * obj.send(symbol [, args...]) -> obj |
mzta | 0:158c61bb030f | 415 | * obj.__send__(symbol [, args...]) -> obj |
mzta | 0:158c61bb030f | 416 | * |
mzta | 0:158c61bb030f | 417 | * Invokes the method identified by _symbol_, passing it any |
mzta | 0:158c61bb030f | 418 | * arguments specified. You can use <code>__send__</code> if the name |
mzta | 0:158c61bb030f | 419 | * +send+ clashes with an existing method in _obj_. |
mzta | 0:158c61bb030f | 420 | * |
mzta | 0:158c61bb030f | 421 | * class Klass |
mzta | 0:158c61bb030f | 422 | * def hello(*args) |
mzta | 0:158c61bb030f | 423 | * "Hello " + args.join(' ') |
mzta | 0:158c61bb030f | 424 | * end |
mzta | 0:158c61bb030f | 425 | * end |
mzta | 0:158c61bb030f | 426 | * k = Klass.new |
mzta | 0:158c61bb030f | 427 | * k.send :hello, "gentle", "readers" #=> "Hello gentle readers" |
mzta | 0:158c61bb030f | 428 | */ |
mzta | 0:158c61bb030f | 429 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 430 | mrb_f_send(mrb_state *mrb, mrb_value self) |
mzta | 0:158c61bb030f | 431 | { |
mzta | 0:158c61bb030f | 432 | mrb_sym name; |
mzta | 0:158c61bb030f | 433 | mrb_value block, *argv, *regs; |
mzta | 0:158c61bb030f | 434 | mrb_int argc, i, len; |
mzta | 0:158c61bb030f | 435 | struct RProc *p; |
mzta | 0:158c61bb030f | 436 | struct RClass *c; |
mzta | 0:158c61bb030f | 437 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 438 | |
mzta | 0:158c61bb030f | 439 | mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block); |
mzta | 0:158c61bb030f | 440 | |
mzta | 0:158c61bb030f | 441 | c = mrb_class(mrb, self); |
mzta | 0:158c61bb030f | 442 | p = mrb_method_search_vm(mrb, &c, name); |
mzta | 0:158c61bb030f | 443 | |
mzta | 0:158c61bb030f | 444 | if (!p) { /* call method_mising */ |
mzta | 0:158c61bb030f | 445 | return mrb_funcall_with_block(mrb, self, name, argc, argv, block); |
mzta | 0:158c61bb030f | 446 | } |
mzta | 0:158c61bb030f | 447 | |
mzta | 0:158c61bb030f | 448 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 449 | ci->mid = name; |
mzta | 0:158c61bb030f | 450 | ci->target_class = c; |
mzta | 0:158c61bb030f | 451 | ci->proc = p; |
mzta | 0:158c61bb030f | 452 | regs = mrb->c->stack+1; |
mzta | 0:158c61bb030f | 453 | /* remove first symbol from arguments */ |
mzta | 0:158c61bb030f | 454 | if (ci->argc >= 0) { |
mzta | 0:158c61bb030f | 455 | for (i=0,len=ci->argc; i<len; i++) { |
mzta | 0:158c61bb030f | 456 | regs[i] = regs[i+1]; |
mzta | 0:158c61bb030f | 457 | } |
mzta | 0:158c61bb030f | 458 | ci->argc--; |
mzta | 0:158c61bb030f | 459 | } |
mzta | 0:158c61bb030f | 460 | else { /* variable length arguments */ |
mzta | 0:158c61bb030f | 461 | mrb_ary_shift(mrb, regs[0]); |
mzta | 0:158c61bb030f | 462 | } |
mzta | 0:158c61bb030f | 463 | |
mzta | 0:158c61bb030f | 464 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 465 | return p->body.func(mrb, self); |
mzta | 0:158c61bb030f | 466 | } |
mzta | 0:158c61bb030f | 467 | |
mzta | 0:158c61bb030f | 468 | ci->nregs = p->body.irep->nregs; |
mzta | 0:158c61bb030f | 469 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 470 | ci->nregs = 0; |
mzta | 0:158c61bb030f | 471 | ci->target_class = 0; |
mzta | 0:158c61bb030f | 472 | ci->pc = p->body.irep->iseq; |
mzta | 0:158c61bb030f | 473 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 474 | ci->acc = 0; |
mzta | 0:158c61bb030f | 475 | |
mzta | 0:158c61bb030f | 476 | return self; |
mzta | 0:158c61bb030f | 477 | } |
mzta | 0:158c61bb030f | 478 | |
mzta | 0:158c61bb030f | 479 | static mrb_value |
mzta | 0:158c61bb030f | 480 | eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) |
mzta | 0:158c61bb030f | 481 | { |
mzta | 0:158c61bb030f | 482 | struct RProc *p; |
mzta | 0:158c61bb030f | 483 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 484 | |
mzta | 0:158c61bb030f | 485 | if (mrb_nil_p(blk)) { |
mzta | 0:158c61bb030f | 486 | mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); |
mzta | 0:158c61bb030f | 487 | } |
mzta | 0:158c61bb030f | 488 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 489 | if (ci->acc == CI_ACC_DIRECT) { |
mzta | 0:158c61bb030f | 490 | return mrb_yield_with_class(mrb, blk, 0, 0, self, c); |
mzta | 0:158c61bb030f | 491 | } |
mzta | 0:158c61bb030f | 492 | ci->target_class = c; |
mzta | 0:158c61bb030f | 493 | p = mrb_proc_ptr(blk); |
mzta | 0:158c61bb030f | 494 | ci->proc = p; |
mzta | 0:158c61bb030f | 495 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 496 | return p->body.func(mrb, self); |
mzta | 0:158c61bb030f | 497 | } |
mzta | 0:158c61bb030f | 498 | ci->nregs = p->body.irep->nregs; |
mzta | 0:158c61bb030f | 499 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 500 | ci->nregs = 0; |
mzta | 0:158c61bb030f | 501 | ci->target_class = 0; |
mzta | 0:158c61bb030f | 502 | ci->pc = p->body.irep->iseq; |
mzta | 0:158c61bb030f | 503 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 504 | ci->acc = 0; |
mzta | 0:158c61bb030f | 505 | |
mzta | 0:158c61bb030f | 506 | return self; |
mzta | 0:158c61bb030f | 507 | } |
mzta | 0:158c61bb030f | 508 | |
mzta | 0:158c61bb030f | 509 | /* 15.2.2.4.35 */ |
mzta | 0:158c61bb030f | 510 | /* |
mzta | 0:158c61bb030f | 511 | * call-seq: |
mzta | 0:158c61bb030f | 512 | * mod.class_eval {| | block } -> obj |
mzta | 0:158c61bb030f | 513 | * mod.module_eval {| | block } -> obj |
mzta | 0:158c61bb030f | 514 | * |
mzta | 0:158c61bb030f | 515 | * Evaluates block in the context of _mod_. This can |
mzta | 0:158c61bb030f | 516 | * be used to add methods to a class. <code>module_eval</code> returns |
mzta | 0:158c61bb030f | 517 | * the result of evaluating its argument. |
mzta | 0:158c61bb030f | 518 | */ |
mzta | 0:158c61bb030f | 519 | mrb_value |
mzta | 0:158c61bb030f | 520 | mrb_mod_module_eval(mrb_state *mrb, mrb_value mod) |
mzta | 0:158c61bb030f | 521 | { |
mzta | 0:158c61bb030f | 522 | mrb_value a, b; |
mzta | 0:158c61bb030f | 523 | |
mzta | 0:158c61bb030f | 524 | if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { |
mzta | 0:158c61bb030f | 525 | mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented"); |
mzta | 0:158c61bb030f | 526 | } |
mzta | 0:158c61bb030f | 527 | return eval_under(mrb, mod, b, mrb_class_ptr(mod)); |
mzta | 0:158c61bb030f | 528 | } |
mzta | 0:158c61bb030f | 529 | |
mzta | 0:158c61bb030f | 530 | /* 15.3.1.3.18 */ |
mzta | 0:158c61bb030f | 531 | /* |
mzta | 0:158c61bb030f | 532 | * call-seq: |
mzta | 0:158c61bb030f | 533 | * obj.instance_eval {| | block } -> obj |
mzta | 0:158c61bb030f | 534 | * |
mzta | 0:158c61bb030f | 535 | * Evaluates the given block,within the context of the receiver (_obj_). |
mzta | 0:158c61bb030f | 536 | * In order to set the context, the variable +self+ is set to _obj_ while |
mzta | 0:158c61bb030f | 537 | * the code is executing, giving the code access to _obj_'s |
mzta | 0:158c61bb030f | 538 | * instance variables. In the version of <code>instance_eval</code> |
mzta | 0:158c61bb030f | 539 | * that takes a +String+, the optional second and third |
mzta | 0:158c61bb030f | 540 | * parameters supply a filename and starting line number that are used |
mzta | 0:158c61bb030f | 541 | * when reporting compilation errors. |
mzta | 0:158c61bb030f | 542 | * |
mzta | 0:158c61bb030f | 543 | * class KlassWithSecret |
mzta | 0:158c61bb030f | 544 | * def initialize |
mzta | 0:158c61bb030f | 545 | * @secret = 99 |
mzta | 0:158c61bb030f | 546 | * end |
mzta | 0:158c61bb030f | 547 | * end |
mzta | 0:158c61bb030f | 548 | * k = KlassWithSecret.new |
mzta | 0:158c61bb030f | 549 | * k.instance_eval { @secret } #=> 99 |
mzta | 0:158c61bb030f | 550 | */ |
mzta | 0:158c61bb030f | 551 | mrb_value |
mzta | 0:158c61bb030f | 552 | mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) |
mzta | 0:158c61bb030f | 553 | { |
mzta | 0:158c61bb030f | 554 | mrb_value a, b; |
mzta | 0:158c61bb030f | 555 | mrb_value cv; |
mzta | 0:158c61bb030f | 556 | struct RClass *c; |
mzta | 0:158c61bb030f | 557 | |
mzta | 0:158c61bb030f | 558 | if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { |
mzta | 0:158c61bb030f | 559 | mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); |
mzta | 0:158c61bb030f | 560 | } |
mzta | 0:158c61bb030f | 561 | switch (mrb_type(self)) { |
mzta | 0:158c61bb030f | 562 | case MRB_TT_SYMBOL: |
mzta | 0:158c61bb030f | 563 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 564 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 565 | c = 0; |
mzta | 0:158c61bb030f | 566 | break; |
mzta | 0:158c61bb030f | 567 | default: |
mzta | 0:158c61bb030f | 568 | cv = mrb_singleton_class(mrb, self); |
mzta | 0:158c61bb030f | 569 | c = mrb_class_ptr(cv); |
mzta | 0:158c61bb030f | 570 | break; |
mzta | 0:158c61bb030f | 571 | } |
mzta | 0:158c61bb030f | 572 | return eval_under(mrb, self, b, c); |
mzta | 0:158c61bb030f | 573 | } |
mzta | 0:158c61bb030f | 574 | |
mzta | 0:158c61bb030f | 575 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 576 | mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c) |
mzta | 0:158c61bb030f | 577 | { |
mzta | 0:158c61bb030f | 578 | struct RProc *p; |
mzta | 0:158c61bb030f | 579 | mrb_sym mid = mrb->c->ci->mid; |
mzta | 0:158c61bb030f | 580 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 581 | int n = mrb->c->ci->nregs; |
mzta | 0:158c61bb030f | 582 | mrb_value val; |
mzta | 0:158c61bb030f | 583 | |
mzta | 0:158c61bb030f | 584 | if (mrb_nil_p(b)) { |
mzta | 0:158c61bb030f | 585 | mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); |
mzta | 0:158c61bb030f | 586 | } |
mzta | 0:158c61bb030f | 587 | p = mrb_proc_ptr(b); |
mzta | 0:158c61bb030f | 588 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 589 | ci->mid = mid; |
mzta | 0:158c61bb030f | 590 | ci->proc = p; |
mzta | 0:158c61bb030f | 591 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 592 | ci->argc = argc; |
mzta | 0:158c61bb030f | 593 | ci->target_class = c; |
mzta | 0:158c61bb030f | 594 | ci->acc = CI_ACC_SKIP; |
mzta | 0:158c61bb030f | 595 | mrb->c->stack = mrb->c->stack + n; |
mzta | 0:158c61bb030f | 596 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 597 | ci->nregs = argc + 2; |
mzta | 0:158c61bb030f | 598 | stack_extend(mrb, ci->nregs, 0); |
mzta | 0:158c61bb030f | 599 | } |
mzta | 0:158c61bb030f | 600 | else { |
mzta | 0:158c61bb030f | 601 | ci->nregs = p->body.irep->nregs; |
mzta | 0:158c61bb030f | 602 | stack_extend(mrb, ci->nregs, argc+2); |
mzta | 0:158c61bb030f | 603 | } |
mzta | 0:158c61bb030f | 604 | |
mzta | 0:158c61bb030f | 605 | mrb->c->stack[0] = self; |
mzta | 0:158c61bb030f | 606 | if (argc > 0) { |
mzta | 0:158c61bb030f | 607 | stack_copy(mrb->c->stack+1, argv, argc); |
mzta | 0:158c61bb030f | 608 | } |
mzta | 0:158c61bb030f | 609 | mrb->c->stack[argc+1] = mrb_nil_value(); |
mzta | 0:158c61bb030f | 610 | |
mzta | 0:158c61bb030f | 611 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 612 | val = p->body.func(mrb, self); |
mzta | 0:158c61bb030f | 613 | mrb->c->stack = mrb->c->ci->stackent; |
mzta | 0:158c61bb030f | 614 | cipop(mrb); |
mzta | 0:158c61bb030f | 615 | } |
mzta | 0:158c61bb030f | 616 | else { |
mzta | 0:158c61bb030f | 617 | val = mrb_run(mrb, p, self); |
mzta | 0:158c61bb030f | 618 | } |
mzta | 0:158c61bb030f | 619 | return val; |
mzta | 0:158c61bb030f | 620 | } |
mzta | 0:158c61bb030f | 621 | |
mzta | 0:158c61bb030f | 622 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 623 | mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv) |
mzta | 0:158c61bb030f | 624 | { |
mzta | 0:158c61bb030f | 625 | struct RProc *p = mrb_proc_ptr(b); |
mzta | 0:158c61bb030f | 626 | |
mzta | 0:158c61bb030f | 627 | return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class); |
mzta | 0:158c61bb030f | 628 | } |
mzta | 0:158c61bb030f | 629 | |
mzta | 0:158c61bb030f | 630 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 631 | mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg) |
mzta | 0:158c61bb030f | 632 | { |
mzta | 0:158c61bb030f | 633 | struct RProc *p = mrb_proc_ptr(b); |
mzta | 0:158c61bb030f | 634 | |
mzta | 0:158c61bb030f | 635 | return mrb_yield_with_class(mrb, b, 1, &arg, p->env->stack[0], p->target_class); |
mzta | 0:158c61bb030f | 636 | } |
mzta | 0:158c61bb030f | 637 | |
mzta | 0:158c61bb030f | 638 | typedef enum { |
mzta | 0:158c61bb030f | 639 | LOCALJUMP_ERROR_RETURN = 0, |
mzta | 0:158c61bb030f | 640 | LOCALJUMP_ERROR_BREAK = 1, |
mzta | 0:158c61bb030f | 641 | LOCALJUMP_ERROR_YIELD = 2 |
mzta | 0:158c61bb030f | 642 | } localjump_error_kind; |
mzta | 0:158c61bb030f | 643 | |
mzta | 0:158c61bb030f | 644 | static void |
mzta | 0:158c61bb030f | 645 | localjump_error(mrb_state *mrb, localjump_error_kind kind) |
mzta | 0:158c61bb030f | 646 | { |
mzta | 0:158c61bb030f | 647 | char kind_str[3][7] = { "return", "break", "yield" }; |
mzta | 0:158c61bb030f | 648 | char kind_str_len[] = { 6, 5, 5 }; |
mzta | 0:158c61bb030f | 649 | static const char lead[] = "unexpected "; |
mzta | 0:158c61bb030f | 650 | mrb_value msg; |
mzta | 0:158c61bb030f | 651 | mrb_value exc; |
mzta | 0:158c61bb030f | 652 | |
mzta | 0:158c61bb030f | 653 | msg = mrb_str_buf_new(mrb, sizeof(lead) + 7); |
mzta | 0:158c61bb030f | 654 | mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1); |
mzta | 0:158c61bb030f | 655 | mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]); |
mzta | 0:158c61bb030f | 656 | exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); |
mzta | 0:158c61bb030f | 657 | mrb->exc = mrb_obj_ptr(exc); |
mzta | 0:158c61bb030f | 658 | } |
mzta | 0:158c61bb030f | 659 | |
mzta | 0:158c61bb030f | 660 | static void |
mzta | 0:158c61bb030f | 661 | argnum_error(mrb_state *mrb, mrb_int num) |
mzta | 0:158c61bb030f | 662 | { |
mzta | 0:158c61bb030f | 663 | mrb_value exc; |
mzta | 0:158c61bb030f | 664 | mrb_value str; |
mzta | 0:158c61bb030f | 665 | |
mzta | 0:158c61bb030f | 666 | if (mrb->c->ci->mid) { |
mzta | 0:158c61bb030f | 667 | str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)", |
mzta | 0:158c61bb030f | 668 | mrb_sym2str(mrb, mrb->c->ci->mid), |
mzta | 0:158c61bb030f | 669 | mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); |
mzta | 0:158c61bb030f | 670 | } |
mzta | 0:158c61bb030f | 671 | else { |
mzta | 0:158c61bb030f | 672 | str = mrb_format(mrb, "wrong number of arguments (%S for %S)", |
mzta | 0:158c61bb030f | 673 | mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); |
mzta | 0:158c61bb030f | 674 | } |
mzta | 0:158c61bb030f | 675 | exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str); |
mzta | 0:158c61bb030f | 676 | mrb->exc = mrb_obj_ptr(exc); |
mzta | 0:158c61bb030f | 677 | } |
mzta | 0:158c61bb030f | 678 | |
mzta | 0:158c61bb030f | 679 | #define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc; |
mzta | 0:158c61bb030f | 680 | #define ERR_PC_CLR(mrb) mrb->c->ci->err = 0; |
mzta | 0:158c61bb030f | 681 | #ifdef ENABLE_DEBUG |
mzta | 0:158c61bb030f | 682 | #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs)); |
mzta | 0:158c61bb030f | 683 | #else |
mzta | 0:158c61bb030f | 684 | #define CODE_FETCH_HOOK(mrb, irep, pc, regs) |
mzta | 0:158c61bb030f | 685 | #endif |
mzta | 0:158c61bb030f | 686 | |
mzta | 0:158c61bb030f | 687 | #if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER |
mzta | 0:158c61bb030f | 688 | #define DIRECT_THREADED |
mzta | 0:158c61bb030f | 689 | #endif |
mzta | 0:158c61bb030f | 690 | |
mzta | 0:158c61bb030f | 691 | #ifndef DIRECT_THREADED |
mzta | 0:158c61bb030f | 692 | |
mzta | 0:158c61bb030f | 693 | #define INIT_DISPATCH for (;;) { i = *pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) { |
mzta | 0:158c61bb030f | 694 | #define CASE(op) case op: |
mzta | 0:158c61bb030f | 695 | #define NEXT pc++; break |
mzta | 0:158c61bb030f | 696 | #define JUMP break |
mzta | 0:158c61bb030f | 697 | #define END_DISPATCH }} |
mzta | 0:158c61bb030f | 698 | |
mzta | 0:158c61bb030f | 699 | #else |
mzta | 0:158c61bb030f | 700 | |
mzta | 0:158c61bb030f | 701 | #define INIT_DISPATCH JUMP; return mrb_nil_value(); |
mzta | 0:158c61bb030f | 702 | #define CASE(op) L_ ## op: |
mzta | 0:158c61bb030f | 703 | #define NEXT i=*++pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] |
mzta | 0:158c61bb030f | 704 | #define JUMP i=*pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] |
mzta | 0:158c61bb030f | 705 | |
mzta | 0:158c61bb030f | 706 | #define END_DISPATCH |
mzta | 0:158c61bb030f | 707 | |
mzta | 0:158c61bb030f | 708 | #endif |
mzta | 0:158c61bb030f | 709 | |
mzta | 0:158c61bb030f | 710 | mrb_value mrb_gv_val_get(mrb_state *mrb, mrb_sym sym); |
mzta | 0:158c61bb030f | 711 | void mrb_gv_val_set(mrb_state *mrb, mrb_sym sym, mrb_value val); |
mzta | 0:158c61bb030f | 712 | |
mzta | 0:158c61bb030f | 713 | #define CALL_MAXARGS 127 |
mzta | 0:158c61bb030f | 714 | |
mzta | 0:158c61bb030f | 715 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 716 | mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) |
mzta | 0:158c61bb030f | 717 | { |
mzta | 0:158c61bb030f | 718 | /* mrb_assert(mrb_proc_cfunc_p(proc)) */ |
mzta | 0:158c61bb030f | 719 | mrb_irep *irep = proc->body.irep; |
mzta | 0:158c61bb030f | 720 | mrb_code *pc = irep->iseq; |
mzta | 0:158c61bb030f | 721 | mrb_value *pool = irep->pool; |
mzta | 0:158c61bb030f | 722 | mrb_sym *syms = irep->syms; |
mzta | 0:158c61bb030f | 723 | mrb_value *regs = NULL; |
mzta | 0:158c61bb030f | 724 | mrb_code i; |
mzta | 0:158c61bb030f | 725 | int ai = mrb_gc_arena_save(mrb); |
mzta | 0:158c61bb030f | 726 | struct mrb_jmpbuf *prev_jmp = mrb->jmp; |
mzta | 0:158c61bb030f | 727 | struct mrb_jmpbuf c_jmp; |
mzta | 0:158c61bb030f | 728 | |
mzta | 0:158c61bb030f | 729 | #ifdef DIRECT_THREADED |
mzta | 0:158c61bb030f | 730 | static void *optable[] = { |
mzta | 0:158c61bb030f | 731 | &&L_OP_NOP, &&L_OP_MOVE, |
mzta | 0:158c61bb030f | 732 | &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL, |
mzta | 0:158c61bb030f | 733 | &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF, |
mzta | 0:158c61bb030f | 734 | &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL, |
mzta | 0:158c61bb030f | 735 | &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV, |
mzta | 0:158c61bb030f | 736 | &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST, |
mzta | 0:158c61bb030f | 737 | &&L_OP_GETUPVAR, &&L_OP_SETUPVAR, |
mzta | 0:158c61bb030f | 738 | &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT, |
mzta | 0:158c61bb030f | 739 | &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP, |
mzta | 0:158c61bb030f | 740 | &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND, |
mzta | 0:158c61bb030f | 741 | &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER, |
mzta | 0:158c61bb030f | 742 | &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH, |
mzta | 0:158c61bb030f | 743 | &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV, |
mzta | 0:158c61bb030f | 744 | &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE, |
mzta | 0:158c61bb030f | 745 | &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST, |
mzta | 0:158c61bb030f | 746 | &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH, |
mzta | 0:158c61bb030f | 747 | &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS, |
mzta | 0:158c61bb030f | 748 | &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC, |
mzta | 0:158c61bb030f | 749 | &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS, |
mzta | 0:158c61bb030f | 750 | &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR, |
mzta | 0:158c61bb030f | 751 | }; |
mzta | 0:158c61bb030f | 752 | #endif |
mzta | 0:158c61bb030f | 753 | |
mzta | 0:158c61bb030f | 754 | mrb_bool exc_catched = FALSE; |
mzta | 0:158c61bb030f | 755 | RETRY_TRY_BLOCK: |
mzta | 0:158c61bb030f | 756 | |
mzta | 0:158c61bb030f | 757 | MRB_TRY(&c_jmp) { |
mzta | 0:158c61bb030f | 758 | |
mzta | 0:158c61bb030f | 759 | if (exc_catched) { |
mzta | 0:158c61bb030f | 760 | exc_catched = FALSE; |
mzta | 0:158c61bb030f | 761 | goto L_RAISE; |
mzta | 0:158c61bb030f | 762 | } |
mzta | 0:158c61bb030f | 763 | mrb->jmp = &c_jmp; |
mzta | 0:158c61bb030f | 764 | if (!mrb->c->stack) { |
mzta | 0:158c61bb030f | 765 | stack_init(mrb); |
mzta | 0:158c61bb030f | 766 | } |
mzta | 0:158c61bb030f | 767 | stack_extend(mrb, irep->nregs, stack_keep); |
mzta | 0:158c61bb030f | 768 | mrb->c->ci->proc = proc; |
mzta | 0:158c61bb030f | 769 | mrb->c->ci->nregs = irep->nregs; |
mzta | 0:158c61bb030f | 770 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 771 | regs[0] = self; |
mzta | 0:158c61bb030f | 772 | |
mzta | 0:158c61bb030f | 773 | INIT_DISPATCH { |
mzta | 0:158c61bb030f | 774 | CASE(OP_NOP) { |
mzta | 0:158c61bb030f | 775 | /* do nothing */ |
mzta | 0:158c61bb030f | 776 | NEXT; |
mzta | 0:158c61bb030f | 777 | } |
mzta | 0:158c61bb030f | 778 | |
mzta | 0:158c61bb030f | 779 | CASE(OP_MOVE) { |
mzta | 0:158c61bb030f | 780 | /* A B R(A) := R(B) */ |
mzta | 0:158c61bb030f | 781 | regs[GETARG_A(i)] = regs[GETARG_B(i)]; |
mzta | 0:158c61bb030f | 782 | NEXT; |
mzta | 0:158c61bb030f | 783 | } |
mzta | 0:158c61bb030f | 784 | |
mzta | 0:158c61bb030f | 785 | CASE(OP_LOADL) { |
mzta | 0:158c61bb030f | 786 | /* A Bx R(A) := Pool(Bx) */ |
mzta | 0:158c61bb030f | 787 | regs[GETARG_A(i)] = pool[GETARG_Bx(i)]; |
mzta | 0:158c61bb030f | 788 | NEXT; |
mzta | 0:158c61bb030f | 789 | } |
mzta | 0:158c61bb030f | 790 | |
mzta | 0:158c61bb030f | 791 | CASE(OP_LOADI) { |
mzta | 0:158c61bb030f | 792 | /* A sBx R(A) := sBx */ |
mzta | 0:158c61bb030f | 793 | SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i)); |
mzta | 0:158c61bb030f | 794 | NEXT; |
mzta | 0:158c61bb030f | 795 | } |
mzta | 0:158c61bb030f | 796 | |
mzta | 0:158c61bb030f | 797 | CASE(OP_LOADSYM) { |
mzta | 0:158c61bb030f | 798 | /* A Bx R(A) := Syms(Bx) */ |
mzta | 0:158c61bb030f | 799 | SET_SYM_VALUE(regs[GETARG_A(i)], syms[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 800 | NEXT; |
mzta | 0:158c61bb030f | 801 | } |
mzta | 0:158c61bb030f | 802 | |
mzta | 0:158c61bb030f | 803 | CASE(OP_LOADSELF) { |
mzta | 0:158c61bb030f | 804 | /* A R(A) := self */ |
mzta | 0:158c61bb030f | 805 | regs[GETARG_A(i)] = regs[0]; |
mzta | 0:158c61bb030f | 806 | NEXT; |
mzta | 0:158c61bb030f | 807 | } |
mzta | 0:158c61bb030f | 808 | |
mzta | 0:158c61bb030f | 809 | CASE(OP_LOADT) { |
mzta | 0:158c61bb030f | 810 | /* A R(A) := true */ |
mzta | 0:158c61bb030f | 811 | SET_TRUE_VALUE(regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 812 | NEXT; |
mzta | 0:158c61bb030f | 813 | } |
mzta | 0:158c61bb030f | 814 | |
mzta | 0:158c61bb030f | 815 | CASE(OP_LOADF) { |
mzta | 0:158c61bb030f | 816 | /* A R(A) := false */ |
mzta | 0:158c61bb030f | 817 | SET_FALSE_VALUE(regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 818 | NEXT; |
mzta | 0:158c61bb030f | 819 | } |
mzta | 0:158c61bb030f | 820 | |
mzta | 0:158c61bb030f | 821 | CASE(OP_GETGLOBAL) { |
mzta | 0:158c61bb030f | 822 | /* A Bx R(A) := getglobal(Syms(Bx)) */ |
mzta | 0:158c61bb030f | 823 | regs[GETARG_A(i)] = mrb_gv_get(mrb, syms[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 824 | NEXT; |
mzta | 0:158c61bb030f | 825 | } |
mzta | 0:158c61bb030f | 826 | |
mzta | 0:158c61bb030f | 827 | CASE(OP_SETGLOBAL) { |
mzta | 0:158c61bb030f | 828 | /* setglobal(Syms(Bx), R(A)) */ |
mzta | 0:158c61bb030f | 829 | mrb_gv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 830 | NEXT; |
mzta | 0:158c61bb030f | 831 | } |
mzta | 0:158c61bb030f | 832 | |
mzta | 0:158c61bb030f | 833 | CASE(OP_GETSPECIAL) { |
mzta | 0:158c61bb030f | 834 | /* A Bx R(A) := Special[Bx] */ |
mzta | 0:158c61bb030f | 835 | regs[GETARG_A(i)] = mrb_vm_special_get(mrb, GETARG_Bx(i)); |
mzta | 0:158c61bb030f | 836 | NEXT; |
mzta | 0:158c61bb030f | 837 | } |
mzta | 0:158c61bb030f | 838 | |
mzta | 0:158c61bb030f | 839 | CASE(OP_SETSPECIAL) { |
mzta | 0:158c61bb030f | 840 | /* A Bx Special[Bx] := R(A) */ |
mzta | 0:158c61bb030f | 841 | mrb_vm_special_set(mrb, GETARG_Bx(i), regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 842 | NEXT; |
mzta | 0:158c61bb030f | 843 | } |
mzta | 0:158c61bb030f | 844 | |
mzta | 0:158c61bb030f | 845 | CASE(OP_GETIV) { |
mzta | 0:158c61bb030f | 846 | /* A Bx R(A) := ivget(Bx) */ |
mzta | 0:158c61bb030f | 847 | regs[GETARG_A(i)] = mrb_vm_iv_get(mrb, syms[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 848 | NEXT; |
mzta | 0:158c61bb030f | 849 | } |
mzta | 0:158c61bb030f | 850 | |
mzta | 0:158c61bb030f | 851 | CASE(OP_SETIV) { |
mzta | 0:158c61bb030f | 852 | /* ivset(Syms(Bx),R(A)) */ |
mzta | 0:158c61bb030f | 853 | mrb_vm_iv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 854 | NEXT; |
mzta | 0:158c61bb030f | 855 | } |
mzta | 0:158c61bb030f | 856 | |
mzta | 0:158c61bb030f | 857 | CASE(OP_GETCV) { |
mzta | 0:158c61bb030f | 858 | /* A Bx R(A) := cvget(Syms(Bx)) */ |
mzta | 0:158c61bb030f | 859 | ERR_PC_SET(mrb, pc); |
mzta | 0:158c61bb030f | 860 | regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 861 | ERR_PC_CLR(mrb); |
mzta | 0:158c61bb030f | 862 | NEXT; |
mzta | 0:158c61bb030f | 863 | } |
mzta | 0:158c61bb030f | 864 | |
mzta | 0:158c61bb030f | 865 | CASE(OP_SETCV) { |
mzta | 0:158c61bb030f | 866 | /* cvset(Syms(Bx),R(A)) */ |
mzta | 0:158c61bb030f | 867 | mrb_vm_cv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 868 | NEXT; |
mzta | 0:158c61bb030f | 869 | } |
mzta | 0:158c61bb030f | 870 | |
mzta | 0:158c61bb030f | 871 | CASE(OP_GETCONST) { |
mzta | 0:158c61bb030f | 872 | /* A Bx R(A) := constget(Syms(Bx)) */ |
mzta | 0:158c61bb030f | 873 | mrb_value val; |
mzta | 0:158c61bb030f | 874 | |
mzta | 0:158c61bb030f | 875 | ERR_PC_SET(mrb, pc); |
mzta | 0:158c61bb030f | 876 | val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 877 | ERR_PC_CLR(mrb); |
mzta | 0:158c61bb030f | 878 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 879 | regs[GETARG_A(i)] = val; |
mzta | 0:158c61bb030f | 880 | NEXT; |
mzta | 0:158c61bb030f | 881 | } |
mzta | 0:158c61bb030f | 882 | |
mzta | 0:158c61bb030f | 883 | CASE(OP_SETCONST) { |
mzta | 0:158c61bb030f | 884 | /* A Bx constset(Syms(Bx),R(A)) */ |
mzta | 0:158c61bb030f | 885 | mrb_vm_const_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 886 | NEXT; |
mzta | 0:158c61bb030f | 887 | } |
mzta | 0:158c61bb030f | 888 | |
mzta | 0:158c61bb030f | 889 | CASE(OP_GETMCNST) { |
mzta | 0:158c61bb030f | 890 | /* A Bx R(A) := R(A)::Syms(Bx) */ |
mzta | 0:158c61bb030f | 891 | mrb_value val; |
mzta | 0:158c61bb030f | 892 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 893 | |
mzta | 0:158c61bb030f | 894 | ERR_PC_SET(mrb, pc); |
mzta | 0:158c61bb030f | 895 | val = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 896 | ERR_PC_CLR(mrb); |
mzta | 0:158c61bb030f | 897 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 898 | regs[a] = val; |
mzta | 0:158c61bb030f | 899 | NEXT; |
mzta | 0:158c61bb030f | 900 | } |
mzta | 0:158c61bb030f | 901 | |
mzta | 0:158c61bb030f | 902 | CASE(OP_SETMCNST) { |
mzta | 0:158c61bb030f | 903 | /* A Bx R(A+1)::Syms(Bx) := R(A) */ |
mzta | 0:158c61bb030f | 904 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 905 | |
mzta | 0:158c61bb030f | 906 | mrb_const_set(mrb, regs[a+1], syms[GETARG_Bx(i)], regs[a]); |
mzta | 0:158c61bb030f | 907 | NEXT; |
mzta | 0:158c61bb030f | 908 | } |
mzta | 0:158c61bb030f | 909 | |
mzta | 0:158c61bb030f | 910 | CASE(OP_GETUPVAR) { |
mzta | 0:158c61bb030f | 911 | /* A B C R(A) := uvget(B,C) */ |
mzta | 0:158c61bb030f | 912 | mrb_value *regs_a = regs + GETARG_A(i); |
mzta | 0:158c61bb030f | 913 | int up = GETARG_C(i); |
mzta | 0:158c61bb030f | 914 | |
mzta | 0:158c61bb030f | 915 | struct REnv *e = uvenv(mrb, up); |
mzta | 0:158c61bb030f | 916 | |
mzta | 0:158c61bb030f | 917 | if (!e) { |
mzta | 0:158c61bb030f | 918 | *regs_a = mrb_nil_value(); |
mzta | 0:158c61bb030f | 919 | } |
mzta | 0:158c61bb030f | 920 | else { |
mzta | 0:158c61bb030f | 921 | int idx = GETARG_B(i); |
mzta | 0:158c61bb030f | 922 | *regs_a = e->stack[idx]; |
mzta | 0:158c61bb030f | 923 | } |
mzta | 0:158c61bb030f | 924 | NEXT; |
mzta | 0:158c61bb030f | 925 | } |
mzta | 0:158c61bb030f | 926 | |
mzta | 0:158c61bb030f | 927 | CASE(OP_SETUPVAR) { |
mzta | 0:158c61bb030f | 928 | /* A B C uvset(B,C,R(A)) */ |
mzta | 0:158c61bb030f | 929 | int up = GETARG_C(i); |
mzta | 0:158c61bb030f | 930 | |
mzta | 0:158c61bb030f | 931 | struct REnv *e = uvenv(mrb, up); |
mzta | 0:158c61bb030f | 932 | |
mzta | 0:158c61bb030f | 933 | if (e) { |
mzta | 0:158c61bb030f | 934 | mrb_value *regs_a = regs + GETARG_A(i); |
mzta | 0:158c61bb030f | 935 | int idx = GETARG_B(i); |
mzta | 0:158c61bb030f | 936 | e->stack[idx] = *regs_a; |
mzta | 0:158c61bb030f | 937 | mrb_write_barrier(mrb, (struct RBasic*)e); |
mzta | 0:158c61bb030f | 938 | } |
mzta | 0:158c61bb030f | 939 | NEXT; |
mzta | 0:158c61bb030f | 940 | } |
mzta | 0:158c61bb030f | 941 | |
mzta | 0:158c61bb030f | 942 | CASE(OP_JMP) { |
mzta | 0:158c61bb030f | 943 | /* sBx pc+=sBx */ |
mzta | 0:158c61bb030f | 944 | pc += GETARG_sBx(i); |
mzta | 0:158c61bb030f | 945 | JUMP; |
mzta | 0:158c61bb030f | 946 | } |
mzta | 0:158c61bb030f | 947 | |
mzta | 0:158c61bb030f | 948 | CASE(OP_JMPIF) { |
mzta | 0:158c61bb030f | 949 | /* A sBx if R(A) pc+=sBx */ |
mzta | 0:158c61bb030f | 950 | if (mrb_test(regs[GETARG_A(i)])) { |
mzta | 0:158c61bb030f | 951 | pc += GETARG_sBx(i); |
mzta | 0:158c61bb030f | 952 | JUMP; |
mzta | 0:158c61bb030f | 953 | } |
mzta | 0:158c61bb030f | 954 | NEXT; |
mzta | 0:158c61bb030f | 955 | } |
mzta | 0:158c61bb030f | 956 | |
mzta | 0:158c61bb030f | 957 | CASE(OP_JMPNOT) { |
mzta | 0:158c61bb030f | 958 | /* A sBx if !R(A) pc+=sBx */ |
mzta | 0:158c61bb030f | 959 | if (!mrb_test(regs[GETARG_A(i)])) { |
mzta | 0:158c61bb030f | 960 | pc += GETARG_sBx(i); |
mzta | 0:158c61bb030f | 961 | JUMP; |
mzta | 0:158c61bb030f | 962 | } |
mzta | 0:158c61bb030f | 963 | NEXT; |
mzta | 0:158c61bb030f | 964 | } |
mzta | 0:158c61bb030f | 965 | |
mzta | 0:158c61bb030f | 966 | CASE(OP_ONERR) { |
mzta | 0:158c61bb030f | 967 | /* sBx pc+=sBx on exception */ |
mzta | 0:158c61bb030f | 968 | if (mrb->c->rsize <= mrb->c->ci->ridx) { |
mzta | 0:158c61bb030f | 969 | if (mrb->c->rsize == 0) mrb->c->rsize = 16; |
mzta | 0:158c61bb030f | 970 | else mrb->c->rsize *= 2; |
mzta | 0:158c61bb030f | 971 | mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize); |
mzta | 0:158c61bb030f | 972 | } |
mzta | 0:158c61bb030f | 973 | mrb->c->rescue[mrb->c->ci->ridx++] = pc + GETARG_sBx(i); |
mzta | 0:158c61bb030f | 974 | NEXT; |
mzta | 0:158c61bb030f | 975 | } |
mzta | 0:158c61bb030f | 976 | |
mzta | 0:158c61bb030f | 977 | CASE(OP_RESCUE) { |
mzta | 0:158c61bb030f | 978 | /* A R(A) := exc; clear(exc) */ |
mzta | 0:158c61bb030f | 979 | SET_OBJ_VALUE(regs[GETARG_A(i)], mrb->exc); |
mzta | 0:158c61bb030f | 980 | mrb->exc = 0; |
mzta | 0:158c61bb030f | 981 | NEXT; |
mzta | 0:158c61bb030f | 982 | } |
mzta | 0:158c61bb030f | 983 | |
mzta | 0:158c61bb030f | 984 | CASE(OP_POPERR) { |
mzta | 0:158c61bb030f | 985 | /* A A.times{rescue_pop()} */ |
mzta | 0:158c61bb030f | 986 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 987 | |
mzta | 0:158c61bb030f | 988 | while (a--) { |
mzta | 0:158c61bb030f | 989 | mrb->c->ci->ridx--; |
mzta | 0:158c61bb030f | 990 | } |
mzta | 0:158c61bb030f | 991 | NEXT; |
mzta | 0:158c61bb030f | 992 | } |
mzta | 0:158c61bb030f | 993 | |
mzta | 0:158c61bb030f | 994 | CASE(OP_RAISE) { |
mzta | 0:158c61bb030f | 995 | /* A raise(R(A)) */ |
mzta | 0:158c61bb030f | 996 | mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 997 | goto L_RAISE; |
mzta | 0:158c61bb030f | 998 | } |
mzta | 0:158c61bb030f | 999 | |
mzta | 0:158c61bb030f | 1000 | CASE(OP_EPUSH) { |
mzta | 0:158c61bb030f | 1001 | /* Bx ensure_push(SEQ[Bx]) */ |
mzta | 0:158c61bb030f | 1002 | struct RProc *p; |
mzta | 0:158c61bb030f | 1003 | |
mzta | 0:158c61bb030f | 1004 | p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 1005 | /* push ensure_stack */ |
mzta | 0:158c61bb030f | 1006 | if (mrb->c->esize <= mrb->c->ci->eidx) { |
mzta | 0:158c61bb030f | 1007 | if (mrb->c->esize == 0) mrb->c->esize = 16; |
mzta | 0:158c61bb030f | 1008 | else mrb->c->esize *= 2; |
mzta | 0:158c61bb030f | 1009 | mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize); |
mzta | 0:158c61bb030f | 1010 | } |
mzta | 0:158c61bb030f | 1011 | mrb->c->ensure[mrb->c->ci->eidx++] = p; |
mzta | 0:158c61bb030f | 1012 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 1013 | NEXT; |
mzta | 0:158c61bb030f | 1014 | } |
mzta | 0:158c61bb030f | 1015 | |
mzta | 0:158c61bb030f | 1016 | CASE(OP_EPOP) { |
mzta | 0:158c61bb030f | 1017 | /* A A.times{ensure_pop().call} */ |
mzta | 0:158c61bb030f | 1018 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1019 | mrb_callinfo *ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1020 | int n, eidx = ci->eidx; |
mzta | 0:158c61bb030f | 1021 | |
mzta | 0:158c61bb030f | 1022 | for (n=0; n<a && eidx > ci[-1].eidx; n++) { |
mzta | 0:158c61bb030f | 1023 | ecall(mrb, --eidx); |
mzta | 0:158c61bb030f | 1024 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 1025 | } |
mzta | 0:158c61bb030f | 1026 | NEXT; |
mzta | 0:158c61bb030f | 1027 | } |
mzta | 0:158c61bb030f | 1028 | |
mzta | 0:158c61bb030f | 1029 | CASE(OP_LOADNIL) { |
mzta | 0:158c61bb030f | 1030 | /* A R(A) := nil */ |
mzta | 0:158c61bb030f | 1031 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1032 | |
mzta | 0:158c61bb030f | 1033 | SET_NIL_VALUE(regs[a]); |
mzta | 0:158c61bb030f | 1034 | NEXT; |
mzta | 0:158c61bb030f | 1035 | } |
mzta | 0:158c61bb030f | 1036 | |
mzta | 0:158c61bb030f | 1037 | CASE(OP_SENDB) { |
mzta | 0:158c61bb030f | 1038 | /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/ |
mzta | 0:158c61bb030f | 1039 | /* fall through */ |
mzta | 0:158c61bb030f | 1040 | }; |
mzta | 0:158c61bb030f | 1041 | |
mzta | 0:158c61bb030f | 1042 | L_SEND: |
mzta | 0:158c61bb030f | 1043 | CASE(OP_SEND) { |
mzta | 0:158c61bb030f | 1044 | /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */ |
mzta | 0:158c61bb030f | 1045 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1046 | int n = GETARG_C(i); |
mzta | 0:158c61bb030f | 1047 | struct RProc *m; |
mzta | 0:158c61bb030f | 1048 | struct RClass *c; |
mzta | 0:158c61bb030f | 1049 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 1050 | mrb_value recv, result; |
mzta | 0:158c61bb030f | 1051 | mrb_sym mid = syms[GETARG_B(i)]; |
mzta | 0:158c61bb030f | 1052 | |
mzta | 0:158c61bb030f | 1053 | recv = regs[a]; |
mzta | 0:158c61bb030f | 1054 | if (GET_OPCODE(i) != OP_SENDB) { |
mzta | 0:158c61bb030f | 1055 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1056 | SET_NIL_VALUE(regs[a+2]); |
mzta | 0:158c61bb030f | 1057 | } |
mzta | 0:158c61bb030f | 1058 | else { |
mzta | 0:158c61bb030f | 1059 | SET_NIL_VALUE(regs[a+n+1]); |
mzta | 0:158c61bb030f | 1060 | } |
mzta | 0:158c61bb030f | 1061 | } |
mzta | 0:158c61bb030f | 1062 | c = mrb_class(mrb, recv); |
mzta | 0:158c61bb030f | 1063 | m = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 1064 | if (!m) { |
mzta | 0:158c61bb030f | 1065 | mrb_value sym = mrb_symbol_value(mid); |
mzta | 0:158c61bb030f | 1066 | |
mzta | 0:158c61bb030f | 1067 | mid = mrb_intern_lit(mrb, "method_missing"); |
mzta | 0:158c61bb030f | 1068 | m = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 1069 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1070 | mrb_ary_unshift(mrb, regs[a+1], sym); |
mzta | 0:158c61bb030f | 1071 | } |
mzta | 0:158c61bb030f | 1072 | else { |
mzta | 0:158c61bb030f | 1073 | value_move(regs+a+2, regs+a+1, ++n); |
mzta | 0:158c61bb030f | 1074 | regs[a+1] = sym; |
mzta | 0:158c61bb030f | 1075 | } |
mzta | 0:158c61bb030f | 1076 | } |
mzta | 0:158c61bb030f | 1077 | |
mzta | 0:158c61bb030f | 1078 | /* push callinfo */ |
mzta | 0:158c61bb030f | 1079 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 1080 | ci->mid = mid; |
mzta | 0:158c61bb030f | 1081 | ci->proc = m; |
mzta | 0:158c61bb030f | 1082 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 1083 | if (c->tt == MRB_TT_ICLASS) { |
mzta | 0:158c61bb030f | 1084 | ci->target_class = c->c; |
mzta | 0:158c61bb030f | 1085 | } |
mzta | 0:158c61bb030f | 1086 | else { |
mzta | 0:158c61bb030f | 1087 | ci->target_class = c; |
mzta | 0:158c61bb030f | 1088 | } |
mzta | 0:158c61bb030f | 1089 | |
mzta | 0:158c61bb030f | 1090 | ci->pc = pc + 1; |
mzta | 0:158c61bb030f | 1091 | ci->acc = a; |
mzta | 0:158c61bb030f | 1092 | |
mzta | 0:158c61bb030f | 1093 | /* prepare stack */ |
mzta | 0:158c61bb030f | 1094 | mrb->c->stack += a; |
mzta | 0:158c61bb030f | 1095 | |
mzta | 0:158c61bb030f | 1096 | if (MRB_PROC_CFUNC_P(m)) { |
mzta | 0:158c61bb030f | 1097 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1098 | ci->argc = -1; |
mzta | 0:158c61bb030f | 1099 | ci->nregs = 3; |
mzta | 0:158c61bb030f | 1100 | } |
mzta | 0:158c61bb030f | 1101 | else { |
mzta | 0:158c61bb030f | 1102 | ci->argc = n; |
mzta | 0:158c61bb030f | 1103 | ci->nregs = n + 2; |
mzta | 0:158c61bb030f | 1104 | } |
mzta | 0:158c61bb030f | 1105 | result = m->body.func(mrb, recv); |
mzta | 0:158c61bb030f | 1106 | mrb->c->stack[0] = result; |
mzta | 0:158c61bb030f | 1107 | mrb_gc_arena_restore(mrb, ai); |
mzta | 0:158c61bb030f | 1108 | if (mrb->exc) goto L_RAISE; |
mzta | 0:158c61bb030f | 1109 | /* pop stackpos */ |
mzta | 0:158c61bb030f | 1110 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1111 | if (!ci->target_class) { /* return from context modifying method (resume/yield) */ |
mzta | 0:158c61bb030f | 1112 | if (!MRB_PROC_CFUNC_P(ci[-1].proc)) { |
mzta | 0:158c61bb030f | 1113 | proc = ci[-1].proc; |
mzta | 0:158c61bb030f | 1114 | irep = proc->body.irep; |
mzta | 0:158c61bb030f | 1115 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1116 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1117 | } |
mzta | 0:158c61bb030f | 1118 | } |
mzta | 0:158c61bb030f | 1119 | regs = mrb->c->stack = ci->stackent; |
mzta | 0:158c61bb030f | 1120 | pc = ci->pc; |
mzta | 0:158c61bb030f | 1121 | cipop(mrb); |
mzta | 0:158c61bb030f | 1122 | JUMP; |
mzta | 0:158c61bb030f | 1123 | } |
mzta | 0:158c61bb030f | 1124 | else { |
mzta | 0:158c61bb030f | 1125 | /* setup environment for calling method */ |
mzta | 0:158c61bb030f | 1126 | proc = mrb->c->ci->proc = m; |
mzta | 0:158c61bb030f | 1127 | irep = m->body.irep; |
mzta | 0:158c61bb030f | 1128 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1129 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1130 | ci->nregs = irep->nregs; |
mzta | 0:158c61bb030f | 1131 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1132 | ci->argc = -1; |
mzta | 0:158c61bb030f | 1133 | stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); |
mzta | 0:158c61bb030f | 1134 | } |
mzta | 0:158c61bb030f | 1135 | else { |
mzta | 0:158c61bb030f | 1136 | ci->argc = n; |
mzta | 0:158c61bb030f | 1137 | stack_extend(mrb, irep->nregs, n+2); |
mzta | 0:158c61bb030f | 1138 | } |
mzta | 0:158c61bb030f | 1139 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 1140 | pc = irep->iseq; |
mzta | 0:158c61bb030f | 1141 | JUMP; |
mzta | 0:158c61bb030f | 1142 | } |
mzta | 0:158c61bb030f | 1143 | } |
mzta | 0:158c61bb030f | 1144 | |
mzta | 0:158c61bb030f | 1145 | CASE(OP_FSEND) { |
mzta | 0:158c61bb030f | 1146 | /* A B C R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */ |
mzta | 0:158c61bb030f | 1147 | NEXT; |
mzta | 0:158c61bb030f | 1148 | } |
mzta | 0:158c61bb030f | 1149 | |
mzta | 0:158c61bb030f | 1150 | CASE(OP_CALL) { |
mzta | 0:158c61bb030f | 1151 | /* A R(A) := self.call(frame.argc, frame.argv) */ |
mzta | 0:158c61bb030f | 1152 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 1153 | mrb_value recv = mrb->c->stack[0]; |
mzta | 0:158c61bb030f | 1154 | struct RProc *m = mrb_proc_ptr(recv); |
mzta | 0:158c61bb030f | 1155 | |
mzta | 0:158c61bb030f | 1156 | /* replace callinfo */ |
mzta | 0:158c61bb030f | 1157 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1158 | ci->target_class = m->target_class; |
mzta | 0:158c61bb030f | 1159 | ci->proc = m; |
mzta | 0:158c61bb030f | 1160 | if (m->env) { |
mzta | 0:158c61bb030f | 1161 | if (m->env->mid) { |
mzta | 0:158c61bb030f | 1162 | ci->mid = m->env->mid; |
mzta | 0:158c61bb030f | 1163 | } |
mzta | 0:158c61bb030f | 1164 | if (!m->env->stack) { |
mzta | 0:158c61bb030f | 1165 | m->env->stack = mrb->c->stack; |
mzta | 0:158c61bb030f | 1166 | } |
mzta | 0:158c61bb030f | 1167 | } |
mzta | 0:158c61bb030f | 1168 | |
mzta | 0:158c61bb030f | 1169 | /* prepare stack */ |
mzta | 0:158c61bb030f | 1170 | if (MRB_PROC_CFUNC_P(m)) { |
mzta | 0:158c61bb030f | 1171 | recv = m->body.func(mrb, recv); |
mzta | 0:158c61bb030f | 1172 | mrb_gc_arena_restore(mrb, ai); |
mzta | 0:158c61bb030f | 1173 | if (mrb->exc) goto L_RAISE; |
mzta | 0:158c61bb030f | 1174 | /* pop stackpos */ |
mzta | 0:158c61bb030f | 1175 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1176 | regs = mrb->c->stack = ci->stackent; |
mzta | 0:158c61bb030f | 1177 | regs[ci->acc] = recv; |
mzta | 0:158c61bb030f | 1178 | pc = ci->pc; |
mzta | 0:158c61bb030f | 1179 | cipop(mrb); |
mzta | 0:158c61bb030f | 1180 | irep = mrb->c->ci->proc->body.irep; |
mzta | 0:158c61bb030f | 1181 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1182 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1183 | JUMP; |
mzta | 0:158c61bb030f | 1184 | } |
mzta | 0:158c61bb030f | 1185 | else { |
mzta | 0:158c61bb030f | 1186 | /* setup environment for calling method */ |
mzta | 0:158c61bb030f | 1187 | proc = m; |
mzta | 0:158c61bb030f | 1188 | irep = m->body.irep; |
mzta | 0:158c61bb030f | 1189 | if (!irep) { |
mzta | 0:158c61bb030f | 1190 | mrb->c->stack[0] = mrb_nil_value(); |
mzta | 0:158c61bb030f | 1191 | goto L_RETURN; |
mzta | 0:158c61bb030f | 1192 | } |
mzta | 0:158c61bb030f | 1193 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1194 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1195 | ci->nregs = irep->nregs; |
mzta | 0:158c61bb030f | 1196 | if (ci->argc < 0) { |
mzta | 0:158c61bb030f | 1197 | stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); |
mzta | 0:158c61bb030f | 1198 | } |
mzta | 0:158c61bb030f | 1199 | else { |
mzta | 0:158c61bb030f | 1200 | stack_extend(mrb, irep->nregs, ci->argc+2); |
mzta | 0:158c61bb030f | 1201 | } |
mzta | 0:158c61bb030f | 1202 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 1203 | regs[0] = m->env->stack[0]; |
mzta | 0:158c61bb030f | 1204 | pc = irep->iseq; |
mzta | 0:158c61bb030f | 1205 | JUMP; |
mzta | 0:158c61bb030f | 1206 | } |
mzta | 0:158c61bb030f | 1207 | } |
mzta | 0:158c61bb030f | 1208 | |
mzta | 0:158c61bb030f | 1209 | CASE(OP_SUPER) { |
mzta | 0:158c61bb030f | 1210 | /* A C R(A) := super(R(A+1),... ,R(A+C+1)) */ |
mzta | 0:158c61bb030f | 1211 | mrb_value recv; |
mzta | 0:158c61bb030f | 1212 | mrb_callinfo *ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1213 | struct RProc *m; |
mzta | 0:158c61bb030f | 1214 | struct RClass *c; |
mzta | 0:158c61bb030f | 1215 | mrb_sym mid = ci->mid; |
mzta | 0:158c61bb030f | 1216 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1217 | int n = GETARG_C(i); |
mzta | 0:158c61bb030f | 1218 | |
mzta | 0:158c61bb030f | 1219 | recv = regs[0]; |
mzta | 0:158c61bb030f | 1220 | c = mrb->c->ci->target_class->super; |
mzta | 0:158c61bb030f | 1221 | m = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 1222 | if (!m) { |
mzta | 0:158c61bb030f | 1223 | mid = mrb_intern_lit(mrb, "method_missing"); |
mzta | 0:158c61bb030f | 1224 | m = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 1225 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1226 | mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); |
mzta | 0:158c61bb030f | 1227 | } |
mzta | 0:158c61bb030f | 1228 | else { |
mzta | 0:158c61bb030f | 1229 | value_move(regs+a+2, regs+a+1, ++n); |
mzta | 0:158c61bb030f | 1230 | SET_SYM_VALUE(regs[a+1], ci->mid); |
mzta | 0:158c61bb030f | 1231 | } |
mzta | 0:158c61bb030f | 1232 | } |
mzta | 0:158c61bb030f | 1233 | |
mzta | 0:158c61bb030f | 1234 | /* push callinfo */ |
mzta | 0:158c61bb030f | 1235 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 1236 | ci->mid = mid; |
mzta | 0:158c61bb030f | 1237 | ci->proc = m; |
mzta | 0:158c61bb030f | 1238 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 1239 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1240 | ci->argc = -1; |
mzta | 0:158c61bb030f | 1241 | } |
mzta | 0:158c61bb030f | 1242 | else { |
mzta | 0:158c61bb030f | 1243 | ci->argc = n; |
mzta | 0:158c61bb030f | 1244 | } |
mzta | 0:158c61bb030f | 1245 | ci->target_class = c; |
mzta | 0:158c61bb030f | 1246 | ci->pc = pc + 1; |
mzta | 0:158c61bb030f | 1247 | |
mzta | 0:158c61bb030f | 1248 | /* prepare stack */ |
mzta | 0:158c61bb030f | 1249 | mrb->c->stack += a; |
mzta | 0:158c61bb030f | 1250 | mrb->c->stack[0] = recv; |
mzta | 0:158c61bb030f | 1251 | |
mzta | 0:158c61bb030f | 1252 | if (MRB_PROC_CFUNC_P(m)) { |
mzta | 0:158c61bb030f | 1253 | ci->nregs = 0; |
mzta | 0:158c61bb030f | 1254 | mrb->c->stack[0] = m->body.func(mrb, recv); |
mzta | 0:158c61bb030f | 1255 | mrb_gc_arena_restore(mrb, ai); |
mzta | 0:158c61bb030f | 1256 | if (mrb->exc) goto L_RAISE; |
mzta | 0:158c61bb030f | 1257 | /* pop stackpos */ |
mzta | 0:158c61bb030f | 1258 | regs = mrb->c->stack = mrb->c->ci->stackent; |
mzta | 0:158c61bb030f | 1259 | cipop(mrb); |
mzta | 0:158c61bb030f | 1260 | NEXT; |
mzta | 0:158c61bb030f | 1261 | } |
mzta | 0:158c61bb030f | 1262 | else { |
mzta | 0:158c61bb030f | 1263 | /* fill callinfo */ |
mzta | 0:158c61bb030f | 1264 | ci->acc = a; |
mzta | 0:158c61bb030f | 1265 | |
mzta | 0:158c61bb030f | 1266 | /* setup environment for calling method */ |
mzta | 0:158c61bb030f | 1267 | ci->proc = m; |
mzta | 0:158c61bb030f | 1268 | irep = m->body.irep; |
mzta | 0:158c61bb030f | 1269 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1270 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1271 | ci->nregs = irep->nregs; |
mzta | 0:158c61bb030f | 1272 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1273 | stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); |
mzta | 0:158c61bb030f | 1274 | } |
mzta | 0:158c61bb030f | 1275 | else { |
mzta | 0:158c61bb030f | 1276 | stack_extend(mrb, irep->nregs, ci->argc+2); |
mzta | 0:158c61bb030f | 1277 | } |
mzta | 0:158c61bb030f | 1278 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 1279 | pc = irep->iseq; |
mzta | 0:158c61bb030f | 1280 | JUMP; |
mzta | 0:158c61bb030f | 1281 | } |
mzta | 0:158c61bb030f | 1282 | } |
mzta | 0:158c61bb030f | 1283 | |
mzta | 0:158c61bb030f | 1284 | CASE(OP_ARGARY) { |
mzta | 0:158c61bb030f | 1285 | /* A Bx R(A) := argument array (16=6:1:5:4) */ |
mzta | 0:158c61bb030f | 1286 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1287 | int bx = GETARG_Bx(i); |
mzta | 0:158c61bb030f | 1288 | int m1 = (bx>>10)&0x3f; |
mzta | 0:158c61bb030f | 1289 | int r = (bx>>9)&0x1; |
mzta | 0:158c61bb030f | 1290 | int m2 = (bx>>4)&0x1f; |
mzta | 0:158c61bb030f | 1291 | int lv = (bx>>0)&0xf; |
mzta | 0:158c61bb030f | 1292 | mrb_value *stack; |
mzta | 0:158c61bb030f | 1293 | |
mzta | 0:158c61bb030f | 1294 | if (lv == 0) stack = regs + 1; |
mzta | 0:158c61bb030f | 1295 | else { |
mzta | 0:158c61bb030f | 1296 | struct REnv *e = uvenv(mrb, lv-1); |
mzta | 0:158c61bb030f | 1297 | if (!e) { |
mzta | 0:158c61bb030f | 1298 | mrb_value exc; |
mzta | 0:158c61bb030f | 1299 | exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); |
mzta | 0:158c61bb030f | 1300 | mrb->exc = mrb_obj_ptr(exc); |
mzta | 0:158c61bb030f | 1301 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1302 | } |
mzta | 0:158c61bb030f | 1303 | stack = e->stack + 1; |
mzta | 0:158c61bb030f | 1304 | } |
mzta | 0:158c61bb030f | 1305 | if (r == 0) { |
mzta | 0:158c61bb030f | 1306 | regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack); |
mzta | 0:158c61bb030f | 1307 | } |
mzta | 0:158c61bb030f | 1308 | else { |
mzta | 0:158c61bb030f | 1309 | mrb_value *pp = NULL; |
mzta | 0:158c61bb030f | 1310 | struct RArray *rest; |
mzta | 0:158c61bb030f | 1311 | int len = 0; |
mzta | 0:158c61bb030f | 1312 | |
mzta | 0:158c61bb030f | 1313 | if (mrb_array_p(stack[m1])) { |
mzta | 0:158c61bb030f | 1314 | struct RArray *ary = mrb_ary_ptr(stack[m1]); |
mzta | 0:158c61bb030f | 1315 | |
mzta | 0:158c61bb030f | 1316 | pp = ary->ptr; |
mzta | 0:158c61bb030f | 1317 | len = ary->len; |
mzta | 0:158c61bb030f | 1318 | } |
mzta | 0:158c61bb030f | 1319 | regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); |
mzta | 0:158c61bb030f | 1320 | rest = mrb_ary_ptr(regs[a]); |
mzta | 0:158c61bb030f | 1321 | if (m1 > 0) { |
mzta | 0:158c61bb030f | 1322 | stack_copy(rest->ptr, stack, m1); |
mzta | 0:158c61bb030f | 1323 | } |
mzta | 0:158c61bb030f | 1324 | if (len > 0) { |
mzta | 0:158c61bb030f | 1325 | stack_copy(rest->ptr+m1, pp, len); |
mzta | 0:158c61bb030f | 1326 | } |
mzta | 0:158c61bb030f | 1327 | if (m2 > 0) { |
mzta | 0:158c61bb030f | 1328 | stack_copy(rest->ptr+m1+len, stack+m1+1, m2); |
mzta | 0:158c61bb030f | 1329 | } |
mzta | 0:158c61bb030f | 1330 | rest->len = m1+len+m2; |
mzta | 0:158c61bb030f | 1331 | } |
mzta | 0:158c61bb030f | 1332 | regs[a+1] = stack[m1+r+m2]; |
mzta | 0:158c61bb030f | 1333 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 1334 | NEXT; |
mzta | 0:158c61bb030f | 1335 | } |
mzta | 0:158c61bb030f | 1336 | |
mzta | 0:158c61bb030f | 1337 | CASE(OP_ENTER) { |
mzta | 0:158c61bb030f | 1338 | /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */ |
mzta | 0:158c61bb030f | 1339 | /* number of optional arguments times OP_JMP should follow */ |
mzta | 0:158c61bb030f | 1340 | mrb_aspec ax = GETARG_Ax(i); |
mzta | 0:158c61bb030f | 1341 | int m1 = MRB_ASPEC_REQ(ax); |
mzta | 0:158c61bb030f | 1342 | int o = MRB_ASPEC_OPT(ax); |
mzta | 0:158c61bb030f | 1343 | int r = MRB_ASPEC_REST(ax); |
mzta | 0:158c61bb030f | 1344 | int m2 = MRB_ASPEC_POST(ax); |
mzta | 0:158c61bb030f | 1345 | /* unused |
mzta | 0:158c61bb030f | 1346 | int k = MRB_ASPEC_KEY(ax); |
mzta | 0:158c61bb030f | 1347 | int kd = MRB_ASPEC_KDICT(ax); |
mzta | 0:158c61bb030f | 1348 | int b = MRB_ASPEC_BLOCK(ax); |
mzta | 0:158c61bb030f | 1349 | */ |
mzta | 0:158c61bb030f | 1350 | int argc = mrb->c->ci->argc; |
mzta | 0:158c61bb030f | 1351 | mrb_value *argv = regs+1; |
mzta | 0:158c61bb030f | 1352 | mrb_value *argv0 = argv; |
mzta | 0:158c61bb030f | 1353 | int len = m1 + o + r + m2; |
mzta | 0:158c61bb030f | 1354 | mrb_value *blk = &argv[argc < 0 ? 1 : argc]; |
mzta | 0:158c61bb030f | 1355 | |
mzta | 0:158c61bb030f | 1356 | if (!mrb_nil_p(*blk) && mrb_type(*blk) != MRB_TT_PROC) { |
mzta | 0:158c61bb030f | 1357 | *blk = mrb_convert_type(mrb, *blk, MRB_TT_PROC, "Proc", "to_proc"); |
mzta | 0:158c61bb030f | 1358 | } |
mzta | 0:158c61bb030f | 1359 | if (argc < 0) { |
mzta | 0:158c61bb030f | 1360 | struct RArray *ary = mrb_ary_ptr(regs[1]); |
mzta | 0:158c61bb030f | 1361 | argv = ary->ptr; |
mzta | 0:158c61bb030f | 1362 | argc = ary->len; |
mzta | 0:158c61bb030f | 1363 | mrb_gc_protect(mrb, regs[1]); |
mzta | 0:158c61bb030f | 1364 | } |
mzta | 0:158c61bb030f | 1365 | if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) { |
mzta | 0:158c61bb030f | 1366 | if (argc >= 0) { |
mzta | 0:158c61bb030f | 1367 | if (argc < m1 + m2 || (r == 0 && argc > len)) { |
mzta | 0:158c61bb030f | 1368 | argnum_error(mrb, m1+m2); |
mzta | 0:158c61bb030f | 1369 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1370 | } |
mzta | 0:158c61bb030f | 1371 | } |
mzta | 0:158c61bb030f | 1372 | } |
mzta | 0:158c61bb030f | 1373 | else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) { |
mzta | 0:158c61bb030f | 1374 | mrb_gc_protect(mrb, argv[0]); |
mzta | 0:158c61bb030f | 1375 | argc = mrb_ary_ptr(argv[0])->len; |
mzta | 0:158c61bb030f | 1376 | argv = mrb_ary_ptr(argv[0])->ptr; |
mzta | 0:158c61bb030f | 1377 | } |
mzta | 0:158c61bb030f | 1378 | mrb->c->ci->argc = len; |
mzta | 0:158c61bb030f | 1379 | if (argc < len) { |
mzta | 0:158c61bb030f | 1380 | int mlen = m2; |
mzta | 0:158c61bb030f | 1381 | if (argc < m1+m2) { |
mzta | 0:158c61bb030f | 1382 | if (m1 < argc) |
mzta | 0:158c61bb030f | 1383 | mlen = argc - m1; |
mzta | 0:158c61bb030f | 1384 | else |
mzta | 0:158c61bb030f | 1385 | mlen = 0; |
mzta | 0:158c61bb030f | 1386 | } |
mzta | 0:158c61bb030f | 1387 | regs[len+1] = *blk; /* move block */ |
mzta | 0:158c61bb030f | 1388 | SET_NIL_VALUE(regs[argc+1]); |
mzta | 0:158c61bb030f | 1389 | if (argv0 != argv) { |
mzta | 0:158c61bb030f | 1390 | value_move(®s[1], argv, argc-mlen); /* m1 + o */ |
mzta | 0:158c61bb030f | 1391 | } |
mzta | 0:158c61bb030f | 1392 | if (mlen) { |
mzta | 0:158c61bb030f | 1393 | value_move(®s[len-m2+1], &argv[argc-mlen], mlen); |
mzta | 0:158c61bb030f | 1394 | } |
mzta | 0:158c61bb030f | 1395 | if (r) { |
mzta | 0:158c61bb030f | 1396 | regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); |
mzta | 0:158c61bb030f | 1397 | } |
mzta | 0:158c61bb030f | 1398 | if (o == 0 || argc < m1+m2) pc++; |
mzta | 0:158c61bb030f | 1399 | else |
mzta | 0:158c61bb030f | 1400 | pc += argc - m1 - m2 + 1; |
mzta | 0:158c61bb030f | 1401 | } |
mzta | 0:158c61bb030f | 1402 | else { |
mzta | 0:158c61bb030f | 1403 | int rnum = 0; |
mzta | 0:158c61bb030f | 1404 | if (argv0 != argv) { |
mzta | 0:158c61bb030f | 1405 | regs[len+1] = *blk; /* move block */ |
mzta | 0:158c61bb030f | 1406 | value_move(®s[1], argv, m1+o); |
mzta | 0:158c61bb030f | 1407 | } |
mzta | 0:158c61bb030f | 1408 | if (r) { |
mzta | 0:158c61bb030f | 1409 | rnum = argc-m1-o-m2; |
mzta | 0:158c61bb030f | 1410 | regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); |
mzta | 0:158c61bb030f | 1411 | } |
mzta | 0:158c61bb030f | 1412 | if (m2) { |
mzta | 0:158c61bb030f | 1413 | if (argc-m2 > m1) { |
mzta | 0:158c61bb030f | 1414 | value_move(®s[m1+o+r+1], &argv[m1+o+rnum], m2); |
mzta | 0:158c61bb030f | 1415 | } |
mzta | 0:158c61bb030f | 1416 | } |
mzta | 0:158c61bb030f | 1417 | if (argv0 == argv) { |
mzta | 0:158c61bb030f | 1418 | regs[len+1] = *blk; /* move block */ |
mzta | 0:158c61bb030f | 1419 | } |
mzta | 0:158c61bb030f | 1420 | pc += o + 1; |
mzta | 0:158c61bb030f | 1421 | } |
mzta | 0:158c61bb030f | 1422 | JUMP; |
mzta | 0:158c61bb030f | 1423 | } |
mzta | 0:158c61bb030f | 1424 | |
mzta | 0:158c61bb030f | 1425 | CASE(OP_KARG) { |
mzta | 0:158c61bb030f | 1426 | /* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */ |
mzta | 0:158c61bb030f | 1427 | /* if C == 2; raise unless kdict.empty? */ |
mzta | 0:158c61bb030f | 1428 | /* OP_JMP should follow to skip init code */ |
mzta | 0:158c61bb030f | 1429 | NEXT; |
mzta | 0:158c61bb030f | 1430 | } |
mzta | 0:158c61bb030f | 1431 | |
mzta | 0:158c61bb030f | 1432 | CASE(OP_KDICT) { |
mzta | 0:158c61bb030f | 1433 | /* A C R(A) := kdict */ |
mzta | 0:158c61bb030f | 1434 | NEXT; |
mzta | 0:158c61bb030f | 1435 | } |
mzta | 0:158c61bb030f | 1436 | |
mzta | 0:158c61bb030f | 1437 | L_RETURN: |
mzta | 0:158c61bb030f | 1438 | i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL); |
mzta | 0:158c61bb030f | 1439 | /* fall through */ |
mzta | 0:158c61bb030f | 1440 | CASE(OP_RETURN) { |
mzta | 0:158c61bb030f | 1441 | /* A B return R(A) (B=normal,in-block return/break) */ |
mzta | 0:158c61bb030f | 1442 | if (mrb->exc) { |
mzta | 0:158c61bb030f | 1443 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 1444 | int eidx; |
mzta | 0:158c61bb030f | 1445 | |
mzta | 0:158c61bb030f | 1446 | L_RAISE: |
mzta | 0:158c61bb030f | 1447 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1448 | mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, pc)); |
mzta | 0:158c61bb030f | 1449 | mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase)); |
mzta | 0:158c61bb030f | 1450 | eidx = ci->eidx; |
mzta | 0:158c61bb030f | 1451 | if (ci == mrb->c->cibase) { |
mzta | 0:158c61bb030f | 1452 | if (ci->ridx == 0) goto L_STOP; |
mzta | 0:158c61bb030f | 1453 | goto L_RESCUE; |
mzta | 0:158c61bb030f | 1454 | } |
mzta | 0:158c61bb030f | 1455 | while (eidx > ci[-1].eidx) { |
mzta | 0:158c61bb030f | 1456 | ecall(mrb, --eidx); |
mzta | 0:158c61bb030f | 1457 | } |
mzta | 0:158c61bb030f | 1458 | while (ci[0].ridx == ci[-1].ridx) { |
mzta | 0:158c61bb030f | 1459 | cipop(mrb); |
mzta | 0:158c61bb030f | 1460 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1461 | mrb->c->stack = ci[1].stackent; |
mzta | 0:158c61bb030f | 1462 | if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { |
mzta | 0:158c61bb030f | 1463 | mrb->jmp = prev_jmp; |
mzta | 0:158c61bb030f | 1464 | MRB_THROW(prev_jmp); |
mzta | 0:158c61bb030f | 1465 | } |
mzta | 0:158c61bb030f | 1466 | if (ci > mrb->c->cibase) { |
mzta | 0:158c61bb030f | 1467 | while (eidx > ci[-1].eidx) { |
mzta | 0:158c61bb030f | 1468 | ecall(mrb, --eidx); |
mzta | 0:158c61bb030f | 1469 | } |
mzta | 0:158c61bb030f | 1470 | } |
mzta | 0:158c61bb030f | 1471 | else if (ci == mrb->c->cibase) { |
mzta | 0:158c61bb030f | 1472 | if (ci->ridx == 0) { |
mzta | 0:158c61bb030f | 1473 | if (mrb->c == mrb->root_c) { |
mzta | 0:158c61bb030f | 1474 | regs = mrb->c->stack = mrb->c->stbase; |
mzta | 0:158c61bb030f | 1475 | goto L_STOP; |
mzta | 0:158c61bb030f | 1476 | } |
mzta | 0:158c61bb030f | 1477 | else { |
mzta | 0:158c61bb030f | 1478 | struct mrb_context *c = mrb->c; |
mzta | 0:158c61bb030f | 1479 | |
mzta | 0:158c61bb030f | 1480 | mrb->c = c->prev; |
mzta | 0:158c61bb030f | 1481 | c->prev = NULL; |
mzta | 0:158c61bb030f | 1482 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1483 | } |
mzta | 0:158c61bb030f | 1484 | } |
mzta | 0:158c61bb030f | 1485 | break; |
mzta | 0:158c61bb030f | 1486 | } |
mzta | 0:158c61bb030f | 1487 | } |
mzta | 0:158c61bb030f | 1488 | L_RESCUE: |
mzta | 0:158c61bb030f | 1489 | if (ci->ridx == 0) goto L_STOP; |
mzta | 0:158c61bb030f | 1490 | proc = ci->proc; |
mzta | 0:158c61bb030f | 1491 | irep = proc->body.irep; |
mzta | 0:158c61bb030f | 1492 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1493 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1494 | regs = mrb->c->stack = ci[1].stackent; |
mzta | 0:158c61bb030f | 1495 | pc = mrb->c->rescue[--ci->ridx]; |
mzta | 0:158c61bb030f | 1496 | } |
mzta | 0:158c61bb030f | 1497 | else { |
mzta | 0:158c61bb030f | 1498 | mrb_callinfo *ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1499 | int acc, eidx = mrb->c->ci->eidx; |
mzta | 0:158c61bb030f | 1500 | mrb_value v = regs[GETARG_A(i)]; |
mzta | 0:158c61bb030f | 1501 | |
mzta | 0:158c61bb030f | 1502 | switch (GETARG_B(i)) { |
mzta | 0:158c61bb030f | 1503 | case OP_R_RETURN: |
mzta | 0:158c61bb030f | 1504 | /* Fall through to OP_R_NORMAL otherwise */ |
mzta | 0:158c61bb030f | 1505 | if (proc->env && !MRB_PROC_STRICT_P(proc)) { |
mzta | 0:158c61bb030f | 1506 | struct REnv *e = top_env(mrb, proc); |
mzta | 0:158c61bb030f | 1507 | |
mzta | 0:158c61bb030f | 1508 | if (!MRB_ENV_STACK_SHARED_P(e)) { |
mzta | 0:158c61bb030f | 1509 | localjump_error(mrb, LOCALJUMP_ERROR_RETURN); |
mzta | 0:158c61bb030f | 1510 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1511 | } |
mzta | 0:158c61bb030f | 1512 | ci = mrb->c->cibase + e->cioff; |
mzta | 0:158c61bb030f | 1513 | if (ci == mrb->c->cibase) { |
mzta | 0:158c61bb030f | 1514 | localjump_error(mrb, LOCALJUMP_ERROR_RETURN); |
mzta | 0:158c61bb030f | 1515 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1516 | } |
mzta | 0:158c61bb030f | 1517 | mrb->c->ci = ci; |
mzta | 0:158c61bb030f | 1518 | break; |
mzta | 0:158c61bb030f | 1519 | } |
mzta | 0:158c61bb030f | 1520 | case OP_R_NORMAL: |
mzta | 0:158c61bb030f | 1521 | if (ci == mrb->c->cibase) { |
mzta | 0:158c61bb030f | 1522 | if (!mrb->c->prev) { /* toplevel return */ |
mzta | 0:158c61bb030f | 1523 | localjump_error(mrb, LOCALJUMP_ERROR_RETURN); |
mzta | 0:158c61bb030f | 1524 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1525 | } |
mzta | 0:158c61bb030f | 1526 | if (mrb->c->prev->ci == mrb->c->prev->cibase) { |
mzta | 0:158c61bb030f | 1527 | mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume"); |
mzta | 0:158c61bb030f | 1528 | mrb->exc = mrb_obj_ptr(exc); |
mzta | 0:158c61bb030f | 1529 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1530 | } |
mzta | 0:158c61bb030f | 1531 | /* automatic yield at the end */ |
mzta | 0:158c61bb030f | 1532 | mrb->c->status = MRB_FIBER_TERMINATED; |
mzta | 0:158c61bb030f | 1533 | mrb->c = mrb->c->prev; |
mzta | 0:158c61bb030f | 1534 | mrb->c->status = MRB_FIBER_RUNNING; |
mzta | 0:158c61bb030f | 1535 | } |
mzta | 0:158c61bb030f | 1536 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1537 | break; |
mzta | 0:158c61bb030f | 1538 | case OP_R_BREAK: |
mzta | 0:158c61bb030f | 1539 | if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) { |
mzta | 0:158c61bb030f | 1540 | localjump_error(mrb, LOCALJUMP_ERROR_BREAK); |
mzta | 0:158c61bb030f | 1541 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1542 | } |
mzta | 0:158c61bb030f | 1543 | /* break from fiber block */ |
mzta | 0:158c61bb030f | 1544 | if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) { |
mzta | 0:158c61bb030f | 1545 | struct mrb_context *c = mrb->c; |
mzta | 0:158c61bb030f | 1546 | |
mzta | 0:158c61bb030f | 1547 | mrb->c = c->prev; |
mzta | 0:158c61bb030f | 1548 | c->prev = NULL; |
mzta | 0:158c61bb030f | 1549 | } |
mzta | 0:158c61bb030f | 1550 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1551 | mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1; |
mzta | 0:158c61bb030f | 1552 | while (ci > mrb->c->ci) { |
mzta | 0:158c61bb030f | 1553 | if (ci[-1].acc == CI_ACC_SKIP) { |
mzta | 0:158c61bb030f | 1554 | mrb->c->ci = ci; |
mzta | 0:158c61bb030f | 1555 | break; |
mzta | 0:158c61bb030f | 1556 | } |
mzta | 0:158c61bb030f | 1557 | ci--; |
mzta | 0:158c61bb030f | 1558 | } |
mzta | 0:158c61bb030f | 1559 | break; |
mzta | 0:158c61bb030f | 1560 | default: |
mzta | 0:158c61bb030f | 1561 | /* cannot happen */ |
mzta | 0:158c61bb030f | 1562 | break; |
mzta | 0:158c61bb030f | 1563 | } |
mzta | 0:158c61bb030f | 1564 | while (eidx > mrb->c->ci[-1].eidx) { |
mzta | 0:158c61bb030f | 1565 | ecall(mrb, --eidx); |
mzta | 0:158c61bb030f | 1566 | } |
mzta | 0:158c61bb030f | 1567 | cipop(mrb); |
mzta | 0:158c61bb030f | 1568 | acc = ci->acc; |
mzta | 0:158c61bb030f | 1569 | pc = ci->pc; |
mzta | 0:158c61bb030f | 1570 | regs = mrb->c->stack = ci->stackent; |
mzta | 0:158c61bb030f | 1571 | if (acc == CI_ACC_SKIP) { |
mzta | 0:158c61bb030f | 1572 | mrb->jmp = prev_jmp; |
mzta | 0:158c61bb030f | 1573 | return v; |
mzta | 0:158c61bb030f | 1574 | } |
mzta | 0:158c61bb030f | 1575 | DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid))); |
mzta | 0:158c61bb030f | 1576 | proc = mrb->c->ci->proc; |
mzta | 0:158c61bb030f | 1577 | irep = proc->body.irep; |
mzta | 0:158c61bb030f | 1578 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1579 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1580 | |
mzta | 0:158c61bb030f | 1581 | regs[acc] = v; |
mzta | 0:158c61bb030f | 1582 | } |
mzta | 0:158c61bb030f | 1583 | JUMP; |
mzta | 0:158c61bb030f | 1584 | } |
mzta | 0:158c61bb030f | 1585 | |
mzta | 0:158c61bb030f | 1586 | CASE(OP_TAILCALL) { |
mzta | 0:158c61bb030f | 1587 | /* A B C return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */ |
mzta | 0:158c61bb030f | 1588 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1589 | int n = GETARG_C(i); |
mzta | 0:158c61bb030f | 1590 | struct RProc *m; |
mzta | 0:158c61bb030f | 1591 | struct RClass *c; |
mzta | 0:158c61bb030f | 1592 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 1593 | mrb_value recv; |
mzta | 0:158c61bb030f | 1594 | mrb_sym mid = syms[GETARG_B(i)]; |
mzta | 0:158c61bb030f | 1595 | |
mzta | 0:158c61bb030f | 1596 | recv = regs[a]; |
mzta | 0:158c61bb030f | 1597 | c = mrb_class(mrb, recv); |
mzta | 0:158c61bb030f | 1598 | m = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 1599 | if (!m) { |
mzta | 0:158c61bb030f | 1600 | mrb_value sym = mrb_symbol_value(mid); |
mzta | 0:158c61bb030f | 1601 | |
mzta | 0:158c61bb030f | 1602 | mid = mrb_intern_lit(mrb, "method_missing"); |
mzta | 0:158c61bb030f | 1603 | m = mrb_method_search_vm(mrb, &c, mid); |
mzta | 0:158c61bb030f | 1604 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1605 | mrb_ary_unshift(mrb, regs[a+1], sym); |
mzta | 0:158c61bb030f | 1606 | } |
mzta | 0:158c61bb030f | 1607 | else { |
mzta | 0:158c61bb030f | 1608 | value_move(regs+a+2, regs+a+1, ++n); |
mzta | 0:158c61bb030f | 1609 | regs[a+1] = sym; |
mzta | 0:158c61bb030f | 1610 | } |
mzta | 0:158c61bb030f | 1611 | } |
mzta | 0:158c61bb030f | 1612 | |
mzta | 0:158c61bb030f | 1613 | /* replace callinfo */ |
mzta | 0:158c61bb030f | 1614 | ci = mrb->c->ci; |
mzta | 0:158c61bb030f | 1615 | ci->mid = mid; |
mzta | 0:158c61bb030f | 1616 | ci->target_class = c; |
mzta | 0:158c61bb030f | 1617 | if (n == CALL_MAXARGS) { |
mzta | 0:158c61bb030f | 1618 | ci->argc = -1; |
mzta | 0:158c61bb030f | 1619 | } |
mzta | 0:158c61bb030f | 1620 | else { |
mzta | 0:158c61bb030f | 1621 | ci->argc = n; |
mzta | 0:158c61bb030f | 1622 | } |
mzta | 0:158c61bb030f | 1623 | |
mzta | 0:158c61bb030f | 1624 | /* move stack */ |
mzta | 0:158c61bb030f | 1625 | value_move(mrb->c->stack, ®s[a], ci->argc+1); |
mzta | 0:158c61bb030f | 1626 | |
mzta | 0:158c61bb030f | 1627 | if (MRB_PROC_CFUNC_P(m)) { |
mzta | 0:158c61bb030f | 1628 | mrb->c->stack[0] = m->body.func(mrb, recv); |
mzta | 0:158c61bb030f | 1629 | mrb_gc_arena_restore(mrb, ai); |
mzta | 0:158c61bb030f | 1630 | goto L_RETURN; |
mzta | 0:158c61bb030f | 1631 | } |
mzta | 0:158c61bb030f | 1632 | else { |
mzta | 0:158c61bb030f | 1633 | /* setup environment for calling method */ |
mzta | 0:158c61bb030f | 1634 | irep = m->body.irep; |
mzta | 0:158c61bb030f | 1635 | pool = irep->pool; |
mzta | 0:158c61bb030f | 1636 | syms = irep->syms; |
mzta | 0:158c61bb030f | 1637 | if (ci->argc < 0) { |
mzta | 0:158c61bb030f | 1638 | stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); |
mzta | 0:158c61bb030f | 1639 | } |
mzta | 0:158c61bb030f | 1640 | else { |
mzta | 0:158c61bb030f | 1641 | stack_extend(mrb, irep->nregs, ci->argc+2); |
mzta | 0:158c61bb030f | 1642 | } |
mzta | 0:158c61bb030f | 1643 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 1644 | pc = irep->iseq; |
mzta | 0:158c61bb030f | 1645 | } |
mzta | 0:158c61bb030f | 1646 | JUMP; |
mzta | 0:158c61bb030f | 1647 | } |
mzta | 0:158c61bb030f | 1648 | |
mzta | 0:158c61bb030f | 1649 | CASE(OP_BLKPUSH) { |
mzta | 0:158c61bb030f | 1650 | /* A Bx R(A) := block (16=6:1:5:4) */ |
mzta | 0:158c61bb030f | 1651 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1652 | int bx = GETARG_Bx(i); |
mzta | 0:158c61bb030f | 1653 | int m1 = (bx>>10)&0x3f; |
mzta | 0:158c61bb030f | 1654 | int r = (bx>>9)&0x1; |
mzta | 0:158c61bb030f | 1655 | int m2 = (bx>>4)&0x1f; |
mzta | 0:158c61bb030f | 1656 | int lv = (bx>>0)&0xf; |
mzta | 0:158c61bb030f | 1657 | mrb_value *stack; |
mzta | 0:158c61bb030f | 1658 | |
mzta | 0:158c61bb030f | 1659 | if (lv == 0) stack = regs + 1; |
mzta | 0:158c61bb030f | 1660 | else { |
mzta | 0:158c61bb030f | 1661 | struct REnv *e = uvenv(mrb, lv-1); |
mzta | 0:158c61bb030f | 1662 | if (!e) { |
mzta | 0:158c61bb030f | 1663 | localjump_error(mrb, LOCALJUMP_ERROR_YIELD); |
mzta | 0:158c61bb030f | 1664 | goto L_RAISE; |
mzta | 0:158c61bb030f | 1665 | } |
mzta | 0:158c61bb030f | 1666 | stack = e->stack + 1; |
mzta | 0:158c61bb030f | 1667 | } |
mzta | 0:158c61bb030f | 1668 | regs[a] = stack[m1+r+m2]; |
mzta | 0:158c61bb030f | 1669 | NEXT; |
mzta | 0:158c61bb030f | 1670 | } |
mzta | 0:158c61bb030f | 1671 | |
mzta | 0:158c61bb030f | 1672 | #define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff)) |
mzta | 0:158c61bb030f | 1673 | #define OP_MATH_BODY(op,v1,v2) do {\ |
mzta | 0:158c61bb030f | 1674 | v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\ |
mzta | 0:158c61bb030f | 1675 | } while(0) |
mzta | 0:158c61bb030f | 1676 | |
mzta | 0:158c61bb030f | 1677 | CASE(OP_ADD) { |
mzta | 0:158c61bb030f | 1678 | /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/ |
mzta | 0:158c61bb030f | 1679 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1680 | |
mzta | 0:158c61bb030f | 1681 | /* need to check if op is overridden */ |
mzta | 0:158c61bb030f | 1682 | switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { |
mzta | 0:158c61bb030f | 1683 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1684 | { |
mzta | 0:158c61bb030f | 1685 | mrb_int x, y, z; |
mzta | 0:158c61bb030f | 1686 | mrb_value *regs_a = regs + a; |
mzta | 0:158c61bb030f | 1687 | |
mzta | 0:158c61bb030f | 1688 | x = mrb_fixnum(regs_a[0]); |
mzta | 0:158c61bb030f | 1689 | y = mrb_fixnum(regs_a[1]); |
mzta | 0:158c61bb030f | 1690 | if (mrb_int_add_overflow(x, y, &z)) { |
mzta | 0:158c61bb030f | 1691 | SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y); |
mzta | 0:158c61bb030f | 1692 | break; |
mzta | 0:158c61bb030f | 1693 | } |
mzta | 0:158c61bb030f | 1694 | SET_INT_VALUE(regs[a], z); |
mzta | 0:158c61bb030f | 1695 | } |
mzta | 0:158c61bb030f | 1696 | break; |
mzta | 0:158c61bb030f | 1697 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1698 | { |
mzta | 0:158c61bb030f | 1699 | mrb_int x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1700 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1701 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y); |
mzta | 0:158c61bb030f | 1702 | } |
mzta | 0:158c61bb030f | 1703 | break; |
mzta | 0:158c61bb030f | 1704 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1705 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1706 | { |
mzta | 0:158c61bb030f | 1707 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1708 | mrb_int y = mrb_fixnum(regs[a+1]); |
mzta | 0:158c61bb030f | 1709 | SET_FLOAT_VALUE(mrb, regs[a], x + y); |
mzta | 0:158c61bb030f | 1710 | } |
mzta | 0:158c61bb030f | 1711 | #else |
mzta | 0:158c61bb030f | 1712 | OP_MATH_BODY(+,mrb_float,mrb_fixnum); |
mzta | 0:158c61bb030f | 1713 | #endif |
mzta | 0:158c61bb030f | 1714 | break; |
mzta | 0:158c61bb030f | 1715 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1716 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1717 | { |
mzta | 0:158c61bb030f | 1718 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1719 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1720 | SET_FLOAT_VALUE(mrb, regs[a], x + y); |
mzta | 0:158c61bb030f | 1721 | } |
mzta | 0:158c61bb030f | 1722 | #else |
mzta | 0:158c61bb030f | 1723 | OP_MATH_BODY(+,mrb_float,mrb_float); |
mzta | 0:158c61bb030f | 1724 | #endif |
mzta | 0:158c61bb030f | 1725 | break; |
mzta | 0:158c61bb030f | 1726 | case TYPES2(MRB_TT_STRING,MRB_TT_STRING): |
mzta | 0:158c61bb030f | 1727 | regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); |
mzta | 0:158c61bb030f | 1728 | break; |
mzta | 0:158c61bb030f | 1729 | default: |
mzta | 0:158c61bb030f | 1730 | goto L_SEND; |
mzta | 0:158c61bb030f | 1731 | } |
mzta | 0:158c61bb030f | 1732 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 1733 | NEXT; |
mzta | 0:158c61bb030f | 1734 | } |
mzta | 0:158c61bb030f | 1735 | |
mzta | 0:158c61bb030f | 1736 | CASE(OP_SUB) { |
mzta | 0:158c61bb030f | 1737 | /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/ |
mzta | 0:158c61bb030f | 1738 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1739 | |
mzta | 0:158c61bb030f | 1740 | /* need to check if op is overridden */ |
mzta | 0:158c61bb030f | 1741 | switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { |
mzta | 0:158c61bb030f | 1742 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1743 | { |
mzta | 0:158c61bb030f | 1744 | mrb_int x, y, z; |
mzta | 0:158c61bb030f | 1745 | |
mzta | 0:158c61bb030f | 1746 | x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1747 | y = mrb_fixnum(regs[a+1]); |
mzta | 0:158c61bb030f | 1748 | if (mrb_int_sub_overflow(x, y, &z)) { |
mzta | 0:158c61bb030f | 1749 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y); |
mzta | 0:158c61bb030f | 1750 | break; |
mzta | 0:158c61bb030f | 1751 | } |
mzta | 0:158c61bb030f | 1752 | SET_INT_VALUE(regs[a], z); |
mzta | 0:158c61bb030f | 1753 | } |
mzta | 0:158c61bb030f | 1754 | break; |
mzta | 0:158c61bb030f | 1755 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1756 | { |
mzta | 0:158c61bb030f | 1757 | mrb_int x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1758 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1759 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y); |
mzta | 0:158c61bb030f | 1760 | } |
mzta | 0:158c61bb030f | 1761 | break; |
mzta | 0:158c61bb030f | 1762 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1763 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1764 | { |
mzta | 0:158c61bb030f | 1765 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1766 | mrb_int y = mrb_fixnum(regs[a+1]); |
mzta | 0:158c61bb030f | 1767 | SET_FLOAT_VALUE(mrb, regs[a], x - y); |
mzta | 0:158c61bb030f | 1768 | } |
mzta | 0:158c61bb030f | 1769 | #else |
mzta | 0:158c61bb030f | 1770 | OP_MATH_BODY(-,mrb_float,mrb_fixnum); |
mzta | 0:158c61bb030f | 1771 | #endif |
mzta | 0:158c61bb030f | 1772 | break; |
mzta | 0:158c61bb030f | 1773 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1774 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1775 | { |
mzta | 0:158c61bb030f | 1776 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1777 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1778 | SET_FLOAT_VALUE(mrb, regs[a], x - y); |
mzta | 0:158c61bb030f | 1779 | } |
mzta | 0:158c61bb030f | 1780 | #else |
mzta | 0:158c61bb030f | 1781 | OP_MATH_BODY(-,mrb_float,mrb_float); |
mzta | 0:158c61bb030f | 1782 | #endif |
mzta | 0:158c61bb030f | 1783 | break; |
mzta | 0:158c61bb030f | 1784 | default: |
mzta | 0:158c61bb030f | 1785 | goto L_SEND; |
mzta | 0:158c61bb030f | 1786 | } |
mzta | 0:158c61bb030f | 1787 | NEXT; |
mzta | 0:158c61bb030f | 1788 | } |
mzta | 0:158c61bb030f | 1789 | |
mzta | 0:158c61bb030f | 1790 | CASE(OP_MUL) { |
mzta | 0:158c61bb030f | 1791 | /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/ |
mzta | 0:158c61bb030f | 1792 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1793 | |
mzta | 0:158c61bb030f | 1794 | /* need to check if op is overridden */ |
mzta | 0:158c61bb030f | 1795 | switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { |
mzta | 0:158c61bb030f | 1796 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1797 | { |
mzta | 0:158c61bb030f | 1798 | mrb_value z; |
mzta | 0:158c61bb030f | 1799 | |
mzta | 0:158c61bb030f | 1800 | z = mrb_fixnum_mul(mrb, regs[a], regs[a+1]); |
mzta | 0:158c61bb030f | 1801 | |
mzta | 0:158c61bb030f | 1802 | switch (mrb_type(z)) { |
mzta | 0:158c61bb030f | 1803 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 1804 | { |
mzta | 0:158c61bb030f | 1805 | SET_INT_VALUE(regs[a], mrb_fixnum(z)); |
mzta | 0:158c61bb030f | 1806 | } |
mzta | 0:158c61bb030f | 1807 | break; |
mzta | 0:158c61bb030f | 1808 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 1809 | { |
mzta | 0:158c61bb030f | 1810 | SET_FLOAT_VALUE(mrb, regs[a], mrb_float(z)); |
mzta | 0:158c61bb030f | 1811 | } |
mzta | 0:158c61bb030f | 1812 | break; |
mzta | 0:158c61bb030f | 1813 | default: |
mzta | 0:158c61bb030f | 1814 | /* cannot happen */ |
mzta | 0:158c61bb030f | 1815 | break; |
mzta | 0:158c61bb030f | 1816 | } |
mzta | 0:158c61bb030f | 1817 | } |
mzta | 0:158c61bb030f | 1818 | break; |
mzta | 0:158c61bb030f | 1819 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1820 | { |
mzta | 0:158c61bb030f | 1821 | mrb_int x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1822 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1823 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y); |
mzta | 0:158c61bb030f | 1824 | } |
mzta | 0:158c61bb030f | 1825 | break; |
mzta | 0:158c61bb030f | 1826 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1827 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1828 | { |
mzta | 0:158c61bb030f | 1829 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1830 | mrb_int y = mrb_fixnum(regs[a+1]); |
mzta | 0:158c61bb030f | 1831 | SET_FLOAT_VALUE(mrb, regs[a], x * y); |
mzta | 0:158c61bb030f | 1832 | } |
mzta | 0:158c61bb030f | 1833 | #else |
mzta | 0:158c61bb030f | 1834 | OP_MATH_BODY(*,mrb_float,mrb_fixnum); |
mzta | 0:158c61bb030f | 1835 | #endif |
mzta | 0:158c61bb030f | 1836 | break; |
mzta | 0:158c61bb030f | 1837 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1838 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1839 | { |
mzta | 0:158c61bb030f | 1840 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1841 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1842 | SET_FLOAT_VALUE(mrb, regs[a], x * y); |
mzta | 0:158c61bb030f | 1843 | } |
mzta | 0:158c61bb030f | 1844 | #else |
mzta | 0:158c61bb030f | 1845 | OP_MATH_BODY(*,mrb_float,mrb_float); |
mzta | 0:158c61bb030f | 1846 | #endif |
mzta | 0:158c61bb030f | 1847 | break; |
mzta | 0:158c61bb030f | 1848 | default: |
mzta | 0:158c61bb030f | 1849 | goto L_SEND; |
mzta | 0:158c61bb030f | 1850 | } |
mzta | 0:158c61bb030f | 1851 | NEXT; |
mzta | 0:158c61bb030f | 1852 | } |
mzta | 0:158c61bb030f | 1853 | |
mzta | 0:158c61bb030f | 1854 | CASE(OP_DIV) { |
mzta | 0:158c61bb030f | 1855 | /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ |
mzta | 0:158c61bb030f | 1856 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1857 | |
mzta | 0:158c61bb030f | 1858 | /* need to check if op is overridden */ |
mzta | 0:158c61bb030f | 1859 | switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { |
mzta | 0:158c61bb030f | 1860 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1861 | { |
mzta | 0:158c61bb030f | 1862 | mrb_int x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1863 | mrb_int y = mrb_fixnum(regs[a+1]); |
mzta | 0:158c61bb030f | 1864 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); |
mzta | 0:158c61bb030f | 1865 | } |
mzta | 0:158c61bb030f | 1866 | break; |
mzta | 0:158c61bb030f | 1867 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1868 | { |
mzta | 0:158c61bb030f | 1869 | mrb_int x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1870 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1871 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y); |
mzta | 0:158c61bb030f | 1872 | } |
mzta | 0:158c61bb030f | 1873 | break; |
mzta | 0:158c61bb030f | 1874 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
mzta | 0:158c61bb030f | 1875 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1876 | { |
mzta | 0:158c61bb030f | 1877 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1878 | mrb_int y = mrb_fixnum(regs[a+1]); |
mzta | 0:158c61bb030f | 1879 | SET_FLOAT_VALUE(mrb, regs[a], x / y); |
mzta | 0:158c61bb030f | 1880 | } |
mzta | 0:158c61bb030f | 1881 | #else |
mzta | 0:158c61bb030f | 1882 | OP_MATH_BODY(/,mrb_float,mrb_fixnum); |
mzta | 0:158c61bb030f | 1883 | #endif |
mzta | 0:158c61bb030f | 1884 | break; |
mzta | 0:158c61bb030f | 1885 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
mzta | 0:158c61bb030f | 1886 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1887 | { |
mzta | 0:158c61bb030f | 1888 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1889 | mrb_float y = mrb_float(regs[a+1]); |
mzta | 0:158c61bb030f | 1890 | SET_FLOAT_VALUE(mrb, regs[a], x / y); |
mzta | 0:158c61bb030f | 1891 | } |
mzta | 0:158c61bb030f | 1892 | #else |
mzta | 0:158c61bb030f | 1893 | OP_MATH_BODY(/,mrb_float,mrb_float); |
mzta | 0:158c61bb030f | 1894 | #endif |
mzta | 0:158c61bb030f | 1895 | break; |
mzta | 0:158c61bb030f | 1896 | default: |
mzta | 0:158c61bb030f | 1897 | goto L_SEND; |
mzta | 0:158c61bb030f | 1898 | } |
mzta | 0:158c61bb030f | 1899 | #ifdef MRB_NAN_BOXING |
mzta | 0:158c61bb030f | 1900 | if (isnan(mrb_float(regs[a]))) { |
mzta | 0:158c61bb030f | 1901 | regs[a] = mrb_float_value(mrb, mrb_float(regs[a])); |
mzta | 0:158c61bb030f | 1902 | } |
mzta | 0:158c61bb030f | 1903 | #endif |
mzta | 0:158c61bb030f | 1904 | NEXT; |
mzta | 0:158c61bb030f | 1905 | } |
mzta | 0:158c61bb030f | 1906 | |
mzta | 0:158c61bb030f | 1907 | CASE(OP_ADDI) { |
mzta | 0:158c61bb030f | 1908 | /* A B C R(A) := R(A)+C (Syms[B]=:+)*/ |
mzta | 0:158c61bb030f | 1909 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1910 | |
mzta | 0:158c61bb030f | 1911 | /* need to check if + is overridden */ |
mzta | 0:158c61bb030f | 1912 | switch (mrb_type(regs[a])) { |
mzta | 0:158c61bb030f | 1913 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 1914 | { |
mzta | 0:158c61bb030f | 1915 | mrb_int x = mrb_fixnum(regs[a]); |
mzta | 0:158c61bb030f | 1916 | mrb_int y = GETARG_C(i); |
mzta | 0:158c61bb030f | 1917 | mrb_int z; |
mzta | 0:158c61bb030f | 1918 | |
mzta | 0:158c61bb030f | 1919 | if (mrb_int_add_overflow(x, y, &z)) { |
mzta | 0:158c61bb030f | 1920 | SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y); |
mzta | 0:158c61bb030f | 1921 | break; |
mzta | 0:158c61bb030f | 1922 | } |
mzta | 0:158c61bb030f | 1923 | mrb_fixnum(regs[a]) = z; |
mzta | 0:158c61bb030f | 1924 | } |
mzta | 0:158c61bb030f | 1925 | break; |
mzta | 0:158c61bb030f | 1926 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 1927 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1928 | { |
mzta | 0:158c61bb030f | 1929 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1930 | SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i)); |
mzta | 0:158c61bb030f | 1931 | } |
mzta | 0:158c61bb030f | 1932 | #else |
mzta | 0:158c61bb030f | 1933 | mrb_float(regs[a]) += GETARG_C(i); |
mzta | 0:158c61bb030f | 1934 | #endif |
mzta | 0:158c61bb030f | 1935 | break; |
mzta | 0:158c61bb030f | 1936 | default: |
mzta | 0:158c61bb030f | 1937 | SET_INT_VALUE(regs[a+1], GETARG_C(i)); |
mzta | 0:158c61bb030f | 1938 | i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); |
mzta | 0:158c61bb030f | 1939 | goto L_SEND; |
mzta | 0:158c61bb030f | 1940 | } |
mzta | 0:158c61bb030f | 1941 | NEXT; |
mzta | 0:158c61bb030f | 1942 | } |
mzta | 0:158c61bb030f | 1943 | |
mzta | 0:158c61bb030f | 1944 | CASE(OP_SUBI) { |
mzta | 0:158c61bb030f | 1945 | /* A B C R(A) := R(A)-C (Syms[B]=:-)*/ |
mzta | 0:158c61bb030f | 1946 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 1947 | mrb_value *regs_a = regs + a; |
mzta | 0:158c61bb030f | 1948 | |
mzta | 0:158c61bb030f | 1949 | /* need to check if + is overridden */ |
mzta | 0:158c61bb030f | 1950 | switch (mrb_type(regs_a[0])) { |
mzta | 0:158c61bb030f | 1951 | case MRB_TT_FIXNUM: |
mzta | 0:158c61bb030f | 1952 | { |
mzta | 0:158c61bb030f | 1953 | mrb_int x = mrb_fixnum(regs_a[0]); |
mzta | 0:158c61bb030f | 1954 | mrb_int y = GETARG_C(i); |
mzta | 0:158c61bb030f | 1955 | mrb_int z; |
mzta | 0:158c61bb030f | 1956 | |
mzta | 0:158c61bb030f | 1957 | if (mrb_int_sub_overflow(x, y, &z)) { |
mzta | 0:158c61bb030f | 1958 | SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y); |
mzta | 0:158c61bb030f | 1959 | } |
mzta | 0:158c61bb030f | 1960 | else { |
mzta | 0:158c61bb030f | 1961 | mrb_fixnum(regs_a[0]) = z; |
mzta | 0:158c61bb030f | 1962 | } |
mzta | 0:158c61bb030f | 1963 | } |
mzta | 0:158c61bb030f | 1964 | break; |
mzta | 0:158c61bb030f | 1965 | case MRB_TT_FLOAT: |
mzta | 0:158c61bb030f | 1966 | #ifdef MRB_WORD_BOXING |
mzta | 0:158c61bb030f | 1967 | { |
mzta | 0:158c61bb030f | 1968 | mrb_float x = mrb_float(regs[a]); |
mzta | 0:158c61bb030f | 1969 | SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i)); |
mzta | 0:158c61bb030f | 1970 | } |
mzta | 0:158c61bb030f | 1971 | #else |
mzta | 0:158c61bb030f | 1972 | mrb_float(regs_a[0]) -= GETARG_C(i); |
mzta | 0:158c61bb030f | 1973 | #endif |
mzta | 0:158c61bb030f | 1974 | break; |
mzta | 0:158c61bb030f | 1975 | default: |
mzta | 0:158c61bb030f | 1976 | SET_INT_VALUE(regs_a[1], GETARG_C(i)); |
mzta | 0:158c61bb030f | 1977 | i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); |
mzta | 0:158c61bb030f | 1978 | goto L_SEND; |
mzta | 0:158c61bb030f | 1979 | } |
mzta | 0:158c61bb030f | 1980 | NEXT; |
mzta | 0:158c61bb030f | 1981 | } |
mzta | 0:158c61bb030f | 1982 | |
mzta | 0:158c61bb030f | 1983 | #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1])) |
mzta | 0:158c61bb030f | 1984 | |
mzta | 0:158c61bb030f | 1985 | #define OP_CMP(op) do {\ |
mzta | 0:158c61bb030f | 1986 | int result;\ |
mzta | 0:158c61bb030f | 1987 | /* need to check if - is overridden */\ |
mzta | 0:158c61bb030f | 1988 | switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ |
mzta | 0:158c61bb030f | 1989 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ |
mzta | 0:158c61bb030f | 1990 | result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ |
mzta | 0:158c61bb030f | 1991 | break;\ |
mzta | 0:158c61bb030f | 1992 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\ |
mzta | 0:158c61bb030f | 1993 | result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\ |
mzta | 0:158c61bb030f | 1994 | break;\ |
mzta | 0:158c61bb030f | 1995 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\ |
mzta | 0:158c61bb030f | 1996 | result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\ |
mzta | 0:158c61bb030f | 1997 | break;\ |
mzta | 0:158c61bb030f | 1998 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\ |
mzta | 0:158c61bb030f | 1999 | result = OP_CMP_BODY(op,mrb_float,mrb_float);\ |
mzta | 0:158c61bb030f | 2000 | break;\ |
mzta | 0:158c61bb030f | 2001 | default:\ |
mzta | 0:158c61bb030f | 2002 | goto L_SEND;\ |
mzta | 0:158c61bb030f | 2003 | }\ |
mzta | 0:158c61bb030f | 2004 | if (result) {\ |
mzta | 0:158c61bb030f | 2005 | SET_TRUE_VALUE(regs[a]);\ |
mzta | 0:158c61bb030f | 2006 | }\ |
mzta | 0:158c61bb030f | 2007 | else {\ |
mzta | 0:158c61bb030f | 2008 | SET_FALSE_VALUE(regs[a]);\ |
mzta | 0:158c61bb030f | 2009 | }\ |
mzta | 0:158c61bb030f | 2010 | } while(0) |
mzta | 0:158c61bb030f | 2011 | |
mzta | 0:158c61bb030f | 2012 | CASE(OP_EQ) { |
mzta | 0:158c61bb030f | 2013 | /* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/ |
mzta | 0:158c61bb030f | 2014 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2015 | if (mrb_obj_eq(mrb, regs[a], regs[a+1])) { |
mzta | 0:158c61bb030f | 2016 | SET_TRUE_VALUE(regs[a]); |
mzta | 0:158c61bb030f | 2017 | } |
mzta | 0:158c61bb030f | 2018 | else { |
mzta | 0:158c61bb030f | 2019 | OP_CMP(==); |
mzta | 0:158c61bb030f | 2020 | } |
mzta | 0:158c61bb030f | 2021 | NEXT; |
mzta | 0:158c61bb030f | 2022 | } |
mzta | 0:158c61bb030f | 2023 | |
mzta | 0:158c61bb030f | 2024 | CASE(OP_LT) { |
mzta | 0:158c61bb030f | 2025 | /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ |
mzta | 0:158c61bb030f | 2026 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2027 | OP_CMP(<); |
mzta | 0:158c61bb030f | 2028 | NEXT; |
mzta | 0:158c61bb030f | 2029 | } |
mzta | 0:158c61bb030f | 2030 | |
mzta | 0:158c61bb030f | 2031 | CASE(OP_LE) { |
mzta | 0:158c61bb030f | 2032 | /* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)*/ |
mzta | 0:158c61bb030f | 2033 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2034 | OP_CMP(<=); |
mzta | 0:158c61bb030f | 2035 | NEXT; |
mzta | 0:158c61bb030f | 2036 | } |
mzta | 0:158c61bb030f | 2037 | |
mzta | 0:158c61bb030f | 2038 | CASE(OP_GT) { |
mzta | 0:158c61bb030f | 2039 | /* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1)*/ |
mzta | 0:158c61bb030f | 2040 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2041 | OP_CMP(>); |
mzta | 0:158c61bb030f | 2042 | NEXT; |
mzta | 0:158c61bb030f | 2043 | } |
mzta | 0:158c61bb030f | 2044 | |
mzta | 0:158c61bb030f | 2045 | CASE(OP_GE) { |
mzta | 0:158c61bb030f | 2046 | /* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/ |
mzta | 0:158c61bb030f | 2047 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2048 | OP_CMP(>=); |
mzta | 0:158c61bb030f | 2049 | NEXT; |
mzta | 0:158c61bb030f | 2050 | } |
mzta | 0:158c61bb030f | 2051 | |
mzta | 0:158c61bb030f | 2052 | CASE(OP_ARRAY) { |
mzta | 0:158c61bb030f | 2053 | /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ |
mzta | 0:158c61bb030f | 2054 | regs[GETARG_A(i)] = mrb_ary_new_from_values(mrb, GETARG_C(i), ®s[GETARG_B(i)]); |
mzta | 0:158c61bb030f | 2055 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2056 | NEXT; |
mzta | 0:158c61bb030f | 2057 | } |
mzta | 0:158c61bb030f | 2058 | |
mzta | 0:158c61bb030f | 2059 | CASE(OP_ARYCAT) { |
mzta | 0:158c61bb030f | 2060 | /* A B mrb_ary_concat(R(A),R(B)) */ |
mzta | 0:158c61bb030f | 2061 | mrb_ary_concat(mrb, regs[GETARG_A(i)], |
mzta | 0:158c61bb030f | 2062 | mrb_ary_splat(mrb, regs[GETARG_B(i)])); |
mzta | 0:158c61bb030f | 2063 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2064 | NEXT; |
mzta | 0:158c61bb030f | 2065 | } |
mzta | 0:158c61bb030f | 2066 | |
mzta | 0:158c61bb030f | 2067 | CASE(OP_ARYPUSH) { |
mzta | 0:158c61bb030f | 2068 | /* A B R(A).push(R(B)) */ |
mzta | 0:158c61bb030f | 2069 | mrb_ary_push(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); |
mzta | 0:158c61bb030f | 2070 | NEXT; |
mzta | 0:158c61bb030f | 2071 | } |
mzta | 0:158c61bb030f | 2072 | |
mzta | 0:158c61bb030f | 2073 | CASE(OP_AREF) { |
mzta | 0:158c61bb030f | 2074 | /* A B C R(A) := R(B)[C] */ |
mzta | 0:158c61bb030f | 2075 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2076 | int c = GETARG_C(i); |
mzta | 0:158c61bb030f | 2077 | mrb_value v = regs[GETARG_B(i)]; |
mzta | 0:158c61bb030f | 2078 | |
mzta | 0:158c61bb030f | 2079 | if (!mrb_array_p(v)) { |
mzta | 0:158c61bb030f | 2080 | if (c == 0) { |
mzta | 0:158c61bb030f | 2081 | regs[GETARG_A(i)] = v; |
mzta | 0:158c61bb030f | 2082 | } |
mzta | 0:158c61bb030f | 2083 | else { |
mzta | 0:158c61bb030f | 2084 | SET_NIL_VALUE(regs[a]); |
mzta | 0:158c61bb030f | 2085 | } |
mzta | 0:158c61bb030f | 2086 | } |
mzta | 0:158c61bb030f | 2087 | else { |
mzta | 0:158c61bb030f | 2088 | regs[GETARG_A(i)] = mrb_ary_ref(mrb, v, c); |
mzta | 0:158c61bb030f | 2089 | } |
mzta | 0:158c61bb030f | 2090 | NEXT; |
mzta | 0:158c61bb030f | 2091 | } |
mzta | 0:158c61bb030f | 2092 | |
mzta | 0:158c61bb030f | 2093 | CASE(OP_ASET) { |
mzta | 0:158c61bb030f | 2094 | /* A B C R(B)[C] := R(A) */ |
mzta | 0:158c61bb030f | 2095 | mrb_ary_set(mrb, regs[GETARG_B(i)], GETARG_C(i), regs[GETARG_A(i)]); |
mzta | 0:158c61bb030f | 2096 | NEXT; |
mzta | 0:158c61bb030f | 2097 | } |
mzta | 0:158c61bb030f | 2098 | |
mzta | 0:158c61bb030f | 2099 | CASE(OP_APOST) { |
mzta | 0:158c61bb030f | 2100 | /* A B C *R(A),R(A+1)..R(A+C) := R(A) */ |
mzta | 0:158c61bb030f | 2101 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2102 | mrb_value v = regs[a]; |
mzta | 0:158c61bb030f | 2103 | int pre = GETARG_B(i); |
mzta | 0:158c61bb030f | 2104 | int post = GETARG_C(i); |
mzta | 0:158c61bb030f | 2105 | |
mzta | 0:158c61bb030f | 2106 | if (!mrb_array_p(v)) { |
mzta | 0:158c61bb030f | 2107 | regs[a++] = mrb_ary_new_capa(mrb, 0); |
mzta | 0:158c61bb030f | 2108 | while (post--) { |
mzta | 0:158c61bb030f | 2109 | SET_NIL_VALUE(regs[a]); |
mzta | 0:158c61bb030f | 2110 | a++; |
mzta | 0:158c61bb030f | 2111 | } |
mzta | 0:158c61bb030f | 2112 | } |
mzta | 0:158c61bb030f | 2113 | else { |
mzta | 0:158c61bb030f | 2114 | struct RArray *ary = mrb_ary_ptr(v); |
mzta | 0:158c61bb030f | 2115 | int len = ary->len; |
mzta | 0:158c61bb030f | 2116 | int idx; |
mzta | 0:158c61bb030f | 2117 | |
mzta | 0:158c61bb030f | 2118 | if (len > pre + post) { |
mzta | 0:158c61bb030f | 2119 | regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre); |
mzta | 0:158c61bb030f | 2120 | while (post--) { |
mzta | 0:158c61bb030f | 2121 | regs[a++] = ary->ptr[len-post-1]; |
mzta | 0:158c61bb030f | 2122 | } |
mzta | 0:158c61bb030f | 2123 | } |
mzta | 0:158c61bb030f | 2124 | else { |
mzta | 0:158c61bb030f | 2125 | regs[a++] = mrb_ary_new_capa(mrb, 0); |
mzta | 0:158c61bb030f | 2126 | for (idx=0; idx+pre<len; idx++) { |
mzta | 0:158c61bb030f | 2127 | regs[a+idx] = ary->ptr[pre+idx]; |
mzta | 0:158c61bb030f | 2128 | } |
mzta | 0:158c61bb030f | 2129 | while (idx < post) { |
mzta | 0:158c61bb030f | 2130 | SET_NIL_VALUE(regs[a+idx]); |
mzta | 0:158c61bb030f | 2131 | idx++; |
mzta | 0:158c61bb030f | 2132 | } |
mzta | 0:158c61bb030f | 2133 | } |
mzta | 0:158c61bb030f | 2134 | } |
mzta | 0:158c61bb030f | 2135 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2136 | NEXT; |
mzta | 0:158c61bb030f | 2137 | } |
mzta | 0:158c61bb030f | 2138 | |
mzta | 0:158c61bb030f | 2139 | CASE(OP_STRING) { |
mzta | 0:158c61bb030f | 2140 | /* A Bx R(A) := str_new(Lit(Bx)) */ |
mzta | 0:158c61bb030f | 2141 | regs[GETARG_A(i)] = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 2142 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2143 | NEXT; |
mzta | 0:158c61bb030f | 2144 | } |
mzta | 0:158c61bb030f | 2145 | |
mzta | 0:158c61bb030f | 2146 | CASE(OP_STRCAT) { |
mzta | 0:158c61bb030f | 2147 | /* A B R(A).concat(R(B)) */ |
mzta | 0:158c61bb030f | 2148 | mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); |
mzta | 0:158c61bb030f | 2149 | NEXT; |
mzta | 0:158c61bb030f | 2150 | } |
mzta | 0:158c61bb030f | 2151 | |
mzta | 0:158c61bb030f | 2152 | CASE(OP_HASH) { |
mzta | 0:158c61bb030f | 2153 | /* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ |
mzta | 0:158c61bb030f | 2154 | int b = GETARG_B(i); |
mzta | 0:158c61bb030f | 2155 | int c = GETARG_C(i); |
mzta | 0:158c61bb030f | 2156 | int lim = b+c*2; |
mzta | 0:158c61bb030f | 2157 | mrb_value hash = mrb_hash_new_capa(mrb, c); |
mzta | 0:158c61bb030f | 2158 | |
mzta | 0:158c61bb030f | 2159 | while (b < lim) { |
mzta | 0:158c61bb030f | 2160 | mrb_hash_set(mrb, hash, regs[b], regs[b+1]); |
mzta | 0:158c61bb030f | 2161 | b+=2; |
mzta | 0:158c61bb030f | 2162 | } |
mzta | 0:158c61bb030f | 2163 | regs[GETARG_A(i)] = hash; |
mzta | 0:158c61bb030f | 2164 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2165 | NEXT; |
mzta | 0:158c61bb030f | 2166 | } |
mzta | 0:158c61bb030f | 2167 | |
mzta | 0:158c61bb030f | 2168 | CASE(OP_LAMBDA) { |
mzta | 0:158c61bb030f | 2169 | /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */ |
mzta | 0:158c61bb030f | 2170 | struct RProc *p; |
mzta | 0:158c61bb030f | 2171 | int c = GETARG_c(i); |
mzta | 0:158c61bb030f | 2172 | |
mzta | 0:158c61bb030f | 2173 | if (c & OP_L_CAPTURE) { |
mzta | 0:158c61bb030f | 2174 | p = mrb_closure_new(mrb, irep->reps[GETARG_b(i)]); |
mzta | 0:158c61bb030f | 2175 | } |
mzta | 0:158c61bb030f | 2176 | else { |
mzta | 0:158c61bb030f | 2177 | p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]); |
mzta | 0:158c61bb030f | 2178 | if (c & OP_L_METHOD) { |
mzta | 0:158c61bb030f | 2179 | if (p->target_class->tt == MRB_TT_SCLASS) { |
mzta | 0:158c61bb030f | 2180 | mrb_value klass; |
mzta | 0:158c61bb030f | 2181 | klass = mrb_obj_iv_get(mrb, |
mzta | 0:158c61bb030f | 2182 | (struct RObject *)p->target_class, |
mzta | 0:158c61bb030f | 2183 | mrb_intern_lit(mrb, "__attached__")); |
mzta | 0:158c61bb030f | 2184 | p->target_class = mrb_class_ptr(klass); |
mzta | 0:158c61bb030f | 2185 | } |
mzta | 0:158c61bb030f | 2186 | } |
mzta | 0:158c61bb030f | 2187 | } |
mzta | 0:158c61bb030f | 2188 | if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; |
mzta | 0:158c61bb030f | 2189 | regs[GETARG_A(i)] = mrb_obj_value(p); |
mzta | 0:158c61bb030f | 2190 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2191 | NEXT; |
mzta | 0:158c61bb030f | 2192 | } |
mzta | 0:158c61bb030f | 2193 | |
mzta | 0:158c61bb030f | 2194 | CASE(OP_OCLASS) { |
mzta | 0:158c61bb030f | 2195 | /* A R(A) := ::Object */ |
mzta | 0:158c61bb030f | 2196 | regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class); |
mzta | 0:158c61bb030f | 2197 | NEXT; |
mzta | 0:158c61bb030f | 2198 | } |
mzta | 0:158c61bb030f | 2199 | |
mzta | 0:158c61bb030f | 2200 | CASE(OP_CLASS) { |
mzta | 0:158c61bb030f | 2201 | /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ |
mzta | 0:158c61bb030f | 2202 | struct RClass *c = 0; |
mzta | 0:158c61bb030f | 2203 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2204 | mrb_value base, super; |
mzta | 0:158c61bb030f | 2205 | mrb_sym id = syms[GETARG_B(i)]; |
mzta | 0:158c61bb030f | 2206 | |
mzta | 0:158c61bb030f | 2207 | base = regs[a]; |
mzta | 0:158c61bb030f | 2208 | super = regs[a+1]; |
mzta | 0:158c61bb030f | 2209 | if (mrb_nil_p(base)) { |
mzta | 0:158c61bb030f | 2210 | base = mrb_obj_value(mrb->c->ci->target_class); |
mzta | 0:158c61bb030f | 2211 | } |
mzta | 0:158c61bb030f | 2212 | c = mrb_vm_define_class(mrb, base, super, id); |
mzta | 0:158c61bb030f | 2213 | regs[a] = mrb_obj_value(c); |
mzta | 0:158c61bb030f | 2214 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2215 | NEXT; |
mzta | 0:158c61bb030f | 2216 | } |
mzta | 0:158c61bb030f | 2217 | |
mzta | 0:158c61bb030f | 2218 | CASE(OP_MODULE) { |
mzta | 0:158c61bb030f | 2219 | /* A B R(A) := newmodule(R(A),Syms(B)) */ |
mzta | 0:158c61bb030f | 2220 | struct RClass *c = 0; |
mzta | 0:158c61bb030f | 2221 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2222 | mrb_value base; |
mzta | 0:158c61bb030f | 2223 | mrb_sym id = syms[GETARG_B(i)]; |
mzta | 0:158c61bb030f | 2224 | |
mzta | 0:158c61bb030f | 2225 | base = regs[a]; |
mzta | 0:158c61bb030f | 2226 | if (mrb_nil_p(base)) { |
mzta | 0:158c61bb030f | 2227 | base = mrb_obj_value(mrb->c->ci->target_class); |
mzta | 0:158c61bb030f | 2228 | } |
mzta | 0:158c61bb030f | 2229 | c = mrb_vm_define_module(mrb, base, id); |
mzta | 0:158c61bb030f | 2230 | regs[a] = mrb_obj_value(c); |
mzta | 0:158c61bb030f | 2231 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2232 | NEXT; |
mzta | 0:158c61bb030f | 2233 | } |
mzta | 0:158c61bb030f | 2234 | |
mzta | 0:158c61bb030f | 2235 | CASE(OP_EXEC) { |
mzta | 0:158c61bb030f | 2236 | /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ |
mzta | 0:158c61bb030f | 2237 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2238 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 2239 | mrb_value recv = regs[a]; |
mzta | 0:158c61bb030f | 2240 | struct RProc *p; |
mzta | 0:158c61bb030f | 2241 | |
mzta | 0:158c61bb030f | 2242 | /* prepare stack */ |
mzta | 0:158c61bb030f | 2243 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 2244 | ci->pc = pc + 1; |
mzta | 0:158c61bb030f | 2245 | ci->acc = a; |
mzta | 0:158c61bb030f | 2246 | ci->mid = 0; |
mzta | 0:158c61bb030f | 2247 | ci->stackent = mrb->c->stack; |
mzta | 0:158c61bb030f | 2248 | ci->argc = 0; |
mzta | 0:158c61bb030f | 2249 | ci->target_class = mrb_class_ptr(recv); |
mzta | 0:158c61bb030f | 2250 | |
mzta | 0:158c61bb030f | 2251 | /* prepare stack */ |
mzta | 0:158c61bb030f | 2252 | mrb->c->stack += a; |
mzta | 0:158c61bb030f | 2253 | |
mzta | 0:158c61bb030f | 2254 | p = mrb_proc_new(mrb, irep->reps[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 2255 | p->target_class = ci->target_class; |
mzta | 0:158c61bb030f | 2256 | ci->proc = p; |
mzta | 0:158c61bb030f | 2257 | |
mzta | 0:158c61bb030f | 2258 | if (MRB_PROC_CFUNC_P(p)) { |
mzta | 0:158c61bb030f | 2259 | ci->nregs = 0; |
mzta | 0:158c61bb030f | 2260 | mrb->c->stack[0] = p->body.func(mrb, recv); |
mzta | 0:158c61bb030f | 2261 | mrb_gc_arena_restore(mrb, ai); |
mzta | 0:158c61bb030f | 2262 | if (mrb->exc) goto L_RAISE; |
mzta | 0:158c61bb030f | 2263 | /* pop stackpos */ |
mzta | 0:158c61bb030f | 2264 | regs = mrb->c->stack = mrb->c->ci->stackent; |
mzta | 0:158c61bb030f | 2265 | cipop(mrb); |
mzta | 0:158c61bb030f | 2266 | NEXT; |
mzta | 0:158c61bb030f | 2267 | } |
mzta | 0:158c61bb030f | 2268 | else { |
mzta | 0:158c61bb030f | 2269 | irep = p->body.irep; |
mzta | 0:158c61bb030f | 2270 | pool = irep->pool; |
mzta | 0:158c61bb030f | 2271 | syms = irep->syms; |
mzta | 0:158c61bb030f | 2272 | stack_extend(mrb, irep->nregs, 1); |
mzta | 0:158c61bb030f | 2273 | ci->nregs = irep->nregs; |
mzta | 0:158c61bb030f | 2274 | regs = mrb->c->stack; |
mzta | 0:158c61bb030f | 2275 | pc = irep->iseq; |
mzta | 0:158c61bb030f | 2276 | JUMP; |
mzta | 0:158c61bb030f | 2277 | } |
mzta | 0:158c61bb030f | 2278 | } |
mzta | 0:158c61bb030f | 2279 | |
mzta | 0:158c61bb030f | 2280 | CASE(OP_METHOD) { |
mzta | 0:158c61bb030f | 2281 | /* A B R(A).newmethod(Syms(B),R(A+1)) */ |
mzta | 0:158c61bb030f | 2282 | int a = GETARG_A(i); |
mzta | 0:158c61bb030f | 2283 | struct RClass *c = mrb_class_ptr(regs[a]); |
mzta | 0:158c61bb030f | 2284 | |
mzta | 0:158c61bb030f | 2285 | mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]); |
mzta | 0:158c61bb030f | 2286 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2287 | NEXT; |
mzta | 0:158c61bb030f | 2288 | } |
mzta | 0:158c61bb030f | 2289 | |
mzta | 0:158c61bb030f | 2290 | CASE(OP_SCLASS) { |
mzta | 0:158c61bb030f | 2291 | /* A B R(A) := R(B).singleton_class */ |
mzta | 0:158c61bb030f | 2292 | regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]); |
mzta | 0:158c61bb030f | 2293 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2294 | NEXT; |
mzta | 0:158c61bb030f | 2295 | } |
mzta | 0:158c61bb030f | 2296 | |
mzta | 0:158c61bb030f | 2297 | CASE(OP_TCLASS) { |
mzta | 0:158c61bb030f | 2298 | /* A R(A) := target_class */ |
mzta | 0:158c61bb030f | 2299 | if (!mrb->c->ci->target_class) { |
mzta | 0:158c61bb030f | 2300 | mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); |
mzta | 0:158c61bb030f | 2301 | mrb->exc = mrb_obj_ptr(exc); |
mzta | 0:158c61bb030f | 2302 | goto L_RAISE; |
mzta | 0:158c61bb030f | 2303 | } |
mzta | 0:158c61bb030f | 2304 | regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class); |
mzta | 0:158c61bb030f | 2305 | NEXT; |
mzta | 0:158c61bb030f | 2306 | } |
mzta | 0:158c61bb030f | 2307 | |
mzta | 0:158c61bb030f | 2308 | CASE(OP_RANGE) { |
mzta | 0:158c61bb030f | 2309 | /* A B C R(A) := range_new(R(B),R(B+1),C) */ |
mzta | 0:158c61bb030f | 2310 | int b = GETARG_B(i); |
mzta | 0:158c61bb030f | 2311 | regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); |
mzta | 0:158c61bb030f | 2312 | ARENA_RESTORE(mrb, ai); |
mzta | 0:158c61bb030f | 2313 | NEXT; |
mzta | 0:158c61bb030f | 2314 | } |
mzta | 0:158c61bb030f | 2315 | |
mzta | 0:158c61bb030f | 2316 | CASE(OP_DEBUG) { |
mzta | 0:158c61bb030f | 2317 | /* A B C debug print R(A),R(B),R(C) */ |
mzta | 0:158c61bb030f | 2318 | #ifdef ENABLE_DEBUG |
mzta | 0:158c61bb030f | 2319 | mrb->debug_op_hook(mrb, irep, pc, regs); |
mzta | 0:158c61bb030f | 2320 | #else |
mzta | 0:158c61bb030f | 2321 | #ifdef ENABLE_STDIO |
mzta | 0:158c61bb030f | 2322 | printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); |
mzta | 0:158c61bb030f | 2323 | #else |
mzta | 0:158c61bb030f | 2324 | abort(); |
mzta | 0:158c61bb030f | 2325 | #endif |
mzta | 0:158c61bb030f | 2326 | #endif |
mzta | 0:158c61bb030f | 2327 | NEXT; |
mzta | 0:158c61bb030f | 2328 | } |
mzta | 0:158c61bb030f | 2329 | |
mzta | 0:158c61bb030f | 2330 | CASE(OP_STOP) { |
mzta | 0:158c61bb030f | 2331 | /* stop VM */ |
mzta | 0:158c61bb030f | 2332 | L_STOP: |
mzta | 0:158c61bb030f | 2333 | { |
mzta | 0:158c61bb030f | 2334 | int eidx_stop = mrb->c->ci == mrb->c->cibase ? 0 : mrb->c->ci[-1].eidx; |
mzta | 0:158c61bb030f | 2335 | int eidx = mrb->c->ci->eidx; |
mzta | 0:158c61bb030f | 2336 | while (eidx > eidx_stop) { |
mzta | 0:158c61bb030f | 2337 | ecall(mrb, --eidx); |
mzta | 0:158c61bb030f | 2338 | } |
mzta | 0:158c61bb030f | 2339 | } |
mzta | 0:158c61bb030f | 2340 | ERR_PC_CLR(mrb); |
mzta | 0:158c61bb030f | 2341 | mrb->jmp = prev_jmp; |
mzta | 0:158c61bb030f | 2342 | if (mrb->exc) { |
mzta | 0:158c61bb030f | 2343 | return mrb_obj_value(mrb->exc); |
mzta | 0:158c61bb030f | 2344 | } |
mzta | 0:158c61bb030f | 2345 | return regs[irep->nlocals]; |
mzta | 0:158c61bb030f | 2346 | } |
mzta | 0:158c61bb030f | 2347 | |
mzta | 0:158c61bb030f | 2348 | CASE(OP_ERR) { |
mzta | 0:158c61bb030f | 2349 | /* Bx raise RuntimeError with message Lit(Bx) */ |
mzta | 0:158c61bb030f | 2350 | mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); |
mzta | 0:158c61bb030f | 2351 | mrb_value exc; |
mzta | 0:158c61bb030f | 2352 | |
mzta | 0:158c61bb030f | 2353 | if (GETARG_A(i) == 0) { |
mzta | 0:158c61bb030f | 2354 | exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg); |
mzta | 0:158c61bb030f | 2355 | } |
mzta | 0:158c61bb030f | 2356 | else { |
mzta | 0:158c61bb030f | 2357 | exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); |
mzta | 0:158c61bb030f | 2358 | } |
mzta | 0:158c61bb030f | 2359 | mrb->exc = mrb_obj_ptr(exc); |
mzta | 0:158c61bb030f | 2360 | goto L_RAISE; |
mzta | 0:158c61bb030f | 2361 | } |
mzta | 0:158c61bb030f | 2362 | } |
mzta | 0:158c61bb030f | 2363 | END_DISPATCH; |
mzta | 0:158c61bb030f | 2364 | |
mzta | 0:158c61bb030f | 2365 | } |
mzta | 0:158c61bb030f | 2366 | MRB_CATCH(&c_jmp) { |
mzta | 0:158c61bb030f | 2367 | exc_catched = TRUE; |
mzta | 0:158c61bb030f | 2368 | goto RETRY_TRY_BLOCK; |
mzta | 0:158c61bb030f | 2369 | } |
mzta | 0:158c61bb030f | 2370 | MRB_END_EXC(&c_jmp); |
mzta | 0:158c61bb030f | 2371 | } |
mzta | 0:158c61bb030f | 2372 | |
mzta | 0:158c61bb030f | 2373 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 2374 | mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) |
mzta | 0:158c61bb030f | 2375 | { |
mzta | 0:158c61bb030f | 2376 | return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ |
mzta | 0:158c61bb030f | 2377 | } |
mzta | 0:158c61bb030f | 2378 | |
mzta | 0:158c61bb030f | 2379 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 2380 | mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_keep) |
mzta | 0:158c61bb030f | 2381 | { |
mzta | 0:158c61bb030f | 2382 | mrb_callinfo *ci; |
mzta | 0:158c61bb030f | 2383 | mrb_value v; |
mzta | 0:158c61bb030f | 2384 | |
mzta | 0:158c61bb030f | 2385 | if (!mrb->c->cibase || mrb->c->ci == mrb->c->cibase) { |
mzta | 0:158c61bb030f | 2386 | return mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); |
mzta | 0:158c61bb030f | 2387 | } |
mzta | 0:158c61bb030f | 2388 | ci = cipush(mrb); |
mzta | 0:158c61bb030f | 2389 | ci->nregs = 1; /* protect the receiver */ |
mzta | 0:158c61bb030f | 2390 | ci->acc = CI_ACC_SKIP; |
mzta | 0:158c61bb030f | 2391 | ci->target_class = mrb->object_class; |
mzta | 0:158c61bb030f | 2392 | v = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); |
mzta | 0:158c61bb030f | 2393 | cipop(mrb); |
mzta | 0:158c61bb030f | 2394 | |
mzta | 0:158c61bb030f | 2395 | return v; |
mzta | 0:158c61bb030f | 2396 | } |
mzta | 0:158c61bb030f | 2397 | |
mzta | 0:158c61bb030f | 2398 | MRB_API mrb_value |
mzta | 0:158c61bb030f | 2399 | mrb_toplevel_run(mrb_state *mrb, struct RProc *proc) |
mzta | 0:158c61bb030f | 2400 | { |
mzta | 0:158c61bb030f | 2401 | return mrb_toplevel_run_keep(mrb, proc, 0); |
mzta | 0:158c61bb030f | 2402 | } |
mzta | 0:158c61bb030f | 2403 |