Make compiler optional
This commit is contained in:
@@ -1,113 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2007 LuaJ. All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
******************************************************************************/
|
|
||||||
package org.luaj.compiler;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
|
|
||||||
import org.luaj.vm.LString;
|
|
||||||
import org.luaj.vm.LPrototype;
|
|
||||||
import org.luaj.vm.Platform;
|
|
||||||
|
|
||||||
|
|
||||||
public class Compiler {
|
|
||||||
|
|
||||||
private static final byte LUAC_BINARY_SIG = '\033';
|
|
||||||
|
|
||||||
/** Try to compile into prototype.
|
|
||||||
* If the supplied stream is a binary file (i.e. lua chunk)
|
|
||||||
* then consume one byte from the input stream, and return null.
|
|
||||||
*
|
|
||||||
* Otherwise, try to compile the file, and return the Prototype
|
|
||||||
* on success, or throw RuntimeException on syntax error or I/O Exception
|
|
||||||
*
|
|
||||||
* @param stream InputStream to read from.
|
|
||||||
* @param name Name of the chunk
|
|
||||||
* @return null if the first byte indicates it is a binary chunk,
|
|
||||||
* a LPrototype instance if it can be compiled,
|
|
||||||
* or an exception is thrown if there is an error.
|
|
||||||
* @throws IOException if an I/O exception occurs
|
|
||||||
* @throws RuntimeException if there is a syntax error.
|
|
||||||
*/
|
|
||||||
public static LPrototype compile(InputStream stream, String name) throws IOException {
|
|
||||||
|
|
||||||
int c = stream.read();
|
|
||||||
if ( c == LUAC_BINARY_SIG )
|
|
||||||
return null;
|
|
||||||
Reader r = Platform.getInstance().createReader( stream );
|
|
||||||
Compiler compiler = new Compiler();
|
|
||||||
return compiler.luaY_parser(c, r, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int nCcalls;
|
|
||||||
|
|
||||||
LPrototype luaY_parser(int firstByte, Reader z, String name) {
|
|
||||||
LexState lexstate = new LexState(this, z);
|
|
||||||
FuncState funcstate = new FuncState();
|
|
||||||
// lexstate.buff = buff;
|
|
||||||
lexstate.setinput( this, firstByte, z, new LString(name) );
|
|
||||||
lexstate.open_func(funcstate);
|
|
||||||
/* main func. is always vararg */
|
|
||||||
funcstate.varargflags = LuaC.VARARG_ISVARARG;
|
|
||||||
funcstate.f.is_vararg = true;
|
|
||||||
funcstate.f.source = new LString("@"+name);
|
|
||||||
lexstate.next(); /* read first token */
|
|
||||||
lexstate.chunk();
|
|
||||||
lexstate.check(LexState.TK_EOS);
|
|
||||||
lexstate.close_func();
|
|
||||||
LuaC._assert (funcstate.prev == null);
|
|
||||||
LuaC._assert (funcstate.f.nups == 0);
|
|
||||||
LuaC._assert (lexstate.fs == null);
|
|
||||||
return funcstate.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// these string utilities were originally
|
|
||||||
// part of the Lua C State object, so we have
|
|
||||||
// left them here for now until we deterimine
|
|
||||||
// what exact purpose they serve.
|
|
||||||
|
|
||||||
// table of all strings -> TString mapping.
|
|
||||||
// this includes reserved words that must be identified
|
|
||||||
// during lexical analysis for the compiler to work at all.
|
|
||||||
// TODO: consider moving this to LexState and simplifying
|
|
||||||
// all the various "newstring()" like functions
|
|
||||||
Hashtable strings = new Hashtable();
|
|
||||||
|
|
||||||
public LString newTString(String s) {
|
|
||||||
LString t = (LString) strings.get(s);
|
|
||||||
if ( t == null )
|
|
||||||
strings.put( s, t = new LString(s) );
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String pushfstring(String string) {
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LString newlstr(char[] chars, int offset, int len) {
|
|
||||||
return newTString( new String(chars,offset,len) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -30,11 +30,11 @@ import org.luaj.vm.LDouble;
|
|||||||
import org.luaj.vm.LInteger;
|
import org.luaj.vm.LInteger;
|
||||||
import org.luaj.vm.LNil;
|
import org.luaj.vm.LNil;
|
||||||
import org.luaj.vm.LNumber;
|
import org.luaj.vm.LNumber;
|
||||||
|
import org.luaj.vm.LPrototype;
|
||||||
import org.luaj.vm.LString;
|
import org.luaj.vm.LString;
|
||||||
import org.luaj.vm.LValue;
|
import org.luaj.vm.LValue;
|
||||||
import org.luaj.vm.LocVars;
|
import org.luaj.vm.LocVars;
|
||||||
import org.luaj.vm.Lua;
|
import org.luaj.vm.Lua;
|
||||||
import org.luaj.vm.LPrototype;
|
|
||||||
|
|
||||||
|
|
||||||
public class FuncState extends LuaC {
|
public class FuncState extends LuaC {
|
||||||
@@ -56,7 +56,7 @@ public class FuncState extends LuaC {
|
|||||||
Hashtable htable; /* table to find (and reuse) elements in `k' */
|
Hashtable htable; /* table to find (and reuse) elements in `k' */
|
||||||
FuncState prev; /* enclosing function */
|
FuncState prev; /* enclosing function */
|
||||||
LexState ls; /* lexical state */
|
LexState ls; /* lexical state */
|
||||||
Compiler L; /* copy of the Lua state */
|
LuaC L; /* compiler being invoked */
|
||||||
BlockCnt bl; /* chain of current blocks */
|
BlockCnt bl; /* chain of current blocks */
|
||||||
int pc; /* next position to code (equivalent to `ncode') */
|
int pc; /* next position to code (equivalent to `ncode') */
|
||||||
int lasttarget; /* `pc' of last `jump target' */
|
int lasttarget; /* `pc' of last `jump target' */
|
||||||
@@ -1036,11 +1036,11 @@ public class FuncState extends LuaC {
|
|||||||
this.dischargejpc(); /* `pc' will change */
|
this.dischargejpc(); /* `pc' will change */
|
||||||
/* put new instruction in code array */
|
/* put new instruction in code array */
|
||||||
if (f.code == null || this.pc + 1 > f.code.length)
|
if (f.code == null || this.pc + 1 > f.code.length)
|
||||||
f.code = LexState.realloc(f.code, this.pc * 2 + 1);
|
f.code = LuaC.realloc(f.code, this.pc * 2 + 1);
|
||||||
f.code[this.pc] = instruction;
|
f.code[this.pc] = instruction;
|
||||||
/* save corresponding line information */
|
/* save corresponding line information */
|
||||||
if (f.lineinfo == null || this.pc + 1 > f.lineinfo.length)
|
if (f.lineinfo == null || this.pc + 1 > f.lineinfo.length)
|
||||||
f.lineinfo = LexState.realloc(f.lineinfo,
|
f.lineinfo = LuaC.realloc(f.lineinfo,
|
||||||
this.pc * 2 + 1);
|
this.pc * 2 + 1);
|
||||||
f.lineinfo[this.pc] = line;
|
f.lineinfo[this.pc] = line;
|
||||||
return this.pc++;
|
return this.pc++;
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ import org.luaj.compiler.FuncState.BlockCnt;
|
|||||||
import org.luaj.vm.LDouble;
|
import org.luaj.vm.LDouble;
|
||||||
import org.luaj.vm.LInteger;
|
import org.luaj.vm.LInteger;
|
||||||
import org.luaj.vm.LNumber;
|
import org.luaj.vm.LNumber;
|
||||||
|
import org.luaj.vm.LPrototype;
|
||||||
import org.luaj.vm.LString;
|
import org.luaj.vm.LString;
|
||||||
import org.luaj.vm.LocVars;
|
import org.luaj.vm.LocVars;
|
||||||
import org.luaj.vm.Lua;
|
import org.luaj.vm.Lua;
|
||||||
import org.luaj.vm.LPrototype;
|
|
||||||
|
|
||||||
|
|
||||||
public class LexState extends LuaC {
|
public class LexState {
|
||||||
|
|
||||||
protected static final String RESERVED_LOCAL_VAR_FOR_CONTROL = "(for control)";
|
protected static final String RESERVED_LOCAL_VAR_FOR_CONTROL = "(for control)";
|
||||||
protected static final String RESERVED_LOCAL_VAR_FOR_STATE = "(for state)";
|
protected static final String RESERVED_LOCAL_VAR_FOR_STATE = "(for state)";
|
||||||
@@ -136,7 +136,7 @@ public class LexState extends LuaC {
|
|||||||
final Token t = new Token(); /* current token */
|
final Token t = new Token(); /* current token */
|
||||||
final Token lookahead = new Token(); /* look ahead token */
|
final Token lookahead = new Token(); /* look ahead token */
|
||||||
FuncState fs; /* `FuncState' is private to the parser */
|
FuncState fs; /* `FuncState' is private to the parser */
|
||||||
Compiler L;
|
LuaC L;
|
||||||
Reader z; /* input stream */
|
Reader z; /* input stream */
|
||||||
char[] buff; /* buffer for tokens */
|
char[] buff; /* buffer for tokens */
|
||||||
int nbuff; /* length of buffer */
|
int nbuff; /* length of buffer */
|
||||||
@@ -196,7 +196,7 @@ public class LexState extends LuaC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LexState(Compiler state, Reader reader) {
|
public LexState(LuaC state, Reader reader) {
|
||||||
this.z = reader;
|
this.z = reader;
|
||||||
this.buff = new char[32];
|
this.buff = new char[32];
|
||||||
this.L = state;
|
this.L = state;
|
||||||
@@ -222,7 +222,7 @@ public class LexState extends LuaC {
|
|||||||
|
|
||||||
void save( int c) {
|
void save( int c) {
|
||||||
if ( buff == null || nbuff + 1 > buff.length )
|
if ( buff == null || nbuff + 1 > buff.length )
|
||||||
buff = realloc( buff, nbuff*2+1 );
|
buff = LuaC.realloc( buff, nbuff*2+1 );
|
||||||
buff[nbuff++] = (char) c;
|
buff[nbuff++] = (char) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ public class LexState extends LuaC {
|
|||||||
|
|
||||||
void inclinenumber() {
|
void inclinenumber() {
|
||||||
int old = current;
|
int old = current;
|
||||||
_assert( currIsNewline() );
|
LuaC._assert( currIsNewline() );
|
||||||
nextChar(); /* skip '\n' or '\r' */
|
nextChar(); /* skip '\n' or '\r' */
|
||||||
if ( currIsNewline() && current != old )
|
if ( currIsNewline() && current != old )
|
||||||
nextChar(); /* skip '\n\r' or '\r\n' */
|
nextChar(); /* skip '\n\r' or '\r\n' */
|
||||||
@@ -298,7 +298,7 @@ public class LexState extends LuaC {
|
|||||||
syntaxerror("chunk has too many lines");
|
syntaxerror("chunk has too many lines");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setinput( Compiler L, int firstByte, Reader z, LString source ) {
|
void setinput( LuaC L, int firstByte, Reader z, LString source ) {
|
||||||
this.decpoint = '.';
|
this.decpoint = '.';
|
||||||
this.L = L;
|
this.L = L;
|
||||||
this.lookahead.token = TK_EOS; /* no look-ahead token */
|
this.lookahead.token = TK_EOS; /* no look-ahead token */
|
||||||
@@ -384,7 +384,7 @@ public class LexState extends LuaC {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void read_numeral(SemInfo seminfo) {
|
void read_numeral(SemInfo seminfo) {
|
||||||
_assert (isdigit(current));
|
LuaC._assert (isdigit(current));
|
||||||
do {
|
do {
|
||||||
save_and_next();
|
save_and_next();
|
||||||
} while (isdigit(current) || current == '.');
|
} while (isdigit(current) || current == '.');
|
||||||
@@ -403,7 +403,7 @@ public class LexState extends LuaC {
|
|||||||
int skip_sep() {
|
int skip_sep() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int s = current;
|
int s = current;
|
||||||
_assert (s == '[' || s == ']');
|
LuaC._assert (s == '[' || s == ']');
|
||||||
save_and_next();
|
save_and_next();
|
||||||
while (current == '=') {
|
while (current == '=') {
|
||||||
save_and_next();
|
save_and_next();
|
||||||
@@ -637,7 +637,7 @@ public class LexState extends LuaC {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (isspace(current)) {
|
if (isspace(current)) {
|
||||||
_assert (!currIsNewline());
|
LuaC._assert (!currIsNewline());
|
||||||
nextChar();
|
nextChar();
|
||||||
continue;
|
continue;
|
||||||
} else if (isdigit(current)) {
|
} else if (isdigit(current)) {
|
||||||
@@ -676,7 +676,7 @@ public class LexState extends LuaC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lookahead() {
|
void lookahead() {
|
||||||
_assert (lookahead.token == TK_EOS);
|
LuaC._assert (lookahead.token == TK_EOS);
|
||||||
lookahead.token = llex(lookahead.seminfo);
|
lookahead.token = llex(lookahead.seminfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,7 +805,7 @@ public class LexState extends LuaC {
|
|||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
LPrototype f = fs.f;
|
LPrototype f = fs.f;
|
||||||
if (f.locvars == null || fs.nlocvars + 1 > f.locvars.length)
|
if (f.locvars == null || fs.nlocvars + 1 > f.locvars.length)
|
||||||
f.locvars = realloc( f.locvars, fs.nlocvars*2+1 );
|
f.locvars = LuaC.realloc( f.locvars, fs.nlocvars*2+1 );
|
||||||
f.locvars[fs.nlocvars] = new LocVars(varname,0,0);
|
f.locvars[fs.nlocvars] = new LocVars(varname,0,0);
|
||||||
return fs.nlocvars++;
|
return fs.nlocvars++;
|
||||||
}
|
}
|
||||||
@@ -884,7 +884,7 @@ public class LexState extends LuaC {
|
|||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
LPrototype f = fs.f;
|
LPrototype f = fs.f;
|
||||||
if (f.p == null || fs.np + 1 > f.p.length)
|
if (f.p == null || fs.np + 1 > f.p.length)
|
||||||
f.p = realloc( f.p, fs.np*2 + 1 );
|
f.p = LuaC.realloc( f.p, fs.np*2 + 1 );
|
||||||
f.p[fs.np++] = func.f;
|
f.p[fs.np++] = func.f;
|
||||||
v.init(VRELOCABLE, fs.codeABx(Lua.OP_CLOSURE, 0, fs.np - 1));
|
v.init(VRELOCABLE, fs.codeABx(Lua.OP_CLOSURE, 0, fs.np - 1));
|
||||||
for (int i = 0; i < func.f.nups; i++) {
|
for (int i = 0; i < func.f.nups; i++) {
|
||||||
@@ -895,7 +895,7 @@ public class LexState extends LuaC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void open_func (FuncState fs) {
|
void open_func (FuncState fs) {
|
||||||
Compiler L = this.L;
|
LuaC L = this.L;
|
||||||
LPrototype f = new LPrototype();
|
LPrototype f = new LPrototype();
|
||||||
if ( this.fs!=null )
|
if ( this.fs!=null )
|
||||||
f.source = this.fs.f.source;
|
f.source = this.fs.f.source;
|
||||||
@@ -920,21 +920,20 @@ public class LexState extends LuaC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close_func() {
|
void close_func() {
|
||||||
// Compiler L = this.L;
|
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
LPrototype f = fs.f;
|
LPrototype f = fs.f;
|
||||||
this.removevars(0);
|
this.removevars(0);
|
||||||
fs.ret(0, 0); /* final return */
|
fs.ret(0, 0); /* final return */
|
||||||
f.code = realloc(f.code, fs.pc);
|
f.code = LuaC.realloc(f.code, fs.pc);
|
||||||
f.lineinfo = realloc(f.lineinfo, fs.pc);
|
f.lineinfo = LuaC.realloc(f.lineinfo, fs.pc);
|
||||||
// f.sizelineinfo = fs.pc;
|
// f.sizelineinfo = fs.pc;
|
||||||
f.k = realloc(f.k, fs.nk);
|
f.k = LuaC.realloc(f.k, fs.nk);
|
||||||
f.p = realloc(f.p, fs.np);
|
f.p = LuaC.realloc(f.p, fs.np);
|
||||||
f.locvars = realloc(f.locvars, fs.nlocvars);
|
f.locvars = LuaC.realloc(f.locvars, fs.nlocvars);
|
||||||
// f.sizelocvars = fs.nlocvars;
|
// f.sizelocvars = fs.nlocvars;
|
||||||
f.upvalues = realloc(f.upvalues, f.nups);
|
f.upvalues = LuaC.realloc(f.upvalues, f.nups);
|
||||||
// _assert (CheckCode.checkcode(f));
|
// LuaC._assert (CheckCode.checkcode(f));
|
||||||
_assert (fs.bl == null);
|
LuaC._assert (fs.bl == null);
|
||||||
this.fs = fs.prev;
|
this.fs = fs.prev;
|
||||||
// L.top -= 2; /* remove table and prototype from the stack */
|
// L.top -= 2; /* remove table and prototype from the stack */
|
||||||
// /* last token read was anchored in defunct function; must reanchor it
|
// /* last token read was anchored in defunct function; must reanchor it
|
||||||
@@ -1023,7 +1022,7 @@ public class LexState extends LuaC {
|
|||||||
fs.exp2nextreg(t); /* fix it at stack top (for gc) */
|
fs.exp2nextreg(t); /* fix it at stack top (for gc) */
|
||||||
this.checknext('{');
|
this.checknext('{');
|
||||||
do {
|
do {
|
||||||
_assert (cc.v.k == VVOID || cc.tostore > 0);
|
LuaC._assert (cc.v.k == VVOID || cc.tostore > 0);
|
||||||
if (this.t.token == '}')
|
if (this.t.token == '}')
|
||||||
break;
|
break;
|
||||||
fs.closelistfield(cc);
|
fs.closelistfield(cc);
|
||||||
@@ -1049,8 +1048,8 @@ public class LexState extends LuaC {
|
|||||||
this.check_match('}', '{', line);
|
this.check_match('}', '{', line);
|
||||||
fs.lastlistfield(cc);
|
fs.lastlistfield(cc);
|
||||||
InstructionPtr i = new InstructionPtr(fs.f.code, pc);
|
InstructionPtr i = new InstructionPtr(fs.f.code, pc);
|
||||||
SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
|
LuaC.SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
|
||||||
SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
|
LuaC.SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1090,10 +1089,10 @@ public class LexState extends LuaC {
|
|||||||
/* use `arg' as default name */
|
/* use `arg' as default name */
|
||||||
this.new_localvarliteral("arg", nparams++);
|
this.new_localvarliteral("arg", nparams++);
|
||||||
// f.is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
|
// f.is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
|
||||||
fs.varargflags = VARARG_HASARG | VARARG_NEEDSARG;
|
fs.varargflags = LuaC.VARARG_HASARG | LuaC.VARARG_NEEDSARG;
|
||||||
}
|
}
|
||||||
// f.is_vararg |= VARARG_ISVARARG;
|
// f.is_vararg |= VARARG_ISVARARG;
|
||||||
fs.varargflags |= VARARG_ISVARARG;
|
fs.varargflags |= LuaC.VARARG_ISVARARG;
|
||||||
f.is_vararg = true;
|
f.is_vararg = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1102,7 +1101,7 @@ public class LexState extends LuaC {
|
|||||||
} while (!f.is_vararg && this.testnext(','));
|
} while (!f.is_vararg && this.testnext(','));
|
||||||
}
|
}
|
||||||
this.adjustlocalvars(nparams);
|
this.adjustlocalvars(nparams);
|
||||||
f.numparams = (fs.nactvar - (fs.varargflags & VARARG_HASARG));
|
f.numparams = (fs.nactvar - (fs.varargflags & LuaC.VARARG_HASARG));
|
||||||
fs.reserveregs(fs.nactvar); /* reserve register for parameters */
|
fs.reserveregs(fs.nactvar); /* reserve register for parameters */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1172,7 +1171,7 @@ public class LexState extends LuaC {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_assert (f.k == VNONRELOC);
|
LuaC._assert (f.k == VNONRELOC);
|
||||||
base = f.u.s.info; /* base register for call */
|
base = f.u.s.info; /* base register for call */
|
||||||
if (hasmultret(args.k))
|
if (hasmultret(args.k))
|
||||||
nparams = Lua.LUA_MULTRET; /* open call */
|
nparams = Lua.LUA_MULTRET; /* open call */
|
||||||
@@ -1291,7 +1290,7 @@ public class LexState extends LuaC {
|
|||||||
this.check_condition(fs.f.is_vararg, "cannot use " + LUA_QL("...")
|
this.check_condition(fs.f.is_vararg, "cannot use " + LUA_QL("...")
|
||||||
+ " outside a vararg function");
|
+ " outside a vararg function");
|
||||||
// fs.f.is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
|
// fs.f.is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
|
||||||
fs.varargflags &= ~VARARG_NEEDSARG; /* don't need 'arg' */
|
fs.varargflags &= ~LuaC.VARARG_NEEDSARG; /* don't need 'arg' */
|
||||||
fs.f.is_vararg = (fs.varargflags != 0);
|
fs.f.is_vararg = (fs.varargflags != 0);
|
||||||
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
|
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
|
||||||
break;
|
break;
|
||||||
@@ -1449,7 +1448,7 @@ public class LexState extends LuaC {
|
|||||||
BlockCnt bl = new BlockCnt();
|
BlockCnt bl = new BlockCnt();
|
||||||
fs.enterblock(bl, false);
|
fs.enterblock(bl, false);
|
||||||
this.chunk();
|
this.chunk();
|
||||||
_assert(bl.breaklist.i == NO_JUMP);
|
LuaC._assert(bl.breaklist.i == NO_JUMP);
|
||||||
fs.leaveblock();
|
fs.leaveblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1800,7 +1799,7 @@ public class LexState extends LuaC {
|
|||||||
LHS_assign v = new LHS_assign();
|
LHS_assign v = new LHS_assign();
|
||||||
this.primaryexp(v.v);
|
this.primaryexp(v.v);
|
||||||
if (v.v.k == VCALL) /* stat -> func */
|
if (v.v.k == VCALL) /* stat -> func */
|
||||||
SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
|
LuaC.SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
|
||||||
else { /* stat -> assignment */
|
else { /* stat -> assignment */
|
||||||
v.prev = null;
|
v.prev = null;
|
||||||
this.assignment(v, 1);
|
this.assignment(v, 1);
|
||||||
@@ -1820,8 +1819,8 @@ public class LexState extends LuaC {
|
|||||||
if (hasmultret(e.k)) {
|
if (hasmultret(e.k)) {
|
||||||
fs.setmultret(e);
|
fs.setmultret(e);
|
||||||
if (e.k == VCALL && nret == 1) { /* tail call? */
|
if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||||
SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
|
LuaC.SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
|
||||||
_assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
|
LuaC._assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
|
||||||
}
|
}
|
||||||
first = fs.nactvar;
|
first = fs.nactvar;
|
||||||
nret = Lua.LUA_MULTRET; /* return all values */
|
nret = Lua.LUA_MULTRET; /* return all values */
|
||||||
@@ -1831,7 +1830,7 @@ public class LexState extends LuaC {
|
|||||||
else {
|
else {
|
||||||
fs.exp2nextreg(e); /* values must go to the `stack' */
|
fs.exp2nextreg(e); /* values must go to the `stack' */
|
||||||
first = fs.nactvar; /* return all `active' values */
|
first = fs.nactvar; /* return all `active' values */
|
||||||
_assert (nret == fs.freereg - first);
|
LuaC._assert (nret == fs.freereg - first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1899,7 +1898,7 @@ public class LexState extends LuaC {
|
|||||||
while (!islast && !block_follow(this.t.token)) {
|
while (!islast && !block_follow(this.t.token)) {
|
||||||
islast = this.statement();
|
islast = this.statement();
|
||||||
this.testnext(';');
|
this.testnext(';');
|
||||||
_assert (this.fs.f.maxstacksize >= this.fs.freereg
|
LuaC._assert (this.fs.f.maxstacksize >= this.fs.freereg
|
||||||
&& this.fs.freereg >= this.fs.nactvar);
|
&& this.fs.freereg >= this.fs.nactvar);
|
||||||
this.fs.freereg = this.fs.nactvar; /* free registers */
|
this.fs.freereg = this.fs.nactvar; /* free registers */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,20 +21,34 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.compiler;
|
package org.luaj.compiler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import org.luaj.vm.LPrototype;
|
||||||
import org.luaj.vm.LString;
|
import org.luaj.vm.LString;
|
||||||
import org.luaj.vm.LValue;
|
import org.luaj.vm.LValue;
|
||||||
|
import org.luaj.vm.LoadState;
|
||||||
import org.luaj.vm.LocVars;
|
import org.luaj.vm.LocVars;
|
||||||
import org.luaj.vm.Lua;
|
import org.luaj.vm.Lua;
|
||||||
import org.luaj.vm.LPrototype;
|
import org.luaj.vm.Platform;
|
||||||
|
import org.luaj.vm.LoadState.LuaCompiler;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional constants and utilities required for the compiler,
|
* Compiler for Lua
|
||||||
* but not required for the interpreter.
|
|
||||||
*
|
|
||||||
* * @deprecated - this class will go away. Constants will probably move to LexState
|
|
||||||
*/
|
*/
|
||||||
public class LuaC extends Lua {
|
public class LuaC extends Lua implements LuaCompiler {
|
||||||
|
|
||||||
|
/** Install the compiler so that LoadState will first
|
||||||
|
* try to use it when handed bytes that are
|
||||||
|
* not already a compiled lua chunk.
|
||||||
|
*/
|
||||||
|
public static void install() {
|
||||||
|
LoadState.compiler = new LuaC();
|
||||||
|
}
|
||||||
|
|
||||||
protected static void _assert(boolean b) {
|
protected static void _assert(boolean b) {
|
||||||
if (!b) throw new RuntimeException("assert failed");
|
if (!b) throw new RuntimeException("assert failed");
|
||||||
}
|
}
|
||||||
@@ -146,4 +160,70 @@ public class LuaC extends Lua {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int nCcalls;
|
||||||
|
Hashtable strings = new Hashtable();
|
||||||
|
|
||||||
|
/** Utility method to invoke the compiler for an input stream
|
||||||
|
*/
|
||||||
|
public static LPrototype compile(InputStream is, String string) throws IOException {
|
||||||
|
return new LuaC().compile(is.read(), is, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compile source bytes into a LPrototype.
|
||||||
|
*
|
||||||
|
* Try to compile the file, and return the Prototype on success,
|
||||||
|
* or throw RuntimeException on syntax error or I/O Exception
|
||||||
|
*
|
||||||
|
* @param firstByte the first byte from the InputStream.
|
||||||
|
* This can be read by the client and tested to see if it is already a binary chunk.
|
||||||
|
* @param stream InputStream to read from.
|
||||||
|
* @param name Name of the chunk
|
||||||
|
* @return null if the first byte indicates it is a binary chunk,
|
||||||
|
* a LPrototype instance if it can be compiled,
|
||||||
|
* or an exception is thrown if there is an error.
|
||||||
|
* @throws IOException if an I/O exception occurs
|
||||||
|
* @throws RuntimeException if there is a syntax error.
|
||||||
|
*/
|
||||||
|
public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException {
|
||||||
|
Reader r = Platform.getInstance().createReader( stream );
|
||||||
|
LuaC compiler = new LuaC();
|
||||||
|
return compiler.luaY_parser(firstByte, r, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Parse the input */
|
||||||
|
private LPrototype luaY_parser(int firstByte, Reader z, String name) {
|
||||||
|
LexState lexstate = new LexState(this, z);
|
||||||
|
FuncState funcstate = new FuncState();
|
||||||
|
// lexstate.buff = buff;
|
||||||
|
lexstate.setinput( this, firstByte, z, new LString(name) );
|
||||||
|
lexstate.open_func(funcstate);
|
||||||
|
/* main func. is always vararg */
|
||||||
|
funcstate.varargflags = LuaC.VARARG_ISVARARG;
|
||||||
|
funcstate.f.is_vararg = true;
|
||||||
|
funcstate.f.source = new LString("@"+name);
|
||||||
|
lexstate.next(); /* read first token */
|
||||||
|
lexstate.chunk();
|
||||||
|
lexstate.check(LexState.TK_EOS);
|
||||||
|
lexstate.close_func();
|
||||||
|
LuaC._assert (funcstate.prev == null);
|
||||||
|
LuaC._assert (funcstate.f.nups == 0);
|
||||||
|
LuaC._assert (lexstate.fs == null);
|
||||||
|
return funcstate.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LString newlstr(char[] chars, int offset, int len) {
|
||||||
|
return newTString( new String(chars,offset,len) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LString newTString(String s) {
|
||||||
|
LString t = (LString) strings.get(s);
|
||||||
|
if ( t == null )
|
||||||
|
strings.put( s, t = new LString(s) );
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String pushfstring(String string) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,13 +33,21 @@ import java.io.InputStream;
|
|||||||
*/
|
*/
|
||||||
public class LoadState {
|
public class LoadState {
|
||||||
|
|
||||||
|
/** Interface for the compiler, if it is installed. */
|
||||||
|
public interface LuaCompiler {
|
||||||
|
public LPrototype compile(int firstByte, InputStream stream, String name) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compiler instance, if installed */
|
||||||
|
public static LuaCompiler compiler = null;
|
||||||
|
|
||||||
|
/** Signature byte indicating the file is a compiled binary chunk */
|
||||||
|
private static final byte[] LUA_SIGNATURE = "\033Lua".getBytes();
|
||||||
|
|
||||||
|
/** Name for compiled chunks */
|
||||||
public static final String SOURCE_BINARY_STRING = "binary string";
|
public static final String SOURCE_BINARY_STRING = "binary string";
|
||||||
|
|
||||||
|
|
||||||
/** mark for precompiled code (`<esc>Lua') */
|
|
||||||
public static final String LUA_SIGNATURE = "\033Lua";
|
|
||||||
|
|
||||||
|
|
||||||
/** for header of binary files -- this is Lua 5.1 */
|
/** for header of binary files -- this is Lua 5.1 */
|
||||||
public static final int LUAC_VERSION = 0x51;
|
public static final int LUAC_VERSION = 0x51;
|
||||||
|
|
||||||
@@ -49,9 +57,6 @@ public class LoadState {
|
|||||||
/** size of header of binary files */
|
/** size of header of binary files */
|
||||||
public static final int LUAC_HEADERSIZE = 12;
|
public static final int LUAC_HEADERSIZE = 12;
|
||||||
|
|
||||||
/** expected lua header bytes */
|
|
||||||
private static final byte[] LUAC_HEADER_SIGNATURE = { '\033', 'L', 'u', 'a' };
|
|
||||||
|
|
||||||
// values read from the header
|
// values read from the header
|
||||||
private int luacVersion;
|
private int luacVersion;
|
||||||
private int luacFormat;
|
private int luacFormat;
|
||||||
@@ -221,15 +226,7 @@ public class LoadState {
|
|||||||
// this.L.pop();
|
// this.L.pop();
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// static void LoadHeader(LoadState* S)
|
|
||||||
// {
|
|
||||||
// char h[LUAC_HEADERSIZE];
|
|
||||||
// char s[LUAC_HEADERSIZE];
|
|
||||||
// luaU_header(h);
|
|
||||||
// LoadBlock(S,s,LUAC_HEADERSIZE);
|
|
||||||
// IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
|
|
||||||
// }
|
|
||||||
public void loadHeader() throws IOException {
|
public void loadHeader() throws IOException {
|
||||||
luacVersion = is.readByte();
|
luacVersion = is.readByte();
|
||||||
luacFormat = is.readByte();
|
luacFormat = is.readByte();
|
||||||
@@ -243,19 +240,21 @@ public class LoadState {
|
|||||||
|
|
||||||
public static LPrototype undump( LuaState L, InputStream stream, String name ) throws IOException {
|
public static LPrototype undump( LuaState L, InputStream stream, String name ) throws IOException {
|
||||||
|
|
||||||
// is this a source file?
|
// check first byte to see if its a precompiled chunk
|
||||||
LPrototype p = org.luaj.compiler.Compiler.compile(stream, name);
|
int c = stream.read();
|
||||||
if ( p != null )
|
if ( c != LUA_SIGNATURE[0] ) {
|
||||||
return p;
|
if ( compiler != null )
|
||||||
|
return compiler.compile(c, stream, name);
|
||||||
|
throw new IllegalArgumentException("no compiler");
|
||||||
|
}
|
||||||
|
|
||||||
// check rest of signature
|
// check rest of signature
|
||||||
// (one byte was consumed by compiler check)
|
|
||||||
for ( int i=1; i<4; i++ ) {
|
for ( int i=1; i<4; i++ ) {
|
||||||
if ( stream.read() != LUAC_HEADER_SIGNATURE[i] )
|
if ( stream.read() != LUA_SIGNATURE[i] )
|
||||||
throw new IllegalArgumentException("bad signature");
|
throw new IllegalArgumentException("bad signature");
|
||||||
}
|
}
|
||||||
|
|
||||||
// load file
|
// load file as a compiled chunk
|
||||||
String sname = getSourceName(name);
|
String sname = getSourceName(name);
|
||||||
LoadState s = new LoadState( L, stream, sname );
|
LoadState s = new LoadState( L, stream, sname );
|
||||||
s.loadHeader();
|
s.loadHeader();
|
||||||
|
|||||||
@@ -26,20 +26,15 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.luaj.compiler.LuaC;
|
||||||
import org.luaj.debug.DebugLuaState;
|
import org.luaj.debug.DebugLuaState;
|
||||||
import org.luaj.debug.DebugSupport;
|
import org.luaj.debug.DebugSupport;
|
||||||
import org.luaj.debug.DebugUtils;
|
import org.luaj.debug.DebugUtils;
|
||||||
import org.luaj.debug.VMException;
|
import org.luaj.debug.VMException;
|
||||||
import org.luaj.lib.CoroutineLib;
|
|
||||||
import org.luaj.lib.MathLib;
|
|
||||||
import org.luaj.lib.PackageLib;
|
|
||||||
import org.luaj.lib.StringLib;
|
|
||||||
import org.luaj.lib.TableLib;
|
|
||||||
import org.luaj.lib.j2se.LuajavaLib;
|
import org.luaj.lib.j2se.LuajavaLib;
|
||||||
import org.luaj.vm.LClosure;
|
import org.luaj.vm.LClosure;
|
||||||
import org.luaj.vm.LPrototype;
|
import org.luaj.vm.LPrototype;
|
||||||
import org.luaj.vm.LString;
|
import org.luaj.vm.LString;
|
||||||
import org.luaj.vm.LTable;
|
|
||||||
import org.luaj.vm.LValue;
|
import org.luaj.vm.LValue;
|
||||||
import org.luaj.vm.LoadState;
|
import org.luaj.vm.LoadState;
|
||||||
import org.luaj.vm.LuaState;
|
import org.luaj.vm.LuaState;
|
||||||
@@ -172,6 +167,9 @@ public class StandardLuaJVM {
|
|||||||
// add LuaJava bindings
|
// add LuaJava bindings
|
||||||
LuajavaLib.install(state._G);
|
LuajavaLib.install(state._G);
|
||||||
|
|
||||||
|
// add the compiler
|
||||||
|
LuaC.install();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doRun() throws IOException {
|
protected void doRun() throws IOException {
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ public class AllTests {
|
|||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
TestSuite suite = new TestSuite("Test for org.luaj");
|
TestSuite suite = new TestSuite("Test for org.luaj");
|
||||||
|
|
||||||
|
// debug tests
|
||||||
|
TestSuite vm = new TestSuite("VM");
|
||||||
|
vm.addTestSuite(org.luaj.vm.LoadStateTest.class);
|
||||||
|
vm.addTestSuite(org.luaj.vm.LStringTest.class);
|
||||||
|
vm.addTestSuite(org.luaj.vm.LTableTest.class);
|
||||||
|
vm.addTestSuite(org.luaj.vm.LuaJTest.class);
|
||||||
|
suite.addTest(vm);
|
||||||
|
|
||||||
// compiler tests
|
// compiler tests
|
||||||
TestSuite compiler = new TestSuite("Compiler");
|
TestSuite compiler = new TestSuite("Compiler");
|
||||||
compiler.addTestSuite(org.luaj.compiler.SimpleTests.class);
|
compiler.addTestSuite(org.luaj.compiler.SimpleTests.class);
|
||||||
@@ -28,14 +36,6 @@ public class AllTests {
|
|||||||
debug.addTestSuite(org.luaj.debug.j2se.LuaJVMTest.class);
|
debug.addTestSuite(org.luaj.debug.j2se.LuaJVMTest.class);
|
||||||
suite.addTest(debug);
|
suite.addTest(debug);
|
||||||
|
|
||||||
// debug tests
|
|
||||||
TestSuite vm = new TestSuite("VM");
|
|
||||||
vm.addTestSuite(org.luaj.vm.LoadStateTest.class);
|
|
||||||
vm.addTestSuite(org.luaj.vm.LStringTest.class);
|
|
||||||
vm.addTestSuite(org.luaj.vm.LTableTest.class);
|
|
||||||
vm.addTestSuite(org.luaj.vm.LuaJTest.class);
|
|
||||||
suite.addTest(vm);
|
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,20 +4,16 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.Reader;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.luaj.compiler.Compiler;
|
|
||||||
import org.luaj.compiler.DumpState;
|
|
||||||
import org.luaj.debug.Print;
|
|
||||||
import org.luaj.vm.LoadState;
|
|
||||||
import org.luaj.vm.LPrototype;
|
|
||||||
import org.luaj.vm.LuaState;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.luaj.debug.Print;
|
||||||
|
import org.luaj.vm.LPrototype;
|
||||||
|
import org.luaj.vm.LoadState;
|
||||||
|
import org.luaj.vm.LuaState;
|
||||||
|
|
||||||
|
|
||||||
abstract
|
abstract
|
||||||
public class AbstractUnitTests extends TestCase {
|
public class AbstractUnitTests extends TestCase {
|
||||||
@@ -38,7 +34,7 @@ public class AbstractUnitTests extends TestCase {
|
|||||||
|
|
||||||
// compile in memory
|
// compile in memory
|
||||||
InputStream is = new ByteArrayInputStream( lua );
|
InputStream is = new ByteArrayInputStream( lua );
|
||||||
LPrototype p = Compiler.compile(is, dir+"/"+file);
|
LPrototype p = LuaC.compile(is, dir+"/"+file);
|
||||||
String actual = protoToString( p );
|
String actual = protoToString( p );
|
||||||
|
|
||||||
// load expected value from jar
|
// load expected value from jar
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class SimpleTests extends TestCase {
|
|||||||
private void doTest( String script ) {
|
private void doTest( String script ) {
|
||||||
try {
|
try {
|
||||||
InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") );
|
InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") );
|
||||||
LPrototype p = Compiler.compile( is, "script" );
|
LPrototype p = LuaC.compile( is, "script" );
|
||||||
assertNotNull( p );
|
assertNotNull( p );
|
||||||
Print.printCode( p );
|
Print.printCode( p );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user