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