xref: /freebsd/contrib/lua/src/lparser.c (revision 8e3e3a7ae841ccf6f6ac30a2eeab85df5d7f04bc)
1*8e3e3a7aSWarner Losh /*
2*8e3e3a7aSWarner Losh ** $Id: lparser.c,v 2.155 2016/08/01 19:51:24 roberto Exp $
3*8e3e3a7aSWarner Losh ** Lua Parser
4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h
5*8e3e3a7aSWarner Losh */
6*8e3e3a7aSWarner Losh 
7*8e3e3a7aSWarner Losh #define lparser_c
8*8e3e3a7aSWarner Losh #define LUA_CORE
9*8e3e3a7aSWarner Losh 
10*8e3e3a7aSWarner Losh #include "lprefix.h"
11*8e3e3a7aSWarner Losh 
12*8e3e3a7aSWarner Losh 
13*8e3e3a7aSWarner Losh #include <string.h>
14*8e3e3a7aSWarner Losh 
15*8e3e3a7aSWarner Losh #include "lua.h"
16*8e3e3a7aSWarner Losh 
17*8e3e3a7aSWarner Losh #include "lcode.h"
18*8e3e3a7aSWarner Losh #include "ldebug.h"
19*8e3e3a7aSWarner Losh #include "ldo.h"
20*8e3e3a7aSWarner Losh #include "lfunc.h"
21*8e3e3a7aSWarner Losh #include "llex.h"
22*8e3e3a7aSWarner Losh #include "lmem.h"
23*8e3e3a7aSWarner Losh #include "lobject.h"
24*8e3e3a7aSWarner Losh #include "lopcodes.h"
25*8e3e3a7aSWarner Losh #include "lparser.h"
26*8e3e3a7aSWarner Losh #include "lstate.h"
27*8e3e3a7aSWarner Losh #include "lstring.h"
28*8e3e3a7aSWarner Losh #include "ltable.h"
29*8e3e3a7aSWarner Losh 
30*8e3e3a7aSWarner Losh 
31*8e3e3a7aSWarner Losh 
32*8e3e3a7aSWarner Losh /* maximum number of local variables per function (must be smaller
33*8e3e3a7aSWarner Losh    than 250, due to the bytecode format) */
34*8e3e3a7aSWarner Losh #define MAXVARS		200
35*8e3e3a7aSWarner Losh 
36*8e3e3a7aSWarner Losh 
37*8e3e3a7aSWarner Losh #define hasmultret(k)		((k) == VCALL || (k) == VVARARG)
38*8e3e3a7aSWarner Losh 
39*8e3e3a7aSWarner Losh 
40*8e3e3a7aSWarner Losh /* because all strings are unified by the scanner, the parser
41*8e3e3a7aSWarner Losh    can use pointer equality for string equality */
42*8e3e3a7aSWarner Losh #define eqstr(a,b)	((a) == (b))
43*8e3e3a7aSWarner Losh 
44*8e3e3a7aSWarner Losh 
45*8e3e3a7aSWarner Losh /*
46*8e3e3a7aSWarner Losh ** nodes for block list (list of active blocks)
47*8e3e3a7aSWarner Losh */
48*8e3e3a7aSWarner Losh typedef struct BlockCnt {
49*8e3e3a7aSWarner Losh   struct BlockCnt *previous;  /* chain */
50*8e3e3a7aSWarner Losh   int firstlabel;  /* index of first label in this block */
51*8e3e3a7aSWarner Losh   int firstgoto;  /* index of first pending goto in this block */
52*8e3e3a7aSWarner Losh   lu_byte nactvar;  /* # active locals outside the block */
53*8e3e3a7aSWarner Losh   lu_byte upval;  /* true if some variable in the block is an upvalue */
54*8e3e3a7aSWarner Losh   lu_byte isloop;  /* true if 'block' is a loop */
55*8e3e3a7aSWarner Losh } BlockCnt;
56*8e3e3a7aSWarner Losh 
57*8e3e3a7aSWarner Losh 
58*8e3e3a7aSWarner Losh 
59*8e3e3a7aSWarner Losh /*
60*8e3e3a7aSWarner Losh ** prototypes for recursive non-terminal functions
61*8e3e3a7aSWarner Losh */
62*8e3e3a7aSWarner Losh static void statement (LexState *ls);
63*8e3e3a7aSWarner Losh static void expr (LexState *ls, expdesc *v);
64*8e3e3a7aSWarner Losh 
65*8e3e3a7aSWarner Losh 
66*8e3e3a7aSWarner Losh /* semantic error */
67*8e3e3a7aSWarner Losh static l_noret semerror (LexState *ls, const char *msg) {
68*8e3e3a7aSWarner Losh   ls->t.token = 0;  /* remove "near <token>" from final message */
69*8e3e3a7aSWarner Losh   luaX_syntaxerror(ls, msg);
70*8e3e3a7aSWarner Losh }
71*8e3e3a7aSWarner Losh 
72*8e3e3a7aSWarner Losh 
73*8e3e3a7aSWarner Losh static l_noret error_expected (LexState *ls, int token) {
74*8e3e3a7aSWarner Losh   luaX_syntaxerror(ls,
75*8e3e3a7aSWarner Losh       luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token)));
76*8e3e3a7aSWarner Losh }
77*8e3e3a7aSWarner Losh 
78*8e3e3a7aSWarner Losh 
79*8e3e3a7aSWarner Losh static l_noret errorlimit (FuncState *fs, int limit, const char *what) {
80*8e3e3a7aSWarner Losh   lua_State *L = fs->ls->L;
81*8e3e3a7aSWarner Losh   const char *msg;
82*8e3e3a7aSWarner Losh   int line = fs->f->linedefined;
83*8e3e3a7aSWarner Losh   const char *where = (line == 0)
84*8e3e3a7aSWarner Losh                       ? "main function"
85*8e3e3a7aSWarner Losh                       : luaO_pushfstring(L, "function at line %d", line);
86*8e3e3a7aSWarner Losh   msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s",
87*8e3e3a7aSWarner Losh                              what, limit, where);
88*8e3e3a7aSWarner Losh   luaX_syntaxerror(fs->ls, msg);
89*8e3e3a7aSWarner Losh }
90*8e3e3a7aSWarner Losh 
91*8e3e3a7aSWarner Losh 
92*8e3e3a7aSWarner Losh static void checklimit (FuncState *fs, int v, int l, const char *what) {
93*8e3e3a7aSWarner Losh   if (v > l) errorlimit(fs, l, what);
94*8e3e3a7aSWarner Losh }
95*8e3e3a7aSWarner Losh 
96*8e3e3a7aSWarner Losh 
97*8e3e3a7aSWarner Losh static int testnext (LexState *ls, int c) {
98*8e3e3a7aSWarner Losh   if (ls->t.token == c) {
99*8e3e3a7aSWarner Losh     luaX_next(ls);
100*8e3e3a7aSWarner Losh     return 1;
101*8e3e3a7aSWarner Losh   }
102*8e3e3a7aSWarner Losh   else return 0;
103*8e3e3a7aSWarner Losh }
104*8e3e3a7aSWarner Losh 
105*8e3e3a7aSWarner Losh 
106*8e3e3a7aSWarner Losh static void check (LexState *ls, int c) {
107*8e3e3a7aSWarner Losh   if (ls->t.token != c)
108*8e3e3a7aSWarner Losh     error_expected(ls, c);
109*8e3e3a7aSWarner Losh }
110*8e3e3a7aSWarner Losh 
111*8e3e3a7aSWarner Losh 
112*8e3e3a7aSWarner Losh static void checknext (LexState *ls, int c) {
113*8e3e3a7aSWarner Losh   check(ls, c);
114*8e3e3a7aSWarner Losh   luaX_next(ls);
115*8e3e3a7aSWarner Losh }
116*8e3e3a7aSWarner Losh 
117*8e3e3a7aSWarner Losh 
118*8e3e3a7aSWarner Losh #define check_condition(ls,c,msg)	{ if (!(c)) luaX_syntaxerror(ls, msg); }
119*8e3e3a7aSWarner Losh 
120*8e3e3a7aSWarner Losh 
121*8e3e3a7aSWarner Losh 
122*8e3e3a7aSWarner Losh static void check_match (LexState *ls, int what, int who, int where) {
123*8e3e3a7aSWarner Losh   if (!testnext(ls, what)) {
124*8e3e3a7aSWarner Losh     if (where == ls->linenumber)
125*8e3e3a7aSWarner Losh       error_expected(ls, what);
126*8e3e3a7aSWarner Losh     else {
127*8e3e3a7aSWarner Losh       luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
128*8e3e3a7aSWarner Losh              "%s expected (to close %s at line %d)",
129*8e3e3a7aSWarner Losh               luaX_token2str(ls, what), luaX_token2str(ls, who), where));
130*8e3e3a7aSWarner Losh     }
131*8e3e3a7aSWarner Losh   }
132*8e3e3a7aSWarner Losh }
133*8e3e3a7aSWarner Losh 
134*8e3e3a7aSWarner Losh 
135*8e3e3a7aSWarner Losh static TString *str_checkname (LexState *ls) {
136*8e3e3a7aSWarner Losh   TString *ts;
137*8e3e3a7aSWarner Losh   check(ls, TK_NAME);
138*8e3e3a7aSWarner Losh   ts = ls->t.seminfo.ts;
139*8e3e3a7aSWarner Losh   luaX_next(ls);
140*8e3e3a7aSWarner Losh   return ts;
141*8e3e3a7aSWarner Losh }
142*8e3e3a7aSWarner Losh 
143*8e3e3a7aSWarner Losh 
144*8e3e3a7aSWarner Losh static void init_exp (expdesc *e, expkind k, int i) {
145*8e3e3a7aSWarner Losh   e->f = e->t = NO_JUMP;
146*8e3e3a7aSWarner Losh   e->k = k;
147*8e3e3a7aSWarner Losh   e->u.info = i;
148*8e3e3a7aSWarner Losh }
149*8e3e3a7aSWarner Losh 
150*8e3e3a7aSWarner Losh 
151*8e3e3a7aSWarner Losh static void codestring (LexState *ls, expdesc *e, TString *s) {
152*8e3e3a7aSWarner Losh   init_exp(e, VK, luaK_stringK(ls->fs, s));
153*8e3e3a7aSWarner Losh }
154*8e3e3a7aSWarner Losh 
155*8e3e3a7aSWarner Losh 
156*8e3e3a7aSWarner Losh static void checkname (LexState *ls, expdesc *e) {
157*8e3e3a7aSWarner Losh   codestring(ls, e, str_checkname(ls));
158*8e3e3a7aSWarner Losh }
159*8e3e3a7aSWarner Losh 
160*8e3e3a7aSWarner Losh 
161*8e3e3a7aSWarner Losh static int registerlocalvar (LexState *ls, TString *varname) {
162*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
163*8e3e3a7aSWarner Losh   Proto *f = fs->f;
164*8e3e3a7aSWarner Losh   int oldsize = f->sizelocvars;
165*8e3e3a7aSWarner Losh   luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
166*8e3e3a7aSWarner Losh                   LocVar, SHRT_MAX, "local variables");
167*8e3e3a7aSWarner Losh   while (oldsize < f->sizelocvars)
168*8e3e3a7aSWarner Losh     f->locvars[oldsize++].varname = NULL;
169*8e3e3a7aSWarner Losh   f->locvars[fs->nlocvars].varname = varname;
170*8e3e3a7aSWarner Losh   luaC_objbarrier(ls->L, f, varname);
171*8e3e3a7aSWarner Losh   return fs->nlocvars++;
172*8e3e3a7aSWarner Losh }
173*8e3e3a7aSWarner Losh 
174*8e3e3a7aSWarner Losh 
175*8e3e3a7aSWarner Losh static void new_localvar (LexState *ls, TString *name) {
176*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
177*8e3e3a7aSWarner Losh   Dyndata *dyd = ls->dyd;
178*8e3e3a7aSWarner Losh   int reg = registerlocalvar(ls, name);
179*8e3e3a7aSWarner Losh   checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
180*8e3e3a7aSWarner Losh                   MAXVARS, "local variables");
181*8e3e3a7aSWarner Losh   luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1,
182*8e3e3a7aSWarner Losh                   dyd->actvar.size, Vardesc, MAX_INT, "local variables");
183*8e3e3a7aSWarner Losh   dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg);
184*8e3e3a7aSWarner Losh }
185*8e3e3a7aSWarner Losh 
186*8e3e3a7aSWarner Losh 
187*8e3e3a7aSWarner Losh static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) {
188*8e3e3a7aSWarner Losh   new_localvar(ls, luaX_newstring(ls, name, sz));
189*8e3e3a7aSWarner Losh }
190*8e3e3a7aSWarner Losh 
191*8e3e3a7aSWarner Losh #define new_localvarliteral(ls,v) \
192*8e3e3a7aSWarner Losh 	new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1)
193*8e3e3a7aSWarner Losh 
194*8e3e3a7aSWarner Losh 
195*8e3e3a7aSWarner Losh static LocVar *getlocvar (FuncState *fs, int i) {
196*8e3e3a7aSWarner Losh   int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx;
197*8e3e3a7aSWarner Losh   lua_assert(idx < fs->nlocvars);
198*8e3e3a7aSWarner Losh   return &fs->f->locvars[idx];
199*8e3e3a7aSWarner Losh }
200*8e3e3a7aSWarner Losh 
201*8e3e3a7aSWarner Losh 
202*8e3e3a7aSWarner Losh static void adjustlocalvars (LexState *ls, int nvars) {
203*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
204*8e3e3a7aSWarner Losh   fs->nactvar = cast_byte(fs->nactvar + nvars);
205*8e3e3a7aSWarner Losh   for (; nvars; nvars--) {
206*8e3e3a7aSWarner Losh     getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc;
207*8e3e3a7aSWarner Losh   }
208*8e3e3a7aSWarner Losh }
209*8e3e3a7aSWarner Losh 
210*8e3e3a7aSWarner Losh 
211*8e3e3a7aSWarner Losh static void removevars (FuncState *fs, int tolevel) {
212*8e3e3a7aSWarner Losh   fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel);
213*8e3e3a7aSWarner Losh   while (fs->nactvar > tolevel)
214*8e3e3a7aSWarner Losh     getlocvar(fs, --fs->nactvar)->endpc = fs->pc;
215*8e3e3a7aSWarner Losh }
216*8e3e3a7aSWarner Losh 
217*8e3e3a7aSWarner Losh 
218*8e3e3a7aSWarner Losh static int searchupvalue (FuncState *fs, TString *name) {
219*8e3e3a7aSWarner Losh   int i;
220*8e3e3a7aSWarner Losh   Upvaldesc *up = fs->f->upvalues;
221*8e3e3a7aSWarner Losh   for (i = 0; i < fs->nups; i++) {
222*8e3e3a7aSWarner Losh     if (eqstr(up[i].name, name)) return i;
223*8e3e3a7aSWarner Losh   }
224*8e3e3a7aSWarner Losh   return -1;  /* not found */
225*8e3e3a7aSWarner Losh }
226*8e3e3a7aSWarner Losh 
227*8e3e3a7aSWarner Losh 
228*8e3e3a7aSWarner Losh static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
229*8e3e3a7aSWarner Losh   Proto *f = fs->f;
230*8e3e3a7aSWarner Losh   int oldsize = f->sizeupvalues;
231*8e3e3a7aSWarner Losh   checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
232*8e3e3a7aSWarner Losh   luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
233*8e3e3a7aSWarner Losh                   Upvaldesc, MAXUPVAL, "upvalues");
234*8e3e3a7aSWarner Losh   while (oldsize < f->sizeupvalues)
235*8e3e3a7aSWarner Losh     f->upvalues[oldsize++].name = NULL;
236*8e3e3a7aSWarner Losh   f->upvalues[fs->nups].instack = (v->k == VLOCAL);
237*8e3e3a7aSWarner Losh   f->upvalues[fs->nups].idx = cast_byte(v->u.info);
238*8e3e3a7aSWarner Losh   f->upvalues[fs->nups].name = name;
239*8e3e3a7aSWarner Losh   luaC_objbarrier(fs->ls->L, f, name);
240*8e3e3a7aSWarner Losh   return fs->nups++;
241*8e3e3a7aSWarner Losh }
242*8e3e3a7aSWarner Losh 
243*8e3e3a7aSWarner Losh 
244*8e3e3a7aSWarner Losh static int searchvar (FuncState *fs, TString *n) {
245*8e3e3a7aSWarner Losh   int i;
246*8e3e3a7aSWarner Losh   for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
247*8e3e3a7aSWarner Losh     if (eqstr(n, getlocvar(fs, i)->varname))
248*8e3e3a7aSWarner Losh       return i;
249*8e3e3a7aSWarner Losh   }
250*8e3e3a7aSWarner Losh   return -1;  /* not found */
251*8e3e3a7aSWarner Losh }
252*8e3e3a7aSWarner Losh 
253*8e3e3a7aSWarner Losh 
254*8e3e3a7aSWarner Losh /*
255*8e3e3a7aSWarner Losh   Mark block where variable at given level was defined
256*8e3e3a7aSWarner Losh   (to emit close instructions later).
257*8e3e3a7aSWarner Losh */
258*8e3e3a7aSWarner Losh static void markupval (FuncState *fs, int level) {
259*8e3e3a7aSWarner Losh   BlockCnt *bl = fs->bl;
260*8e3e3a7aSWarner Losh   while (bl->nactvar > level)
261*8e3e3a7aSWarner Losh     bl = bl->previous;
262*8e3e3a7aSWarner Losh   bl->upval = 1;
263*8e3e3a7aSWarner Losh }
264*8e3e3a7aSWarner Losh 
265*8e3e3a7aSWarner Losh 
266*8e3e3a7aSWarner Losh /*
267*8e3e3a7aSWarner Losh   Find variable with given name 'n'. If it is an upvalue, add this
268*8e3e3a7aSWarner Losh   upvalue into all intermediate functions.
269*8e3e3a7aSWarner Losh */
270*8e3e3a7aSWarner Losh static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
271*8e3e3a7aSWarner Losh   if (fs == NULL)  /* no more levels? */
272*8e3e3a7aSWarner Losh     init_exp(var, VVOID, 0);  /* default is global */
273*8e3e3a7aSWarner Losh   else {
274*8e3e3a7aSWarner Losh     int v = searchvar(fs, n);  /* look up locals at current level */
275*8e3e3a7aSWarner Losh     if (v >= 0) {  /* found? */
276*8e3e3a7aSWarner Losh       init_exp(var, VLOCAL, v);  /* variable is local */
277*8e3e3a7aSWarner Losh       if (!base)
278*8e3e3a7aSWarner Losh         markupval(fs, v);  /* local will be used as an upval */
279*8e3e3a7aSWarner Losh     }
280*8e3e3a7aSWarner Losh     else {  /* not found as local at current level; try upvalues */
281*8e3e3a7aSWarner Losh       int idx = searchupvalue(fs, n);  /* try existing upvalues */
282*8e3e3a7aSWarner Losh       if (idx < 0) {  /* not found? */
283*8e3e3a7aSWarner Losh         singlevaraux(fs->prev, n, var, 0);  /* try upper levels */
284*8e3e3a7aSWarner Losh         if (var->k == VVOID)  /* not found? */
285*8e3e3a7aSWarner Losh           return;  /* it is a global */
286*8e3e3a7aSWarner Losh         /* else was LOCAL or UPVAL */
287*8e3e3a7aSWarner Losh         idx  = newupvalue(fs, n, var);  /* will be a new upvalue */
288*8e3e3a7aSWarner Losh       }
289*8e3e3a7aSWarner Losh       init_exp(var, VUPVAL, idx);  /* new or old upvalue */
290*8e3e3a7aSWarner Losh     }
291*8e3e3a7aSWarner Losh   }
292*8e3e3a7aSWarner Losh }
293*8e3e3a7aSWarner Losh 
294*8e3e3a7aSWarner Losh 
295*8e3e3a7aSWarner Losh static void singlevar (LexState *ls, expdesc *var) {
296*8e3e3a7aSWarner Losh   TString *varname = str_checkname(ls);
297*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
298*8e3e3a7aSWarner Losh   singlevaraux(fs, varname, var, 1);
299*8e3e3a7aSWarner Losh   if (var->k == VVOID) {  /* global name? */
300*8e3e3a7aSWarner Losh     expdesc key;
301*8e3e3a7aSWarner Losh     singlevaraux(fs, ls->envn, var, 1);  /* get environment variable */
302*8e3e3a7aSWarner Losh     lua_assert(var->k != VVOID);  /* this one must exist */
303*8e3e3a7aSWarner Losh     codestring(ls, &key, varname);  /* key is variable name */
304*8e3e3a7aSWarner Losh     luaK_indexed(fs, var, &key);  /* env[varname] */
305*8e3e3a7aSWarner Losh   }
306*8e3e3a7aSWarner Losh }
307*8e3e3a7aSWarner Losh 
308*8e3e3a7aSWarner Losh 
309*8e3e3a7aSWarner Losh static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
310*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
311*8e3e3a7aSWarner Losh   int extra = nvars - nexps;
312*8e3e3a7aSWarner Losh   if (hasmultret(e->k)) {
313*8e3e3a7aSWarner Losh     extra++;  /* includes call itself */
314*8e3e3a7aSWarner Losh     if (extra < 0) extra = 0;
315*8e3e3a7aSWarner Losh     luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */
316*8e3e3a7aSWarner Losh     if (extra > 1) luaK_reserveregs(fs, extra-1);
317*8e3e3a7aSWarner Losh   }
318*8e3e3a7aSWarner Losh   else {
319*8e3e3a7aSWarner Losh     if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */
320*8e3e3a7aSWarner Losh     if (extra > 0) {
321*8e3e3a7aSWarner Losh       int reg = fs->freereg;
322*8e3e3a7aSWarner Losh       luaK_reserveregs(fs, extra);
323*8e3e3a7aSWarner Losh       luaK_nil(fs, reg, extra);
324*8e3e3a7aSWarner Losh     }
325*8e3e3a7aSWarner Losh   }
326*8e3e3a7aSWarner Losh   if (nexps > nvars)
327*8e3e3a7aSWarner Losh     ls->fs->freereg -= nexps - nvars;  /* remove extra values */
328*8e3e3a7aSWarner Losh }
329*8e3e3a7aSWarner Losh 
330*8e3e3a7aSWarner Losh 
331*8e3e3a7aSWarner Losh static void enterlevel (LexState *ls) {
332*8e3e3a7aSWarner Losh   lua_State *L = ls->L;
333*8e3e3a7aSWarner Losh   ++L->nCcalls;
334*8e3e3a7aSWarner Losh   checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels");
335*8e3e3a7aSWarner Losh }
336*8e3e3a7aSWarner Losh 
337*8e3e3a7aSWarner Losh 
338*8e3e3a7aSWarner Losh #define leavelevel(ls)	((ls)->L->nCcalls--)
339*8e3e3a7aSWarner Losh 
340*8e3e3a7aSWarner Losh 
341*8e3e3a7aSWarner Losh static void closegoto (LexState *ls, int g, Labeldesc *label) {
342*8e3e3a7aSWarner Losh   int i;
343*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
344*8e3e3a7aSWarner Losh   Labellist *gl = &ls->dyd->gt;
345*8e3e3a7aSWarner Losh   Labeldesc *gt = &gl->arr[g];
346*8e3e3a7aSWarner Losh   lua_assert(eqstr(gt->name, label->name));
347*8e3e3a7aSWarner Losh   if (gt->nactvar < label->nactvar) {
348*8e3e3a7aSWarner Losh     TString *vname = getlocvar(fs, gt->nactvar)->varname;
349*8e3e3a7aSWarner Losh     const char *msg = luaO_pushfstring(ls->L,
350*8e3e3a7aSWarner Losh       "<goto %s> at line %d jumps into the scope of local '%s'",
351*8e3e3a7aSWarner Losh       getstr(gt->name), gt->line, getstr(vname));
352*8e3e3a7aSWarner Losh     semerror(ls, msg);
353*8e3e3a7aSWarner Losh   }
354*8e3e3a7aSWarner Losh   luaK_patchlist(fs, gt->pc, label->pc);
355*8e3e3a7aSWarner Losh   /* remove goto from pending list */
356*8e3e3a7aSWarner Losh   for (i = g; i < gl->n - 1; i++)
357*8e3e3a7aSWarner Losh     gl->arr[i] = gl->arr[i + 1];
358*8e3e3a7aSWarner Losh   gl->n--;
359*8e3e3a7aSWarner Losh }
360*8e3e3a7aSWarner Losh 
361*8e3e3a7aSWarner Losh 
362*8e3e3a7aSWarner Losh /*
363*8e3e3a7aSWarner Losh ** try to close a goto with existing labels; this solves backward jumps
364*8e3e3a7aSWarner Losh */
365*8e3e3a7aSWarner Losh static int findlabel (LexState *ls, int g) {
366*8e3e3a7aSWarner Losh   int i;
367*8e3e3a7aSWarner Losh   BlockCnt *bl = ls->fs->bl;
368*8e3e3a7aSWarner Losh   Dyndata *dyd = ls->dyd;
369*8e3e3a7aSWarner Losh   Labeldesc *gt = &dyd->gt.arr[g];
370*8e3e3a7aSWarner Losh   /* check labels in current block for a match */
371*8e3e3a7aSWarner Losh   for (i = bl->firstlabel; i < dyd->label.n; i++) {
372*8e3e3a7aSWarner Losh     Labeldesc *lb = &dyd->label.arr[i];
373*8e3e3a7aSWarner Losh     if (eqstr(lb->name, gt->name)) {  /* correct label? */
374*8e3e3a7aSWarner Losh       if (gt->nactvar > lb->nactvar &&
375*8e3e3a7aSWarner Losh           (bl->upval || dyd->label.n > bl->firstlabel))
376*8e3e3a7aSWarner Losh         luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
377*8e3e3a7aSWarner Losh       closegoto(ls, g, lb);  /* close it */
378*8e3e3a7aSWarner Losh       return 1;
379*8e3e3a7aSWarner Losh     }
380*8e3e3a7aSWarner Losh   }
381*8e3e3a7aSWarner Losh   return 0;  /* label not found; cannot close goto */
382*8e3e3a7aSWarner Losh }
383*8e3e3a7aSWarner Losh 
384*8e3e3a7aSWarner Losh 
385*8e3e3a7aSWarner Losh static int newlabelentry (LexState *ls, Labellist *l, TString *name,
386*8e3e3a7aSWarner Losh                           int line, int pc) {
387*8e3e3a7aSWarner Losh   int n = l->n;
388*8e3e3a7aSWarner Losh   luaM_growvector(ls->L, l->arr, n, l->size,
389*8e3e3a7aSWarner Losh                   Labeldesc, SHRT_MAX, "labels/gotos");
390*8e3e3a7aSWarner Losh   l->arr[n].name = name;
391*8e3e3a7aSWarner Losh   l->arr[n].line = line;
392*8e3e3a7aSWarner Losh   l->arr[n].nactvar = ls->fs->nactvar;
393*8e3e3a7aSWarner Losh   l->arr[n].pc = pc;
394*8e3e3a7aSWarner Losh   l->n = n + 1;
395*8e3e3a7aSWarner Losh   return n;
396*8e3e3a7aSWarner Losh }
397*8e3e3a7aSWarner Losh 
398*8e3e3a7aSWarner Losh 
399*8e3e3a7aSWarner Losh /*
400*8e3e3a7aSWarner Losh ** check whether new label 'lb' matches any pending gotos in current
401*8e3e3a7aSWarner Losh ** block; solves forward jumps
402*8e3e3a7aSWarner Losh */
403*8e3e3a7aSWarner Losh static void findgotos (LexState *ls, Labeldesc *lb) {
404*8e3e3a7aSWarner Losh   Labellist *gl = &ls->dyd->gt;
405*8e3e3a7aSWarner Losh   int i = ls->fs->bl->firstgoto;
406*8e3e3a7aSWarner Losh   while (i < gl->n) {
407*8e3e3a7aSWarner Losh     if (eqstr(gl->arr[i].name, lb->name))
408*8e3e3a7aSWarner Losh       closegoto(ls, i, lb);
409*8e3e3a7aSWarner Losh     else
410*8e3e3a7aSWarner Losh       i++;
411*8e3e3a7aSWarner Losh   }
412*8e3e3a7aSWarner Losh }
413*8e3e3a7aSWarner Losh 
414*8e3e3a7aSWarner Losh 
415*8e3e3a7aSWarner Losh /*
416*8e3e3a7aSWarner Losh ** export pending gotos to outer level, to check them against
417*8e3e3a7aSWarner Losh ** outer labels; if the block being exited has upvalues, and
418*8e3e3a7aSWarner Losh ** the goto exits the scope of any variable (which can be the
419*8e3e3a7aSWarner Losh ** upvalue), close those variables being exited.
420*8e3e3a7aSWarner Losh */
421*8e3e3a7aSWarner Losh static void movegotosout (FuncState *fs, BlockCnt *bl) {
422*8e3e3a7aSWarner Losh   int i = bl->firstgoto;
423*8e3e3a7aSWarner Losh   Labellist *gl = &fs->ls->dyd->gt;
424*8e3e3a7aSWarner Losh   /* correct pending gotos to current block and try to close it
425*8e3e3a7aSWarner Losh      with visible labels */
426*8e3e3a7aSWarner Losh   while (i < gl->n) {
427*8e3e3a7aSWarner Losh     Labeldesc *gt = &gl->arr[i];
428*8e3e3a7aSWarner Losh     if (gt->nactvar > bl->nactvar) {
429*8e3e3a7aSWarner Losh       if (bl->upval)
430*8e3e3a7aSWarner Losh         luaK_patchclose(fs, gt->pc, bl->nactvar);
431*8e3e3a7aSWarner Losh       gt->nactvar = bl->nactvar;
432*8e3e3a7aSWarner Losh     }
433*8e3e3a7aSWarner Losh     if (!findlabel(fs->ls, i))
434*8e3e3a7aSWarner Losh       i++;  /* move to next one */
435*8e3e3a7aSWarner Losh   }
436*8e3e3a7aSWarner Losh }
437*8e3e3a7aSWarner Losh 
438*8e3e3a7aSWarner Losh 
439*8e3e3a7aSWarner Losh static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
440*8e3e3a7aSWarner Losh   bl->isloop = isloop;
441*8e3e3a7aSWarner Losh   bl->nactvar = fs->nactvar;
442*8e3e3a7aSWarner Losh   bl->firstlabel = fs->ls->dyd->label.n;
443*8e3e3a7aSWarner Losh   bl->firstgoto = fs->ls->dyd->gt.n;
444*8e3e3a7aSWarner Losh   bl->upval = 0;
445*8e3e3a7aSWarner Losh   bl->previous = fs->bl;
446*8e3e3a7aSWarner Losh   fs->bl = bl;
447*8e3e3a7aSWarner Losh   lua_assert(fs->freereg == fs->nactvar);
448*8e3e3a7aSWarner Losh }
449*8e3e3a7aSWarner Losh 
450*8e3e3a7aSWarner Losh 
451*8e3e3a7aSWarner Losh /*
452*8e3e3a7aSWarner Losh ** create a label named 'break' to resolve break statements
453*8e3e3a7aSWarner Losh */
454*8e3e3a7aSWarner Losh static void breaklabel (LexState *ls) {
455*8e3e3a7aSWarner Losh   TString *n = luaS_new(ls->L, "break");
456*8e3e3a7aSWarner Losh   int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc);
457*8e3e3a7aSWarner Losh   findgotos(ls, &ls->dyd->label.arr[l]);
458*8e3e3a7aSWarner Losh }
459*8e3e3a7aSWarner Losh 
460*8e3e3a7aSWarner Losh /*
461*8e3e3a7aSWarner Losh ** generates an error for an undefined 'goto'; choose appropriate
462*8e3e3a7aSWarner Losh ** message when label name is a reserved word (which can only be 'break')
463*8e3e3a7aSWarner Losh */
464*8e3e3a7aSWarner Losh static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
465*8e3e3a7aSWarner Losh   const char *msg = isreserved(gt->name)
466*8e3e3a7aSWarner Losh                     ? "<%s> at line %d not inside a loop"
467*8e3e3a7aSWarner Losh                     : "no visible label '%s' for <goto> at line %d";
468*8e3e3a7aSWarner Losh   msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
469*8e3e3a7aSWarner Losh   semerror(ls, msg);
470*8e3e3a7aSWarner Losh }
471*8e3e3a7aSWarner Losh 
472*8e3e3a7aSWarner Losh 
473*8e3e3a7aSWarner Losh static void leaveblock (FuncState *fs) {
474*8e3e3a7aSWarner Losh   BlockCnt *bl = fs->bl;
475*8e3e3a7aSWarner Losh   LexState *ls = fs->ls;
476*8e3e3a7aSWarner Losh   if (bl->previous && bl->upval) {
477*8e3e3a7aSWarner Losh     /* create a 'jump to here' to close upvalues */
478*8e3e3a7aSWarner Losh     int j = luaK_jump(fs);
479*8e3e3a7aSWarner Losh     luaK_patchclose(fs, j, bl->nactvar);
480*8e3e3a7aSWarner Losh     luaK_patchtohere(fs, j);
481*8e3e3a7aSWarner Losh   }
482*8e3e3a7aSWarner Losh   if (bl->isloop)
483*8e3e3a7aSWarner Losh     breaklabel(ls);  /* close pending breaks */
484*8e3e3a7aSWarner Losh   fs->bl = bl->previous;
485*8e3e3a7aSWarner Losh   removevars(fs, bl->nactvar);
486*8e3e3a7aSWarner Losh   lua_assert(bl->nactvar == fs->nactvar);
487*8e3e3a7aSWarner Losh   fs->freereg = fs->nactvar;  /* free registers */
488*8e3e3a7aSWarner Losh   ls->dyd->label.n = bl->firstlabel;  /* remove local labels */
489*8e3e3a7aSWarner Losh   if (bl->previous)  /* inner block? */
490*8e3e3a7aSWarner Losh     movegotosout(fs, bl);  /* update pending gotos to outer block */
491*8e3e3a7aSWarner Losh   else if (bl->firstgoto < ls->dyd->gt.n)  /* pending gotos in outer block? */
492*8e3e3a7aSWarner Losh     undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]);  /* error */
493*8e3e3a7aSWarner Losh }
494*8e3e3a7aSWarner Losh 
495*8e3e3a7aSWarner Losh 
496*8e3e3a7aSWarner Losh /*
497*8e3e3a7aSWarner Losh ** adds a new prototype into list of prototypes
498*8e3e3a7aSWarner Losh */
499*8e3e3a7aSWarner Losh static Proto *addprototype (LexState *ls) {
500*8e3e3a7aSWarner Losh   Proto *clp;
501*8e3e3a7aSWarner Losh   lua_State *L = ls->L;
502*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
503*8e3e3a7aSWarner Losh   Proto *f = fs->f;  /* prototype of current function */
504*8e3e3a7aSWarner Losh   if (fs->np >= f->sizep) {
505*8e3e3a7aSWarner Losh     int oldsize = f->sizep;
506*8e3e3a7aSWarner Losh     luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
507*8e3e3a7aSWarner Losh     while (oldsize < f->sizep)
508*8e3e3a7aSWarner Losh       f->p[oldsize++] = NULL;
509*8e3e3a7aSWarner Losh   }
510*8e3e3a7aSWarner Losh   f->p[fs->np++] = clp = luaF_newproto(L);
511*8e3e3a7aSWarner Losh   luaC_objbarrier(L, f, clp);
512*8e3e3a7aSWarner Losh   return clp;
513*8e3e3a7aSWarner Losh }
514*8e3e3a7aSWarner Losh 
515*8e3e3a7aSWarner Losh 
516*8e3e3a7aSWarner Losh /*
517*8e3e3a7aSWarner Losh ** codes instruction to create new closure in parent function.
518*8e3e3a7aSWarner Losh ** The OP_CLOSURE instruction must use the last available register,
519*8e3e3a7aSWarner Losh ** so that, if it invokes the GC, the GC knows which registers
520*8e3e3a7aSWarner Losh ** are in use at that time.
521*8e3e3a7aSWarner Losh */
522*8e3e3a7aSWarner Losh static void codeclosure (LexState *ls, expdesc *v) {
523*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs->prev;
524*8e3e3a7aSWarner Losh   init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
525*8e3e3a7aSWarner Losh   luaK_exp2nextreg(fs, v);  /* fix it at the last register */
526*8e3e3a7aSWarner Losh }
527*8e3e3a7aSWarner Losh 
528*8e3e3a7aSWarner Losh 
529*8e3e3a7aSWarner Losh static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
530*8e3e3a7aSWarner Losh   Proto *f;
531*8e3e3a7aSWarner Losh   fs->prev = ls->fs;  /* linked list of funcstates */
532*8e3e3a7aSWarner Losh   fs->ls = ls;
533*8e3e3a7aSWarner Losh   ls->fs = fs;
534*8e3e3a7aSWarner Losh   fs->pc = 0;
535*8e3e3a7aSWarner Losh   fs->lasttarget = 0;
536*8e3e3a7aSWarner Losh   fs->jpc = NO_JUMP;
537*8e3e3a7aSWarner Losh   fs->freereg = 0;
538*8e3e3a7aSWarner Losh   fs->nk = 0;
539*8e3e3a7aSWarner Losh   fs->np = 0;
540*8e3e3a7aSWarner Losh   fs->nups = 0;
541*8e3e3a7aSWarner Losh   fs->nlocvars = 0;
542*8e3e3a7aSWarner Losh   fs->nactvar = 0;
543*8e3e3a7aSWarner Losh   fs->firstlocal = ls->dyd->actvar.n;
544*8e3e3a7aSWarner Losh   fs->bl = NULL;
545*8e3e3a7aSWarner Losh   f = fs->f;
546*8e3e3a7aSWarner Losh   f->source = ls->source;
547*8e3e3a7aSWarner Losh   f->maxstacksize = 2;  /* registers 0/1 are always valid */
548*8e3e3a7aSWarner Losh   enterblock(fs, bl, 0);
549*8e3e3a7aSWarner Losh }
550*8e3e3a7aSWarner Losh 
551*8e3e3a7aSWarner Losh 
552*8e3e3a7aSWarner Losh static void close_func (LexState *ls) {
553*8e3e3a7aSWarner Losh   lua_State *L = ls->L;
554*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
555*8e3e3a7aSWarner Losh   Proto *f = fs->f;
556*8e3e3a7aSWarner Losh   luaK_ret(fs, 0, 0);  /* final return */
557*8e3e3a7aSWarner Losh   leaveblock(fs);
558*8e3e3a7aSWarner Losh   luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
559*8e3e3a7aSWarner Losh   f->sizecode = fs->pc;
560*8e3e3a7aSWarner Losh   luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
561*8e3e3a7aSWarner Losh   f->sizelineinfo = fs->pc;
562*8e3e3a7aSWarner Losh   luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
563*8e3e3a7aSWarner Losh   f->sizek = fs->nk;
564*8e3e3a7aSWarner Losh   luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
565*8e3e3a7aSWarner Losh   f->sizep = fs->np;
566*8e3e3a7aSWarner Losh   luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
567*8e3e3a7aSWarner Losh   f->sizelocvars = fs->nlocvars;
568*8e3e3a7aSWarner Losh   luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
569*8e3e3a7aSWarner Losh   f->sizeupvalues = fs->nups;
570*8e3e3a7aSWarner Losh   lua_assert(fs->bl == NULL);
571*8e3e3a7aSWarner Losh   ls->fs = fs->prev;
572*8e3e3a7aSWarner Losh   luaC_checkGC(L);
573*8e3e3a7aSWarner Losh }
574*8e3e3a7aSWarner Losh 
575*8e3e3a7aSWarner Losh 
576*8e3e3a7aSWarner Losh 
577*8e3e3a7aSWarner Losh /*============================================================*/
578*8e3e3a7aSWarner Losh /* GRAMMAR RULES */
579*8e3e3a7aSWarner Losh /*============================================================*/
580*8e3e3a7aSWarner Losh 
581*8e3e3a7aSWarner Losh 
582*8e3e3a7aSWarner Losh /*
583*8e3e3a7aSWarner Losh ** check whether current token is in the follow set of a block.
584*8e3e3a7aSWarner Losh ** 'until' closes syntactical blocks, but do not close scope,
585*8e3e3a7aSWarner Losh ** so it is handled in separate.
586*8e3e3a7aSWarner Losh */
587*8e3e3a7aSWarner Losh static int block_follow (LexState *ls, int withuntil) {
588*8e3e3a7aSWarner Losh   switch (ls->t.token) {
589*8e3e3a7aSWarner Losh     case TK_ELSE: case TK_ELSEIF:
590*8e3e3a7aSWarner Losh     case TK_END: case TK_EOS:
591*8e3e3a7aSWarner Losh       return 1;
592*8e3e3a7aSWarner Losh     case TK_UNTIL: return withuntil;
593*8e3e3a7aSWarner Losh     default: return 0;
594*8e3e3a7aSWarner Losh   }
595*8e3e3a7aSWarner Losh }
596*8e3e3a7aSWarner Losh 
597*8e3e3a7aSWarner Losh 
598*8e3e3a7aSWarner Losh static void statlist (LexState *ls) {
599*8e3e3a7aSWarner Losh   /* statlist -> { stat [';'] } */
600*8e3e3a7aSWarner Losh   while (!block_follow(ls, 1)) {
601*8e3e3a7aSWarner Losh     if (ls->t.token == TK_RETURN) {
602*8e3e3a7aSWarner Losh       statement(ls);
603*8e3e3a7aSWarner Losh       return;  /* 'return' must be last statement */
604*8e3e3a7aSWarner Losh     }
605*8e3e3a7aSWarner Losh     statement(ls);
606*8e3e3a7aSWarner Losh   }
607*8e3e3a7aSWarner Losh }
608*8e3e3a7aSWarner Losh 
609*8e3e3a7aSWarner Losh 
610*8e3e3a7aSWarner Losh static void fieldsel (LexState *ls, expdesc *v) {
611*8e3e3a7aSWarner Losh   /* fieldsel -> ['.' | ':'] NAME */
612*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
613*8e3e3a7aSWarner Losh   expdesc key;
614*8e3e3a7aSWarner Losh   luaK_exp2anyregup(fs, v);
615*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip the dot or colon */
616*8e3e3a7aSWarner Losh   checkname(ls, &key);
617*8e3e3a7aSWarner Losh   luaK_indexed(fs, v, &key);
618*8e3e3a7aSWarner Losh }
619*8e3e3a7aSWarner Losh 
620*8e3e3a7aSWarner Losh 
621*8e3e3a7aSWarner Losh static void yindex (LexState *ls, expdesc *v) {
622*8e3e3a7aSWarner Losh   /* index -> '[' expr ']' */
623*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip the '[' */
624*8e3e3a7aSWarner Losh   expr(ls, v);
625*8e3e3a7aSWarner Losh   luaK_exp2val(ls->fs, v);
626*8e3e3a7aSWarner Losh   checknext(ls, ']');
627*8e3e3a7aSWarner Losh }
628*8e3e3a7aSWarner Losh 
629*8e3e3a7aSWarner Losh 
630*8e3e3a7aSWarner Losh /*
631*8e3e3a7aSWarner Losh ** {======================================================================
632*8e3e3a7aSWarner Losh ** Rules for Constructors
633*8e3e3a7aSWarner Losh ** =======================================================================
634*8e3e3a7aSWarner Losh */
635*8e3e3a7aSWarner Losh 
636*8e3e3a7aSWarner Losh 
637*8e3e3a7aSWarner Losh struct ConsControl {
638*8e3e3a7aSWarner Losh   expdesc v;  /* last list item read */
639*8e3e3a7aSWarner Losh   expdesc *t;  /* table descriptor */
640*8e3e3a7aSWarner Losh   int nh;  /* total number of 'record' elements */
641*8e3e3a7aSWarner Losh   int na;  /* total number of array elements */
642*8e3e3a7aSWarner Losh   int tostore;  /* number of array elements pending to be stored */
643*8e3e3a7aSWarner Losh };
644*8e3e3a7aSWarner Losh 
645*8e3e3a7aSWarner Losh 
646*8e3e3a7aSWarner Losh static void recfield (LexState *ls, struct ConsControl *cc) {
647*8e3e3a7aSWarner Losh   /* recfield -> (NAME | '['exp1']') = exp1 */
648*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
649*8e3e3a7aSWarner Losh   int reg = ls->fs->freereg;
650*8e3e3a7aSWarner Losh   expdesc key, val;
651*8e3e3a7aSWarner Losh   int rkkey;
652*8e3e3a7aSWarner Losh   if (ls->t.token == TK_NAME) {
653*8e3e3a7aSWarner Losh     checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
654*8e3e3a7aSWarner Losh     checkname(ls, &key);
655*8e3e3a7aSWarner Losh   }
656*8e3e3a7aSWarner Losh   else  /* ls->t.token == '[' */
657*8e3e3a7aSWarner Losh     yindex(ls, &key);
658*8e3e3a7aSWarner Losh   cc->nh++;
659*8e3e3a7aSWarner Losh   checknext(ls, '=');
660*8e3e3a7aSWarner Losh   rkkey = luaK_exp2RK(fs, &key);
661*8e3e3a7aSWarner Losh   expr(ls, &val);
662*8e3e3a7aSWarner Losh   luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val));
663*8e3e3a7aSWarner Losh   fs->freereg = reg;  /* free registers */
664*8e3e3a7aSWarner Losh }
665*8e3e3a7aSWarner Losh 
666*8e3e3a7aSWarner Losh 
667*8e3e3a7aSWarner Losh static void closelistfield (FuncState *fs, struct ConsControl *cc) {
668*8e3e3a7aSWarner Losh   if (cc->v.k == VVOID) return;  /* there is no list item */
669*8e3e3a7aSWarner Losh   luaK_exp2nextreg(fs, &cc->v);
670*8e3e3a7aSWarner Losh   cc->v.k = VVOID;
671*8e3e3a7aSWarner Losh   if (cc->tostore == LFIELDS_PER_FLUSH) {
672*8e3e3a7aSWarner Losh     luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore);  /* flush */
673*8e3e3a7aSWarner Losh     cc->tostore = 0;  /* no more items pending */
674*8e3e3a7aSWarner Losh   }
675*8e3e3a7aSWarner Losh }
676*8e3e3a7aSWarner Losh 
677*8e3e3a7aSWarner Losh 
678*8e3e3a7aSWarner Losh static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
679*8e3e3a7aSWarner Losh   if (cc->tostore == 0) return;
680*8e3e3a7aSWarner Losh   if (hasmultret(cc->v.k)) {
681*8e3e3a7aSWarner Losh     luaK_setmultret(fs, &cc->v);
682*8e3e3a7aSWarner Losh     luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET);
683*8e3e3a7aSWarner Losh     cc->na--;  /* do not count last expression (unknown number of elements) */
684*8e3e3a7aSWarner Losh   }
685*8e3e3a7aSWarner Losh   else {
686*8e3e3a7aSWarner Losh     if (cc->v.k != VVOID)
687*8e3e3a7aSWarner Losh       luaK_exp2nextreg(fs, &cc->v);
688*8e3e3a7aSWarner Losh     luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore);
689*8e3e3a7aSWarner Losh   }
690*8e3e3a7aSWarner Losh }
691*8e3e3a7aSWarner Losh 
692*8e3e3a7aSWarner Losh 
693*8e3e3a7aSWarner Losh static void listfield (LexState *ls, struct ConsControl *cc) {
694*8e3e3a7aSWarner Losh   /* listfield -> exp */
695*8e3e3a7aSWarner Losh   expr(ls, &cc->v);
696*8e3e3a7aSWarner Losh   checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
697*8e3e3a7aSWarner Losh   cc->na++;
698*8e3e3a7aSWarner Losh   cc->tostore++;
699*8e3e3a7aSWarner Losh }
700*8e3e3a7aSWarner Losh 
701*8e3e3a7aSWarner Losh 
702*8e3e3a7aSWarner Losh static void field (LexState *ls, struct ConsControl *cc) {
703*8e3e3a7aSWarner Losh   /* field -> listfield | recfield */
704*8e3e3a7aSWarner Losh   switch(ls->t.token) {
705*8e3e3a7aSWarner Losh     case TK_NAME: {  /* may be 'listfield' or 'recfield' */
706*8e3e3a7aSWarner Losh       if (luaX_lookahead(ls) != '=')  /* expression? */
707*8e3e3a7aSWarner Losh         listfield(ls, cc);
708*8e3e3a7aSWarner Losh       else
709*8e3e3a7aSWarner Losh         recfield(ls, cc);
710*8e3e3a7aSWarner Losh       break;
711*8e3e3a7aSWarner Losh     }
712*8e3e3a7aSWarner Losh     case '[': {
713*8e3e3a7aSWarner Losh       recfield(ls, cc);
714*8e3e3a7aSWarner Losh       break;
715*8e3e3a7aSWarner Losh     }
716*8e3e3a7aSWarner Losh     default: {
717*8e3e3a7aSWarner Losh       listfield(ls, cc);
718*8e3e3a7aSWarner Losh       break;
719*8e3e3a7aSWarner Losh     }
720*8e3e3a7aSWarner Losh   }
721*8e3e3a7aSWarner Losh }
722*8e3e3a7aSWarner Losh 
723*8e3e3a7aSWarner Losh 
724*8e3e3a7aSWarner Losh static void constructor (LexState *ls, expdesc *t) {
725*8e3e3a7aSWarner Losh   /* constructor -> '{' [ field { sep field } [sep] ] '}'
726*8e3e3a7aSWarner Losh      sep -> ',' | ';' */
727*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
728*8e3e3a7aSWarner Losh   int line = ls->linenumber;
729*8e3e3a7aSWarner Losh   int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
730*8e3e3a7aSWarner Losh   struct ConsControl cc;
731*8e3e3a7aSWarner Losh   cc.na = cc.nh = cc.tostore = 0;
732*8e3e3a7aSWarner Losh   cc.t = t;
733*8e3e3a7aSWarner Losh   init_exp(t, VRELOCABLE, pc);
734*8e3e3a7aSWarner Losh   init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
735*8e3e3a7aSWarner Losh   luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top */
736*8e3e3a7aSWarner Losh   checknext(ls, '{');
737*8e3e3a7aSWarner Losh   do {
738*8e3e3a7aSWarner Losh     lua_assert(cc.v.k == VVOID || cc.tostore > 0);
739*8e3e3a7aSWarner Losh     if (ls->t.token == '}') break;
740*8e3e3a7aSWarner Losh     closelistfield(fs, &cc);
741*8e3e3a7aSWarner Losh     field(ls, &cc);
742*8e3e3a7aSWarner Losh   } while (testnext(ls, ',') || testnext(ls, ';'));
743*8e3e3a7aSWarner Losh   check_match(ls, '}', '{', line);
744*8e3e3a7aSWarner Losh   lastlistfield(fs, &cc);
745*8e3e3a7aSWarner Losh   SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
746*8e3e3a7aSWarner Losh   SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */
747*8e3e3a7aSWarner Losh }
748*8e3e3a7aSWarner Losh 
749*8e3e3a7aSWarner Losh /* }====================================================================== */
750*8e3e3a7aSWarner Losh 
751*8e3e3a7aSWarner Losh 
752*8e3e3a7aSWarner Losh 
753*8e3e3a7aSWarner Losh static void parlist (LexState *ls) {
754*8e3e3a7aSWarner Losh   /* parlist -> [ param { ',' param } ] */
755*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
756*8e3e3a7aSWarner Losh   Proto *f = fs->f;
757*8e3e3a7aSWarner Losh   int nparams = 0;
758*8e3e3a7aSWarner Losh   f->is_vararg = 0;
759*8e3e3a7aSWarner Losh   if (ls->t.token != ')') {  /* is 'parlist' not empty? */
760*8e3e3a7aSWarner Losh     do {
761*8e3e3a7aSWarner Losh       switch (ls->t.token) {
762*8e3e3a7aSWarner Losh         case TK_NAME: {  /* param -> NAME */
763*8e3e3a7aSWarner Losh           new_localvar(ls, str_checkname(ls));
764*8e3e3a7aSWarner Losh           nparams++;
765*8e3e3a7aSWarner Losh           break;
766*8e3e3a7aSWarner Losh         }
767*8e3e3a7aSWarner Losh         case TK_DOTS: {  /* param -> '...' */
768*8e3e3a7aSWarner Losh           luaX_next(ls);
769*8e3e3a7aSWarner Losh           f->is_vararg = 1;  /* declared vararg */
770*8e3e3a7aSWarner Losh           break;
771*8e3e3a7aSWarner Losh         }
772*8e3e3a7aSWarner Losh         default: luaX_syntaxerror(ls, "<name> or '...' expected");
773*8e3e3a7aSWarner Losh       }
774*8e3e3a7aSWarner Losh     } while (!f->is_vararg && testnext(ls, ','));
775*8e3e3a7aSWarner Losh   }
776*8e3e3a7aSWarner Losh   adjustlocalvars(ls, nparams);
777*8e3e3a7aSWarner Losh   f->numparams = cast_byte(fs->nactvar);
778*8e3e3a7aSWarner Losh   luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */
779*8e3e3a7aSWarner Losh }
780*8e3e3a7aSWarner Losh 
781*8e3e3a7aSWarner Losh 
782*8e3e3a7aSWarner Losh static void body (LexState *ls, expdesc *e, int ismethod, int line) {
783*8e3e3a7aSWarner Losh   /* body ->  '(' parlist ')' block END */
784*8e3e3a7aSWarner Losh   FuncState new_fs;
785*8e3e3a7aSWarner Losh   BlockCnt bl;
786*8e3e3a7aSWarner Losh   new_fs.f = addprototype(ls);
787*8e3e3a7aSWarner Losh   new_fs.f->linedefined = line;
788*8e3e3a7aSWarner Losh   open_func(ls, &new_fs, &bl);
789*8e3e3a7aSWarner Losh   checknext(ls, '(');
790*8e3e3a7aSWarner Losh   if (ismethod) {
791*8e3e3a7aSWarner Losh     new_localvarliteral(ls, "self");  /* create 'self' parameter */
792*8e3e3a7aSWarner Losh     adjustlocalvars(ls, 1);
793*8e3e3a7aSWarner Losh   }
794*8e3e3a7aSWarner Losh   parlist(ls);
795*8e3e3a7aSWarner Losh   checknext(ls, ')');
796*8e3e3a7aSWarner Losh   statlist(ls);
797*8e3e3a7aSWarner Losh   new_fs.f->lastlinedefined = ls->linenumber;
798*8e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_FUNCTION, line);
799*8e3e3a7aSWarner Losh   codeclosure(ls, e);
800*8e3e3a7aSWarner Losh   close_func(ls);
801*8e3e3a7aSWarner Losh }
802*8e3e3a7aSWarner Losh 
803*8e3e3a7aSWarner Losh 
804*8e3e3a7aSWarner Losh static int explist (LexState *ls, expdesc *v) {
805*8e3e3a7aSWarner Losh   /* explist -> expr { ',' expr } */
806*8e3e3a7aSWarner Losh   int n = 1;  /* at least one expression */
807*8e3e3a7aSWarner Losh   expr(ls, v);
808*8e3e3a7aSWarner Losh   while (testnext(ls, ',')) {
809*8e3e3a7aSWarner Losh     luaK_exp2nextreg(ls->fs, v);
810*8e3e3a7aSWarner Losh     expr(ls, v);
811*8e3e3a7aSWarner Losh     n++;
812*8e3e3a7aSWarner Losh   }
813*8e3e3a7aSWarner Losh   return n;
814*8e3e3a7aSWarner Losh }
815*8e3e3a7aSWarner Losh 
816*8e3e3a7aSWarner Losh 
817*8e3e3a7aSWarner Losh static void funcargs (LexState *ls, expdesc *f, int line) {
818*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
819*8e3e3a7aSWarner Losh   expdesc args;
820*8e3e3a7aSWarner Losh   int base, nparams;
821*8e3e3a7aSWarner Losh   switch (ls->t.token) {
822*8e3e3a7aSWarner Losh     case '(': {  /* funcargs -> '(' [ explist ] ')' */
823*8e3e3a7aSWarner Losh       luaX_next(ls);
824*8e3e3a7aSWarner Losh       if (ls->t.token == ')')  /* arg list is empty? */
825*8e3e3a7aSWarner Losh         args.k = VVOID;
826*8e3e3a7aSWarner Losh       else {
827*8e3e3a7aSWarner Losh         explist(ls, &args);
828*8e3e3a7aSWarner Losh         luaK_setmultret(fs, &args);
829*8e3e3a7aSWarner Losh       }
830*8e3e3a7aSWarner Losh       check_match(ls, ')', '(', line);
831*8e3e3a7aSWarner Losh       break;
832*8e3e3a7aSWarner Losh     }
833*8e3e3a7aSWarner Losh     case '{': {  /* funcargs -> constructor */
834*8e3e3a7aSWarner Losh       constructor(ls, &args);
835*8e3e3a7aSWarner Losh       break;
836*8e3e3a7aSWarner Losh     }
837*8e3e3a7aSWarner Losh     case TK_STRING: {  /* funcargs -> STRING */
838*8e3e3a7aSWarner Losh       codestring(ls, &args, ls->t.seminfo.ts);
839*8e3e3a7aSWarner Losh       luaX_next(ls);  /* must use 'seminfo' before 'next' */
840*8e3e3a7aSWarner Losh       break;
841*8e3e3a7aSWarner Losh     }
842*8e3e3a7aSWarner Losh     default: {
843*8e3e3a7aSWarner Losh       luaX_syntaxerror(ls, "function arguments expected");
844*8e3e3a7aSWarner Losh     }
845*8e3e3a7aSWarner Losh   }
846*8e3e3a7aSWarner Losh   lua_assert(f->k == VNONRELOC);
847*8e3e3a7aSWarner Losh   base = f->u.info;  /* base register for call */
848*8e3e3a7aSWarner Losh   if (hasmultret(args.k))
849*8e3e3a7aSWarner Losh     nparams = LUA_MULTRET;  /* open call */
850*8e3e3a7aSWarner Losh   else {
851*8e3e3a7aSWarner Losh     if (args.k != VVOID)
852*8e3e3a7aSWarner Losh       luaK_exp2nextreg(fs, &args);  /* close last argument */
853*8e3e3a7aSWarner Losh     nparams = fs->freereg - (base+1);
854*8e3e3a7aSWarner Losh   }
855*8e3e3a7aSWarner Losh   init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
856*8e3e3a7aSWarner Losh   luaK_fixline(fs, line);
857*8e3e3a7aSWarner Losh   fs->freereg = base+1;  /* call remove function and arguments and leaves
858*8e3e3a7aSWarner Losh                             (unless changed) one result */
859*8e3e3a7aSWarner Losh }
860*8e3e3a7aSWarner Losh 
861*8e3e3a7aSWarner Losh 
862*8e3e3a7aSWarner Losh 
863*8e3e3a7aSWarner Losh 
864*8e3e3a7aSWarner Losh /*
865*8e3e3a7aSWarner Losh ** {======================================================================
866*8e3e3a7aSWarner Losh ** Expression parsing
867*8e3e3a7aSWarner Losh ** =======================================================================
868*8e3e3a7aSWarner Losh */
869*8e3e3a7aSWarner Losh 
870*8e3e3a7aSWarner Losh 
871*8e3e3a7aSWarner Losh static void primaryexp (LexState *ls, expdesc *v) {
872*8e3e3a7aSWarner Losh   /* primaryexp -> NAME | '(' expr ')' */
873*8e3e3a7aSWarner Losh   switch (ls->t.token) {
874*8e3e3a7aSWarner Losh     case '(': {
875*8e3e3a7aSWarner Losh       int line = ls->linenumber;
876*8e3e3a7aSWarner Losh       luaX_next(ls);
877*8e3e3a7aSWarner Losh       expr(ls, v);
878*8e3e3a7aSWarner Losh       check_match(ls, ')', '(', line);
879*8e3e3a7aSWarner Losh       luaK_dischargevars(ls->fs, v);
880*8e3e3a7aSWarner Losh       return;
881*8e3e3a7aSWarner Losh     }
882*8e3e3a7aSWarner Losh     case TK_NAME: {
883*8e3e3a7aSWarner Losh       singlevar(ls, v);
884*8e3e3a7aSWarner Losh       return;
885*8e3e3a7aSWarner Losh     }
886*8e3e3a7aSWarner Losh     default: {
887*8e3e3a7aSWarner Losh       luaX_syntaxerror(ls, "unexpected symbol");
888*8e3e3a7aSWarner Losh     }
889*8e3e3a7aSWarner Losh   }
890*8e3e3a7aSWarner Losh }
891*8e3e3a7aSWarner Losh 
892*8e3e3a7aSWarner Losh 
893*8e3e3a7aSWarner Losh static void suffixedexp (LexState *ls, expdesc *v) {
894*8e3e3a7aSWarner Losh   /* suffixedexp ->
895*8e3e3a7aSWarner Losh        primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
896*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
897*8e3e3a7aSWarner Losh   int line = ls->linenumber;
898*8e3e3a7aSWarner Losh   primaryexp(ls, v);
899*8e3e3a7aSWarner Losh   for (;;) {
900*8e3e3a7aSWarner Losh     switch (ls->t.token) {
901*8e3e3a7aSWarner Losh       case '.': {  /* fieldsel */
902*8e3e3a7aSWarner Losh         fieldsel(ls, v);
903*8e3e3a7aSWarner Losh         break;
904*8e3e3a7aSWarner Losh       }
905*8e3e3a7aSWarner Losh       case '[': {  /* '[' exp1 ']' */
906*8e3e3a7aSWarner Losh         expdesc key;
907*8e3e3a7aSWarner Losh         luaK_exp2anyregup(fs, v);
908*8e3e3a7aSWarner Losh         yindex(ls, &key);
909*8e3e3a7aSWarner Losh         luaK_indexed(fs, v, &key);
910*8e3e3a7aSWarner Losh         break;
911*8e3e3a7aSWarner Losh       }
912*8e3e3a7aSWarner Losh       case ':': {  /* ':' NAME funcargs */
913*8e3e3a7aSWarner Losh         expdesc key;
914*8e3e3a7aSWarner Losh         luaX_next(ls);
915*8e3e3a7aSWarner Losh         checkname(ls, &key);
916*8e3e3a7aSWarner Losh         luaK_self(fs, v, &key);
917*8e3e3a7aSWarner Losh         funcargs(ls, v, line);
918*8e3e3a7aSWarner Losh         break;
919*8e3e3a7aSWarner Losh       }
920*8e3e3a7aSWarner Losh       case '(': case TK_STRING: case '{': {  /* funcargs */
921*8e3e3a7aSWarner Losh         luaK_exp2nextreg(fs, v);
922*8e3e3a7aSWarner Losh         funcargs(ls, v, line);
923*8e3e3a7aSWarner Losh         break;
924*8e3e3a7aSWarner Losh       }
925*8e3e3a7aSWarner Losh       default: return;
926*8e3e3a7aSWarner Losh     }
927*8e3e3a7aSWarner Losh   }
928*8e3e3a7aSWarner Losh }
929*8e3e3a7aSWarner Losh 
930*8e3e3a7aSWarner Losh 
931*8e3e3a7aSWarner Losh static void simpleexp (LexState *ls, expdesc *v) {
932*8e3e3a7aSWarner Losh   /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... |
933*8e3e3a7aSWarner Losh                   constructor | FUNCTION body | suffixedexp */
934*8e3e3a7aSWarner Losh   switch (ls->t.token) {
935*8e3e3a7aSWarner Losh     case TK_FLT: {
936*8e3e3a7aSWarner Losh       init_exp(v, VKFLT, 0);
937*8e3e3a7aSWarner Losh       v->u.nval = ls->t.seminfo.r;
938*8e3e3a7aSWarner Losh       break;
939*8e3e3a7aSWarner Losh     }
940*8e3e3a7aSWarner Losh     case TK_INT: {
941*8e3e3a7aSWarner Losh       init_exp(v, VKINT, 0);
942*8e3e3a7aSWarner Losh       v->u.ival = ls->t.seminfo.i;
943*8e3e3a7aSWarner Losh       break;
944*8e3e3a7aSWarner Losh     }
945*8e3e3a7aSWarner Losh     case TK_STRING: {
946*8e3e3a7aSWarner Losh       codestring(ls, v, ls->t.seminfo.ts);
947*8e3e3a7aSWarner Losh       break;
948*8e3e3a7aSWarner Losh     }
949*8e3e3a7aSWarner Losh     case TK_NIL: {
950*8e3e3a7aSWarner Losh       init_exp(v, VNIL, 0);
951*8e3e3a7aSWarner Losh       break;
952*8e3e3a7aSWarner Losh     }
953*8e3e3a7aSWarner Losh     case TK_TRUE: {
954*8e3e3a7aSWarner Losh       init_exp(v, VTRUE, 0);
955*8e3e3a7aSWarner Losh       break;
956*8e3e3a7aSWarner Losh     }
957*8e3e3a7aSWarner Losh     case TK_FALSE: {
958*8e3e3a7aSWarner Losh       init_exp(v, VFALSE, 0);
959*8e3e3a7aSWarner Losh       break;
960*8e3e3a7aSWarner Losh     }
961*8e3e3a7aSWarner Losh     case TK_DOTS: {  /* vararg */
962*8e3e3a7aSWarner Losh       FuncState *fs = ls->fs;
963*8e3e3a7aSWarner Losh       check_condition(ls, fs->f->is_vararg,
964*8e3e3a7aSWarner Losh                       "cannot use '...' outside a vararg function");
965*8e3e3a7aSWarner Losh       init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
966*8e3e3a7aSWarner Losh       break;
967*8e3e3a7aSWarner Losh     }
968*8e3e3a7aSWarner Losh     case '{': {  /* constructor */
969*8e3e3a7aSWarner Losh       constructor(ls, v);
970*8e3e3a7aSWarner Losh       return;
971*8e3e3a7aSWarner Losh     }
972*8e3e3a7aSWarner Losh     case TK_FUNCTION: {
973*8e3e3a7aSWarner Losh       luaX_next(ls);
974*8e3e3a7aSWarner Losh       body(ls, v, 0, ls->linenumber);
975*8e3e3a7aSWarner Losh       return;
976*8e3e3a7aSWarner Losh     }
977*8e3e3a7aSWarner Losh     default: {
978*8e3e3a7aSWarner Losh       suffixedexp(ls, v);
979*8e3e3a7aSWarner Losh       return;
980*8e3e3a7aSWarner Losh     }
981*8e3e3a7aSWarner Losh   }
982*8e3e3a7aSWarner Losh   luaX_next(ls);
983*8e3e3a7aSWarner Losh }
984*8e3e3a7aSWarner Losh 
985*8e3e3a7aSWarner Losh 
986*8e3e3a7aSWarner Losh static UnOpr getunopr (int op) {
987*8e3e3a7aSWarner Losh   switch (op) {
988*8e3e3a7aSWarner Losh     case TK_NOT: return OPR_NOT;
989*8e3e3a7aSWarner Losh     case '-': return OPR_MINUS;
990*8e3e3a7aSWarner Losh     case '~': return OPR_BNOT;
991*8e3e3a7aSWarner Losh     case '#': return OPR_LEN;
992*8e3e3a7aSWarner Losh     default: return OPR_NOUNOPR;
993*8e3e3a7aSWarner Losh   }
994*8e3e3a7aSWarner Losh }
995*8e3e3a7aSWarner Losh 
996*8e3e3a7aSWarner Losh 
997*8e3e3a7aSWarner Losh static BinOpr getbinopr (int op) {
998*8e3e3a7aSWarner Losh   switch (op) {
999*8e3e3a7aSWarner Losh     case '+': return OPR_ADD;
1000*8e3e3a7aSWarner Losh     case '-': return OPR_SUB;
1001*8e3e3a7aSWarner Losh     case '*': return OPR_MUL;
1002*8e3e3a7aSWarner Losh     case '%': return OPR_MOD;
1003*8e3e3a7aSWarner Losh     case '^': return OPR_POW;
1004*8e3e3a7aSWarner Losh     case '/': return OPR_DIV;
1005*8e3e3a7aSWarner Losh     case TK_IDIV: return OPR_IDIV;
1006*8e3e3a7aSWarner Losh     case '&': return OPR_BAND;
1007*8e3e3a7aSWarner Losh     case '|': return OPR_BOR;
1008*8e3e3a7aSWarner Losh     case '~': return OPR_BXOR;
1009*8e3e3a7aSWarner Losh     case TK_SHL: return OPR_SHL;
1010*8e3e3a7aSWarner Losh     case TK_SHR: return OPR_SHR;
1011*8e3e3a7aSWarner Losh     case TK_CONCAT: return OPR_CONCAT;
1012*8e3e3a7aSWarner Losh     case TK_NE: return OPR_NE;
1013*8e3e3a7aSWarner Losh     case TK_EQ: return OPR_EQ;
1014*8e3e3a7aSWarner Losh     case '<': return OPR_LT;
1015*8e3e3a7aSWarner Losh     case TK_LE: return OPR_LE;
1016*8e3e3a7aSWarner Losh     case '>': return OPR_GT;
1017*8e3e3a7aSWarner Losh     case TK_GE: return OPR_GE;
1018*8e3e3a7aSWarner Losh     case TK_AND: return OPR_AND;
1019*8e3e3a7aSWarner Losh     case TK_OR: return OPR_OR;
1020*8e3e3a7aSWarner Losh     default: return OPR_NOBINOPR;
1021*8e3e3a7aSWarner Losh   }
1022*8e3e3a7aSWarner Losh }
1023*8e3e3a7aSWarner Losh 
1024*8e3e3a7aSWarner Losh 
1025*8e3e3a7aSWarner Losh static const struct {
1026*8e3e3a7aSWarner Losh   lu_byte left;  /* left priority for each binary operator */
1027*8e3e3a7aSWarner Losh   lu_byte right; /* right priority */
1028*8e3e3a7aSWarner Losh } priority[] = {  /* ORDER OPR */
1029*8e3e3a7aSWarner Losh    {10, 10}, {10, 10},           /* '+' '-' */
1030*8e3e3a7aSWarner Losh    {11, 11}, {11, 11},           /* '*' '%' */
1031*8e3e3a7aSWarner Losh    {14, 13},                  /* '^' (right associative) */
1032*8e3e3a7aSWarner Losh    {11, 11}, {11, 11},           /* '/' '//' */
1033*8e3e3a7aSWarner Losh    {6, 6}, {4, 4}, {5, 5},   /* '&' '|' '~' */
1034*8e3e3a7aSWarner Losh    {7, 7}, {7, 7},           /* '<<' '>>' */
1035*8e3e3a7aSWarner Losh    {9, 8},                   /* '..' (right associative) */
1036*8e3e3a7aSWarner Losh    {3, 3}, {3, 3}, {3, 3},   /* ==, <, <= */
1037*8e3e3a7aSWarner Losh    {3, 3}, {3, 3}, {3, 3},   /* ~=, >, >= */
1038*8e3e3a7aSWarner Losh    {2, 2}, {1, 1}            /* and, or */
1039*8e3e3a7aSWarner Losh };
1040*8e3e3a7aSWarner Losh 
1041*8e3e3a7aSWarner Losh #define UNARY_PRIORITY	12  /* priority for unary operators */
1042*8e3e3a7aSWarner Losh 
1043*8e3e3a7aSWarner Losh 
1044*8e3e3a7aSWarner Losh /*
1045*8e3e3a7aSWarner Losh ** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
1046*8e3e3a7aSWarner Losh ** where 'binop' is any binary operator with a priority higher than 'limit'
1047*8e3e3a7aSWarner Losh */
1048*8e3e3a7aSWarner Losh static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
1049*8e3e3a7aSWarner Losh   BinOpr op;
1050*8e3e3a7aSWarner Losh   UnOpr uop;
1051*8e3e3a7aSWarner Losh   enterlevel(ls);
1052*8e3e3a7aSWarner Losh   uop = getunopr(ls->t.token);
1053*8e3e3a7aSWarner Losh   if (uop != OPR_NOUNOPR) {
1054*8e3e3a7aSWarner Losh     int line = ls->linenumber;
1055*8e3e3a7aSWarner Losh     luaX_next(ls);
1056*8e3e3a7aSWarner Losh     subexpr(ls, v, UNARY_PRIORITY);
1057*8e3e3a7aSWarner Losh     luaK_prefix(ls->fs, uop, v, line);
1058*8e3e3a7aSWarner Losh   }
1059*8e3e3a7aSWarner Losh   else simpleexp(ls, v);
1060*8e3e3a7aSWarner Losh   /* expand while operators have priorities higher than 'limit' */
1061*8e3e3a7aSWarner Losh   op = getbinopr(ls->t.token);
1062*8e3e3a7aSWarner Losh   while (op != OPR_NOBINOPR && priority[op].left > limit) {
1063*8e3e3a7aSWarner Losh     expdesc v2;
1064*8e3e3a7aSWarner Losh     BinOpr nextop;
1065*8e3e3a7aSWarner Losh     int line = ls->linenumber;
1066*8e3e3a7aSWarner Losh     luaX_next(ls);
1067*8e3e3a7aSWarner Losh     luaK_infix(ls->fs, op, v);
1068*8e3e3a7aSWarner Losh     /* read sub-expression with higher priority */
1069*8e3e3a7aSWarner Losh     nextop = subexpr(ls, &v2, priority[op].right);
1070*8e3e3a7aSWarner Losh     luaK_posfix(ls->fs, op, v, &v2, line);
1071*8e3e3a7aSWarner Losh     op = nextop;
1072*8e3e3a7aSWarner Losh   }
1073*8e3e3a7aSWarner Losh   leavelevel(ls);
1074*8e3e3a7aSWarner Losh   return op;  /* return first untreated operator */
1075*8e3e3a7aSWarner Losh }
1076*8e3e3a7aSWarner Losh 
1077*8e3e3a7aSWarner Losh 
1078*8e3e3a7aSWarner Losh static void expr (LexState *ls, expdesc *v) {
1079*8e3e3a7aSWarner Losh   subexpr(ls, v, 0);
1080*8e3e3a7aSWarner Losh }
1081*8e3e3a7aSWarner Losh 
1082*8e3e3a7aSWarner Losh /* }==================================================================== */
1083*8e3e3a7aSWarner Losh 
1084*8e3e3a7aSWarner Losh 
1085*8e3e3a7aSWarner Losh 
1086*8e3e3a7aSWarner Losh /*
1087*8e3e3a7aSWarner Losh ** {======================================================================
1088*8e3e3a7aSWarner Losh ** Rules for Statements
1089*8e3e3a7aSWarner Losh ** =======================================================================
1090*8e3e3a7aSWarner Losh */
1091*8e3e3a7aSWarner Losh 
1092*8e3e3a7aSWarner Losh 
1093*8e3e3a7aSWarner Losh static void block (LexState *ls) {
1094*8e3e3a7aSWarner Losh   /* block -> statlist */
1095*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1096*8e3e3a7aSWarner Losh   BlockCnt bl;
1097*8e3e3a7aSWarner Losh   enterblock(fs, &bl, 0);
1098*8e3e3a7aSWarner Losh   statlist(ls);
1099*8e3e3a7aSWarner Losh   leaveblock(fs);
1100*8e3e3a7aSWarner Losh }
1101*8e3e3a7aSWarner Losh 
1102*8e3e3a7aSWarner Losh 
1103*8e3e3a7aSWarner Losh /*
1104*8e3e3a7aSWarner Losh ** structure to chain all variables in the left-hand side of an
1105*8e3e3a7aSWarner Losh ** assignment
1106*8e3e3a7aSWarner Losh */
1107*8e3e3a7aSWarner Losh struct LHS_assign {
1108*8e3e3a7aSWarner Losh   struct LHS_assign *prev;
1109*8e3e3a7aSWarner Losh   expdesc v;  /* variable (global, local, upvalue, or indexed) */
1110*8e3e3a7aSWarner Losh };
1111*8e3e3a7aSWarner Losh 
1112*8e3e3a7aSWarner Losh 
1113*8e3e3a7aSWarner Losh /*
1114*8e3e3a7aSWarner Losh ** check whether, in an assignment to an upvalue/local variable, the
1115*8e3e3a7aSWarner Losh ** upvalue/local variable is begin used in a previous assignment to a
1116*8e3e3a7aSWarner Losh ** table. If so, save original upvalue/local value in a safe place and
1117*8e3e3a7aSWarner Losh ** use this safe copy in the previous assignment.
1118*8e3e3a7aSWarner Losh */
1119*8e3e3a7aSWarner Losh static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
1120*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1121*8e3e3a7aSWarner Losh   int extra = fs->freereg;  /* eventual position to save local variable */
1122*8e3e3a7aSWarner Losh   int conflict = 0;
1123*8e3e3a7aSWarner Losh   for (; lh; lh = lh->prev) {  /* check all previous assignments */
1124*8e3e3a7aSWarner Losh     if (lh->v.k == VINDEXED) {  /* assigning to a table? */
1125*8e3e3a7aSWarner Losh       /* table is the upvalue/local being assigned now? */
1126*8e3e3a7aSWarner Losh       if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) {
1127*8e3e3a7aSWarner Losh         conflict = 1;
1128*8e3e3a7aSWarner Losh         lh->v.u.ind.vt = VLOCAL;
1129*8e3e3a7aSWarner Losh         lh->v.u.ind.t = extra;  /* previous assignment will use safe copy */
1130*8e3e3a7aSWarner Losh       }
1131*8e3e3a7aSWarner Losh       /* index is the local being assigned? (index cannot be upvalue) */
1132*8e3e3a7aSWarner Losh       if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {
1133*8e3e3a7aSWarner Losh         conflict = 1;
1134*8e3e3a7aSWarner Losh         lh->v.u.ind.idx = extra;  /* previous assignment will use safe copy */
1135*8e3e3a7aSWarner Losh       }
1136*8e3e3a7aSWarner Losh     }
1137*8e3e3a7aSWarner Losh   }
1138*8e3e3a7aSWarner Losh   if (conflict) {
1139*8e3e3a7aSWarner Losh     /* copy upvalue/local value to a temporary (in position 'extra') */
1140*8e3e3a7aSWarner Losh     OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
1141*8e3e3a7aSWarner Losh     luaK_codeABC(fs, op, extra, v->u.info, 0);
1142*8e3e3a7aSWarner Losh     luaK_reserveregs(fs, 1);
1143*8e3e3a7aSWarner Losh   }
1144*8e3e3a7aSWarner Losh }
1145*8e3e3a7aSWarner Losh 
1146*8e3e3a7aSWarner Losh 
1147*8e3e3a7aSWarner Losh static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
1148*8e3e3a7aSWarner Losh   expdesc e;
1149*8e3e3a7aSWarner Losh   check_condition(ls, vkisvar(lh->v.k), "syntax error");
1150*8e3e3a7aSWarner Losh   if (testnext(ls, ',')) {  /* assignment -> ',' suffixedexp assignment */
1151*8e3e3a7aSWarner Losh     struct LHS_assign nv;
1152*8e3e3a7aSWarner Losh     nv.prev = lh;
1153*8e3e3a7aSWarner Losh     suffixedexp(ls, &nv.v);
1154*8e3e3a7aSWarner Losh     if (nv.v.k != VINDEXED)
1155*8e3e3a7aSWarner Losh       check_conflict(ls, lh, &nv.v);
1156*8e3e3a7aSWarner Losh     checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
1157*8e3e3a7aSWarner Losh                     "C levels");
1158*8e3e3a7aSWarner Losh     assignment(ls, &nv, nvars+1);
1159*8e3e3a7aSWarner Losh   }
1160*8e3e3a7aSWarner Losh   else {  /* assignment -> '=' explist */
1161*8e3e3a7aSWarner Losh     int nexps;
1162*8e3e3a7aSWarner Losh     checknext(ls, '=');
1163*8e3e3a7aSWarner Losh     nexps = explist(ls, &e);
1164*8e3e3a7aSWarner Losh     if (nexps != nvars)
1165*8e3e3a7aSWarner Losh       adjust_assign(ls, nvars, nexps, &e);
1166*8e3e3a7aSWarner Losh     else {
1167*8e3e3a7aSWarner Losh       luaK_setoneret(ls->fs, &e);  /* close last expression */
1168*8e3e3a7aSWarner Losh       luaK_storevar(ls->fs, &lh->v, &e);
1169*8e3e3a7aSWarner Losh       return;  /* avoid default */
1170*8e3e3a7aSWarner Losh     }
1171*8e3e3a7aSWarner Losh   }
1172*8e3e3a7aSWarner Losh   init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */
1173*8e3e3a7aSWarner Losh   luaK_storevar(ls->fs, &lh->v, &e);
1174*8e3e3a7aSWarner Losh }
1175*8e3e3a7aSWarner Losh 
1176*8e3e3a7aSWarner Losh 
1177*8e3e3a7aSWarner Losh static int cond (LexState *ls) {
1178*8e3e3a7aSWarner Losh   /* cond -> exp */
1179*8e3e3a7aSWarner Losh   expdesc v;
1180*8e3e3a7aSWarner Losh   expr(ls, &v);  /* read condition */
1181*8e3e3a7aSWarner Losh   if (v.k == VNIL) v.k = VFALSE;  /* 'falses' are all equal here */
1182*8e3e3a7aSWarner Losh   luaK_goiftrue(ls->fs, &v);
1183*8e3e3a7aSWarner Losh   return v.f;
1184*8e3e3a7aSWarner Losh }
1185*8e3e3a7aSWarner Losh 
1186*8e3e3a7aSWarner Losh 
1187*8e3e3a7aSWarner Losh static void gotostat (LexState *ls, int pc) {
1188*8e3e3a7aSWarner Losh   int line = ls->linenumber;
1189*8e3e3a7aSWarner Losh   TString *label;
1190*8e3e3a7aSWarner Losh   int g;
1191*8e3e3a7aSWarner Losh   if (testnext(ls, TK_GOTO))
1192*8e3e3a7aSWarner Losh     label = str_checkname(ls);
1193*8e3e3a7aSWarner Losh   else {
1194*8e3e3a7aSWarner Losh     luaX_next(ls);  /* skip break */
1195*8e3e3a7aSWarner Losh     label = luaS_new(ls->L, "break");
1196*8e3e3a7aSWarner Losh   }
1197*8e3e3a7aSWarner Losh   g = newlabelentry(ls, &ls->dyd->gt, label, line, pc);
1198*8e3e3a7aSWarner Losh   findlabel(ls, g);  /* close it if label already defined */
1199*8e3e3a7aSWarner Losh }
1200*8e3e3a7aSWarner Losh 
1201*8e3e3a7aSWarner Losh 
1202*8e3e3a7aSWarner Losh /* check for repeated labels on the same block */
1203*8e3e3a7aSWarner Losh static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
1204*8e3e3a7aSWarner Losh   int i;
1205*8e3e3a7aSWarner Losh   for (i = fs->bl->firstlabel; i < ll->n; i++) {
1206*8e3e3a7aSWarner Losh     if (eqstr(label, ll->arr[i].name)) {
1207*8e3e3a7aSWarner Losh       const char *msg = luaO_pushfstring(fs->ls->L,
1208*8e3e3a7aSWarner Losh                           "label '%s' already defined on line %d",
1209*8e3e3a7aSWarner Losh                           getstr(label), ll->arr[i].line);
1210*8e3e3a7aSWarner Losh       semerror(fs->ls, msg);
1211*8e3e3a7aSWarner Losh     }
1212*8e3e3a7aSWarner Losh   }
1213*8e3e3a7aSWarner Losh }
1214*8e3e3a7aSWarner Losh 
1215*8e3e3a7aSWarner Losh 
1216*8e3e3a7aSWarner Losh /* skip no-op statements */
1217*8e3e3a7aSWarner Losh static void skipnoopstat (LexState *ls) {
1218*8e3e3a7aSWarner Losh   while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
1219*8e3e3a7aSWarner Losh     statement(ls);
1220*8e3e3a7aSWarner Losh }
1221*8e3e3a7aSWarner Losh 
1222*8e3e3a7aSWarner Losh 
1223*8e3e3a7aSWarner Losh static void labelstat (LexState *ls, TString *label, int line) {
1224*8e3e3a7aSWarner Losh   /* label -> '::' NAME '::' */
1225*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1226*8e3e3a7aSWarner Losh   Labellist *ll = &ls->dyd->label;
1227*8e3e3a7aSWarner Losh   int l;  /* index of new label being created */
1228*8e3e3a7aSWarner Losh   checkrepeated(fs, ll, label);  /* check for repeated labels */
1229*8e3e3a7aSWarner Losh   checknext(ls, TK_DBCOLON);  /* skip double colon */
1230*8e3e3a7aSWarner Losh   /* create new entry for this label */
1231*8e3e3a7aSWarner Losh   l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
1232*8e3e3a7aSWarner Losh   skipnoopstat(ls);  /* skip other no-op statements */
1233*8e3e3a7aSWarner Losh   if (block_follow(ls, 0)) {  /* label is last no-op statement in the block? */
1234*8e3e3a7aSWarner Losh     /* assume that locals are already out of scope */
1235*8e3e3a7aSWarner Losh     ll->arr[l].nactvar = fs->bl->nactvar;
1236*8e3e3a7aSWarner Losh   }
1237*8e3e3a7aSWarner Losh   findgotos(ls, &ll->arr[l]);
1238*8e3e3a7aSWarner Losh }
1239*8e3e3a7aSWarner Losh 
1240*8e3e3a7aSWarner Losh 
1241*8e3e3a7aSWarner Losh static void whilestat (LexState *ls, int line) {
1242*8e3e3a7aSWarner Losh   /* whilestat -> WHILE cond DO block END */
1243*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1244*8e3e3a7aSWarner Losh   int whileinit;
1245*8e3e3a7aSWarner Losh   int condexit;
1246*8e3e3a7aSWarner Losh   BlockCnt bl;
1247*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip WHILE */
1248*8e3e3a7aSWarner Losh   whileinit = luaK_getlabel(fs);
1249*8e3e3a7aSWarner Losh   condexit = cond(ls);
1250*8e3e3a7aSWarner Losh   enterblock(fs, &bl, 1);
1251*8e3e3a7aSWarner Losh   checknext(ls, TK_DO);
1252*8e3e3a7aSWarner Losh   block(ls);
1253*8e3e3a7aSWarner Losh   luaK_jumpto(fs, whileinit);
1254*8e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_WHILE, line);
1255*8e3e3a7aSWarner Losh   leaveblock(fs);
1256*8e3e3a7aSWarner Losh   luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */
1257*8e3e3a7aSWarner Losh }
1258*8e3e3a7aSWarner Losh 
1259*8e3e3a7aSWarner Losh 
1260*8e3e3a7aSWarner Losh static void repeatstat (LexState *ls, int line) {
1261*8e3e3a7aSWarner Losh   /* repeatstat -> REPEAT block UNTIL cond */
1262*8e3e3a7aSWarner Losh   int condexit;
1263*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1264*8e3e3a7aSWarner Losh   int repeat_init = luaK_getlabel(fs);
1265*8e3e3a7aSWarner Losh   BlockCnt bl1, bl2;
1266*8e3e3a7aSWarner Losh   enterblock(fs, &bl1, 1);  /* loop block */
1267*8e3e3a7aSWarner Losh   enterblock(fs, &bl2, 0);  /* scope block */
1268*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip REPEAT */
1269*8e3e3a7aSWarner Losh   statlist(ls);
1270*8e3e3a7aSWarner Losh   check_match(ls, TK_UNTIL, TK_REPEAT, line);
1271*8e3e3a7aSWarner Losh   condexit = cond(ls);  /* read condition (inside scope block) */
1272*8e3e3a7aSWarner Losh   if (bl2.upval)  /* upvalues? */
1273*8e3e3a7aSWarner Losh     luaK_patchclose(fs, condexit, bl2.nactvar);
1274*8e3e3a7aSWarner Losh   leaveblock(fs);  /* finish scope */
1275*8e3e3a7aSWarner Losh   luaK_patchlist(fs, condexit, repeat_init);  /* close the loop */
1276*8e3e3a7aSWarner Losh   leaveblock(fs);  /* finish loop */
1277*8e3e3a7aSWarner Losh }
1278*8e3e3a7aSWarner Losh 
1279*8e3e3a7aSWarner Losh 
1280*8e3e3a7aSWarner Losh static int exp1 (LexState *ls) {
1281*8e3e3a7aSWarner Losh   expdesc e;
1282*8e3e3a7aSWarner Losh   int reg;
1283*8e3e3a7aSWarner Losh   expr(ls, &e);
1284*8e3e3a7aSWarner Losh   luaK_exp2nextreg(ls->fs, &e);
1285*8e3e3a7aSWarner Losh   lua_assert(e.k == VNONRELOC);
1286*8e3e3a7aSWarner Losh   reg = e.u.info;
1287*8e3e3a7aSWarner Losh   return reg;
1288*8e3e3a7aSWarner Losh }
1289*8e3e3a7aSWarner Losh 
1290*8e3e3a7aSWarner Losh 
1291*8e3e3a7aSWarner Losh static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
1292*8e3e3a7aSWarner Losh   /* forbody -> DO block */
1293*8e3e3a7aSWarner Losh   BlockCnt bl;
1294*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1295*8e3e3a7aSWarner Losh   int prep, endfor;
1296*8e3e3a7aSWarner Losh   adjustlocalvars(ls, 3);  /* control variables */
1297*8e3e3a7aSWarner Losh   checknext(ls, TK_DO);
1298*8e3e3a7aSWarner Losh   prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
1299*8e3e3a7aSWarner Losh   enterblock(fs, &bl, 0);  /* scope for declared variables */
1300*8e3e3a7aSWarner Losh   adjustlocalvars(ls, nvars);
1301*8e3e3a7aSWarner Losh   luaK_reserveregs(fs, nvars);
1302*8e3e3a7aSWarner Losh   block(ls);
1303*8e3e3a7aSWarner Losh   leaveblock(fs);  /* end of scope for declared variables */
1304*8e3e3a7aSWarner Losh   luaK_patchtohere(fs, prep);
1305*8e3e3a7aSWarner Losh   if (isnum)  /* numeric for? */
1306*8e3e3a7aSWarner Losh     endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
1307*8e3e3a7aSWarner Losh   else {  /* generic for */
1308*8e3e3a7aSWarner Losh     luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
1309*8e3e3a7aSWarner Losh     luaK_fixline(fs, line);
1310*8e3e3a7aSWarner Losh     endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP);
1311*8e3e3a7aSWarner Losh   }
1312*8e3e3a7aSWarner Losh   luaK_patchlist(fs, endfor, prep + 1);
1313*8e3e3a7aSWarner Losh   luaK_fixline(fs, line);
1314*8e3e3a7aSWarner Losh }
1315*8e3e3a7aSWarner Losh 
1316*8e3e3a7aSWarner Losh 
1317*8e3e3a7aSWarner Losh static void fornum (LexState *ls, TString *varname, int line) {
1318*8e3e3a7aSWarner Losh   /* fornum -> NAME = exp1,exp1[,exp1] forbody */
1319*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1320*8e3e3a7aSWarner Losh   int base = fs->freereg;
1321*8e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for index)");
1322*8e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for limit)");
1323*8e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for step)");
1324*8e3e3a7aSWarner Losh   new_localvar(ls, varname);
1325*8e3e3a7aSWarner Losh   checknext(ls, '=');
1326*8e3e3a7aSWarner Losh   exp1(ls);  /* initial value */
1327*8e3e3a7aSWarner Losh   checknext(ls, ',');
1328*8e3e3a7aSWarner Losh   exp1(ls);  /* limit */
1329*8e3e3a7aSWarner Losh   if (testnext(ls, ','))
1330*8e3e3a7aSWarner Losh     exp1(ls);  /* optional step */
1331*8e3e3a7aSWarner Losh   else {  /* default step = 1 */
1332*8e3e3a7aSWarner Losh     luaK_codek(fs, fs->freereg, luaK_intK(fs, 1));
1333*8e3e3a7aSWarner Losh     luaK_reserveregs(fs, 1);
1334*8e3e3a7aSWarner Losh   }
1335*8e3e3a7aSWarner Losh   forbody(ls, base, line, 1, 1);
1336*8e3e3a7aSWarner Losh }
1337*8e3e3a7aSWarner Losh 
1338*8e3e3a7aSWarner Losh 
1339*8e3e3a7aSWarner Losh static void forlist (LexState *ls, TString *indexname) {
1340*8e3e3a7aSWarner Losh   /* forlist -> NAME {,NAME} IN explist forbody */
1341*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1342*8e3e3a7aSWarner Losh   expdesc e;
1343*8e3e3a7aSWarner Losh   int nvars = 4;  /* gen, state, control, plus at least one declared var */
1344*8e3e3a7aSWarner Losh   int line;
1345*8e3e3a7aSWarner Losh   int base = fs->freereg;
1346*8e3e3a7aSWarner Losh   /* create control variables */
1347*8e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for generator)");
1348*8e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for state)");
1349*8e3e3a7aSWarner Losh   new_localvarliteral(ls, "(for control)");
1350*8e3e3a7aSWarner Losh   /* create declared variables */
1351*8e3e3a7aSWarner Losh   new_localvar(ls, indexname);
1352*8e3e3a7aSWarner Losh   while (testnext(ls, ',')) {
1353*8e3e3a7aSWarner Losh     new_localvar(ls, str_checkname(ls));
1354*8e3e3a7aSWarner Losh     nvars++;
1355*8e3e3a7aSWarner Losh   }
1356*8e3e3a7aSWarner Losh   checknext(ls, TK_IN);
1357*8e3e3a7aSWarner Losh   line = ls->linenumber;
1358*8e3e3a7aSWarner Losh   adjust_assign(ls, 3, explist(ls, &e), &e);
1359*8e3e3a7aSWarner Losh   luaK_checkstack(fs, 3);  /* extra space to call generator */
1360*8e3e3a7aSWarner Losh   forbody(ls, base, line, nvars - 3, 0);
1361*8e3e3a7aSWarner Losh }
1362*8e3e3a7aSWarner Losh 
1363*8e3e3a7aSWarner Losh 
1364*8e3e3a7aSWarner Losh static void forstat (LexState *ls, int line) {
1365*8e3e3a7aSWarner Losh   /* forstat -> FOR (fornum | forlist) END */
1366*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1367*8e3e3a7aSWarner Losh   TString *varname;
1368*8e3e3a7aSWarner Losh   BlockCnt bl;
1369*8e3e3a7aSWarner Losh   enterblock(fs, &bl, 1);  /* scope for loop and control variables */
1370*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip 'for' */
1371*8e3e3a7aSWarner Losh   varname = str_checkname(ls);  /* first variable name */
1372*8e3e3a7aSWarner Losh   switch (ls->t.token) {
1373*8e3e3a7aSWarner Losh     case '=': fornum(ls, varname, line); break;
1374*8e3e3a7aSWarner Losh     case ',': case TK_IN: forlist(ls, varname); break;
1375*8e3e3a7aSWarner Losh     default: luaX_syntaxerror(ls, "'=' or 'in' expected");
1376*8e3e3a7aSWarner Losh   }
1377*8e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_FOR, line);
1378*8e3e3a7aSWarner Losh   leaveblock(fs);  /* loop scope ('break' jumps to this point) */
1379*8e3e3a7aSWarner Losh }
1380*8e3e3a7aSWarner Losh 
1381*8e3e3a7aSWarner Losh 
1382*8e3e3a7aSWarner Losh static void test_then_block (LexState *ls, int *escapelist) {
1383*8e3e3a7aSWarner Losh   /* test_then_block -> [IF | ELSEIF] cond THEN block */
1384*8e3e3a7aSWarner Losh   BlockCnt bl;
1385*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1386*8e3e3a7aSWarner Losh   expdesc v;
1387*8e3e3a7aSWarner Losh   int jf;  /* instruction to skip 'then' code (if condition is false) */
1388*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip IF or ELSEIF */
1389*8e3e3a7aSWarner Losh   expr(ls, &v);  /* read condition */
1390*8e3e3a7aSWarner Losh   checknext(ls, TK_THEN);
1391*8e3e3a7aSWarner Losh   if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) {
1392*8e3e3a7aSWarner Losh     luaK_goiffalse(ls->fs, &v);  /* will jump to label if condition is true */
1393*8e3e3a7aSWarner Losh     enterblock(fs, &bl, 0);  /* must enter block before 'goto' */
1394*8e3e3a7aSWarner Losh     gotostat(ls, v.t);  /* handle goto/break */
1395*8e3e3a7aSWarner Losh     skipnoopstat(ls);  /* skip other no-op statements */
1396*8e3e3a7aSWarner Losh     if (block_follow(ls, 0)) {  /* 'goto' is the entire block? */
1397*8e3e3a7aSWarner Losh       leaveblock(fs);
1398*8e3e3a7aSWarner Losh       return;  /* and that is it */
1399*8e3e3a7aSWarner Losh     }
1400*8e3e3a7aSWarner Losh     else  /* must skip over 'then' part if condition is false */
1401*8e3e3a7aSWarner Losh       jf = luaK_jump(fs);
1402*8e3e3a7aSWarner Losh   }
1403*8e3e3a7aSWarner Losh   else {  /* regular case (not goto/break) */
1404*8e3e3a7aSWarner Losh     luaK_goiftrue(ls->fs, &v);  /* skip over block if condition is false */
1405*8e3e3a7aSWarner Losh     enterblock(fs, &bl, 0);
1406*8e3e3a7aSWarner Losh     jf = v.f;
1407*8e3e3a7aSWarner Losh   }
1408*8e3e3a7aSWarner Losh   statlist(ls);  /* 'then' part */
1409*8e3e3a7aSWarner Losh   leaveblock(fs);
1410*8e3e3a7aSWarner Losh   if (ls->t.token == TK_ELSE ||
1411*8e3e3a7aSWarner Losh       ls->t.token == TK_ELSEIF)  /* followed by 'else'/'elseif'? */
1412*8e3e3a7aSWarner Losh     luaK_concat(fs, escapelist, luaK_jump(fs));  /* must jump over it */
1413*8e3e3a7aSWarner Losh   luaK_patchtohere(fs, jf);
1414*8e3e3a7aSWarner Losh }
1415*8e3e3a7aSWarner Losh 
1416*8e3e3a7aSWarner Losh 
1417*8e3e3a7aSWarner Losh static void ifstat (LexState *ls, int line) {
1418*8e3e3a7aSWarner Losh   /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
1419*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1420*8e3e3a7aSWarner Losh   int escapelist = NO_JUMP;  /* exit list for finished parts */
1421*8e3e3a7aSWarner Losh   test_then_block(ls, &escapelist);  /* IF cond THEN block */
1422*8e3e3a7aSWarner Losh   while (ls->t.token == TK_ELSEIF)
1423*8e3e3a7aSWarner Losh     test_then_block(ls, &escapelist);  /* ELSEIF cond THEN block */
1424*8e3e3a7aSWarner Losh   if (testnext(ls, TK_ELSE))
1425*8e3e3a7aSWarner Losh     block(ls);  /* 'else' part */
1426*8e3e3a7aSWarner Losh   check_match(ls, TK_END, TK_IF, line);
1427*8e3e3a7aSWarner Losh   luaK_patchtohere(fs, escapelist);  /* patch escape list to 'if' end */
1428*8e3e3a7aSWarner Losh }
1429*8e3e3a7aSWarner Losh 
1430*8e3e3a7aSWarner Losh 
1431*8e3e3a7aSWarner Losh static void localfunc (LexState *ls) {
1432*8e3e3a7aSWarner Losh   expdesc b;
1433*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1434*8e3e3a7aSWarner Losh   new_localvar(ls, str_checkname(ls));  /* new local variable */
1435*8e3e3a7aSWarner Losh   adjustlocalvars(ls, 1);  /* enter its scope */
1436*8e3e3a7aSWarner Losh   body(ls, &b, 0, ls->linenumber);  /* function created in next register */
1437*8e3e3a7aSWarner Losh   /* debug information will only see the variable after this point! */
1438*8e3e3a7aSWarner Losh   getlocvar(fs, b.u.info)->startpc = fs->pc;
1439*8e3e3a7aSWarner Losh }
1440*8e3e3a7aSWarner Losh 
1441*8e3e3a7aSWarner Losh 
1442*8e3e3a7aSWarner Losh static void localstat (LexState *ls) {
1443*8e3e3a7aSWarner Losh   /* stat -> LOCAL NAME {',' NAME} ['=' explist] */
1444*8e3e3a7aSWarner Losh   int nvars = 0;
1445*8e3e3a7aSWarner Losh   int nexps;
1446*8e3e3a7aSWarner Losh   expdesc e;
1447*8e3e3a7aSWarner Losh   do {
1448*8e3e3a7aSWarner Losh     new_localvar(ls, str_checkname(ls));
1449*8e3e3a7aSWarner Losh     nvars++;
1450*8e3e3a7aSWarner Losh   } while (testnext(ls, ','));
1451*8e3e3a7aSWarner Losh   if (testnext(ls, '='))
1452*8e3e3a7aSWarner Losh     nexps = explist(ls, &e);
1453*8e3e3a7aSWarner Losh   else {
1454*8e3e3a7aSWarner Losh     e.k = VVOID;
1455*8e3e3a7aSWarner Losh     nexps = 0;
1456*8e3e3a7aSWarner Losh   }
1457*8e3e3a7aSWarner Losh   adjust_assign(ls, nvars, nexps, &e);
1458*8e3e3a7aSWarner Losh   adjustlocalvars(ls, nvars);
1459*8e3e3a7aSWarner Losh }
1460*8e3e3a7aSWarner Losh 
1461*8e3e3a7aSWarner Losh 
1462*8e3e3a7aSWarner Losh static int funcname (LexState *ls, expdesc *v) {
1463*8e3e3a7aSWarner Losh   /* funcname -> NAME {fieldsel} [':' NAME] */
1464*8e3e3a7aSWarner Losh   int ismethod = 0;
1465*8e3e3a7aSWarner Losh   singlevar(ls, v);
1466*8e3e3a7aSWarner Losh   while (ls->t.token == '.')
1467*8e3e3a7aSWarner Losh     fieldsel(ls, v);
1468*8e3e3a7aSWarner Losh   if (ls->t.token == ':') {
1469*8e3e3a7aSWarner Losh     ismethod = 1;
1470*8e3e3a7aSWarner Losh     fieldsel(ls, v);
1471*8e3e3a7aSWarner Losh   }
1472*8e3e3a7aSWarner Losh   return ismethod;
1473*8e3e3a7aSWarner Losh }
1474*8e3e3a7aSWarner Losh 
1475*8e3e3a7aSWarner Losh 
1476*8e3e3a7aSWarner Losh static void funcstat (LexState *ls, int line) {
1477*8e3e3a7aSWarner Losh   /* funcstat -> FUNCTION funcname body */
1478*8e3e3a7aSWarner Losh   int ismethod;
1479*8e3e3a7aSWarner Losh   expdesc v, b;
1480*8e3e3a7aSWarner Losh   luaX_next(ls);  /* skip FUNCTION */
1481*8e3e3a7aSWarner Losh   ismethod = funcname(ls, &v);
1482*8e3e3a7aSWarner Losh   body(ls, &b, ismethod, line);
1483*8e3e3a7aSWarner Losh   luaK_storevar(ls->fs, &v, &b);
1484*8e3e3a7aSWarner Losh   luaK_fixline(ls->fs, line);  /* definition "happens" in the first line */
1485*8e3e3a7aSWarner Losh }
1486*8e3e3a7aSWarner Losh 
1487*8e3e3a7aSWarner Losh 
1488*8e3e3a7aSWarner Losh static void exprstat (LexState *ls) {
1489*8e3e3a7aSWarner Losh   /* stat -> func | assignment */
1490*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1491*8e3e3a7aSWarner Losh   struct LHS_assign v;
1492*8e3e3a7aSWarner Losh   suffixedexp(ls, &v.v);
1493*8e3e3a7aSWarner Losh   if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
1494*8e3e3a7aSWarner Losh     v.prev = NULL;
1495*8e3e3a7aSWarner Losh     assignment(ls, &v, 1);
1496*8e3e3a7aSWarner Losh   }
1497*8e3e3a7aSWarner Losh   else {  /* stat -> func */
1498*8e3e3a7aSWarner Losh     check_condition(ls, v.v.k == VCALL, "syntax error");
1499*8e3e3a7aSWarner Losh     SETARG_C(getinstruction(fs, &v.v), 1);  /* call statement uses no results */
1500*8e3e3a7aSWarner Losh   }
1501*8e3e3a7aSWarner Losh }
1502*8e3e3a7aSWarner Losh 
1503*8e3e3a7aSWarner Losh 
1504*8e3e3a7aSWarner Losh static void retstat (LexState *ls) {
1505*8e3e3a7aSWarner Losh   /* stat -> RETURN [explist] [';'] */
1506*8e3e3a7aSWarner Losh   FuncState *fs = ls->fs;
1507*8e3e3a7aSWarner Losh   expdesc e;
1508*8e3e3a7aSWarner Losh   int first, nret;  /* registers with returned values */
1509*8e3e3a7aSWarner Losh   if (block_follow(ls, 1) || ls->t.token == ';')
1510*8e3e3a7aSWarner Losh     first = nret = 0;  /* return no values */
1511*8e3e3a7aSWarner Losh   else {
1512*8e3e3a7aSWarner Losh     nret = explist(ls, &e);  /* optional return values */
1513*8e3e3a7aSWarner Losh     if (hasmultret(e.k)) {
1514*8e3e3a7aSWarner Losh       luaK_setmultret(fs, &e);
1515*8e3e3a7aSWarner Losh       if (e.k == VCALL && nret == 1) {  /* tail call? */
1516*8e3e3a7aSWarner Losh         SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
1517*8e3e3a7aSWarner Losh         lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
1518*8e3e3a7aSWarner Losh       }
1519*8e3e3a7aSWarner Losh       first = fs->nactvar;
1520*8e3e3a7aSWarner Losh       nret = LUA_MULTRET;  /* return all values */
1521*8e3e3a7aSWarner Losh     }
1522*8e3e3a7aSWarner Losh     else {
1523*8e3e3a7aSWarner Losh       if (nret == 1)  /* only one single value? */
1524*8e3e3a7aSWarner Losh         first = luaK_exp2anyreg(fs, &e);
1525*8e3e3a7aSWarner Losh       else {
1526*8e3e3a7aSWarner Losh         luaK_exp2nextreg(fs, &e);  /* values must go to the stack */
1527*8e3e3a7aSWarner Losh         first = fs->nactvar;  /* return all active values */
1528*8e3e3a7aSWarner Losh         lua_assert(nret == fs->freereg - first);
1529*8e3e3a7aSWarner Losh       }
1530*8e3e3a7aSWarner Losh     }
1531*8e3e3a7aSWarner Losh   }
1532*8e3e3a7aSWarner Losh   luaK_ret(fs, first, nret);
1533*8e3e3a7aSWarner Losh   testnext(ls, ';');  /* skip optional semicolon */
1534*8e3e3a7aSWarner Losh }
1535*8e3e3a7aSWarner Losh 
1536*8e3e3a7aSWarner Losh 
1537*8e3e3a7aSWarner Losh static void statement (LexState *ls) {
1538*8e3e3a7aSWarner Losh   int line = ls->linenumber;  /* may be needed for error messages */
1539*8e3e3a7aSWarner Losh   enterlevel(ls);
1540*8e3e3a7aSWarner Losh   switch (ls->t.token) {
1541*8e3e3a7aSWarner Losh     case ';': {  /* stat -> ';' (empty statement) */
1542*8e3e3a7aSWarner Losh       luaX_next(ls);  /* skip ';' */
1543*8e3e3a7aSWarner Losh       break;
1544*8e3e3a7aSWarner Losh     }
1545*8e3e3a7aSWarner Losh     case TK_IF: {  /* stat -> ifstat */
1546*8e3e3a7aSWarner Losh       ifstat(ls, line);
1547*8e3e3a7aSWarner Losh       break;
1548*8e3e3a7aSWarner Losh     }
1549*8e3e3a7aSWarner Losh     case TK_WHILE: {  /* stat -> whilestat */
1550*8e3e3a7aSWarner Losh       whilestat(ls, line);
1551*8e3e3a7aSWarner Losh       break;
1552*8e3e3a7aSWarner Losh     }
1553*8e3e3a7aSWarner Losh     case TK_DO: {  /* stat -> DO block END */
1554*8e3e3a7aSWarner Losh       luaX_next(ls);  /* skip DO */
1555*8e3e3a7aSWarner Losh       block(ls);
1556*8e3e3a7aSWarner Losh       check_match(ls, TK_END, TK_DO, line);
1557*8e3e3a7aSWarner Losh       break;
1558*8e3e3a7aSWarner Losh     }
1559*8e3e3a7aSWarner Losh     case TK_FOR: {  /* stat -> forstat */
1560*8e3e3a7aSWarner Losh       forstat(ls, line);
1561*8e3e3a7aSWarner Losh       break;
1562*8e3e3a7aSWarner Losh     }
1563*8e3e3a7aSWarner Losh     case TK_REPEAT: {  /* stat -> repeatstat */
1564*8e3e3a7aSWarner Losh       repeatstat(ls, line);
1565*8e3e3a7aSWarner Losh       break;
1566*8e3e3a7aSWarner Losh     }
1567*8e3e3a7aSWarner Losh     case TK_FUNCTION: {  /* stat -> funcstat */
1568*8e3e3a7aSWarner Losh       funcstat(ls, line);
1569*8e3e3a7aSWarner Losh       break;
1570*8e3e3a7aSWarner Losh     }
1571*8e3e3a7aSWarner Losh     case TK_LOCAL: {  /* stat -> localstat */
1572*8e3e3a7aSWarner Losh       luaX_next(ls);  /* skip LOCAL */
1573*8e3e3a7aSWarner Losh       if (testnext(ls, TK_FUNCTION))  /* local function? */
1574*8e3e3a7aSWarner Losh         localfunc(ls);
1575*8e3e3a7aSWarner Losh       else
1576*8e3e3a7aSWarner Losh         localstat(ls);
1577*8e3e3a7aSWarner Losh       break;
1578*8e3e3a7aSWarner Losh     }
1579*8e3e3a7aSWarner Losh     case TK_DBCOLON: {  /* stat -> label */
1580*8e3e3a7aSWarner Losh       luaX_next(ls);  /* skip double colon */
1581*8e3e3a7aSWarner Losh       labelstat(ls, str_checkname(ls), line);
1582*8e3e3a7aSWarner Losh       break;
1583*8e3e3a7aSWarner Losh     }
1584*8e3e3a7aSWarner Losh     case TK_RETURN: {  /* stat -> retstat */
1585*8e3e3a7aSWarner Losh       luaX_next(ls);  /* skip RETURN */
1586*8e3e3a7aSWarner Losh       retstat(ls);
1587*8e3e3a7aSWarner Losh       break;
1588*8e3e3a7aSWarner Losh     }
1589*8e3e3a7aSWarner Losh     case TK_BREAK:   /* stat -> breakstat */
1590*8e3e3a7aSWarner Losh     case TK_GOTO: {  /* stat -> 'goto' NAME */
1591*8e3e3a7aSWarner Losh       gotostat(ls, luaK_jump(ls->fs));
1592*8e3e3a7aSWarner Losh       break;
1593*8e3e3a7aSWarner Losh     }
1594*8e3e3a7aSWarner Losh     default: {  /* stat -> func | assignment */
1595*8e3e3a7aSWarner Losh       exprstat(ls);
1596*8e3e3a7aSWarner Losh       break;
1597*8e3e3a7aSWarner Losh     }
1598*8e3e3a7aSWarner Losh   }
1599*8e3e3a7aSWarner Losh   lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
1600*8e3e3a7aSWarner Losh              ls->fs->freereg >= ls->fs->nactvar);
1601*8e3e3a7aSWarner Losh   ls->fs->freereg = ls->fs->nactvar;  /* free registers */
1602*8e3e3a7aSWarner Losh   leavelevel(ls);
1603*8e3e3a7aSWarner Losh }
1604*8e3e3a7aSWarner Losh 
1605*8e3e3a7aSWarner Losh /* }====================================================================== */
1606*8e3e3a7aSWarner Losh 
1607*8e3e3a7aSWarner Losh 
1608*8e3e3a7aSWarner Losh /*
1609*8e3e3a7aSWarner Losh ** compiles the main function, which is a regular vararg function with an
1610*8e3e3a7aSWarner Losh ** upvalue named LUA_ENV
1611*8e3e3a7aSWarner Losh */
1612*8e3e3a7aSWarner Losh static void mainfunc (LexState *ls, FuncState *fs) {
1613*8e3e3a7aSWarner Losh   BlockCnt bl;
1614*8e3e3a7aSWarner Losh   expdesc v;
1615*8e3e3a7aSWarner Losh   open_func(ls, fs, &bl);
1616*8e3e3a7aSWarner Losh   fs->f->is_vararg = 1;  /* main function is always declared vararg */
1617*8e3e3a7aSWarner Losh   init_exp(&v, VLOCAL, 0);  /* create and... */
1618*8e3e3a7aSWarner Losh   newupvalue(fs, ls->envn, &v);  /* ...set environment upvalue */
1619*8e3e3a7aSWarner Losh   luaX_next(ls);  /* read first token */
1620*8e3e3a7aSWarner Losh   statlist(ls);  /* parse main body */
1621*8e3e3a7aSWarner Losh   check(ls, TK_EOS);
1622*8e3e3a7aSWarner Losh   close_func(ls);
1623*8e3e3a7aSWarner Losh }
1624*8e3e3a7aSWarner Losh 
1625*8e3e3a7aSWarner Losh 
1626*8e3e3a7aSWarner Losh LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
1627*8e3e3a7aSWarner Losh                        Dyndata *dyd, const char *name, int firstchar) {
1628*8e3e3a7aSWarner Losh   LexState lexstate;
1629*8e3e3a7aSWarner Losh   FuncState funcstate;
1630*8e3e3a7aSWarner Losh   LClosure *cl = luaF_newLclosure(L, 1);  /* create main closure */
1631*8e3e3a7aSWarner Losh   setclLvalue(L, L->top, cl);  /* anchor it (to avoid being collected) */
1632*8e3e3a7aSWarner Losh   luaD_inctop(L);
1633*8e3e3a7aSWarner Losh   lexstate.h = luaH_new(L);  /* create table for scanner */
1634*8e3e3a7aSWarner Losh   sethvalue(L, L->top, lexstate.h);  /* anchor it */
1635*8e3e3a7aSWarner Losh   luaD_inctop(L);
1636*8e3e3a7aSWarner Losh   funcstate.f = cl->p = luaF_newproto(L);
1637*8e3e3a7aSWarner Losh   funcstate.f->source = luaS_new(L, name);  /* create and anchor TString */
1638*8e3e3a7aSWarner Losh   lua_assert(iswhite(funcstate.f));  /* do not need barrier here */
1639*8e3e3a7aSWarner Losh   lexstate.buff = buff;
1640*8e3e3a7aSWarner Losh   lexstate.dyd = dyd;
1641*8e3e3a7aSWarner Losh   dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
1642*8e3e3a7aSWarner Losh   luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
1643*8e3e3a7aSWarner Losh   mainfunc(&lexstate, &funcstate);
1644*8e3e3a7aSWarner Losh   lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
1645*8e3e3a7aSWarner Losh   /* all scopes should be correctly finished */
1646*8e3e3a7aSWarner Losh   lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
1647*8e3e3a7aSWarner Losh   L->top--;  /* remove scanner's table */
1648*8e3e3a7aSWarner Losh   return cl;  /* closure is on the stack, too */
1649*8e3e3a7aSWarner Losh }
1650*8e3e3a7aSWarner Losh 
1651