static int assignment (LexState *ls, struct LHS_assign *lh, int nvars, lu_byte *from_var) { expdesc e; int from = 0; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); from = assignment(ls, &nv, nvars+1, from_var); } else { /* assignment -> IN primaryexp | `=' explist1 */ int nexps; if (testnext(ls, TK_IN)) { new_localvarliteral(ls, "(from)", 0); primaryexp(ls, &e); luaK_exp2nextreg(ls->fs, &e); *from_var = ls->fs->nactvar; adjustlocalvars(ls, 1); luaK_setoneret(ls->fs, &e); /* close last expression */ getfrom(ls, &e, &lh->v); luaK_storevar(ls->fs, &lh->v, &e); return 1; /* avoid default */ } else { checknext(ls, '='); nexps = explist1(ls, &e); } if (nexps == nvars) { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return 0; /* avoid default */ } else { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ if (from) getfrom(ls, &e, &lh->v); luaK_storevar(ls->fs, &lh->v, &e); return from; }
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist1 */ int nexps; checknext(ls, '='); nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); }
/* ** Ensure that expression 'e' is not a variable. */ void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { /* already in a register */ e->k = VNONRELOC; /* becomes a non-relocatable value */ break; } case VUPVAL: { /* move value to some (pending) register */ e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; break; } case VINDEXED: { OpCode op; freereg(fs, e->u.ind.idx); if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ freereg(fs, e->u.ind.t); op = OP_GETTABLE; } else { lua_assert(e->u.ind.vt == VUPVAL); op = OP_GETTABUP; /* 't' is in an upvalue */ } e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; break; } case VUPVAL: { e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); e->k = VRELOCABLE; break; } case VGLOBAL: { e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); e->k = VRELOCABLE; break; } case VINDEXED: { freereg(fs, e->u.s.aux); freereg(fs, e->u.s.info); e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; break; } case VUPVAL: { e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; break; } case VINDEXED: { OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e->u.ind.idx); if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ freereg(fs, e->u.ind.t); op = OP_GETTABLE; } e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; DEBUG_EXPR(raviY_printf(fs, "luaK_dischargevars (VLOCAL->VNONRELOC) %e\n", e)); break; } case VUPVAL: { e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); e->k = VRELOCABLE; DEBUG_EXPR(raviY_printf(fs, "luaK_dischargevars (VUPVAL->VRELOCABLE) %e\n", e)); break; } case VINDEXED: { OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e->u.ind.idx); if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ freereg(fs, e->u.ind.t); /* TODO we should do this for upvalues too */ /* table access - set specialized op codes if array types are detected */ if (e->ravi_type == RAVI_TARRAYFLT && e->u.ind.key_type == RAVI_TNUMINT) op = OP_RAVI_GETTABLE_AF; else if (e->ravi_type == RAVI_TARRAYINT && e->u.ind.key_type == RAVI_TNUMINT) op = OP_RAVI_GETTABLE_AI; /* Check that we have a short string constant */ else if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx)) op = OP_RAVI_GETTABLE_S; else if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_type == RAVI_TNUMINT) op = OP_RAVI_GETTABLE_I; else op = OP_GETTABLE; if (e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TARRAYINT) /* set the type of resulting expression */ e->ravi_type = e->ravi_type == RAVI_TARRAYFLT ? RAVI_TNUMFLT : RAVI_TNUMINT; else e->ravi_type = RAVI_TANY; } e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; DEBUG_EXPR(raviY_printf(fs, "luaK_dischargevars (VINDEXED->VRELOCABLE) %e\n", e)); break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } }
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars, BinOpr *opr) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); assignment(ls, &nv, nvars+1, opr); } else { /* assignment -> `=' explist1 */ int nexps; *opr = OPR_NOBINOPR; switch(ls->t.token) { case '=': break; case TK_CONCATASSIGN: *opr = OPR_CONCAT; break; case TK_ADDASSIGN: *opr = OPR_ADD; break; case TK_SUBASSIGN: *opr = OPR_SUB; break; case TK_MULASSIGN: *opr = OPR_MUL; break; case TK_DIVASSIGN: *opr = OPR_DIV; break; case TK_POWASSIGN: *opr = OPR_POW; break; case TK_MODASSIGN: *opr = OPR_MOD; break; default: luaX_syntaxerror(ls, "unexpected symbol"); break; }; luaX_next(ls); nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e, *opr); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e, *opr); }
static void localstat (LexState *ls) { /* stat -> LOCAL NAME {`,' NAME} [ IN primaryexp | `=' explist1] */ int nvars = 0; int nexps; expdesc e; do { new_localvar(ls, str_checkname(ls), nvars++); } while (testnext(ls, ',')); if (testnext(ls, TK_IN)) { lu_byte from_var; int regs = ls->fs->freereg; int vars = ls->fs->nactvar; luaK_reserveregs(ls->fs, nvars); adjustlocalvars(ls, nvars); new_localvarliteral(ls, "(from)", 0); primaryexp(ls, &e); luaK_exp2nextreg(ls->fs, &e); from_var = ls->fs->nactvar; adjustlocalvars(ls, 1); luaK_setoneret(ls->fs, &e); /* close last expression */ for (nexps=0; nexps<nvars; nexps++) { expdesc v, key; init_exp(&e, VNONRELOC, ls->fs->freereg-1); codestring(ls, &key, getlocvar(ls->fs, vars+nexps).varname); luaK_indexed(ls->fs, &e, &key); init_exp(&v, VLOCAL, regs+nexps); luaK_storevar(ls->fs, &v, &e); } removevars(ls, from_var); return; } if (testnext(ls, '=')) nexps = explist1(ls, &e); else { e.k = VVOID; nexps = 0; } adjust_assign(ls, nvars, nexps, &e); adjustlocalvars(ls, nvars); }
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist1 */ int nexps; /* hook for inc_assignment */ if(nvars==1) { switch(ls->t.token) { case '+': case '-': case '*': case '/': case TK_CONCAT: inc_assignment(ls,lh); /* If you're using Shook's table unpack patch, return 0 here.*/ return; } } checknext(ls, '='); nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); }
static void inc_assignment(LexState *ls, struct LHS_assign *lh) { BinOpr op = getbinopr(ls->t.token); FuncState * fs=ls->fs; expdesc e, v2; /* reserve all registers needed by the lvalue */ luaK_reserveregs(fs,fs->freereg-fs->nactvar); luaX_next(ls); checknext(ls, '='); enterlevel(ls); e = lh->v; luaK_infix(fs,op,&e); /* we only match one expr(), not a full explist(), so "a+=2,2" will be a parse error. */ expr(ls,&v2); luaK_posfix(fs, op, &e, &v2); leavelevel(ls); luaK_exp2nextreg(fs,&e); luaK_setoneret(ls->fs, &e); luaK_storevar(ls->fs, &lh->v, &e); }
static void changevalue (LexState *ls, int op) { FuncState *fs = ls->fs; expdesc v, e1, e2; testnext(ls, '('); primaryexp(ls, &v); e1 = v; if (v.k == VINDEXED) luaK_reserveregs(fs, 1); /* <- this call solved the problem with indexed values */ if (testnext(ls, ',')) { luaK_exp2nextreg(fs, &e1); /* <- this call solved the problem with indexed values, 0.32.0 */ expr(ls, &e2); } else { /* using special opcodes is not faster */ init_exp(&e2, VKNUM, 0); e2.u.nval = (lua_Integer)1; } testnext(ls, ')'); codearith(fs, op, &e1, &e2); luaK_setoneret(fs, &e1); /* close last expression */ luaK_storevar(fs, &v, &e1); }
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist1 */ int nexps; #if LUA_MUTATION_OPERATORS luaX_next(ls); /* consume `=' token. */ #else checknext(ls, '='); #endif /* LUA_MUTATION_OPERATORS */ nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); }