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