|
@@ -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 */
|
|
|
}
|
|
|
;
|
|
|
|