new way to handle global state during compilation.

This commit is contained in:
Roberto Ierusalimschy 1997-07-29 17:38:45 -03:00
parent 05e8b0ae80
commit 2c580a0afb
4 changed files with 164 additions and 188 deletions

35
func.c
View File

@ -9,9 +9,6 @@
static TFunc *function_root = NULL; static TFunc *function_root = NULL;
static LocVar *currvars = NULL;
static int numcurrvars = 0;
static int maxcurrvars = 0;
/* /*
@ -105,38 +102,6 @@ void lua_funcinfo (lua_Object func, char **filename, int *linedefined)
} }
} }
/*
** Stores information to know that variable has been declared in given line
*/
void luaI_registerlocalvar (TaggedString *varname, int line)
{
if (numcurrvars >= maxcurrvars)
maxcurrvars = growvector(&currvars, maxcurrvars, LocVar, "", MAX_WORD);
currvars[numcurrvars].varname = varname;
currvars[numcurrvars].line = line;
numcurrvars++;
}
/*
** Stores information to know that variable has been out of scope in given line
*/
void luaI_unregisterlocalvar (int line)
{
luaI_registerlocalvar(NULL, line);
}
/*
** Copies "currvars" into a new area and store it in function header.
** The values (varname = NULL, line = -1) signal the end of vector.
*/
void luaI_closelocalvars (TFunc *func)
{
func->locvars = newvector (numcurrvars+1, LocVar);
memcpy (func->locvars, currvars, numcurrvars*sizeof(LocVar));
func->locvars[numcurrvars].varname = NULL;
func->locvars[numcurrvars].line = -1;
numcurrvars = 0; /* prepares for next function */
}
/* /*
** Look for n-esim local variable at line "line" in function "func". ** Look for n-esim local variable at line "line" in function "func".

5
func.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: func.h,v 1.9 1997/05/14 18:38:29 roberto Exp roberto $ ** $Id: func.h,v 1.10 1997/07/29 19:44:02 roberto Exp roberto $
*/ */
#ifndef func_h #ifndef func_h
@ -36,9 +36,6 @@ void luaI_insertfunction (TFunc *f);
void luaI_initTFunc (TFunc *f); void luaI_initTFunc (TFunc *f);
void luaI_freefunc (TFunc *f); void luaI_freefunc (TFunc *f);
void luaI_registerlocalvar (TaggedString *varname, int line);
void luaI_unregisterlocalvar (int line);
void luaI_closelocalvars (TFunc *func);
char *luaI_getlocalname (TFunc *func, int local_number, int line); char *luaI_getlocalname (TFunc *func, int local_number, int line);
#endif #endif

309
lua.stx
View File

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

View File

@ -1,7 +1,7 @@
/* /*
** mem.c ** mem.c
** memory manager for lua ** memory manager for lua
** $Id: luamem.h,v 1.8 1996/05/24 14:31:10 roberto Exp roberto $ ** $Id: luamem.h,v 1.9 1997/03/31 14:10:11 roberto Exp roberto $
*/ */
#ifndef luamem_h #ifndef luamem_h
@ -34,6 +34,7 @@ int luaI_growvector (void **block, unsigned long nelems, int size,
#define newvector(n,s) ((s *)luaI_malloc((n)*sizeof(s))) #define newvector(n,s) ((s *)luaI_malloc((n)*sizeof(s)))
#define growvector(old,n,s,e,l) \ #define growvector(old,n,s,e,l) \
(luaI_growvector((void**)old,n,sizeof(s),e,l)) (luaI_growvector((void**)old,n,sizeof(s),e,l))
#define shrinkvector(v,n,t) ((t *)luaI_realloc(v,(n)*sizeof(t)))
#endif #endif