int exp2RK(expdesc e) { this.exp2val(e); switch (e.k) { case LexState.VTRUE: case LexState.VFALSE: case LexState.VNIL: { if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */ e.u.info = (e.k == LexState.VNIL) ? this.nilK() : this.boolK((e.k == LexState.VTRUE)); e.k = LexState.VK; return RKASK(e.u.info); } else break; } case LexState.VKNUM: { e.u.info = this.numberK(e.u.nval()); e.k = LexState.VK; /* go through */ } case LexState.VK: { if (e.u.info <= MAXINDEXRK) /* constant fit in argC? */ return RKASK(e.u.info); else break; } default: break; } /* not a constant in the right range: put it in a register */ return this.exp2anyreg(e); }
void setoneret(expdesc e) { if (e.k == LexState.VCALL) { /* expression is an open function call? */ e.k = LexState.VNONRELOC; e.u.info = GETARG_A(this.getcode(e)); } else if (e.k == LexState.VVARARG) { SETARG_B(this.getcodePtr(e), 2); e.k = LexState.VRELOCABLE; /* can relocate its simple result */ } }
void indexed(expdesc t, expdesc k) { t.u.ind_t = (short) t.u.info; t.u.ind_idx = (short) this.exp2RK(k); LuaC._assert(t.k == LexState.VUPVAL || vkisinreg(t.k)); t.u.ind_vt = (short) ((t.k == LexState.VUPVAL) ? LexState.VUPVAL : LexState.VLOCAL); t.k = LexState.VINDEXED; }
void codenot(expdesc e) { this.dischargevars(e); switch (e.k) { case LexState.VNIL: case LexState.VFALSE: { e.k = LexState.VTRUE; break; } case LexState.VK: case LexState.VKNUM: case LexState.VTRUE: { e.k = LexState.VFALSE; break; } case LexState.VJMP: { this.invertjump(e); break; } case LexState.VRELOCABLE: case LexState.VNONRELOC: { this.discharge2anyreg(e); this.freeexp(e); e.u.info = this.codeABC(OP_NOT, 0, e.u.info, 0); e.k = LexState.VRELOCABLE; break; } default: { _assert(false); /* cannot happen */ break; } } /* interchange true and false lists */ { int temp = e.f.i; e.f.i = e.t.i; e.t.i = temp; } this.removevalues(e.f.i); this.removevalues(e.t.i); }
void self(expdesc e, expdesc key) { int func; this.exp2anyreg(e); this.freeexp(e); func = this.freereg; this.reserveregs(2); this.codeABC(OP_SELF, func, e.u.info, this.exp2RK(key)); this.freeexp(key); e.u.info = func; e.k = LexState.VNONRELOC; }
void codecomp(int /* OpCode */ op, int cond, expdesc e1, expdesc e2) { int o1 = this.exp2RK(e1); int o2 = this.exp2RK(e2); this.freeexp(e2); this.freeexp(e1); if (cond == 0 && op != OP_EQ) { int temp; /* exchange args to replace by `<' or `<=' */ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ cond = 1; } e1.u.info = this.condjump(op, cond, o1, o2); e1.k = LexState.VJMP; }
void dischargevars(expdesc e) { switch (e.k) { case LexState.VLOCAL: { e.k = LexState.VNONRELOC; break; } case LexState.VUPVAL: { e.u.info = this.codeABC(OP_GETUPVAL, 0, e.u.info, 0); e.k = LexState.VRELOCABLE; break; } case LexState.VINDEXED: { int op = OP_GETTABUP; /* assume 't' is in an upvalue */ this.freereg(e.u.ind_idx); if (e.u.ind_vt == LexState.VLOCAL) { /* 't' is in a register? */ this.freereg(e.u.ind_t); op = OP_GETTABLE; } e.u.info = this.codeABC(op, 0, e.u.ind_t, e.u.ind_idx); e.k = LexState.VRELOCABLE; break; } case LexState.VVARARG: case LexState.VCALL: { this.setoneret(e); break; } default: break; /* there is one value available (somewhere) */ } }
void codearith(int op, expdesc e1, expdesc e2, int line) { if (constfolding(op, e1, e2)) return; else { int o2 = (op != OP_UNM && op != OP_LEN) ? this.exp2RK(e2) : 0; int o1 = this.exp2RK(e1); if (o1 > o2) { this.freeexp(e1); this.freeexp(e2); } else { this.freeexp(e2); this.freeexp(e1); } e1.u.info = this.codeABC(op, 0, o1, o2); e1.k = LexState.VRELOCABLE; fixline(line); } }
void discharge2reg(expdesc e, int reg) { this.dischargevars(e); switch (e.k) { case LexState.VNIL: { this.nil(reg, 1); break; } case LexState.VFALSE: case LexState.VTRUE: { this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE ? 1 : 0), 0); break; } case LexState.VK: { this.codeABx(OP_LOADK, reg, e.u.info); break; } case LexState.VKNUM: { this.codeABx(OP_LOADK, reg, this.numberK(e.u.nval())); break; } case LexState.VRELOCABLE: { InstructionPtr pc = this.getcodePtr(e); SETARG_A(pc, reg); break; } case LexState.VNONRELOC: { if (reg != e.u.info) this.codeABC(OP_MOVE, reg, e.u.info, 0); break; } default: { _assert(e.k == LexState.VVOID || e.k == LexState.VJMP); return; /* nothing to do... */ } } e.u.info = reg; e.k = LexState.VNONRELOC; }
void exp2reg(expdesc e, int reg) { this.discharge2reg(e, reg); if (e.k == LexState.VJMP) this.concat(e.t, e.u.info); /* put this jump in `t' list */ if (e.hasjumps()) { int _final; /* position after whole expression */ int p_f = LexState.NO_JUMP; /* position of an eventual LOAD false */ int p_t = LexState.NO_JUMP; /* position of an eventual LOAD true */ if (this.need_value(e.t.i) || this.need_value(e.f.i)) { int fj = (e.k == LexState.VJMP) ? LexState.NO_JUMP : this.jump(); p_f = this.code_label(reg, 0, 1); p_t = this.code_label(reg, 1, 0); this.patchtohere(fj); } _final = this.getlabel(); this.patchlistaux(e.f.i, _final, reg, p_f); this.patchlistaux(e.t.i, _final, reg, p_t); } e.f.i = e.t.i = LexState.NO_JUMP; e.u.info = reg; e.k = LexState.VNONRELOC; }
void posfix(int op, expdesc e1, expdesc e2, int line) { switch (op) { case LexState.OPR_AND: { _assert(e1.t.i == LexState.NO_JUMP); /* list must be closed */ this.dischargevars(e2); this.concat(e2.f, e1.f.i); // *e1 = *e2; e1.setvalue(e2); break; } case LexState.OPR_OR: { _assert(e1.f.i == LexState.NO_JUMP); /* list must be closed */ this.dischargevars(e2); this.concat(e2.t, e1.t.i); // *e1 = *e2; e1.setvalue(e2); break; } case LexState.OPR_CONCAT: { this.exp2val(e2); if (e2.k == LexState.VRELOCABLE && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) { _assert(e1.u.info == GETARG_B(this.getcode(e2)) - 1); this.freeexp(e1); SETARG_B(this.getcodePtr(e2), e1.u.info); e1.k = LexState.VRELOCABLE; e1.u.info = e2.u.info; } else { this.exp2nextreg(e2); /* operand must be on the 'stack' */ this.codearith(OP_CONCAT, e1, e2, line); } break; } case LexState.OPR_ADD: this.codearith(OP_ADD, e1, e2, line); break; case LexState.OPR_SUB: this.codearith(OP_SUB, e1, e2, line); break; case LexState.OPR_MUL: this.codearith(OP_MUL, e1, e2, line); break; case LexState.OPR_DIV: this.codearith(OP_DIV, e1, e2, line); break; case LexState.OPR_MOD: this.codearith(OP_MOD, e1, e2, line); break; case LexState.OPR_POW: this.codearith(OP_POW, e1, e2, line); break; case LexState.OPR_EQ: this.codecomp(OP_EQ, 1, e1, e2); break; case LexState.OPR_NE: this.codecomp(OP_EQ, 0, e1, e2); break; case LexState.OPR_LT: this.codecomp(OP_LT, 1, e1, e2); break; case LexState.OPR_LE: this.codecomp(OP_LE, 1, e1, e2); break; case LexState.OPR_GT: this.codecomp(OP_LT, 0, e1, e2); break; case LexState.OPR_GE: this.codecomp(OP_LE, 0, e1, e2); break; default: _assert(false); } }