Compiler for lua 5.2 fixes.

This commit is contained in:
James Roseborough
2012-09-02 15:29:30 +00:00
parent 2c748e0d3b
commit f6cc1948f1
3 changed files with 124 additions and 101 deletions

View File

@@ -214,8 +214,6 @@ public class FuncState extends LuaC {
void enterblock (BlockCnt bl, boolean isloop) { void enterblock (BlockCnt bl, boolean isloop) {
bl.isloop = isloop; bl.isloop = isloop;
bl.nactvar = nactvar; bl.nactvar = nactvar;
if (ls.dyd == null)
ls.dyd = new LexState.Dyndata();
bl.firstlabel = (short) ls.dyd.n_label; bl.firstlabel = (short) ls.dyd.n_label;
bl.firstgoto = (short) ls.dyd.n_gt; bl.firstgoto = (short) ls.dyd.n_gt;
bl.upval = false; bl.upval = false;

View File

@@ -138,7 +138,7 @@ public class LexState {
InputStream z; /* input stream */ InputStream z; /* input stream */
byte[] buff; /* buffer for tokens */ byte[] buff; /* buffer for tokens */
int nbuff; /* length of buffer */ int nbuff; /* length of buffer */
Dyndata dyd; /* dynamic structures used by the parser */ Dyndata dyd = new Dyndata(); /* dynamic structures used by the parser */
LuaString source; /* current source name */ LuaString source; /* current source name */
LuaString envn; /* environment variable name */ LuaString envn; /* environment variable name */
byte decpoint; /* locale decimal point */ byte decpoint; /* locale decimal point */
@@ -146,11 +146,11 @@ public class LexState {
/* ORDER RESERVED */ /* ORDER RESERVED */
final static String luaX_tokens [] = { final static String luaX_tokens [] = {
"and", "break", "do", "else", "elseif", "and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if", "end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat", "in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while", "return", "then", "true", "until", "while",
"..", "...", "==", ">=", "<=", "~=", "..", "...", "==", ">=", "<=", "~=",
"<number>", "<name>", "<string>", "<eof>", "::", "<eos>", "<number>", "<name>", "<string>", "<eof>",
}; };
final static int final static int
@@ -191,6 +191,12 @@ public class LexState {
return (c >= '0' && c <= '9'); return (c >= '0' && c <= '9');
} }
private boolean isxdigit(int c) {
return (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'f')
|| (c >= 'F' && c <= 'F');
}
private boolean isspace(int c) { private boolean isspace(int c) {
return (c <= ' '); return (c <= ' ');
} }
@@ -387,19 +393,22 @@ public class LexState {
*/ */
void read_numeral(SemInfo seminfo) { void read_numeral(SemInfo seminfo) {
String expo = "Ee";
int first = current;
LuaC._assert (isdigit(current)); LuaC._assert (isdigit(current));
do { save_and_next();
save_and_next(); if (first == '0' && check_next("Xx"))
} while (isdigit(current) || current == '.'); expo = "PpEe";
if (check_next("Ee")) /* `E'? */ while (true) {
check_next("+-"); /* optional exponent sign */ if (check_next(expo))
while (isalnum(current) || current == '_') check_next("+-");
save_and_next(); if(isxdigit(current))
save_and_next();
else
break;
}
save('\0'); save('\0');
buffreplace((byte)'.', decpoint); /* follow locale for decimal point */
String str = new String(buff, 0, nbuff); String str = new String(buff, 0, nbuff);
// if (!str2d(str, seminfo)) /* format error? */
// trydecpoint(str, seminfo); /* try to update decimal point separator */
str2d(str, seminfo); str2d(str, seminfo);
} }
@@ -544,6 +553,7 @@ public class LexState {
int llex(SemInfo seminfo) { int llex(SemInfo seminfo) {
nbuff = 0; nbuff = 0;
while (true) { while (true) {
System.out.println("llex current " + ((int) current) + "("+((char)current)+")");
switch (current) { switch (current) {
case '\n': case '\n':
case '\r': { case '\r': {
@@ -616,6 +626,15 @@ public class LexState {
return TK_NE; return TK_NE;
} }
} }
case ':': {
nextChar();
if (current != ':')
return ':';
else {
nextChar();
return TK_DBCOLON;
}
}
case '"': case '"':
case '\'': { case '\'': {
read_string(current, seminfo); read_string(current, seminfo);
@@ -635,7 +654,12 @@ public class LexState {
return TK_NUMBER; return TK_NUMBER;
} }
} }
case EOZ: { case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
read_numeral(seminfo);
return TK_NUMBER;
}
case EOZ: {
return TK_EOS; return TK_EOS;
} }
default: { default: {
@@ -869,23 +893,18 @@ public class LexState {
f.locvars[fs.nlocvars] = new LocVars(varname,0,0); f.locvars[fs.nlocvars] = new LocVars(varname,0,0);
return fs.nlocvars++; return fs.nlocvars++;
} }
// void new_localvar(LuaString name) {
// #define new_localvarliteral(ls,v,n) \
// this.new_localvar(luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
//
void new_localvarliteral(String v, int n) {
LuaString ts = newstring(v);
new_localvar(ts, n);
}
void new_localvar(LuaString name, int n) {
int reg = registerlocalvar(name); int reg = registerlocalvar(name);
fs.checklimit(fs.nactvar + n + 1, FuncState.LUAI_MAXVARS, "local variables"); fs.checklimit(dyd.n_actvar + 1, FuncState.LUAI_MAXVARS, "local variables");
if (dyd.actvar == null || dyd.n_actvar + 1 > dyd.actvar.length) if (dyd.actvar == null || dyd.n_actvar + 1 > dyd.actvar.length)
dyd.actvar = LuaC.realloc(dyd.actvar, Math.max(1, dyd.n_actvar * 2)); dyd.actvar = LuaC.realloc(dyd.actvar, Math.max(1, dyd.n_actvar * 2));
dyd.actvar[dyd.n_actvar] = new Vardesc(reg); dyd.actvar[dyd.n_actvar++] = new Vardesc(reg);
}
void new_localvarliteral(String v) {
LuaString ts = newstring(v);
new_localvar(ts);
} }
void adjustlocalvars(int nvars) { void adjustlocalvars(int nvars) {
@@ -1080,8 +1099,8 @@ public class LexState {
/* GRAMMAR RULES */ /* GRAMMAR RULES */
/*============================================================*/ /*============================================================*/
void field(expdesc v) { void fieldsel(expdesc v) {
/* field -> ['.' | ':'] NAME */ /* fieldsel -> ['.' | ':'] NAME */
FuncState fs = this.fs; FuncState fs = this.fs;
expdesc key = new expdesc(); expdesc key = new expdesc();
fs.exp2anyreg(v); fs.exp2anyreg(v);
@@ -1215,17 +1234,13 @@ public class LexState {
do { do {
switch (this.t.token) { switch (this.t.token) {
case TK_NAME: { /* param . NAME */ case TK_NAME: { /* param . NAME */
this.new_localvar(this.str_checkname(), nparams++); this.new_localvar(this.str_checkname());
++nparams;
break; break;
} }
case TK_DOTS: { /* param . `...' */ case TK_DOTS: { /* param . `...' */
this.next(); this.next();
if (LUA_COMPAT_VARARG) { f.is_vararg = 1;
/* use `arg' as default name */
this.new_localvarliteral("arg", nparams++);
f.is_vararg = LuaC.VARARG_HASARG | LuaC.VARARG_NEEDSARG;
}
f.is_vararg |= LuaC.VARARG_ISVARARG;
break; break;
} }
default: this.syntaxerror("<name> or " + LUA_QL("...") + " expected"); default: this.syntaxerror("<name> or " + LUA_QL("...") + " expected");
@@ -1246,7 +1261,7 @@ public class LexState {
new_fs.f.linedefined = line; new_fs.f.linedefined = line;
this.checknext('('); this.checknext('(');
if (needself) { if (needself) {
new_localvarliteral("self", 0); new_localvarliteral("self");
adjustlocalvars(1); adjustlocalvars(1);
} }
this.parlist(); this.parlist();
@@ -1325,11 +1340,11 @@ public class LexState {
** ======================================================================= ** =======================================================================
*/ */
void prefixexp(expdesc v) { void primaryexp (expdesc v) {
/* prefixexp -> NAME | '(' expr ')' */ /* primaryexp -> NAME | '(' expr ')' */
switch (this.t.token) { switch (t.token) {
case '(': { case '(': {
int line = this.linenumber; int line = linenumber;
this.next(); this.next();
this.expr(v); this.expr(v);
this.check_match(')', '(', line); this.check_match(')', '(', line);
@@ -1337,28 +1352,26 @@ public class LexState {
return; return;
} }
case TK_NAME: { case TK_NAME: {
this.singlevar(v); singlevar(v);
return; return;
} }
default: { default: {
this.syntaxerror("unexpected symbol"); this.syntaxerror("unexpected symbol " + t.token + " (" + ((char) t.token) + ")");
return; return;
} }
} }
} }
void primaryexp(expdesc v) { void suffixedexp (expdesc v) {
/* /* suffixedexp ->
* primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
* funcargs } int line = linenumber;
*/ primaryexp(v);
FuncState fs = this.fs;
this.prefixexp(v);
for (;;) { for (;;) {
switch (this.t.token) { switch (t.token) {
case '.': { /* field */ case '.': { /* fieldsel */
this.field(v); this.fieldsel(v);
break; break;
} }
case '[': { /* `[' exp1 `]' */ case '[': { /* `[' exp1 `]' */
@@ -1387,7 +1400,7 @@ public class LexState {
return; return;
} }
} }
} }
void simpleexp(expdesc v) { void simpleexp(expdesc v) {
@@ -1435,7 +1448,7 @@ public class LexState {
return; return;
} }
default: { default: {
this.primaryexp(v); this.suffixedexp(v);
return; return;
} }
} }
@@ -1680,7 +1693,7 @@ public class LexState {
next(); /* skip break */ next(); /* skip break */
label = LuaString.valueOf("break"); label = LuaString.valueOf("break");
} }
g = newlabelentry(LuaC.grow(dyd.gt, dyd.n_gt+1), dyd.n_gt++, label, line, pc); g = newlabelentry(dyd.gt =LuaC.grow(dyd.gt, dyd.n_gt+1), dyd.n_gt++, label, line, pc);
findlabel(g); /* close it if label already defined */ findlabel(g); /* close it if label already defined */
} }
@@ -1785,10 +1798,10 @@ public class LexState {
/* fornum -> NAME = exp1,exp1[,exp1] forbody */ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
FuncState fs = this.fs; FuncState fs = this.fs;
int base = fs.freereg; int base = fs.freereg;
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_INDEX, 0); this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_INDEX);
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_LIMIT, 1); this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_LIMIT);
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_STEP, 2); this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_STEP);
this.new_localvar(varname, 3); this.new_localvar(varname);
this.checknext('='); this.checknext('=');
this.exp1(); /* initial value */ this.exp1(); /* initial value */
this.checknext(','); this.checknext(',');
@@ -1807,17 +1820,19 @@ public class LexState {
/* forlist -> NAME {,NAME} IN explist1 forbody */ /* forlist -> NAME {,NAME} IN explist1 forbody */
FuncState fs = this.fs; FuncState fs = this.fs;
expdesc e = new expdesc(); expdesc e = new expdesc();
int nvars = 0; int nvars = 4; /* gen, state, control, plus at least one declared var */
int line; int line;
int base = fs.freereg; int base = fs.freereg;
/* create control variables */ /* create control variables */
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_GENERATOR, nvars++); this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_GENERATOR);
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_STATE, nvars++); this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_STATE);
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_CONTROL, nvars++); this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_CONTROL);
/* create declared variables */ /* create declared variables */
this.new_localvar(indexname, nvars++); this.new_localvar(indexname);
while (this.testnext(',')) while (this.testnext(',')) {
this.new_localvar(this.str_checkname(), nvars++); this.new_localvar(this.str_checkname());
++nvars;
}
this.checknext(TK_IN); this.checknext(TK_IN);
line = this.linenumber; line = this.linenumber;
this.adjust_assign(3, this.explist1(e), e); this.adjust_assign(3, this.explist1(e), e);
@@ -1850,45 +1865,54 @@ public class LexState {
} }
int test_then_block() { void test_then_block(IntPtr escapelist) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */ /* test_then_block -> [IF | ELSEIF] cond THEN block */
int condexit; expdesc v = new expdesc();
BlockCnt bl = new BlockCnt();
int jf; /* instruction to skip 'then' code (if condition is false) */
this.next(); /* skip IF or ELSEIF */ this.next(); /* skip IF or ELSEIF */
condexit = this.cond(); expr(v); /* read expression */
this.checknext(TK_THEN); this.checknext(TK_THEN);
this.block(); /* `then' part */ if (t.token == TK_GOTO || t.token == TK_BREAK) {
return condexit; fs.goiffalse(v); /* will jump to label if condition is true */
fs.enterblock(bl, false); /* must enter block before 'goto' */
gotostat(v.t.i); /* handle goto/break */
skipnoopstat(); /* skip other no-op statements */
if (block_follow(false)) { /* 'goto' is the entire block? */
fs.leaveblock();
return; /* and that is it */
} else
/* must skip over 'then' part if condition is false */
jf = fs.jump();
} else { /* regular case (not goto/break) */
fs.goiftrue(v); /* skip over block if condition is false */
fs.enterblock(bl, false);
jf = v.f.i;
}
statlist(); /* `then' part */
fs.leaveblock();
if (t.token == TK_ELSE || t.token == TK_ELSEIF)
fs.concat(escapelist, fs.jump()); /* must jump over it */
fs.patchtohere(jf);
} }
void ifstat(int line) { void ifstat(int line) {
/* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] IntPtr escapelist = new IntPtr(NO_JUMP); /* exit list for finished parts */
* END */ test_then_block(escapelist); /* IF cond THEN block */
FuncState fs = this.fs; while (t.token == TK_ELSEIF)
int flist; test_then_block(escapelist); /* ELSEIF cond THEN block */
IntPtr escapelist = new IntPtr(NO_JUMP); if (testnext(TK_ELSE))
flist = test_then_block(); /* IF cond THEN block */ block(); /* `else' part */
while (this.t.token == TK_ELSEIF) { check_match(TK_END, TK_IF, line);
fs.concat(escapelist, fs.jump()); fs.patchtohere(escapelist.i); /* patch escape list to 'if' end */
fs.patchtohere(flist);
flist = test_then_block(); /* ELSEIF cond THEN block */
}
if (this.t.token == TK_ELSE) {
fs.concat(escapelist, fs.jump());
fs.patchtohere(flist);
this.next(); /* skip ELSE (after patch, for correct line info) */
this.block(); /* `else' part */
} else
fs.concat(escapelist, flist);
fs.patchtohere(escapelist.i);
this.check_match(TK_END, TK_IF, line);
} }
void localfunc() { void localfunc() {
expdesc v = new expdesc(); expdesc v = new expdesc();
expdesc b = new expdesc(); expdesc b = new expdesc();
FuncState fs = this.fs; FuncState fs = this.fs;
this.new_localvar(this.str_checkname(), 0); this.new_localvar(this.str_checkname());
v.init(VLOCAL, fs.freereg); v.init(VLOCAL, fs.freereg);
fs.reserveregs(1); fs.reserveregs(1);
this.adjustlocalvars(1); this.adjustlocalvars(1);
@@ -1905,7 +1929,8 @@ public class LexState {
int nexps; int nexps;
expdesc e = new expdesc(); expdesc e = new expdesc();
do { do {
this.new_localvar(this.str_checkname(), nvars++); this.new_localvar(this.str_checkname());
++nvars;
} while (this.testnext(',')); } while (this.testnext(','));
if (this.testnext('=')) if (this.testnext('='))
nexps = this.explist1(e); nexps = this.explist1(e);
@@ -1920,15 +1945,15 @@ public class LexState {
boolean funcname(expdesc v) { boolean funcname(expdesc v) {
/* funcname -> NAME {field} [`:' NAME] */ /* funcname -> NAME {field} [`:' NAME] */
boolean needself = false; boolean ismethod = false;
this.singlevar(v); this.singlevar(v);
while (this.t.token == '.') while (this.t.token == '.')
this.field(v); this.fieldsel(v);
if (this.t.token == ':') { if (this.t.token == ':') {
needself = true; ismethod = true;
this.field(v); this.fieldsel(v);
} }
return needself; return ismethod;
} }