--- lparser.c (lua 5.2.2) +++ lparser.c (working copy) @@ -1094,7 +1094,7 @@ ** assignment */ struct LHS_assign { - struct LHS_assign *prev; + struct LHS_assign *prev, *next; expdesc v; /* variable (global, local, upvalue, or indexed) */ }; @@ -1132,22 +1132,138 @@ } } +enum { + NORMAL_ASSIGNMENT, + COMPOUND_ASSIGNMENT +}; -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + +static int compound_assignment(LexState *ls, struct LHS_assign *lh, int nvars) { + BinOpr op = getbinopr(ls->t.token); + FuncState * fs=ls->fs; + int tolevel=fs->nactvar; + int old_free=fs->freereg; + expdesc e,infix; + double inc=0; + int nexps=0,i; + int line=ls->linenumber; + struct LHS_assign * assign=lh; + while(assign->prev) assign=assign->prev; + luaX_next(ls); + + { /* create temporary local variables to lock up any registers needed + by VINDEXED lvalues. */ + lu_byte top=fs->nactvar; + struct LHS_assign * a = lh; + int nextra; + while(a) { + expdesc * v= &a->v; + /* protect both the table and index result registers, + ** ensuring that they won't be overwritten prior to the + ** storevar calls. */ + if(v->k==VINDEXED) { + if( !ISK( v->u.ind.t ) && v->u.ind.t>= top) { + top= v->u.ind.t+1; + } + if( !ISK( v->u.ind.idx ) && v->u.ind.idx>= top) { + top= v->u.ind.idx+1; + } + } + a=a->prev; + } + nextra=top-fs->nactvar; + if(nextra) { + for(i=0;i
v; + luaK_infix(fs,op,&infix); + luaK_posfix(fs, op, &infix, &e, line); + luaK_storevar(fs, &assign->v, &infix); + assign=assign->next; + } + goto done; + } + checknext(ls, '='); + do { + if(!assign) { + luaX_syntaxerror(ls,"too many right hand side values in compound assignment"); + } + infix=assign->v; + luaK_infix(fs,op,&infix); + expr(ls, &e); + if(ls->t.token == ',') { + luaK_posfix(fs, op, &infix, &e, line); + luaK_storevar(fs, &assign->v, &infix); + assign=assign->next; + nexps++; + } + } while (testnext(ls, ',')); + + if(nexps+1==nvars ) { + luaK_posfix(fs, op, &infix, &e, line); + luaK_storevar(fs, &lh->v, &infix); + } else if( hasmultret(e.k) ) { + adjust_assign(ls, nvars-nexps, 1, &e); + assign=lh; + { + int top=ls->fs->freereg-1; + int first_top=top; + for(i=0;i
v; + luaK_infix(fs,op,&infix); + + init_exp(&e, VNONRELOC, top--); + luaK_posfix(fs, op, &infix, &e, line); + luaK_storevar(fs, &assign->v, &infix); + assign=assign->prev; + } + } + } else { + luaX_syntaxerror(ls,"insufficient right hand variables in compound assignment."); + } + + done: + removevars(fs,tolevel); + if(old_free
freereg) { + fs->freereg=old_free; + } + return COMPOUND_ASSIGNMENT; +} + +static int assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; + int assignment_type = NORMAL_ASSIGNMENT; check_condition(ls, vkisvar(lh->v.k), "syntax error"); if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ struct LHS_assign nv; nv.prev = lh; + nv.next = NULL; + lh->next = &nv; suffixedexp(ls, &nv.v); if (nv.v.k != VINDEXED) check_conflict(ls, lh, &nv.v); checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, "C levels"); - assignment(ls, &nv, nvars+1); + assignment_type=assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist */ int nexps; + switch(ls->t.token) { + /* hook for compound_assignment */ + case '+': case '-': case '*': case '/': case TK_CONCAT: + return compound_assignment(ls,lh,nvars); + } checknext(ls, '='); nexps = explist(ls, &e); if (nexps != nvars) { @@ -1158,11 +1274,13 @@ else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ + return assignment_type; /* avoid default */ } } + if(assignment_type==COMPOUND_ASSIGNMENT) return assignment_type; init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); + return assignment_type; } @@ -1482,14 +1600,12 @@ FuncState *fs = ls->fs; struct LHS_assign v; suffixedexp(ls, &v.v); - if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ - v.prev = NULL; + if (v.v.k == VCALL) + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + else { /* stat -> assignment ? */ + v.prev = v.next = NULL; assignment(ls, &v, 1); } - else { /* stat -> func */ - check_condition(ls, v.v.k == VCALL, "syntax error"); - SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ - } }
AltStyle
によって変換されたページ
(->オリジナル)
/
アドレス:
モード:
デフォルト
音声ブラウザ
ルビ付き
配色反転
文字拡大
モバイル