xref: /freebsd/contrib/lua/src/lparser.c (revision a9490b81b032b43cdb3c8c76b4d01bbad9ff82c1)
18e3e3a7aSWarner Losh /*
20495ed39SKyle Evans ** $Id: lparser.c $
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 
130495ed39SKyle Evans #include <limits.h>
148e3e3a7aSWarner Losh #include <string.h>
158e3e3a7aSWarner Losh 
168e3e3a7aSWarner Losh #include "lua.h"
178e3e3a7aSWarner Losh 
188e3e3a7aSWarner Losh #include "lcode.h"
198e3e3a7aSWarner Losh #include "ldebug.h"
208e3e3a7aSWarner Losh #include "ldo.h"
218e3e3a7aSWarner Losh #include "lfunc.h"
228e3e3a7aSWarner Losh #include "llex.h"
238e3e3a7aSWarner Losh #include "lmem.h"
248e3e3a7aSWarner Losh #include "lobject.h"
258e3e3a7aSWarner Losh #include "lopcodes.h"
268e3e3a7aSWarner Losh #include "lparser.h"
278e3e3a7aSWarner Losh #include "lstate.h"
288e3e3a7aSWarner Losh #include "lstring.h"
298e3e3a7aSWarner Losh #include "ltable.h"
308e3e3a7aSWarner Losh 
318e3e3a7aSWarner Losh 
328e3e3a7aSWarner Losh 
338e3e3a7aSWarner Losh /* maximum number of local variables per function (must be smaller
348e3e3a7aSWarner Losh    than 250, due to the bytecode format) */
358e3e3a7aSWarner Losh #define MAXVARS		200
368e3e3a7aSWarner Losh 
378e3e3a7aSWarner Losh 
388e3e3a7aSWarner Losh #define hasmultret(k)		((k) == VCALL || (k) == VVARARG)
398e3e3a7aSWarner Losh 
408e3e3a7aSWarner Losh 
418e3e3a7aSWarner Losh /* because all strings are unified by the scanner, the parser
428e3e3a7aSWarner Losh    can use pointer equality for string equality */
438e3e3a7aSWarner Losh #define eqstr(a,b)	((a) == (b))
448e3e3a7aSWarner Losh 
458e3e3a7aSWarner Losh 
468e3e3a7aSWarner Losh /*
478e3e3a7aSWarner Losh ** nodes for block list (list of active blocks)
488e3e3a7aSWarner Losh */
498e3e3a7aSWarner Losh typedef struct BlockCnt {
508e3e3a7aSWarner Losh   struct BlockCnt *previous;  /* chain */
518e3e3a7aSWarner Losh   int firstlabel;  /* index of first label in this block */
528e3e3a7aSWarner Losh   int firstgoto;  /* index of first pending goto in this block */
538e3e3a7aSWarner Losh   lu_byte nactvar;  /* # active locals outside the block */
548e3e3a7aSWarner Losh   lu_byte upval;  /* true if some variable in the block is an upvalue */
558e3e3a7aSWarner Losh   lu_byte isloop;  /* true if 'block' is a loop */
560495ed39SKyle Evans   lu_byte insidetbc;  /* true if inside the scope of a to-be-closed var. */
578e3e3a7aSWarner Losh } BlockCnt;
588e3e3a7aSWarner Losh 
598e3e3a7aSWarner Losh 
608e3e3a7aSWarner Losh 
618e3e3a7aSWarner Losh /*
628e3e3a7aSWarner Losh ** prototypes for recursive non-terminal functions
638e3e3a7aSWarner Losh */
648e3e3a7aSWarner Losh static void statement (LexState *ls);
658e3e3a7aSWarner Losh static void expr (LexState *ls, expdesc *v);
668e3e3a7aSWarner Losh 
678e3e3a7aSWarner Losh 
error_expected(LexState * ls,int token)688e3e3a7aSWarner Losh static l_noret error_expected (LexState *ls, int token) {
698e3e3a7aSWarner Losh   luaX_syntaxerror(ls,
708e3e3a7aSWarner Losh       luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token)));
718e3e3a7aSWarner Losh }
728e3e3a7aSWarner Losh 
738e3e3a7aSWarner Losh 
errorlimit(FuncState * fs,int limit,const char * what)748e3e3a7aSWarner Losh static l_noret errorlimit (FuncState *fs, int limit, const char *what) {
758e3e3a7aSWarner Losh   lua_State *L = fs->ls->L;
768e3e3a7aSWarner Losh   const char *msg;
778e3e3a7aSWarner Losh   int line = fs->f->linedefined;
788e3e3a7aSWarner Losh   const char *where = (line == 0)
798e3e3a7aSWarner Losh                       ? "main function"
808e3e3a7aSWarner Losh                       : luaO_pushfstring(L, "function at line %d", line);
818e3e3a7aSWarner Losh   msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s",
828e3e3a7aSWarner Losh                              what, limit, where);
838e3e3a7aSWarner Losh   luaX_syntaxerror(fs->ls, msg);
848e3e3a7aSWarner Losh }
858e3e3a7aSWarner Losh 
868e3e3a7aSWarner Losh 
checklimit(FuncState * fs,int v,int l,const char * what)878e3e3a7aSWarner Losh static void checklimit (FuncState *fs, int v, int l, const char *what) {
888e3e3a7aSWarner Losh   if (v > l) errorlimit(fs, l, what);
898e3e3a7aSWarner Losh }
908e3e3a7aSWarner Losh 
918e3e3a7aSWarner Losh 
920495ed39SKyle Evans /*
930495ed39SKyle Evans ** Test whether next token is 'c'; if so, skip it.
940495ed39SKyle Evans */
testnext(LexState * ls,int c)958e3e3a7aSWarner Losh static int testnext (LexState *ls, int c) {
968e3e3a7aSWarner Losh   if (ls->t.token == c) {
978e3e3a7aSWarner Losh     luaX_next(ls);
988e3e3a7aSWarner Losh     return 1;
998e3e3a7aSWarner Losh   }
1008e3e3a7aSWarner Losh   else return 0;
1018e3e3a7aSWarner Losh }
1028e3e3a7aSWarner Losh 
1038e3e3a7aSWarner Losh 
1040495ed39SKyle Evans /*
1050495ed39SKyle Evans ** Check that next token is 'c'.
1060495ed39SKyle Evans */
check(LexState * ls,int c)1078e3e3a7aSWarner Losh static void check (LexState *ls, int c) {
1088e3e3a7aSWarner Losh   if (ls->t.token != c)
1098e3e3a7aSWarner Losh     error_expected(ls, c);
1108e3e3a7aSWarner Losh }
1118e3e3a7aSWarner Losh 
1128e3e3a7aSWarner Losh 
1130495ed39SKyle Evans /*
1140495ed39SKyle Evans ** Check that next token is 'c' and skip it.
1150495ed39SKyle Evans */
checknext(LexState * ls,int c)1168e3e3a7aSWarner Losh static void checknext (LexState *ls, int c) {
1178e3e3a7aSWarner Losh   check(ls, c);
1188e3e3a7aSWarner Losh   luaX_next(ls);
1198e3e3a7aSWarner Losh }
1208e3e3a7aSWarner Losh 
1218e3e3a7aSWarner Losh 
1228e3e3a7aSWarner Losh #define check_condition(ls,c,msg)	{ if (!(c)) luaX_syntaxerror(ls, msg); }
1238e3e3a7aSWarner Losh 
1248e3e3a7aSWarner Losh 
1250495ed39SKyle Evans /*
1260495ed39SKyle Evans ** Check that next token is 'what' and skip it. In case of error,
1270495ed39SKyle Evans ** raise an error that the expected 'what' should match a 'who'
1280495ed39SKyle Evans ** in line 'where' (if that is not the current line).
1290495ed39SKyle Evans */
check_match(LexState * ls,int what,int who,int where)1308e3e3a7aSWarner Losh static void check_match (LexState *ls, int what, int who, int where) {
1318c784bb8SWarner Losh   if (l_unlikely(!testnext(ls, what))) {
1320495ed39SKyle Evans     if (where == ls->linenumber)  /* all in the same line? */
1330495ed39SKyle Evans       error_expected(ls, what);  /* do not need a complex message */
1348e3e3a7aSWarner Losh     else {
1358e3e3a7aSWarner Losh       luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
1368e3e3a7aSWarner Losh              "%s expected (to close %s at line %d)",
1378e3e3a7aSWarner Losh               luaX_token2str(ls, what), luaX_token2str(ls, who), where));
1388e3e3a7aSWarner Losh     }
1398e3e3a7aSWarner Losh   }
1408e3e3a7aSWarner Losh }
1418e3e3a7aSWarner Losh 
1428e3e3a7aSWarner Losh 
str_checkname(LexState * ls)1438e3e3a7aSWarner Losh static TString *str_checkname (LexState *ls) {
1448e3e3a7aSWarner Losh   TString *ts;
1458e3e3a7aSWarner Losh   check(ls, TK_NAME);
1468e3e3a7aSWarner Losh   ts = ls->t.seminfo.ts;
1478e3e3a7aSWarner Losh   luaX_next(ls);
1488e3e3a7aSWarner Losh   return ts;
1498e3e3a7aSWarner Losh }
1508e3e3a7aSWarner Losh 
1518e3e3a7aSWarner Losh 
init_exp(expdesc * e,expkind k,int i)1528e3e3a7aSWarner Losh static void init_exp (expdesc *e, expkind k, int i) {
1538e3e3a7aSWarner Losh   e->f = e->t = NO_JUMP;
1548e3e3a7aSWarner Losh   e->k = k;
1558e3e3a7aSWarner Losh   e->u.info = i;
1568e3e3a7aSWarner Losh }
1578e3e3a7aSWarner Losh 
1588e3e3a7aSWarner Losh 
codestring(expdesc * e,TString * s)1590495ed39SKyle Evans static void codestring (expdesc *e, TString *s) {
1600495ed39SKyle Evans   e->f = e->t = NO_JUMP;
1610495ed39SKyle Evans   e->k = VKSTR;
1620495ed39SKyle Evans   e->u.strval = s;
1638e3e3a7aSWarner Losh }
1648e3e3a7aSWarner Losh 
1658e3e3a7aSWarner Losh 
codename(LexState * ls,expdesc * e)1660495ed39SKyle Evans static void codename (LexState *ls, expdesc *e) {
1670495ed39SKyle Evans   codestring(e, str_checkname(ls));
1688e3e3a7aSWarner Losh }
1698e3e3a7aSWarner Losh 
1708e3e3a7aSWarner Losh 
1710495ed39SKyle Evans /*
1720495ed39SKyle Evans ** Register a new local variable in the active 'Proto' (for debug
1730495ed39SKyle Evans ** information).
1740495ed39SKyle Evans */
registerlocalvar(LexState * ls,FuncState * fs,TString * varname)1750495ed39SKyle Evans static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) {
1768e3e3a7aSWarner Losh   Proto *f = fs->f;
1778e3e3a7aSWarner Losh   int oldsize = f->sizelocvars;
1780495ed39SKyle Evans   luaM_growvector(ls->L, f->locvars, fs->ndebugvars, f->sizelocvars,
1798e3e3a7aSWarner Losh                   LocVar, SHRT_MAX, "local variables");
1808e3e3a7aSWarner Losh   while (oldsize < f->sizelocvars)
1818e3e3a7aSWarner Losh     f->locvars[oldsize++].varname = NULL;
1820495ed39SKyle Evans   f->locvars[fs->ndebugvars].varname = varname;
1830495ed39SKyle Evans   f->locvars[fs->ndebugvars].startpc = fs->pc;
1848e3e3a7aSWarner Losh   luaC_objbarrier(ls->L, f, varname);
1850495ed39SKyle Evans   return fs->ndebugvars++;
1868e3e3a7aSWarner Losh }
1878e3e3a7aSWarner Losh 
1888e3e3a7aSWarner Losh 
1890495ed39SKyle Evans /*
1900495ed39SKyle Evans ** Create a new local variable with the given 'name'. Return its index
1910495ed39SKyle Evans ** in the function.
1920495ed39SKyle Evans */
new_localvar(LexState * ls,TString * name)1930495ed39SKyle Evans static int new_localvar (LexState *ls, TString *name) {
1940495ed39SKyle Evans   lua_State *L = ls->L;
1958e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1968e3e3a7aSWarner Losh   Dyndata *dyd = ls->dyd;
1970495ed39SKyle Evans   Vardesc *var;
1988e3e3a7aSWarner Losh   checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
1998e3e3a7aSWarner Losh                  MAXVARS, "local variables");
2000495ed39SKyle Evans   luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
2010495ed39SKyle Evans                   dyd->actvar.size, Vardesc, USHRT_MAX, "local variables");
2020495ed39SKyle Evans   var = &dyd->actvar.arr[dyd->actvar.n++];
2030495ed39SKyle Evans   var->vd.kind = VDKREG;  /* default */
2040495ed39SKyle Evans   var->vd.name = name;
2050495ed39SKyle Evans   return dyd->actvar.n - 1 - fs->firstlocal;
2068e3e3a7aSWarner Losh }
2078e3e3a7aSWarner Losh 
2088e3e3a7aSWarner Losh #define new_localvarliteral(ls,v) \
2090495ed39SKyle Evans     new_localvar(ls,  \
2100495ed39SKyle Evans       luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1));
2118e3e3a7aSWarner Losh 
2128e3e3a7aSWarner Losh 
2130495ed39SKyle Evans 
2140495ed39SKyle Evans /*
2150495ed39SKyle Evans ** Return the "variable description" (Vardesc) of a given variable.
2160495ed39SKyle Evans ** (Unless noted otherwise, all variables are referred to by their
2170495ed39SKyle Evans ** compiler indices.)
2180495ed39SKyle Evans */
getlocalvardesc(FuncState * fs,int vidx)2190495ed39SKyle Evans static Vardesc *getlocalvardesc (FuncState *fs, int vidx) {
2200495ed39SKyle Evans   return &fs->ls->dyd->actvar.arr[fs->firstlocal + vidx];
2210495ed39SKyle Evans }
2220495ed39SKyle Evans 
2230495ed39SKyle Evans 
2240495ed39SKyle Evans /*
2258c784bb8SWarner Losh ** Convert 'nvar', a compiler index level, to its corresponding
2268c784bb8SWarner Losh ** register. For that, search for the highest variable below that level
2278c784bb8SWarner Losh ** that is in a register and uses its register index ('ridx') plus one.
2280495ed39SKyle Evans */
reglevel(FuncState * fs,int nvar)2298c784bb8SWarner Losh static int reglevel (FuncState *fs, int nvar) {
2300495ed39SKyle Evans   while (nvar-- > 0) {
2318c784bb8SWarner Losh     Vardesc *vd = getlocalvardesc(fs, nvar);  /* get previous variable */
2328c784bb8SWarner Losh     if (vd->vd.kind != RDKCTC)  /* is in a register? */
2338c784bb8SWarner Losh       return vd->vd.ridx + 1;
2340495ed39SKyle Evans   }
2358c784bb8SWarner Losh   return 0;  /* no variables in registers */
2360495ed39SKyle Evans }
2370495ed39SKyle Evans 
2380495ed39SKyle Evans 
2390495ed39SKyle Evans /*
2408c784bb8SWarner Losh ** Return the number of variables in the register stack for the given
2418c784bb8SWarner Losh ** function.
2420495ed39SKyle Evans */
luaY_nvarstack(FuncState * fs)2430495ed39SKyle Evans int luaY_nvarstack (FuncState *fs) {
2448c784bb8SWarner Losh   return reglevel(fs, fs->nactvar);
2450495ed39SKyle Evans }
2460495ed39SKyle Evans 
2470495ed39SKyle Evans 
2480495ed39SKyle Evans /*
2490495ed39SKyle Evans ** Get the debug-information entry for current variable 'vidx'.
2500495ed39SKyle Evans */
localdebuginfo(FuncState * fs,int vidx)2510495ed39SKyle Evans static LocVar *localdebuginfo (FuncState *fs, int vidx) {
2520495ed39SKyle Evans   Vardesc *vd = getlocalvardesc(fs,  vidx);
2530495ed39SKyle Evans   if (vd->vd.kind == RDKCTC)
2540495ed39SKyle Evans     return NULL;  /* no debug info. for constants */
2550495ed39SKyle Evans   else {
2560495ed39SKyle Evans     int idx = vd->vd.pidx;
2570495ed39SKyle Evans     lua_assert(idx < fs->ndebugvars);
2588e3e3a7aSWarner Losh     return &fs->f->locvars[idx];
2598e3e3a7aSWarner Losh   }
2600495ed39SKyle Evans }
2618e3e3a7aSWarner Losh 
2628e3e3a7aSWarner Losh 
2630495ed39SKyle Evans /*
2640495ed39SKyle Evans ** Create an expression representing variable 'vidx'
2650495ed39SKyle Evans */
init_var(FuncState * fs,expdesc * e,int vidx)2660495ed39SKyle Evans static void init_var (FuncState *fs, expdesc *e, int vidx) {
2670495ed39SKyle Evans   e->f = e->t = NO_JUMP;
2680495ed39SKyle Evans   e->k = VLOCAL;
2690495ed39SKyle Evans   e->u.var.vidx = vidx;
2708c784bb8SWarner Losh   e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx;
2710495ed39SKyle Evans }
2720495ed39SKyle Evans 
2730495ed39SKyle Evans 
2740495ed39SKyle Evans /*
2750495ed39SKyle Evans ** Raises an error if variable described by 'e' is read only
2760495ed39SKyle Evans */
check_readonly(LexState * ls,expdesc * e)2770495ed39SKyle Evans static void check_readonly (LexState *ls, expdesc *e) {
2780495ed39SKyle Evans   FuncState *fs = ls->fs;
2790495ed39SKyle Evans   TString *varname = NULL;  /* to be set if variable is const */
2800495ed39SKyle Evans   switch (e->k) {
2810495ed39SKyle Evans     case VCONST: {
2820495ed39SKyle Evans       varname = ls->dyd->actvar.arr[e->u.info].vd.name;
2830495ed39SKyle Evans       break;
2840495ed39SKyle Evans     }
2850495ed39SKyle Evans     case VLOCAL: {
2860495ed39SKyle Evans       Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx);
2870495ed39SKyle Evans       if (vardesc->vd.kind != VDKREG)  /* not a regular variable? */
2880495ed39SKyle Evans         varname = vardesc->vd.name;
2890495ed39SKyle Evans       break;
2900495ed39SKyle Evans     }
2910495ed39SKyle Evans     case VUPVAL: {
2920495ed39SKyle Evans       Upvaldesc *up = &fs->f->upvalues[e->u.info];
2930495ed39SKyle Evans       if (up->kind != VDKREG)
2940495ed39SKyle Evans         varname = up->name;
2950495ed39SKyle Evans       break;
2960495ed39SKyle Evans     }
2970495ed39SKyle Evans     default:
2980495ed39SKyle Evans       return;  /* other cases cannot be read-only */
2990495ed39SKyle Evans   }
3000495ed39SKyle Evans   if (varname) {
3010495ed39SKyle Evans     const char *msg = luaO_pushfstring(ls->L,
3020495ed39SKyle Evans        "attempt to assign to const variable '%s'", getstr(varname));
3030495ed39SKyle Evans     luaK_semerror(ls, msg);  /* error */
3040495ed39SKyle Evans   }
3050495ed39SKyle Evans }
3060495ed39SKyle Evans 
3070495ed39SKyle Evans 
3080495ed39SKyle Evans /*
3090495ed39SKyle Evans ** Start the scope for the last 'nvars' created variables.
3100495ed39SKyle Evans */
adjustlocalvars(LexState * ls,int nvars)3118e3e3a7aSWarner Losh static void adjustlocalvars (LexState *ls, int nvars) {
3128e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
3138c784bb8SWarner Losh   int reglevel = luaY_nvarstack(fs);
3140495ed39SKyle Evans   int i;
3150495ed39SKyle Evans   for (i = 0; i < nvars; i++) {
3160495ed39SKyle Evans     int vidx = fs->nactvar++;
3170495ed39SKyle Evans     Vardesc *var = getlocalvardesc(fs, vidx);
3188c784bb8SWarner Losh     var->vd.ridx = reglevel++;
3190495ed39SKyle Evans     var->vd.pidx = registerlocalvar(ls, fs, var->vd.name);
3208e3e3a7aSWarner Losh   }
3218e3e3a7aSWarner Losh }
3228e3e3a7aSWarner Losh 
3238e3e3a7aSWarner Losh 
3240495ed39SKyle Evans /*
3250495ed39SKyle Evans ** Close the scope for all variables up to level 'tolevel'.
3260495ed39SKyle Evans ** (debug info.)
3270495ed39SKyle Evans */
removevars(FuncState * fs,int tolevel)3288e3e3a7aSWarner Losh static void removevars (FuncState *fs, int tolevel) {
3298e3e3a7aSWarner Losh   fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel);
3300495ed39SKyle Evans   while (fs->nactvar > tolevel) {
3310495ed39SKyle Evans     LocVar *var = localdebuginfo(fs, --fs->nactvar);
3320495ed39SKyle Evans     if (var)  /* does it have debug information? */
3330495ed39SKyle Evans       var->endpc = fs->pc;
3340495ed39SKyle Evans   }
3358e3e3a7aSWarner Losh }
3368e3e3a7aSWarner Losh 
3378e3e3a7aSWarner Losh 
3380495ed39SKyle Evans /*
3390495ed39SKyle Evans ** Search the upvalues of the function 'fs' for one
3400495ed39SKyle Evans ** with the given 'name'.
3410495ed39SKyle Evans */
searchupvalue(FuncState * fs,TString * name)3428e3e3a7aSWarner Losh static int searchupvalue (FuncState *fs, TString *name) {
3438e3e3a7aSWarner Losh   int i;
3448e3e3a7aSWarner Losh   Upvaldesc *up = fs->f->upvalues;
3458e3e3a7aSWarner Losh   for (i = 0; i < fs->nups; i++) {
3468e3e3a7aSWarner Losh     if (eqstr(up[i].name, name)) return i;
3478e3e3a7aSWarner Losh   }
3488e3e3a7aSWarner Losh   return -1;  /* not found */
3498e3e3a7aSWarner Losh }
3508e3e3a7aSWarner Losh 
3518e3e3a7aSWarner Losh 
allocupvalue(FuncState * fs)3520495ed39SKyle Evans static Upvaldesc *allocupvalue (FuncState *fs) {
3538e3e3a7aSWarner Losh   Proto *f = fs->f;
3548e3e3a7aSWarner Losh   int oldsize = f->sizeupvalues;
3558e3e3a7aSWarner Losh   checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
3568e3e3a7aSWarner Losh   luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
3578e3e3a7aSWarner Losh                   Upvaldesc, MAXUPVAL, "upvalues");
3588e3e3a7aSWarner Losh   while (oldsize < f->sizeupvalues)
3598e3e3a7aSWarner Losh     f->upvalues[oldsize++].name = NULL;
3600495ed39SKyle Evans   return &f->upvalues[fs->nups++];
3618e3e3a7aSWarner Losh }
3628e3e3a7aSWarner Losh 
3638e3e3a7aSWarner Losh 
newupvalue(FuncState * fs,TString * name,expdesc * v)3640495ed39SKyle Evans static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
3650495ed39SKyle Evans   Upvaldesc *up = allocupvalue(fs);
3660495ed39SKyle Evans   FuncState *prev = fs->prev;
3670495ed39SKyle Evans   if (v->k == VLOCAL) {
3680495ed39SKyle Evans     up->instack = 1;
3698c784bb8SWarner Losh     up->idx = v->u.var.ridx;
3700495ed39SKyle Evans     up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind;
3710495ed39SKyle Evans     lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name));
3720495ed39SKyle Evans   }
3730495ed39SKyle Evans   else {
3740495ed39SKyle Evans     up->instack = 0;
3750495ed39SKyle Evans     up->idx = cast_byte(v->u.info);
3760495ed39SKyle Evans     up->kind = prev->f->upvalues[v->u.info].kind;
3770495ed39SKyle Evans     lua_assert(eqstr(name, prev->f->upvalues[v->u.info].name));
3780495ed39SKyle Evans   }
3790495ed39SKyle Evans   up->name = name;
3800495ed39SKyle Evans   luaC_objbarrier(fs->ls->L, fs->f, name);
3810495ed39SKyle Evans   return fs->nups - 1;
3820495ed39SKyle Evans }
3830495ed39SKyle Evans 
3840495ed39SKyle Evans 
3850495ed39SKyle Evans /*
3860495ed39SKyle Evans ** Look for an active local variable with the name 'n' in the
3870495ed39SKyle Evans ** function 'fs'. If found, initialize 'var' with it and return
3880495ed39SKyle Evans ** its expression kind; otherwise return -1.
3890495ed39SKyle Evans */
searchvar(FuncState * fs,TString * n,expdesc * var)3900495ed39SKyle Evans static int searchvar (FuncState *fs, TString *n, expdesc *var) {
3918e3e3a7aSWarner Losh   int i;
3928e3e3a7aSWarner Losh   for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
3930495ed39SKyle Evans     Vardesc *vd = getlocalvardesc(fs, i);
3940495ed39SKyle Evans     if (eqstr(n, vd->vd.name)) {  /* found? */
3950495ed39SKyle Evans       if (vd->vd.kind == RDKCTC)  /* compile-time constant? */
3960495ed39SKyle Evans         init_exp(var, VCONST, fs->firstlocal + i);
3970495ed39SKyle Evans       else  /* real variable */
3980495ed39SKyle Evans         init_var(fs, var, i);
3990495ed39SKyle Evans       return var->k;
4000495ed39SKyle Evans     }
4018e3e3a7aSWarner Losh   }
4028e3e3a7aSWarner Losh   return -1;  /* not found */
4038e3e3a7aSWarner Losh }
4048e3e3a7aSWarner Losh 
4058e3e3a7aSWarner Losh 
4068e3e3a7aSWarner Losh /*
4070495ed39SKyle Evans ** Mark block where variable at given level was defined
4080495ed39SKyle Evans ** (to emit close instructions later).
4098e3e3a7aSWarner Losh */
markupval(FuncState * fs,int level)4108e3e3a7aSWarner Losh static void markupval (FuncState *fs, int level) {
4118e3e3a7aSWarner Losh   BlockCnt *bl = fs->bl;
4128e3e3a7aSWarner Losh   while (bl->nactvar > level)
4138e3e3a7aSWarner Losh     bl = bl->previous;
4148e3e3a7aSWarner Losh   bl->upval = 1;
4150495ed39SKyle Evans   fs->needclose = 1;
4168e3e3a7aSWarner Losh }
4178e3e3a7aSWarner Losh 
4188e3e3a7aSWarner Losh 
4198e3e3a7aSWarner Losh /*
4208c784bb8SWarner Losh ** Mark that current block has a to-be-closed variable.
4218c784bb8SWarner Losh */
marktobeclosed(FuncState * fs)4228c784bb8SWarner Losh static void marktobeclosed (FuncState *fs) {
4238c784bb8SWarner Losh   BlockCnt *bl = fs->bl;
4248c784bb8SWarner Losh   bl->upval = 1;
4258c784bb8SWarner Losh   bl->insidetbc = 1;
4268c784bb8SWarner Losh   fs->needclose = 1;
4278c784bb8SWarner Losh }
4288c784bb8SWarner Losh 
4298c784bb8SWarner Losh 
4308c784bb8SWarner Losh /*
4310495ed39SKyle Evans ** Find a variable with the given name 'n'. If it is an upvalue, add
4320495ed39SKyle Evans ** this upvalue into all intermediate functions. If it is a global, set
4330495ed39SKyle Evans ** 'var' as 'void' as a flag.
4348e3e3a7aSWarner Losh */
singlevaraux(FuncState * fs,TString * n,expdesc * var,int base)4358e3e3a7aSWarner Losh static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
4368e3e3a7aSWarner Losh   if (fs == NULL)  /* no more levels? */
4378e3e3a7aSWarner Losh     init_exp(var, VVOID, 0);  /* default is global */
4388e3e3a7aSWarner Losh   else {
4390495ed39SKyle Evans     int v = searchvar(fs, n, var);  /* look up locals at current level */
4408e3e3a7aSWarner Losh     if (v >= 0) {  /* found? */
4410495ed39SKyle Evans       if (v == VLOCAL && !base)
4420495ed39SKyle Evans         markupval(fs, var->u.var.vidx);  /* local will be used as an upval */
4438e3e3a7aSWarner Losh     }
4448e3e3a7aSWarner Losh     else {  /* not found as local at current level; try upvalues */
4458e3e3a7aSWarner Losh       int idx = searchupvalue(fs, n);  /* try existing upvalues */
4468e3e3a7aSWarner Losh       if (idx < 0) {  /* not found? */
4478e3e3a7aSWarner Losh         singlevaraux(fs->prev, n, var, 0);  /* try upper levels */
4480495ed39SKyle Evans         if (var->k == VLOCAL || var->k == VUPVAL)  /* local or upvalue? */
4498e3e3a7aSWarner Losh           idx  = newupvalue(fs, n, var);  /* will be a new upvalue */
4500495ed39SKyle Evans         else  /* it is a global or a constant */
4510495ed39SKyle Evans           return;  /* don't need to do anything at this level */
4528e3e3a7aSWarner Losh       }
4538e3e3a7aSWarner Losh       init_exp(var, VUPVAL, idx);  /* new or old upvalue */
4548e3e3a7aSWarner Losh     }
4558e3e3a7aSWarner Losh   }
4568e3e3a7aSWarner Losh }
4578e3e3a7aSWarner Losh 
4588e3e3a7aSWarner Losh 
4590495ed39SKyle Evans /*
4600495ed39SKyle Evans ** Find a variable with the given name 'n', handling global variables
4610495ed39SKyle Evans ** too.
4620495ed39SKyle Evans */
singlevar(LexState * ls,expdesc * var)4638e3e3a7aSWarner Losh static void singlevar (LexState *ls, expdesc *var) {
4648e3e3a7aSWarner Losh   TString *varname = str_checkname(ls);
4658e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
4668e3e3a7aSWarner Losh   singlevaraux(fs, varname, var, 1);
4678e3e3a7aSWarner Losh   if (var->k == VVOID) {  /* global name? */
4688e3e3a7aSWarner Losh     expdesc key;
4698e3e3a7aSWarner Losh     singlevaraux(fs, ls->envn, var, 1);  /* get environment variable */
4708e3e3a7aSWarner Losh     lua_assert(var->k != VVOID);  /* this one must exist */
471*a9490b81SWarner Losh     luaK_exp2anyregup(fs, var);  /* but could be a constant */
4720495ed39SKyle Evans     codestring(&key, varname);  /* key is variable name */
4738e3e3a7aSWarner Losh     luaK_indexed(fs, var, &key);  /* env[varname] */
4748e3e3a7aSWarner Losh   }
4758e3e3a7aSWarner Losh }
4768e3e3a7aSWarner Losh 
4778e3e3a7aSWarner Losh 
4780495ed39SKyle Evans /*
4790495ed39SKyle Evans ** Adjust the number of results from an expression list 'e' with 'nexps'
4800495ed39SKyle Evans ** expressions to 'nvars' values.
4810495ed39SKyle Evans */
adjust_assign(LexState * ls,int nvars,int nexps,expdesc * e)4828e3e3a7aSWarner Losh static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
4838e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
4840495ed39SKyle Evans   int needed = nvars - nexps;  /* extra values needed */
4850495ed39SKyle Evans   if (hasmultret(e->k)) {  /* last expression has multiple returns? */
4860495ed39SKyle Evans     int extra = needed + 1;  /* discount last expression itself */
4870495ed39SKyle Evans     if (extra < 0)
4880495ed39SKyle Evans       extra = 0;
4898e3e3a7aSWarner Losh     luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */
4908e3e3a7aSWarner Losh   }
4918e3e3a7aSWarner Losh   else {
4920495ed39SKyle Evans     if (e->k != VVOID)  /* at least one expression? */
4930495ed39SKyle Evans       luaK_exp2nextreg(fs, e);  /* close last expression */
4940495ed39SKyle Evans     if (needed > 0)  /* missing values? */
4950495ed39SKyle Evans       luaK_nil(fs, fs->freereg, needed);  /* complete with nils */
4968e3e3a7aSWarner Losh   }
4970495ed39SKyle Evans   if (needed > 0)
4980495ed39SKyle Evans     luaK_reserveregs(fs, needed);  /* registers for extra values */
4990495ed39SKyle Evans   else  /* adding 'needed' is actually a subtraction */
5000495ed39SKyle Evans     fs->freereg += needed;  /* remove extra values */
5018e3e3a7aSWarner Losh }
5028e3e3a7aSWarner Losh 
5038e3e3a7aSWarner Losh 
5040495ed39SKyle Evans #define enterlevel(ls)	luaE_incCstack(ls->L)
5058e3e3a7aSWarner Losh 
5068e3e3a7aSWarner Losh 
5078e3e3a7aSWarner Losh #define leavelevel(ls) ((ls)->L->nCcalls--)
5088e3e3a7aSWarner Losh 
5098e3e3a7aSWarner Losh 
5100495ed39SKyle Evans /*
5110495ed39SKyle Evans ** Generates an error that a goto jumps into the scope of some
5120495ed39SKyle Evans ** local variable.
5130495ed39SKyle Evans */
jumpscopeerror(LexState * ls,Labeldesc * gt)5140495ed39SKyle Evans static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) {
5150495ed39SKyle Evans   const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->vd.name);
5160495ed39SKyle Evans   const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'";
5170495ed39SKyle Evans   msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname);
5180495ed39SKyle Evans   luaK_semerror(ls, msg);  /* raise the error */
5198e3e3a7aSWarner Losh }
5200495ed39SKyle Evans 
5210495ed39SKyle Evans 
5220495ed39SKyle Evans /*
5230495ed39SKyle Evans ** Solves the goto at index 'g' to given 'label' and removes it
524*a9490b81SWarner Losh ** from the list of pending gotos.
5250495ed39SKyle Evans ** If it jumps into the scope of some variable, raises an error.
5260495ed39SKyle Evans */
solvegoto(LexState * ls,int g,Labeldesc * label)5270495ed39SKyle Evans static void solvegoto (LexState *ls, int g, Labeldesc *label) {
5280495ed39SKyle Evans   int i;
529*a9490b81SWarner Losh   Labellist *gl = &ls->dyd->gt;  /* list of gotos */
5300495ed39SKyle Evans   Labeldesc *gt = &gl->arr[g];  /* goto to be resolved */
5310495ed39SKyle Evans   lua_assert(eqstr(gt->name, label->name));
5328c784bb8SWarner Losh   if (l_unlikely(gt->nactvar < label->nactvar))  /* enter some scope? */
5330495ed39SKyle Evans     jumpscopeerror(ls, gt);
5340495ed39SKyle Evans   luaK_patchlist(ls->fs, gt->pc, label->pc);
5350495ed39SKyle Evans   for (i = g; i < gl->n - 1; i++)  /* remove goto from pending list */
5368e3e3a7aSWarner Losh     gl->arr[i] = gl->arr[i + 1];
5378e3e3a7aSWarner Losh   gl->n--;
5388e3e3a7aSWarner Losh }
5398e3e3a7aSWarner Losh 
5408e3e3a7aSWarner Losh 
5418e3e3a7aSWarner Losh /*
5420495ed39SKyle Evans ** Search for an active label with the given name.
5438e3e3a7aSWarner Losh */
findlabel(LexState * ls,TString * name)5440495ed39SKyle Evans static Labeldesc *findlabel (LexState *ls, TString *name) {
5458e3e3a7aSWarner Losh   int i;
5468e3e3a7aSWarner Losh   Dyndata *dyd = ls->dyd;
5470495ed39SKyle Evans   /* check labels in current function for a match */
5480495ed39SKyle Evans   for (i = ls->fs->firstlabel; i < dyd->label.n; i++) {
5498e3e3a7aSWarner Losh     Labeldesc *lb = &dyd->label.arr[i];
5500495ed39SKyle Evans     if (eqstr(lb->name, name))  /* correct label? */
5510495ed39SKyle Evans       return lb;
5528e3e3a7aSWarner Losh   }
5530495ed39SKyle Evans   return NULL;  /* label not found */
5548e3e3a7aSWarner Losh }
5558e3e3a7aSWarner Losh 
5568e3e3a7aSWarner Losh 
5570495ed39SKyle Evans /*
5580495ed39SKyle Evans ** Adds a new label/goto in the corresponding list.
5590495ed39SKyle Evans */
newlabelentry(LexState * ls,Labellist * l,TString * name,int line,int pc)5608e3e3a7aSWarner Losh static int newlabelentry (LexState *ls, Labellist *l, TString *name,
5618e3e3a7aSWarner Losh                           int line, int pc) {
5628e3e3a7aSWarner Losh   int n = l->n;
5638e3e3a7aSWarner Losh   luaM_growvector(ls->L, l->arr, n, l->size,
5648e3e3a7aSWarner Losh                   Labeldesc, SHRT_MAX, "labels/gotos");
5658e3e3a7aSWarner Losh   l->arr[n].name = name;
5668e3e3a7aSWarner Losh   l->arr[n].line = line;
5678e3e3a7aSWarner Losh   l->arr[n].nactvar = ls->fs->nactvar;
5680495ed39SKyle Evans   l->arr[n].close = 0;
5698e3e3a7aSWarner Losh   l->arr[n].pc = pc;
5708e3e3a7aSWarner Losh   l->n = n + 1;
5718e3e3a7aSWarner Losh   return n;
5728e3e3a7aSWarner Losh }
5738e3e3a7aSWarner Losh 
5748e3e3a7aSWarner Losh 
newgotoentry(LexState * ls,TString * name,int line,int pc)5750495ed39SKyle Evans static int newgotoentry (LexState *ls, TString *name, int line, int pc) {
5760495ed39SKyle Evans   return newlabelentry(ls, &ls->dyd->gt, name, line, pc);
5770495ed39SKyle Evans }
5780495ed39SKyle Evans 
5790495ed39SKyle Evans 
5808e3e3a7aSWarner Losh /*
5810495ed39SKyle Evans ** Solves forward jumps. Check whether new label 'lb' matches any
5820495ed39SKyle Evans ** pending gotos in current block and solves them. Return true
583*a9490b81SWarner Losh ** if any of the gotos need to close upvalues.
5848e3e3a7aSWarner Losh */
solvegotos(LexState * ls,Labeldesc * lb)5850495ed39SKyle Evans static int solvegotos (LexState *ls, Labeldesc *lb) {
5868e3e3a7aSWarner Losh   Labellist *gl = &ls->dyd->gt;
5878e3e3a7aSWarner Losh   int i = ls->fs->bl->firstgoto;
5880495ed39SKyle Evans   int needsclose = 0;
5898e3e3a7aSWarner Losh   while (i < gl->n) {
5900495ed39SKyle Evans     if (eqstr(gl->arr[i].name, lb->name)) {
5910495ed39SKyle Evans       needsclose |= gl->arr[i].close;
5920495ed39SKyle Evans       solvegoto(ls, i, lb);  /* will remove 'i' from the list */
5930495ed39SKyle Evans     }
5948e3e3a7aSWarner Losh     else
5958e3e3a7aSWarner Losh       i++;
5968e3e3a7aSWarner Losh   }
5970495ed39SKyle Evans   return needsclose;
5988e3e3a7aSWarner Losh }
5998e3e3a7aSWarner Losh 
6008e3e3a7aSWarner Losh 
6018e3e3a7aSWarner Losh /*
6020495ed39SKyle Evans ** Create a new label with the given 'name' at the given 'line'.
6030495ed39SKyle Evans ** 'last' tells whether label is the last non-op statement in its
604*a9490b81SWarner Losh ** block. Solves all pending gotos to this new label and adds
6050495ed39SKyle Evans ** a close instruction if necessary.
6060495ed39SKyle Evans ** Returns true iff it added a close instruction.
6070495ed39SKyle Evans */
createlabel(LexState * ls,TString * name,int line,int last)6080495ed39SKyle Evans static int createlabel (LexState *ls, TString *name, int line,
6090495ed39SKyle Evans                         int last) {
6100495ed39SKyle Evans   FuncState *fs = ls->fs;
6110495ed39SKyle Evans   Labellist *ll = &ls->dyd->label;
6120495ed39SKyle Evans   int l = newlabelentry(ls, ll, name, line, luaK_getlabel(fs));
6130495ed39SKyle Evans   if (last) {  /* label is last no-op statement in the block? */
6140495ed39SKyle Evans     /* assume that locals are already out of scope */
6150495ed39SKyle Evans     ll->arr[l].nactvar = fs->bl->nactvar;
6160495ed39SKyle Evans   }
6170495ed39SKyle Evans   if (solvegotos(ls, &ll->arr[l])) {  /* need close? */
6180495ed39SKyle Evans     luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0);
6190495ed39SKyle Evans     return 1;
6200495ed39SKyle Evans   }
6210495ed39SKyle Evans   return 0;
6220495ed39SKyle Evans }
6230495ed39SKyle Evans 
6240495ed39SKyle Evans 
6250495ed39SKyle Evans /*
6260495ed39SKyle Evans ** Adjust pending gotos to outer level of a block.
6278e3e3a7aSWarner Losh */
movegotosout(FuncState * fs,BlockCnt * bl)6288e3e3a7aSWarner Losh static void movegotosout (FuncState *fs, BlockCnt *bl) {
6290495ed39SKyle Evans   int i;
6308e3e3a7aSWarner Losh   Labellist *gl = &fs->ls->dyd->gt;
6310495ed39SKyle Evans   /* correct pending gotos to current block */
6320495ed39SKyle Evans   for (i = bl->firstgoto; i < gl->n; i++) {  /* for each pending goto */
6338e3e3a7aSWarner Losh     Labeldesc *gt = &gl->arr[i];
6340495ed39SKyle Evans     /* leaving a variable scope? */
6358c784bb8SWarner Losh     if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar))
6360495ed39SKyle Evans       gt->close |= bl->upval;  /* jump may need a close */
6370495ed39SKyle Evans     gt->nactvar = bl->nactvar;  /* update goto level */
6388e3e3a7aSWarner Losh   }
6398e3e3a7aSWarner Losh }
6408e3e3a7aSWarner Losh 
6418e3e3a7aSWarner Losh 
enterblock(FuncState * fs,BlockCnt * bl,lu_byte isloop)6428e3e3a7aSWarner Losh static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
6438e3e3a7aSWarner Losh   bl->isloop = isloop;
6448e3e3a7aSWarner Losh   bl->nactvar = fs->nactvar;
6458e3e3a7aSWarner Losh   bl->firstlabel = fs->ls->dyd->label.n;
6468e3e3a7aSWarner Losh   bl->firstgoto = fs->ls->dyd->gt.n;
6478e3e3a7aSWarner Losh   bl->upval = 0;
6480495ed39SKyle Evans   bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc);
6498e3e3a7aSWarner Losh   bl->previous = fs->bl;
6508e3e3a7aSWarner Losh   fs->bl = bl;
6510495ed39SKyle Evans   lua_assert(fs->freereg == luaY_nvarstack(fs));
6528e3e3a7aSWarner Losh }
6538e3e3a7aSWarner Losh 
6548e3e3a7aSWarner Losh 
6558e3e3a7aSWarner Losh /*
6560495ed39SKyle Evans ** generates an error for an undefined 'goto'.
6578e3e3a7aSWarner Losh */
undefgoto(LexState * ls,Labeldesc * gt)6588e3e3a7aSWarner Losh static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
6590495ed39SKyle Evans   const char *msg;
6600495ed39SKyle Evans   if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) {
6610495ed39SKyle Evans     msg = "break outside loop at line %d";
6620495ed39SKyle Evans     msg = luaO_pushfstring(ls->L, msg, gt->line);
6630495ed39SKyle Evans   }
6640495ed39SKyle Evans   else {
6650495ed39SKyle Evans     msg = "no visible label '%s' for <goto> at line %d";
6668e3e3a7aSWarner Losh     msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
6670495ed39SKyle Evans   }
6680495ed39SKyle Evans   luaK_semerror(ls, msg);
6698e3e3a7aSWarner Losh }
6708e3e3a7aSWarner Losh 
6718e3e3a7aSWarner Losh 
leaveblock(FuncState * fs)6728e3e3a7aSWarner Losh static void leaveblock (FuncState *fs) {
6738e3e3a7aSWarner Losh   BlockCnt *bl = fs->bl;
6748e3e3a7aSWarner Losh   LexState *ls = fs->ls;
6750495ed39SKyle Evans   int hasclose = 0;
6768c784bb8SWarner Losh   int stklevel = reglevel(fs, bl->nactvar);  /* level outside the block */
677*a9490b81SWarner Losh   removevars(fs, bl->nactvar);  /* remove block locals */
678*a9490b81SWarner Losh   lua_assert(bl->nactvar == fs->nactvar);  /* back to level on entry */
679*a9490b81SWarner Losh   if (bl->isloop)  /* has to fix pending breaks? */
6800495ed39SKyle Evans     hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0);
681*a9490b81SWarner Losh   if (!hasclose && bl->previous && bl->upval)  /* still need a 'close'? */
6820495ed39SKyle Evans     luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0);
6830495ed39SKyle Evans   fs->freereg = stklevel;  /* free registers */
6848e3e3a7aSWarner Losh   ls->dyd->label.n = bl->firstlabel;  /* remove local labels */
685*a9490b81SWarner Losh   fs->bl = bl->previous;  /* current block now is previous one */
686*a9490b81SWarner Losh   if (bl->previous)  /* was it a nested block? */
687*a9490b81SWarner Losh     movegotosout(fs, bl);  /* update pending gotos to enclosing block */
6880495ed39SKyle Evans   else {
689*a9490b81SWarner Losh     if (bl->firstgoto < ls->dyd->gt.n)  /* still pending gotos? */
6908e3e3a7aSWarner Losh       undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]);  /* error */
6918e3e3a7aSWarner Losh   }
6920495ed39SKyle Evans }
6938e3e3a7aSWarner Losh 
6948e3e3a7aSWarner Losh 
6958e3e3a7aSWarner Losh /*
6968e3e3a7aSWarner Losh ** adds a new prototype into list of prototypes
6978e3e3a7aSWarner Losh */
addprototype(LexState * ls)6988e3e3a7aSWarner Losh static Proto *addprototype (LexState *ls) {
6998e3e3a7aSWarner Losh   Proto *clp;
7008e3e3a7aSWarner Losh   lua_State *L = ls->L;
7018e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
7028e3e3a7aSWarner Losh   Proto *f = fs->f;  /* prototype of current function */
7038e3e3a7aSWarner Losh   if (fs->np >= f->sizep) {
7048e3e3a7aSWarner Losh     int oldsize = f->sizep;
7058e3e3a7aSWarner Losh     luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
7068e3e3a7aSWarner Losh     while (oldsize < f->sizep)
7078e3e3a7aSWarner Losh       f->p[oldsize++] = NULL;
7088e3e3a7aSWarner Losh   }
7098e3e3a7aSWarner Losh   f->p[fs->np++] = clp = luaF_newproto(L);
7108e3e3a7aSWarner Losh   luaC_objbarrier(L, f, clp);
7118e3e3a7aSWarner Losh   return clp;
7128e3e3a7aSWarner Losh }
7138e3e3a7aSWarner Losh 
7148e3e3a7aSWarner Losh 
7158e3e3a7aSWarner Losh /*
7168e3e3a7aSWarner Losh ** codes instruction to create new closure in parent function.
7170495ed39SKyle Evans ** The OP_CLOSURE instruction uses the last available register,
7188e3e3a7aSWarner Losh ** so that, if it invokes the GC, the GC knows which registers
7198e3e3a7aSWarner Losh ** are in use at that time.
7200495ed39SKyle Evans 
7218e3e3a7aSWarner Losh */
codeclosure(LexState * ls,expdesc * v)7228e3e3a7aSWarner Losh static void codeclosure (LexState *ls, expdesc *v) {
7238e3e3a7aSWarner Losh   FuncState *fs = ls->fs->prev;
7240495ed39SKyle Evans   init_exp(v, VRELOC, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
7258e3e3a7aSWarner Losh   luaK_exp2nextreg(fs, v);  /* fix it at the last register */
7268e3e3a7aSWarner Losh }
7278e3e3a7aSWarner Losh 
7288e3e3a7aSWarner Losh 
open_func(LexState * ls,FuncState * fs,BlockCnt * bl)7298e3e3a7aSWarner Losh static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
7300495ed39SKyle Evans   Proto *f = fs->f;
7318e3e3a7aSWarner Losh   fs->prev = ls->fs;  /* linked list of funcstates */
7328e3e3a7aSWarner Losh   fs->ls = ls;
7338e3e3a7aSWarner Losh   ls->fs = fs;
7348e3e3a7aSWarner Losh   fs->pc = 0;
7350495ed39SKyle Evans   fs->previousline = f->linedefined;
7360495ed39SKyle Evans   fs->iwthabs = 0;
7378e3e3a7aSWarner Losh   fs->lasttarget = 0;
7388e3e3a7aSWarner Losh   fs->freereg = 0;
7398e3e3a7aSWarner Losh   fs->nk = 0;
7400495ed39SKyle Evans   fs->nabslineinfo = 0;
7418e3e3a7aSWarner Losh   fs->np = 0;
7428e3e3a7aSWarner Losh   fs->nups = 0;
7430495ed39SKyle Evans   fs->ndebugvars = 0;
7448e3e3a7aSWarner Losh   fs->nactvar = 0;
7450495ed39SKyle Evans   fs->needclose = 0;
7468e3e3a7aSWarner Losh   fs->firstlocal = ls->dyd->actvar.n;
7470495ed39SKyle Evans   fs->firstlabel = ls->dyd->label.n;
7488e3e3a7aSWarner Losh   fs->bl = NULL;
7498e3e3a7aSWarner Losh   f->source = ls->source;
750bf9580a1SKyle Evans   luaC_objbarrier(ls->L, f, f->source);
7518e3e3a7aSWarner Losh   f->maxstacksize = 2;  /* registers 0/1 are always valid */
7528e3e3a7aSWarner Losh   enterblock(fs, bl, 0);
7538e3e3a7aSWarner Losh }
7548e3e3a7aSWarner Losh 
7558e3e3a7aSWarner Losh 
close_func(LexState * ls)7568e3e3a7aSWarner Losh static void close_func (LexState *ls) {
7578e3e3a7aSWarner Losh   lua_State *L = ls->L;
7588e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
7598e3e3a7aSWarner Losh   Proto *f = fs->f;
7600495ed39SKyle Evans   luaK_ret(fs, luaY_nvarstack(fs), 0);  /* final return */
7618e3e3a7aSWarner Losh   leaveblock(fs);
7628e3e3a7aSWarner Losh   lua_assert(fs->bl == NULL);
7630495ed39SKyle Evans   luaK_finish(fs);
7640495ed39SKyle Evans   luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction);
7650495ed39SKyle Evans   luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte);
7660495ed39SKyle Evans   luaM_shrinkvector(L, f->abslineinfo, f->sizeabslineinfo,
7670495ed39SKyle Evans                        fs->nabslineinfo, AbsLineInfo);
7680495ed39SKyle Evans   luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue);
7690495ed39SKyle Evans   luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *);
7700495ed39SKyle Evans   luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar);
7710495ed39SKyle Evans   luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
7728e3e3a7aSWarner Losh   ls->fs = fs->prev;
7738e3e3a7aSWarner Losh   luaC_checkGC(L);
7748e3e3a7aSWarner Losh }
7758e3e3a7aSWarner Losh 
7768e3e3a7aSWarner Losh 
7778e3e3a7aSWarner Losh 
7788e3e3a7aSWarner Losh /*============================================================*/
7798e3e3a7aSWarner Losh /* GRAMMAR RULES */
7808e3e3a7aSWarner Losh /*============================================================*/
7818e3e3a7aSWarner Losh 
7828e3e3a7aSWarner Losh 
7838e3e3a7aSWarner Losh /*
7848e3e3a7aSWarner Losh ** check whether current token is in the follow set of a block.
7858e3e3a7aSWarner Losh ** 'until' closes syntactical blocks, but do not close scope,
7868e3e3a7aSWarner Losh ** so it is handled in separate.
7878e3e3a7aSWarner Losh */
block_follow(LexState * ls,int withuntil)7888e3e3a7aSWarner Losh static int block_follow (LexState *ls, int withuntil) {
7898e3e3a7aSWarner Losh   switch (ls->t.token) {
7908e3e3a7aSWarner Losh     case TK_ELSE: case TK_ELSEIF:
7918e3e3a7aSWarner Losh     case TK_END: case TK_EOS:
7928e3e3a7aSWarner Losh       return 1;
7938e3e3a7aSWarner Losh     case TK_UNTIL: return withuntil;
7948e3e3a7aSWarner Losh     default: return 0;
7958e3e3a7aSWarner Losh   }
7968e3e3a7aSWarner Losh }
7978e3e3a7aSWarner Losh 
7988e3e3a7aSWarner Losh 
statlist(LexState * ls)7998e3e3a7aSWarner Losh static void statlist (LexState *ls) {
8008e3e3a7aSWarner Losh   /* statlist -> { stat [';'] } */
8018e3e3a7aSWarner Losh   while (!block_follow(ls, 1)) {
8028e3e3a7aSWarner Losh     if (ls->t.token == TK_RETURN) {
8038e3e3a7aSWarner Losh       statement(ls);
8048e3e3a7aSWarner Losh       return;  /* 'return' must be last statement */
8058e3e3a7aSWarner Losh     }
8068e3e3a7aSWarner Losh     statement(ls);
8078e3e3a7aSWarner Losh   }
8088e3e3a7aSWarner Losh }
8098e3e3a7aSWarner Losh 
8108e3e3a7aSWarner Losh 
fieldsel(LexState * ls,expdesc * v)8118e3e3a7aSWarner Losh static void fieldsel (LexState *ls, expdesc *v) {
8128e3e3a7aSWarner Losh   /* fieldsel -> ['.' | ':'] NAME */
8138e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
8148e3e3a7aSWarner Losh   expdesc key;
8158e3e3a7aSWarner Losh   luaK_exp2anyregup(fs, v);
8168e3e3a7aSWarner Losh   luaX_next(ls);  /* skip the dot or colon */
8170495ed39SKyle Evans   codename(ls, &key);
8188e3e3a7aSWarner Losh   luaK_indexed(fs, v, &key);
8198e3e3a7aSWarner Losh }
8208e3e3a7aSWarner Losh 
8218e3e3a7aSWarner Losh 
yindex(LexState * ls,expdesc * v)8228e3e3a7aSWarner Losh static void yindex (LexState *ls, expdesc *v) {
8238e3e3a7aSWarner Losh   /* index -> '[' expr ']' */
8248e3e3a7aSWarner Losh   luaX_next(ls);  /* skip the '[' */
8258e3e3a7aSWarner Losh   expr(ls, v);
8268e3e3a7aSWarner Losh   luaK_exp2val(ls->fs, v);
8278e3e3a7aSWarner Losh   checknext(ls, ']');
8288e3e3a7aSWarner Losh }
8298e3e3a7aSWarner Losh 
8308e3e3a7aSWarner Losh 
8318e3e3a7aSWarner Losh /*
8328e3e3a7aSWarner Losh ** {======================================================================
8338e3e3a7aSWarner Losh ** Rules for Constructors
8348e3e3a7aSWarner Losh ** =======================================================================
8358e3e3a7aSWarner Losh */
8368e3e3a7aSWarner Losh 
8378e3e3a7aSWarner Losh 
8380495ed39SKyle Evans typedef struct ConsControl {
8398e3e3a7aSWarner Losh   expdesc v;  /* last list item read */
8408e3e3a7aSWarner Losh   expdesc *t;  /* table descriptor */
8418e3e3a7aSWarner Losh   int nh;  /* total number of 'record' elements */
8420495ed39SKyle Evans   int na;  /* number of array elements already stored */
8438e3e3a7aSWarner Losh   int tostore;  /* number of array elements pending to be stored */
8440495ed39SKyle Evans } ConsControl;
8458e3e3a7aSWarner Losh 
8468e3e3a7aSWarner Losh 
recfield(LexState * ls,ConsControl * cc)8470495ed39SKyle Evans static void recfield (LexState *ls, ConsControl *cc) {
8480495ed39SKyle Evans   /* recfield -> (NAME | '['exp']') = exp */
8498e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
8508e3e3a7aSWarner Losh   int reg = ls->fs->freereg;
8510495ed39SKyle Evans   expdesc tab, key, val;
8528e3e3a7aSWarner Losh   if (ls->t.token == TK_NAME) {
8538e3e3a7aSWarner Losh     checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
8540495ed39SKyle Evans     codename(ls, &key);
8558e3e3a7aSWarner Losh   }
8568e3e3a7aSWarner Losh   else  /* ls->t.token == '[' */
8578e3e3a7aSWarner Losh     yindex(ls, &key);
8588e3e3a7aSWarner Losh   cc->nh++;
8598e3e3a7aSWarner Losh   checknext(ls, '=');
8600495ed39SKyle Evans   tab = *cc->t;
8610495ed39SKyle Evans   luaK_indexed(fs, &tab, &key);
8628e3e3a7aSWarner Losh   expr(ls, &val);
8630495ed39SKyle Evans   luaK_storevar(fs, &tab, &val);
8648e3e3a7aSWarner Losh   fs->freereg = reg;  /* free registers */
8658e3e3a7aSWarner Losh }
8668e3e3a7aSWarner Losh 
8678e3e3a7aSWarner Losh 
closelistfield(FuncState * fs,ConsControl * cc)8680495ed39SKyle Evans static void closelistfield (FuncState *fs, ConsControl *cc) {
8698e3e3a7aSWarner Losh   if (cc->v.k == VVOID) return;  /* there is no list item */
8708e3e3a7aSWarner Losh   luaK_exp2nextreg(fs, &cc->v);
8718e3e3a7aSWarner Losh   cc->v.k = VVOID;
8728e3e3a7aSWarner Losh   if (cc->tostore == LFIELDS_PER_FLUSH) {
8738e3e3a7aSWarner Losh     luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore);  /* flush */
8740495ed39SKyle Evans     cc->na += cc->tostore;
8758e3e3a7aSWarner Losh     cc->tostore = 0;  /* no more items pending */
8768e3e3a7aSWarner Losh   }
8778e3e3a7aSWarner Losh }
8788e3e3a7aSWarner Losh 
8798e3e3a7aSWarner Losh 
lastlistfield(FuncState * fs,ConsControl * cc)8800495ed39SKyle Evans static void lastlistfield (FuncState *fs, ConsControl *cc) {
8818e3e3a7aSWarner Losh   if (cc->tostore == 0) return;
8828e3e3a7aSWarner Losh   if (hasmultret(cc->v.k)) {
8838e3e3a7aSWarner Losh     luaK_setmultret(fs, &cc->v);
8848e3e3a7aSWarner Losh     luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET);
8858e3e3a7aSWarner Losh     cc->na--;  /* do not count last expression (unknown number of elements) */
8868e3e3a7aSWarner Losh   }
8878e3e3a7aSWarner Losh   else {
8888e3e3a7aSWarner Losh     if (cc->v.k != VVOID)
8898e3e3a7aSWarner Losh       luaK_exp2nextreg(fs, &cc->v);
8908e3e3a7aSWarner Losh     luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore);
8918e3e3a7aSWarner Losh   }
8920495ed39SKyle Evans   cc->na += cc->tostore;
8938e3e3a7aSWarner Losh }
8948e3e3a7aSWarner Losh 
8958e3e3a7aSWarner Losh 
listfield(LexState * ls,ConsControl * cc)8960495ed39SKyle Evans static void listfield (LexState *ls, ConsControl *cc) {
8978e3e3a7aSWarner Losh   /* listfield -> exp */
8988e3e3a7aSWarner Losh   expr(ls, &cc->v);
8998e3e3a7aSWarner Losh   cc->tostore++;
9008e3e3a7aSWarner Losh }
9018e3e3a7aSWarner Losh 
9028e3e3a7aSWarner Losh 
field(LexState * ls,ConsControl * cc)9030495ed39SKyle Evans static void field (LexState *ls, ConsControl *cc) {
9048e3e3a7aSWarner Losh   /* field -> listfield | recfield */
9058e3e3a7aSWarner Losh   switch(ls->t.token) {
9068e3e3a7aSWarner Losh     case TK_NAME: {  /* may be 'listfield' or 'recfield' */
9078e3e3a7aSWarner Losh       if (luaX_lookahead(ls) != '=')  /* expression? */
9088e3e3a7aSWarner Losh         listfield(ls, cc);
9098e3e3a7aSWarner Losh       else
9108e3e3a7aSWarner Losh         recfield(ls, cc);
9118e3e3a7aSWarner Losh       break;
9128e3e3a7aSWarner Losh     }
9138e3e3a7aSWarner Losh     case '[': {
9148e3e3a7aSWarner Losh       recfield(ls, cc);
9158e3e3a7aSWarner Losh       break;
9168e3e3a7aSWarner Losh     }
9178e3e3a7aSWarner Losh     default: {
9188e3e3a7aSWarner Losh       listfield(ls, cc);
9198e3e3a7aSWarner Losh       break;
9208e3e3a7aSWarner Losh     }
9218e3e3a7aSWarner Losh   }
9228e3e3a7aSWarner Losh }
9238e3e3a7aSWarner Losh 
9248e3e3a7aSWarner Losh 
constructor(LexState * ls,expdesc * t)9258e3e3a7aSWarner Losh static void constructor (LexState *ls, expdesc *t) {
9268e3e3a7aSWarner Losh   /* constructor -> '{' [ field { sep field } [sep] ] '}'
9278e3e3a7aSWarner Losh      sep -> ',' | ';' */
9288e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
9298e3e3a7aSWarner Losh   int line = ls->linenumber;
9308e3e3a7aSWarner Losh   int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
9310495ed39SKyle Evans   ConsControl cc;
9320495ed39SKyle Evans   luaK_code(fs, 0);  /* space for extra arg. */
9338e3e3a7aSWarner Losh   cc.na = cc.nh = cc.tostore = 0;
9348e3e3a7aSWarner Losh   cc.t = t;
9350495ed39SKyle Evans   init_exp(t, VNONRELOC, fs->freereg);  /* table will be at stack top */
9360495ed39SKyle Evans   luaK_reserveregs(fs, 1);
9378e3e3a7aSWarner Losh   init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
9388e3e3a7aSWarner Losh   checknext(ls, '{');
9398e3e3a7aSWarner Losh   do {
9408e3e3a7aSWarner Losh     lua_assert(cc.v.k == VVOID || cc.tostore > 0);
9418e3e3a7aSWarner Losh     if (ls->t.token == '}') break;
9428e3e3a7aSWarner Losh     closelistfield(fs, &cc);
9438e3e3a7aSWarner Losh     field(ls, &cc);
9448e3e3a7aSWarner Losh   } while (testnext(ls, ',') || testnext(ls, ';'));
9458e3e3a7aSWarner Losh   check_match(ls, '}', '{', line);
9468e3e3a7aSWarner Losh   lastlistfield(fs, &cc);
9470495ed39SKyle Evans   luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh);
9488e3e3a7aSWarner Losh }
9498e3e3a7aSWarner Losh 
9508e3e3a7aSWarner Losh /* }====================================================================== */
9518e3e3a7aSWarner Losh 
9528e3e3a7aSWarner Losh 
setvararg(FuncState * fs,int nparams)9530495ed39SKyle Evans static void setvararg (FuncState *fs, int nparams) {
9540495ed39SKyle Evans   fs->f->is_vararg = 1;
9550495ed39SKyle Evans   luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0);
9560495ed39SKyle Evans }
9570495ed39SKyle Evans 
9588e3e3a7aSWarner Losh 
parlist(LexState * ls)9598e3e3a7aSWarner Losh static void parlist (LexState *ls) {
9600495ed39SKyle Evans   /* parlist -> [ {NAME ','} (NAME | '...') ] */
9618e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
9628e3e3a7aSWarner Losh   Proto *f = fs->f;
9638e3e3a7aSWarner Losh   int nparams = 0;
9640495ed39SKyle Evans   int isvararg = 0;
9658e3e3a7aSWarner Losh   if (ls->t.token != ')') {  /* is 'parlist' not empty? */
9668e3e3a7aSWarner Losh     do {
9678e3e3a7aSWarner Losh       switch (ls->t.token) {
9680495ed39SKyle Evans         case TK_NAME: {
9698e3e3a7aSWarner Losh           new_localvar(ls, str_checkname(ls));
9708e3e3a7aSWarner Losh           nparams++;
9718e3e3a7aSWarner Losh           break;
9728e3e3a7aSWarner Losh         }
9730495ed39SKyle Evans         case TK_DOTS: {
9748e3e3a7aSWarner Losh           luaX_next(ls);
9750495ed39SKyle Evans           isvararg = 1;
9768e3e3a7aSWarner Losh           break;
9778e3e3a7aSWarner Losh         }
9788e3e3a7aSWarner Losh         default: luaX_syntaxerror(ls, "<name> or '...' expected");
9798e3e3a7aSWarner Losh       }
9800495ed39SKyle Evans     } while (!isvararg && testnext(ls, ','));
9818e3e3a7aSWarner Losh   }
9828e3e3a7aSWarner Losh   adjustlocalvars(ls, nparams);
9838e3e3a7aSWarner Losh   f->numparams = cast_byte(fs->nactvar);
9840495ed39SKyle Evans   if (isvararg)
9850495ed39SKyle Evans     setvararg(fs, f->numparams);  /* declared vararg */
9860495ed39SKyle Evans   luaK_reserveregs(fs, fs->nactvar);  /* reserve registers for parameters */
9878e3e3a7aSWarner Losh }
9888e3e3a7aSWarner Losh 
9898e3e3a7aSWarner Losh 
body(LexState * ls,expdesc * e,int ismethod,int line)9908e3e3a7aSWarner Losh static void body (LexState *ls, expdesc *e, int ismethod, int line) {
9918e3e3a7aSWarner Losh   /* body ->  '(' parlist ')' block END */
9928e3e3a7aSWarner Losh   FuncState new_fs;
9938e3e3a7aSWarner Losh   BlockCnt bl;
9948e3e3a7aSWarner Losh   new_fs.f = addprototype(ls);
9958e3e3a7aSWarner Losh   new_fs.f->linedefined = line;
9968e3e3a7aSWarner Losh   open_func(ls, &new_fs, &bl);
9978e3e3a7aSWarner Losh   checknext(ls, '(');
9988e3e3a7aSWarner Losh   if (ismethod) {
9998e3e3a7aSWarner Losh     new_localvarliteral(ls, "self");  /* create 'self' parameter */
10008e3e3a7aSWarner Losh     adjustlocalvars(ls, 1);
10018e3e3a7aSWarner Losh   }
10028e3e3a7aSWarner Losh   parlist(ls);
10038e3e3a7aSWarner Losh   checknext(ls, ')');
10048e3e3a7aSWarner Losh   statlist(ls);
10058e3e3a7aSWarner Losh   new_fs.f->lastlinedefined = ls->linenumber;
10068e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_FUNCTION, line);
10078e3e3a7aSWarner Losh   codeclosure(ls, e);
10088e3e3a7aSWarner Losh   close_func(ls);
10098e3e3a7aSWarner Losh }
10108e3e3a7aSWarner Losh 
10118e3e3a7aSWarner Losh 
explist(LexState * ls,expdesc * v)10128e3e3a7aSWarner Losh static int explist (LexState *ls, expdesc *v) {
10138e3e3a7aSWarner Losh   /* explist -> expr { ',' expr } */
10148e3e3a7aSWarner Losh   int n = 1;  /* at least one expression */
10158e3e3a7aSWarner Losh   expr(ls, v);
10168e3e3a7aSWarner Losh   while (testnext(ls, ',')) {
10178e3e3a7aSWarner Losh     luaK_exp2nextreg(ls->fs, v);
10188e3e3a7aSWarner Losh     expr(ls, v);
10198e3e3a7aSWarner Losh     n++;
10208e3e3a7aSWarner Losh   }
10218e3e3a7aSWarner Losh   return n;
10228e3e3a7aSWarner Losh }
10238e3e3a7aSWarner Losh 
10248e3e3a7aSWarner Losh 
funcargs(LexState * ls,expdesc * f,int line)10258e3e3a7aSWarner Losh static void funcargs (LexState *ls, expdesc *f, int line) {
10268e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
10278e3e3a7aSWarner Losh   expdesc args;
10288e3e3a7aSWarner Losh   int base, nparams;
10298e3e3a7aSWarner Losh   switch (ls->t.token) {
10308e3e3a7aSWarner Losh     case '(': {  /* funcargs -> '(' [ explist ] ')' */
10318e3e3a7aSWarner Losh       luaX_next(ls);
10328e3e3a7aSWarner Losh       if (ls->t.token == ')')  /* arg list is empty? */
10338e3e3a7aSWarner Losh         args.k = VVOID;
10348e3e3a7aSWarner Losh       else {
10358e3e3a7aSWarner Losh         explist(ls, &args);
10360495ed39SKyle Evans         if (hasmultret(args.k))
10378e3e3a7aSWarner Losh           luaK_setmultret(fs, &args);
10388e3e3a7aSWarner Losh       }
10398e3e3a7aSWarner Losh       check_match(ls, ')', '(', line);
10408e3e3a7aSWarner Losh       break;
10418e3e3a7aSWarner Losh     }
10428e3e3a7aSWarner Losh     case '{': {  /* funcargs -> constructor */
10438e3e3a7aSWarner Losh       constructor(ls, &args);
10448e3e3a7aSWarner Losh       break;
10458e3e3a7aSWarner Losh     }
10468e3e3a7aSWarner Losh     case TK_STRING: {  /* funcargs -> STRING */
10470495ed39SKyle Evans       codestring(&args, ls->t.seminfo.ts);
10488e3e3a7aSWarner Losh       luaX_next(ls);  /* must use 'seminfo' before 'next' */
10498e3e3a7aSWarner Losh       break;
10508e3e3a7aSWarner Losh     }
10518e3e3a7aSWarner Losh     default: {
10528e3e3a7aSWarner Losh       luaX_syntaxerror(ls, "function arguments expected");
10538e3e3a7aSWarner Losh     }
10548e3e3a7aSWarner Losh   }
10558e3e3a7aSWarner Losh   lua_assert(f->k == VNONRELOC);
10568e3e3a7aSWarner Losh   base = f->u.info;  /* base register for call */
10578e3e3a7aSWarner Losh   if (hasmultret(args.k))
10588e3e3a7aSWarner Losh     nparams = LUA_MULTRET;  /* open call */
10598e3e3a7aSWarner Losh   else {
10608e3e3a7aSWarner Losh     if (args.k != VVOID)
10618e3e3a7aSWarner Losh       luaK_exp2nextreg(fs, &args);  /* close last argument */
10628e3e3a7aSWarner Losh     nparams = fs->freereg - (base+1);
10638e3e3a7aSWarner Losh   }
10648e3e3a7aSWarner Losh   init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
10658e3e3a7aSWarner Losh   luaK_fixline(fs, line);
10668e3e3a7aSWarner Losh   fs->freereg = base+1;  /* call remove function and arguments and leaves
10678e3e3a7aSWarner Losh                             (unless changed) one result */
10688e3e3a7aSWarner Losh }
10698e3e3a7aSWarner Losh 
10708e3e3a7aSWarner Losh 
10718e3e3a7aSWarner Losh 
10728e3e3a7aSWarner Losh 
10738e3e3a7aSWarner Losh /*
10748e3e3a7aSWarner Losh ** {======================================================================
10758e3e3a7aSWarner Losh ** Expression parsing
10768e3e3a7aSWarner Losh ** =======================================================================
10778e3e3a7aSWarner Losh */
10788e3e3a7aSWarner Losh 
10798e3e3a7aSWarner Losh 
primaryexp(LexState * ls,expdesc * v)10808e3e3a7aSWarner Losh static void primaryexp (LexState *ls, expdesc *v) {
10818e3e3a7aSWarner Losh   /* primaryexp -> NAME | '(' expr ')' */
10828e3e3a7aSWarner Losh   switch (ls->t.token) {
10838e3e3a7aSWarner Losh     case '(': {
10848e3e3a7aSWarner Losh       int line = ls->linenumber;
10858e3e3a7aSWarner Losh       luaX_next(ls);
10868e3e3a7aSWarner Losh       expr(ls, v);
10878e3e3a7aSWarner Losh       check_match(ls, ')', '(', line);
10888e3e3a7aSWarner Losh       luaK_dischargevars(ls->fs, v);
10898e3e3a7aSWarner Losh       return;
10908e3e3a7aSWarner Losh     }
10918e3e3a7aSWarner Losh     case TK_NAME: {
10928e3e3a7aSWarner Losh       singlevar(ls, v);
10938e3e3a7aSWarner Losh       return;
10948e3e3a7aSWarner Losh     }
10958e3e3a7aSWarner Losh     default: {
10968e3e3a7aSWarner Losh       luaX_syntaxerror(ls, "unexpected symbol");
10978e3e3a7aSWarner Losh     }
10988e3e3a7aSWarner Losh   }
10998e3e3a7aSWarner Losh }
11008e3e3a7aSWarner Losh 
11018e3e3a7aSWarner Losh 
suffixedexp(LexState * ls,expdesc * v)11028e3e3a7aSWarner Losh static void suffixedexp (LexState *ls, expdesc *v) {
11038e3e3a7aSWarner Losh   /* suffixedexp ->
11048e3e3a7aSWarner Losh        primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
11058e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
11068e3e3a7aSWarner Losh   int line = ls->linenumber;
11078e3e3a7aSWarner Losh   primaryexp(ls, v);
11088e3e3a7aSWarner Losh   for (;;) {
11098e3e3a7aSWarner Losh     switch (ls->t.token) {
11108e3e3a7aSWarner Losh       case '.': {  /* fieldsel */
11118e3e3a7aSWarner Losh         fieldsel(ls, v);
11128e3e3a7aSWarner Losh         break;
11138e3e3a7aSWarner Losh       }
11140495ed39SKyle Evans       case '[': {  /* '[' exp ']' */
11158e3e3a7aSWarner Losh         expdesc key;
11168e3e3a7aSWarner Losh         luaK_exp2anyregup(fs, v);
11178e3e3a7aSWarner Losh         yindex(ls, &key);
11188e3e3a7aSWarner Losh         luaK_indexed(fs, v, &key);
11198e3e3a7aSWarner Losh         break;
11208e3e3a7aSWarner Losh       }
11218e3e3a7aSWarner Losh       case ':': {  /* ':' NAME funcargs */
11228e3e3a7aSWarner Losh         expdesc key;
11238e3e3a7aSWarner Losh         luaX_next(ls);
11240495ed39SKyle Evans         codename(ls, &key);
11258e3e3a7aSWarner Losh         luaK_self(fs, v, &key);
11268e3e3a7aSWarner Losh         funcargs(ls, v, line);
11278e3e3a7aSWarner Losh         break;
11288e3e3a7aSWarner Losh       }
11298e3e3a7aSWarner Losh       case '(': case TK_STRING: case '{': {  /* funcargs */
11308e3e3a7aSWarner Losh         luaK_exp2nextreg(fs, v);
11318e3e3a7aSWarner Losh         funcargs(ls, v, line);
11328e3e3a7aSWarner Losh         break;
11338e3e3a7aSWarner Losh       }
11348e3e3a7aSWarner Losh       default: return;
11358e3e3a7aSWarner Losh     }
11368e3e3a7aSWarner Losh   }
11378e3e3a7aSWarner Losh }
11388e3e3a7aSWarner Losh 
11398e3e3a7aSWarner Losh 
simpleexp(LexState * ls,expdesc * v)11408e3e3a7aSWarner Losh static void simpleexp (LexState *ls, expdesc *v) {
11418e3e3a7aSWarner Losh   /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... |
11428e3e3a7aSWarner Losh                   constructor | FUNCTION body | suffixedexp */
11438e3e3a7aSWarner Losh   switch (ls->t.token) {
11448e3e3a7aSWarner Losh     case TK_FLT: {
11458e3e3a7aSWarner Losh       init_exp(v, VKFLT, 0);
11468e3e3a7aSWarner Losh       v->u.nval = ls->t.seminfo.r;
11478e3e3a7aSWarner Losh       break;
11488e3e3a7aSWarner Losh     }
11498e3e3a7aSWarner Losh     case TK_INT: {
11508e3e3a7aSWarner Losh       init_exp(v, VKINT, 0);
11518e3e3a7aSWarner Losh       v->u.ival = ls->t.seminfo.i;
11528e3e3a7aSWarner Losh       break;
11538e3e3a7aSWarner Losh     }
11548e3e3a7aSWarner Losh     case TK_STRING: {
11550495ed39SKyle Evans       codestring(v, ls->t.seminfo.ts);
11568e3e3a7aSWarner Losh       break;
11578e3e3a7aSWarner Losh     }
11588e3e3a7aSWarner Losh     case TK_NIL: {
11598e3e3a7aSWarner Losh       init_exp(v, VNIL, 0);
11608e3e3a7aSWarner Losh       break;
11618e3e3a7aSWarner Losh     }
11628e3e3a7aSWarner Losh     case TK_TRUE: {
11638e3e3a7aSWarner Losh       init_exp(v, VTRUE, 0);
11648e3e3a7aSWarner Losh       break;
11658e3e3a7aSWarner Losh     }
11668e3e3a7aSWarner Losh     case TK_FALSE: {
11678e3e3a7aSWarner Losh       init_exp(v, VFALSE, 0);
11688e3e3a7aSWarner Losh       break;
11698e3e3a7aSWarner Losh     }
11708e3e3a7aSWarner Losh     case TK_DOTS: {  /* vararg */
11718e3e3a7aSWarner Losh       FuncState *fs = ls->fs;
11728e3e3a7aSWarner Losh       check_condition(ls, fs->f->is_vararg,
11738e3e3a7aSWarner Losh                       "cannot use '...' outside a vararg function");
11740495ed39SKyle Evans       init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1));
11758e3e3a7aSWarner Losh       break;
11768e3e3a7aSWarner Losh     }
11778e3e3a7aSWarner Losh     case '{': {  /* constructor */
11788e3e3a7aSWarner Losh       constructor(ls, v);
11798e3e3a7aSWarner Losh       return;
11808e3e3a7aSWarner Losh     }
11818e3e3a7aSWarner Losh     case TK_FUNCTION: {
11828e3e3a7aSWarner Losh       luaX_next(ls);
11838e3e3a7aSWarner Losh       body(ls, v, 0, ls->linenumber);
11848e3e3a7aSWarner Losh       return;
11858e3e3a7aSWarner Losh     }
11868e3e3a7aSWarner Losh     default: {
11878e3e3a7aSWarner Losh       suffixedexp(ls, v);
11888e3e3a7aSWarner Losh       return;
11898e3e3a7aSWarner Losh     }
11908e3e3a7aSWarner Losh   }
11918e3e3a7aSWarner Losh   luaX_next(ls);
11928e3e3a7aSWarner Losh }
11938e3e3a7aSWarner Losh 
11948e3e3a7aSWarner Losh 
getunopr(int op)11958e3e3a7aSWarner Losh static UnOpr getunopr (int op) {
11968e3e3a7aSWarner Losh   switch (op) {
11978e3e3a7aSWarner Losh     case TK_NOT: return OPR_NOT;
11988e3e3a7aSWarner Losh     case '-': return OPR_MINUS;
11998e3e3a7aSWarner Losh     case '~': return OPR_BNOT;
12008e3e3a7aSWarner Losh     case '#': return OPR_LEN;
12018e3e3a7aSWarner Losh     default: return OPR_NOUNOPR;
12028e3e3a7aSWarner Losh   }
12038e3e3a7aSWarner Losh }
12048e3e3a7aSWarner Losh 
12058e3e3a7aSWarner Losh 
getbinopr(int op)12068e3e3a7aSWarner Losh static BinOpr getbinopr (int op) {
12078e3e3a7aSWarner Losh   switch (op) {
12088e3e3a7aSWarner Losh     case '+': return OPR_ADD;
12098e3e3a7aSWarner Losh     case '-': return OPR_SUB;
12108e3e3a7aSWarner Losh     case '*': return OPR_MUL;
12118e3e3a7aSWarner Losh     case '%': return OPR_MOD;
12128e3e3a7aSWarner Losh     case '^': return OPR_POW;
12138e3e3a7aSWarner Losh     case '/': return OPR_DIV;
12148e3e3a7aSWarner Losh     case TK_IDIV: return OPR_IDIV;
12158e3e3a7aSWarner Losh     case '&': return OPR_BAND;
12168e3e3a7aSWarner Losh     case '|': return OPR_BOR;
12178e3e3a7aSWarner Losh     case '~': return OPR_BXOR;
12188e3e3a7aSWarner Losh     case TK_SHL: return OPR_SHL;
12198e3e3a7aSWarner Losh     case TK_SHR: return OPR_SHR;
12208e3e3a7aSWarner Losh     case TK_CONCAT: return OPR_CONCAT;
12218e3e3a7aSWarner Losh     case TK_NE: return OPR_NE;
12228e3e3a7aSWarner Losh     case TK_EQ: return OPR_EQ;
12238e3e3a7aSWarner Losh     case '<': return OPR_LT;
12248e3e3a7aSWarner Losh     case TK_LE: return OPR_LE;
12258e3e3a7aSWarner Losh     case '>': return OPR_GT;
12268e3e3a7aSWarner Losh     case TK_GE: return OPR_GE;
12278e3e3a7aSWarner Losh     case TK_AND: return OPR_AND;
12288e3e3a7aSWarner Losh     case TK_OR: return OPR_OR;
12298e3e3a7aSWarner Losh     default: return OPR_NOBINOPR;
12308e3e3a7aSWarner Losh   }
12318e3e3a7aSWarner Losh }
12328e3e3a7aSWarner Losh 
12338e3e3a7aSWarner Losh 
12340495ed39SKyle Evans /*
12350495ed39SKyle Evans ** Priority table for binary operators.
12360495ed39SKyle Evans */
12378e3e3a7aSWarner Losh static const struct {
12388e3e3a7aSWarner Losh   lu_byte left;  /* left priority for each binary operator */
12398e3e3a7aSWarner Losh   lu_byte right; /* right priority */
12408e3e3a7aSWarner Losh } priority[] = {  /* ORDER OPR */
12418e3e3a7aSWarner Losh    {10, 10}, {10, 10},           /* '+' '-' */
12428e3e3a7aSWarner Losh    {11, 11}, {11, 11},           /* '*' '%' */
12438e3e3a7aSWarner Losh    {14, 13},                  /* '^' (right associative) */
12448e3e3a7aSWarner Losh    {11, 11}, {11, 11},           /* '/' '//' */
12458e3e3a7aSWarner Losh    {6, 6}, {4, 4}, {5, 5},   /* '&' '|' '~' */
12468e3e3a7aSWarner Losh    {7, 7}, {7, 7},           /* '<<' '>>' */
12478e3e3a7aSWarner Losh    {9, 8},                   /* '..' (right associative) */
12488e3e3a7aSWarner Losh    {3, 3}, {3, 3}, {3, 3},   /* ==, <, <= */
12498e3e3a7aSWarner Losh    {3, 3}, {3, 3}, {3, 3},   /* ~=, >, >= */
12508e3e3a7aSWarner Losh    {2, 2}, {1, 1}            /* and, or */
12518e3e3a7aSWarner Losh };
12528e3e3a7aSWarner Losh 
12538e3e3a7aSWarner Losh #define UNARY_PRIORITY	12  /* priority for unary operators */
12548e3e3a7aSWarner Losh 
12558e3e3a7aSWarner Losh 
12568e3e3a7aSWarner Losh /*
12578e3e3a7aSWarner Losh ** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
12588e3e3a7aSWarner Losh ** where 'binop' is any binary operator with a priority higher than 'limit'
12598e3e3a7aSWarner Losh */
subexpr(LexState * ls,expdesc * v,int limit)12608e3e3a7aSWarner Losh static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
12618e3e3a7aSWarner Losh   BinOpr op;
12628e3e3a7aSWarner Losh   UnOpr uop;
12638e3e3a7aSWarner Losh   enterlevel(ls);
12648e3e3a7aSWarner Losh   uop = getunopr(ls->t.token);
12650495ed39SKyle Evans   if (uop != OPR_NOUNOPR) {  /* prefix (unary) operator? */
12668e3e3a7aSWarner Losh     int line = ls->linenumber;
12670495ed39SKyle Evans     luaX_next(ls);  /* skip operator */
12688e3e3a7aSWarner Losh     subexpr(ls, v, UNARY_PRIORITY);
12698e3e3a7aSWarner Losh     luaK_prefix(ls->fs, uop, v, line);
12708e3e3a7aSWarner Losh   }
12718e3e3a7aSWarner Losh   else simpleexp(ls, v);
12728e3e3a7aSWarner Losh   /* expand while operators have priorities higher than 'limit' */
12738e3e3a7aSWarner Losh   op = getbinopr(ls->t.token);
12748e3e3a7aSWarner Losh   while (op != OPR_NOBINOPR && priority[op].left > limit) {
12758e3e3a7aSWarner Losh     expdesc v2;
12768e3e3a7aSWarner Losh     BinOpr nextop;
12778e3e3a7aSWarner Losh     int line = ls->linenumber;
12780495ed39SKyle Evans     luaX_next(ls);  /* skip operator */
12798e3e3a7aSWarner Losh     luaK_infix(ls->fs, op, v);
12808e3e3a7aSWarner Losh     /* read sub-expression with higher priority */
12818e3e3a7aSWarner Losh     nextop = subexpr(ls, &v2, priority[op].right);
12828e3e3a7aSWarner Losh     luaK_posfix(ls->fs, op, v, &v2, line);
12838e3e3a7aSWarner Losh     op = nextop;
12848e3e3a7aSWarner Losh   }
12858e3e3a7aSWarner Losh   leavelevel(ls);
12868e3e3a7aSWarner Losh   return op;  /* return first untreated operator */
12878e3e3a7aSWarner Losh }
12888e3e3a7aSWarner Losh 
12898e3e3a7aSWarner Losh 
expr(LexState * ls,expdesc * v)12908e3e3a7aSWarner Losh static void expr (LexState *ls, expdesc *v) {
12918e3e3a7aSWarner Losh   subexpr(ls, v, 0);
12928e3e3a7aSWarner Losh }
12938e3e3a7aSWarner Losh 
12948e3e3a7aSWarner Losh /* }==================================================================== */
12958e3e3a7aSWarner Losh 
12968e3e3a7aSWarner Losh 
12978e3e3a7aSWarner Losh 
12988e3e3a7aSWarner Losh /*
12998e3e3a7aSWarner Losh ** {======================================================================
13008e3e3a7aSWarner Losh ** Rules for Statements
13018e3e3a7aSWarner Losh ** =======================================================================
13028e3e3a7aSWarner Losh */
13038e3e3a7aSWarner Losh 
13048e3e3a7aSWarner Losh 
block(LexState * ls)13058e3e3a7aSWarner Losh static void block (LexState *ls) {
13068e3e3a7aSWarner Losh   /* block -> statlist */
13078e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
13088e3e3a7aSWarner Losh   BlockCnt bl;
13098e3e3a7aSWarner Losh   enterblock(fs, &bl, 0);
13108e3e3a7aSWarner Losh   statlist(ls);
13118e3e3a7aSWarner Losh   leaveblock(fs);
13128e3e3a7aSWarner Losh }
13138e3e3a7aSWarner Losh 
13148e3e3a7aSWarner Losh 
13158e3e3a7aSWarner Losh /*
13168e3e3a7aSWarner Losh ** structure to chain all variables in the left-hand side of an
13178e3e3a7aSWarner Losh ** assignment
13188e3e3a7aSWarner Losh */
13198e3e3a7aSWarner Losh struct LHS_assign {
13208e3e3a7aSWarner Losh   struct LHS_assign *prev;
13218e3e3a7aSWarner Losh   expdesc v;  /* variable (global, local, upvalue, or indexed) */
13228e3e3a7aSWarner Losh };
13238e3e3a7aSWarner Losh 
13248e3e3a7aSWarner Losh 
13258e3e3a7aSWarner Losh /*
13268e3e3a7aSWarner Losh ** check whether, in an assignment to an upvalue/local variable, the
13278e3e3a7aSWarner Losh ** upvalue/local variable is begin used in a previous assignment to a
13288e3e3a7aSWarner Losh ** table. If so, save original upvalue/local value in a safe place and
13298e3e3a7aSWarner Losh ** use this safe copy in the previous assignment.
13308e3e3a7aSWarner Losh */
check_conflict(LexState * ls,struct LHS_assign * lh,expdesc * v)13318e3e3a7aSWarner Losh static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
13328e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
13338e3e3a7aSWarner Losh   int extra = fs->freereg;  /* eventual position to save local variable */
13348e3e3a7aSWarner Losh   int conflict = 0;
13358e3e3a7aSWarner Losh   for (; lh; lh = lh->prev) {  /* check all previous assignments */
13360495ed39SKyle Evans     if (vkisindexed(lh->v.k)) {  /* assignment to table field? */
13370495ed39SKyle Evans       if (lh->v.k == VINDEXUP) {  /* is table an upvalue? */
13380495ed39SKyle Evans         if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) {
13390495ed39SKyle Evans           conflict = 1;  /* table is the upvalue being assigned now */
13400495ed39SKyle Evans           lh->v.k = VINDEXSTR;
13410495ed39SKyle Evans           lh->v.u.ind.t = extra;  /* assignment will use safe copy */
13428e3e3a7aSWarner Losh         }
13430495ed39SKyle Evans       }
13440495ed39SKyle Evans       else {  /* table is a register */
13458c784bb8SWarner Losh         if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) {
13460495ed39SKyle Evans           conflict = 1;  /* table is the local being assigned now */
13470495ed39SKyle Evans           lh->v.u.ind.t = extra;  /* assignment will use safe copy */
13480495ed39SKyle Evans         }
13490495ed39SKyle Evans         /* is index the local being assigned? */
13500495ed39SKyle Evans         if (lh->v.k == VINDEXED && v->k == VLOCAL &&
13518c784bb8SWarner Losh             lh->v.u.ind.idx == v->u.var.ridx) {
13528e3e3a7aSWarner Losh           conflict = 1;
13538e3e3a7aSWarner Losh           lh->v.u.ind.idx = extra;  /* previous assignment will use safe copy */
13548e3e3a7aSWarner Losh         }
13558e3e3a7aSWarner Losh       }
13568e3e3a7aSWarner Losh     }
13570495ed39SKyle Evans   }
13588e3e3a7aSWarner Losh   if (conflict) {
13598e3e3a7aSWarner Losh     /* copy upvalue/local value to a temporary (in position 'extra') */
13600495ed39SKyle Evans     if (v->k == VLOCAL)
13618c784bb8SWarner Losh       luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0);
13620495ed39SKyle Evans     else
13630495ed39SKyle Evans       luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0);
13648e3e3a7aSWarner Losh     luaK_reserveregs(fs, 1);
13658e3e3a7aSWarner Losh   }
13668e3e3a7aSWarner Losh }
13678e3e3a7aSWarner Losh 
13680495ed39SKyle Evans /*
13690495ed39SKyle Evans ** Parse and compile a multiple assignment. The first "variable"
13700495ed39SKyle Evans ** (a 'suffixedexp') was already read by the caller.
13710495ed39SKyle Evans **
13720495ed39SKyle Evans ** assignment -> suffixedexp restassign
13730495ed39SKyle Evans ** restassign -> ',' suffixedexp restassign | '=' explist
13740495ed39SKyle Evans */
restassign(LexState * ls,struct LHS_assign * lh,int nvars)13750495ed39SKyle Evans static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) {
13768e3e3a7aSWarner Losh   expdesc e;
13778e3e3a7aSWarner Losh   check_condition(ls, vkisvar(lh->v.k), "syntax error");
13780495ed39SKyle Evans   check_readonly(ls, &lh->v);
13790495ed39SKyle Evans   if (testnext(ls, ',')) {  /* restassign -> ',' suffixedexp restassign */
13808e3e3a7aSWarner Losh     struct LHS_assign nv;
13818e3e3a7aSWarner Losh     nv.prev = lh;
13828e3e3a7aSWarner Losh     suffixedexp(ls, &nv.v);
13830495ed39SKyle Evans     if (!vkisindexed(nv.v.k))
13848e3e3a7aSWarner Losh       check_conflict(ls, lh, &nv.v);
13850495ed39SKyle Evans     enterlevel(ls);  /* control recursion depth */
13860495ed39SKyle Evans     restassign(ls, &nv, nvars+1);
13870495ed39SKyle Evans     leavelevel(ls);
13888e3e3a7aSWarner Losh   }
13890495ed39SKyle Evans   else {  /* restassign -> '=' explist */
13908e3e3a7aSWarner Losh     int nexps;
13918e3e3a7aSWarner Losh     checknext(ls, '=');
13928e3e3a7aSWarner Losh     nexps = explist(ls, &e);
13938e3e3a7aSWarner Losh     if (nexps != nvars)
13948e3e3a7aSWarner Losh       adjust_assign(ls, nvars, nexps, &e);
13958e3e3a7aSWarner Losh     else {
13968e3e3a7aSWarner Losh       luaK_setoneret(ls->fs, &e);  /* close last expression */
13978e3e3a7aSWarner Losh       luaK_storevar(ls->fs, &lh->v, &e);
13988e3e3a7aSWarner Losh       return;  /* avoid default */
13998e3e3a7aSWarner Losh     }
14008e3e3a7aSWarner Losh   }
14018e3e3a7aSWarner Losh   init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */
14028e3e3a7aSWarner Losh   luaK_storevar(ls->fs, &lh->v, &e);
14038e3e3a7aSWarner Losh }
14048e3e3a7aSWarner Losh 
14058e3e3a7aSWarner Losh 
cond(LexState * ls)14068e3e3a7aSWarner Losh static int cond (LexState *ls) {
14078e3e3a7aSWarner Losh   /* cond -> exp */
14088e3e3a7aSWarner Losh   expdesc v;
14098e3e3a7aSWarner Losh   expr(ls, &v);  /* read condition */
14108e3e3a7aSWarner Losh   if (v.k == VNIL) v.k = VFALSE;  /* 'falses' are all equal here */
14118e3e3a7aSWarner Losh   luaK_goiftrue(ls->fs, &v);
14128e3e3a7aSWarner Losh   return v.f;
14138e3e3a7aSWarner Losh }
14148e3e3a7aSWarner Losh 
14158e3e3a7aSWarner Losh 
gotostat(LexState * ls)14160495ed39SKyle Evans static void gotostat (LexState *ls) {
14178e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
14180495ed39SKyle Evans   int line = ls->linenumber;
14190495ed39SKyle Evans   TString *name = str_checkname(ls);  /* label's name */
14200495ed39SKyle Evans   Labeldesc *lb = findlabel(ls, name);
14210495ed39SKyle Evans   if (lb == NULL)  /* no label? */
14220495ed39SKyle Evans     /* forward jump; will be resolved when the label is declared */
14230495ed39SKyle Evans     newgotoentry(ls, name, line, luaK_jump(fs));
14240495ed39SKyle Evans   else {  /* found a label */
14250495ed39SKyle Evans     /* backward jump; will be resolved here */
14268c784bb8SWarner Losh     int lblevel = reglevel(fs, lb->nactvar);  /* label level */
14270495ed39SKyle Evans     if (luaY_nvarstack(fs) > lblevel)  /* leaving the scope of a variable? */
14280495ed39SKyle Evans       luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0);
14290495ed39SKyle Evans     /* create jump and link it to the label */
14300495ed39SKyle Evans     luaK_patchlist(fs, luaK_jump(fs), lb->pc);
14318e3e3a7aSWarner Losh   }
14320495ed39SKyle Evans }
14330495ed39SKyle Evans 
14340495ed39SKyle Evans 
14350495ed39SKyle Evans /*
14360495ed39SKyle Evans ** Break statement. Semantically equivalent to "goto break".
14370495ed39SKyle Evans */
breakstat(LexState * ls)14380495ed39SKyle Evans static void breakstat (LexState *ls) {
14390495ed39SKyle Evans   int line = ls->linenumber;
14400495ed39SKyle Evans   luaX_next(ls);  /* skip break */
14410495ed39SKyle Evans   newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, luaK_jump(ls->fs));
14420495ed39SKyle Evans }
14430495ed39SKyle Evans 
14440495ed39SKyle Evans 
14450495ed39SKyle Evans /*
14460495ed39SKyle Evans ** Check whether there is already a label with the given 'name'.
14470495ed39SKyle Evans */
checkrepeated(LexState * ls,TString * name)14480495ed39SKyle Evans static void checkrepeated (LexState *ls, TString *name) {
14490495ed39SKyle Evans   Labeldesc *lb = findlabel(ls, name);
14508c784bb8SWarner Losh   if (l_unlikely(lb != NULL)) {  /* already defined? */
14510495ed39SKyle Evans     const char *msg = "label '%s' already defined on line %d";
14520495ed39SKyle Evans     msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line);
14530495ed39SKyle Evans     luaK_semerror(ls, msg);  /* error */
14540495ed39SKyle Evans   }
14550495ed39SKyle Evans }
14560495ed39SKyle Evans 
14570495ed39SKyle Evans 
labelstat(LexState * ls,TString * name,int line)14580495ed39SKyle Evans static void labelstat (LexState *ls, TString *name, int line) {
14590495ed39SKyle Evans   /* label -> '::' NAME '::' */
14600495ed39SKyle Evans   checknext(ls, TK_DBCOLON);  /* skip double colon */
14610495ed39SKyle Evans   while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
14620495ed39SKyle Evans     statement(ls);  /* skip other no-op statements */
14630495ed39SKyle Evans   checkrepeated(ls, name);  /* check for repeated labels */
14640495ed39SKyle Evans   createlabel(ls, name, line, block_follow(ls, 0));
14658e3e3a7aSWarner Losh }
14668e3e3a7aSWarner Losh 
14678e3e3a7aSWarner Losh 
whilestat(LexState * ls,int line)14688e3e3a7aSWarner Losh static void whilestat (LexState *ls, int line) {
14698e3e3a7aSWarner Losh   /* whilestat -> WHILE cond DO block END */
14708e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
14718e3e3a7aSWarner Losh   int whileinit;
14728e3e3a7aSWarner Losh   int condexit;
14738e3e3a7aSWarner Losh   BlockCnt bl;
14748e3e3a7aSWarner Losh   luaX_next(ls);  /* skip WHILE */
14758e3e3a7aSWarner Losh   whileinit = luaK_getlabel(fs);
14768e3e3a7aSWarner Losh   condexit = cond(ls);
14778e3e3a7aSWarner Losh   enterblock(fs, &bl, 1);
14788e3e3a7aSWarner Losh   checknext(ls, TK_DO);
14798e3e3a7aSWarner Losh   block(ls);
14808e3e3a7aSWarner Losh   luaK_jumpto(fs, whileinit);
14818e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_WHILE, line);
14828e3e3a7aSWarner Losh   leaveblock(fs);
14838e3e3a7aSWarner Losh   luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */
14848e3e3a7aSWarner Losh }
14858e3e3a7aSWarner Losh 
14868e3e3a7aSWarner Losh 
repeatstat(LexState * ls,int line)14878e3e3a7aSWarner Losh static void repeatstat (LexState *ls, int line) {
14888e3e3a7aSWarner Losh   /* repeatstat -> REPEAT block UNTIL cond */
14898e3e3a7aSWarner Losh   int condexit;
14908e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
14918e3e3a7aSWarner Losh   int repeat_init = luaK_getlabel(fs);
14928e3e3a7aSWarner Losh   BlockCnt bl1, bl2;
14938e3e3a7aSWarner Losh   enterblock(fs, &bl1, 1);  /* loop block */
14948e3e3a7aSWarner Losh   enterblock(fs, &bl2, 0);  /* scope block */
14958e3e3a7aSWarner Losh   luaX_next(ls);  /* skip REPEAT */
14968e3e3a7aSWarner Losh   statlist(ls);
14978e3e3a7aSWarner Losh   check_match(ls, TK_UNTIL, TK_REPEAT, line);
14988e3e3a7aSWarner Losh   condexit = cond(ls);  /* read condition (inside scope block) */
14998e3e3a7aSWarner Losh   leaveblock(fs);  /* finish scope */
15000495ed39SKyle Evans   if (bl2.upval) {  /* upvalues? */
15010495ed39SKyle Evans     int exit = luaK_jump(fs);  /* normal exit must jump over fix */
15020495ed39SKyle Evans     luaK_patchtohere(fs, condexit);  /* repetition must close upvalues */
15038c784bb8SWarner Losh     luaK_codeABC(fs, OP_CLOSE, reglevel(fs, bl2.nactvar), 0, 0);
15040495ed39SKyle Evans     condexit = luaK_jump(fs);  /* repeat after closing upvalues */
15050495ed39SKyle Evans     luaK_patchtohere(fs, exit);  /* normal exit comes to here */
15060495ed39SKyle Evans   }
15078e3e3a7aSWarner Losh   luaK_patchlist(fs, condexit, repeat_init);  /* close the loop */
15088e3e3a7aSWarner Losh   leaveblock(fs);  /* finish loop */
15098e3e3a7aSWarner Losh }
15108e3e3a7aSWarner Losh 
15118e3e3a7aSWarner Losh 
15120495ed39SKyle Evans /*
15130495ed39SKyle Evans ** Read an expression and generate code to put its results in next
15140495ed39SKyle Evans ** stack slot.
15150495ed39SKyle Evans **
15160495ed39SKyle Evans */
exp1(LexState * ls)15170495ed39SKyle Evans static void exp1 (LexState *ls) {
15188e3e3a7aSWarner Losh   expdesc e;
15198e3e3a7aSWarner Losh   expr(ls, &e);
15208e3e3a7aSWarner Losh   luaK_exp2nextreg(ls->fs, &e);
15218e3e3a7aSWarner Losh   lua_assert(e.k == VNONRELOC);
15228e3e3a7aSWarner Losh }
15238e3e3a7aSWarner Losh 
15248e3e3a7aSWarner Losh 
15250495ed39SKyle Evans /*
15260495ed39SKyle Evans ** Fix for instruction at position 'pc' to jump to 'dest'.
15270495ed39SKyle Evans ** (Jump addresses are relative in Lua). 'back' true means
15280495ed39SKyle Evans ** a back jump.
15290495ed39SKyle Evans */
fixforjump(FuncState * fs,int pc,int dest,int back)15300495ed39SKyle Evans static void fixforjump (FuncState *fs, int pc, int dest, int back) {
15310495ed39SKyle Evans   Instruction *jmp = &fs->f->code[pc];
15320495ed39SKyle Evans   int offset = dest - (pc + 1);
15330495ed39SKyle Evans   if (back)
15340495ed39SKyle Evans     offset = -offset;
15358c784bb8SWarner Losh   if (l_unlikely(offset > MAXARG_Bx))
15360495ed39SKyle Evans     luaX_syntaxerror(fs->ls, "control structure too long");
15370495ed39SKyle Evans   SETARG_Bx(*jmp, offset);
15380495ed39SKyle Evans }
15390495ed39SKyle Evans 
15400495ed39SKyle Evans 
15410495ed39SKyle Evans /*
15420495ed39SKyle Evans ** Generate code for a 'for' loop.
15430495ed39SKyle Evans */
forbody(LexState * ls,int base,int line,int nvars,int isgen)15440495ed39SKyle Evans static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
15458e3e3a7aSWarner Losh   /* forbody -> DO block */
15460495ed39SKyle Evans   static const OpCode forprep[2] = {OP_FORPREP, OP_TFORPREP};
15470495ed39SKyle Evans   static const OpCode forloop[2] = {OP_FORLOOP, OP_TFORLOOP};
15488e3e3a7aSWarner Losh   BlockCnt bl;
15498e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
15508e3e3a7aSWarner Losh   int prep, endfor;
15518e3e3a7aSWarner Losh   checknext(ls, TK_DO);
15520495ed39SKyle Evans   prep = luaK_codeABx(fs, forprep[isgen], base, 0);
15538e3e3a7aSWarner Losh   enterblock(fs, &bl, 0);  /* scope for declared variables */
15548e3e3a7aSWarner Losh   adjustlocalvars(ls, nvars);
15558e3e3a7aSWarner Losh   luaK_reserveregs(fs, nvars);
15568e3e3a7aSWarner Losh   block(ls);
15578e3e3a7aSWarner Losh   leaveblock(fs);  /* end of scope for declared variables */
15580495ed39SKyle Evans   fixforjump(fs, prep, luaK_getlabel(fs), 0);
15590495ed39SKyle Evans   if (isgen) {  /* generic for? */
15608e3e3a7aSWarner Losh     luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
15618e3e3a7aSWarner Losh     luaK_fixline(fs, line);
15628e3e3a7aSWarner Losh   }
15630495ed39SKyle Evans   endfor = luaK_codeABx(fs, forloop[isgen], base, 0);
15640495ed39SKyle Evans   fixforjump(fs, endfor, prep + 1, 1);
15658e3e3a7aSWarner Losh   luaK_fixline(fs, line);
15668e3e3a7aSWarner Losh }
15678e3e3a7aSWarner Losh 
15688e3e3a7aSWarner Losh 
fornum(LexState * ls,TString * varname,int line)15698e3e3a7aSWarner Losh static void fornum (LexState *ls, TString *varname, int line) {
15700495ed39SKyle Evans   /* fornum -> NAME = exp,exp[,exp] forbody */
15718e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
15728e3e3a7aSWarner Losh   int base = fs->freereg;
15730495ed39SKyle Evans   new_localvarliteral(ls, "(for state)");
15740495ed39SKyle Evans   new_localvarliteral(ls, "(for state)");
15750495ed39SKyle Evans   new_localvarliteral(ls, "(for state)");
15768e3e3a7aSWarner Losh   new_localvar(ls, varname);
15778e3e3a7aSWarner Losh   checknext(ls, '=');
15788e3e3a7aSWarner Losh   exp1(ls);  /* initial value */
15798e3e3a7aSWarner Losh   checknext(ls, ',');
15808e3e3a7aSWarner Losh   exp1(ls);  /* limit */
15818e3e3a7aSWarner Losh   if (testnext(ls, ','))
15828e3e3a7aSWarner Losh     exp1(ls);  /* optional step */
15838e3e3a7aSWarner Losh   else {  /* default step = 1 */
15840495ed39SKyle Evans     luaK_int(fs, fs->freereg, 1);
15858e3e3a7aSWarner Losh     luaK_reserveregs(fs, 1);
15868e3e3a7aSWarner Losh   }
15870495ed39SKyle Evans   adjustlocalvars(ls, 3);  /* control variables */
15880495ed39SKyle Evans   forbody(ls, base, line, 1, 0);
15898e3e3a7aSWarner Losh }
15908e3e3a7aSWarner Losh 
15918e3e3a7aSWarner Losh 
forlist(LexState * ls,TString * indexname)15928e3e3a7aSWarner Losh static void forlist (LexState *ls, TString *indexname) {
15938e3e3a7aSWarner Losh   /* forlist -> NAME {,NAME} IN explist forbody */
15948e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
15958e3e3a7aSWarner Losh   expdesc e;
15960495ed39SKyle Evans   int nvars = 5;  /* gen, state, control, toclose, 'indexname' */
15978e3e3a7aSWarner Losh   int line;
15988e3e3a7aSWarner Losh   int base = fs->freereg;
15998e3e3a7aSWarner Losh   /* create control variables */
16008e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for state)");
16010495ed39SKyle Evans   new_localvarliteral(ls, "(for state)");
16020495ed39SKyle Evans   new_localvarliteral(ls, "(for state)");
16030495ed39SKyle Evans   new_localvarliteral(ls, "(for state)");
16048e3e3a7aSWarner Losh   /* create declared variables */
16058e3e3a7aSWarner Losh   new_localvar(ls, indexname);
16068e3e3a7aSWarner Losh   while (testnext(ls, ',')) {
16078e3e3a7aSWarner Losh     new_localvar(ls, str_checkname(ls));
16088e3e3a7aSWarner Losh     nvars++;
16098e3e3a7aSWarner Losh   }
16108e3e3a7aSWarner Losh   checknext(ls, TK_IN);
16118e3e3a7aSWarner Losh   line = ls->linenumber;
16120495ed39SKyle Evans   adjust_assign(ls, 4, explist(ls, &e), &e);
16130495ed39SKyle Evans   adjustlocalvars(ls, 4);  /* control variables */
16148c784bb8SWarner Losh   marktobeclosed(fs);  /* last control var. must be closed */
16158e3e3a7aSWarner Losh   luaK_checkstack(fs, 3);  /* extra space to call generator */
16160495ed39SKyle Evans   forbody(ls, base, line, nvars - 4, 1);
16178e3e3a7aSWarner Losh }
16188e3e3a7aSWarner Losh 
16198e3e3a7aSWarner Losh 
forstat(LexState * ls,int line)16208e3e3a7aSWarner Losh static void forstat (LexState *ls, int line) {
16218e3e3a7aSWarner Losh   /* forstat -> FOR (fornum | forlist) END */
16228e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
16238e3e3a7aSWarner Losh   TString *varname;
16248e3e3a7aSWarner Losh   BlockCnt bl;
16258e3e3a7aSWarner Losh   enterblock(fs, &bl, 1);  /* scope for loop and control variables */
16268e3e3a7aSWarner Losh   luaX_next(ls);  /* skip 'for' */
16278e3e3a7aSWarner Losh   varname = str_checkname(ls);  /* first variable name */
16288e3e3a7aSWarner Losh   switch (ls->t.token) {
16298e3e3a7aSWarner Losh     case '=': fornum(ls, varname, line); break;
16308e3e3a7aSWarner Losh     case ',': case TK_IN: forlist(ls, varname); break;
16318e3e3a7aSWarner Losh     default: luaX_syntaxerror(ls, "'=' or 'in' expected");
16328e3e3a7aSWarner Losh   }
16338e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_FOR, line);
16348e3e3a7aSWarner Losh   leaveblock(fs);  /* loop scope ('break' jumps to this point) */
16358e3e3a7aSWarner Losh }
16368e3e3a7aSWarner Losh 
16378e3e3a7aSWarner Losh 
test_then_block(LexState * ls,int * escapelist)16388e3e3a7aSWarner Losh static void test_then_block (LexState *ls, int *escapelist) {
16398e3e3a7aSWarner Losh   /* test_then_block -> [IF | ELSEIF] cond THEN block */
16408e3e3a7aSWarner Losh   BlockCnt bl;
16418e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
16428e3e3a7aSWarner Losh   expdesc v;
16438e3e3a7aSWarner Losh   int jf;  /* instruction to skip 'then' code (if condition is false) */
16448e3e3a7aSWarner Losh   luaX_next(ls);  /* skip IF or ELSEIF */
16458e3e3a7aSWarner Losh   expr(ls, &v);  /* read condition */
16468e3e3a7aSWarner Losh   checknext(ls, TK_THEN);
16470495ed39SKyle Evans   if (ls->t.token == TK_BREAK) {  /* 'if x then break' ? */
16480495ed39SKyle Evans     int line = ls->linenumber;
16490495ed39SKyle Evans     luaK_goiffalse(ls->fs, &v);  /* will jump if condition is true */
16500495ed39SKyle Evans     luaX_next(ls);  /* skip 'break' */
16518e3e3a7aSWarner Losh     enterblock(fs, &bl, 0);  /* must enter block before 'goto' */
16520495ed39SKyle Evans     newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
16530495ed39SKyle Evans     while (testnext(ls, ';')) {}  /* skip semicolons */
16540495ed39SKyle Evans     if (block_follow(ls, 0)) {  /* jump is the entire block? */
16558e3e3a7aSWarner Losh       leaveblock(fs);
16568e3e3a7aSWarner Losh       return;  /* and that is it */
16578e3e3a7aSWarner Losh     }
16588e3e3a7aSWarner Losh     else  /* must skip over 'then' part if condition is false */
16598e3e3a7aSWarner Losh       jf = luaK_jump(fs);
16608e3e3a7aSWarner Losh   }
16610495ed39SKyle Evans   else {  /* regular case (not a break) */
16628e3e3a7aSWarner Losh     luaK_goiftrue(ls->fs, &v);  /* skip over block if condition is false */
16638e3e3a7aSWarner Losh     enterblock(fs, &bl, 0);
16648e3e3a7aSWarner Losh     jf = v.f;
16658e3e3a7aSWarner Losh   }
16668e3e3a7aSWarner Losh   statlist(ls);  /* 'then' part */
16678e3e3a7aSWarner Losh   leaveblock(fs);
16688e3e3a7aSWarner Losh   if (ls->t.token == TK_ELSE ||
16698e3e3a7aSWarner Losh       ls->t.token == TK_ELSEIF)  /* followed by 'else'/'elseif'? */
16708e3e3a7aSWarner Losh     luaK_concat(fs, escapelist, luaK_jump(fs));  /* must jump over it */
16718e3e3a7aSWarner Losh   luaK_patchtohere(fs, jf);
16728e3e3a7aSWarner Losh }
16738e3e3a7aSWarner Losh 
16748e3e3a7aSWarner Losh 
ifstat(LexState * ls,int line)16758e3e3a7aSWarner Losh static void ifstat (LexState *ls, int line) {
16768e3e3a7aSWarner Losh   /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
16778e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
16788e3e3a7aSWarner Losh   int escapelist = NO_JUMP;  /* exit list for finished parts */
16798e3e3a7aSWarner Losh   test_then_block(ls, &escapelist);  /* IF cond THEN block */
16808e3e3a7aSWarner Losh   while (ls->t.token == TK_ELSEIF)
16818e3e3a7aSWarner Losh     test_then_block(ls, &escapelist);  /* ELSEIF cond THEN block */
16828e3e3a7aSWarner Losh   if (testnext(ls, TK_ELSE))
16838e3e3a7aSWarner Losh     block(ls);  /* 'else' part */
16848e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_IF, line);
16858e3e3a7aSWarner Losh   luaK_patchtohere(fs, escapelist);  /* patch escape list to 'if' end */
16868e3e3a7aSWarner Losh }
16878e3e3a7aSWarner Losh 
16888e3e3a7aSWarner Losh 
localfunc(LexState * ls)16898e3e3a7aSWarner Losh static void localfunc (LexState *ls) {
16908e3e3a7aSWarner Losh   expdesc b;
16918e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
16920495ed39SKyle Evans   int fvar = fs->nactvar;  /* function's variable index */
16938e3e3a7aSWarner Losh   new_localvar(ls, str_checkname(ls));  /* new local variable */
16948e3e3a7aSWarner Losh   adjustlocalvars(ls, 1);  /* enter its scope */
16958e3e3a7aSWarner Losh   body(ls, &b, 0, ls->linenumber);  /* function created in next register */
16968e3e3a7aSWarner Losh   /* debug information will only see the variable after this point! */
16970495ed39SKyle Evans   localdebuginfo(fs, fvar)->startpc = fs->pc;
16980495ed39SKyle Evans }
16990495ed39SKyle Evans 
17000495ed39SKyle Evans 
getlocalattribute(LexState * ls)17010495ed39SKyle Evans static int getlocalattribute (LexState *ls) {
17020495ed39SKyle Evans   /* ATTRIB -> ['<' Name '>'] */
17030495ed39SKyle Evans   if (testnext(ls, '<')) {
17040495ed39SKyle Evans     const char *attr = getstr(str_checkname(ls));
17050495ed39SKyle Evans     checknext(ls, '>');
17060495ed39SKyle Evans     if (strcmp(attr, "const") == 0)
17070495ed39SKyle Evans       return RDKCONST;  /* read-only variable */
17080495ed39SKyle Evans     else if (strcmp(attr, "close") == 0)
17090495ed39SKyle Evans       return RDKTOCLOSE;  /* to-be-closed variable */
17100495ed39SKyle Evans     else
17110495ed39SKyle Evans       luaK_semerror(ls,
17120495ed39SKyle Evans         luaO_pushfstring(ls->L, "unknown attribute '%s'", attr));
17130495ed39SKyle Evans   }
17140495ed39SKyle Evans   return VDKREG;  /* regular variable */
17150495ed39SKyle Evans }
17160495ed39SKyle Evans 
17170495ed39SKyle Evans 
checktoclose(FuncState * fs,int level)17188c784bb8SWarner Losh static void checktoclose (FuncState *fs, int level) {
17190495ed39SKyle Evans   if (level != -1) {  /* is there a to-be-closed variable? */
17208c784bb8SWarner Losh     marktobeclosed(fs);
17218c784bb8SWarner Losh     luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
17220495ed39SKyle Evans   }
17238e3e3a7aSWarner Losh }
17248e3e3a7aSWarner Losh 
17258e3e3a7aSWarner Losh 
localstat(LexState * ls)17268e3e3a7aSWarner Losh static void localstat (LexState *ls) {
17270495ed39SKyle Evans   /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */
17280495ed39SKyle Evans   FuncState *fs = ls->fs;
17290495ed39SKyle Evans   int toclose = -1;  /* index of to-be-closed variable (if any) */
17300495ed39SKyle Evans   Vardesc *var;  /* last variable */
17310495ed39SKyle Evans   int vidx, kind;  /* index and kind of last variable */
17328e3e3a7aSWarner Losh   int nvars = 0;
17338e3e3a7aSWarner Losh   int nexps;
17348e3e3a7aSWarner Losh   expdesc e;
17358e3e3a7aSWarner Losh   do {
17360495ed39SKyle Evans     vidx = new_localvar(ls, str_checkname(ls));
17370495ed39SKyle Evans     kind = getlocalattribute(ls);
17380495ed39SKyle Evans     getlocalvardesc(fs, vidx)->vd.kind = kind;
17390495ed39SKyle Evans     if (kind == RDKTOCLOSE) {  /* to-be-closed? */
17400495ed39SKyle Evans       if (toclose != -1)  /* one already present? */
17410495ed39SKyle Evans         luaK_semerror(ls, "multiple to-be-closed variables in local list");
17420495ed39SKyle Evans       toclose = fs->nactvar + nvars;
17430495ed39SKyle Evans     }
17448e3e3a7aSWarner Losh     nvars++;
17458e3e3a7aSWarner Losh   } while (testnext(ls, ','));
17468e3e3a7aSWarner Losh   if (testnext(ls, '='))
17478e3e3a7aSWarner Losh     nexps = explist(ls, &e);
17488e3e3a7aSWarner Losh   else {
17498e3e3a7aSWarner Losh     e.k = VVOID;
17508e3e3a7aSWarner Losh     nexps = 0;
17518e3e3a7aSWarner Losh   }
17520495ed39SKyle Evans   var = getlocalvardesc(fs, vidx);  /* get last variable */
17530495ed39SKyle Evans   if (nvars == nexps &&  /* no adjustments? */
17540495ed39SKyle Evans       var->vd.kind == RDKCONST &&  /* last variable is const? */
17550495ed39SKyle Evans       luaK_exp2const(fs, &e, &var->k)) {  /* compile-time constant? */
17560495ed39SKyle Evans     var->vd.kind = RDKCTC;  /* variable is a compile-time constant */
17570495ed39SKyle Evans     adjustlocalvars(ls, nvars - 1);  /* exclude last variable */
17580495ed39SKyle Evans     fs->nactvar++;  /* but count it */
17590495ed39SKyle Evans   }
17600495ed39SKyle Evans   else {
17618e3e3a7aSWarner Losh     adjust_assign(ls, nvars, nexps, &e);
17628e3e3a7aSWarner Losh     adjustlocalvars(ls, nvars);
17638e3e3a7aSWarner Losh   }
17648c784bb8SWarner Losh   checktoclose(fs, toclose);
17650495ed39SKyle Evans }
17668e3e3a7aSWarner Losh 
17678e3e3a7aSWarner Losh 
funcname(LexState * ls,expdesc * v)17688e3e3a7aSWarner Losh static int funcname (LexState *ls, expdesc *v) {
17698e3e3a7aSWarner Losh   /* funcname -> NAME {fieldsel} [':' NAME] */
17708e3e3a7aSWarner Losh   int ismethod = 0;
17718e3e3a7aSWarner Losh   singlevar(ls, v);
17728e3e3a7aSWarner Losh   while (ls->t.token == '.')
17738e3e3a7aSWarner Losh     fieldsel(ls, v);
17748e3e3a7aSWarner Losh   if (ls->t.token == ':') {
17758e3e3a7aSWarner Losh     ismethod = 1;
17768e3e3a7aSWarner Losh     fieldsel(ls, v);
17778e3e3a7aSWarner Losh   }
17788e3e3a7aSWarner Losh   return ismethod;
17798e3e3a7aSWarner Losh }
17808e3e3a7aSWarner Losh 
17818e3e3a7aSWarner Losh 
funcstat(LexState * ls,int line)17828e3e3a7aSWarner Losh static void funcstat (LexState *ls, int line) {
17838e3e3a7aSWarner Losh   /* funcstat -> FUNCTION funcname body */
17848e3e3a7aSWarner Losh   int ismethod;
17858e3e3a7aSWarner Losh   expdesc v, b;
17868e3e3a7aSWarner Losh   luaX_next(ls);  /* skip FUNCTION */
17878e3e3a7aSWarner Losh   ismethod = funcname(ls, &v);
17888e3e3a7aSWarner Losh   body(ls, &b, ismethod, line);
17898c784bb8SWarner Losh   check_readonly(ls, &v);
17908e3e3a7aSWarner Losh   luaK_storevar(ls->fs, &v, &b);
17918e3e3a7aSWarner Losh   luaK_fixline(ls->fs, line);  /* definition "happens" in the first line */
17928e3e3a7aSWarner Losh }
17938e3e3a7aSWarner Losh 
17948e3e3a7aSWarner Losh 
exprstat(LexState * ls)17958e3e3a7aSWarner Losh static void exprstat (LexState *ls) {
17968e3e3a7aSWarner Losh   /* stat -> func | assignment */
17978e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
17988e3e3a7aSWarner Losh   struct LHS_assign v;
17998e3e3a7aSWarner Losh   suffixedexp(ls, &v.v);
18008e3e3a7aSWarner Losh   if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
18018e3e3a7aSWarner Losh     v.prev = NULL;
18020495ed39SKyle Evans     restassign(ls, &v, 1);
18038e3e3a7aSWarner Losh   }
18048e3e3a7aSWarner Losh   else {  /* stat -> func */
18050495ed39SKyle Evans     Instruction *inst;
18068e3e3a7aSWarner Losh     check_condition(ls, v.v.k == VCALL, "syntax error");
18070495ed39SKyle Evans     inst = &getinstruction(fs, &v.v);
18080495ed39SKyle Evans     SETARG_C(*inst, 1);  /* call statement uses no results */
18098e3e3a7aSWarner Losh   }
18108e3e3a7aSWarner Losh }
18118e3e3a7aSWarner Losh 
18128e3e3a7aSWarner Losh 
retstat(LexState * ls)18138e3e3a7aSWarner Losh static void retstat (LexState *ls) {
18148e3e3a7aSWarner Losh   /* stat -> RETURN [explist] [';'] */
18158e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
18168e3e3a7aSWarner Losh   expdesc e;
18170495ed39SKyle Evans   int nret;  /* number of values being returned */
18180495ed39SKyle Evans   int first = luaY_nvarstack(fs);  /* first slot to be returned */
18198e3e3a7aSWarner Losh   if (block_follow(ls, 1) || ls->t.token == ';')
18200495ed39SKyle Evans     nret = 0;  /* return no values */
18218e3e3a7aSWarner Losh   else {
18228e3e3a7aSWarner Losh     nret = explist(ls, &e);  /* optional return values */
18238e3e3a7aSWarner Losh     if (hasmultret(e.k)) {
18248e3e3a7aSWarner Losh       luaK_setmultret(fs, &e);
18250495ed39SKyle Evans       if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) {  /* tail call? */
18268e3e3a7aSWarner Losh         SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
18270495ed39SKyle Evans         lua_assert(GETARG_A(getinstruction(fs,&e)) == luaY_nvarstack(fs));
18288e3e3a7aSWarner Losh       }
18298e3e3a7aSWarner Losh       nret = LUA_MULTRET;  /* return all values */
18308e3e3a7aSWarner Losh     }
18318e3e3a7aSWarner Losh     else {
18328e3e3a7aSWarner Losh       if (nret == 1)  /* only one single value? */
18330495ed39SKyle Evans         first = luaK_exp2anyreg(fs, &e);  /* can use original slot */
18340495ed39SKyle Evans       else {  /* values must go to the top of the stack */
18350495ed39SKyle Evans         luaK_exp2nextreg(fs, &e);
18368e3e3a7aSWarner Losh         lua_assert(nret == fs->freereg - first);
18378e3e3a7aSWarner Losh       }
18388e3e3a7aSWarner Losh     }
18398e3e3a7aSWarner Losh   }
18408e3e3a7aSWarner Losh   luaK_ret(fs, first, nret);
18418e3e3a7aSWarner Losh   testnext(ls, ';');  /* skip optional semicolon */
18428e3e3a7aSWarner Losh }
18438e3e3a7aSWarner Losh 
18448e3e3a7aSWarner Losh 
statement(LexState * ls)18458e3e3a7aSWarner Losh static void statement (LexState *ls) {
18468e3e3a7aSWarner Losh   int line = ls->linenumber;  /* may be needed for error messages */
18478e3e3a7aSWarner Losh   enterlevel(ls);
18488e3e3a7aSWarner Losh   switch (ls->t.token) {
18498e3e3a7aSWarner Losh     case ';': {  /* stat -> ';' (empty statement) */
18508e3e3a7aSWarner Losh       luaX_next(ls);  /* skip ';' */
18518e3e3a7aSWarner Losh       break;
18528e3e3a7aSWarner Losh     }
18538e3e3a7aSWarner Losh     case TK_IF: {  /* stat -> ifstat */
18548e3e3a7aSWarner Losh       ifstat(ls, line);
18558e3e3a7aSWarner Losh       break;
18568e3e3a7aSWarner Losh     }
18578e3e3a7aSWarner Losh     case TK_WHILE: {  /* stat -> whilestat */
18588e3e3a7aSWarner Losh       whilestat(ls, line);
18598e3e3a7aSWarner Losh       break;
18608e3e3a7aSWarner Losh     }
18618e3e3a7aSWarner Losh     case TK_DO: {  /* stat -> DO block END */
18628e3e3a7aSWarner Losh       luaX_next(ls);  /* skip DO */
18638e3e3a7aSWarner Losh       block(ls);
18648e3e3a7aSWarner Losh       check_match(ls, TK_END, TK_DO, line);
18658e3e3a7aSWarner Losh       break;
18668e3e3a7aSWarner Losh     }
18678e3e3a7aSWarner Losh     case TK_FOR: {  /* stat -> forstat */
18688e3e3a7aSWarner Losh       forstat(ls, line);
18698e3e3a7aSWarner Losh       break;
18708e3e3a7aSWarner Losh     }
18718e3e3a7aSWarner Losh     case TK_REPEAT: {  /* stat -> repeatstat */
18728e3e3a7aSWarner Losh       repeatstat(ls, line);
18738e3e3a7aSWarner Losh       break;
18748e3e3a7aSWarner Losh     }
18758e3e3a7aSWarner Losh     case TK_FUNCTION: {  /* stat -> funcstat */
18768e3e3a7aSWarner Losh       funcstat(ls, line);
18778e3e3a7aSWarner Losh       break;
18788e3e3a7aSWarner Losh     }
18798e3e3a7aSWarner Losh     case TK_LOCAL: {  /* stat -> localstat */
18808e3e3a7aSWarner Losh       luaX_next(ls);  /* skip LOCAL */
18818e3e3a7aSWarner Losh       if (testnext(ls, TK_FUNCTION))  /* local function? */
18828e3e3a7aSWarner Losh         localfunc(ls);
18838e3e3a7aSWarner Losh       else
18848e3e3a7aSWarner Losh         localstat(ls);
18858e3e3a7aSWarner Losh       break;
18868e3e3a7aSWarner Losh     }
18878e3e3a7aSWarner Losh     case TK_DBCOLON: {  /* stat -> label */
18888e3e3a7aSWarner Losh       luaX_next(ls);  /* skip double colon */
18898e3e3a7aSWarner Losh       labelstat(ls, str_checkname(ls), line);
18908e3e3a7aSWarner Losh       break;
18918e3e3a7aSWarner Losh     }
18928e3e3a7aSWarner Losh     case TK_RETURN: {  /* stat -> retstat */
18938e3e3a7aSWarner Losh       luaX_next(ls);  /* skip RETURN */
18948e3e3a7aSWarner Losh       retstat(ls);
18958e3e3a7aSWarner Losh       break;
18968e3e3a7aSWarner Losh     }
18970495ed39SKyle Evans     case TK_BREAK: {  /* stat -> breakstat */
18980495ed39SKyle Evans       breakstat(ls);
18990495ed39SKyle Evans       break;
19000495ed39SKyle Evans     }
19018e3e3a7aSWarner Losh     case TK_GOTO: {  /* stat -> 'goto' NAME */
19020495ed39SKyle Evans       luaX_next(ls);  /* skip 'goto' */
19030495ed39SKyle Evans       gotostat(ls);
19048e3e3a7aSWarner Losh       break;
19058e3e3a7aSWarner Losh     }
19068e3e3a7aSWarner Losh     default: {  /* stat -> func | assignment */
19078e3e3a7aSWarner Losh       exprstat(ls);
19088e3e3a7aSWarner Losh       break;
19098e3e3a7aSWarner Losh     }
19108e3e3a7aSWarner Losh   }
19118e3e3a7aSWarner Losh   lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
19120495ed39SKyle Evans              ls->fs->freereg >= luaY_nvarstack(ls->fs));
19130495ed39SKyle Evans   ls->fs->freereg = luaY_nvarstack(ls->fs);  /* free registers */
19148e3e3a7aSWarner Losh   leavelevel(ls);
19158e3e3a7aSWarner Losh }
19168e3e3a7aSWarner Losh 
19178e3e3a7aSWarner Losh /* }====================================================================== */
19188e3e3a7aSWarner Losh 
19198e3e3a7aSWarner Losh 
19208e3e3a7aSWarner Losh /*
19218e3e3a7aSWarner Losh ** compiles the main function, which is a regular vararg function with an
19228e3e3a7aSWarner Losh ** upvalue named LUA_ENV
19238e3e3a7aSWarner Losh */
mainfunc(LexState * ls,FuncState * fs)19248e3e3a7aSWarner Losh static void mainfunc (LexState *ls, FuncState *fs) {
19258e3e3a7aSWarner Losh   BlockCnt bl;
19260495ed39SKyle Evans   Upvaldesc *env;
19278e3e3a7aSWarner Losh   open_func(ls, fs, &bl);
19280495ed39SKyle Evans   setvararg(fs, 0);  /* main function is always declared vararg */
19290495ed39SKyle Evans   env = allocupvalue(fs);  /* ...set environment upvalue */
19300495ed39SKyle Evans   env->instack = 1;
19310495ed39SKyle Evans   env->idx = 0;
19320495ed39SKyle Evans   env->kind = VDKREG;
19330495ed39SKyle Evans   env->name = ls->envn;
19340495ed39SKyle Evans   luaC_objbarrier(ls->L, fs->f, env->name);
19358e3e3a7aSWarner Losh   luaX_next(ls);  /* read first token */
19368e3e3a7aSWarner Losh   statlist(ls);  /* parse main body */
19378e3e3a7aSWarner Losh   check(ls, TK_EOS);
19388e3e3a7aSWarner Losh   close_func(ls);
19398e3e3a7aSWarner Losh }
19408e3e3a7aSWarner Losh 
19418e3e3a7aSWarner Losh 
luaY_parser(lua_State * L,ZIO * z,Mbuffer * buff,Dyndata * dyd,const char * name,int firstchar)19428e3e3a7aSWarner Losh LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
19438e3e3a7aSWarner Losh                        Dyndata *dyd, const char *name, int firstchar) {
19448e3e3a7aSWarner Losh   LexState lexstate;
19458e3e3a7aSWarner Losh   FuncState funcstate;
19468e3e3a7aSWarner Losh   LClosure *cl = luaF_newLclosure(L, 1);  /* create main closure */
1947*a9490b81SWarner Losh   setclLvalue2s(L, L->top.p, cl);  /* anchor it (to avoid being collected) */
19488e3e3a7aSWarner Losh   luaD_inctop(L);
19498e3e3a7aSWarner Losh   lexstate.h = luaH_new(L);  /* create table for scanner */
1950*a9490b81SWarner Losh   sethvalue2s(L, L->top.p, lexstate.h);  /* anchor it */
19518e3e3a7aSWarner Losh   luaD_inctop(L);
19528e3e3a7aSWarner Losh   funcstate.f = cl->p = luaF_newproto(L);
1953bf9580a1SKyle Evans   luaC_objbarrier(L, cl, cl->p);
19548e3e3a7aSWarner Losh   funcstate.f->source = luaS_new(L, name);  /* create and anchor TString */
19550495ed39SKyle Evans   luaC_objbarrier(L, funcstate.f, funcstate.f->source);
19568e3e3a7aSWarner Losh   lexstate.buff = buff;
19578e3e3a7aSWarner Losh   lexstate.dyd = dyd;
19588e3e3a7aSWarner Losh   dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
19598e3e3a7aSWarner Losh   luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
19608e3e3a7aSWarner Losh   mainfunc(&lexstate, &funcstate);
19618e3e3a7aSWarner Losh   lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
19628e3e3a7aSWarner Losh   /* all scopes should be correctly finished */
19638e3e3a7aSWarner Losh   lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
1964*a9490b81SWarner Losh   L->top.p--;  /* remove scanner's table */
19658e3e3a7aSWarner Losh   return cl;  /* closure is on the stack, too */
19668e3e3a7aSWarner Losh }
19678e3e3a7aSWarner Losh 
1968