|
|
@ -1,10 +1,8 @@ |
|
|
|
%{ |
|
|
|
|
|
|
|
char *rcs_luastx = "$Id: lua.stx,v 3.47 1997/06/19 17:46:12 roberto Exp roberto $"; |
|
|
|
char *rcs_luastx = "$Id: lua.stx,v 3.48 1997/07/29 20:38:45 roberto Exp roberto $"; |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
#include "luadebug.h" |
|
|
|
#include "luamem.h" |
|
|
@ -40,6 +38,7 @@ struct State { |
|
|
|
int pc; /* next position to code */ |
|
|
|
TaggedString *localvar[MAXLOCALS]; /* store local variable names */ |
|
|
|
int nlocalvar; /* number of active local variables */ |
|
|
|
int maxconsts; /* size of consts vector */ |
|
|
|
int nvars; /* total number of local variables (for debugging information) */ |
|
|
|
int maxvars; /* = -1 if no debug information */ |
|
|
|
} stateMain, stateFunc, *currState; |
|
|
@ -69,41 +68,106 @@ static void check_space (int i) |
|
|
|
Byte, codeEM, MAX_INT); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void code_byte (Byte c) |
|
|
|
{ |
|
|
|
check_space(1); |
|
|
|
currState->f->code[currState->pc++] = c; |
|
|
|
} |
|
|
|
|
|
|
|
static void code_float (real n) |
|
|
|
|
|
|
|
static void code_word_at (int pc, int n) |
|
|
|
{ |
|
|
|
check_space(sizeof(real)); |
|
|
|
memcpy(currState->f->code+currState->pc, &n, sizeof(real)); |
|
|
|
currState->pc += sizeof(real); |
|
|
|
Word w = n; |
|
|
|
if (w != n) |
|
|
|
yyerror("block too big"); |
|
|
|
currState->f->code[pc] = n&0xFF; |
|
|
|
currState->f->code[pc+1] = n>>8; |
|
|
|
} |
|
|
|
|
|
|
|
static void code_code (TFunc *tf) |
|
|
|
static void code_word (int n) |
|
|
|
{ |
|
|
|
check_space(sizeof(TFunc *)); |
|
|
|
memcpy(currState->f->code+currState->pc, &tf, sizeof(TFunc *)); |
|
|
|
currState->pc += sizeof(TFunc *); |
|
|
|
code_byte(n&0xFF); |
|
|
|
code_byte(n>>8); |
|
|
|
} |
|
|
|
|
|
|
|
static void code_word_at (int pc, int n) |
|
|
|
static void code_constant (int c) |
|
|
|
{ |
|
|
|
Word w = n; |
|
|
|
if (w != n) |
|
|
|
yyerror("block too big"); |
|
|
|
memcpy(currState->f->code+pc, &w, sizeof(Word)); |
|
|
|
if (c <= 255) { |
|
|
|
code_byte(PUSHCONSTANTB); |
|
|
|
code_byte(c); |
|
|
|
} |
|
|
|
else { |
|
|
|
code_byte(PUSHCONSTANT); |
|
|
|
code_word(c); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int next_constant (void) |
|
|
|
{ |
|
|
|
if (currState->f->nconsts >= currState->maxconsts) { |
|
|
|
currState->maxconsts = |
|
|
|
growvector(&currState->f->consts, currState->maxconsts, |
|
|
|
TObject, constantEM, MAX_WORD); |
|
|
|
} |
|
|
|
return currState->f->nconsts++; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int string_constant (TaggedString *s) |
|
|
|
{ |
|
|
|
int c = s->u.s.constindex; |
|
|
|
if (!(0 <= c && c < currState->f->nconsts && |
|
|
|
ttype(&currState->f->consts[c]) == LUA_T_STRING && |
|
|
|
tsvalue(&currState->f->consts[c]) == s)) { |
|
|
|
c = next_constant(); |
|
|
|
ttype(&currState->f->consts[c]) = LUA_T_STRING; |
|
|
|
tsvalue(&currState->f->consts[c]) = s; |
|
|
|
s->u.s.constindex = c; /* hint for next time */ |
|
|
|
luaI_releasestring(s); |
|
|
|
} |
|
|
|
return c; |
|
|
|
} |
|
|
|
|
|
|
|
static void code_word (Word n) |
|
|
|
|
|
|
|
static void code_string (TaggedString *s) |
|
|
|
{ |
|
|
|
check_space(sizeof(Word)); |
|
|
|
memcpy(currState->f->code+currState->pc, &n, sizeof(Word)); |
|
|
|
currState->pc += sizeof(Word); |
|
|
|
int c = string_constant(s); |
|
|
|
code_constant(c); |
|
|
|
} |
|
|
|
|
|
|
|
static void code_float (real n) |
|
|
|
{ |
|
|
|
int c = next_constant(); |
|
|
|
ttype(&currState->f->consts[c]) = LUA_T_NUMBER; |
|
|
|
nvalue(&currState->f->consts[c]) = n; |
|
|
|
code_constant(c); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void code_number (float f) |
|
|
|
{ |
|
|
|
Word i; |
|
|
|
if (f >= 0 && f <= (float)MAX_WORD && (float)(i=(Word)f) == f) { |
|
|
|
/* f has an (short) integer value */ |
|
|
|
if (i <= 2) code_byte(PUSH0 + i); |
|
|
|
else if (i <= 255) |
|
|
|
{ |
|
|
|
code_byte(PUSHBYTE); |
|
|
|
code_byte(i); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
code_byte(PUSHWORD); |
|
|
|
code_word(i); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
code_float(f); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void flush_record (int n) |
|
|
|
{ |
|
|
|
if (n == 0) return; |
|
|
@ -149,6 +213,7 @@ static void luaI_unregisterlocalvar (int line) |
|
|
|
|
|
|
|
static void store_localvar (TaggedString *name, int n) |
|
|
|
{ |
|
|
|
luaI_fixstring(name); /* local var names cannot be GC */ |
|
|
|
if (currState->nlocalvar+n < MAXLOCALS) |
|
|
|
currState->localvar[currState->nlocalvar+n] = name; |
|
|
|
else |
|
|
@ -170,40 +235,6 @@ static void add_varbuffer (Long var) |
|
|
|
yyerror ("variable buffer overflow"); |
|
|
|
} |
|
|
|
|
|
|
|
static void code_string (Word w) |
|
|
|
{ |
|
|
|
code_byte(PUSHSTRING); |
|
|
|
code_word(w); |
|
|
|
} |
|
|
|
|
|
|
|
static void code_constant (TaggedString *s) |
|
|
|
{ |
|
|
|
code_string(luaI_findconstant(s)); |
|
|
|
} |
|
|
|
|
|
|
|
static void code_number (float f) |
|
|
|
{ |
|
|
|
Word i; |
|
|
|
if (f >= 0 && f <= (float)MAX_WORD && (float)(i=(Word)f) == f) { |
|
|
|
/* f has an (short) integer value */ |
|
|
|
if (i <= 2) code_byte(PUSH0 + i); |
|
|
|
else if (i <= 255) |
|
|
|
{ |
|
|
|
code_byte(PUSHBYTE); |
|
|
|
code_byte(i); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
code_byte(PUSHWORD); |
|
|
|
code_word(i); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
code_byte(PUSHFLOAT); |
|
|
|
code_float(f); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
** Search a local name and if find return its index. If do not find return -1 |
|
|
@ -256,55 +287,6 @@ static void lua_codeadjust (int n) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void init_state (TFunc *f) |
|
|
|
{ |
|
|
|
luaI_initTFunc(f); |
|
|
|
currState->nlocalvar = 0; |
|
|
|
currState->f = f; |
|
|
|
currState->pc = 0; |
|
|
|
currState->codesize = CODE_BLOCK; |
|
|
|
f->code = newvector(CODE_BLOCK, Byte); |
|
|
|
if (lua_debug) { |
|
|
|
currState->nvars = 0; |
|
|
|
currState->maxvars = 0; |
|
|
|
} |
|
|
|
else |
|
|
|
currState->maxvars = -1; /* flag no debug information */ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void init_func (void) |
|
|
|
{ |
|
|
|
currState = &stateFunc; |
|
|
|
init_state(new(TFunc)); |
|
|
|
luaI_codedebugline(lua_linenumber); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void codereturn (void) |
|
|
|
{ |
|
|
|
if (currState->nlocalvar == 0) |
|
|
|
code_byte(RETCODE0); |
|
|
|
else |
|
|
|
{ |
|
|
|
code_byte(RETCODE); |
|
|
|
code_byte(currState->nlocalvar); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void close_func (void) |
|
|
|
{ |
|
|
|
codereturn(); |
|
|
|
code_byte(ENDCODE); |
|
|
|
currState->f->code = shrinkvector(currState->f->code, currState->pc, Byte); |
|
|
|
if (currState->maxvars != -1) { /* debug information? */ |
|
|
|
luaI_registerlocalvar(NULL, -1); /* flag end of vector */ |
|
|
|
currState->f->locvars = shrinkvector(currState->f->locvars, |
|
|
|
currState->nvars, LocVar); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void luaI_codedebugline (int line) |
|
|
|
{ |
|
|
@ -350,7 +332,7 @@ static int close_parlist (int dots) |
|
|
|
else { |
|
|
|
code_byte(VARARGS); |
|
|
|
code_byte(currState->nlocalvar); |
|
|
|
add_localvar(luaI_createfixedstring("arg")); |
|
|
|
add_localvar(luaI_createstring("arg")); |
|
|
|
} |
|
|
|
return lua_linenumber; |
|
|
|
} |
|
|
@ -423,6 +405,65 @@ static void code_shortcircuit (int pc, Byte jmp) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void init_state (TFunc *f) |
|
|
|
{ |
|
|
|
currState->nlocalvar = 0; |
|
|
|
currState->f = f; |
|
|
|
currState->pc = 0; |
|
|
|
currState->codesize = CODE_BLOCK; |
|
|
|
f->code = newvector(CODE_BLOCK, Byte); |
|
|
|
currState->maxconsts = 0; |
|
|
|
if (lua_debug) { |
|
|
|
currState->nvars = 0; |
|
|
|
currState->maxvars = 0; |
|
|
|
} |
|
|
|
else |
|
|
|
currState->maxvars = -1; /* flag no debug information */ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void init_func (Long v) |
|
|
|
{ |
|
|
|
TFunc *f = new(TFunc); |
|
|
|
int c = next_constant(); |
|
|
|
ttype(&currState->f->consts[c]) = LUA_T_FUNCTION; |
|
|
|
currState->f->consts[c].value.tf = f; |
|
|
|
code_constant(c); |
|
|
|
storesinglevar(v); |
|
|
|
currState = &stateFunc; |
|
|
|
luaI_initTFunc(f); |
|
|
|
init_state(f); |
|
|
|
luaI_codedebugline(lua_linenumber); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void codereturn (void) |
|
|
|
{ |
|
|
|
if (currState->nlocalvar == 0) |
|
|
|
code_byte(RETCODE0); |
|
|
|
else |
|
|
|
{ |
|
|
|
code_byte(RETCODE); |
|
|
|
code_byte(currState->nlocalvar); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void close_func (void) |
|
|
|
{ |
|
|
|
codereturn(); |
|
|
|
code_byte(ENDCODE); |
|
|
|
currState->f->code = shrinkvector(currState->f->code, currState->pc, Byte); |
|
|
|
currState->f->consts = shrinkvector(currState->f->consts, |
|
|
|
currState->f->nconsts, TObject); |
|
|
|
if (currState->maxvars != -1) { /* debug information? */ |
|
|
|
luaI_registerlocalvar(NULL, -1); /* flag end of vector */ |
|
|
|
currState->f->locvars = shrinkvector(currState->f->locvars, |
|
|
|
currState->nvars, LocVar); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
** Parse LUA code. |
|
|
|
*/ |
|
|
@ -444,9 +485,7 @@ void lua_parse (TFunc *tf) |
|
|
|
int vInt; |
|
|
|
float vFloat; |
|
|
|
char *pChar; |
|
|
|
Word vWord; |
|
|
|
Long vLong; |
|
|
|
TFunc *pFunc; |
|
|
|
TaggedString *pTStr; |
|
|
|
} |
|
|
|
|
|
|
@ -460,8 +499,7 @@ void lua_parse (TFunc *tf) |
|
|
|
%token FUNCTION |
|
|
|
%token DOTS |
|
|
|
%token <vFloat> NUMBER |
|
|
|
%token <vWord> STRING |
|
|
|
%token <pTStr> NAME |
|
|
|
%token <pTStr> NAME STRING |
|
|
|
|
|
|
|
%type <vLong> PrepJump |
|
|
|
%type <vLong> exprlist, exprlist1 /* if > 0, points to function return |
|
|
@ -473,8 +511,7 @@ void lua_parse (TFunc *tf) |
|
|
|
%type <vInt> ffieldlist, ffieldlist1, semicolonpart |
|
|
|
%type <vInt> lfieldlist, lfieldlist1 |
|
|
|
%type <vInt> parlist, parlist1, par |
|
|
|
%type <vLong> var, singlevar, funcname |
|
|
|
%type <pFunc> body |
|
|
|
%type <vLong> var, singlevar |
|
|
|
|
|
|
|
%left AND OR |
|
|
|
%left EQ NE '>' '<' LE GE |
|
|
@ -495,28 +532,21 @@ chunklist : /* empty */ |
|
|
|
; |
|
|
|
|
|
|
|
function : FUNCTION funcname body |
|
|
|
{ |
|
|
|
code_byte(PUSHFUNCTION); |
|
|
|
code_code($3); |
|
|
|
storesinglevar($2); |
|
|
|
} |
|
|
|
; |
|
|
|
|
|
|
|
funcname : var { $$ =$1; init_func(); } |
|
|
|
funcname : var { init_func($1); } |
|
|
|
| varexp ':' NAME |
|
|
|
{ |
|
|
|
code_constant($3); |
|
|
|
$$ = 0; /* indexed variable */ |
|
|
|
init_func(); |
|
|
|
add_localvar(luaI_createfixedstring("self")); |
|
|
|
code_string($3); |
|
|
|
init_func(0); /* indexed variable */ |
|
|
|
add_localvar(luaI_createstring("self")); |
|
|
|
} |
|
|
|
; |
|
|
|
|
|
|
|
body : '(' parlist ')' block END |
|
|
|
{ |
|
|
|
close_func(); |
|
|
|
$$ = currState->f; |
|
|
|
$$->lineDefined = $2; |
|
|
|
currState->f->lineDefined = $2; |
|
|
|
currState = &stateMain; /* change back to main code */ |
|
|
|
} |
|
|
|
; |
|
|
@ -658,7 +688,7 @@ funcvalue : varexp { $$ = 0; } |
|
|
|
| varexp ':' NAME |
|
|
|
{ |
|
|
|
code_byte(PUSHSELF); |
|
|
|
code_word(luaI_findconstant($3)); |
|
|
|
code_word(string_constant($3)); |
|
|
|
$$ = 1; |
|
|
|
} |
|
|
|
; |
|
|
@ -735,7 +765,7 @@ ffield : ffieldkey '=' expr1 |
|
|
|
; |
|
|
|
|
|
|
|
ffieldkey : '[' expr1 ']' |
|
|
|
| NAME { code_constant($1); } |
|
|
|
| NAME { code_string($1); } |
|
|
|
; |
|
|
|
|
|
|
|
lfieldlist : /* empty */ { $$ = 0; } |
|
|
@ -771,7 +801,7 @@ var : singlevar { $$ = $1; } |
|
|
|
} |
|
|
|
| varexp '.' NAME |
|
|
|
{ |
|
|
|
code_constant($3); |
|
|
|
code_string($3); |
|
|
|
$$ = 0; /* indexed variable */ |
|
|
|
} |
|
|
|
; |
|
|
@ -783,6 +813,7 @@ singlevar : NAME |
|
|
|
$$ = luaI_findsymbol($1)+1; /* return positive value */ |
|
|
|
else |
|
|
|
$$ = -(local+1); /* return negative value */ |
|
|
|
luaI_fixstring($1); /* cannot GC variable names */ |
|
|
|
} |
|
|
|
; |
|
|
|
|
|
|
|