void op_for(void) { Var idx, list; idx = pop(); list = pop(); if( list.type == MAP) { list.v.list = map_keys( list.v.map ); list.type = LIST; } if( list.type == STR) { list.v.list = string_list( list.v.str ); list.type = LIST; } if (list.type != LIST) { var_free(list); raise(E_FOR); } else if (idx.v.num >= list.v.list->len) { /* loop is complete */ var_free(list); frame.pc = frame.m->code[frame.pc + 1]; /* skip to end */ } else { var_assign_local(frame.stack, frame.m->code[frame.pc], var_dup(list.v.list->el[idx.v.num])); idx.v.num++; push(list); /* push list */ push(idx); /* push new index */ pushpc(frame.pc - 1); /* push address of FOR statement */ frame.pc += 2; /* go to first instruction in loop */ } }
void op_continue(void) { Var newpc; int break_lvl = frame.m->code[frame.pc++]; while (break_lvl--) { do { newpc = pop(); var_free(newpc); } while (newpc.type != PC || newpc.v.num < 0); } if (frame.m->code[newpc.v.num] == DOWHILE) { pushpc(newpc.v.num); frame.pc = frame.m->code[newpc.v.num + 2]; } else { frame.pc = newpc.v.num; /* all the others push their own PC */ } }
void op_forrng(void) { Var v, upper; upper = pop(); v = pop(); if (v.type != NUM || upper.type != NUM) { var_free(upper); var_free(v); raise(E_TYPE); } else if (v.v.num > upper.v.num) { frame.pc = frame.m->code[frame.pc + 1]; } else { var_assign_local(frame.stack, frame.m->code[frame.pc], v); v.v.num++; push(v); push(upper); pushpc(frame.pc - 1); frame.pc += 2; } }
void op_do(void) { pushpc(frame.m->code[frame.pc++]); }
void op_argstart(void) { pushpc(-ARGSTART); }
void op_pushpc(void) { pushpc(frame.pc - 1); }
static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ const Instruction *code = pt->code; int top = pt->numparams; int pc = 0; if (pt->is_vararg) /* varargs? */ top++; /* `arg' */ while (pc < lastpc) { const Instruction i = code[pc++]; LUA_ASSERT(0 <= top && top <= pt->maxstacksize, "wrong stack"); switch (GET_OPCODE(i)) { case OP_RETURN: { LUA_ASSERT(top >= GETARG_U(i), "wrong stack"); top = GETARG_U(i); break; } case OP_TAILCALL: { LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); top = GETARG_B(i); break; } case OP_CALL: { int nresults = GETARG_B(i); if (nresults == MULT_RET) nresults = 1; LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); top = pushpc(stack, pc, GETARG_A(i), nresults); break; } case OP_PUSHNIL: { top = pushpc(stack, pc, top, GETARG_U(i)); break; } case OP_POP: { top -= GETARG_U(i); break; } case OP_SETTABLE: case OP_SETLIST: { top -= GETARG_B(i); break; } case OP_SETMAP: { top -= 2*GETARG_U(i); break; } case OP_CONCAT: { top -= GETARG_U(i); stack[top++] = pc-1; break; } case OP_CLOSURE: { top -= GETARG_B(i); stack[top++] = pc-1; break; } case OP_JMPONT: case OP_JMPONF: { int newpc = pc + GETARG_S(i); /* jump is forward and do not skip `lastpc'? */ if (pc < newpc && newpc <= lastpc) { stack[top-1] = pc-1; /* value comes from `and'/`or' */ pc = newpc; /* do the jump */ } else top--; /* do not jump; pop value */ break; } default: { OpCode op = GET_OPCODE(i); LUA_ASSERT(luaK_opproperties[op].push != VD, "invalid opcode for default"); top -= luaK_opproperties[op].pop; LUA_ASSERT(top >= 0, "wrong stack"); top = pushpc(stack, pc, top, luaK_opproperties[op].push); } } } return code[stack[stackpos]]; }