|
@@ -1,6 +1,6 @@
|
|
|
%{
|
|
|
/*
|
|
|
-** $Id: lua.stx,v 1.7 1997/10/01 20:05:34 roberto Exp roberto $
|
|
|
+** $Id: lua.stx,v 1.8 1997/10/06 14:51:11 roberto Exp roberto $
|
|
|
** Syntax analizer and code generator
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -23,9 +23,6 @@
|
|
|
|
|
|
/* to avoid warnings generated by yacc */
|
|
|
int luaY_parse (void);
|
|
|
-#define malloc luaM_malloc
|
|
|
-#define realloc luaM_realloc
|
|
|
-#define free luaM_free
|
|
|
|
|
|
|
|
|
/* size of a "normal" jump instruction: OpCode + 1 byte */
|
|
@@ -118,23 +115,6 @@ static void code_byte (Byte c)
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void code_word_at (int pc, int n)
|
|
|
-{
|
|
|
- if (n > MAX_WORD)
|
|
|
- luaY_error("construction too big; unable to compile");
|
|
|
- currState->f->code[pc] = n&0xFF;
|
|
|
- currState->f->code[pc+1] = n>>8;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void code_word (int n)
|
|
|
-{
|
|
|
- check_pc(2);
|
|
|
- currState->pc += 2;
|
|
|
- code_word_at(currState->pc-2, n);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
static void deltastack (int delta)
|
|
|
{
|
|
|
currState->stacksize += delta;
|
|
@@ -146,41 +126,55 @@ static void deltastack (int delta)
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void code_opcode (OpCode op, int delta)
|
|
|
+static int code_oparg_at (int pc, OpCode op, int builtin, int arg, int delta)
|
|
|
{
|
|
|
- code_byte(op);
|
|
|
deltastack(delta);
|
|
|
+ if (arg < builtin) {
|
|
|
+ currState->f->code[pc] = op+1+arg;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ else if (arg <= 255) {
|
|
|
+ currState->f->code[pc] = op;
|
|
|
+ currState->f->code[pc+1] = arg;
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+ else if (arg <= MAX_WORD) {
|
|
|
+ currState->f->code[pc] = op+1+builtin;
|
|
|
+ currState->f->code[pc+1] = arg&0xFF;
|
|
|
+ currState->f->code[pc+2] = arg>>8;
|
|
|
+ return 3;
|
|
|
+ }
|
|
|
+ else luaY_error("construction too big - unable to compile");
|
|
|
+ return 0; /* to avoid warnings */
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void code_opb (OpCode opbyte, int arg, int delta)
|
|
|
+static int fix_opcode (int pc, OpCode op, int builtin, int arg)
|
|
|
{
|
|
|
- code_opcode(opbyte, delta);
|
|
|
- code_byte(arg);
|
|
|
-}
|
|
|
-
|
|
|
-static void code_opw (OpCode opbyte, int arg, int delta)
|
|
|
-{
|
|
|
- code_opcode(opbyte, delta);
|
|
|
- code_word(arg);
|
|
|
+ if (arg < builtin) { /* close space */
|
|
|
+ movecode_down(pc+1, pc+2, currState->pc-(pc+2));
|
|
|
+ currState->pc--;
|
|
|
+ }
|
|
|
+ else if (arg > 255) { /* open space */
|
|
|
+ check_pc(1);
|
|
|
+ movecode_up(pc+1, pc, currState->pc-pc);
|
|
|
+ currState->pc++;
|
|
|
+ }
|
|
|
+ return code_oparg_at(pc, op, builtin, arg, 0) - 2;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void code_opborw (OpCode opbyte, int arg, int delta)
|
|
|
+static void code_oparg (OpCode op, int builtin, int arg, int delta)
|
|
|
{
|
|
|
- if (arg <= 255)
|
|
|
- code_opb(opbyte, arg, delta);
|
|
|
- else
|
|
|
- code_opw(opbyte+1, arg, delta);
|
|
|
+ check_pc(3); /* maximum code size */
|
|
|
+ currState->pc += code_oparg_at(currState->pc, op, builtin, arg, delta);
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void code_oparg (OpCode firstop, OpCode opbyte, int arg, int delta)
|
|
|
+static void code_opcode (OpCode op, int delta)
|
|
|
{
|
|
|
- if (firstop+arg < opbyte)
|
|
|
- code_opcode(firstop+arg, delta);
|
|
|
- else
|
|
|
- code_opborw(opbyte, arg, delta);
|
|
|
+ deltastack(delta);
|
|
|
+ code_byte(op);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -193,7 +187,10 @@ static void code_pop (OpCode op)
|
|
|
#define code_binop(op) code_pop(op)
|
|
|
|
|
|
|
|
|
-#define code_neutralop(op) code_byte(op)
|
|
|
+static void code_neutralop (OpCode op)
|
|
|
+{
|
|
|
+ code_opcode(op, 0);
|
|
|
+}
|
|
|
|
|
|
/* unary operations get 1 argument and leave one, so they are neutral */
|
|
|
#define code_unop(op) code_neutralop(op)
|
|
@@ -201,7 +198,7 @@ static void code_pop (OpCode op)
|
|
|
|
|
|
static void code_constant (int c)
|
|
|
{
|
|
|
- code_oparg(PUSHCONSTANT0, PUSHCONSTANTB, c, 1);
|
|
|
+ code_oparg(PUSHCONSTANT, 8, c, 1);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -237,7 +234,7 @@ static void code_string (TaggedString *s)
|
|
|
}
|
|
|
|
|
|
|
|
|
-#define LIM 13
|
|
|
+#define LIM 20
|
|
|
static int real_constant (real r)
|
|
|
{
|
|
|
/* check whether 'r' has appeared within the last LIM entries */
|
|
@@ -261,7 +258,7 @@ static void code_number (real f)
|
|
|
{
|
|
|
Word i;
|
|
|
if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(Word)f) == f)
|
|
|
- code_oparg(PUSH0, PUSHBYTE, i, 1); /* f has an (short) integer value */
|
|
|
+ code_oparg(PUSHNUMBER, 3, i, 1); /* f has an (short) integer value */
|
|
|
else
|
|
|
code_constant(real_constant(f));
|
|
|
}
|
|
@@ -270,18 +267,13 @@ static void code_number (real f)
|
|
|
static void flush_record (int n)
|
|
|
{
|
|
|
if (n > 0)
|
|
|
- code_opb(SETMAP, n, -2*n);
|
|
|
+ code_oparg(SETMAP, 1, n-1, -2*n);
|
|
|
}
|
|
|
|
|
|
static void flush_list (int m, int n)
|
|
|
{
|
|
|
if (n == 0) return;
|
|
|
- if (m == 0)
|
|
|
- code_opcode(SETLIST0, -n);
|
|
|
- else if (m < 255)
|
|
|
- code_opb(SETLIST, m, -n);
|
|
|
- else
|
|
|
- luaY_error("list constructor too long");
|
|
|
+ code_oparg(SETLIST, 1, m, -n);
|
|
|
code_byte(n);
|
|
|
}
|
|
|
|
|
@@ -375,7 +367,7 @@ static void pushupvalue (TaggedString *n)
|
|
|
if (aux_localname(n, currState) >= 0)
|
|
|
luaY_syntaxerror("cannot access an upvalue in current scope", n->str);
|
|
|
i = indexupvalue(n);
|
|
|
- code_oparg(PUSHUPVALUE0, PUSHUPVALUE, i, 1);
|
|
|
+ code_oparg(PUSHUPVALUE, 2, i, 1);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -383,7 +375,7 @@ void luaY_codedebugline (int line)
|
|
|
{
|
|
|
static int lastline = 0;
|
|
|
if (lua_debug && line != lastline) {
|
|
|
- code_opw(SETLINE, line, 0);
|
|
|
+ code_oparg(SETLINE, 0, line, 0);
|
|
|
lastline = line;
|
|
|
}
|
|
|
}
|
|
@@ -392,22 +384,25 @@ void luaY_codedebugline (int line)
|
|
|
static void adjuststack (int n)
|
|
|
{
|
|
|
if (n > 0)
|
|
|
- code_oparg(POP1-1, POPS, n, -n); /* POP1-1 = POP0 */
|
|
|
+ code_oparg(POP, 2, n-1, -n);
|
|
|
else if (n < 0)
|
|
|
- code_oparg(PUSHNIL-1, PUSHNILS, -n, -n); /* PUSHNIL1-1 = PUSHNIL0 */
|
|
|
+ code_oparg(PUSHNIL, 1, (-n)-1, -n);
|
|
|
}
|
|
|
|
|
|
|
|
|
-static long adjust_functioncall (long exp, int i)
|
|
|
+static long adjust_functioncall (long exp, int nresults)
|
|
|
{
|
|
|
if (exp <= 0)
|
|
|
return -exp; /* exp is -list length */
|
|
|
else {
|
|
|
int temp = currState->f->code[exp];
|
|
|
- currState->f->code[exp] = i;
|
|
|
- if (i != MULT_RET)
|
|
|
- deltastack(i);
|
|
|
- return temp+i;
|
|
|
+ int nparams = currState->f->code[exp-1];
|
|
|
+ exp += fix_opcode(exp-2, CALLFUNC, 2, nresults);
|
|
|
+ currState->f->code[exp] = nparams;
|
|
|
+ if (nresults != MULT_RET)
|
|
|
+ deltastack(nresults);
|
|
|
+ deltastack(-(nparams+1));
|
|
|
+ return temp+nresults;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -430,9 +425,9 @@ static void adjust_mult_assign (int vars, long exps)
|
|
|
static void code_args (int dots)
|
|
|
{
|
|
|
if (!dots)
|
|
|
- code_opb(ARGS, currState->nlocalvar, currState->nlocalvar);
|
|
|
+ code_oparg(ARGS, 0, currState->nlocalvar, currState->nlocalvar);
|
|
|
else {
|
|
|
- code_opb(VARARGS, currState->nlocalvar, currState->nlocalvar+1);
|
|
|
+ code_oparg(VARARGS, 0, currState->nlocalvar, currState->nlocalvar+1);
|
|
|
add_localvar(luaS_new("arg"));
|
|
|
}
|
|
|
}
|
|
@@ -441,9 +436,9 @@ static void code_args (int dots)
|
|
|
static void lua_pushvar (vardesc number)
|
|
|
{
|
|
|
if (number > 0) /* global var */
|
|
|
- code_oparg(GETGLOBAL0, GETGLOBALB, number-1, 1);
|
|
|
+ code_oparg(GETGLOBAL, 8, number-1, 1);
|
|
|
else if (number < 0) /* local var */
|
|
|
- code_oparg(PUSHLOCAL0, PUSHLOCAL, (-number)-1, 1);
|
|
|
+ code_oparg(PUSHLOCAL, 8, (-number)-1, 1);
|
|
|
else
|
|
|
code_pop(GETTABLE);
|
|
|
}
|
|
@@ -454,9 +449,9 @@ static void storevar (vardesc number)
|
|
|
if (number == 0) /* indexed var */
|
|
|
code_opcode(SETTABLE0, -3);
|
|
|
else if (number > 0) /* global var */
|
|
|
- code_opborw(SETGLOBALB, number-1, -1);
|
|
|
+ code_oparg(SETGLOBAL, 8, number-1, -1);
|
|
|
else /* number < 0 - local var */
|
|
|
- code_oparg(SETLOCAL0, SETLOCAL, (-number)-1, -1);
|
|
|
+ code_oparg(SETLOCAL, 8, (-number)-1, -1);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -469,35 +464,16 @@ static int lua_codestore (int i, int left)
|
|
|
return left;
|
|
|
}
|
|
|
else { /* indexed var with values in between*/
|
|
|
- code_pop(SETTABLE);
|
|
|
- code_byte(left+i); /* number of elements between table/index and value */
|
|
|
+ code_oparg(SETTABLE, 0, left+i, -1);
|
|
|
return left+2; /* table/index are not poped, since they are not on top */
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
-static int fix_opcode (int pc, OpCode op, int n)
|
|
|
-{
|
|
|
- if (n <= 255) {
|
|
|
- currState->f->code[pc] = op;
|
|
|
- currState->f->code[pc+1] = n;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- else {
|
|
|
- check_pc(1); /* open space */
|
|
|
- movecode_up(pc+1, pc, currState->pc-pc);
|
|
|
- currState->pc++;
|
|
|
- currState->f->code[pc] = op+1; /* opcode must be word variant */
|
|
|
- code_word_at(pc+1, n);
|
|
|
- return 1;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
static int fix_jump (int pc, OpCode op, int n)
|
|
|
{
|
|
|
/* jump is relative to position following jump instruction */
|
|
|
- return fix_opcode(pc, op, n-(pc+JMPSIZE));
|
|
|
+ return fix_opcode(pc, op, 0, n-(pc+JMPSIZE));
|
|
|
}
|
|
|
|
|
|
|
|
@@ -505,7 +481,7 @@ static void fix_upjmp (OpCode op, int pos)
|
|
|
{
|
|
|
int delta = currState->pc+JMPSIZE - pos; /* jump is relative */
|
|
|
if (delta > 255) delta++;
|
|
|
- code_opborw(op, delta, 0);
|
|
|
+ code_oparg(op, 0, delta, 0);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -517,25 +493,20 @@ static void codeIf (int thenAdd, int elseAdd)
|
|
|
elseinit = currState->pc;
|
|
|
}
|
|
|
else
|
|
|
- elseinit += fix_jump(elseAdd, JMPB, currState->pc);
|
|
|
- fix_jump(thenAdd, IFFJMPB, elseinit);
|
|
|
+ elseinit += fix_jump(elseAdd, JMP, currState->pc);
|
|
|
+ fix_jump(thenAdd, IFFJMP, elseinit);
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void code_shortcircuit (OpCode op, int pos)
|
|
|
+static void code_shortcircuit (int pc, OpCode op)
|
|
|
{
|
|
|
- int dist = currState->pc - (pos+JMPSIZE);
|
|
|
- if (dist > 255)
|
|
|
- luaY_error("and/or expression too long");
|
|
|
- currState->f->code[pos] = op;
|
|
|
- currState->f->code[pos+1] = dist;
|
|
|
+ fix_jump(pc, op, currState->pc);
|
|
|
}
|
|
|
|
|
|
|
|
|
static void codereturn (void)
|
|
|
{
|
|
|
- code_neutralop(RETCODE);
|
|
|
- code_byte(currState->nlocalvar);
|
|
|
+ code_oparg(RETCODE, 0, currState->nlocalvar, 0);
|
|
|
currState->stacksize = currState->nlocalvar;
|
|
|
}
|
|
|
|
|
@@ -549,7 +520,7 @@ static void func_onstack (TProtoFunc *f)
|
|
|
currState->f->consts[c].value.tf = (currState+1)->f;
|
|
|
for (i=0; i<nupvalues; i++)
|
|
|
lua_pushvar((currState+1)->upvalues[i]);
|
|
|
- code_opborw(CLOSUREB, c, 1-nupvalues);
|
|
|
+ code_oparg(CLOSURE, 0, c, 1-nupvalues);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -585,7 +556,6 @@ static void init_func (void)
|
|
|
currState->f->lineDefined = luaX_linenumber;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static TProtoFunc *close_func (void)
|
|
|
{
|
|
|
TProtoFunc *f = currState->f;
|
|
@@ -687,13 +657,13 @@ stat : IF cond THEN block SaveWord elsepart END
|
|
|
memcpy(&currState->f->code[currState->pc],
|
|
|
&currState->f->code[$2], expsize);
|
|
|
movecode_down($2, $3, currState->pc-$2);
|
|
|
- newpos += fix_jump($2, JMPB, currState->pc-expsize);
|
|
|
- fix_upjmp(IFTUPJMPB, newpos);
|
|
|
+ newpos += fix_jump($2, JMP, currState->pc-expsize);
|
|
|
+ fix_upjmp(IFTUPJMP, newpos);
|
|
|
}}
|
|
|
|
|
|
| REPEAT GetPC block UNTIL expr1
|
|
|
{
|
|
|
- fix_upjmp(IFFUPJMPB, $2);
|
|
|
+ fix_upjmp(IFFUPJMP, $2);
|
|
|
deltastack(-1); /* pops condition */
|
|
|
}
|
|
|
|
|
@@ -706,7 +676,7 @@ stat : IF cond THEN block SaveWord elsepart END
|
|
|
left = lua_codestore(i, left);
|
|
|
adjuststack(left); /* remove eventual 'garbage' left on stack */
|
|
|
}}
|
|
|
- | functioncall
|
|
|
+ | functioncall { adjust_functioncall($1, 0); }
|
|
|
| LOCAL localdeclist decinit
|
|
|
{
|
|
|
currState->nlocalvar += $2;
|
|
@@ -757,7 +727,11 @@ ret : /* empty */
|
|
|
GetPC : /* empty */ { $$ = currState->pc; }
|
|
|
;
|
|
|
|
|
|
-SaveWord : GetPC { $$ = $1; code_word(0); /* open space */ }
|
|
|
+SaveWord : /* empty */
|
|
|
+ { $$ = currState->pc;
|
|
|
+ check_pc(JMPSIZE);
|
|
|
+ currState->pc += JMPSIZE; /* open space */
|
|
|
+ }
|
|
|
;
|
|
|
|
|
|
SaveWordPop : SaveWord { $$ = $1; deltastack(-1); /* pop condition */ }
|
|
@@ -787,33 +761,33 @@ expr : '(' expr ')' { $$ = $2; }
|
|
|
| expr1 CONC expr1 { code_binop(CONCOP); $$ = 0; }
|
|
|
| '-' expr1 %prec UNARY { code_unop(MINUSOP); $$ = 0;}
|
|
|
| NOT expr1 { code_unop(NOTOP); $$ = 0;}
|
|
|
- | table { $$ = 0; }
|
|
|
+ | table { $$ = 0; }
|
|
|
| varexp { $$ = 0;}
|
|
|
| NUMBER { code_number($1); $$ = 0; }
|
|
|
| STRING { code_string($1); $$ = 0; }
|
|
|
- | NIL {code_opcode(PUSHNIL, 1); $$ = 0; }
|
|
|
+ | NIL { adjuststack(-1); $$ = 0; }
|
|
|
| functioncall { $$ = $1; }
|
|
|
- | FUNCTION { init_func(); } body { func_onstack($3); $$ = 0; }
|
|
|
- | expr1 AND SaveWordPop expr1 { code_shortcircuit(ONFJMP, $3); $$ = 0; }
|
|
|
- | expr1 OR SaveWordPop expr1 { code_shortcircuit(ONTJMP, $3); $$ = 0; }
|
|
|
+ | FUNCTION { init_func(); } body { func_onstack($3); $$ = 0; }
|
|
|
+ | expr1 AND SaveWordPop expr1 { code_shortcircuit($3, ONFJMP); $$ = 0; }
|
|
|
+ | expr1 OR SaveWordPop expr1 { code_shortcircuit($3, ONTJMP); $$ = 0; }
|
|
|
;
|
|
|
|
|
|
-table : '{' SaveWordPush fieldlist '}' { fix_opcode($2, CREATEARRAYB, $3); }
|
|
|
+table : '{' SaveWordPush fieldlist '}' { fix_opcode($2, CREATEARRAY, 2, $3); }
|
|
|
;
|
|
|
|
|
|
functioncall : funcvalue funcParams
|
|
|
{
|
|
|
- code_opcode(CALLFUNC, -($1+$2+1)); /* ajdust counts results */
|
|
|
- code_byte($1+$2);
|
|
|
+ code_byte(0); /* save space for opcode */
|
|
|
+ code_byte($1+$2); /* number of parameters */
|
|
|
$$ = currState->pc;
|
|
|
- code_byte(0); /* may be adjusted by other rules */
|
|
|
+ code_byte(0); /* must be adjusted by other rules */
|
|
|
}
|
|
|
;
|
|
|
|
|
|
funcvalue : varexp { $$ = 0; }
|
|
|
| varexp ':' NAME
|
|
|
{
|
|
|
- code_opborw(PUSHSELFB, string_constant($3, currState), 1);
|
|
|
+ code_oparg(PUSHSELF, 0, string_constant($3, currState), 1);
|
|
|
$$ = 1;
|
|
|
}
|
|
|
;
|