mirror of
https://github.com/lua/lua.git
synced 2025-01-14 05:43:00 +08:00
change of code generation design (independent functions for each opcode)
This commit is contained in:
parent
3c9d999424
commit
d1ea38580a
237
lcode.c
237
lcode.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.c,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $
|
||||
** $Id: lcode.c,v 1.3 2000/03/03 14:58:26 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -20,12 +20,10 @@ void luaK_error (LexState *ls, const char *msg) {
|
||||
}
|
||||
|
||||
|
||||
static Instruction *last_i (FuncState *fs) {
|
||||
static Instruction dummy = SET_OPCODE(0, ENDCODE);
|
||||
if (fs->last_pc < 0)
|
||||
return &dummy;
|
||||
else
|
||||
return &fs->f->code[fs->last_pc];
|
||||
static Instruction *last_i (LexState *ls, expdesc *v) {
|
||||
FuncState *fs = ls->fs;
|
||||
int last_pc = (v->info != NOJUMPS) ? v->info : fs->pc-1;
|
||||
return &fs->f->code[last_pc];
|
||||
}
|
||||
|
||||
|
||||
@ -37,58 +35,64 @@ int luaK_primitivecode (LexState *ls, Instruction i) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
int luaK_code (LexState *ls, Instruction i) {
|
||||
FuncState *fs = ls->fs;
|
||||
Instruction *last = last_i(fs);
|
||||
switch (GET_OPCODE(i)) {
|
||||
|
||||
case MINUSOP:
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); break;
|
||||
case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); break;
|
||||
case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); break;
|
||||
default: fs->last_pc = luaK_primitivecode(ls, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case GETTABLE:
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break;
|
||||
default: fs->last_pc = luaK_primitivecode(ls, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case RETCODE:
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case CALL:
|
||||
*last = SET_OPCODE(*last, TAILCALL);
|
||||
*last = SETARG_B(*last, GETARG_U(i));
|
||||
break;
|
||||
default: fs->last_pc = luaK_primitivecode(ls, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case ADDOP:
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHINT: *last = SET_OPCODE(*last, ADDI); break;
|
||||
default: fs->last_pc = luaK_primitivecode(ls, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case SUBOP:
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHINT:
|
||||
*last = SET_OPCODE(*last, ADDI);
|
||||
*last = SETARG_S(*last, -GETARG_S(*last));
|
||||
break;
|
||||
default: fs->last_pc = luaK_primitivecode(ls, i);
|
||||
}
|
||||
break;
|
||||
|
||||
default: fs->last_pc = luaK_primitivecode(ls, i);
|
||||
static void luaK_minus (LexState *ls, expdesc *v) {
|
||||
Instruction *last = last_i(ls, v);
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); return;
|
||||
case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); return;
|
||||
case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); return;
|
||||
default: luaK_primitivecode(ls, CREATE_0(MINUSOP));
|
||||
}
|
||||
return fs->last_pc;
|
||||
}
|
||||
|
||||
|
||||
static void luaK_gettable (LexState *ls, expdesc *v) {
|
||||
Instruction *last = last_i(ls, v);
|
||||
luaK_deltastack(ls, -1);
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break;
|
||||
default: luaK_primitivecode(ls, CREATE_0(GETTABLE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void luaK_add (LexState *ls, expdesc *v) {
|
||||
Instruction *last = last_i(ls, v);
|
||||
luaK_deltastack(ls, -1);
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHINT: *last = SET_OPCODE(*last, ADDI); break;
|
||||
default: luaK_primitivecode(ls, CREATE_0(ADDOP));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void luaK_sub (LexState *ls, expdesc *v) {
|
||||
Instruction *last = last_i(ls, v);
|
||||
luaK_deltastack(ls, -1);
|
||||
switch(GET_OPCODE(*last)) {
|
||||
case PUSHINT:
|
||||
*last = SET_OPCODE(*last, ADDI);
|
||||
*last = SETARG_S(*last, -GETARG_S(*last));
|
||||
break;
|
||||
default: luaK_primitivecode(ls, CREATE_0(SUBOP));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_retcode (LexState *ls, int nlocals, listdesc *e) {
|
||||
if (e->n > 0 && luaK_iscall(ls, e->info)) {
|
||||
Instruction *last = &ls->fs->f->code[ls->fs->pc-1];
|
||||
*last = SET_OPCODE(*last, TAILCALL);
|
||||
*last = SETARG_B(*last, nlocals);
|
||||
}
|
||||
else
|
||||
luaK_U(ls, RETCODE, nlocals, 0);
|
||||
}
|
||||
|
||||
|
||||
int luaK_code (LexState *ls, Instruction i, int delta) {
|
||||
luaK_deltastack(ls, delta);
|
||||
return luaK_primitivecode(ls, i);
|
||||
}
|
||||
|
||||
|
||||
@ -97,7 +101,6 @@ void luaK_fixjump (LexState *ls, int pc, int dest) {
|
||||
Instruction *jmp = &fs->f->code[pc];
|
||||
/* jump is relative to position following jump instruction */
|
||||
*jmp = SETARG_S(*jmp, dest-(pc+1));
|
||||
fs->last_pc = pc;
|
||||
}
|
||||
|
||||
|
||||
@ -112,38 +115,8 @@ void luaK_deltastack (LexState *ls, int delta) {
|
||||
}
|
||||
|
||||
|
||||
static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) {
|
||||
luaK_deltastack(ls, delta);
|
||||
return luaK_code(ls, SET_OPCODE(i, op));
|
||||
}
|
||||
|
||||
|
||||
int luaK_0 (LexState *ls, OpCode op, int delta) {
|
||||
return aux_code(ls, op, 0, delta);
|
||||
}
|
||||
|
||||
|
||||
int luaK_U (LexState *ls, OpCode op, int u, int delta) {
|
||||
Instruction i = SETARG_U(0, u);
|
||||
return aux_code(ls, op, i, delta);
|
||||
}
|
||||
|
||||
|
||||
int luaK_S (LexState *ls, OpCode op, int s, int delta) {
|
||||
Instruction i = SETARG_S(0, s);
|
||||
return aux_code(ls, op, i, delta);
|
||||
}
|
||||
|
||||
|
||||
int luaK_AB (LexState *ls, OpCode op, int a, int b, int delta) {
|
||||
Instruction i = SETARG_A(0, a);
|
||||
i = SETARG_B(i, b);
|
||||
return aux_code(ls, op, i, delta);
|
||||
}
|
||||
|
||||
|
||||
int luaK_kstr (LexState *ls, int c) {
|
||||
return luaK_U(ls, PUSHSTRING, c, 1);
|
||||
void luaK_kstr (LexState *ls, int c) {
|
||||
luaK_U(ls, PUSHSTRING, c, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -166,37 +139,40 @@ static int real_constant (LexState *ls, real r) {
|
||||
}
|
||||
|
||||
|
||||
int luaK_number (LexState *ls, real f) {
|
||||
void luaK_number (LexState *ls, real f) {
|
||||
if (f <= (real)MAXARG_S && (int)f == f)
|
||||
return luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */
|
||||
luaK_S(ls, PUSHINT, (int)f, 1); /* f has a short integer value */
|
||||
else
|
||||
return luaK_U(ls, PUSHNUM, real_constant(ls, f), 1);
|
||||
luaK_U(ls, PUSHNUM, real_constant(ls, f), 1);
|
||||
}
|
||||
|
||||
|
||||
int luaK_adjuststack (LexState *ls, int n) {
|
||||
void luaK_adjuststack (LexState *ls, int n) {
|
||||
if (n > 0)
|
||||
return luaK_U(ls, POP, n, -n);
|
||||
luaK_U(ls, POP, n, -n);
|
||||
else if (n < 0)
|
||||
return luaK_U(ls, PUSHNIL, (-n)-1, -n);
|
||||
else return 0;
|
||||
luaK_U(ls, PUSHNIL, (-n)-1, -n);
|
||||
}
|
||||
|
||||
|
||||
int luaK_iscall (LexState *ls, int pc) {
|
||||
return (GET_OPCODE(ls->fs->f->code[pc]) == CALL);
|
||||
int luaK_iscall (LexState *ls, int hasjumps) {
|
||||
if (hasjumps) return 0; /* a call cannot have internal jumps */
|
||||
else /* check whether last instruction is a function call */
|
||||
return (GET_OPCODE(ls->fs->f->code[ls->fs->pc-1]) == CALL);
|
||||
}
|
||||
|
||||
|
||||
void luaK_setcallreturns (LexState *ls, int pc, int nresults) {
|
||||
if (luaK_iscall(ls, pc)) { /* expression is a function call? */
|
||||
Instruction *i = &ls->fs->f->code[pc];
|
||||
int old_nresults = GETARG_B(*i);
|
||||
if (old_nresults != MULT_RET)
|
||||
luaK_deltastack(ls, -old_nresults); /* pop old nresults */
|
||||
*i = SETARG_B(*i, nresults); /* set nresults */
|
||||
if (nresults != MULT_RET)
|
||||
luaK_deltastack(ls, nresults); /* push results */
|
||||
void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) {
|
||||
if (!hasjumps) { /* if `hasjumps' cannot be a function call */
|
||||
Instruction *i = &ls->fs->f->code[ls->fs->pc-1];
|
||||
if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */
|
||||
int old_nresults = GETARG_B(*i);
|
||||
if (old_nresults != MULT_RET)
|
||||
luaK_deltastack(ls, -old_nresults); /* pop old nresults */
|
||||
*i = SETARG_B(*i, nresults); /* set nresults */
|
||||
if (nresults != MULT_RET)
|
||||
luaK_deltastack(ls, nresults); /* push results */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,20 +185,21 @@ static void assertglobal (LexState *ls, int index) {
|
||||
void luaK_2stack (LexState *ls, expdesc *var) {
|
||||
switch (var->k) {
|
||||
case VLOCAL:
|
||||
var->info = luaK_U(ls, PUSHLOCAL, var->info, 1);
|
||||
luaK_U(ls, PUSHLOCAL, var->info, 1);
|
||||
break;
|
||||
case VGLOBAL:
|
||||
luaK_U(ls, GETGLOBAL, var->info, 1);
|
||||
assertglobal(ls, var->info); /* make sure that there is a global */
|
||||
var->info = luaK_U(ls, GETGLOBAL, var->info, 1);
|
||||
break;
|
||||
case VINDEXED:
|
||||
var->info = luaK_0(ls, GETTABLE, -1);
|
||||
luaK_gettable(ls, var);
|
||||
break;
|
||||
case VEXP:
|
||||
luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */
|
||||
break;
|
||||
return; /* does not change var->info */
|
||||
}
|
||||
var->k = VEXP;
|
||||
var->info = NOJUMPS;
|
||||
}
|
||||
|
||||
|
||||
@ -246,10 +223,9 @@ void luaK_storevar (LexState *ls, const expdesc *var) {
|
||||
|
||||
void luaK_prefix (LexState *ls, int op, expdesc *v) {
|
||||
luaK_2stack(ls, v);
|
||||
if (op == '-')
|
||||
v->info = luaK_0(ls, MINUSOP, 0);
|
||||
else
|
||||
v->info = luaK_0(ls, NOTOP, 0);
|
||||
if (op == '-') luaK_minus(ls, v);
|
||||
else luaK_0(ls, NOTOP, 0);
|
||||
v->info = NOJUMPS;
|
||||
}
|
||||
|
||||
|
||||
@ -267,19 +243,20 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) {
|
||||
switch (op) {
|
||||
case AND: case OR:
|
||||
luaK_fixjump(ls, v1->info, ls->fs->pc);
|
||||
break;
|
||||
case '+': v1->info = luaK_0(ls, ADDOP, -1); break;
|
||||
case '-': v1->info = luaK_0(ls, SUBOP, -1); break;
|
||||
case '*': v1->info = luaK_0(ls, MULTOP, -1); break;
|
||||
case '/': v1->info = luaK_0(ls, DIVOP, -1); break;
|
||||
case '^': v1->info = luaK_0(ls, POWOP, -1); break;
|
||||
case CONC: v1->info = luaK_0(ls, CONCOP, -1); break;
|
||||
case EQ: v1->info = luaK_0(ls, EQOP, -1); break;
|
||||
case NE: v1->info = luaK_0(ls, NEQOP, -1); break;
|
||||
case '>': v1->info = luaK_0(ls, GTOP, -1); break;
|
||||
case '<': v1->info = luaK_0(ls, LTOP, -1); break;
|
||||
case GE: v1->info = luaK_0(ls, GEOP, -1); break;
|
||||
case LE: v1->info = luaK_0(ls, LEOP, -1); break;
|
||||
return; /* keep v1->info != NOJUMPS */
|
||||
case '+': luaK_add(ls, v2); break;
|
||||
case '-': luaK_sub(ls, v2); break;
|
||||
case '*': luaK_0(ls, MULTOP, -1); break;
|
||||
case '/': luaK_0(ls, DIVOP, -1); break;
|
||||
case '^': luaK_0(ls, POWOP, -1); break;
|
||||
case CONC: luaK_0(ls, CONCOP, -1); break;
|
||||
case EQ: luaK_0(ls, EQOP, -1); break;
|
||||
case NE: luaK_0(ls, NEQOP, -1); break;
|
||||
case '>': luaK_0(ls, GTOP, -1); break;
|
||||
case '<': luaK_0(ls, LTOP, -1); break;
|
||||
case GE: luaK_0(ls, GEOP, -1); break;
|
||||
case LE: luaK_0(ls, LEOP, -1); break;
|
||||
}
|
||||
v1->info = NOJUMPS;
|
||||
}
|
||||
|
||||
|
25
lcode.h
25
lcode.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.h,v 1.1 2000/02/22 13:31:19 roberto Exp roberto $
|
||||
** $Id: lcode.h,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -13,20 +13,23 @@
|
||||
#include "lparser.h"
|
||||
|
||||
|
||||
#define luaK_0(ls,o,d) luaK_code(ls, CREATE_0(o), d)
|
||||
#define luaK_U(ls,o,u,d) luaK_code(ls, CREATE_U(o,u), d)
|
||||
#define luaK_S(ls,o,s,d) luaK_code(ls, CREATE_S(o,s), d)
|
||||
#define luaK_AB(ls,o,a,b,d) luaK_code(ls, CREATE_AB(o,a,b), d)
|
||||
|
||||
|
||||
void luaK_error (LexState *ls, const char *msg);
|
||||
int luaK_primitivecode (LexState *ls, Instruction i);
|
||||
int luaK_code (LexState *ls, Instruction i);
|
||||
int luaK_code (LexState *ls, Instruction i, int delta);
|
||||
void luaK_retcode (LexState *ls, int nlocals, listdesc *e);
|
||||
void luaK_fixjump (LexState *ls, int pc, int dest);
|
||||
void luaK_deltastack (LexState *ls, int delta);
|
||||
int luaK_0 (LexState *ls, OpCode op, int delta);
|
||||
int luaK_U (LexState *ls, OpCode op, int u, int delta);
|
||||
int luaK_S (LexState *ls, OpCode op, int s, int delta);
|
||||
int luaK_AB (LexState *ls, OpCode op, int a, int b, int delta);
|
||||
int luaK_kstr (LexState *ls, int c);
|
||||
int luaK_number (LexState *ls, real f);
|
||||
int luaK_adjuststack (LexState *ls, int n);
|
||||
int luaK_iscall (LexState *ls, int pc);
|
||||
void luaK_setcallreturns (LexState *ls, int pc, int nresults);
|
||||
void luaK_kstr (LexState *ls, int c);
|
||||
void luaK_number (LexState *ls, real f);
|
||||
void luaK_adjuststack (LexState *ls, int n);
|
||||
int luaK_iscall (LexState *ls, int hasjumps);
|
||||
void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults);
|
||||
void luaK_2stack (LexState *ls, expdesc *var);
|
||||
void luaK_storevar (LexState *ls, const expdesc *var);
|
||||
void luaK_prefix (LexState *ls, int op, expdesc *v);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.h,v 1.42 2000/03/02 12:32:53 roberto Exp roberto $
|
||||
** $Id: lopcodes.h,v 1.43 2000/03/03 14:58:26 roberto Exp roberto $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -47,6 +47,11 @@
|
||||
#define SETARG_A(i,a) (((i)&0x0000FFFFu) | ((Instruction)(a)<<16))
|
||||
#define SETARG_B(i,b) (((i)&0xFFFF00FFu) | ((Instruction)(b)<<8))
|
||||
|
||||
#define CREATE_0(o) ((Instruction)(o))
|
||||
#define CREATE_U(o,u) ((Instruction)(o) | (Instruction)(u)<<8)
|
||||
#define CREATE_S(o,s) ((Instruction)(o) | ((Instruction)(s)+EXCESS_S)<<8)
|
||||
#define CREATE_AB(o,a,b) ((Instruction)(o) | ((Instruction)(a)<<16) \
|
||||
| ((Instruction)(b)<<8))
|
||||
|
||||
|
||||
/*
|
||||
|
85
lparser.c
85
lparser.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.c,v 1.61 2000/03/03 12:33:59 roberto Exp roberto $
|
||||
** $Id: lparser.c,v 1.62 2000/03/03 14:58:26 roberto Exp roberto $
|
||||
** LL(1) Parser and code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -23,15 +23,13 @@
|
||||
|
||||
|
||||
/*
|
||||
** Expression List descriptor:
|
||||
** tells number of expressions in the list,
|
||||
** and, if last expression is open (a function call),
|
||||
** where is the call pc index.
|
||||
** check whether arbitrary limits fit in respective opcode types
|
||||
*/
|
||||
typedef struct listdesc {
|
||||
int n;
|
||||
int pc; /* 0 if last expression is closed */
|
||||
} listdesc;
|
||||
#if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \
|
||||
MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B
|
||||
#error invalid limits
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@ -51,11 +49,11 @@ typedef struct constdesc {
|
||||
/*
|
||||
** prototypes for recursive non-terminal functions
|
||||
*/
|
||||
static int body (LexState *ls, int needself, int line);
|
||||
static void body (LexState *ls, int needself, int line);
|
||||
static void chunk (LexState *ls);
|
||||
static int constructor (LexState *ls);
|
||||
static void constructor (LexState *ls);
|
||||
static void expr (LexState *ls, expdesc *v);
|
||||
static void exp1 (LexState *ls);
|
||||
static int exp1 (LexState *ls);
|
||||
|
||||
|
||||
static void next (LexState *ls) {
|
||||
@ -145,8 +143,8 @@ static int string_constant (LexState *ls, FuncState *fs, TaggedString *s) {
|
||||
}
|
||||
|
||||
|
||||
static int code_string (LexState *ls, TaggedString *s) {
|
||||
return luaK_kstr(ls, string_constant(ls, ls->fs, s));
|
||||
static void code_string (LexState *ls, TaggedString *s) {
|
||||
luaK_kstr(ls, string_constant(ls, ls->fs, s));
|
||||
}
|
||||
|
||||
|
||||
@ -249,18 +247,18 @@ static int indexupvalue (LexState *ls, TaggedString *n) {
|
||||
}
|
||||
|
||||
|
||||
static int pushupvalue (LexState *ls, TaggedString *n) {
|
||||
static void pushupvalue (LexState *ls, TaggedString *n) {
|
||||
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);
|
||||
return luaK_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1);
|
||||
luaK_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1);
|
||||
}
|
||||
|
||||
|
||||
static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) {
|
||||
int diff = d->n - nvars;
|
||||
if (d->n == 0 || !luaK_iscall(ls, d->pc)) { /* list is empty or closed */
|
||||
if (d->n == 0 || !luaK_iscall(ls, d->info)) { /* list is empty or closed */
|
||||
/* push or pop eventual difference between list lengths */
|
||||
luaK_adjuststack(ls, diff);
|
||||
}
|
||||
@ -268,10 +266,10 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) {
|
||||
diff--; /* do not count function call itself */
|
||||
if (diff <= 0) { /* more variables than values? */
|
||||
/* function call must provide extra values */
|
||||
luaK_setcallreturns(ls, d->pc, -diff);
|
||||
luaK_setcallreturns(ls, d->info, -diff);
|
||||
}
|
||||
else { /* more values than variables */
|
||||
luaK_setcallreturns(ls, d->pc, 0); /* call should provide no value */
|
||||
luaK_setcallreturns(ls, d->info, 0); /* call should provide no value */
|
||||
luaK_adjuststack(ls, diff); /* pop eventual extra values */
|
||||
}
|
||||
}
|
||||
@ -308,7 +306,7 @@ static int getvarname (LexState *ls, expdesc *var) {
|
||||
}
|
||||
|
||||
|
||||
static int func_onstack (LexState *ls, FuncState *func) {
|
||||
static void func_onstack (LexState *ls, FuncState *func) {
|
||||
TProtoFunc *f = ls->fs->f;
|
||||
int i;
|
||||
for (i=0; i<func->nupvalues; i++)
|
||||
@ -317,7 +315,7 @@ static int func_onstack (LexState *ls, FuncState *func) {
|
||||
constantEM, MAXARG_A);
|
||||
f->kproto[f->nkproto++] = func->f;
|
||||
luaK_deltastack(ls, 1); /* CLOSURE puts one extra element before popping */
|
||||
return luaK_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues);
|
||||
luaK_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues);
|
||||
}
|
||||
|
||||
|
||||
@ -333,7 +331,6 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) {
|
||||
fs->f = f;
|
||||
f->source = source;
|
||||
fs->pc = 0;
|
||||
fs->last_pc = -1; /* invalid index to signal no last instruction */
|
||||
f->code = NULL;
|
||||
f->maxstacksize = 0;
|
||||
f->numparams = 0; /* default for main chunk */
|
||||
@ -395,7 +392,7 @@ static void explist1 (LexState *ls, listdesc *d) {
|
||||
}
|
||||
luaK_2stack(ls, &v);
|
||||
luaK_setcallreturns(ls, v.info, MULT_RET); /* default for explists */
|
||||
d->pc = v.info;
|
||||
d->info = v.info;
|
||||
}
|
||||
|
||||
|
||||
@ -412,7 +409,7 @@ static void explist (LexState *ls, listdesc *d) {
|
||||
}
|
||||
|
||||
|
||||
static int funcparams (LexState *ls, int slf) {
|
||||
static void funcparams (LexState *ls, int slf) {
|
||||
FuncState *fs = ls->fs;
|
||||
int slevel = fs->stacksize - slf - 1; /* where is func in the stack */
|
||||
switch (ls->token) {
|
||||
@ -443,7 +440,7 @@ static int funcparams (LexState *ls, int slf) {
|
||||
break;
|
||||
}
|
||||
fs->stacksize = slevel; /* call will remove func and params */
|
||||
return luaK_AB(ls, CALL, slevel, 0, 0);
|
||||
luaK_AB(ls, CALL, slevel, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -455,14 +452,15 @@ static void var_or_func_tail (LexState *ls, expdesc *v) {
|
||||
luaK_2stack(ls, v); /* `v' must be on stack */
|
||||
luaK_kstr(ls, checkname(ls));
|
||||
v->k = VINDEXED;
|
||||
v->info = NOJUMPS;
|
||||
break;
|
||||
|
||||
case '[': /* var_or_func_tail -> '[' exp1 ']' */
|
||||
next(ls);
|
||||
luaK_2stack(ls, v); /* `v' must be on stack */
|
||||
exp1(ls);
|
||||
check(ls, ']');
|
||||
v->k = VINDEXED;
|
||||
v->info = exp1(ls);
|
||||
check(ls, ']');
|
||||
break;
|
||||
|
||||
case ':': { /* var_or_func_tail -> ':' NAME funcparams */
|
||||
@ -471,15 +469,17 @@ static void var_or_func_tail (LexState *ls, expdesc *v) {
|
||||
name = checkname(ls);
|
||||
luaK_2stack(ls, v); /* `v' must be on stack */
|
||||
luaK_U(ls, PUSHSELF, name, 1);
|
||||
funcparams(ls, 1);
|
||||
v->k = VEXP;
|
||||
v->info = funcparams(ls, 1);
|
||||
v->info = NOJUMPS;
|
||||
break;
|
||||
}
|
||||
|
||||
case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */
|
||||
luaK_2stack(ls, v); /* `v' must be on stack */
|
||||
funcparams(ls, 0);
|
||||
v->k = VEXP;
|
||||
v->info = funcparams(ls, 0);
|
||||
v->info = NOJUMPS;
|
||||
break;
|
||||
|
||||
default: return; /* should be follow... */
|
||||
@ -491,8 +491,9 @@ static void var_or_func_tail (LexState *ls, expdesc *v) {
|
||||
static void var_or_func (LexState *ls, expdesc *v) {
|
||||
/* var_or_func -> ['%'] NAME var_or_func_tail */
|
||||
if (optional(ls, '%')) { /* upvalue? */
|
||||
pushupvalue(ls, str_checkname(ls));
|
||||
v->k = VEXP;
|
||||
v->info = pushupvalue(ls, str_checkname(ls));
|
||||
v->info = NOJUMPS;
|
||||
}
|
||||
else /* variable name */
|
||||
singlevar(ls, str_checkname(ls), v, 0);
|
||||
@ -614,7 +615,7 @@ static void constructor_part (LexState *ls, constdesc *cd) {
|
||||
}
|
||||
|
||||
|
||||
static int constructor (LexState *ls) {
|
||||
static void constructor (LexState *ls) {
|
||||
/* constructor -> '{' constructor_part [';' constructor_part] '}' */
|
||||
int line = ls->linenumber;
|
||||
int pc = luaK_U(ls, CREATETABLE, 0, 1);
|
||||
@ -634,7 +635,6 @@ static int constructor (LexState *ls) {
|
||||
check_match(ls, '}', '{', line);
|
||||
/* set initial table size */
|
||||
ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems);
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* }====================================================================== */
|
||||
@ -655,28 +655,27 @@ static void simpleexp (LexState *ls, expdesc *v) {
|
||||
case NUMBER: { /* simpleexp -> NUMBER */
|
||||
real r = ls->seminfo.r;
|
||||
next(ls);
|
||||
v->info = luaK_number(ls, r);
|
||||
luaK_number(ls, r);
|
||||
break;
|
||||
}
|
||||
|
||||
case STRING: /* simpleexp -> STRING */
|
||||
/* must use `seminfo' before `next' */
|
||||
v->info = code_string(ls, ls->seminfo.ts);
|
||||
code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */
|
||||
next(ls);
|
||||
break;
|
||||
|
||||
case NIL: /* simpleexp -> NIL */
|
||||
v->info = luaK_adjuststack(ls, -1);
|
||||
luaK_adjuststack(ls, -1);
|
||||
next(ls);
|
||||
break;
|
||||
|
||||
case '{': /* simpleexp -> constructor */
|
||||
v->info = constructor(ls);
|
||||
constructor(ls);
|
||||
break;
|
||||
|
||||
case FUNCTION: /* simpleexp -> FUNCTION body */
|
||||
next(ls);
|
||||
v->info = body(ls, 0, ls->linenumber);
|
||||
body(ls, 0, ls->linenumber);
|
||||
break;
|
||||
|
||||
case '(': /* simpleexp -> '(' expr ')' */
|
||||
@ -694,13 +693,15 @@ static void simpleexp (LexState *ls, expdesc *v) {
|
||||
return;
|
||||
}
|
||||
v->k = VEXP;
|
||||
v->info = NOJUMPS;
|
||||
}
|
||||
|
||||
|
||||
static void exp1 (LexState *ls) {
|
||||
static int exp1 (LexState *ls) {
|
||||
expdesc v;
|
||||
expr(ls, &v);
|
||||
luaK_2stack(ls, &v);
|
||||
return v.info;
|
||||
}
|
||||
|
||||
|
||||
@ -1052,7 +1053,7 @@ static void parlist (LexState *ls) {
|
||||
}
|
||||
|
||||
|
||||
static int body (LexState *ls, int needself, int line) {
|
||||
static void body (LexState *ls, int needself, int line) {
|
||||
/* body -> '(' parlist ')' chunk END */
|
||||
FuncState new_fs;
|
||||
init_state(ls, &new_fs, ls->fs->f->source);
|
||||
@ -1065,7 +1066,7 @@ static int body (LexState *ls, int needself, int line) {
|
||||
chunk(ls);
|
||||
check_match(ls, END, FUNCTION, line);
|
||||
close_func(ls);
|
||||
return func_onstack(ls, &new_fs);
|
||||
func_onstack(ls, &new_fs);
|
||||
}
|
||||
|
||||
|
||||
@ -1076,7 +1077,7 @@ static void ret (LexState *ls) {
|
||||
check_debugline(ls);
|
||||
next(ls);
|
||||
explist(ls, &e);
|
||||
luaK_U(ls, RETCODE, ls->fs->nlocalvar, 0);
|
||||
luaK_retcode(ls, ls->fs->nlocalvar, &e);
|
||||
ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */
|
||||
optional(ls, ';');
|
||||
}
|
||||
|
28
lparser.h
28
lparser.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.h,v 1.7 2000/03/03 12:33:59 roberto Exp roberto $
|
||||
** $Id: lparser.h,v 1.8 2000/03/03 14:58:26 roberto Exp roberto $
|
||||
** LL(1) Parser and code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -8,7 +8,6 @@
|
||||
#define lparser_h
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
@ -42,21 +41,18 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \
|
||||
MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B
|
||||
#error invalid limits
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Expression descriptor
|
||||
*/
|
||||
|
||||
#define NOJUMPS 0
|
||||
|
||||
typedef enum {
|
||||
VGLOBAL, /* info is constant index of global name */
|
||||
VLOCAL, /* info is stack index */
|
||||
VINDEXED, /* no info (table and index are on the stack) */
|
||||
VEXP /* info is pc index of exp main operator */
|
||||
VINDEXED, /* info is info of the index expression */
|
||||
VEXP /* info is NOJUMPS if exp has no internal jumps */
|
||||
} expkind;
|
||||
|
||||
typedef struct expdesc {
|
||||
@ -65,12 +61,22 @@ typedef struct expdesc {
|
||||
} expdesc;
|
||||
|
||||
|
||||
/*
|
||||
** Expression List descriptor:
|
||||
** tells number of expressions in the list,
|
||||
** and gives the `info' of last expression.
|
||||
*/
|
||||
typedef struct listdesc {
|
||||
int n;
|
||||
int info; /* 0 if last expression has no internal jumps */
|
||||
} listdesc;
|
||||
|
||||
|
||||
/* state needed to generate code for a given function */
|
||||
typedef struct FuncState {
|
||||
TProtoFunc *f; /* current function header */
|
||||
struct FuncState *prev; /* enclosing function */
|
||||
int pc; /* next position to code */
|
||||
int last_pc; /* last instruction coded (for optimizations) */
|
||||
int stacksize; /* number of values on activation register */
|
||||
int nlocalvar; /* number of active local variables */
|
||||
int nupvalues; /* number of upvalues */
|
||||
|
Loading…
x
Reference in New Issue
Block a user