summaryrefslogtreecommitdiff
path: root/src/lparser.c
diff options
context:
space:
mode:
authorLua Team <team@lua.org>1999-07-08 12:00:00 +0000
committerrepogen <>1999-07-08 12:00:00 +0000
commitafb67002d94ef22c14741910ba83da262a6e9338 (patch)
treeb51ab3502813f590a4b115997f6fe41da43b6586 /src/lparser.c
parent377347776f1f3d820f92151f70bec667f96d5e6b (diff)
downloadlua-github-3.2.tar.gz
Lua 3.23.2
Diffstat (limited to 'src/lparser.c')
-rw-r--r--src/lparser.c570
1 files changed, 314 insertions, 256 deletions
diff --git a/src/lparser.c b/src/lparser.c
index 9b37d9df..c18b75cc 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,11 +1,12 @@
/*
-** $Id: lparser.c,v 1.3 1998/07/06 22:07:51 roberto Exp $
+** $Id: lparser.c,v 1.37 1999/06/17 17:04:03 roberto Exp $
** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h
*/
#include <stdio.h>
+#include <string.h>
#include "lauxlib.h"
#include "ldo.h"
@@ -21,35 +22,48 @@
#include "lzio.h"
-/* for limit numbers in error messages */
-#define MES_LIM(x) "(limit=" x ")"
-
/* size of a "normal" jump instruction: OpCode + 1 byte */
#define JMPSIZE 2
/* maximum number of local variables */
-#define MAXLOCALS 32
-#define SMAXLOCALS "32"
+#ifndef MAXLOCALS
+#define MAXLOCALS 200 /* arbitrary limit (<256) */
+#endif
/* maximum number of upvalues */
-#define MAXUPVALUES 16
-#define SMAXUPVALUES "16"
+#ifndef MAXUPVALUES
+#define MAXUPVALUES 32 /* arbitrary limit (<256) */
+#endif
+
+
+/* maximum number of variables in the left side of an assignment */
+#ifndef MAXVARSLH
+#define MAXVARSLH 100 /* arbitrary limit (<255) */
+#endif
+
+
+/* maximum number of parameters in a function */
+#ifndef MAXPARAMS
+#define MAXPARAMS 100 /* arbitrary limit (<ZEROVARARG) */
+#endif
/*
** Variable descriptor:
-** must include a "exp" option because LL(1) cannot distinguish
+** must include an "exp" option because LL(1) cannot distinguish
** between variables, upvalues and function calls on first sight.
-** VGLOBAL: info is constant index of global name
-** VLOCAL: info is stack index
-** VDOT: info is constant index of index name
-** VEXP: info is pc index of "nparam" of function call (or 0 if exp is closed)
*/
-typedef enum {VGLOBAL, VLOCAL, VDOT, VINDEXED, VEXP} varkind;
-
-typedef struct {
+typedef enum {
+ VGLOBAL, /* info is constant index of global name */
+ VLOCAL, /* info is stack index */
+ VDOT, /* info is constant index of index name */
+ VINDEXED, /* no info (table and index are on the stack) */
+ VEXP /* info is pc index of "nparam" of a call (or 0 if exp is closed) */
+} varkind;
+
+typedef struct vardesc {
varkind k;
int info;
} vardesc;
@@ -61,7 +75,7 @@ typedef struct {
** and, if last expression is open (a function call),
** where is its pc index of "nparam"
*/
-typedef struct {
+typedef struct listdesc {
int n;
int pc; /* 0 if last expression is closed */
} listdesc;
@@ -73,7 +87,7 @@ typedef struct {
** it is a list constructor (k = 0) or a record constructor (k = 1)
** or empty (k = ';' or '}')
*/
-typedef struct {
+typedef struct constdesc {
int n;
int k;
} constdesc;
@@ -88,16 +102,16 @@ typedef struct FuncState {
int maxstacksize; /* maximum number of values on activation register */
int nlocalvar; /* number of active local variables */
int nupvalues; /* number of upvalues */
- int nvars; /* number of entries in f->locvars */
- int maxcode; /* size of f->code */
- int maxvars; /* size of f->locvars (-1 if no debug information) */
- int maxconsts; /* size of f->consts */
+ int nvars; /* number of entries in f->locvars (-1 if no debug information) */
int lastsetline; /* line where last SETLINE was issued */
vardesc upvalues[MAXUPVALUES]; /* upvalues */
TaggedString *localvar[MAXLOCALS]; /* store local variable names */
} FuncState;
+/*
+** prototypes for non-terminal functions
+*/
static int assignment (LexState *ls, vardesc *v, int nvars);
static int cond (LexState *ls);
static int funcname (LexState *ls, vardesc *v);
@@ -117,22 +131,28 @@ static void exp1 (LexState *ls);
static void exp2 (LexState *ls, vardesc *v);
static void explist (LexState *ls, listdesc *e);
static void explist1 (LexState *ls, listdesc *e);
-static void ifpart (LexState *ls);
+static void ifpart (LexState *ls, int line);
static void parlist (LexState *ls);
static void part (LexState *ls, constdesc *cd);
static void recfield (LexState *ls);
static void ret (LexState *ls);
-static void simpleexp (LexState *ls, vardesc *v);
static void statlist (LexState *ls);
static void var_or_func (LexState *ls, vardesc *v);
static void var_or_func_tail (LexState *ls, vardesc *v);
+static void checklimit (LexState *ls, int val, int limit, char *msg) {
+ if (val > limit) {
+ char buff[100];
+ sprintf(buff, "too many %s (limit=%d)", msg, limit);
+ luaX_error(ls, buff);
+ }
+}
+
+
static void check_pc (FuncState *fs, int n) {
- if (fs->pc+n > fs->maxcode)
- fs->maxcode = luaM_growvector(&fs->f->code, fs->maxcode,
- Byte, codeEM, MAX_INT);
+ luaM_growvector(fs->f->code, fs->pc, n, Byte, codeEM, MAX_INT);
}
@@ -146,76 +166,79 @@ static void deltastack (LexState *ls, int delta) {
FuncState *fs = ls->fs;
fs->stacksize += delta;
if (fs->stacksize > fs->maxstacksize) {
- if (fs->stacksize > 255)
+ if (fs->stacksize > MAX_BYTE)
luaX_error(ls, "function/expression too complex");
fs->maxstacksize = fs->stacksize;
}
}
-static int code_oparg_at (LexState *ls, int pc, OpCode op, int builtin,
- int arg, int delta) {
+static void code_oparg_at (LexState *ls, int pc, OpCode op,
+ int arg, int delta) {
Byte *code = ls->fs->f->code;
deltastack(ls, delta);
- if (arg < builtin) {
- code[pc] = op+1+arg;
- return 1;
+ if (arg <= MAX_BYTE) {
+ code[pc] = (Byte)op;
+ code[pc+1] = (Byte)arg;
}
- else if (arg <= 255) {
- code[pc] = op;
- code[pc+1] = arg;
- return 2;
- }
- else if (arg <= MAX_WORD) {
- code[pc] = op+1+builtin;
- code[pc+1] = arg>>8;
- code[pc+2] = arg&0xFF;
- return 3;
+ else if (arg > MAX_ARG)
+ luaX_error(ls, "code too long");
+ else { /* MAX_BYTE < arg < MAX_ARG */
+ if (arg > MAX_WORD) {
+ code[pc] = (Byte)LONGARG;
+ code[pc+1] = (Byte)(arg>>16);
+ pc += 2;
+ }
+ code[pc] = (Byte)(op-1); /* opcode for word argument */
+ code[pc+1] = (Byte)((arg&0xFFFF)>>8);
+ code[pc+2] = (Byte)(arg&0xFF);
}
- else luaX_error(ls, "code too long " MES_LIM("64K"));
- return 0; /* to avoid warnings */
}
-static int fix_opcode (LexState *ls, int pc, OpCode op, int builtin, int arg) {
- FuncState *fs = ls->fs;
- TProtoFunc *f = fs->f;
- if (arg < builtin) { /* close space */
- luaO_memdown(f->code+pc+1, f->code+pc+2, fs->pc-(pc+2));
- fs->pc--;
- }
- else if (arg > 255) { /* open space */
- check_pc(fs, 1);
- luaO_memup(f->code+pc+1, f->code+pc, fs->pc-pc);
- fs->pc++;
+static int codesize (int arg) {
+ if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */
+ else if (arg <= MAX_WORD) return 3; /* opcode + 1 word (2 bytes) */
+ else return 5; /* LONGARG + 1 byte + opcode + 1 word (2 bytes) */
+}
+
+
+static int fix_opcode (LexState *ls, int pc, OpCode op, int arg) {
+ int tomove = codesize(arg)-2;
+ if (tomove > 0) { /* need to open space? */
+ FuncState *fs = ls->fs;
+ TProtoFunc *f = fs->f;
+ check_pc(fs, tomove);
+ luaO_memup(f->code+pc+tomove, f->code+pc, fs->pc-pc);
+ fs->pc += tomove;
}
- return code_oparg_at(ls, pc, op, builtin, arg, 0) - 2;
+ code_oparg_at(ls, pc, op, arg, 0);
+ return tomove;
}
-static void code_oparg (LexState *ls, OpCode op, int builtin, int arg,
- int delta) {
- check_pc(ls->fs, 3); /* maximum code size */
- ls->fs->pc += code_oparg_at(ls, ls->fs->pc, op, builtin, arg, delta);
+
+static void code_oparg (LexState *ls, OpCode op, int arg, int delta) {
+ int size = codesize(arg);
+ check_pc(ls->fs, size);
+ code_oparg_at(ls, ls->fs->pc, op, arg, delta);
+ ls->fs->pc += size;
}
static void code_opcode (LexState *ls, OpCode op, int delta) {
deltastack(ls, delta);
- code_byte(ls->fs, op);
+ code_byte(ls->fs, (Byte)op);
}
static void code_constant (LexState *ls, int c) {
- code_oparg(ls, PUSHCONSTANT, 8, c, 1);
+ code_oparg(ls, PUSHCONSTANT, c, 1);
}
static int next_constant (FuncState *fs) {
TProtoFunc *f = fs->f;
- if (f->nconsts >= fs->maxconsts) {
- fs->maxconsts = luaM_growvector(&f->consts, fs->maxconsts, TObject,
- constantEM, MAX_WORD);
- }
+ luaM_growvector(f->consts, f->nconsts, 1, TObject, constantEM, MAX_ARG);
return f->nconsts++;
}
@@ -249,9 +272,9 @@ static int real_constant (FuncState *fs, real r) {
if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r)
return c;
}
- /* not found; create a luaM_new entry */
+ /* not found; create a new entry */
c = next_constant(fs);
- cnt = fs->f->consts; /* 'next_constant' may reallocate this vector */
+ cnt = fs->f->consts; /* 'next_constant' may have reallocated this vector */
ttype(&cnt[c]) = LUA_T_NUMBER;
nvalue(&cnt[c]) = r;
return c;
@@ -259,9 +282,11 @@ static int real_constant (FuncState *fs, real r) {
static void code_number (LexState *ls, real f) {
- int i;
- if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f)
- code_oparg(ls, PUSHNUMBER, 3, i, 1); /* f has a short integer value */
+ real af = (f<0) ? -f : f;
+ if (0 <= af && af <= (real)MAX_WORD && (int)af == af) {
+ /* abs(f) has a short integer value */
+ code_oparg(ls, (f<0) ? PUSHNUMBERNEG : PUSHNUMBER, (int)af, 1);
+ }
else
code_constant(ls, real_constant(ls->fs, f));
}
@@ -269,24 +294,23 @@ static void code_number (LexState *ls, real f) {
static void flush_record (LexState *ls, int n) {
if (n > 0)
- code_oparg(ls, SETMAP, 1, n-1, -2*n);
+ code_oparg(ls, SETMAP, n-1, -2*n);
}
static void flush_list (LexState *ls, int m, int n) {
- if (n == 0) return;
- code_oparg(ls, SETLIST, 1, m, -n);
- code_byte(ls->fs, n);
+ if (n > 0) {
+ code_oparg(ls, SETLIST, m, -n);
+ code_byte(ls->fs, (Byte)n);
+ }
}
static void luaI_registerlocalvar (FuncState *fs, TaggedString *varname,
int line) {
- if (fs->maxvars != -1) { /* debug information? */
+ if (fs->nvars != -1) { /* debug information? */
TProtoFunc *f = fs->f;
- if (fs->nvars >= fs->maxvars)
- fs->maxvars = luaM_growvector(&f->locvars, fs->maxvars,
- LocVar, "", MAX_WORD);
+ luaM_growvector(f->locvars, fs->nvars, 1, LocVar, "", MAX_INT);
f->locvars[fs->nvars].varname = varname;
f->locvars[fs->nvars].line = line;
fs->nvars++;
@@ -301,10 +325,8 @@ static void luaI_unregisterlocalvar (FuncState *fs, int line) {
static void store_localvar (LexState *ls, TaggedString *name, int n) {
FuncState *fs = ls->fs;
- if (fs->nlocalvar+n < MAXLOCALS)
- fs->localvar[fs->nlocalvar+n] = name;
- else
- luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS));
+ checklimit(ls, fs->nlocalvar+n+1, MAXLOCALS, "local variables");
+ fs->localvar[fs->nlocalvar+n] = name;
luaI_registerlocalvar(fs, name, ls->linenumber);
}
@@ -315,6 +337,16 @@ static void add_localvar (LexState *ls, TaggedString *name) {
}
+static void correctvarlines (LexState *ls, int nvars) {
+ FuncState *fs = ls->fs;
+ if (fs->nvars != -1) { /* debug information? */
+ for (; nvars; nvars--) { /* correct line information */
+ fs->f->locvars[fs->nvars-nvars].line = fs->lastsetline;
+ }
+ }
+}
+
+
static int aux_localname (FuncState *fs, TaggedString *n) {
int i;
for (i=fs->nlocalvar-1; i >= 0; i--)
@@ -326,13 +358,13 @@ static int aux_localname (FuncState *fs, TaggedString *n) {
static void singlevar (LexState *ls, TaggedString *n, vardesc *var, int prev) {
FuncState *fs = prev ? ls->fs->prev : ls->fs;
int i = aux_localname(fs, n);
- if (i >= 0) { /* local value */
+ if (i >= 0) { /* local value? */
var->k = VLOCAL;
var->info = i;
}
- else { /* check shadowing */
+ else {
FuncState *level = fs;
- while ((level = level->prev) != NULL)
+ while ((level = level->prev) != NULL) /* check shadowing */
if (aux_localname(level, n) >= 0)
luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str);
var->k = VGLOBAL;
@@ -351,29 +383,26 @@ static int indexupvalue (LexState *ls, TaggedString *n) {
return i;
}
/* new one */
- if (++(fs->nupvalues) > MAXUPVALUES)
- luaX_error(ls, "too many upvalues in a single function "
- MES_LIM(SMAXUPVALUES));
+ ++(fs->nupvalues);
+ checklimit(ls, fs->nupvalues, MAXUPVALUES, "upvalues");
fs->upvalues[i] = v; /* i = fs->nupvalues - 1 */
return i;
}
static void pushupvalue (LexState *ls, TaggedString *n) {
- int i;
if (ls->fs->prev == NULL)
luaX_syntaxerror(ls, "cannot access upvalue in main", n->str);
if (aux_localname(ls->fs, n) >= 0)
luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str);
- i = indexupvalue(ls, n);
- code_oparg(ls, PUSHUPVALUE, 2, i, 1);
+ code_oparg(ls, PUSHUPVALUE, indexupvalue(ls, n), 1);
}
static void check_debugline (LexState *ls) {
- if (lua_debug && ls->linenumber != ls->fs->lastsetline) {
- code_oparg(ls, SETLINE, 0, ls->linenumber, 0);
+ if (L->debug && ls->linenumber != ls->fs->lastsetline) {
+ code_oparg(ls, SETLINE, ls->linenumber, 0);
ls->fs->lastsetline = ls->linenumber;
}
}
@@ -381,22 +410,22 @@ static void check_debugline (LexState *ls) {
static void adjuststack (LexState *ls, int n) {
if (n > 0)
- code_oparg(ls, POP, 2, n-1, -n);
+ code_oparg(ls, POP, n, -n);
else if (n < 0)
- code_oparg(ls, PUSHNIL, 1, (-n)-1, -n);
+ code_oparg(ls, PUSHNIL, (-n)-1, -n);
}
static void close_exp (LexState *ls, int pc, int nresults) {
- if (pc > 0) { /* expression is an open function call */
+ if (pc > 0) { /* expression is an open function call? */
Byte *code = ls->fs->f->code;
- int nparams = code[pc]; /* save nparams */
- pc += fix_opcode(ls, pc-2, CALLFUNC, 2, nresults);
- code[pc] = nparams; /* restore nparams */
- if (nresults != MULT_RET)
- deltastack(ls, nresults); /* "push" results */
- deltastack(ls, -(nparams+1)); /* "pop" params and function */
+ code[pc-1] = (Byte)nresults; /* set nresults */
+ /* push results, pop params (at code[pc]) and function */
+ deltastack(ls, nresults-(code[pc]+1));
}
+#ifdef DEBUG
+ code_oparg(ls, CHECKSTACK, ls->fs->stacksize, 0);
+#endif
}
@@ -408,7 +437,7 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) {
}
else { /* must correct function call */
diff--; /* do not count function call itself */
- if (diff < 0) { /* more variables than values */
+ if (diff <= 0) { /* more variables than values? */
/* function call must provide extra values */
close_exp(ls, d->pc, -diff);
}
@@ -423,29 +452,39 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) {
static void code_args (LexState *ls, int nparams, int dots) {
FuncState *fs = ls->fs;
fs->nlocalvar += nparams; /* "self" may already be there */
+ checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters");
nparams = fs->nlocalvar;
if (!dots) {
- fs->f->code[1] = nparams; /* fill-in arg information */
+ fs->f->code[1] = (Byte)nparams; /* fill-in arg information */
deltastack(ls, nparams);
}
else {
- fs->f->code[1] = nparams+ZEROVARARG;
+ fs->f->code[1] = (Byte)(nparams+ZEROVARARG);
deltastack(ls, nparams+1);
add_localvar(ls, luaS_new("arg"));
}
}
+static void unloaddot (LexState *ls, vardesc *v) {
+ /* dotted variables <a.x> must be stored like regular indexed vars <a["x"]> */
+ if (v->k == VDOT) {
+ code_constant(ls, v->info);
+ v->k = VINDEXED;
+ }
+}
+
+
static void lua_pushvar (LexState *ls, vardesc *var) {
switch (var->k) {
case VLOCAL:
- code_oparg(ls, PUSHLOCAL, 8, var->info, 1);
+ code_oparg(ls, PUSHLOCAL, var->info, 1);
break;
case VGLOBAL:
- code_oparg(ls, GETGLOBAL, 8, var->info, 1);
+ code_oparg(ls, GETGLOBAL, var->info, 1);
break;
case VDOT:
- code_oparg(ls, GETDOTTED, 8, var->info, 0);
+ code_oparg(ls, GETDOTTED, var->info, 0);
break;
case VINDEXED:
code_opcode(ls, GETTABLE, -1);
@@ -462,13 +501,13 @@ static void lua_pushvar (LexState *ls, vardesc *var) {
static void storevar (LexState *ls, vardesc *var) {
switch (var->k) {
case VLOCAL:
- code_oparg(ls, SETLOCAL, 8, var->info, -1);
+ code_oparg(ls, SETLOCAL, var->info, -1);
break;
case VGLOBAL:
- code_oparg(ls, SETGLOBAL, 8, var->info, -1);
+ code_oparg(ls, SETGLOBAL, var->info, -1);
break;
case VINDEXED:
- code_opcode(ls, SETTABLE0, -3);
+ code_opcode(ls, SETTABLEPOP, -3);
break;
default:
LUA_INTERNALERROR("invalid var kind to store");
@@ -478,21 +517,20 @@ static void storevar (LexState *ls, vardesc *var) {
static int fix_jump (LexState *ls, int pc, OpCode op, int n) {
/* jump is relative to position following jump instruction */
- return fix_opcode(ls, pc, op, 0, n-(pc+JMPSIZE));
+ return fix_opcode(ls, pc, op, n-(pc+JMPSIZE));
}
static void fix_upjmp (LexState *ls, OpCode op, int pos) {
int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */
- if (delta > 255) delta++;
- code_oparg(ls, op, 0, delta, 0);
+ code_oparg(ls, op, delta+(codesize(delta)-2), 0);
}
static void codeIf (LexState *ls, int thenAdd, int elseAdd) {
FuncState *fs = ls->fs;
int elseinit = elseAdd+JMPSIZE;
- if (fs->pc == elseinit) { /* no else part */
+ if (fs->pc == elseinit) { /* no else part? */
fs->pc -= JMPSIZE;
elseinit = fs->pc;
}
@@ -513,13 +551,14 @@ static void func_onstack (LexState *ls, FuncState *func) {
else {
for (i=0; i<func->nupvalues; i++)
lua_pushvar(ls, &func->upvalues[i]);
- code_oparg(ls, CLOSURE, 0, c, -func->nupvalues+1);
- code_byte(fs, func->nupvalues);
+ deltastack(ls, 1); /* CLOSURE puts one extra element (before poping) */
+ code_oparg(ls, CLOSURE, c, -func->nupvalues);
+ code_byte(fs, (Byte)func->nupvalues);
}
}
-static void init_state (LexState *ls, FuncState *fs, TaggedString *filename) {
+static void init_state (LexState *ls, FuncState *fs, TaggedString *source) {
TProtoFunc *f = luaF_newproto();
fs->prev = ls->fs; /* linked list of funcstates */
ls->fs = fs;
@@ -529,17 +568,15 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *filename) {
fs->nupvalues = 0;
fs->lastsetline = 0;
fs->f = f;
- f->fileName = filename;
+ f->source = source;
fs->pc = 0;
- fs->maxcode = 0;
f->code = NULL;
- fs->maxconsts = 0;
- if (lua_debug)
- fs->nvars = fs->maxvars = 0;
- else
- fs->maxvars = -1; /* flag no debug information */
- code_byte(fs, 0); /* to be filled with stacksize */
+ fs->nvars = (L->debug) ? 0 : -1; /* flag no debug information? */
+ code_byte(fs, 0); /* to be filled with maxstacksize */
code_byte(fs, 0); /* to be filled with arg information */
+ /* push function (to avoid GC) */
+ tfvalue(L->stack.top) = f; ttype(L->stack.top) = LUA_T_PROTO;
+ incr_top;
}
@@ -547,14 +584,15 @@ static void close_func (LexState *ls) {
FuncState *fs = ls->fs;
TProtoFunc *f = fs->f;
code_opcode(ls, ENDCODE, 0);
- f->code[0] = fs->maxstacksize;
- f->code = luaM_reallocvector(f->code, fs->pc, Byte);
- f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject);
- if (fs->maxvars != -1) { /* debug information? */
+ f->code[0] = (Byte)fs->maxstacksize;
+ luaM_reallocvector(f->code, fs->pc, Byte);
+ luaM_reallocvector(f->consts, f->nconsts, TObject);
+ if (fs->nvars != -1) { /* debug information? */
luaI_registerlocalvar(fs, NULL, -1); /* flag end of vector */
- f->locvars = luaM_reallocvector(f->locvars, fs->nvars, LocVar);
+ luaM_reallocvector(f->locvars, fs->nvars, LocVar);
}
ls->fs = fs->prev;
+ L->stack.top--; /* pop function */
}
@@ -562,13 +600,11 @@ static void close_func (LexState *ls) {
static int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, DO, NAME,
LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', EOS, ',', 0};
+
static int is_in (int tok, int *toks) {
- int *t = toks;
- while (*t) {
- if (*t == tok)
- return t-toks;
- t++;
- }
+ int *t;
+ for (t=toks; *t; t++)
+ if (*t == tok) return t-toks;
return -1;
}
@@ -580,19 +616,25 @@ static void next (LexState *ls) {
static void error_expected (LexState *ls, int token) {
char buff[100], t[TOKEN_LEN];
- luaX_token2str(ls, token, t);
+ luaX_token2str(token, t);
sprintf(buff, "`%s' expected", t);
luaX_error(ls, buff);
}
+
+static void error_unexpected (LexState *ls) {
+ luaX_error(ls, "unexpected token");
+}
+
+
static void error_unmatched (LexState *ls, int what, int who, int where) {
if (where == ls->linenumber)
error_expected(ls, what);
else {
char buff[100];
char t_what[TOKEN_LEN], t_who[TOKEN_LEN];
- luaX_token2str(ls, what, t_what);
- luaX_token2str(ls, who, t_who);
+ luaX_token2str(what, t_what);
+ luaX_token2str(who, t_who);
sprintf(buff, "`%s' expected (to close `%s' at line %d)",
t_what, t_who, where);
luaX_error(ls, buff);
@@ -612,13 +654,18 @@ static void check_match (LexState *ls, int what, int who, int where) {
next(ls);
}
-static TaggedString *checkname (LexState *ls) {
- TaggedString *ts;
+static int checkname (LexState *ls) {
+ int sc;
if (ls->token != NAME)
luaX_error(ls, "`NAME' expected");
- ts = ls->seminfo.ts;
+ sc = string_constant(ls->fs, ls->seminfo.ts);
next(ls);
- return ts;
+ return sc;
+}
+
+
+static TaggedString *str_checkname (LexState *ls) {
+ return tsvalue(&ls->fs->f->consts[checkname(ls)]);
}
@@ -669,12 +716,9 @@ static int stat (LexState *ls) {
int line = ls->linenumber; /* may be needed for error messages */
FuncState *fs = ls->fs;
switch (ls->token) {
- case IF: { /* stat -> IF ifpart END */
- next(ls);
- ifpart(ls);
- check_match(ls, END, IF, line);
+ case IF: /* stat -> IF ifpart END */
+ ifpart(ls, line);
return 1;
- }
case WHILE: { /* stat -> WHILE cond DO block END */
TProtoFunc *f = fs->f;
@@ -732,7 +776,8 @@ static int stat (LexState *ls) {
next(ls);
nvars = localnamelist(ls);
decinit(ls, &d);
- ls->fs->nlocalvar += nvars;
+ fs->nlocalvar += nvars;
+ correctvarlines(ls, nvars); /* vars will be alive only after decinit */
adjust_mult_assign(ls, nvars, &d);
return 1;
}
@@ -746,8 +791,8 @@ static int stat (LexState *ls) {
luaX_error(ls, "syntax error");
close_exp(ls, v.info, 0);
}
- else {
- int left = assignment(ls, &v, 1); /* stat -> ['%'] NAME assignment */
+ else { /* stat -> ['%'] NAME assignment */
+ int left = assignment(ls, &v, 1);
adjuststack(ls, left); /* remove eventual 'garbage' left on stack */
}
return 1;
@@ -758,7 +803,7 @@ static int stat (LexState *ls) {
return 0;
default:
- luaX_error(ls, "<statement> expected");
+ error_unexpected(ls);
return 0; /* to avoid warnings */
}
}
@@ -788,18 +833,18 @@ static void block (LexState *ls) {
chunk(ls);
adjuststack(ls, fs->nlocalvar - nlocalvar);
for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--)
- luaI_unregisterlocalvar(fs, ls->linenumber);
+ luaI_unregisterlocalvar(fs, fs->lastsetline);
}
static int funcname (LexState *ls, vardesc *v) {
/* funcname -> NAME [':' NAME | '.' NAME] */
int needself = 0;
- singlevar(ls, checkname(ls), v, 0);
+ singlevar(ls, str_checkname(ls), v, 0);
if (ls->token == ':' || ls->token == '.') {
needself = (ls->token == ':');
next(ls);
lua_pushvar(ls, v);
- code_string(ls, checkname(ls));
+ code_constant(ls, checkname(ls));
v->k = VINDEXED;
}
return needself;
@@ -808,7 +853,7 @@ static int funcname (LexState *ls, vardesc *v) {
static void body (LexState *ls, int needself, int line) {
/* body -> '(' parlist ')' chunk END */
FuncState newfs;
- init_state(ls, &newfs, ls->fs->f->fileName);
+ init_state(ls, &newfs, ls->fs->f->source);
newfs.f->lineDefined = line;
check(ls, '(');
if (needself)
@@ -821,36 +866,40 @@ static void body (LexState *ls, int needself, int line) {
func_onstack(ls, &newfs);
}
-static void ifpart (LexState *ls) {
+
+static void ifpart (LexState *ls, int line) {
/* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */
- int c = cond(ls);
+ int c;
int e;
+ next(ls); /* skip IF or ELSEIF */
+ c = cond(ls);
check(ls, THEN);
block(ls);
e = SaveWord(ls);
- switch (ls->token) {
- case ELSE:
- next(ls);
+ if (ls->token == ELSEIF)
+ ifpart(ls, line);
+ else {
+ if (optional(ls, ELSE))
block(ls);
- break;
-
- case ELSEIF:
- next(ls);
- ifpart(ls);
- break;
+ check_match(ls, END, IF, line);
}
codeIf(ls, c, e);
}
+
static void ret (LexState *ls) {
/* ret -> [RETURN explist sc] */
- if (ls->token == RETURN) {
+ if (optional(ls, RETURN)) {
listdesc e;
check_debugline(ls);
- next(ls);
- explist(ls, &e);
- close_exp(ls, e.pc, MULT_RET);
- code_oparg(ls, RETCODE, 0, ls->fs->nlocalvar, 0);
+ explist(ls, &e);
+ if (e.pc > 0) { /* expression is an open function call? */
+ Byte *code = ls->fs->f->code;
+ code[e.pc-2] = TAILCALL; /* instead of a conventional CALL */
+ code[e.pc-1] = (Byte)ls->fs->nlocalvar;
+ }
+ else
+ code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0);
ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */
optional(ls, ';');
}
@@ -863,6 +912,9 @@ static void ret (LexState *ls) {
** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1.
*/
+#define INDNOT 0
+#define INDMINUS 1
+
/* code of first binary operator */
#define FIRSTBIN 2
@@ -879,9 +931,9 @@ static int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6};
static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP,
LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP};
-#define MAXOPS 20
+#define MAXOPS 20 /* op's stack size (arbitrary limit) */
-typedef struct {
+typedef struct stack_op {
int ops[MAXOPS];
int top;
} stack_op;
@@ -892,39 +944,33 @@ static void exp1 (LexState *ls) {
exp0(ls, &v);
lua_pushvar(ls, &v);
if (is_in(ls->token, expfollow) < 0)
- luaX_error(ls, "ill formed expression");
+ luaX_error(ls, "ill-formed expression");
}
static void exp0 (LexState *ls, vardesc *v) {
+ /* exp0 -> exp2 {(AND | OR) exp2} */
exp2(ls, v);
while (ls->token == AND || ls->token == OR) {
- int is_and = (ls->token == AND);
+ int op = (ls->token == AND) ? ONFJMP : ONTJMP;
int pc;
lua_pushvar(ls, v);
next(ls);
pc = SaveWordPop(ls);
exp2(ls, v);
lua_pushvar(ls, v);
- fix_jump(ls, pc, (is_and?ONFJMP:ONTJMP), ls->fs->pc);
+ fix_jump(ls, pc, op, ls->fs->pc);
}
}
static void push (LexState *ls, stack_op *s, int op) {
- if (s->top == MAXOPS)
+ if (s->top >= MAXOPS)
luaX_error(ls, "expression too complex");
s->ops[s->top++] = op;
}
-static void prefix (LexState *ls, stack_op *s) {
- while (ls->token == NOT || ls->token == '-') {
- push(ls, s, ls->token==NOT?0:1);
- next(ls);
- }
-}
-
static void pop_to (LexState *ls, stack_op *s, int prio) {
int op;
while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) {
@@ -933,92 +979,104 @@ static void pop_to (LexState *ls, stack_op *s, int prio) {
}
}
-static void exp2 (LexState *ls, vardesc *v) {
- stack_op s;
- int op;
- s.top = 0;
- prefix(ls, &s);
- simpleexp(ls, v);
- while ((op = is_in(ls->token, binop)) >= 0) {
- op += FIRSTBIN;
- lua_pushvar(ls, v);
- /* '^' is right associative, so must 'simulate' a higher priority */
- pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]);
- push(ls, &s, op);
- next(ls);
- prefix(ls, &s);
- simpleexp(ls, v);
- lua_pushvar(ls, v);
- }
- if (s.top > 0) {
- lua_pushvar(ls, v);
- pop_to(ls, &s, 0);
- }
-}
-
-
-static void simpleexp (LexState *ls, vardesc *v) {
+static void simpleexp (LexState *ls, vardesc *v, stack_op *s) {
check_debugline(ls);
switch (ls->token) {
- case '(': /* simpleexp -> '(' exp0 ')' */
- next(ls);
- exp0(ls, v);
- check(ls, ')');
- break;
-
- case NUMBER: /* simpleexp -> NUMBER */
- code_number(ls, ls->seminfo.r);
+ case NUMBER: { /* simpleexp -> NUMBER */
+ real r = ls->seminfo.r;
next(ls);
- v->k = VEXP; v->info = 0;
+ /* dirty trick: check whether it is a -NUMBER not followed by '^' */
+ /* (because the priority of '^' is closer than '-'...) */
+ if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') {
+ s->top--; /* remove '-' from stack */
+ r = -r;
+ }
+ code_number(ls, r);
break;
+ }
case STRING: /* simpleexp -> STRING */
- code_string(ls, ls->seminfo.ts);
+ code_string(ls, ls->seminfo.ts); /* must use 'seminfo' before "next" */
next(ls);
- v->k = VEXP; v->info = 0;
break;
case NIL: /* simpleexp -> NIL */
adjuststack(ls, -1);
next(ls);
- v->k = VEXP; v->info = 0;
break;
case '{': /* simpleexp -> constructor */
constructor(ls);
- v->k = VEXP; v->info = 0;
break;
- case FUNCTION: { /* simpleexp -> FUNCTION body */
- int line = ls->linenumber;
+ case FUNCTION: /* simpleexp -> FUNCTION body */
next(ls);
- body(ls, 0, line);
- v->k = VEXP; v->info = 0;
+ body(ls, 0, ls->linenumber);
break;
- }
+
+ case '(': /* simpleexp -> '(' exp0 ')' */
+ next(ls);
+ exp0(ls, v);
+ check(ls, ')');
+ return;
case NAME: case '%':
var_or_func(ls, v);
- break;
+ return;
default:
luaX_error(ls, "<expression> expected");
- break;
+ return;
+ }
+ v->k = VEXP; v->info = 0;
+}
+
+
+static void prefixexp (LexState *ls, vardesc *v, stack_op *s) {
+ /* prefixexp -> {NOT | '-'} simpleexp */
+ while (ls->token == NOT || ls->token == '-') {
+ push(ls, s, (ls->token==NOT)?INDNOT:INDMINUS);
+ next(ls);
+ }
+ simpleexp(ls, v, s);
+}
+
+
+static void exp2 (LexState *ls, vardesc *v) {
+ stack_op s;
+ int op;
+ s.top = 0;
+ prefixexp(ls, v, &s);
+ while ((op = is_in(ls->token, binop)) >= 0) {
+ op += FIRSTBIN;
+ lua_pushvar(ls, v);
+ /* '^' is right associative, so must 'simulate' a higher priority */
+ pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]);
+ push(ls, &s, op);
+ next(ls);
+ prefixexp(ls, v, &s);
+ lua_pushvar(ls, v);
+ }
+ if (s.top > 0) {
+ lua_pushvar(ls, v);
+ pop_to(ls, &s, 0);
}
}
+
static void var_or_func (LexState *ls, vardesc *v) {
/* var_or_func -> ['%'] NAME var_or_func_tail */
if (optional(ls, '%')) { /* upvalue? */
- pushupvalue(ls, checkname(ls));
+ pushupvalue(ls, str_checkname(ls));
v->k = VEXP;
v->info = 0; /* closed expression */
}
else /* variable name */
- singlevar(ls, checkname(ls), v, 0);
+ singlevar(ls, str_checkname(ls), v, 0);
var_or_func_tail(ls, v);
}
+
static void var_or_func_tail (LexState *ls, vardesc *v) {
for (;;) {
switch (ls->token) {
@@ -1026,7 +1084,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) {
next(ls);
lua_pushvar(ls, v); /* 'v' must be on stack */
v->k = VDOT;
- v->info = string_constant(ls->fs, checkname(ls));
+ v->info = checkname(ls);
break;
case '[': /* var_or_func_tail -> '[' exp1 ']' */
@@ -1040,7 +1098,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) {
case ':': /* var_or_func_tail -> ':' NAME funcparams */
next(ls);
lua_pushvar(ls, v); /* 'v' must be on stack */
- code_oparg(ls, PUSHSELF, 8, string_constant(ls->fs, checkname(ls)), 1);
+ code_oparg(ls, PUSHSELF, checkname(ls), 1);
v->k = VEXP;
v->info = funcparams(ls, 1);
break;
@@ -1058,13 +1116,14 @@ static void var_or_func_tail (LexState *ls, vardesc *v) {
static int funcparams (LexState *ls, int slf) {
FuncState *fs = ls->fs;
- int nparams = 1; /* default value */
+ int nparams = 1; /* in cases STRING and constructor */
switch (ls->token) {
case '(': { /* funcparams -> '(' explist ')' */
+ int line = ls->linenumber;
listdesc e;
next(ls);
explist(ls, &e);
- check(ls, ')');
+ check_match(ls, ')', '(', line);
close_exp(ls, e.pc, 1);
nparams = e.n;
break;
@@ -1075,7 +1134,7 @@ static int funcparams (LexState *ls, int slf) {
break;
case STRING: /* funcparams -> STRING */
- code_string(ls, ls->seminfo.ts);
+ code_string(ls, ls->seminfo.ts); /* must use 'seminfo' before "next" */
next(ls);
break;
@@ -1083,9 +1142,9 @@ static int funcparams (LexState *ls, int slf) {
luaX_error(ls, "function arguments expected");
break;
}
- code_byte(fs, 0); /* save space for opcode */
- code_byte(fs, 0); /* and nresult */
- code_byte(fs, nparams+slf);
+ code_byte(fs, CALL);
+ code_byte(fs, 0); /* save space for nresult */
+ code_byte(fs, (Byte)(nparams+slf));
return fs->pc-1;
}
@@ -1131,7 +1190,7 @@ static void parlist (LexState *ls) {
case NAME: /* parlist, tailparlist -> NAME [',' tailparlist] */
init:
- store_localvar(ls, checkname(ls), nparams++);
+ store_localvar(ls, str_checkname(ls), nparams++);
if (ls->token == ',') {
next(ls);
switch (ls->token) {
@@ -1158,10 +1217,10 @@ static void parlist (LexState *ls) {
static int localnamelist (LexState *ls) {
/* localnamelist -> NAME {',' NAME} */
int i = 1;
- store_localvar(ls, checkname(ls), 0);
+ store_localvar(ls, str_checkname(ls), 0);
while (ls->token == ',') {
next(ls);
- store_localvar(ls, checkname(ls), i++);
+ store_localvar(ls, str_checkname(ls), i++);
}
return i;
}
@@ -1178,13 +1237,11 @@ static void decinit (LexState *ls, listdesc *d) {
}
}
+
static int assignment (LexState *ls, vardesc *v, int nvars) {
int left = 0;
- /* dotted variables <a.x> must be stored like regular indexed vars <a["x"]> */
- if (v->k == VDOT) {
- code_constant(ls, v->info);
- v->k = VINDEXED;
- }
+ checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment");
+ unloaddot(ls, v);
if (ls->token == ',') { /* assignment -> ',' NAME assignment */
vardesc nv;
next(ls);
@@ -1204,12 +1261,13 @@ static int assignment (LexState *ls, vardesc *v, int nvars) {
storevar(ls, v);
}
else { /* indexed var with values in between*/
- code_oparg(ls, SETTABLE, 0, left+(nvars-1), -1);
- left += 2; /* table/index are not popped, because they aren't on top */
+ code_oparg(ls, SETTABLE, left+(nvars-1), -1);
+ left += 2; /* table&index are not popped, because they aren't on top */
}
return left;
}
+
static void constructor (LexState *ls) {
/* constructor -> '{' part [';' part] '}' */
int line = ls->linenumber;
@@ -1229,7 +1287,7 @@ static void constructor (LexState *ls) {
nelems += other_cd.n;
}
check_match(ls, '}', '{', line);
- fix_opcode(ls, pc, CREATEARRAY, 2, nelems);
+ fix_opcode(ls, pc, CREATEARRAY, nelems);
}
static void part (LexState *ls, constdesc *cd) {
@@ -1251,7 +1309,7 @@ static void part (LexState *ls, constdesc *cd) {
code_string(ls, ls->fs->localvar[v.info]);
break;
default:
- luaX_error(ls, "`=' unexpected");
+ error_unexpected(ls);
}
next(ls);
exp1(ls);
@@ -1316,7 +1374,7 @@ static void recfield (LexState *ls) {
/* recfield -> (NAME | '['exp1']') = exp1 */
switch (ls->token) {
case NAME:
- code_string(ls, checkname(ls));
+ code_constant(ls, checkname(ls));
break;
case '[':