Remove compiler dependence on mark()/reset()

This commit is contained in:
James Roseborough
2007-09-22 16:57:25 +00:00
parent e07382c90d
commit 9f6d7543cd
6 changed files with 57 additions and 33 deletions

View File

@@ -1,5 +1,8 @@
package lua.addon.compile; package lua.addon.compile;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.util.Hashtable; import java.util.Hashtable;
@@ -8,19 +11,41 @@ import lua.value.LString;
public class Compiler { public class Compiler {
public int nCcalls; private static final byte LUAC_BINARY_SIG = '\033';
public static Proto compile( Reader reader, String name ) { /** 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 Proto 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 Proto compile(InputStream stream, String name) throws IOException {
int c = stream.read();
if ( c == LUAC_BINARY_SIG )
return null;
// TODO: handle UTF-8 here!
InputStreamReader isr = new InputStreamReader(stream);
Compiler compiler = new Compiler(); Compiler compiler = new Compiler();
return compiler.luaY_parser(reader, name); return compiler.luaY_parser(c, isr, name);
} }
public int nCcalls;
Proto luaY_parser(Reader z, String name) { Proto luaY_parser(int firstByte, Reader z, String name) {
LexState lexstate = new LexState(this, z); LexState lexstate = new LexState(this, z);
FuncState funcstate = new FuncState(); FuncState funcstate = new FuncState();
// lexstate.buff = buff; // lexstate.buff = buff;
lexstate.setinput( this, z, new LString(name) ); lexstate.setinput( this, firstByte, z, new LString(name) );
lexstate.open_func(funcstate); lexstate.open_func(funcstate);
/* main func. is always vararg */ /* main func. is always vararg */
funcstate.varargflags = LuaC.VARARG_ISVARARG; funcstate.varargflags = LuaC.VARARG_ISVARARG;
@@ -63,4 +88,5 @@ public class Compiler {
public LString newlstr(char[] chars, int offset, int len) { public LString newlstr(char[] chars, int offset, int len) {
return newTString( new String(chars,offset,len) ); return newTString( new String(chars,offset,len) );
} }
} }

View File

@@ -252,7 +252,7 @@ public class LexState extends LuaC {
syntaxerror("chunk has too many lines"); syntaxerror("chunk has too many lines");
} }
void setinput( Compiler L, Reader z, LString source ) { void setinput( Compiler 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 */
@@ -262,7 +262,7 @@ public class LexState extends LuaC {
this.lastline = 1; this.lastline = 1;
this.source = source; this.source = source;
this.nbuff = 0; /* initialize buffer */ this.nbuff = 0; /* initialize buffer */
this.nextChar(); /* read first char */ this.current = firstByte; /* read first char */
this.skipShebang(); this.skipShebang();
} }

View File

@@ -468,7 +468,7 @@ public class LuaCompat extends LFunction {
// return true if loaded, false if error put onto stack // return true if loaded, false if error put onto stack
private static boolean loadfile( VM vm, String fileName ) { public static boolean loadfile( VM vm, String fileName ) {
InputStream is; InputStream is;
String script; String script;

View File

@@ -239,16 +239,12 @@ public class LoadState {
public static Proto undump( VM L, InputStream stream, String name ) throws IOException { public static Proto undump( VM L, InputStream stream, String name ) throws IOException {
// is this a source file? // is this a source file?
stream.mark(1); Proto p = lua.addon.compile.Compiler.compile(stream, name);
if ( stream.read() != LUAC_HEADER_SIGNATURE[0] ) { if ( p != null )
stream.reset(); return p;
// TODO: handle UTF-8 here!
return lua.addon.compile.Compiler.compile(
new InputStreamReader(stream),
name );
}
// check 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() != LUAC_HEADER_SIGNATURE[i] )
throw new IllegalArgumentException("bad signature"); throw new IllegalArgumentException("bad signature");

View File

@@ -37,8 +37,7 @@ public class AbstractUnitTests extends TestCase {
// compile in memory // compile in memory
InputStream is = new ByteArrayInputStream( lua ); InputStream is = new ByteArrayInputStream( lua );
Reader r = new InputStreamReader( is ); Proto p = Compiler.compile(is, dir+"/"+file);
Proto p = Compiler.compile(r, dir+"/"+file);
String actual = protoToString( p ); String actual = protoToString( p );
// load expected value from jar // load expected value from jar

View File

@@ -1,12 +1,12 @@
package lua.addon.compile; package lua.addon.compile;
import java.io.Reader; import java.io.ByteArrayInputStream;
import java.io.StringReader; import java.io.IOException;
import java.io.InputStream;
import junit.framework.TestCase; import junit.framework.TestCase;
import lua.Print; import lua.Print;
import lua.StackState; import lua.StackState;
import lua.addon.compile.Compiler;
import lua.io.Closure; import lua.io.Closure;
import lua.io.Proto; import lua.io.Proto;
import lua.value.LValue; import lua.value.LValue;
@@ -14,16 +14,19 @@ import lua.value.LValue;
public class SimpleTests extends TestCase { public class SimpleTests extends TestCase {
private void doTest( String script ) { private void doTest( String script ) {
Reader r = new StringReader( script ); try {
Proto p = Compiler.compile( r, "script" ); InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") );
assertNotNull( p ); Proto p = Compiler.compile( is, "script" );
Print.printCode( p ); assertNotNull( p );
Print.printCode( p );
// try running the code!
StackState state = new StackState(); // try running the code!
Closure c = new Closure( state, p ); StackState state = new StackState();
state.doCall( c, new LValue[0] ); Closure c = new Closure( state, p );
state.doCall( c, new LValue[0] );
} catch ( Exception e ) {
fail("i/o exception: "+e );
}
} }
public void testTrivial() { public void testTrivial() {