|
@@ -1,6 +1,6 @@
|
|
|
%{
|
|
|
|
|
|
-char *rcs_luastx = "$Id: lua.stx,v 3.46 1997/03/31 14:19:01 roberto Exp roberto $";
|
|
|
+char *rcs_luastx = "$Id: lua.stx,v 3.47 1997/06/19 17:46:12 roberto Exp roberto $";
|
|
|
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
@@ -28,16 +28,21 @@ int yyparse (void);
|
|
|
#endif
|
|
|
|
|
|
#ifndef CODE_BLOCK
|
|
|
-#define CODE_BLOCK 256
|
|
|
+#define CODE_BLOCK 1000
|
|
|
#endif
|
|
|
-static int maxcode;
|
|
|
-static int maxmain;
|
|
|
-static int maxcurr;
|
|
|
-static Byte *funcCode = NULL;
|
|
|
-static Byte **initcode;
|
|
|
-static Byte *basepc;
|
|
|
-static int maincode;
|
|
|
-static int pc;
|
|
|
+
|
|
|
+#define MAXLOCALS 32
|
|
|
+
|
|
|
+/* state needed to generate code for a given function */
|
|
|
+struct State {
|
|
|
+ TFunc *f; /* current function header */
|
|
|
+ int codesize;
|
|
|
+ int pc; /* next position to code */
|
|
|
+ TaggedString *localvar[MAXLOCALS]; /* store local variable names */
|
|
|
+ int nlocalvar; /* number of active local variables */
|
|
|
+ int nvars; /* total number of local variables (for debugging information) */
|
|
|
+ int maxvars; /* = -1 if no debug information */
|
|
|
+} stateMain, stateFunc, *currState;
|
|
|
|
|
|
|
|
|
#define MAXVAR 32
|
|
@@ -45,9 +50,6 @@ static Long varbuffer[MAXVAR]; /* variables in an assignment list;
|
|
|
it's long to store negative Word values */
|
|
|
static int nvarbuffer=0; /* number of variables at a list */
|
|
|
|
|
|
-#define MAXLOCALS 32
|
|
|
-static TaggedString *localvar[MAXLOCALS]; /* store local variable names */
|
|
|
-static int nlocalvar=0; /* number of local variables */
|
|
|
|
|
|
#define MAXFIELDS FIELDS_PER_FLUSH*2
|
|
|
|
|
@@ -62,43 +64,44 @@ static void yyerror (char *s)
|
|
|
|
|
|
static void check_space (int i)
|
|
|
{
|
|
|
- if (pc+i>maxcurr-1) /* 1 byte free to code HALT of main code */
|
|
|
- maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT);
|
|
|
+ if (currState->pc+i >= currState->codesize)
|
|
|
+ currState->codesize = growvector(&currState->f->code, currState->codesize,
|
|
|
+ Byte, codeEM, MAX_INT);
|
|
|
}
|
|
|
|
|
|
static void code_byte (Byte c)
|
|
|
{
|
|
|
- check_space(1);
|
|
|
- basepc[pc++] = c;
|
|
|
-}
|
|
|
-
|
|
|
-static void code_word (Word n)
|
|
|
-{
|
|
|
- check_space(sizeof(Word));
|
|
|
- memcpy(basepc+pc, &n, sizeof(Word));
|
|
|
- pc += sizeof(Word);
|
|
|
+ check_space(1);
|
|
|
+ currState->f->code[currState->pc++] = c;
|
|
|
}
|
|
|
|
|
|
static void code_float (real n)
|
|
|
{
|
|
|
check_space(sizeof(real));
|
|
|
- memcpy(basepc+pc, &n, sizeof(real));
|
|
|
- pc += sizeof(real);
|
|
|
+ memcpy(currState->f->code+currState->pc, &n, sizeof(real));
|
|
|
+ currState->pc += sizeof(real);
|
|
|
}
|
|
|
|
|
|
static void code_code (TFunc *tf)
|
|
|
{
|
|
|
check_space(sizeof(TFunc *));
|
|
|
- memcpy(basepc+pc, &tf, sizeof(TFunc *));
|
|
|
- pc += sizeof(TFunc *);
|
|
|
+ memcpy(currState->f->code+currState->pc, &tf, sizeof(TFunc *));
|
|
|
+ currState->pc += sizeof(TFunc *);
|
|
|
}
|
|
|
|
|
|
-static void code_word_at (Byte *p, int n)
|
|
|
+static void code_word_at (int pc, int n)
|
|
|
{
|
|
|
Word w = n;
|
|
|
if (w != n)
|
|
|
yyerror("block too big");
|
|
|
- memcpy(p, &w, sizeof(Word));
|
|
|
+ memcpy(currState->f->code+pc, &w, sizeof(Word));
|
|
|
+}
|
|
|
+
|
|
|
+static void code_word (Word n)
|
|
|
+{
|
|
|
+ check_space(sizeof(Word));
|
|
|
+ memcpy(currState->f->code+currState->pc, &n, sizeof(Word));
|
|
|
+ currState->pc += sizeof(Word);
|
|
|
}
|
|
|
|
|
|
static void flush_record (int n)
|
|
@@ -124,20 +127,39 @@ static void flush_list (int m, int n)
|
|
|
code_byte(n);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static void luaI_registerlocalvar (TaggedString *varname, int line)
|
|
|
+{
|
|
|
+ if (currState->maxvars != -1) { /* debug information? */
|
|
|
+ if (currState->nvars >= currState->maxvars)
|
|
|
+ currState->maxvars = growvector(&currState->f->locvars,
|
|
|
+ currState->maxvars, LocVar, "", MAX_WORD);
|
|
|
+ currState->f->locvars[currState->nvars].varname = varname;
|
|
|
+ currState->f->locvars[currState->nvars].line = line;
|
|
|
+ currState->nvars++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void luaI_unregisterlocalvar (int line)
|
|
|
+{
|
|
|
+ luaI_registerlocalvar(NULL, line);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static void store_localvar (TaggedString *name, int n)
|
|
|
{
|
|
|
- if (nlocalvar+n < MAXLOCALS)
|
|
|
- localvar[nlocalvar+n] = name;
|
|
|
- else
|
|
|
- yyerror ("too many local variables");
|
|
|
- if (lua_debug)
|
|
|
- luaI_registerlocalvar(name, lua_linenumber);
|
|
|
+ if (currState->nlocalvar+n < MAXLOCALS)
|
|
|
+ currState->localvar[currState->nlocalvar+n] = name;
|
|
|
+ else
|
|
|
+ yyerror ("too many local variables");
|
|
|
+ luaI_registerlocalvar(name, lua_linenumber);
|
|
|
}
|
|
|
|
|
|
static void add_localvar (TaggedString *name)
|
|
|
{
|
|
|
store_localvar(name, 0);
|
|
|
- nlocalvar++;
|
|
|
+ currState->nlocalvar++;
|
|
|
}
|
|
|
|
|
|
static void add_varbuffer (Long var)
|
|
@@ -189,9 +211,9 @@ static void code_number (float f)
|
|
|
static int lua_localname (TaggedString *n)
|
|
|
{
|
|
|
int i;
|
|
|
- for (i=nlocalvar-1; i >= 0; i--)
|
|
|
- if (n == localvar[i]) return i; /* local var */
|
|
|
- return -1; /* global var */
|
|
|
+ for (i=currState->nlocalvar-1; i >= 0; i--)
|
|
|
+ if (n == currState->localvar[i]) return i; /* local var */
|
|
|
+ return -1; /* global var */
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -224,53 +246,66 @@ static void lua_pushvar (Long number)
|
|
|
|
|
|
static void lua_codeadjust (int n)
|
|
|
{
|
|
|
- if (n+nlocalvar == 0)
|
|
|
- code_byte(ADJUST0);
|
|
|
- else
|
|
|
- {
|
|
|
- code_byte(ADJUST);
|
|
|
- code_byte(n+nlocalvar);
|
|
|
- }
|
|
|
+ n += currState->nlocalvar;
|
|
|
+ if (n == 0)
|
|
|
+ code_byte(ADJUST0);
|
|
|
+ else {
|
|
|
+ code_byte(ADJUST);
|
|
|
+ code_byte(n);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-static void change2main (void)
|
|
|
-{
|
|
|
- /* (re)store main values */
|
|
|
- pc=maincode; basepc=*initcode; maxcurr=maxmain;
|
|
|
- nlocalvar=0;
|
|
|
-}
|
|
|
|
|
|
-static void savemain (void)
|
|
|
+static void init_state (TFunc *f)
|
|
|
{
|
|
|
- /* save main values */
|
|
|
- maincode=pc; *initcode=basepc; maxmain=maxcurr;
|
|
|
+ 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)
|
|
|
{
|
|
|
- if (funcCode == NULL) /* first function */
|
|
|
- {
|
|
|
- funcCode = newvector(CODE_BLOCK, Byte);
|
|
|
- maxcode = CODE_BLOCK;
|
|
|
- }
|
|
|
- savemain(); /* save main values */
|
|
|
- /* set func values */
|
|
|
- pc=0; basepc=funcCode; maxcurr=maxcode;
|
|
|
- nlocalvar = 0;
|
|
|
+ currState = &stateFunc;
|
|
|
+ init_state(new(TFunc));
|
|
|
luaI_codedebugline(lua_linenumber);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static void codereturn (void)
|
|
|
{
|
|
|
- if (nlocalvar == 0)
|
|
|
+ if (currState->nlocalvar == 0)
|
|
|
code_byte(RETCODE0);
|
|
|
else
|
|
|
{
|
|
|
code_byte(RETCODE);
|
|
|
- code_byte(nlocalvar);
|
|
|
+ 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)
|
|
|
{
|
|
|
static int lastline = 0;
|
|
@@ -286,23 +321,20 @@ static int adjust_functioncall (Long exp, int i)
|
|
|
{
|
|
|
if (exp <= 0)
|
|
|
return -exp; /* exp is -list length */
|
|
|
- else
|
|
|
- {
|
|
|
- int temp = basepc[exp];
|
|
|
- basepc[exp] = i;
|
|
|
+ else {
|
|
|
+ int temp = currState->f->code[exp];
|
|
|
+ currState->f->code[exp] = i;
|
|
|
return temp+i;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void adjust_mult_assign (int vars, Long exps, int temps)
|
|
|
{
|
|
|
- if (exps > 0)
|
|
|
- { /* must correct function call */
|
|
|
- int diff = vars - basepc[exps];
|
|
|
+ if (exps > 0) { /* must correct function call */
|
|
|
+ int diff = vars - currState->f->code[exps];
|
|
|
if (diff >= 0)
|
|
|
adjust_functioncall(exps, diff);
|
|
|
- else
|
|
|
- {
|
|
|
+ else {
|
|
|
adjust_functioncall(exps, 0);
|
|
|
lua_codeadjust(temps);
|
|
|
}
|
|
@@ -315,15 +347,15 @@ static int close_parlist (int dots)
|
|
|
{
|
|
|
if (!dots)
|
|
|
lua_codeadjust(0);
|
|
|
- else
|
|
|
- {
|
|
|
+ else {
|
|
|
code_byte(VARARGS);
|
|
|
- code_byte(nlocalvar);
|
|
|
+ code_byte(currState->nlocalvar);
|
|
|
add_localvar(luaI_createfixedstring("arg"));
|
|
|
}
|
|
|
return lua_linenumber;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static void storesinglevar (Long v)
|
|
|
{
|
|
|
if (v > 0) /* global var */
|
|
@@ -345,6 +377,7 @@ static void storesinglevar (Long v)
|
|
|
code_byte(STOREINDEXED0);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static void lua_codestore (int i)
|
|
|
{
|
|
|
if (varbuffer[i] != 0) /* global or local var */
|
|
@@ -370,18 +403,23 @@ static void lua_codestore (int i)
|
|
|
static void codeIf (Long thenAdd, Long elseAdd)
|
|
|
{
|
|
|
Long elseinit = elseAdd+sizeof(Word)+1;
|
|
|
- if (pc == elseinit) /* no else */
|
|
|
- {
|
|
|
- pc -= sizeof(Word)+1;
|
|
|
- elseinit = pc;
|
|
|
+ if (currState->pc == elseinit) { /* no else */
|
|
|
+ currState->pc -= sizeof(Word)+1;
|
|
|
+ elseinit = currState->pc;
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- basepc[elseAdd] = JMP;
|
|
|
- code_word_at(basepc+elseAdd+1, pc-elseinit);
|
|
|
+ else {
|
|
|
+ currState->f->code[elseAdd] = JMP;
|
|
|
+ code_word_at(elseAdd+1, currState->pc-elseinit);
|
|
|
}
|
|
|
- basepc[thenAdd] = IFFJMP;
|
|
|
- code_word_at(basepc+thenAdd+1,elseinit-(thenAdd+sizeof(Word)+1));
|
|
|
+ currState->f->code[thenAdd] = IFFJMP;
|
|
|
+ code_word_at(thenAdd+1, elseinit-(thenAdd+sizeof(Word)+1));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void code_shortcircuit (int pc, Byte jmp)
|
|
|
+{
|
|
|
+ currState->f->code[pc] = jmp;
|
|
|
+ code_word_at(pc+1, currState->pc - (pc + sizeof(Word)+1));
|
|
|
}
|
|
|
|
|
|
|
|
@@ -390,19 +428,11 @@ static void codeIf (Long thenAdd, Long elseAdd)
|
|
|
*/
|
|
|
void lua_parse (TFunc *tf)
|
|
|
{
|
|
|
- initcode = &(tf->code);
|
|
|
- *initcode = newvector(CODE_BLOCK, Byte);
|
|
|
- maincode = 0;
|
|
|
- maxmain = CODE_BLOCK;
|
|
|
- change2main();
|
|
|
- if (yyparse ()) lua_error("parse error");
|
|
|
- savemain();
|
|
|
- (*initcode)[maincode++] = RETCODE0;
|
|
|
- tf->size = maincode;
|
|
|
-#if LISTING
|
|
|
-{ static void PrintCode (Byte *c, Byte *end);
|
|
|
- PrintCode(*initcode,*initcode+maincode); }
|
|
|
-#endif
|
|
|
+ currState = &stateMain;
|
|
|
+ init_state(tf);
|
|
|
+ if (yyparse ()) lua_error("parse error");
|
|
|
+ currState = &stateMain;
|
|
|
+ close_func();
|
|
|
}
|
|
|
|
|
|
|
|
@@ -484,21 +514,10 @@ funcname : var { $$ =$1; init_func(); }
|
|
|
|
|
|
body : '(' parlist ')' block END
|
|
|
{
|
|
|
- codereturn();
|
|
|
- $$ = new(TFunc);
|
|
|
- luaI_initTFunc($$);
|
|
|
- $$->size = pc;
|
|
|
- $$->code = newvector(pc, Byte);
|
|
|
+ close_func();
|
|
|
+ $$ = currState->f;
|
|
|
$$->lineDefined = $2;
|
|
|
- memcpy($$->code, basepc, pc*sizeof(Byte));
|
|
|
- if (lua_debug)
|
|
|
- luaI_closelocalvars($$);
|
|
|
- /* save func values */
|
|
|
- funcCode = basepc; maxcode=maxcurr;
|
|
|
-#if LISTING
|
|
|
- PrintCode(funcCode,funcCode+pc);
|
|
|
-#endif
|
|
|
- change2main(); /* change back to main code */
|
|
|
+ currState = &stateMain; /* change back to main code */
|
|
|
}
|
|
|
;
|
|
|
|
|
@@ -511,18 +530,18 @@ sc : /* empty */ | ';' ;
|
|
|
stat : IF expr1 THEN PrepJump block PrepJump elsepart END
|
|
|
{ codeIf($4, $6); }
|
|
|
|
|
|
- | WHILE {$<vLong>$=pc;} expr1 DO PrepJump block PrepJump END
|
|
|
+ | WHILE {$<vLong>$=currState->pc;} expr1 DO PrepJump block PrepJump END
|
|
|
{
|
|
|
- basepc[$5] = IFFJMP;
|
|
|
- code_word_at(basepc+$5+1, pc - ($5 + sizeof(Word)+1));
|
|
|
- basepc[$7] = UPJMP;
|
|
|
- code_word_at(basepc+$7+1, pc - ($<vLong>2));
|
|
|
+ currState->f->code[$5] = IFFJMP;
|
|
|
+ code_word_at($5+1, currState->pc - ($5+sizeof(Word)+1));
|
|
|
+ currState->f->code[$7] = UPJMP;
|
|
|
+ code_word_at($7+1, currState->pc - ($<vLong>2));
|
|
|
}
|
|
|
|
|
|
- | REPEAT {$<vLong>$=pc;} block UNTIL expr1 PrepJump
|
|
|
+ | REPEAT {$<vLong>$=currState->pc;} block UNTIL expr1 PrepJump
|
|
|
{
|
|
|
- basepc[$6] = IFFUPJMP;
|
|
|
- code_word_at(basepc+$6+1, pc - ($<vLong>2));
|
|
|
+ currState->f->code[$6] = IFFUPJMP;
|
|
|
+ code_word_at($6+1, currState->pc - ($<vLong>2));
|
|
|
}
|
|
|
|
|
|
| varlist1 '=' exprlist1
|
|
@@ -531,14 +550,14 @@ stat : IF expr1 THEN PrepJump block PrepJump elsepart END
|
|
|
int i;
|
|
|
adjust_mult_assign(nvarbuffer, $3, $1 * 2 + nvarbuffer);
|
|
|
for (i=nvarbuffer-1; i>=0; i--)
|
|
|
- lua_codestore (i);
|
|
|
+ lua_codestore(i);
|
|
|
if ($1 > 1 || ($1 == 1 && varbuffer[0] != 0))
|
|
|
- lua_codeadjust (0);
|
|
|
+ lua_codeadjust(0);
|
|
|
}
|
|
|
}
|
|
|
| functioncall {;}
|
|
|
| LOCAL localdeclist decinit
|
|
|
- { nlocalvar += $2;
|
|
|
+ { currState->nlocalvar += $2;
|
|
|
adjust_mult_assign($2, $3, 0);
|
|
|
}
|
|
|
;
|
|
@@ -549,17 +568,13 @@ elsepart : /* empty */
|
|
|
{ codeIf($4, $6); }
|
|
|
;
|
|
|
|
|
|
-block : {$<vInt>$ = nlocalvar;} statlist ret
|
|
|
+block : {$<vInt>$ = currState->nlocalvar;} statlist ret
|
|
|
{
|
|
|
- if (nlocalvar != $<vInt>1)
|
|
|
- {
|
|
|
- if (lua_debug)
|
|
|
- for (; nlocalvar > $<vInt>1; nlocalvar--)
|
|
|
- luaI_unregisterlocalvar(lua_linenumber);
|
|
|
- else
|
|
|
- nlocalvar = $<vInt>1;
|
|
|
- lua_codeadjust (0);
|
|
|
- }
|
|
|
+ if (currState->nlocalvar != $<vInt>1) {
|
|
|
+ for (; currState->nlocalvar > $<vInt>1; currState->nlocalvar--)
|
|
|
+ luaI_unregisterlocalvar(lua_linenumber);
|
|
|
+ lua_codeadjust(0);
|
|
|
+ }
|
|
|
}
|
|
|
;
|
|
|
|
|
@@ -573,9 +588,9 @@ ret : /* empty */
|
|
|
|
|
|
PrepJump : /* empty */
|
|
|
{
|
|
|
- $$ = pc;
|
|
|
+ $$ = currState->pc;
|
|
|
code_byte(0); /* open space */
|
|
|
- code_word (0);
|
|
|
+ code_word(0);
|
|
|
}
|
|
|
;
|
|
|
|
|
@@ -609,26 +624,24 @@ expr : '(' expr ')' { $$ = $2; }
|
|
|
| NOT expr1 { code_byte(NOTOP); $$ = 0;}
|
|
|
| expr1 AND PrepJump {code_byte(POP); } expr1
|
|
|
{
|
|
|
- basepc[$3] = ONFJMP;
|
|
|
- code_word_at(basepc+$3+1, pc - ($3 + sizeof(Word)+1));
|
|
|
- $$ = 0;
|
|
|
+ code_shortcircuit($3, ONFJMP);
|
|
|
+ $$ = 0;
|
|
|
}
|
|
|
| expr1 OR PrepJump {code_byte(POP); } expr1
|
|
|
{
|
|
|
- basepc[$3] = ONTJMP;
|
|
|
- code_word_at(basepc+$3+1, pc - ($3 + sizeof(Word)+1));
|
|
|
- $$ = 0;
|
|
|
+ code_shortcircuit($3, ONTJMP);
|
|
|
+ $$ = 0;
|
|
|
}
|
|
|
;
|
|
|
|
|
|
table :
|
|
|
{
|
|
|
code_byte(CREATEARRAY);
|
|
|
- $<vLong>$ = pc; code_word(0);
|
|
|
+ $<vLong>$ = currState->pc; code_word(0);
|
|
|
}
|
|
|
'{' fieldlist '}'
|
|
|
{
|
|
|
- code_word_at(basepc+$<vLong>1, $3);
|
|
|
+ code_word_at($<vLong>1, $3);
|
|
|
}
|
|
|
;
|
|
|
|
|
@@ -636,7 +649,7 @@ functioncall : funcvalue funcParams
|
|
|
{
|
|
|
code_byte(CALLFUNC);
|
|
|
code_byte($1+$2);
|
|
|
- $$ = pc;
|
|
|
+ $$ = currState->pc;
|
|
|
code_byte(0); /* may be modified by other rules */
|
|
|
}
|
|
|
;
|