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