18e3e3a7aSWarner Losh /* 2e112e9d2SKyle Evans ** $Id: lparser.c,v 2.155.1.2 2017/04/29 18:11:40 roberto Exp $ 38e3e3a7aSWarner Losh ** Lua Parser 48e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 58e3e3a7aSWarner Losh */ 68e3e3a7aSWarner Losh 78e3e3a7aSWarner Losh #define lparser_c 88e3e3a7aSWarner Losh #define LUA_CORE 98e3e3a7aSWarner Losh 108e3e3a7aSWarner Losh #include "lprefix.h" 118e3e3a7aSWarner Losh 128e3e3a7aSWarner Losh 138e3e3a7aSWarner Losh #include <string.h> 148e3e3a7aSWarner Losh 158e3e3a7aSWarner Losh #include "lua.h" 168e3e3a7aSWarner Losh 178e3e3a7aSWarner Losh #include "lcode.h" 188e3e3a7aSWarner Losh #include "ldebug.h" 198e3e3a7aSWarner Losh #include "ldo.h" 208e3e3a7aSWarner Losh #include "lfunc.h" 218e3e3a7aSWarner Losh #include "llex.h" 228e3e3a7aSWarner Losh #include "lmem.h" 238e3e3a7aSWarner Losh #include "lobject.h" 248e3e3a7aSWarner Losh #include "lopcodes.h" 258e3e3a7aSWarner Losh #include "lparser.h" 268e3e3a7aSWarner Losh #include "lstate.h" 278e3e3a7aSWarner Losh #include "lstring.h" 288e3e3a7aSWarner Losh #include "ltable.h" 298e3e3a7aSWarner Losh 308e3e3a7aSWarner Losh 318e3e3a7aSWarner Losh 328e3e3a7aSWarner Losh /* maximum number of local variables per function (must be smaller 338e3e3a7aSWarner Losh than 250, due to the bytecode format) */ 348e3e3a7aSWarner Losh #define MAXVARS 200 358e3e3a7aSWarner Losh 368e3e3a7aSWarner Losh 378e3e3a7aSWarner Losh #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) 388e3e3a7aSWarner Losh 398e3e3a7aSWarner Losh 408e3e3a7aSWarner Losh /* because all strings are unified by the scanner, the parser 418e3e3a7aSWarner Losh can use pointer equality for string equality */ 428e3e3a7aSWarner Losh #define eqstr(a,b) ((a) == (b)) 438e3e3a7aSWarner Losh 448e3e3a7aSWarner Losh 458e3e3a7aSWarner Losh /* 468e3e3a7aSWarner Losh ** nodes for block list (list of active blocks) 478e3e3a7aSWarner Losh */ 488e3e3a7aSWarner Losh typedef struct BlockCnt { 498e3e3a7aSWarner Losh struct BlockCnt *previous; /* chain */ 508e3e3a7aSWarner Losh int firstlabel; /* index of first label in this block */ 518e3e3a7aSWarner Losh int firstgoto; /* index of first pending goto in this block */ 528e3e3a7aSWarner Losh lu_byte nactvar; /* # active locals outside the block */ 538e3e3a7aSWarner Losh lu_byte upval; /* true if some variable in the block is an upvalue */ 548e3e3a7aSWarner Losh lu_byte isloop; /* true if 'block' is a loop */ 558e3e3a7aSWarner Losh } BlockCnt; 568e3e3a7aSWarner Losh 578e3e3a7aSWarner Losh 588e3e3a7aSWarner Losh 598e3e3a7aSWarner Losh /* 608e3e3a7aSWarner Losh ** prototypes for recursive non-terminal functions 618e3e3a7aSWarner Losh */ 628e3e3a7aSWarner Losh static void statement (LexState *ls); 638e3e3a7aSWarner Losh static void expr (LexState *ls, expdesc *v); 648e3e3a7aSWarner Losh 658e3e3a7aSWarner Losh 668e3e3a7aSWarner Losh /* semantic error */ 678e3e3a7aSWarner Losh static l_noret semerror (LexState *ls, const char *msg) { 688e3e3a7aSWarner Losh ls->t.token = 0; /* remove "near <token>" from final message */ 698e3e3a7aSWarner Losh luaX_syntaxerror(ls, msg); 708e3e3a7aSWarner Losh } 718e3e3a7aSWarner Losh 728e3e3a7aSWarner Losh 738e3e3a7aSWarner Losh static l_noret error_expected (LexState *ls, int token) { 748e3e3a7aSWarner Losh luaX_syntaxerror(ls, 758e3e3a7aSWarner Losh luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); 768e3e3a7aSWarner Losh } 778e3e3a7aSWarner Losh 788e3e3a7aSWarner Losh 798e3e3a7aSWarner Losh static l_noret errorlimit (FuncState *fs, int limit, const char *what) { 808e3e3a7aSWarner Losh lua_State *L = fs->ls->L; 818e3e3a7aSWarner Losh const char *msg; 828e3e3a7aSWarner Losh int line = fs->f->linedefined; 838e3e3a7aSWarner Losh const char *where = (line == 0) 848e3e3a7aSWarner Losh ? "main function" 858e3e3a7aSWarner Losh : luaO_pushfstring(L, "function at line %d", line); 868e3e3a7aSWarner Losh msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", 878e3e3a7aSWarner Losh what, limit, where); 888e3e3a7aSWarner Losh luaX_syntaxerror(fs->ls, msg); 898e3e3a7aSWarner Losh } 908e3e3a7aSWarner Losh 918e3e3a7aSWarner Losh 928e3e3a7aSWarner Losh static void checklimit (FuncState *fs, int v, int l, const char *what) { 938e3e3a7aSWarner Losh if (v > l) errorlimit(fs, l, what); 948e3e3a7aSWarner Losh } 958e3e3a7aSWarner Losh 968e3e3a7aSWarner Losh 978e3e3a7aSWarner Losh static int testnext (LexState *ls, int c) { 988e3e3a7aSWarner Losh if (ls->t.token == c) { 998e3e3a7aSWarner Losh luaX_next(ls); 1008e3e3a7aSWarner Losh return 1; 1018e3e3a7aSWarner Losh } 1028e3e3a7aSWarner Losh else return 0; 1038e3e3a7aSWarner Losh } 1048e3e3a7aSWarner Losh 1058e3e3a7aSWarner Losh 1068e3e3a7aSWarner Losh static void check (LexState *ls, int c) { 1078e3e3a7aSWarner Losh if (ls->t.token != c) 1088e3e3a7aSWarner Losh error_expected(ls, c); 1098e3e3a7aSWarner Losh } 1108e3e3a7aSWarner Losh 1118e3e3a7aSWarner Losh 1128e3e3a7aSWarner Losh static void checknext (LexState *ls, int c) { 1138e3e3a7aSWarner Losh check(ls, c); 1148e3e3a7aSWarner Losh luaX_next(ls); 1158e3e3a7aSWarner Losh } 1168e3e3a7aSWarner Losh 1178e3e3a7aSWarner Losh 1188e3e3a7aSWarner Losh #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } 1198e3e3a7aSWarner Losh 1208e3e3a7aSWarner Losh 1218e3e3a7aSWarner Losh 1228e3e3a7aSWarner Losh static void check_match (LexState *ls, int what, int who, int where) { 1238e3e3a7aSWarner Losh if (!testnext(ls, what)) { 1248e3e3a7aSWarner Losh if (where == ls->linenumber) 1258e3e3a7aSWarner Losh error_expected(ls, what); 1268e3e3a7aSWarner Losh else { 1278e3e3a7aSWarner Losh luaX_syntaxerror(ls, luaO_pushfstring(ls->L, 1288e3e3a7aSWarner Losh "%s expected (to close %s at line %d)", 1298e3e3a7aSWarner Losh luaX_token2str(ls, what), luaX_token2str(ls, who), where)); 1308e3e3a7aSWarner Losh } 1318e3e3a7aSWarner Losh } 1328e3e3a7aSWarner Losh } 1338e3e3a7aSWarner Losh 1348e3e3a7aSWarner Losh 1358e3e3a7aSWarner Losh static TString *str_checkname (LexState *ls) { 1368e3e3a7aSWarner Losh TString *ts; 1378e3e3a7aSWarner Losh check(ls, TK_NAME); 1388e3e3a7aSWarner Losh ts = ls->t.seminfo.ts; 1398e3e3a7aSWarner Losh luaX_next(ls); 1408e3e3a7aSWarner Losh return ts; 1418e3e3a7aSWarner Losh } 1428e3e3a7aSWarner Losh 1438e3e3a7aSWarner Losh 1448e3e3a7aSWarner Losh static void init_exp (expdesc *e, expkind k, int i) { 1458e3e3a7aSWarner Losh e->f = e->t = NO_JUMP; 1468e3e3a7aSWarner Losh e->k = k; 1478e3e3a7aSWarner Losh e->u.info = i; 1488e3e3a7aSWarner Losh } 1498e3e3a7aSWarner Losh 1508e3e3a7aSWarner Losh 1518e3e3a7aSWarner Losh static void codestring (LexState *ls, expdesc *e, TString *s) { 1528e3e3a7aSWarner Losh init_exp(e, VK, luaK_stringK(ls->fs, s)); 1538e3e3a7aSWarner Losh } 1548e3e3a7aSWarner Losh 1558e3e3a7aSWarner Losh 1568e3e3a7aSWarner Losh static void checkname (LexState *ls, expdesc *e) { 1578e3e3a7aSWarner Losh codestring(ls, e, str_checkname(ls)); 1588e3e3a7aSWarner Losh } 1598e3e3a7aSWarner Losh 1608e3e3a7aSWarner Losh 1618e3e3a7aSWarner Losh static int registerlocalvar (LexState *ls, TString *varname) { 1628e3e3a7aSWarner Losh FuncState *fs = ls->fs; 1638e3e3a7aSWarner Losh Proto *f = fs->f; 1648e3e3a7aSWarner Losh int oldsize = f->sizelocvars; 1658e3e3a7aSWarner Losh luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, 1668e3e3a7aSWarner Losh LocVar, SHRT_MAX, "local variables"); 1678e3e3a7aSWarner Losh while (oldsize < f->sizelocvars) 1688e3e3a7aSWarner Losh f->locvars[oldsize++].varname = NULL; 1698e3e3a7aSWarner Losh f->locvars[fs->nlocvars].varname = varname; 1708e3e3a7aSWarner Losh luaC_objbarrier(ls->L, f, varname); 1718e3e3a7aSWarner Losh return fs->nlocvars++; 1728e3e3a7aSWarner Losh } 1738e3e3a7aSWarner Losh 1748e3e3a7aSWarner Losh 1758e3e3a7aSWarner Losh static void new_localvar (LexState *ls, TString *name) { 1768e3e3a7aSWarner Losh FuncState *fs = ls->fs; 1778e3e3a7aSWarner Losh Dyndata *dyd = ls->dyd; 1788e3e3a7aSWarner Losh int reg = registerlocalvar(ls, name); 1798e3e3a7aSWarner Losh checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, 1808e3e3a7aSWarner Losh MAXVARS, "local variables"); 1818e3e3a7aSWarner Losh luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, 1828e3e3a7aSWarner Losh dyd->actvar.size, Vardesc, MAX_INT, "local variables"); 1838e3e3a7aSWarner Losh dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); 1848e3e3a7aSWarner Losh } 1858e3e3a7aSWarner Losh 1868e3e3a7aSWarner Losh 1878e3e3a7aSWarner Losh static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { 1888e3e3a7aSWarner Losh new_localvar(ls, luaX_newstring(ls, name, sz)); 1898e3e3a7aSWarner Losh } 1908e3e3a7aSWarner Losh 1918e3e3a7aSWarner Losh #define new_localvarliteral(ls,v) \ 1928e3e3a7aSWarner Losh new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) 1938e3e3a7aSWarner Losh 1948e3e3a7aSWarner Losh 1958e3e3a7aSWarner Losh static LocVar *getlocvar (FuncState *fs, int i) { 1968e3e3a7aSWarner Losh int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; 1978e3e3a7aSWarner Losh lua_assert(idx < fs->nlocvars); 1988e3e3a7aSWarner Losh return &fs->f->locvars[idx]; 1998e3e3a7aSWarner Losh } 2008e3e3a7aSWarner Losh 2018e3e3a7aSWarner Losh 2028e3e3a7aSWarner Losh static void adjustlocalvars (LexState *ls, int nvars) { 2038e3e3a7aSWarner Losh FuncState *fs = ls->fs; 2048e3e3a7aSWarner Losh fs->nactvar = cast_byte(fs->nactvar + nvars); 2058e3e3a7aSWarner Losh for (; nvars; nvars--) { 2068e3e3a7aSWarner Losh getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; 2078e3e3a7aSWarner Losh } 2088e3e3a7aSWarner Losh } 2098e3e3a7aSWarner Losh 2108e3e3a7aSWarner Losh 2118e3e3a7aSWarner Losh static void removevars (FuncState *fs, int tolevel) { 2128e3e3a7aSWarner Losh fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); 2138e3e3a7aSWarner Losh while (fs->nactvar > tolevel) 2148e3e3a7aSWarner Losh getlocvar(fs, --fs->nactvar)->endpc = fs->pc; 2158e3e3a7aSWarner Losh } 2168e3e3a7aSWarner Losh 2178e3e3a7aSWarner Losh 2188e3e3a7aSWarner Losh static int searchupvalue (FuncState *fs, TString *name) { 2198e3e3a7aSWarner Losh int i; 2208e3e3a7aSWarner Losh Upvaldesc *up = fs->f->upvalues; 2218e3e3a7aSWarner Losh for (i = 0; i < fs->nups; i++) { 2228e3e3a7aSWarner Losh if (eqstr(up[i].name, name)) return i; 2238e3e3a7aSWarner Losh } 2248e3e3a7aSWarner Losh return -1; /* not found */ 2258e3e3a7aSWarner Losh } 2268e3e3a7aSWarner Losh 2278e3e3a7aSWarner Losh 2288e3e3a7aSWarner Losh static int newupvalue (FuncState *fs, TString *name, expdesc *v) { 2298e3e3a7aSWarner Losh Proto *f = fs->f; 2308e3e3a7aSWarner Losh int oldsize = f->sizeupvalues; 2318e3e3a7aSWarner Losh checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); 2328e3e3a7aSWarner Losh luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, 2338e3e3a7aSWarner Losh Upvaldesc, MAXUPVAL, "upvalues"); 2348e3e3a7aSWarner Losh while (oldsize < f->sizeupvalues) 2358e3e3a7aSWarner Losh f->upvalues[oldsize++].name = NULL; 2368e3e3a7aSWarner Losh f->upvalues[fs->nups].instack = (v->k == VLOCAL); 2378e3e3a7aSWarner Losh f->upvalues[fs->nups].idx = cast_byte(v->u.info); 2388e3e3a7aSWarner Losh f->upvalues[fs->nups].name = name; 2398e3e3a7aSWarner Losh luaC_objbarrier(fs->ls->L, f, name); 2408e3e3a7aSWarner Losh return fs->nups++; 2418e3e3a7aSWarner Losh } 2428e3e3a7aSWarner Losh 2438e3e3a7aSWarner Losh 2448e3e3a7aSWarner Losh static int searchvar (FuncState *fs, TString *n) { 2458e3e3a7aSWarner Losh int i; 2468e3e3a7aSWarner Losh for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { 2478e3e3a7aSWarner Losh if (eqstr(n, getlocvar(fs, i)->varname)) 2488e3e3a7aSWarner Losh return i; 2498e3e3a7aSWarner Losh } 2508e3e3a7aSWarner Losh return -1; /* not found */ 2518e3e3a7aSWarner Losh } 2528e3e3a7aSWarner Losh 2538e3e3a7aSWarner Losh 2548e3e3a7aSWarner Losh /* 2558e3e3a7aSWarner Losh Mark block where variable at given level was defined 2568e3e3a7aSWarner Losh (to emit close instructions later). 2578e3e3a7aSWarner Losh */ 2588e3e3a7aSWarner Losh static void markupval (FuncState *fs, int level) { 2598e3e3a7aSWarner Losh BlockCnt *bl = fs->bl; 2608e3e3a7aSWarner Losh while (bl->nactvar > level) 2618e3e3a7aSWarner Losh bl = bl->previous; 2628e3e3a7aSWarner Losh bl->upval = 1; 2638e3e3a7aSWarner Losh } 2648e3e3a7aSWarner Losh 2658e3e3a7aSWarner Losh 2668e3e3a7aSWarner Losh /* 2678e3e3a7aSWarner Losh Find variable with given name 'n'. If it is an upvalue, add this 2688e3e3a7aSWarner Losh upvalue into all intermediate functions. 2698e3e3a7aSWarner Losh */ 2708e3e3a7aSWarner Losh static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { 2718e3e3a7aSWarner Losh if (fs == NULL) /* no more levels? */ 2728e3e3a7aSWarner Losh init_exp(var, VVOID, 0); /* default is global */ 2738e3e3a7aSWarner Losh else { 2748e3e3a7aSWarner Losh int v = searchvar(fs, n); /* look up locals at current level */ 2758e3e3a7aSWarner Losh if (v >= 0) { /* found? */ 2768e3e3a7aSWarner Losh init_exp(var, VLOCAL, v); /* variable is local */ 2778e3e3a7aSWarner Losh if (!base) 2788e3e3a7aSWarner Losh markupval(fs, v); /* local will be used as an upval */ 2798e3e3a7aSWarner Losh } 2808e3e3a7aSWarner Losh else { /* not found as local at current level; try upvalues */ 2818e3e3a7aSWarner Losh int idx = searchupvalue(fs, n); /* try existing upvalues */ 2828e3e3a7aSWarner Losh if (idx < 0) { /* not found? */ 2838e3e3a7aSWarner Losh singlevaraux(fs->prev, n, var, 0); /* try upper levels */ 2848e3e3a7aSWarner Losh if (var->k == VVOID) /* not found? */ 2858e3e3a7aSWarner Losh return; /* it is a global */ 2868e3e3a7aSWarner Losh /* else was LOCAL or UPVAL */ 2878e3e3a7aSWarner Losh idx = newupvalue(fs, n, var); /* will be a new upvalue */ 2888e3e3a7aSWarner Losh } 2898e3e3a7aSWarner Losh init_exp(var, VUPVAL, idx); /* new or old upvalue */ 2908e3e3a7aSWarner Losh } 2918e3e3a7aSWarner Losh } 2928e3e3a7aSWarner Losh } 2938e3e3a7aSWarner Losh 2948e3e3a7aSWarner Losh 2958e3e3a7aSWarner Losh static void singlevar (LexState *ls, expdesc *var) { 2968e3e3a7aSWarner Losh TString *varname = str_checkname(ls); 2978e3e3a7aSWarner Losh FuncState *fs = ls->fs; 2988e3e3a7aSWarner Losh singlevaraux(fs, varname, var, 1); 2998e3e3a7aSWarner Losh if (var->k == VVOID) { /* global name? */ 3008e3e3a7aSWarner Losh expdesc key; 3018e3e3a7aSWarner Losh singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ 3028e3e3a7aSWarner Losh lua_assert(var->k != VVOID); /* this one must exist */ 3038e3e3a7aSWarner Losh codestring(ls, &key, varname); /* key is variable name */ 3048e3e3a7aSWarner Losh luaK_indexed(fs, var, &key); /* env[varname] */ 3058e3e3a7aSWarner Losh } 3068e3e3a7aSWarner Losh } 3078e3e3a7aSWarner Losh 3088e3e3a7aSWarner Losh 3098e3e3a7aSWarner Losh static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { 3108e3e3a7aSWarner Losh FuncState *fs = ls->fs; 3118e3e3a7aSWarner Losh int extra = nvars - nexps; 3128e3e3a7aSWarner Losh if (hasmultret(e->k)) { 3138e3e3a7aSWarner Losh extra++; /* includes call itself */ 3148e3e3a7aSWarner Losh if (extra < 0) extra = 0; 3158e3e3a7aSWarner Losh luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ 3168e3e3a7aSWarner Losh if (extra > 1) luaK_reserveregs(fs, extra-1); 3178e3e3a7aSWarner Losh } 3188e3e3a7aSWarner Losh else { 3198e3e3a7aSWarner Losh if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ 3208e3e3a7aSWarner Losh if (extra > 0) { 3218e3e3a7aSWarner Losh int reg = fs->freereg; 3228e3e3a7aSWarner Losh luaK_reserveregs(fs, extra); 3238e3e3a7aSWarner Losh luaK_nil(fs, reg, extra); 3248e3e3a7aSWarner Losh } 3258e3e3a7aSWarner Losh } 3268e3e3a7aSWarner Losh if (nexps > nvars) 3278e3e3a7aSWarner Losh ls->fs->freereg -= nexps - nvars; /* remove extra values */ 3288e3e3a7aSWarner Losh } 3298e3e3a7aSWarner Losh 3308e3e3a7aSWarner Losh 3318e3e3a7aSWarner Losh static void enterlevel (LexState *ls) { 3328e3e3a7aSWarner Losh lua_State *L = ls->L; 3338e3e3a7aSWarner Losh ++L->nCcalls; 3348e3e3a7aSWarner Losh checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); 3358e3e3a7aSWarner Losh } 3368e3e3a7aSWarner Losh 3378e3e3a7aSWarner Losh 3388e3e3a7aSWarner Losh #define leavelevel(ls) ((ls)->L->nCcalls--) 3398e3e3a7aSWarner Losh 3408e3e3a7aSWarner Losh 3418e3e3a7aSWarner Losh static void closegoto (LexState *ls, int g, Labeldesc *label) { 3428e3e3a7aSWarner Losh int i; 3438e3e3a7aSWarner Losh FuncState *fs = ls->fs; 3448e3e3a7aSWarner Losh Labellist *gl = &ls->dyd->gt; 3458e3e3a7aSWarner Losh Labeldesc *gt = &gl->arr[g]; 3468e3e3a7aSWarner Losh lua_assert(eqstr(gt->name, label->name)); 3478e3e3a7aSWarner Losh if (gt->nactvar < label->nactvar) { 3488e3e3a7aSWarner Losh TString *vname = getlocvar(fs, gt->nactvar)->varname; 3498e3e3a7aSWarner Losh const char *msg = luaO_pushfstring(ls->L, 3508e3e3a7aSWarner Losh "<goto %s> at line %d jumps into the scope of local '%s'", 3518e3e3a7aSWarner Losh getstr(gt->name), gt->line, getstr(vname)); 3528e3e3a7aSWarner Losh semerror(ls, msg); 3538e3e3a7aSWarner Losh } 3548e3e3a7aSWarner Losh luaK_patchlist(fs, gt->pc, label->pc); 3558e3e3a7aSWarner Losh /* remove goto from pending list */ 3568e3e3a7aSWarner Losh for (i = g; i < gl->n - 1; i++) 3578e3e3a7aSWarner Losh gl->arr[i] = gl->arr[i + 1]; 3588e3e3a7aSWarner Losh gl->n--; 3598e3e3a7aSWarner Losh } 3608e3e3a7aSWarner Losh 3618e3e3a7aSWarner Losh 3628e3e3a7aSWarner Losh /* 3638e3e3a7aSWarner Losh ** try to close a goto with existing labels; this solves backward jumps 3648e3e3a7aSWarner Losh */ 3658e3e3a7aSWarner Losh static int findlabel (LexState *ls, int g) { 3668e3e3a7aSWarner Losh int i; 3678e3e3a7aSWarner Losh BlockCnt *bl = ls->fs->bl; 3688e3e3a7aSWarner Losh Dyndata *dyd = ls->dyd; 3698e3e3a7aSWarner Losh Labeldesc *gt = &dyd->gt.arr[g]; 3708e3e3a7aSWarner Losh /* check labels in current block for a match */ 3718e3e3a7aSWarner Losh for (i = bl->firstlabel; i < dyd->label.n; i++) { 3728e3e3a7aSWarner Losh Labeldesc *lb = &dyd->label.arr[i]; 3738e3e3a7aSWarner Losh if (eqstr(lb->name, gt->name)) { /* correct label? */ 3748e3e3a7aSWarner Losh if (gt->nactvar > lb->nactvar && 3758e3e3a7aSWarner Losh (bl->upval || dyd->label.n > bl->firstlabel)) 3768e3e3a7aSWarner Losh luaK_patchclose(ls->fs, gt->pc, lb->nactvar); 3778e3e3a7aSWarner Losh closegoto(ls, g, lb); /* close it */ 3788e3e3a7aSWarner Losh return 1; 3798e3e3a7aSWarner Losh } 3808e3e3a7aSWarner Losh } 3818e3e3a7aSWarner Losh return 0; /* label not found; cannot close goto */ 3828e3e3a7aSWarner Losh } 3838e3e3a7aSWarner Losh 3848e3e3a7aSWarner Losh 3858e3e3a7aSWarner Losh static int newlabelentry (LexState *ls, Labellist *l, TString *name, 3868e3e3a7aSWarner Losh int line, int pc) { 3878e3e3a7aSWarner Losh int n = l->n; 3888e3e3a7aSWarner Losh luaM_growvector(ls->L, l->arr, n, l->size, 3898e3e3a7aSWarner Losh Labeldesc, SHRT_MAX, "labels/gotos"); 3908e3e3a7aSWarner Losh l->arr[n].name = name; 3918e3e3a7aSWarner Losh l->arr[n].line = line; 3928e3e3a7aSWarner Losh l->arr[n].nactvar = ls->fs->nactvar; 3938e3e3a7aSWarner Losh l->arr[n].pc = pc; 3948e3e3a7aSWarner Losh l->n = n + 1; 3958e3e3a7aSWarner Losh return n; 3968e3e3a7aSWarner Losh } 3978e3e3a7aSWarner Losh 3988e3e3a7aSWarner Losh 3998e3e3a7aSWarner Losh /* 4008e3e3a7aSWarner Losh ** check whether new label 'lb' matches any pending gotos in current 4018e3e3a7aSWarner Losh ** block; solves forward jumps 4028e3e3a7aSWarner Losh */ 4038e3e3a7aSWarner Losh static void findgotos (LexState *ls, Labeldesc *lb) { 4048e3e3a7aSWarner Losh Labellist *gl = &ls->dyd->gt; 4058e3e3a7aSWarner Losh int i = ls->fs->bl->firstgoto; 4068e3e3a7aSWarner Losh while (i < gl->n) { 4078e3e3a7aSWarner Losh if (eqstr(gl->arr[i].name, lb->name)) 4088e3e3a7aSWarner Losh closegoto(ls, i, lb); 4098e3e3a7aSWarner Losh else 4108e3e3a7aSWarner Losh i++; 4118e3e3a7aSWarner Losh } 4128e3e3a7aSWarner Losh } 4138e3e3a7aSWarner Losh 4148e3e3a7aSWarner Losh 4158e3e3a7aSWarner Losh /* 4168e3e3a7aSWarner Losh ** export pending gotos to outer level, to check them against 4178e3e3a7aSWarner Losh ** outer labels; if the block being exited has upvalues, and 4188e3e3a7aSWarner Losh ** the goto exits the scope of any variable (which can be the 4198e3e3a7aSWarner Losh ** upvalue), close those variables being exited. 4208e3e3a7aSWarner Losh */ 4218e3e3a7aSWarner Losh static void movegotosout (FuncState *fs, BlockCnt *bl) { 4228e3e3a7aSWarner Losh int i = bl->firstgoto; 4238e3e3a7aSWarner Losh Labellist *gl = &fs->ls->dyd->gt; 4248e3e3a7aSWarner Losh /* correct pending gotos to current block and try to close it 4258e3e3a7aSWarner Losh with visible labels */ 4268e3e3a7aSWarner Losh while (i < gl->n) { 4278e3e3a7aSWarner Losh Labeldesc *gt = &gl->arr[i]; 4288e3e3a7aSWarner Losh if (gt->nactvar > bl->nactvar) { 4298e3e3a7aSWarner Losh if (bl->upval) 4308e3e3a7aSWarner Losh luaK_patchclose(fs, gt->pc, bl->nactvar); 4318e3e3a7aSWarner Losh gt->nactvar = bl->nactvar; 4328e3e3a7aSWarner Losh } 4338e3e3a7aSWarner Losh if (!findlabel(fs->ls, i)) 4348e3e3a7aSWarner Losh i++; /* move to next one */ 4358e3e3a7aSWarner Losh } 4368e3e3a7aSWarner Losh } 4378e3e3a7aSWarner Losh 4388e3e3a7aSWarner Losh 4398e3e3a7aSWarner Losh static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { 4408e3e3a7aSWarner Losh bl->isloop = isloop; 4418e3e3a7aSWarner Losh bl->nactvar = fs->nactvar; 4428e3e3a7aSWarner Losh bl->firstlabel = fs->ls->dyd->label.n; 4438e3e3a7aSWarner Losh bl->firstgoto = fs->ls->dyd->gt.n; 4448e3e3a7aSWarner Losh bl->upval = 0; 4458e3e3a7aSWarner Losh bl->previous = fs->bl; 4468e3e3a7aSWarner Losh fs->bl = bl; 4478e3e3a7aSWarner Losh lua_assert(fs->freereg == fs->nactvar); 4488e3e3a7aSWarner Losh } 4498e3e3a7aSWarner Losh 4508e3e3a7aSWarner Losh 4518e3e3a7aSWarner Losh /* 4528e3e3a7aSWarner Losh ** create a label named 'break' to resolve break statements 4538e3e3a7aSWarner Losh */ 4548e3e3a7aSWarner Losh static void breaklabel (LexState *ls) { 4558e3e3a7aSWarner Losh TString *n = luaS_new(ls->L, "break"); 4568e3e3a7aSWarner Losh int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); 4578e3e3a7aSWarner Losh findgotos(ls, &ls->dyd->label.arr[l]); 4588e3e3a7aSWarner Losh } 4598e3e3a7aSWarner Losh 4608e3e3a7aSWarner Losh /* 4618e3e3a7aSWarner Losh ** generates an error for an undefined 'goto'; choose appropriate 4628e3e3a7aSWarner Losh ** message when label name is a reserved word (which can only be 'break') 4638e3e3a7aSWarner Losh */ 4648e3e3a7aSWarner Losh static l_noret undefgoto (LexState *ls, Labeldesc *gt) { 4658e3e3a7aSWarner Losh const char *msg = isreserved(gt->name) 4668e3e3a7aSWarner Losh ? "<%s> at line %d not inside a loop" 4678e3e3a7aSWarner Losh : "no visible label '%s' for <goto> at line %d"; 4688e3e3a7aSWarner Losh msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); 4698e3e3a7aSWarner Losh semerror(ls, msg); 4708e3e3a7aSWarner Losh } 4718e3e3a7aSWarner Losh 4728e3e3a7aSWarner Losh 4738e3e3a7aSWarner Losh static void leaveblock (FuncState *fs) { 4748e3e3a7aSWarner Losh BlockCnt *bl = fs->bl; 4758e3e3a7aSWarner Losh LexState *ls = fs->ls; 4768e3e3a7aSWarner Losh if (bl->previous && bl->upval) { 4778e3e3a7aSWarner Losh /* create a 'jump to here' to close upvalues */ 4788e3e3a7aSWarner Losh int j = luaK_jump(fs); 4798e3e3a7aSWarner Losh luaK_patchclose(fs, j, bl->nactvar); 4808e3e3a7aSWarner Losh luaK_patchtohere(fs, j); 4818e3e3a7aSWarner Losh } 4828e3e3a7aSWarner Losh if (bl->isloop) 4838e3e3a7aSWarner Losh breaklabel(ls); /* close pending breaks */ 4848e3e3a7aSWarner Losh fs->bl = bl->previous; 4858e3e3a7aSWarner Losh removevars(fs, bl->nactvar); 4868e3e3a7aSWarner Losh lua_assert(bl->nactvar == fs->nactvar); 4878e3e3a7aSWarner Losh fs->freereg = fs->nactvar; /* free registers */ 4888e3e3a7aSWarner Losh ls->dyd->label.n = bl->firstlabel; /* remove local labels */ 4898e3e3a7aSWarner Losh if (bl->previous) /* inner block? */ 4908e3e3a7aSWarner Losh movegotosout(fs, bl); /* update pending gotos to outer block */ 4918e3e3a7aSWarner Losh else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ 4928e3e3a7aSWarner Losh undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ 4938e3e3a7aSWarner Losh } 4948e3e3a7aSWarner Losh 4958e3e3a7aSWarner Losh 4968e3e3a7aSWarner Losh /* 4978e3e3a7aSWarner Losh ** adds a new prototype into list of prototypes 4988e3e3a7aSWarner Losh */ 4998e3e3a7aSWarner Losh static Proto *addprototype (LexState *ls) { 5008e3e3a7aSWarner Losh Proto *clp; 5018e3e3a7aSWarner Losh lua_State *L = ls->L; 5028e3e3a7aSWarner Losh FuncState *fs = ls->fs; 5038e3e3a7aSWarner Losh Proto *f = fs->f; /* prototype of current function */ 5048e3e3a7aSWarner Losh if (fs->np >= f->sizep) { 5058e3e3a7aSWarner Losh int oldsize = f->sizep; 5068e3e3a7aSWarner Losh luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); 5078e3e3a7aSWarner Losh while (oldsize < f->sizep) 5088e3e3a7aSWarner Losh f->p[oldsize++] = NULL; 5098e3e3a7aSWarner Losh } 5108e3e3a7aSWarner Losh f->p[fs->np++] = clp = luaF_newproto(L); 5118e3e3a7aSWarner Losh luaC_objbarrier(L, f, clp); 5128e3e3a7aSWarner Losh return clp; 5138e3e3a7aSWarner Losh } 5148e3e3a7aSWarner Losh 5158e3e3a7aSWarner Losh 5168e3e3a7aSWarner Losh /* 5178e3e3a7aSWarner Losh ** codes instruction to create new closure in parent function. 5188e3e3a7aSWarner Losh ** The OP_CLOSURE instruction must use the last available register, 5198e3e3a7aSWarner Losh ** so that, if it invokes the GC, the GC knows which registers 5208e3e3a7aSWarner Losh ** are in use at that time. 5218e3e3a7aSWarner Losh */ 5228e3e3a7aSWarner Losh static void codeclosure (LexState *ls, expdesc *v) { 5238e3e3a7aSWarner Losh FuncState *fs = ls->fs->prev; 5248e3e3a7aSWarner Losh init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); 5258e3e3a7aSWarner Losh luaK_exp2nextreg(fs, v); /* fix it at the last register */ 5268e3e3a7aSWarner Losh } 5278e3e3a7aSWarner Losh 5288e3e3a7aSWarner Losh 5298e3e3a7aSWarner Losh static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { 5308e3e3a7aSWarner Losh Proto *f; 5318e3e3a7aSWarner Losh fs->prev = ls->fs; /* linked list of funcstates */ 5328e3e3a7aSWarner Losh fs->ls = ls; 5338e3e3a7aSWarner Losh ls->fs = fs; 5348e3e3a7aSWarner Losh fs->pc = 0; 5358e3e3a7aSWarner Losh fs->lasttarget = 0; 5368e3e3a7aSWarner Losh fs->jpc = NO_JUMP; 5378e3e3a7aSWarner Losh fs->freereg = 0; 5388e3e3a7aSWarner Losh fs->nk = 0; 5398e3e3a7aSWarner Losh fs->np = 0; 5408e3e3a7aSWarner Losh fs->nups = 0; 5418e3e3a7aSWarner Losh fs->nlocvars = 0; 5428e3e3a7aSWarner Losh fs->nactvar = 0; 5438e3e3a7aSWarner Losh fs->firstlocal = ls->dyd->actvar.n; 5448e3e3a7aSWarner Losh fs->bl = NULL; 5458e3e3a7aSWarner Losh f = fs->f; 5468e3e3a7aSWarner Losh f->source = ls->source; 547*bf9580a1SKyle Evans luaC_objbarrier(ls->L, f, f->source); 5488e3e3a7aSWarner Losh f->maxstacksize = 2; /* registers 0/1 are always valid */ 5498e3e3a7aSWarner Losh enterblock(fs, bl, 0); 5508e3e3a7aSWarner Losh } 5518e3e3a7aSWarner Losh 5528e3e3a7aSWarner Losh 5538e3e3a7aSWarner Losh static void close_func (LexState *ls) { 5548e3e3a7aSWarner Losh lua_State *L = ls->L; 5558e3e3a7aSWarner Losh FuncState *fs = ls->fs; 5568e3e3a7aSWarner Losh Proto *f = fs->f; 5578e3e3a7aSWarner Losh luaK_ret(fs, 0, 0); /* final return */ 5588e3e3a7aSWarner Losh leaveblock(fs); 5598e3e3a7aSWarner Losh luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); 5608e3e3a7aSWarner Losh f->sizecode = fs->pc; 5618e3e3a7aSWarner Losh luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); 5628e3e3a7aSWarner Losh f->sizelineinfo = fs->pc; 5638e3e3a7aSWarner Losh luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); 5648e3e3a7aSWarner Losh f->sizek = fs->nk; 5658e3e3a7aSWarner Losh luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); 5668e3e3a7aSWarner Losh f->sizep = fs->np; 5678e3e3a7aSWarner Losh luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); 5688e3e3a7aSWarner Losh f->sizelocvars = fs->nlocvars; 5698e3e3a7aSWarner Losh luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); 5708e3e3a7aSWarner Losh f->sizeupvalues = fs->nups; 5718e3e3a7aSWarner Losh lua_assert(fs->bl == NULL); 5728e3e3a7aSWarner Losh ls->fs = fs->prev; 5738e3e3a7aSWarner Losh luaC_checkGC(L); 5748e3e3a7aSWarner Losh } 5758e3e3a7aSWarner Losh 5768e3e3a7aSWarner Losh 5778e3e3a7aSWarner Losh 5788e3e3a7aSWarner Losh /*============================================================*/ 5798e3e3a7aSWarner Losh /* GRAMMAR RULES */ 5808e3e3a7aSWarner Losh /*============================================================*/ 5818e3e3a7aSWarner Losh 5828e3e3a7aSWarner Losh 5838e3e3a7aSWarner Losh /* 5848e3e3a7aSWarner Losh ** check whether current token is in the follow set of a block. 5858e3e3a7aSWarner Losh ** 'until' closes syntactical blocks, but do not close scope, 5868e3e3a7aSWarner Losh ** so it is handled in separate. 5878e3e3a7aSWarner Losh */ 5888e3e3a7aSWarner Losh static int block_follow (LexState *ls, int withuntil) { 5898e3e3a7aSWarner Losh switch (ls->t.token) { 5908e3e3a7aSWarner Losh case TK_ELSE: case TK_ELSEIF: 5918e3e3a7aSWarner Losh case TK_END: case TK_EOS: 5928e3e3a7aSWarner Losh return 1; 5938e3e3a7aSWarner Losh case TK_UNTIL: return withuntil; 5948e3e3a7aSWarner Losh default: return 0; 5958e3e3a7aSWarner Losh } 5968e3e3a7aSWarner Losh } 5978e3e3a7aSWarner Losh 5988e3e3a7aSWarner Losh 5998e3e3a7aSWarner Losh static void statlist (LexState *ls) { 6008e3e3a7aSWarner Losh /* statlist -> { stat [';'] } */ 6018e3e3a7aSWarner Losh while (!block_follow(ls, 1)) { 6028e3e3a7aSWarner Losh if (ls->t.token == TK_RETURN) { 6038e3e3a7aSWarner Losh statement(ls); 6048e3e3a7aSWarner Losh return; /* 'return' must be last statement */ 6058e3e3a7aSWarner Losh } 6068e3e3a7aSWarner Losh statement(ls); 6078e3e3a7aSWarner Losh } 6088e3e3a7aSWarner Losh } 6098e3e3a7aSWarner Losh 6108e3e3a7aSWarner Losh 6118e3e3a7aSWarner Losh static void fieldsel (LexState *ls, expdesc *v) { 6128e3e3a7aSWarner Losh /* fieldsel -> ['.' | ':'] NAME */ 6138e3e3a7aSWarner Losh FuncState *fs = ls->fs; 6148e3e3a7aSWarner Losh expdesc key; 6158e3e3a7aSWarner Losh luaK_exp2anyregup(fs, v); 6168e3e3a7aSWarner Losh luaX_next(ls); /* skip the dot or colon */ 6178e3e3a7aSWarner Losh checkname(ls, &key); 6188e3e3a7aSWarner Losh luaK_indexed(fs, v, &key); 6198e3e3a7aSWarner Losh } 6208e3e3a7aSWarner Losh 6218e3e3a7aSWarner Losh 6228e3e3a7aSWarner Losh static void yindex (LexState *ls, expdesc *v) { 6238e3e3a7aSWarner Losh /* index -> '[' expr ']' */ 6248e3e3a7aSWarner Losh luaX_next(ls); /* skip the '[' */ 6258e3e3a7aSWarner Losh expr(ls, v); 6268e3e3a7aSWarner Losh luaK_exp2val(ls->fs, v); 6278e3e3a7aSWarner Losh checknext(ls, ']'); 6288e3e3a7aSWarner Losh } 6298e3e3a7aSWarner Losh 6308e3e3a7aSWarner Losh 6318e3e3a7aSWarner Losh /* 6328e3e3a7aSWarner Losh ** {====================================================================== 6338e3e3a7aSWarner Losh ** Rules for Constructors 6348e3e3a7aSWarner Losh ** ======================================================================= 6358e3e3a7aSWarner Losh */ 6368e3e3a7aSWarner Losh 6378e3e3a7aSWarner Losh 6388e3e3a7aSWarner Losh struct ConsControl { 6398e3e3a7aSWarner Losh expdesc v; /* last list item read */ 6408e3e3a7aSWarner Losh expdesc *t; /* table descriptor */ 6418e3e3a7aSWarner Losh int nh; /* total number of 'record' elements */ 6428e3e3a7aSWarner Losh int na; /* total number of array elements */ 6438e3e3a7aSWarner Losh int tostore; /* number of array elements pending to be stored */ 6448e3e3a7aSWarner Losh }; 6458e3e3a7aSWarner Losh 6468e3e3a7aSWarner Losh 6478e3e3a7aSWarner Losh static void recfield (LexState *ls, struct ConsControl *cc) { 6488e3e3a7aSWarner Losh /* recfield -> (NAME | '['exp1']') = exp1 */ 6498e3e3a7aSWarner Losh FuncState *fs = ls->fs; 6508e3e3a7aSWarner Losh int reg = ls->fs->freereg; 6518e3e3a7aSWarner Losh expdesc key, val; 6528e3e3a7aSWarner Losh int rkkey; 6538e3e3a7aSWarner Losh if (ls->t.token == TK_NAME) { 6548e3e3a7aSWarner Losh checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); 6558e3e3a7aSWarner Losh checkname(ls, &key); 6568e3e3a7aSWarner Losh } 6578e3e3a7aSWarner Losh else /* ls->t.token == '[' */ 6588e3e3a7aSWarner Losh yindex(ls, &key); 6598e3e3a7aSWarner Losh cc->nh++; 6608e3e3a7aSWarner Losh checknext(ls, '='); 6618e3e3a7aSWarner Losh rkkey = luaK_exp2RK(fs, &key); 6628e3e3a7aSWarner Losh expr(ls, &val); 6638e3e3a7aSWarner Losh luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); 6648e3e3a7aSWarner Losh fs->freereg = reg; /* free registers */ 6658e3e3a7aSWarner Losh } 6668e3e3a7aSWarner Losh 6678e3e3a7aSWarner Losh 6688e3e3a7aSWarner Losh static void closelistfield (FuncState *fs, struct ConsControl *cc) { 6698e3e3a7aSWarner Losh if (cc->v.k == VVOID) return; /* there is no list item */ 6708e3e3a7aSWarner Losh luaK_exp2nextreg(fs, &cc->v); 6718e3e3a7aSWarner Losh cc->v.k = VVOID; 6728e3e3a7aSWarner Losh if (cc->tostore == LFIELDS_PER_FLUSH) { 6738e3e3a7aSWarner Losh luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ 6748e3e3a7aSWarner Losh cc->tostore = 0; /* no more items pending */ 6758e3e3a7aSWarner Losh } 6768e3e3a7aSWarner Losh } 6778e3e3a7aSWarner Losh 6788e3e3a7aSWarner Losh 6798e3e3a7aSWarner Losh static void lastlistfield (FuncState *fs, struct ConsControl *cc) { 6808e3e3a7aSWarner Losh if (cc->tostore == 0) return; 6818e3e3a7aSWarner Losh if (hasmultret(cc->v.k)) { 6828e3e3a7aSWarner Losh luaK_setmultret(fs, &cc->v); 6838e3e3a7aSWarner Losh luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); 6848e3e3a7aSWarner Losh cc->na--; /* do not count last expression (unknown number of elements) */ 6858e3e3a7aSWarner Losh } 6868e3e3a7aSWarner Losh else { 6878e3e3a7aSWarner Losh if (cc->v.k != VVOID) 6888e3e3a7aSWarner Losh luaK_exp2nextreg(fs, &cc->v); 6898e3e3a7aSWarner Losh luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); 6908e3e3a7aSWarner Losh } 6918e3e3a7aSWarner Losh } 6928e3e3a7aSWarner Losh 6938e3e3a7aSWarner Losh 6948e3e3a7aSWarner Losh static void listfield (LexState *ls, struct ConsControl *cc) { 6958e3e3a7aSWarner Losh /* listfield -> exp */ 6968e3e3a7aSWarner Losh expr(ls, &cc->v); 6978e3e3a7aSWarner Losh checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); 6988e3e3a7aSWarner Losh cc->na++; 6998e3e3a7aSWarner Losh cc->tostore++; 7008e3e3a7aSWarner Losh } 7018e3e3a7aSWarner Losh 7028e3e3a7aSWarner Losh 7038e3e3a7aSWarner Losh static void field (LexState *ls, struct ConsControl *cc) { 7048e3e3a7aSWarner Losh /* field -> listfield | recfield */ 7058e3e3a7aSWarner Losh switch(ls->t.token) { 7068e3e3a7aSWarner Losh case TK_NAME: { /* may be 'listfield' or 'recfield' */ 7078e3e3a7aSWarner Losh if (luaX_lookahead(ls) != '=') /* expression? */ 7088e3e3a7aSWarner Losh listfield(ls, cc); 7098e3e3a7aSWarner Losh else 7108e3e3a7aSWarner Losh recfield(ls, cc); 7118e3e3a7aSWarner Losh break; 7128e3e3a7aSWarner Losh } 7138e3e3a7aSWarner Losh case '[': { 7148e3e3a7aSWarner Losh recfield(ls, cc); 7158e3e3a7aSWarner Losh break; 7168e3e3a7aSWarner Losh } 7178e3e3a7aSWarner Losh default: { 7188e3e3a7aSWarner Losh listfield(ls, cc); 7198e3e3a7aSWarner Losh break; 7208e3e3a7aSWarner Losh } 7218e3e3a7aSWarner Losh } 7228e3e3a7aSWarner Losh } 7238e3e3a7aSWarner Losh 7248e3e3a7aSWarner Losh 7258e3e3a7aSWarner Losh static void constructor (LexState *ls, expdesc *t) { 7268e3e3a7aSWarner Losh /* constructor -> '{' [ field { sep field } [sep] ] '}' 7278e3e3a7aSWarner Losh sep -> ',' | ';' */ 7288e3e3a7aSWarner Losh FuncState *fs = ls->fs; 7298e3e3a7aSWarner Losh int line = ls->linenumber; 7308e3e3a7aSWarner Losh int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); 7318e3e3a7aSWarner Losh struct ConsControl cc; 7328e3e3a7aSWarner Losh cc.na = cc.nh = cc.tostore = 0; 7338e3e3a7aSWarner Losh cc.t = t; 7348e3e3a7aSWarner Losh init_exp(t, VRELOCABLE, pc); 7358e3e3a7aSWarner Losh init_exp(&cc.v, VVOID, 0); /* no value (yet) */ 7368e3e3a7aSWarner Losh luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ 7378e3e3a7aSWarner Losh checknext(ls, '{'); 7388e3e3a7aSWarner Losh do { 7398e3e3a7aSWarner Losh lua_assert(cc.v.k == VVOID || cc.tostore > 0); 7408e3e3a7aSWarner Losh if (ls->t.token == '}') break; 7418e3e3a7aSWarner Losh closelistfield(fs, &cc); 7428e3e3a7aSWarner Losh field(ls, &cc); 7438e3e3a7aSWarner Losh } while (testnext(ls, ',') || testnext(ls, ';')); 7448e3e3a7aSWarner Losh check_match(ls, '}', '{', line); 7458e3e3a7aSWarner Losh lastlistfield(fs, &cc); 7468e3e3a7aSWarner Losh SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ 7478e3e3a7aSWarner Losh SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ 7488e3e3a7aSWarner Losh } 7498e3e3a7aSWarner Losh 7508e3e3a7aSWarner Losh /* }====================================================================== */ 7518e3e3a7aSWarner Losh 7528e3e3a7aSWarner Losh 7538e3e3a7aSWarner Losh 7548e3e3a7aSWarner Losh static void parlist (LexState *ls) { 7558e3e3a7aSWarner Losh /* parlist -> [ param { ',' param } ] */ 7568e3e3a7aSWarner Losh FuncState *fs = ls->fs; 7578e3e3a7aSWarner Losh Proto *f = fs->f; 7588e3e3a7aSWarner Losh int nparams = 0; 7598e3e3a7aSWarner Losh f->is_vararg = 0; 7608e3e3a7aSWarner Losh if (ls->t.token != ')') { /* is 'parlist' not empty? */ 7618e3e3a7aSWarner Losh do { 7628e3e3a7aSWarner Losh switch (ls->t.token) { 7638e3e3a7aSWarner Losh case TK_NAME: { /* param -> NAME */ 7648e3e3a7aSWarner Losh new_localvar(ls, str_checkname(ls)); 7658e3e3a7aSWarner Losh nparams++; 7668e3e3a7aSWarner Losh break; 7678e3e3a7aSWarner Losh } 7688e3e3a7aSWarner Losh case TK_DOTS: { /* param -> '...' */ 7698e3e3a7aSWarner Losh luaX_next(ls); 7708e3e3a7aSWarner Losh f->is_vararg = 1; /* declared vararg */ 7718e3e3a7aSWarner Losh break; 7728e3e3a7aSWarner Losh } 7738e3e3a7aSWarner Losh default: luaX_syntaxerror(ls, "<name> or '...' expected"); 7748e3e3a7aSWarner Losh } 7758e3e3a7aSWarner Losh } while (!f->is_vararg && testnext(ls, ',')); 7768e3e3a7aSWarner Losh } 7778e3e3a7aSWarner Losh adjustlocalvars(ls, nparams); 7788e3e3a7aSWarner Losh f->numparams = cast_byte(fs->nactvar); 7798e3e3a7aSWarner Losh luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ 7808e3e3a7aSWarner Losh } 7818e3e3a7aSWarner Losh 7828e3e3a7aSWarner Losh 7838e3e3a7aSWarner Losh static void body (LexState *ls, expdesc *e, int ismethod, int line) { 7848e3e3a7aSWarner Losh /* body -> '(' parlist ')' block END */ 7858e3e3a7aSWarner Losh FuncState new_fs; 7868e3e3a7aSWarner Losh BlockCnt bl; 7878e3e3a7aSWarner Losh new_fs.f = addprototype(ls); 7888e3e3a7aSWarner Losh new_fs.f->linedefined = line; 7898e3e3a7aSWarner Losh open_func(ls, &new_fs, &bl); 7908e3e3a7aSWarner Losh checknext(ls, '('); 7918e3e3a7aSWarner Losh if (ismethod) { 7928e3e3a7aSWarner Losh new_localvarliteral(ls, "self"); /* create 'self' parameter */ 7938e3e3a7aSWarner Losh adjustlocalvars(ls, 1); 7948e3e3a7aSWarner Losh } 7958e3e3a7aSWarner Losh parlist(ls); 7968e3e3a7aSWarner Losh checknext(ls, ')'); 7978e3e3a7aSWarner Losh statlist(ls); 7988e3e3a7aSWarner Losh new_fs.f->lastlinedefined = ls->linenumber; 7998e3e3a7aSWarner Losh check_match(ls, TK_END, TK_FUNCTION, line); 8008e3e3a7aSWarner Losh codeclosure(ls, e); 8018e3e3a7aSWarner Losh close_func(ls); 8028e3e3a7aSWarner Losh } 8038e3e3a7aSWarner Losh 8048e3e3a7aSWarner Losh 8058e3e3a7aSWarner Losh static int explist (LexState *ls, expdesc *v) { 8068e3e3a7aSWarner Losh /* explist -> expr { ',' expr } */ 8078e3e3a7aSWarner Losh int n = 1; /* at least one expression */ 8088e3e3a7aSWarner Losh expr(ls, v); 8098e3e3a7aSWarner Losh while (testnext(ls, ',')) { 8108e3e3a7aSWarner Losh luaK_exp2nextreg(ls->fs, v); 8118e3e3a7aSWarner Losh expr(ls, v); 8128e3e3a7aSWarner Losh n++; 8138e3e3a7aSWarner Losh } 8148e3e3a7aSWarner Losh return n; 8158e3e3a7aSWarner Losh } 8168e3e3a7aSWarner Losh 8178e3e3a7aSWarner Losh 8188e3e3a7aSWarner Losh static void funcargs (LexState *ls, expdesc *f, int line) { 8198e3e3a7aSWarner Losh FuncState *fs = ls->fs; 8208e3e3a7aSWarner Losh expdesc args; 8218e3e3a7aSWarner Losh int base, nparams; 8228e3e3a7aSWarner Losh switch (ls->t.token) { 8238e3e3a7aSWarner Losh case '(': { /* funcargs -> '(' [ explist ] ')' */ 8248e3e3a7aSWarner Losh luaX_next(ls); 8258e3e3a7aSWarner Losh if (ls->t.token == ')') /* arg list is empty? */ 8268e3e3a7aSWarner Losh args.k = VVOID; 8278e3e3a7aSWarner Losh else { 8288e3e3a7aSWarner Losh explist(ls, &args); 8298e3e3a7aSWarner Losh luaK_setmultret(fs, &args); 8308e3e3a7aSWarner Losh } 8318e3e3a7aSWarner Losh check_match(ls, ')', '(', line); 8328e3e3a7aSWarner Losh break; 8338e3e3a7aSWarner Losh } 8348e3e3a7aSWarner Losh case '{': { /* funcargs -> constructor */ 8358e3e3a7aSWarner Losh constructor(ls, &args); 8368e3e3a7aSWarner Losh break; 8378e3e3a7aSWarner Losh } 8388e3e3a7aSWarner Losh case TK_STRING: { /* funcargs -> STRING */ 8398e3e3a7aSWarner Losh codestring(ls, &args, ls->t.seminfo.ts); 8408e3e3a7aSWarner Losh luaX_next(ls); /* must use 'seminfo' before 'next' */ 8418e3e3a7aSWarner Losh break; 8428e3e3a7aSWarner Losh } 8438e3e3a7aSWarner Losh default: { 8448e3e3a7aSWarner Losh luaX_syntaxerror(ls, "function arguments expected"); 8458e3e3a7aSWarner Losh } 8468e3e3a7aSWarner Losh } 8478e3e3a7aSWarner Losh lua_assert(f->k == VNONRELOC); 8488e3e3a7aSWarner Losh base = f->u.info; /* base register for call */ 8498e3e3a7aSWarner Losh if (hasmultret(args.k)) 8508e3e3a7aSWarner Losh nparams = LUA_MULTRET; /* open call */ 8518e3e3a7aSWarner Losh else { 8528e3e3a7aSWarner Losh if (args.k != VVOID) 8538e3e3a7aSWarner Losh luaK_exp2nextreg(fs, &args); /* close last argument */ 8548e3e3a7aSWarner Losh nparams = fs->freereg - (base+1); 8558e3e3a7aSWarner Losh } 8568e3e3a7aSWarner Losh init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); 8578e3e3a7aSWarner Losh luaK_fixline(fs, line); 8588e3e3a7aSWarner Losh fs->freereg = base+1; /* call remove function and arguments and leaves 8598e3e3a7aSWarner Losh (unless changed) one result */ 8608e3e3a7aSWarner Losh } 8618e3e3a7aSWarner Losh 8628e3e3a7aSWarner Losh 8638e3e3a7aSWarner Losh 8648e3e3a7aSWarner Losh 8658e3e3a7aSWarner Losh /* 8668e3e3a7aSWarner Losh ** {====================================================================== 8678e3e3a7aSWarner Losh ** Expression parsing 8688e3e3a7aSWarner Losh ** ======================================================================= 8698e3e3a7aSWarner Losh */ 8708e3e3a7aSWarner Losh 8718e3e3a7aSWarner Losh 8728e3e3a7aSWarner Losh static void primaryexp (LexState *ls, expdesc *v) { 8738e3e3a7aSWarner Losh /* primaryexp -> NAME | '(' expr ')' */ 8748e3e3a7aSWarner Losh switch (ls->t.token) { 8758e3e3a7aSWarner Losh case '(': { 8768e3e3a7aSWarner Losh int line = ls->linenumber; 8778e3e3a7aSWarner Losh luaX_next(ls); 8788e3e3a7aSWarner Losh expr(ls, v); 8798e3e3a7aSWarner Losh check_match(ls, ')', '(', line); 8808e3e3a7aSWarner Losh luaK_dischargevars(ls->fs, v); 8818e3e3a7aSWarner Losh return; 8828e3e3a7aSWarner Losh } 8838e3e3a7aSWarner Losh case TK_NAME: { 8848e3e3a7aSWarner Losh singlevar(ls, v); 8858e3e3a7aSWarner Losh return; 8868e3e3a7aSWarner Losh } 8878e3e3a7aSWarner Losh default: { 8888e3e3a7aSWarner Losh luaX_syntaxerror(ls, "unexpected symbol"); 8898e3e3a7aSWarner Losh } 8908e3e3a7aSWarner Losh } 8918e3e3a7aSWarner Losh } 8928e3e3a7aSWarner Losh 8938e3e3a7aSWarner Losh 8948e3e3a7aSWarner Losh static void suffixedexp (LexState *ls, expdesc *v) { 8958e3e3a7aSWarner Losh /* suffixedexp -> 8968e3e3a7aSWarner Losh primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ 8978e3e3a7aSWarner Losh FuncState *fs = ls->fs; 8988e3e3a7aSWarner Losh int line = ls->linenumber; 8998e3e3a7aSWarner Losh primaryexp(ls, v); 9008e3e3a7aSWarner Losh for (;;) { 9018e3e3a7aSWarner Losh switch (ls->t.token) { 9028e3e3a7aSWarner Losh case '.': { /* fieldsel */ 9038e3e3a7aSWarner Losh fieldsel(ls, v); 9048e3e3a7aSWarner Losh break; 9058e3e3a7aSWarner Losh } 9068e3e3a7aSWarner Losh case '[': { /* '[' exp1 ']' */ 9078e3e3a7aSWarner Losh expdesc key; 9088e3e3a7aSWarner Losh luaK_exp2anyregup(fs, v); 9098e3e3a7aSWarner Losh yindex(ls, &key); 9108e3e3a7aSWarner Losh luaK_indexed(fs, v, &key); 9118e3e3a7aSWarner Losh break; 9128e3e3a7aSWarner Losh } 9138e3e3a7aSWarner Losh case ':': { /* ':' NAME funcargs */ 9148e3e3a7aSWarner Losh expdesc key; 9158e3e3a7aSWarner Losh luaX_next(ls); 9168e3e3a7aSWarner Losh checkname(ls, &key); 9178e3e3a7aSWarner Losh luaK_self(fs, v, &key); 9188e3e3a7aSWarner Losh funcargs(ls, v, line); 9198e3e3a7aSWarner Losh break; 9208e3e3a7aSWarner Losh } 9218e3e3a7aSWarner Losh case '(': case TK_STRING: case '{': { /* funcargs */ 9228e3e3a7aSWarner Losh luaK_exp2nextreg(fs, v); 9238e3e3a7aSWarner Losh funcargs(ls, v, line); 9248e3e3a7aSWarner Losh break; 9258e3e3a7aSWarner Losh } 9268e3e3a7aSWarner Losh default: return; 9278e3e3a7aSWarner Losh } 9288e3e3a7aSWarner Losh } 9298e3e3a7aSWarner Losh } 9308e3e3a7aSWarner Losh 9318e3e3a7aSWarner Losh 9328e3e3a7aSWarner Losh static void simpleexp (LexState *ls, expdesc *v) { 9338e3e3a7aSWarner Losh /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | 9348e3e3a7aSWarner Losh constructor | FUNCTION body | suffixedexp */ 9358e3e3a7aSWarner Losh switch (ls->t.token) { 9368e3e3a7aSWarner Losh case TK_FLT: { 9378e3e3a7aSWarner Losh init_exp(v, VKFLT, 0); 9388e3e3a7aSWarner Losh v->u.nval = ls->t.seminfo.r; 9398e3e3a7aSWarner Losh break; 9408e3e3a7aSWarner Losh } 9418e3e3a7aSWarner Losh case TK_INT: { 9428e3e3a7aSWarner Losh init_exp(v, VKINT, 0); 9438e3e3a7aSWarner Losh v->u.ival = ls->t.seminfo.i; 9448e3e3a7aSWarner Losh break; 9458e3e3a7aSWarner Losh } 9468e3e3a7aSWarner Losh case TK_STRING: { 9478e3e3a7aSWarner Losh codestring(ls, v, ls->t.seminfo.ts); 9488e3e3a7aSWarner Losh break; 9498e3e3a7aSWarner Losh } 9508e3e3a7aSWarner Losh case TK_NIL: { 9518e3e3a7aSWarner Losh init_exp(v, VNIL, 0); 9528e3e3a7aSWarner Losh break; 9538e3e3a7aSWarner Losh } 9548e3e3a7aSWarner Losh case TK_TRUE: { 9558e3e3a7aSWarner Losh init_exp(v, VTRUE, 0); 9568e3e3a7aSWarner Losh break; 9578e3e3a7aSWarner Losh } 9588e3e3a7aSWarner Losh case TK_FALSE: { 9598e3e3a7aSWarner Losh init_exp(v, VFALSE, 0); 9608e3e3a7aSWarner Losh break; 9618e3e3a7aSWarner Losh } 9628e3e3a7aSWarner Losh case TK_DOTS: { /* vararg */ 9638e3e3a7aSWarner Losh FuncState *fs = ls->fs; 9648e3e3a7aSWarner Losh check_condition(ls, fs->f->is_vararg, 9658e3e3a7aSWarner Losh "cannot use '...' outside a vararg function"); 9668e3e3a7aSWarner Losh init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); 9678e3e3a7aSWarner Losh break; 9688e3e3a7aSWarner Losh } 9698e3e3a7aSWarner Losh case '{': { /* constructor */ 9708e3e3a7aSWarner Losh constructor(ls, v); 9718e3e3a7aSWarner Losh return; 9728e3e3a7aSWarner Losh } 9738e3e3a7aSWarner Losh case TK_FUNCTION: { 9748e3e3a7aSWarner Losh luaX_next(ls); 9758e3e3a7aSWarner Losh body(ls, v, 0, ls->linenumber); 9768e3e3a7aSWarner Losh return; 9778e3e3a7aSWarner Losh } 9788e3e3a7aSWarner Losh default: { 9798e3e3a7aSWarner Losh suffixedexp(ls, v); 9808e3e3a7aSWarner Losh return; 9818e3e3a7aSWarner Losh } 9828e3e3a7aSWarner Losh } 9838e3e3a7aSWarner Losh luaX_next(ls); 9848e3e3a7aSWarner Losh } 9858e3e3a7aSWarner Losh 9868e3e3a7aSWarner Losh 9878e3e3a7aSWarner Losh static UnOpr getunopr (int op) { 9888e3e3a7aSWarner Losh switch (op) { 9898e3e3a7aSWarner Losh case TK_NOT: return OPR_NOT; 9908e3e3a7aSWarner Losh case '-': return OPR_MINUS; 9918e3e3a7aSWarner Losh case '~': return OPR_BNOT; 9928e3e3a7aSWarner Losh case '#': return OPR_LEN; 9938e3e3a7aSWarner Losh default: return OPR_NOUNOPR; 9948e3e3a7aSWarner Losh } 9958e3e3a7aSWarner Losh } 9968e3e3a7aSWarner Losh 9978e3e3a7aSWarner Losh 9988e3e3a7aSWarner Losh static BinOpr getbinopr (int op) { 9998e3e3a7aSWarner Losh switch (op) { 10008e3e3a7aSWarner Losh case '+': return OPR_ADD; 10018e3e3a7aSWarner Losh case '-': return OPR_SUB; 10028e3e3a7aSWarner Losh case '*': return OPR_MUL; 10038e3e3a7aSWarner Losh case '%': return OPR_MOD; 10048e3e3a7aSWarner Losh case '^': return OPR_POW; 10058e3e3a7aSWarner Losh case '/': return OPR_DIV; 10068e3e3a7aSWarner Losh case TK_IDIV: return OPR_IDIV; 10078e3e3a7aSWarner Losh case '&': return OPR_BAND; 10088e3e3a7aSWarner Losh case '|': return OPR_BOR; 10098e3e3a7aSWarner Losh case '~': return OPR_BXOR; 10108e3e3a7aSWarner Losh case TK_SHL: return OPR_SHL; 10118e3e3a7aSWarner Losh case TK_SHR: return OPR_SHR; 10128e3e3a7aSWarner Losh case TK_CONCAT: return OPR_CONCAT; 10138e3e3a7aSWarner Losh case TK_NE: return OPR_NE; 10148e3e3a7aSWarner Losh case TK_EQ: return OPR_EQ; 10158e3e3a7aSWarner Losh case '<': return OPR_LT; 10168e3e3a7aSWarner Losh case TK_LE: return OPR_LE; 10178e3e3a7aSWarner Losh case '>': return OPR_GT; 10188e3e3a7aSWarner Losh case TK_GE: return OPR_GE; 10198e3e3a7aSWarner Losh case TK_AND: return OPR_AND; 10208e3e3a7aSWarner Losh case TK_OR: return OPR_OR; 10218e3e3a7aSWarner Losh default: return OPR_NOBINOPR; 10228e3e3a7aSWarner Losh } 10238e3e3a7aSWarner Losh } 10248e3e3a7aSWarner Losh 10258e3e3a7aSWarner Losh 10268e3e3a7aSWarner Losh static const struct { 10278e3e3a7aSWarner Losh lu_byte left; /* left priority for each binary operator */ 10288e3e3a7aSWarner Losh lu_byte right; /* right priority */ 10298e3e3a7aSWarner Losh } priority[] = { /* ORDER OPR */ 10308e3e3a7aSWarner Losh {10, 10}, {10, 10}, /* '+' '-' */ 10318e3e3a7aSWarner Losh {11, 11}, {11, 11}, /* '*' '%' */ 10328e3e3a7aSWarner Losh {14, 13}, /* '^' (right associative) */ 10338e3e3a7aSWarner Losh {11, 11}, {11, 11}, /* '/' '//' */ 10348e3e3a7aSWarner Losh {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ 10358e3e3a7aSWarner Losh {7, 7}, {7, 7}, /* '<<' '>>' */ 10368e3e3a7aSWarner Losh {9, 8}, /* '..' (right associative) */ 10378e3e3a7aSWarner Losh {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ 10388e3e3a7aSWarner Losh {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ 10398e3e3a7aSWarner Losh {2, 2}, {1, 1} /* and, or */ 10408e3e3a7aSWarner Losh }; 10418e3e3a7aSWarner Losh 10428e3e3a7aSWarner Losh #define UNARY_PRIORITY 12 /* priority for unary operators */ 10438e3e3a7aSWarner Losh 10448e3e3a7aSWarner Losh 10458e3e3a7aSWarner Losh /* 10468e3e3a7aSWarner Losh ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } 10478e3e3a7aSWarner Losh ** where 'binop' is any binary operator with a priority higher than 'limit' 10488e3e3a7aSWarner Losh */ 10498e3e3a7aSWarner Losh static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { 10508e3e3a7aSWarner Losh BinOpr op; 10518e3e3a7aSWarner Losh UnOpr uop; 10528e3e3a7aSWarner Losh enterlevel(ls); 10538e3e3a7aSWarner Losh uop = getunopr(ls->t.token); 10548e3e3a7aSWarner Losh if (uop != OPR_NOUNOPR) { 10558e3e3a7aSWarner Losh int line = ls->linenumber; 10568e3e3a7aSWarner Losh luaX_next(ls); 10578e3e3a7aSWarner Losh subexpr(ls, v, UNARY_PRIORITY); 10588e3e3a7aSWarner Losh luaK_prefix(ls->fs, uop, v, line); 10598e3e3a7aSWarner Losh } 10608e3e3a7aSWarner Losh else simpleexp(ls, v); 10618e3e3a7aSWarner Losh /* expand while operators have priorities higher than 'limit' */ 10628e3e3a7aSWarner Losh op = getbinopr(ls->t.token); 10638e3e3a7aSWarner Losh while (op != OPR_NOBINOPR && priority[op].left > limit) { 10648e3e3a7aSWarner Losh expdesc v2; 10658e3e3a7aSWarner Losh BinOpr nextop; 10668e3e3a7aSWarner Losh int line = ls->linenumber; 10678e3e3a7aSWarner Losh luaX_next(ls); 10688e3e3a7aSWarner Losh luaK_infix(ls->fs, op, v); 10698e3e3a7aSWarner Losh /* read sub-expression with higher priority */ 10708e3e3a7aSWarner Losh nextop = subexpr(ls, &v2, priority[op].right); 10718e3e3a7aSWarner Losh luaK_posfix(ls->fs, op, v, &v2, line); 10728e3e3a7aSWarner Losh op = nextop; 10738e3e3a7aSWarner Losh } 10748e3e3a7aSWarner Losh leavelevel(ls); 10758e3e3a7aSWarner Losh return op; /* return first untreated operator */ 10768e3e3a7aSWarner Losh } 10778e3e3a7aSWarner Losh 10788e3e3a7aSWarner Losh 10798e3e3a7aSWarner Losh static void expr (LexState *ls, expdesc *v) { 10808e3e3a7aSWarner Losh subexpr(ls, v, 0); 10818e3e3a7aSWarner Losh } 10828e3e3a7aSWarner Losh 10838e3e3a7aSWarner Losh /* }==================================================================== */ 10848e3e3a7aSWarner Losh 10858e3e3a7aSWarner Losh 10868e3e3a7aSWarner Losh 10878e3e3a7aSWarner Losh /* 10888e3e3a7aSWarner Losh ** {====================================================================== 10898e3e3a7aSWarner Losh ** Rules for Statements 10908e3e3a7aSWarner Losh ** ======================================================================= 10918e3e3a7aSWarner Losh */ 10928e3e3a7aSWarner Losh 10938e3e3a7aSWarner Losh 10948e3e3a7aSWarner Losh static void block (LexState *ls) { 10958e3e3a7aSWarner Losh /* block -> statlist */ 10968e3e3a7aSWarner Losh FuncState *fs = ls->fs; 10978e3e3a7aSWarner Losh BlockCnt bl; 10988e3e3a7aSWarner Losh enterblock(fs, &bl, 0); 10998e3e3a7aSWarner Losh statlist(ls); 11008e3e3a7aSWarner Losh leaveblock(fs); 11018e3e3a7aSWarner Losh } 11028e3e3a7aSWarner Losh 11038e3e3a7aSWarner Losh 11048e3e3a7aSWarner Losh /* 11058e3e3a7aSWarner Losh ** structure to chain all variables in the left-hand side of an 11068e3e3a7aSWarner Losh ** assignment 11078e3e3a7aSWarner Losh */ 11088e3e3a7aSWarner Losh struct LHS_assign { 11098e3e3a7aSWarner Losh struct LHS_assign *prev; 11108e3e3a7aSWarner Losh expdesc v; /* variable (global, local, upvalue, or indexed) */ 11118e3e3a7aSWarner Losh }; 11128e3e3a7aSWarner Losh 11138e3e3a7aSWarner Losh 11148e3e3a7aSWarner Losh /* 11158e3e3a7aSWarner Losh ** check whether, in an assignment to an upvalue/local variable, the 11168e3e3a7aSWarner Losh ** upvalue/local variable is begin used in a previous assignment to a 11178e3e3a7aSWarner Losh ** table. If so, save original upvalue/local value in a safe place and 11188e3e3a7aSWarner Losh ** use this safe copy in the previous assignment. 11198e3e3a7aSWarner Losh */ 11208e3e3a7aSWarner Losh static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { 11218e3e3a7aSWarner Losh FuncState *fs = ls->fs; 11228e3e3a7aSWarner Losh int extra = fs->freereg; /* eventual position to save local variable */ 11238e3e3a7aSWarner Losh int conflict = 0; 11248e3e3a7aSWarner Losh for (; lh; lh = lh->prev) { /* check all previous assignments */ 11258e3e3a7aSWarner Losh if (lh->v.k == VINDEXED) { /* assigning to a table? */ 11268e3e3a7aSWarner Losh /* table is the upvalue/local being assigned now? */ 11278e3e3a7aSWarner Losh if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { 11288e3e3a7aSWarner Losh conflict = 1; 11298e3e3a7aSWarner Losh lh->v.u.ind.vt = VLOCAL; 11308e3e3a7aSWarner Losh lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ 11318e3e3a7aSWarner Losh } 11328e3e3a7aSWarner Losh /* index is the local being assigned? (index cannot be upvalue) */ 11338e3e3a7aSWarner Losh if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { 11348e3e3a7aSWarner Losh conflict = 1; 11358e3e3a7aSWarner Losh lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ 11368e3e3a7aSWarner Losh } 11378e3e3a7aSWarner Losh } 11388e3e3a7aSWarner Losh } 11398e3e3a7aSWarner Losh if (conflict) { 11408e3e3a7aSWarner Losh /* copy upvalue/local value to a temporary (in position 'extra') */ 11418e3e3a7aSWarner Losh OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; 11428e3e3a7aSWarner Losh luaK_codeABC(fs, op, extra, v->u.info, 0); 11438e3e3a7aSWarner Losh luaK_reserveregs(fs, 1); 11448e3e3a7aSWarner Losh } 11458e3e3a7aSWarner Losh } 11468e3e3a7aSWarner Losh 11478e3e3a7aSWarner Losh 11488e3e3a7aSWarner Losh static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { 11498e3e3a7aSWarner Losh expdesc e; 11508e3e3a7aSWarner Losh check_condition(ls, vkisvar(lh->v.k), "syntax error"); 11518e3e3a7aSWarner Losh if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ 11528e3e3a7aSWarner Losh struct LHS_assign nv; 11538e3e3a7aSWarner Losh nv.prev = lh; 11548e3e3a7aSWarner Losh suffixedexp(ls, &nv.v); 11558e3e3a7aSWarner Losh if (nv.v.k != VINDEXED) 11568e3e3a7aSWarner Losh check_conflict(ls, lh, &nv.v); 11578e3e3a7aSWarner Losh checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, 11588e3e3a7aSWarner Losh "C levels"); 11598e3e3a7aSWarner Losh assignment(ls, &nv, nvars+1); 11608e3e3a7aSWarner Losh } 11618e3e3a7aSWarner Losh else { /* assignment -> '=' explist */ 11628e3e3a7aSWarner Losh int nexps; 11638e3e3a7aSWarner Losh checknext(ls, '='); 11648e3e3a7aSWarner Losh nexps = explist(ls, &e); 11658e3e3a7aSWarner Losh if (nexps != nvars) 11668e3e3a7aSWarner Losh adjust_assign(ls, nvars, nexps, &e); 11678e3e3a7aSWarner Losh else { 11688e3e3a7aSWarner Losh luaK_setoneret(ls->fs, &e); /* close last expression */ 11698e3e3a7aSWarner Losh luaK_storevar(ls->fs, &lh->v, &e); 11708e3e3a7aSWarner Losh return; /* avoid default */ 11718e3e3a7aSWarner Losh } 11728e3e3a7aSWarner Losh } 11738e3e3a7aSWarner Losh init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ 11748e3e3a7aSWarner Losh luaK_storevar(ls->fs, &lh->v, &e); 11758e3e3a7aSWarner Losh } 11768e3e3a7aSWarner Losh 11778e3e3a7aSWarner Losh 11788e3e3a7aSWarner Losh static int cond (LexState *ls) { 11798e3e3a7aSWarner Losh /* cond -> exp */ 11808e3e3a7aSWarner Losh expdesc v; 11818e3e3a7aSWarner Losh expr(ls, &v); /* read condition */ 11828e3e3a7aSWarner Losh if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ 11838e3e3a7aSWarner Losh luaK_goiftrue(ls->fs, &v); 11848e3e3a7aSWarner Losh return v.f; 11858e3e3a7aSWarner Losh } 11868e3e3a7aSWarner Losh 11878e3e3a7aSWarner Losh 11888e3e3a7aSWarner Losh static void gotostat (LexState *ls, int pc) { 11898e3e3a7aSWarner Losh int line = ls->linenumber; 11908e3e3a7aSWarner Losh TString *label; 11918e3e3a7aSWarner Losh int g; 11928e3e3a7aSWarner Losh if (testnext(ls, TK_GOTO)) 11938e3e3a7aSWarner Losh label = str_checkname(ls); 11948e3e3a7aSWarner Losh else { 11958e3e3a7aSWarner Losh luaX_next(ls); /* skip break */ 11968e3e3a7aSWarner Losh label = luaS_new(ls->L, "break"); 11978e3e3a7aSWarner Losh } 11988e3e3a7aSWarner Losh g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); 11998e3e3a7aSWarner Losh findlabel(ls, g); /* close it if label already defined */ 12008e3e3a7aSWarner Losh } 12018e3e3a7aSWarner Losh 12028e3e3a7aSWarner Losh 12038e3e3a7aSWarner Losh /* check for repeated labels on the same block */ 12048e3e3a7aSWarner Losh static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { 12058e3e3a7aSWarner Losh int i; 12068e3e3a7aSWarner Losh for (i = fs->bl->firstlabel; i < ll->n; i++) { 12078e3e3a7aSWarner Losh if (eqstr(label, ll->arr[i].name)) { 12088e3e3a7aSWarner Losh const char *msg = luaO_pushfstring(fs->ls->L, 12098e3e3a7aSWarner Losh "label '%s' already defined on line %d", 12108e3e3a7aSWarner Losh getstr(label), ll->arr[i].line); 12118e3e3a7aSWarner Losh semerror(fs->ls, msg); 12128e3e3a7aSWarner Losh } 12138e3e3a7aSWarner Losh } 12148e3e3a7aSWarner Losh } 12158e3e3a7aSWarner Losh 12168e3e3a7aSWarner Losh 12178e3e3a7aSWarner Losh /* skip no-op statements */ 12188e3e3a7aSWarner Losh static void skipnoopstat (LexState *ls) { 12198e3e3a7aSWarner Losh while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) 12208e3e3a7aSWarner Losh statement(ls); 12218e3e3a7aSWarner Losh } 12228e3e3a7aSWarner Losh 12238e3e3a7aSWarner Losh 12248e3e3a7aSWarner Losh static void labelstat (LexState *ls, TString *label, int line) { 12258e3e3a7aSWarner Losh /* label -> '::' NAME '::' */ 12268e3e3a7aSWarner Losh FuncState *fs = ls->fs; 12278e3e3a7aSWarner Losh Labellist *ll = &ls->dyd->label; 12288e3e3a7aSWarner Losh int l; /* index of new label being created */ 12298e3e3a7aSWarner Losh checkrepeated(fs, ll, label); /* check for repeated labels */ 12308e3e3a7aSWarner Losh checknext(ls, TK_DBCOLON); /* skip double colon */ 12318e3e3a7aSWarner Losh /* create new entry for this label */ 12328e3e3a7aSWarner Losh l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); 12338e3e3a7aSWarner Losh skipnoopstat(ls); /* skip other no-op statements */ 12348e3e3a7aSWarner Losh if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ 12358e3e3a7aSWarner Losh /* assume that locals are already out of scope */ 12368e3e3a7aSWarner Losh ll->arr[l].nactvar = fs->bl->nactvar; 12378e3e3a7aSWarner Losh } 12388e3e3a7aSWarner Losh findgotos(ls, &ll->arr[l]); 12398e3e3a7aSWarner Losh } 12408e3e3a7aSWarner Losh 12418e3e3a7aSWarner Losh 12428e3e3a7aSWarner Losh static void whilestat (LexState *ls, int line) { 12438e3e3a7aSWarner Losh /* whilestat -> WHILE cond DO block END */ 12448e3e3a7aSWarner Losh FuncState *fs = ls->fs; 12458e3e3a7aSWarner Losh int whileinit; 12468e3e3a7aSWarner Losh int condexit; 12478e3e3a7aSWarner Losh BlockCnt bl; 12488e3e3a7aSWarner Losh luaX_next(ls); /* skip WHILE */ 12498e3e3a7aSWarner Losh whileinit = luaK_getlabel(fs); 12508e3e3a7aSWarner Losh condexit = cond(ls); 12518e3e3a7aSWarner Losh enterblock(fs, &bl, 1); 12528e3e3a7aSWarner Losh checknext(ls, TK_DO); 12538e3e3a7aSWarner Losh block(ls); 12548e3e3a7aSWarner Losh luaK_jumpto(fs, whileinit); 12558e3e3a7aSWarner Losh check_match(ls, TK_END, TK_WHILE, line); 12568e3e3a7aSWarner Losh leaveblock(fs); 12578e3e3a7aSWarner Losh luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ 12588e3e3a7aSWarner Losh } 12598e3e3a7aSWarner Losh 12608e3e3a7aSWarner Losh 12618e3e3a7aSWarner Losh static void repeatstat (LexState *ls, int line) { 12628e3e3a7aSWarner Losh /* repeatstat -> REPEAT block UNTIL cond */ 12638e3e3a7aSWarner Losh int condexit; 12648e3e3a7aSWarner Losh FuncState *fs = ls->fs; 12658e3e3a7aSWarner Losh int repeat_init = luaK_getlabel(fs); 12668e3e3a7aSWarner Losh BlockCnt bl1, bl2; 12678e3e3a7aSWarner Losh enterblock(fs, &bl1, 1); /* loop block */ 12688e3e3a7aSWarner Losh enterblock(fs, &bl2, 0); /* scope block */ 12698e3e3a7aSWarner Losh luaX_next(ls); /* skip REPEAT */ 12708e3e3a7aSWarner Losh statlist(ls); 12718e3e3a7aSWarner Losh check_match(ls, TK_UNTIL, TK_REPEAT, line); 12728e3e3a7aSWarner Losh condexit = cond(ls); /* read condition (inside scope block) */ 12738e3e3a7aSWarner Losh if (bl2.upval) /* upvalues? */ 12748e3e3a7aSWarner Losh luaK_patchclose(fs, condexit, bl2.nactvar); 12758e3e3a7aSWarner Losh leaveblock(fs); /* finish scope */ 12768e3e3a7aSWarner Losh luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ 12778e3e3a7aSWarner Losh leaveblock(fs); /* finish loop */ 12788e3e3a7aSWarner Losh } 12798e3e3a7aSWarner Losh 12808e3e3a7aSWarner Losh 12818e3e3a7aSWarner Losh static int exp1 (LexState *ls) { 12828e3e3a7aSWarner Losh expdesc e; 12838e3e3a7aSWarner Losh int reg; 12848e3e3a7aSWarner Losh expr(ls, &e); 12858e3e3a7aSWarner Losh luaK_exp2nextreg(ls->fs, &e); 12868e3e3a7aSWarner Losh lua_assert(e.k == VNONRELOC); 12878e3e3a7aSWarner Losh reg = e.u.info; 12888e3e3a7aSWarner Losh return reg; 12898e3e3a7aSWarner Losh } 12908e3e3a7aSWarner Losh 12918e3e3a7aSWarner Losh 12928e3e3a7aSWarner Losh static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { 12938e3e3a7aSWarner Losh /* forbody -> DO block */ 12948e3e3a7aSWarner Losh BlockCnt bl; 12958e3e3a7aSWarner Losh FuncState *fs = ls->fs; 12968e3e3a7aSWarner Losh int prep, endfor; 12978e3e3a7aSWarner Losh adjustlocalvars(ls, 3); /* control variables */ 12988e3e3a7aSWarner Losh checknext(ls, TK_DO); 12998e3e3a7aSWarner Losh prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); 13008e3e3a7aSWarner Losh enterblock(fs, &bl, 0); /* scope for declared variables */ 13018e3e3a7aSWarner Losh adjustlocalvars(ls, nvars); 13028e3e3a7aSWarner Losh luaK_reserveregs(fs, nvars); 13038e3e3a7aSWarner Losh block(ls); 13048e3e3a7aSWarner Losh leaveblock(fs); /* end of scope for declared variables */ 13058e3e3a7aSWarner Losh luaK_patchtohere(fs, prep); 13068e3e3a7aSWarner Losh if (isnum) /* numeric for? */ 13078e3e3a7aSWarner Losh endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); 13088e3e3a7aSWarner Losh else { /* generic for */ 13098e3e3a7aSWarner Losh luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); 13108e3e3a7aSWarner Losh luaK_fixline(fs, line); 13118e3e3a7aSWarner Losh endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); 13128e3e3a7aSWarner Losh } 13138e3e3a7aSWarner Losh luaK_patchlist(fs, endfor, prep + 1); 13148e3e3a7aSWarner Losh luaK_fixline(fs, line); 13158e3e3a7aSWarner Losh } 13168e3e3a7aSWarner Losh 13178e3e3a7aSWarner Losh 13188e3e3a7aSWarner Losh static void fornum (LexState *ls, TString *varname, int line) { 13198e3e3a7aSWarner Losh /* fornum -> NAME = exp1,exp1[,exp1] forbody */ 13208e3e3a7aSWarner Losh FuncState *fs = ls->fs; 13218e3e3a7aSWarner Losh int base = fs->freereg; 13228e3e3a7aSWarner Losh new_localvarliteral(ls, "(for index)"); 13238e3e3a7aSWarner Losh new_localvarliteral(ls, "(for limit)"); 13248e3e3a7aSWarner Losh new_localvarliteral(ls, "(for step)"); 13258e3e3a7aSWarner Losh new_localvar(ls, varname); 13268e3e3a7aSWarner Losh checknext(ls, '='); 13278e3e3a7aSWarner Losh exp1(ls); /* initial value */ 13288e3e3a7aSWarner Losh checknext(ls, ','); 13298e3e3a7aSWarner Losh exp1(ls); /* limit */ 13308e3e3a7aSWarner Losh if (testnext(ls, ',')) 13318e3e3a7aSWarner Losh exp1(ls); /* optional step */ 13328e3e3a7aSWarner Losh else { /* default step = 1 */ 13338e3e3a7aSWarner Losh luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); 13348e3e3a7aSWarner Losh luaK_reserveregs(fs, 1); 13358e3e3a7aSWarner Losh } 13368e3e3a7aSWarner Losh forbody(ls, base, line, 1, 1); 13378e3e3a7aSWarner Losh } 13388e3e3a7aSWarner Losh 13398e3e3a7aSWarner Losh 13408e3e3a7aSWarner Losh static void forlist (LexState *ls, TString *indexname) { 13418e3e3a7aSWarner Losh /* forlist -> NAME {,NAME} IN explist forbody */ 13428e3e3a7aSWarner Losh FuncState *fs = ls->fs; 13438e3e3a7aSWarner Losh expdesc e; 13448e3e3a7aSWarner Losh int nvars = 4; /* gen, state, control, plus at least one declared var */ 13458e3e3a7aSWarner Losh int line; 13468e3e3a7aSWarner Losh int base = fs->freereg; 13478e3e3a7aSWarner Losh /* create control variables */ 13488e3e3a7aSWarner Losh new_localvarliteral(ls, "(for generator)"); 13498e3e3a7aSWarner Losh new_localvarliteral(ls, "(for state)"); 13508e3e3a7aSWarner Losh new_localvarliteral(ls, "(for control)"); 13518e3e3a7aSWarner Losh /* create declared variables */ 13528e3e3a7aSWarner Losh new_localvar(ls, indexname); 13538e3e3a7aSWarner Losh while (testnext(ls, ',')) { 13548e3e3a7aSWarner Losh new_localvar(ls, str_checkname(ls)); 13558e3e3a7aSWarner Losh nvars++; 13568e3e3a7aSWarner Losh } 13578e3e3a7aSWarner Losh checknext(ls, TK_IN); 13588e3e3a7aSWarner Losh line = ls->linenumber; 13598e3e3a7aSWarner Losh adjust_assign(ls, 3, explist(ls, &e), &e); 13608e3e3a7aSWarner Losh luaK_checkstack(fs, 3); /* extra space to call generator */ 13618e3e3a7aSWarner Losh forbody(ls, base, line, nvars - 3, 0); 13628e3e3a7aSWarner Losh } 13638e3e3a7aSWarner Losh 13648e3e3a7aSWarner Losh 13658e3e3a7aSWarner Losh static void forstat (LexState *ls, int line) { 13668e3e3a7aSWarner Losh /* forstat -> FOR (fornum | forlist) END */ 13678e3e3a7aSWarner Losh FuncState *fs = ls->fs; 13688e3e3a7aSWarner Losh TString *varname; 13698e3e3a7aSWarner Losh BlockCnt bl; 13708e3e3a7aSWarner Losh enterblock(fs, &bl, 1); /* scope for loop and control variables */ 13718e3e3a7aSWarner Losh luaX_next(ls); /* skip 'for' */ 13728e3e3a7aSWarner Losh varname = str_checkname(ls); /* first variable name */ 13738e3e3a7aSWarner Losh switch (ls->t.token) { 13748e3e3a7aSWarner Losh case '=': fornum(ls, varname, line); break; 13758e3e3a7aSWarner Losh case ',': case TK_IN: forlist(ls, varname); break; 13768e3e3a7aSWarner Losh default: luaX_syntaxerror(ls, "'=' or 'in' expected"); 13778e3e3a7aSWarner Losh } 13788e3e3a7aSWarner Losh check_match(ls, TK_END, TK_FOR, line); 13798e3e3a7aSWarner Losh leaveblock(fs); /* loop scope ('break' jumps to this point) */ 13808e3e3a7aSWarner Losh } 13818e3e3a7aSWarner Losh 13828e3e3a7aSWarner Losh 13838e3e3a7aSWarner Losh static void test_then_block (LexState *ls, int *escapelist) { 13848e3e3a7aSWarner Losh /* test_then_block -> [IF | ELSEIF] cond THEN block */ 13858e3e3a7aSWarner Losh BlockCnt bl; 13868e3e3a7aSWarner Losh FuncState *fs = ls->fs; 13878e3e3a7aSWarner Losh expdesc v; 13888e3e3a7aSWarner Losh int jf; /* instruction to skip 'then' code (if condition is false) */ 13898e3e3a7aSWarner Losh luaX_next(ls); /* skip IF or ELSEIF */ 13908e3e3a7aSWarner Losh expr(ls, &v); /* read condition */ 13918e3e3a7aSWarner Losh checknext(ls, TK_THEN); 13928e3e3a7aSWarner Losh if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { 13938e3e3a7aSWarner Losh luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ 13948e3e3a7aSWarner Losh enterblock(fs, &bl, 0); /* must enter block before 'goto' */ 13958e3e3a7aSWarner Losh gotostat(ls, v.t); /* handle goto/break */ 1396e112e9d2SKyle Evans while (testnext(ls, ';')) {} /* skip colons */ 13978e3e3a7aSWarner Losh if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ 13988e3e3a7aSWarner Losh leaveblock(fs); 13998e3e3a7aSWarner Losh return; /* and that is it */ 14008e3e3a7aSWarner Losh } 14018e3e3a7aSWarner Losh else /* must skip over 'then' part if condition is false */ 14028e3e3a7aSWarner Losh jf = luaK_jump(fs); 14038e3e3a7aSWarner Losh } 14048e3e3a7aSWarner Losh else { /* regular case (not goto/break) */ 14058e3e3a7aSWarner Losh luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ 14068e3e3a7aSWarner Losh enterblock(fs, &bl, 0); 14078e3e3a7aSWarner Losh jf = v.f; 14088e3e3a7aSWarner Losh } 14098e3e3a7aSWarner Losh statlist(ls); /* 'then' part */ 14108e3e3a7aSWarner Losh leaveblock(fs); 14118e3e3a7aSWarner Losh if (ls->t.token == TK_ELSE || 14128e3e3a7aSWarner Losh ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ 14138e3e3a7aSWarner Losh luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ 14148e3e3a7aSWarner Losh luaK_patchtohere(fs, jf); 14158e3e3a7aSWarner Losh } 14168e3e3a7aSWarner Losh 14178e3e3a7aSWarner Losh 14188e3e3a7aSWarner Losh static void ifstat (LexState *ls, int line) { 14198e3e3a7aSWarner Losh /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ 14208e3e3a7aSWarner Losh FuncState *fs = ls->fs; 14218e3e3a7aSWarner Losh int escapelist = NO_JUMP; /* exit list for finished parts */ 14228e3e3a7aSWarner Losh test_then_block(ls, &escapelist); /* IF cond THEN block */ 14238e3e3a7aSWarner Losh while (ls->t.token == TK_ELSEIF) 14248e3e3a7aSWarner Losh test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ 14258e3e3a7aSWarner Losh if (testnext(ls, TK_ELSE)) 14268e3e3a7aSWarner Losh block(ls); /* 'else' part */ 14278e3e3a7aSWarner Losh check_match(ls, TK_END, TK_IF, line); 14288e3e3a7aSWarner Losh luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ 14298e3e3a7aSWarner Losh } 14308e3e3a7aSWarner Losh 14318e3e3a7aSWarner Losh 14328e3e3a7aSWarner Losh static void localfunc (LexState *ls) { 14338e3e3a7aSWarner Losh expdesc b; 14348e3e3a7aSWarner Losh FuncState *fs = ls->fs; 14358e3e3a7aSWarner Losh new_localvar(ls, str_checkname(ls)); /* new local variable */ 14368e3e3a7aSWarner Losh adjustlocalvars(ls, 1); /* enter its scope */ 14378e3e3a7aSWarner Losh body(ls, &b, 0, ls->linenumber); /* function created in next register */ 14388e3e3a7aSWarner Losh /* debug information will only see the variable after this point! */ 14398e3e3a7aSWarner Losh getlocvar(fs, b.u.info)->startpc = fs->pc; 14408e3e3a7aSWarner Losh } 14418e3e3a7aSWarner Losh 14428e3e3a7aSWarner Losh 14438e3e3a7aSWarner Losh static void localstat (LexState *ls) { 14448e3e3a7aSWarner Losh /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ 14458e3e3a7aSWarner Losh int nvars = 0; 14468e3e3a7aSWarner Losh int nexps; 14478e3e3a7aSWarner Losh expdesc e; 14488e3e3a7aSWarner Losh do { 14498e3e3a7aSWarner Losh new_localvar(ls, str_checkname(ls)); 14508e3e3a7aSWarner Losh nvars++; 14518e3e3a7aSWarner Losh } while (testnext(ls, ',')); 14528e3e3a7aSWarner Losh if (testnext(ls, '=')) 14538e3e3a7aSWarner Losh nexps = explist(ls, &e); 14548e3e3a7aSWarner Losh else { 14558e3e3a7aSWarner Losh e.k = VVOID; 14568e3e3a7aSWarner Losh nexps = 0; 14578e3e3a7aSWarner Losh } 14588e3e3a7aSWarner Losh adjust_assign(ls, nvars, nexps, &e); 14598e3e3a7aSWarner Losh adjustlocalvars(ls, nvars); 14608e3e3a7aSWarner Losh } 14618e3e3a7aSWarner Losh 14628e3e3a7aSWarner Losh 14638e3e3a7aSWarner Losh static int funcname (LexState *ls, expdesc *v) { 14648e3e3a7aSWarner Losh /* funcname -> NAME {fieldsel} [':' NAME] */ 14658e3e3a7aSWarner Losh int ismethod = 0; 14668e3e3a7aSWarner Losh singlevar(ls, v); 14678e3e3a7aSWarner Losh while (ls->t.token == '.') 14688e3e3a7aSWarner Losh fieldsel(ls, v); 14698e3e3a7aSWarner Losh if (ls->t.token == ':') { 14708e3e3a7aSWarner Losh ismethod = 1; 14718e3e3a7aSWarner Losh fieldsel(ls, v); 14728e3e3a7aSWarner Losh } 14738e3e3a7aSWarner Losh return ismethod; 14748e3e3a7aSWarner Losh } 14758e3e3a7aSWarner Losh 14768e3e3a7aSWarner Losh 14778e3e3a7aSWarner Losh static void funcstat (LexState *ls, int line) { 14788e3e3a7aSWarner Losh /* funcstat -> FUNCTION funcname body */ 14798e3e3a7aSWarner Losh int ismethod; 14808e3e3a7aSWarner Losh expdesc v, b; 14818e3e3a7aSWarner Losh luaX_next(ls); /* skip FUNCTION */ 14828e3e3a7aSWarner Losh ismethod = funcname(ls, &v); 14838e3e3a7aSWarner Losh body(ls, &b, ismethod, line); 14848e3e3a7aSWarner Losh luaK_storevar(ls->fs, &v, &b); 14858e3e3a7aSWarner Losh luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ 14868e3e3a7aSWarner Losh } 14878e3e3a7aSWarner Losh 14888e3e3a7aSWarner Losh 14898e3e3a7aSWarner Losh static void exprstat (LexState *ls) { 14908e3e3a7aSWarner Losh /* stat -> func | assignment */ 14918e3e3a7aSWarner Losh FuncState *fs = ls->fs; 14928e3e3a7aSWarner Losh struct LHS_assign v; 14938e3e3a7aSWarner Losh suffixedexp(ls, &v.v); 14948e3e3a7aSWarner Losh if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ 14958e3e3a7aSWarner Losh v.prev = NULL; 14968e3e3a7aSWarner Losh assignment(ls, &v, 1); 14978e3e3a7aSWarner Losh } 14988e3e3a7aSWarner Losh else { /* stat -> func */ 14998e3e3a7aSWarner Losh check_condition(ls, v.v.k == VCALL, "syntax error"); 15008e3e3a7aSWarner Losh SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */ 15018e3e3a7aSWarner Losh } 15028e3e3a7aSWarner Losh } 15038e3e3a7aSWarner Losh 15048e3e3a7aSWarner Losh 15058e3e3a7aSWarner Losh static void retstat (LexState *ls) { 15068e3e3a7aSWarner Losh /* stat -> RETURN [explist] [';'] */ 15078e3e3a7aSWarner Losh FuncState *fs = ls->fs; 15088e3e3a7aSWarner Losh expdesc e; 15098e3e3a7aSWarner Losh int first, nret; /* registers with returned values */ 15108e3e3a7aSWarner Losh if (block_follow(ls, 1) || ls->t.token == ';') 15118e3e3a7aSWarner Losh first = nret = 0; /* return no values */ 15128e3e3a7aSWarner Losh else { 15138e3e3a7aSWarner Losh nret = explist(ls, &e); /* optional return values */ 15148e3e3a7aSWarner Losh if (hasmultret(e.k)) { 15158e3e3a7aSWarner Losh luaK_setmultret(fs, &e); 15168e3e3a7aSWarner Losh if (e.k == VCALL && nret == 1) { /* tail call? */ 15178e3e3a7aSWarner Losh SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); 15188e3e3a7aSWarner Losh lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); 15198e3e3a7aSWarner Losh } 15208e3e3a7aSWarner Losh first = fs->nactvar; 15218e3e3a7aSWarner Losh nret = LUA_MULTRET; /* return all values */ 15228e3e3a7aSWarner Losh } 15238e3e3a7aSWarner Losh else { 15248e3e3a7aSWarner Losh if (nret == 1) /* only one single value? */ 15258e3e3a7aSWarner Losh first = luaK_exp2anyreg(fs, &e); 15268e3e3a7aSWarner Losh else { 15278e3e3a7aSWarner Losh luaK_exp2nextreg(fs, &e); /* values must go to the stack */ 15288e3e3a7aSWarner Losh first = fs->nactvar; /* return all active values */ 15298e3e3a7aSWarner Losh lua_assert(nret == fs->freereg - first); 15308e3e3a7aSWarner Losh } 15318e3e3a7aSWarner Losh } 15328e3e3a7aSWarner Losh } 15338e3e3a7aSWarner Losh luaK_ret(fs, first, nret); 15348e3e3a7aSWarner Losh testnext(ls, ';'); /* skip optional semicolon */ 15358e3e3a7aSWarner Losh } 15368e3e3a7aSWarner Losh 15378e3e3a7aSWarner Losh 15388e3e3a7aSWarner Losh static void statement (LexState *ls) { 15398e3e3a7aSWarner Losh int line = ls->linenumber; /* may be needed for error messages */ 15408e3e3a7aSWarner Losh enterlevel(ls); 15418e3e3a7aSWarner Losh switch (ls->t.token) { 15428e3e3a7aSWarner Losh case ';': { /* stat -> ';' (empty statement) */ 15438e3e3a7aSWarner Losh luaX_next(ls); /* skip ';' */ 15448e3e3a7aSWarner Losh break; 15458e3e3a7aSWarner Losh } 15468e3e3a7aSWarner Losh case TK_IF: { /* stat -> ifstat */ 15478e3e3a7aSWarner Losh ifstat(ls, line); 15488e3e3a7aSWarner Losh break; 15498e3e3a7aSWarner Losh } 15508e3e3a7aSWarner Losh case TK_WHILE: { /* stat -> whilestat */ 15518e3e3a7aSWarner Losh whilestat(ls, line); 15528e3e3a7aSWarner Losh break; 15538e3e3a7aSWarner Losh } 15548e3e3a7aSWarner Losh case TK_DO: { /* stat -> DO block END */ 15558e3e3a7aSWarner Losh luaX_next(ls); /* skip DO */ 15568e3e3a7aSWarner Losh block(ls); 15578e3e3a7aSWarner Losh check_match(ls, TK_END, TK_DO, line); 15588e3e3a7aSWarner Losh break; 15598e3e3a7aSWarner Losh } 15608e3e3a7aSWarner Losh case TK_FOR: { /* stat -> forstat */ 15618e3e3a7aSWarner Losh forstat(ls, line); 15628e3e3a7aSWarner Losh break; 15638e3e3a7aSWarner Losh } 15648e3e3a7aSWarner Losh case TK_REPEAT: { /* stat -> repeatstat */ 15658e3e3a7aSWarner Losh repeatstat(ls, line); 15668e3e3a7aSWarner Losh break; 15678e3e3a7aSWarner Losh } 15688e3e3a7aSWarner Losh case TK_FUNCTION: { /* stat -> funcstat */ 15698e3e3a7aSWarner Losh funcstat(ls, line); 15708e3e3a7aSWarner Losh break; 15718e3e3a7aSWarner Losh } 15728e3e3a7aSWarner Losh case TK_LOCAL: { /* stat -> localstat */ 15738e3e3a7aSWarner Losh luaX_next(ls); /* skip LOCAL */ 15748e3e3a7aSWarner Losh if (testnext(ls, TK_FUNCTION)) /* local function? */ 15758e3e3a7aSWarner Losh localfunc(ls); 15768e3e3a7aSWarner Losh else 15778e3e3a7aSWarner Losh localstat(ls); 15788e3e3a7aSWarner Losh break; 15798e3e3a7aSWarner Losh } 15808e3e3a7aSWarner Losh case TK_DBCOLON: { /* stat -> label */ 15818e3e3a7aSWarner Losh luaX_next(ls); /* skip double colon */ 15828e3e3a7aSWarner Losh labelstat(ls, str_checkname(ls), line); 15838e3e3a7aSWarner Losh break; 15848e3e3a7aSWarner Losh } 15858e3e3a7aSWarner Losh case TK_RETURN: { /* stat -> retstat */ 15868e3e3a7aSWarner Losh luaX_next(ls); /* skip RETURN */ 15878e3e3a7aSWarner Losh retstat(ls); 15888e3e3a7aSWarner Losh break; 15898e3e3a7aSWarner Losh } 15908e3e3a7aSWarner Losh case TK_BREAK: /* stat -> breakstat */ 15918e3e3a7aSWarner Losh case TK_GOTO: { /* stat -> 'goto' NAME */ 15928e3e3a7aSWarner Losh gotostat(ls, luaK_jump(ls->fs)); 15938e3e3a7aSWarner Losh break; 15948e3e3a7aSWarner Losh } 15958e3e3a7aSWarner Losh default: { /* stat -> func | assignment */ 15968e3e3a7aSWarner Losh exprstat(ls); 15978e3e3a7aSWarner Losh break; 15988e3e3a7aSWarner Losh } 15998e3e3a7aSWarner Losh } 16008e3e3a7aSWarner Losh lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && 16018e3e3a7aSWarner Losh ls->fs->freereg >= ls->fs->nactvar); 16028e3e3a7aSWarner Losh ls->fs->freereg = ls->fs->nactvar; /* free registers */ 16038e3e3a7aSWarner Losh leavelevel(ls); 16048e3e3a7aSWarner Losh } 16058e3e3a7aSWarner Losh 16068e3e3a7aSWarner Losh /* }====================================================================== */ 16078e3e3a7aSWarner Losh 16088e3e3a7aSWarner Losh 16098e3e3a7aSWarner Losh /* 16108e3e3a7aSWarner Losh ** compiles the main function, which is a regular vararg function with an 16118e3e3a7aSWarner Losh ** upvalue named LUA_ENV 16128e3e3a7aSWarner Losh */ 16138e3e3a7aSWarner Losh static void mainfunc (LexState *ls, FuncState *fs) { 16148e3e3a7aSWarner Losh BlockCnt bl; 16158e3e3a7aSWarner Losh expdesc v; 16168e3e3a7aSWarner Losh open_func(ls, fs, &bl); 16178e3e3a7aSWarner Losh fs->f->is_vararg = 1; /* main function is always declared vararg */ 16188e3e3a7aSWarner Losh init_exp(&v, VLOCAL, 0); /* create and... */ 16198e3e3a7aSWarner Losh newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ 1620*bf9580a1SKyle Evans luaC_objbarrier(ls->L, fs->f, ls->envn); 16218e3e3a7aSWarner Losh luaX_next(ls); /* read first token */ 16228e3e3a7aSWarner Losh statlist(ls); /* parse main body */ 16238e3e3a7aSWarner Losh check(ls, TK_EOS); 16248e3e3a7aSWarner Losh close_func(ls); 16258e3e3a7aSWarner Losh } 16268e3e3a7aSWarner Losh 16278e3e3a7aSWarner Losh 16288e3e3a7aSWarner Losh LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 16298e3e3a7aSWarner Losh Dyndata *dyd, const char *name, int firstchar) { 16308e3e3a7aSWarner Losh LexState lexstate; 16318e3e3a7aSWarner Losh FuncState funcstate; 16328e3e3a7aSWarner Losh LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ 16338e3e3a7aSWarner Losh setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ 16348e3e3a7aSWarner Losh luaD_inctop(L); 16358e3e3a7aSWarner Losh lexstate.h = luaH_new(L); /* create table for scanner */ 16368e3e3a7aSWarner Losh sethvalue(L, L->top, lexstate.h); /* anchor it */ 16378e3e3a7aSWarner Losh luaD_inctop(L); 16388e3e3a7aSWarner Losh funcstate.f = cl->p = luaF_newproto(L); 1639*bf9580a1SKyle Evans luaC_objbarrier(L, cl, cl->p); 16408e3e3a7aSWarner Losh funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ 16418e3e3a7aSWarner Losh lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ 16428e3e3a7aSWarner Losh lexstate.buff = buff; 16438e3e3a7aSWarner Losh lexstate.dyd = dyd; 16448e3e3a7aSWarner Losh dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; 16458e3e3a7aSWarner Losh luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); 16468e3e3a7aSWarner Losh mainfunc(&lexstate, &funcstate); 16478e3e3a7aSWarner Losh lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); 16488e3e3a7aSWarner Losh /* all scopes should be correctly finished */ 16498e3e3a7aSWarner Losh lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); 16508e3e3a7aSWarner Losh L->top--; /* remove scanner's table */ 16518e3e3a7aSWarner Losh return cl; /* closure is on the stack, too */ 16528e3e3a7aSWarner Losh } 16538e3e3a7aSWarner Losh 1654