mirror of https://github.com/rusefi/lua.git
new opcode for "long" arguments (3 bytes)
This commit is contained in:
parent
80001ab0eb
commit
cbc58af260
32
lopcodes.h
32
lopcodes.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lopcodes.h,v 1.19 1999/02/02 17:57:49 roberto Exp roberto $
|
** $Id: lopcodes.h,v 1.20 1999/02/02 19:41:17 roberto Exp roberto $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -8,8 +8,6 @@
|
||||||
#define lopcodes_h
|
#define lopcodes_h
|
||||||
|
|
||||||
|
|
||||||
#define NUMOFFSET 100
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** NOTICE: variants of the same opcode must be consecutive: First, those
|
** NOTICE: variants of the same opcode must be consecutive: First, those
|
||||||
** with word parameter, then with byte parameter.
|
** with word parameter, then with byte parameter.
|
||||||
|
@ -100,14 +98,38 @@ CLOSURE,/* b c v_c...v_1 closure(CNST[b], v_c...v_1) */
|
||||||
CALLFUNC,/* b c v_c...v_1 f r_b...r_1 f(v1,...,v_c) */
|
CALLFUNC,/* b c v_c...v_1 f r_b...r_1 f(v1,...,v_c) */
|
||||||
|
|
||||||
SETLINEW,/* w - - LINE=w */
|
SETLINEW,/* w - - LINE=w */
|
||||||
SETLINE /* b - - LINE=b */
|
SETLINE,/* b - - LINE=b */
|
||||||
|
|
||||||
|
LONGARG /* b (add b*(1<<16) to arg of next instruction) */
|
||||||
|
|
||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
|
|
||||||
|
#define NUMOFFSET 100 /* offset for immediate numbers */
|
||||||
|
|
||||||
#define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */
|
#define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */
|
||||||
#define LFIELDS_PER_FLUSH 64 /* lists (SETLIST) */
|
#define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) */
|
||||||
|
|
||||||
#define ZEROVARARG 64
|
#define ZEROVARARG 64
|
||||||
|
|
||||||
|
|
||||||
|
/* maximum value of an arg of 3 bytes; must fit in an "int" */
|
||||||
|
#if MAX_INT < (1<<24)
|
||||||
|
#define MAX_ARG MAX_INT
|
||||||
|
#else
|
||||||
|
#define MAX_ARG ((1<<24)-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* maximum value of a word of 2 bytes; cannot be bigger than MAX_ARG */
|
||||||
|
#if MAX_ARG < (1<<16)
|
||||||
|
#define MAX_WORD MAX_ARG
|
||||||
|
#else
|
||||||
|
#define MAX_WORD ((1<<16)-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* maximum value of a byte */
|
||||||
|
#define MAX_BYTE ((1<<8)-1)
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
196
lparser.c
196
lparser.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lparser.c,v 1.13 1999/02/02 17:57:49 roberto Exp roberto $
|
** $Id: lparser.c,v 1.14 1999/02/02 19:41:17 roberto Exp roberto $
|
||||||
** LL(1) Parser and code generator for Lua
|
** LL(1) Parser and code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -99,6 +99,9 @@ typedef struct FuncState {
|
||||||
} FuncState;
|
} FuncState;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** prototypes for non-terminal functions
|
||||||
|
*/
|
||||||
static int assignment (LexState *ls, vardesc *v, int nvars);
|
static int assignment (LexState *ls, vardesc *v, int nvars);
|
||||||
static int cond (LexState *ls);
|
static int cond (LexState *ls);
|
||||||
static int funcname (LexState *ls, vardesc *v);
|
static int funcname (LexState *ls, vardesc *v);
|
||||||
|
@ -147,48 +150,61 @@ static void deltastack (LexState *ls, int delta) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
fs->stacksize += delta;
|
fs->stacksize += delta;
|
||||||
if (fs->stacksize > fs->maxstacksize) {
|
if (fs->stacksize > fs->maxstacksize) {
|
||||||
if (fs->stacksize > 255)
|
if (fs->stacksize > MAX_BYTE)
|
||||||
luaX_error(ls, "function/expression too complex");
|
luaX_error(ls, "function/expression too complex");
|
||||||
fs->maxstacksize = fs->stacksize;
|
fs->maxstacksize = fs->stacksize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int code_oparg_at (LexState *ls, int pc, OpCode op, 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;
|
Byte *code = ls->fs->f->code;
|
||||||
deltastack(ls, delta);
|
deltastack(ls, delta);
|
||||||
if (arg <= 255) {
|
if (arg <= MAX_BYTE) {
|
||||||
code[pc] = (Byte)op;
|
code[pc] = (Byte)op;
|
||||||
code[pc+1] = (Byte)arg;
|
code[pc+1] = (Byte)arg;
|
||||||
return 2; /* code size (opcode + 1 byte) */
|
|
||||||
}
|
}
|
||||||
else if (arg <= MAX_WORD) {
|
else if (arg <= MAX_WORD) {
|
||||||
code[pc] = (Byte)(op-1);
|
code[pc] = (Byte)(op-1); /* opcode for word argument */
|
||||||
code[pc+1] = (Byte)(arg>>8);
|
code[pc+1] = (Byte)(arg>>8);
|
||||||
code[pc+2] = (Byte)(arg&0xFF);
|
code[pc+2] = (Byte)(arg&0xFF);
|
||||||
return 3; /* code size (opcode + 1 word) */
|
|
||||||
}
|
}
|
||||||
else luaX_error(ls, "code too long " MES_LIM("64K")
|
else if (arg <= MAX_ARG) {
|
||||||
" (try turning off debug mode)");
|
code[pc] = (Byte)LONGARG;
|
||||||
return 0; /* to avoid warnings */
|
code[pc+1] = (Byte)(arg>>16);
|
||||||
|
code_oparg_at(ls, pc+2, op, arg&0xFFFF, 0);
|
||||||
|
}
|
||||||
|
else luaX_error(ls, "code too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int codesize (int arg) {
|
||||||
|
if (arg <= MAX_BYTE) return 2; /* opcode + 1 byte */
|
||||||
|
else if (arg <= MAX_WORD) return 3; /* opcode + 1 word */
|
||||||
|
else return 2+codesize(arg&0xFFFF); /* LONGARG + 1 byte + original opcode */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int fix_opcode (LexState *ls, int pc, OpCode op, int arg) {
|
static int fix_opcode (LexState *ls, int pc, OpCode op, int arg) {
|
||||||
FuncState *fs = ls->fs;
|
int tomove = codesize(arg)-2;
|
||||||
TProtoFunc *f = fs->f;
|
if (tomove > 0) { /* need to open space? */
|
||||||
if (arg > 255) { /* open space */
|
FuncState *fs = ls->fs;
|
||||||
check_pc(fs, 1);
|
TProtoFunc *f = fs->f;
|
||||||
luaO_memup(f->code+pc+1, f->code+pc, fs->pc-pc);
|
check_pc(fs, tomove);
|
||||||
fs->pc++;
|
luaO_memup(f->code+pc+tomove, f->code+pc, fs->pc-pc);
|
||||||
|
fs->pc += tomove;
|
||||||
}
|
}
|
||||||
return code_oparg_at(ls, pc, op, arg, 0) - 2;
|
code_oparg_at(ls, pc, op, arg, 0);
|
||||||
|
return tomove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void code_oparg (LexState *ls, OpCode op, int arg, int delta) {
|
static void code_oparg (LexState *ls, OpCode op, int arg, int delta) {
|
||||||
check_pc(ls->fs, 3); /* maximum code size */
|
int size = codesize(arg);
|
||||||
ls->fs->pc += code_oparg_at(ls, ls->fs->pc, op, arg, delta);
|
check_pc(ls->fs, size);
|
||||||
|
code_oparg_at(ls, ls->fs->pc, op, arg, delta);
|
||||||
|
ls->fs->pc += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,10 +221,9 @@ static void code_constant (LexState *ls, int c) {
|
||||||
|
|
||||||
static int next_constant (FuncState *fs) {
|
static int next_constant (FuncState *fs) {
|
||||||
TProtoFunc *f = fs->f;
|
TProtoFunc *f = fs->f;
|
||||||
if (f->nconsts >= fs->maxconsts) {
|
if (f->nconsts >= fs->maxconsts)
|
||||||
fs->maxconsts = luaM_growvector(&f->consts, fs->maxconsts, TObject,
|
fs->maxconsts = luaM_growvector(&f->consts, fs->maxconsts, TObject,
|
||||||
constantEM, MAX_WORD);
|
constantEM, MAX_ARG);
|
||||||
}
|
|
||||||
return f->nconsts++;
|
return f->nconsts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,9 +257,9 @@ static int real_constant (FuncState *fs, real r) {
|
||||||
if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r)
|
if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
/* not found; create a luaM_new entry */
|
/* not found; create a new entry */
|
||||||
c = next_constant(fs);
|
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;
|
ttype(&cnt[c]) = LUA_T_NUMBER;
|
||||||
nvalue(&cnt[c]) = r;
|
nvalue(&cnt[c]) = r;
|
||||||
return c;
|
return c;
|
||||||
|
@ -252,10 +267,9 @@ static int real_constant (FuncState *fs, real r) {
|
||||||
|
|
||||||
|
|
||||||
static void code_number (LexState *ls, real f) {
|
static void code_number (LexState *ls, real f) {
|
||||||
int i;
|
if (-NUMOFFSET <= f && f <= (real)(MAX_WORD-NUMOFFSET) &&
|
||||||
if (0 <= f+NUMOFFSET && f+NUMOFFSET <= (real)MAX_WORD &&
|
(int)f == f) /* f+NUMOFFSET has a short integer value? */
|
||||||
(real)(i=(int)f) == f) /* f+NUMOFFSET has a short integer value? */
|
code_oparg(ls, PUSHNUMBER, (int)f+NUMOFFSET, 1);
|
||||||
code_oparg(ls, PUSHNUMBER, i+NUMOFFSET, 1);
|
|
||||||
else
|
else
|
||||||
code_constant(ls, real_constant(ls->fs, f));
|
code_constant(ls, real_constant(ls->fs, f));
|
||||||
}
|
}
|
||||||
|
@ -268,9 +282,10 @@ static void flush_record (LexState *ls, int n) {
|
||||||
|
|
||||||
|
|
||||||
static void flush_list (LexState *ls, int m, int n) {
|
static void flush_list (LexState *ls, int m, int n) {
|
||||||
if (n == 0) return;
|
if (n > 0) {
|
||||||
code_oparg(ls, SETLIST, m, -n);
|
code_oparg(ls, SETLIST, m, -n);
|
||||||
code_byte(ls->fs, (Byte)n);
|
code_byte(ls->fs, (Byte)n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,7 +295,7 @@ static void luaI_registerlocalvar (FuncState *fs, TaggedString *varname,
|
||||||
TProtoFunc *f = fs->f;
|
TProtoFunc *f = fs->f;
|
||||||
if (fs->nvars+1 > fs->maxvars)
|
if (fs->nvars+1 > fs->maxvars)
|
||||||
fs->maxvars = luaM_growvector(&f->locvars, fs->maxvars+1,
|
fs->maxvars = luaM_growvector(&f->locvars, fs->maxvars+1,
|
||||||
LocVar, "", MAX_WORD);
|
LocVar, "", MAX_INT);
|
||||||
f->locvars[fs->nvars].varname = varname;
|
f->locvars[fs->nvars].varname = varname;
|
||||||
f->locvars[fs->nvars].line = line;
|
f->locvars[fs->nvars].line = line;
|
||||||
fs->nvars++;
|
fs->nvars++;
|
||||||
|
@ -295,10 +310,9 @@ static void luaI_unregisterlocalvar (FuncState *fs, int line) {
|
||||||
|
|
||||||
static void store_localvar (LexState *ls, TaggedString *name, int n) {
|
static void store_localvar (LexState *ls, TaggedString *name, int n) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
if (fs->nlocalvar+n < MAXLOCALS)
|
if (fs->nlocalvar+n >= MAXLOCALS)
|
||||||
fs->localvar[fs->nlocalvar+n] = name;
|
|
||||||
else
|
|
||||||
luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS));
|
luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS));
|
||||||
|
fs->localvar[fs->nlocalvar+n] = name;
|
||||||
luaI_registerlocalvar(fs, name, ls->linenumber);
|
luaI_registerlocalvar(fs, name, ls->linenumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,13 +334,13 @@ static int aux_localname (FuncState *fs, TaggedString *n) {
|
||||||
static void singlevar (LexState *ls, TaggedString *n, vardesc *var, int prev) {
|
static void singlevar (LexState *ls, TaggedString *n, vardesc *var, int prev) {
|
||||||
FuncState *fs = prev ? ls->fs->prev : ls->fs;
|
FuncState *fs = prev ? ls->fs->prev : ls->fs;
|
||||||
int i = aux_localname(fs, n);
|
int i = aux_localname(fs, n);
|
||||||
if (i >= 0) { /* local value */
|
if (i >= 0) { /* local value? */
|
||||||
var->k = VLOCAL;
|
var->k = VLOCAL;
|
||||||
var->info = i;
|
var->info = i;
|
||||||
}
|
}
|
||||||
else { /* check shadowing */
|
else {
|
||||||
FuncState *level = fs;
|
FuncState *level = fs;
|
||||||
while ((level = level->prev) != NULL)
|
while ((level = level->prev) != NULL) /* check shadowing */
|
||||||
if (aux_localname(level, n) >= 0)
|
if (aux_localname(level, n) >= 0)
|
||||||
luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str);
|
luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str);
|
||||||
var->k = VGLOBAL;
|
var->k = VGLOBAL;
|
||||||
|
@ -354,13 +368,11 @@ static int indexupvalue (LexState *ls, TaggedString *n) {
|
||||||
|
|
||||||
|
|
||||||
static void pushupvalue (LexState *ls, TaggedString *n) {
|
static void pushupvalue (LexState *ls, TaggedString *n) {
|
||||||
int i;
|
|
||||||
if (ls->fs->prev == NULL)
|
if (ls->fs->prev == NULL)
|
||||||
luaX_syntaxerror(ls, "cannot access upvalue in main", n->str);
|
luaX_syntaxerror(ls, "cannot access upvalue in main", n->str);
|
||||||
if (aux_localname(ls->fs, n) >= 0)
|
if (aux_localname(ls->fs, n) >= 0)
|
||||||
luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str);
|
luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str);
|
||||||
i = indexupvalue(ls, n);
|
code_oparg(ls, PUSHUPVALUE, indexupvalue(ls, n), 1);
|
||||||
code_oparg(ls, PUSHUPVALUE, i, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,12 +396,10 @@ static void adjuststack (LexState *ls, int n) {
|
||||||
static void close_exp (LexState *ls, int pc, int nresults) {
|
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;
|
Byte *code = ls->fs->f->code;
|
||||||
Byte nparams = code[pc]; /* save nparams */
|
code[pc-1] = nresults; /* set nresults */
|
||||||
pc += fix_opcode(ls, pc-2, CALLFUNC, nresults);
|
|
||||||
code[pc] = nparams; /* restore nparams */
|
|
||||||
if (nresults != MULT_RET)
|
if (nresults != MULT_RET)
|
||||||
deltastack(ls, nresults); /* "push" results */
|
deltastack(ls, nresults); /* push results */
|
||||||
deltastack(ls, -(nparams+1)); /* "pop" params and function */
|
deltastack(ls, -(code[pc]+1)); /* pop params (at code[pc]) and function */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +412,7 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) {
|
||||||
}
|
}
|
||||||
else { /* must correct function call */
|
else { /* must correct function call */
|
||||||
diff--; /* do not count function call itself */
|
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 */
|
/* function call must provide extra values */
|
||||||
close_exp(ls, d->pc, -diff);
|
close_exp(ls, d->pc, -diff);
|
||||||
}
|
}
|
||||||
|
@ -493,15 +503,14 @@ static int fix_jump (LexState *ls, int pc, OpCode op, int n) {
|
||||||
|
|
||||||
static void fix_upjmp (LexState *ls, OpCode op, int pos) {
|
static void fix_upjmp (LexState *ls, OpCode op, int pos) {
|
||||||
int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */
|
int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */
|
||||||
if (delta > 255) delta++;
|
code_oparg(ls, op, delta+(codesize(delta)-2), 0);
|
||||||
code_oparg(ls, op, delta, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void codeIf (LexState *ls, int thenAdd, int elseAdd) {
|
static void codeIf (LexState *ls, int thenAdd, int elseAdd) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int elseinit = elseAdd+JMPSIZE;
|
int elseinit = elseAdd+JMPSIZE;
|
||||||
if (fs->pc == elseinit) { /* no else part */
|
if (fs->pc == elseinit) { /* no else part? */
|
||||||
fs->pc -= JMPSIZE;
|
fs->pc -= JMPSIZE;
|
||||||
elseinit = fs->pc;
|
elseinit = fs->pc;
|
||||||
}
|
}
|
||||||
|
@ -547,14 +556,13 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *filename) {
|
||||||
fs->nvars = fs->maxvars = 0;
|
fs->nvars = fs->maxvars = 0;
|
||||||
else
|
else
|
||||||
fs->maxvars = -1; /* flag no debug information */
|
fs->maxvars = -1; /* flag no debug information */
|
||||||
code_byte(fs, 0); /* to be filled with stacksize */
|
code_byte(fs, 0); /* to be filled with maxstacksize */
|
||||||
code_byte(fs, 0); /* to be filled with arg information */
|
code_byte(fs, 0); /* to be filled with arg information */
|
||||||
/* push function (to avoid GC) */
|
/* push function (to avoid GC) */
|
||||||
tfvalue(L->stack.top) = f; ttype(L->stack.top) = LUA_T_PROTO;
|
tfvalue(L->stack.top) = f; ttype(L->stack.top) = LUA_T_PROTO;
|
||||||
incr_top;
|
incr_top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void close_func (LexState *ls) {
|
static void close_func (LexState *ls) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
TProtoFunc *f = fs->f;
|
TProtoFunc *f = fs->f;
|
||||||
|
@ -575,13 +583,11 @@ static void close_func (LexState *ls) {
|
||||||
static int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, DO, NAME,
|
static int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, DO, NAME,
|
||||||
LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', EOS, ',', 0};
|
LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', EOS, ',', 0};
|
||||||
|
|
||||||
|
|
||||||
static int is_in (int tok, int *toks) {
|
static int is_in (int tok, int *toks) {
|
||||||
int *t = toks;
|
int *t;
|
||||||
while (*t) {
|
for (t=toks; *t; t++)
|
||||||
if (*t == tok)
|
if (*t == tok) return t-toks;
|
||||||
return t-toks;
|
|
||||||
t++;
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,9 +648,7 @@ static int checkname (LexState *ls) {
|
||||||
|
|
||||||
|
|
||||||
static TaggedString *str_checkname (LexState *ls) {
|
static TaggedString *str_checkname (LexState *ls) {
|
||||||
/* call "checkname" to put string at constant table (to avoid GC) */
|
return tsvalue(&ls->fs->f->consts[checkname(ls)]);
|
||||||
int i = checkname(ls);
|
|
||||||
return tsvalue(&ls->fs->f->consts[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -855,7 +859,7 @@ static void ifpart (LexState *ls, int isexp, int line) {
|
||||||
check(ls, THEN);
|
check(ls, THEN);
|
||||||
if (isexp) {
|
if (isexp) {
|
||||||
exp1(ls);
|
exp1(ls);
|
||||||
deltastack(ls, -1); /* only then xor else part will stay on the stack */
|
deltastack(ls, -1); /* only 'then' x-or 'else' will stay on the stack */
|
||||||
}
|
}
|
||||||
else block(ls);
|
else block(ls);
|
||||||
e = SaveWord(ls);
|
e = SaveWord(ls);
|
||||||
|
@ -878,10 +882,9 @@ static void ifpart (LexState *ls, int isexp, int line) {
|
||||||
|
|
||||||
static void ret (LexState *ls) {
|
static void ret (LexState *ls) {
|
||||||
/* ret -> [RETURN explist sc] */
|
/* ret -> [RETURN explist sc] */
|
||||||
if (ls->token == RETURN) {
|
check_debugline(ls);
|
||||||
|
if (optional(ls, RETURN)) {
|
||||||
listdesc e;
|
listdesc e;
|
||||||
check_debugline(ls);
|
|
||||||
next(ls);
|
|
||||||
explist(ls, &e);
|
explist(ls, &e);
|
||||||
close_exp(ls, e.pc, MULT_RET);
|
close_exp(ls, e.pc, MULT_RET);
|
||||||
code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0);
|
code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0);
|
||||||
|
@ -897,6 +900,9 @@ static void ret (LexState *ls) {
|
||||||
** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1.
|
** (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 */
|
/* code of first binary operator */
|
||||||
#define FIRSTBIN 2
|
#define FIRSTBIN 2
|
||||||
|
|
||||||
|
@ -913,10 +919,7 @@ 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,
|
static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP,
|
||||||
LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP};
|
LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP};
|
||||||
|
|
||||||
#define INDNOT 0
|
#define MAXOPS 20 /* op's stack size */
|
||||||
#define INDMINUS 1
|
|
||||||
|
|
||||||
#define MAXOPS 20
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int ops[MAXOPS];
|
int ops[MAXOPS];
|
||||||
|
@ -934,16 +937,17 @@ static void exp1 (LexState *ls) {
|
||||||
|
|
||||||
|
|
||||||
static void exp0 (LexState *ls, vardesc *v) {
|
static void exp0 (LexState *ls, vardesc *v) {
|
||||||
|
/* exp0 -> exp2 {(AND | OR) exp2} */
|
||||||
exp2(ls, v);
|
exp2(ls, v);
|
||||||
while (ls->token == AND || ls->token == OR) {
|
while (ls->token == AND || ls->token == OR) {
|
||||||
int is_and = (ls->token == AND);
|
int op = (ls->token == AND) ? ONFJMP : ONTJMP;
|
||||||
int pc;
|
int pc;
|
||||||
lua_pushvar(ls, v);
|
lua_pushvar(ls, v);
|
||||||
next(ls);
|
next(ls);
|
||||||
pc = SaveWordPop(ls);
|
pc = SaveWordPop(ls);
|
||||||
exp2(ls, v);
|
exp2(ls, v);
|
||||||
lua_pushvar(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -952,31 +956,23 @@ static void Gexp (LexState *ls, vardesc *v) {
|
||||||
/* Gexp -> exp0 | var '=' exp1 */
|
/* Gexp -> exp0 | var '=' exp1 */
|
||||||
static OpCode codes[] = {SETLOCALDUP, SETGLOBALDUP, SETTABLEDUP};
|
static OpCode codes[] = {SETLOCALDUP, SETGLOBALDUP, SETTABLEDUP};
|
||||||
exp0(ls, v);
|
exp0(ls, v);
|
||||||
if (ls->token == '=' && v->k != VEXP) { /* assignment expression? */
|
if (v->k != VEXP && optional(ls, '=')) { /* assignment expression? */
|
||||||
next(ls); /* skip '=' */
|
|
||||||
unloaddot(ls, v);
|
unloaddot(ls, v);
|
||||||
exp1(ls);
|
exp1(ls);
|
||||||
genstorevar(ls, v, codes);
|
genstorevar(ls, v, codes);
|
||||||
deltastack(ls, 1); /* DUP operations push an extra value */
|
deltastack(ls, 1); /* DUP operations push an extra value */
|
||||||
v->k = VEXP; v->info = 0;
|
v->k = VEXP; v->info = 0; /* this expression is closed now */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void push (LexState *ls, stack_op *s, int op) {
|
static void push (LexState *ls, stack_op *s, int op) {
|
||||||
if (s->top == MAXOPS)
|
if (s->top >= MAXOPS)
|
||||||
luaX_error(ls, "expression too complex");
|
luaX_error(ls, "expression too complex");
|
||||||
s->ops[s->top++] = op;
|
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?INDNOT:INDMINUS);
|
|
||||||
next(ls);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pop_to (LexState *ls, stack_op *s, int prio) {
|
static void pop_to (LexState *ls, stack_op *s, int prio) {
|
||||||
int op;
|
int op;
|
||||||
while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) {
|
while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) {
|
||||||
|
@ -991,10 +987,10 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) {
|
||||||
case NUMBER: { /* simpleexp -> NUMBER */
|
case NUMBER: { /* simpleexp -> NUMBER */
|
||||||
real r = ls->seminfo.r;
|
real r = ls->seminfo.r;
|
||||||
next(ls);
|
next(ls);
|
||||||
/* dirty trick: check whether is a -NUMBER not followed by "^" */
|
/* dirty trick: check whether it is a -NUMBER not followed by '^' */
|
||||||
/* (because the priority of "^" is closer than "-"...) */
|
/* (because the priority of '^' is closer than '-'...) */
|
||||||
if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') {
|
if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') {
|
||||||
s->top--;
|
s->top--; /* remove '-' from stack */
|
||||||
r = -r;
|
r = -r;
|
||||||
}
|
}
|
||||||
code_number(ls, r);
|
code_number(ls, r);
|
||||||
|
@ -1002,7 +998,7 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case STRING: /* simpleexp -> STRING */
|
case STRING: /* simpleexp -> STRING */
|
||||||
code_string(ls, ls->seminfo.ts); /* must use before "next" */
|
code_string(ls, ls->seminfo.ts); /* must use 'seminfo' before "next" */
|
||||||
next(ls);
|
next(ls);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1042,12 +1038,21 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
static void exp2 (LexState *ls, vardesc *v) {
|
||||||
stack_op s;
|
stack_op s;
|
||||||
int op;
|
int op;
|
||||||
s.top = 0;
|
s.top = 0;
|
||||||
prefix(ls, &s);
|
prefixexp(ls, v, &s);
|
||||||
simpleexp(ls, v, &s);
|
|
||||||
while ((op = is_in(ls->token, binop)) >= 0) {
|
while ((op = is_in(ls->token, binop)) >= 0) {
|
||||||
op += FIRSTBIN;
|
op += FIRSTBIN;
|
||||||
lua_pushvar(ls, v);
|
lua_pushvar(ls, v);
|
||||||
|
@ -1055,8 +1060,7 @@ static void exp2 (LexState *ls, vardesc *v) {
|
||||||
pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]);
|
pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]);
|
||||||
push(ls, &s, op);
|
push(ls, &s, op);
|
||||||
next(ls);
|
next(ls);
|
||||||
prefix(ls, &s);
|
prefixexp(ls, v, &s);
|
||||||
simpleexp(ls, v, &s);
|
|
||||||
lua_pushvar(ls, v);
|
lua_pushvar(ls, v);
|
||||||
}
|
}
|
||||||
if (s.top > 0) {
|
if (s.top > 0) {
|
||||||
|
@ -1078,6 +1082,7 @@ static void var_or_func (LexState *ls, vardesc *v) {
|
||||||
var_or_func_tail(ls, v);
|
var_or_func_tail(ls, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void var_or_func_tail (LexState *ls, vardesc *v) {
|
static void var_or_func_tail (LexState *ls, vardesc *v) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (ls->token) {
|
switch (ls->token) {
|
||||||
|
@ -1117,13 +1122,14 @@ static void var_or_func_tail (LexState *ls, vardesc *v) {
|
||||||
|
|
||||||
static int funcparams (LexState *ls, int slf) {
|
static int funcparams (LexState *ls, int slf) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int nparams = 1; /* default value */
|
int nparams = 1; /* in cases STRING and constructor */
|
||||||
switch (ls->token) {
|
switch (ls->token) {
|
||||||
case '(': { /* funcparams -> '(' explist ')' */
|
case '(': { /* funcparams -> '(' explist ')' */
|
||||||
|
int line = ls->linenumber;
|
||||||
listdesc e;
|
listdesc e;
|
||||||
next(ls);
|
next(ls);
|
||||||
explist(ls, &e);
|
explist(ls, &e);
|
||||||
check(ls, ')');
|
check_match(ls, ')', '(', line);
|
||||||
close_exp(ls, e.pc, 1);
|
close_exp(ls, e.pc, 1);
|
||||||
nparams = e.n;
|
nparams = e.n;
|
||||||
break;
|
break;
|
||||||
|
@ -1134,7 +1140,7 @@ static int funcparams (LexState *ls, int slf) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRING: /* funcparams -> STRING */
|
case STRING: /* funcparams -> STRING */
|
||||||
code_string(ls, ls->seminfo.ts); /* must use before "next" */
|
code_string(ls, ls->seminfo.ts); /* must use 'seminfo' before "next" */
|
||||||
next(ls);
|
next(ls);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1142,8 +1148,8 @@ static int funcparams (LexState *ls, int slf) {
|
||||||
luaX_error(ls, "function arguments expected");
|
luaX_error(ls, "function arguments expected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
code_byte(fs, 0); /* save space for opcode */
|
code_byte(fs, CALLFUNC);
|
||||||
code_byte(fs, 0); /* and nresult */
|
code_byte(fs, 0); /* save space for nresult */
|
||||||
code_byte(fs, (Byte)(nparams+slf));
|
code_byte(fs, (Byte)(nparams+slf));
|
||||||
return fs->pc-1;
|
return fs->pc-1;
|
||||||
}
|
}
|
||||||
|
|
43
lvm.c
43
lvm.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 1.42 1999/02/02 17:57:49 roberto Exp roberto $
|
** $Id: lvm.c,v 1.43 1999/02/02 19:41:17 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -328,6 +328,7 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
register int aux = 0;
|
register int aux = 0;
|
||||||
|
switchentry:
|
||||||
switch ((OpCode)*pc++) {
|
switch ((OpCode)*pc++) {
|
||||||
|
|
||||||
case ENDCODE: aux = 1;
|
case ENDCODE: aux = 1;
|
||||||
|
@ -348,14 +349,14 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
S->top -= (aux+1);
|
S->top -= (aux+1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PUSHNUMBERW: aux = highbyte(*pc++);
|
case PUSHNUMBERW: aux += highbyte(*pc++);
|
||||||
case PUSHNUMBER: aux += *pc++;
|
case PUSHNUMBER: aux += *pc++;
|
||||||
ttype(S->top) = LUA_T_NUMBER;
|
ttype(S->top) = LUA_T_NUMBER;
|
||||||
nvalue(S->top) = aux-NUMOFFSET;
|
nvalue(S->top) = aux-NUMOFFSET;
|
||||||
S->top++;
|
S->top++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PUSHCONSTANTW: aux = highbyte(*pc++);
|
case PUSHCONSTANTW: aux += highbyte(*pc++);
|
||||||
case PUSHCONSTANT: aux += *pc++;
|
case PUSHCONSTANT: aux += *pc++;
|
||||||
*S->top++ = consts[aux];
|
*S->top++ = consts[aux];
|
||||||
break;
|
break;
|
||||||
|
@ -368,22 +369,22 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
*S->top++ = *((S->stack+base) + aux);
|
*S->top++ = *((S->stack+base) + aux);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GETGLOBALW: aux = highbyte(*pc++);
|
case GETGLOBALW: aux += highbyte(*pc++);
|
||||||
case GETGLOBAL: aux += *pc++;
|
case GETGLOBAL: aux += *pc++;
|
||||||
luaV_getglobal(tsvalue(&consts[aux]));
|
luaV_getglobal(tsvalue(&consts[aux]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GETTABLE:
|
case GETTABLE:
|
||||||
luaV_gettable();
|
luaV_gettable();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GETDOTTEDW: aux = highbyte(*pc++);
|
case GETDOTTEDW: aux += highbyte(*pc++);
|
||||||
case GETDOTTED: aux += *pc++;
|
case GETDOTTED: aux += *pc++;
|
||||||
*S->top++ = consts[aux];
|
*S->top++ = consts[aux];
|
||||||
luaV_gettable();
|
luaV_gettable();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PUSHSELFW: aux = highbyte(*pc++);
|
case PUSHSELFW: aux += highbyte(*pc++);
|
||||||
case PUSHSELF: aux += *pc++; {
|
case PUSHSELF: aux += *pc++; {
|
||||||
TObject receiver = *(S->top-1);
|
TObject receiver = *(S->top-1);
|
||||||
*S->top++ = consts[aux];
|
*S->top++ = consts[aux];
|
||||||
|
@ -392,7 +393,7 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CREATEARRAYW: aux = highbyte(*pc++);
|
case CREATEARRAYW: aux += highbyte(*pc++);
|
||||||
case CREATEARRAY: aux += *pc++;
|
case CREATEARRAY: aux += *pc++;
|
||||||
luaC_checkGC();
|
luaC_checkGC();
|
||||||
avalue(S->top) = luaH_new(aux);
|
avalue(S->top) = luaH_new(aux);
|
||||||
|
@ -408,12 +409,12 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
*((S->stack+base) + aux) = *(S->top-1);
|
*((S->stack+base) + aux) = *(S->top-1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SETGLOBALW: aux = highbyte(*pc++);
|
case SETGLOBALW: aux += highbyte(*pc++);
|
||||||
case SETGLOBAL: aux += *pc++;
|
case SETGLOBAL: aux += *pc++;
|
||||||
luaV_setglobal(tsvalue(&consts[aux]));
|
luaV_setglobal(tsvalue(&consts[aux]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SETGLOBALDUPW: aux = highbyte(*pc++);
|
case SETGLOBALDUPW: aux += highbyte(*pc++);
|
||||||
case SETGLOBALDUP: aux += *pc++;
|
case SETGLOBALDUP: aux += *pc++;
|
||||||
*S->top = *(S->top-1);
|
*S->top = *(S->top-1);
|
||||||
S->top++;
|
S->top++;
|
||||||
|
@ -435,7 +436,7 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
luaV_settable(S->top-3-(*pc++), 1);
|
luaV_settable(S->top-3-(*pc++), 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SETLISTW: aux = highbyte(*pc++);
|
case SETLISTW: aux += highbyte(*pc++);
|
||||||
case SETLIST: aux += *pc++; {
|
case SETLIST: aux += *pc++; {
|
||||||
int n = *(pc++);
|
int n = *(pc++);
|
||||||
TObject *arr = S->top-n-1;
|
TObject *arr = S->top-n-1;
|
||||||
|
@ -561,34 +562,34 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
nvalue(S->top-1) = 1;
|
nvalue(S->top-1) = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ONTJMPW: aux = highbyte(*pc++);
|
case ONTJMPW: aux += highbyte(*pc++);
|
||||||
case ONTJMP: aux += *pc++;
|
case ONTJMP: aux += *pc++;
|
||||||
if (ttype(S->top-1) != LUA_T_NIL) pc += aux;
|
if (ttype(S->top-1) != LUA_T_NIL) pc += aux;
|
||||||
else S->top--;
|
else S->top--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ONFJMPW: aux = highbyte(*pc++);
|
case ONFJMPW: aux += highbyte(*pc++);
|
||||||
case ONFJMP: aux += *pc++;
|
case ONFJMP: aux += *pc++;
|
||||||
if (ttype(S->top-1) == LUA_T_NIL) pc += aux;
|
if (ttype(S->top-1) == LUA_T_NIL) pc += aux;
|
||||||
else S->top--;
|
else S->top--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JMPW: aux = highbyte(*pc++);
|
case JMPW: aux += highbyte(*pc++);
|
||||||
case JMP: aux += *pc++;
|
case JMP: aux += *pc++;
|
||||||
pc += aux;
|
pc += aux;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IFFJMPW: aux = highbyte(*pc++);
|
case IFFJMPW: aux += highbyte(*pc++);
|
||||||
case IFFJMP: aux += *pc++;
|
case IFFJMP: aux += *pc++;
|
||||||
if (ttype(--S->top) == LUA_T_NIL) pc += aux;
|
if (ttype(--S->top) == LUA_T_NIL) pc += aux;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IFTUPJMPW: aux = highbyte(*pc++);
|
case IFTUPJMPW: aux += highbyte(*pc++);
|
||||||
case IFTUPJMP: aux += *pc++;
|
case IFTUPJMP: aux += *pc++;
|
||||||
if (ttype(--S->top) != LUA_T_NIL) pc -= aux;
|
if (ttype(--S->top) != LUA_T_NIL) pc -= aux;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IFFUPJMPW: aux = highbyte(*pc++);
|
case IFFUPJMPW: aux += highbyte(*pc++);
|
||||||
case IFFUPJMP: aux += *pc++;
|
case IFFUPJMP: aux += *pc++;
|
||||||
if (ttype(--S->top) == LUA_T_NIL) pc -= aux;
|
if (ttype(--S->top) == LUA_T_NIL) pc -= aux;
|
||||||
break;
|
break;
|
||||||
|
@ -605,7 +606,7 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SETLINEW: aux = highbyte(*pc++);
|
case SETLINEW: aux += highbyte(*pc++);
|
||||||
case SETLINE: aux += *pc++;
|
case SETLINE: aux += *pc++;
|
||||||
if ((S->stack+base-1)->ttype != LUA_T_LINE) {
|
if ((S->stack+base-1)->ttype != LUA_T_LINE) {
|
||||||
/* open space for LINE value */
|
/* open space for LINE value */
|
||||||
|
@ -618,6 +619,10 @@ StkId luaV_execute (Closure *cl, TProtoFunc *tf, StkId base) {
|
||||||
luaD_lineHook(aux);
|
luaD_lineHook(aux);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LONGARG:
|
||||||
|
aux = highbyte(highbyte(*pc++));
|
||||||
|
goto switchentry; /* do not reset "aux" */
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue