Refactor API's related to compiling and loading scripts and character encoding handling.

This commit is contained in:
James Roseborough
2013-09-18 05:32:30 +00:00
parent a552494b72
commit 2123d3f924
35 changed files with 489 additions and 293 deletions

View File

@@ -241,15 +241,22 @@ Lua scripts can also be run directly in this mode without precompiling using the
<h2>Run a script in a Java Application</h2>
<p>
The following pattern is used within Java SE
A simple hello, world example in luaj is:
<pre>
import org.luaj.vm2.*;
import org.luaj.vm2.lib.jse.*;
String script = "examples/lua/hello.lua";
LuaValue _G = JsePlatform.standardGlobals();
_G.get("dofile").call( LuaValue.valueOf(script) );
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("print 'hello, world'");
chunk.call();
</pre>
Loading from a file is done via Globals.loadFile():
<pre>
LuaValue chunk = globals.loadfile("examples/lua/hello.lua");
</pre>
<p>
@@ -270,13 +277,13 @@ The for MIDlets the <em>JmePlatform</em> is used instead:
import org.luaj.vm2.*;
import org.luaj.vm2.lib.jme.*;
String script = "examples/lua/hello.lua";
LuaValue _G = JmePlatform.standardGlobals();
_G.get("dofile").call( LuaValue.valueOf(script) );
Globals globals = JmePlatform.standardGlobals();
LuaValue chunk = globals.loadfile("examples/lua/hello.lua");
chunk.call();
</pre>
<p>
The file must be a resource within within the midlet jar for <em>dofile()</em> to find it.
The file must be a resource within within the midlet jar for the loader to find it.
Any files included via <em>require()</em> must also be part of the midlet resources.
<p>
@@ -310,6 +317,8 @@ The standard use of JSR-223 scripting engines may be used:
System.out.println( "y="+e.get("y") );
</pre>
You can also look up the engine by language "lua" or mimetypes "text/lua" or "application/lua".
<p>
All standard aspects of script engines including compiled statements should be supported.
@@ -341,7 +350,7 @@ To exclude the lua-to-lua-bytecode compiler, do not call
but instead initialize globals with including only those libraries
that are needed and omitting the line:
<pre>
org.luaj.vm2.compiler.LuaC.install();
org.luaj.vm2.compiler.LuaC.install(globals);
</pre>
@@ -349,10 +358,10 @@ that are needed and omitting the line:
<p>
To compile from lua to Java bytecode for all lua loaded at runtime,
install the LuaJC compiler <em>after</em> globals have been created using:
install the LuaJC compiler into a <em>globals</em> object use:
<pre>
org.luaj.vm2.jse.luajc.LuaJC.install();
org.luaj.vm2.jse.luajc.LuaJC.install(globals);
</pre>
<p>
@@ -389,8 +398,8 @@ Luaj 3.0 can be run in multiple threads, with the following restrictions:
<ul>
<li>Each thread created by client code must be given its own, distinct Globals instance
<li>Each thread must not be allowed to access Globals from other threads
<li>Shared metatables for Number, String, Thread, Function, Boolean, and and Nil
should not be mutated once lua code is running
<li>Metatables for Number, String, Thread, Function, Boolean, and and Nil
are shared and therefore should not be mutated once lua code is running in any thread.
</ul>
For an example of loading allocating per-thread Globals and invoking scripts in
@@ -886,12 +895,14 @@ Files are no longer hosted at LuaForge.
<tr valign="top"><td>&nbsp;&nbsp;<b>3.0-beta2</b></td><td><ul>
<li>LuaValue.checkfunction() now returns LuaFunction.</li>
<li>Fix os.time() to return a number of seconds.</li>
<li>Implement formatting with os.date(), and table argument for os.time()..</li>
<li>Implement formatting with os.date(), and table argument for os.time().</li>
<li>Refactor APIs related to compiling and loading scripts.</li>
</ul></td></tr>
</table></td></tr></table>
<h2>Known Issues</h2>
<h3>Limitations</h3>
<ul>
<li>debug code may not be completely removed by some obfuscators
<li>tail calls are not tracked in debug information
@@ -902,4 +913,20 @@ Files are no longer hosted at LuaForge.
<li>lua compiled into java bytecode using luajc cannot use string.dump() or xpcall()
<li>number formatting with string.format() is not supported
</ul>
<h3>File Character Encoding</h3>
Source files can be considered encoded in UTF-8 or ISO-8859-1 and results should be as expected,
with literal string contianing quoted characters compiling to the same byte sequences as the input.
For a non ASCII-compatible encoding such as EBSDIC, however, there are restrictions:
<ul>
<li>supplying a Reader to Globals.load() is preferred over InputStream variants
<li>using FileReader or InputStreamReader to get the default OS encoding should work in most cases
<li>string literals with quoted characters may not produce the expected values in generated code
<li>command-line tools lua, luac, and luajc will require <em>-c Cp037</em> to specify the encoding
</ul>
These restrictions are mainly a side effect of how the language is defined as allowing byte literals
within literal strings in source files.
Code that is generated on the fly within lua and compiled with lua's <em>load()</em> function
should work as expected, however, since these strings will never be represented with the
host's native character encoding.

View File

@@ -4,9 +4,7 @@ import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import org.luaj.vm2.*;
import org.luaj.vm2.lib.*;
import org.luaj.vm2.lib.jme.JmePlatform;
import org.luaj.vm2.compiler.LuaC;
public class SampleMIDlet extends MIDlet {
@@ -21,8 +19,8 @@ public class SampleMIDlet extends MIDlet {
script = DEFAULT_SCRIPT;
// create an environment to run in
LuaValue _G = JmePlatform.standardGlobals();
_G.get("require").call( LuaValue.valueOf(script) );
Globals globals = JmePlatform.standardGlobals();
globals.get("require").call( LuaValue.valueOf(script) );
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {

View File

@@ -13,7 +13,7 @@ public class SampleJseMain {
Globals globals = JsePlatform.standardGlobals();
// Use the convenience function on the globals to load a chunk.
LuaValue chunk = globals.loadFile(script);
LuaValue chunk = globals.loadfile(script);
// Use any of the "call()" or "invoke()" functions directly on the chunk.
chunk.call( LuaValue.valueOf(script) );

View File

@@ -26,8 +26,8 @@ public class SampleMultiThreaded {
// Once a Globals is created, it can and should be reused
// within the same thread.
g.loadFile(script1).call();
g.loadFile(script2).call();
g.loadfile(script1).call();
g.loadfile(script2).call();
} catch ( Exception e ) {
e.printStackTrace();

View File

@@ -163,13 +163,13 @@ public final class Buffer {
* Append a Java String to the buffer.
* The Java string will be converted to bytes using the UTF8 encoding.
* @return {@code this} to allow call chaining
* @see LuaString#encodeToUtf8(char[], byte[], int)
* @see LuaString#encodeToUtf8(char[], int, byte[], int)
*/
public final Buffer append( String str ) {
char[] chars = str.toCharArray();
final int n = LuaString.lengthAsUtf8( chars );
char[] c = str.toCharArray();
final int n = LuaString.lengthAsUtf8( c );
makeroom( 0, n );
LuaString.encodeToUtf8( chars, bytes, offset + length );
LuaString.encodeToUtf8( c, c.length, bytes, offset + length );
length += n;
return this;
}

View File

@@ -21,10 +21,11 @@
******************************************************************************/
package org.luaj.vm2;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.Reader;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.DebugLib;
import org.luaj.vm2.lib.PackageLib;
@@ -68,9 +69,6 @@ public class Globals extends LuaTable {
/** The installed ResourceFinder for looking files by name. */
public ResourceFinder FINDER;
/** The installed compiler. */
public LuaCompiler compiler = null;
/** The currently running thread. Should not be changed by non-library code. */
public LuaThread running = new LuaThread(this);
@@ -86,30 +84,119 @@ public class Globals extends LuaTable {
/** The current error handler for this Globals */
public LuaValue errorfunc;
/** Interface for module that converts a Prototype into a LuaFunction with an environment. */
public interface Loader {
/** Convert the prototype into a LuaFunction with the supplied environment. */
LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException;
}
/** Interface for module that converts lua source text into a prototype. */
public interface Compiler {
/** Compile lua source into a Prototype. The InputStream is assumed to be in UTF-8. */
Prototype compile(InputStream stream, String chunkname) throws IOException;
}
/** Interface for module that loads lua binary chunk into a prototype. */
public interface Undumper {
/** Load the supplied input stream into a prototype. */
Prototype undump(InputStream stream, String chunkname) throws IOException;
}
/** Check that this object is a Globals object, and return it, otherwise throw an error. */
public Globals checkglobals() {
return this;
}
/** Convenience function for loading a file.
/** The installed loader. */
public Loader loader;
/** The installed compiler. */
public Compiler compiler;
/** The installed undumper. */
public Undumper undumper;
/** Convenience function for loading a file that is either binary lua or lua source.
* @param filename Name of the file to load.
* @return LuaValue that can be call()'ed or invoke()'ed.
* @throws LuaError if the file could not be loaded.
*/
public LuaValue loadFile(String filename) {
Varargs v = baselib.loadFile(filename, "bt", this);
return !v.isnil(1)? v.arg1(): error(v.arg(2).tojstring());
public LuaValue loadfile(String filename) {
try {
return load(FINDER.findResource(filename), "@"+filename, "bt", this);
} catch (Exception e) {
return error("load "+filename+": "+e);
}
}
/** Convenience function to load a string value as a script.
/** Convenience function to load a string value as a script. Must be lua source.
* @param script Contents of a lua script, such as "print 'hello, world.'"
* @param chunkname Name that will be used within the chunk as the source.
* @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
* @throws LuaError if the script could not be compiled.
*/
public LuaValue loadString(String script, String chunkname) {
Varargs v = baselib.loadStream(valueOf(script).toInputStream(), chunkname, "bt", this);
return !v.isnil(1)? v.arg1(): error(v.arg(2).tojstring());
public LuaValue load(String script, String chunkname) {
return load(new StrReader(script), chunkname);
}
/** Load the content form a reader as a text file. Must be lua source.
* The source is converted to UTF-8, so any characters appearing in quoted literals
* above the range 128 will be converted into multiple bytes. */
public LuaValue load(Reader reader, String chunkname) {
return load(new UTF8Stream(reader), chunkname, "t", this);
}
/** Load the content form an input stream as a binary chunk or text file. */
public LuaValue load(InputStream is, String chunkname, String mode, LuaValue env) {
try {
Prototype p = loadPrototype(is, chunkname, mode);
return loader.load(p, chunkname, env);
} catch (LuaError l) {
throw l;
} catch (Exception e) {
return error("load "+chunkname+": "+e);
}
}
/** Load lua source or lua binary from an input stream into a Prototype.
* The InputStream is either a binary lua chunk starting with the lua binary chunk signature,
* or a text input file. If it is a text input file, it is interpreted as a UTF-8 byte sequence.
*/
public Prototype loadPrototype(InputStream is, String chunkname, String mode) throws IOException {
if (mode.indexOf('b') >= 0) {
if (undumper == null)
error("No undumper.");
if (!is.markSupported())
is = new MarkStream(is);
is.mark(4);
final Prototype p = undumper.undump(is, chunkname);
if (p != null)
return p;
is.reset();
}
if (mode.indexOf('t') >= 0) {
return compilePrototype(is, chunkname);
}
error("Failed to load prototype "+chunkname+" using mode '"+mode+"'");
return null;
}
/** Compile lua source from a Reader into a Prototype. The characters in the reader
* are converted to bytes using the UTF-8 encoding, so a string literal containing
* characters with codepoints 128 or above will be converted into multiple bytes.
*/
public Prototype compilePrototype(Reader reader, String chunkname) throws IOException {
return compilePrototype(new UTF8Stream(reader), chunkname);
}
/** Compile lua source from an InputStream into a Prototype.
* The input is assumed to be UTf-8, but since bytes in the range 128-255 are passed along as
* literal bytes, any ASCII-compatible encoding such as ISO 8859-1 may also be used.
*/
public Prototype compilePrototype(InputStream stream, String chunkname) throws IOException {
if (compiler == null)
error("No compiler.");
return compiler.compile(stream, chunkname);
}
/** Function which yields the current thread.
@@ -123,4 +210,80 @@ public class Globals extends LuaTable {
return s.lua_yield(args);
}
/** Reader implementation to read chars from a String in JME or JSE. */
static class StrReader extends Reader {
final String s;
int i = 0, n;
StrReader(String s) {
this.s = s;
n = s.length();
}
public void close() throws IOException {
i = n;
}
public int read(char[] cbuf, int off, int len) throws IOException {
int j = 0;
for (; j < len && i < n; ++j, ++i)
cbuf[off+j] = s.charAt(i);
return j > 0 || len == 0 ? j : -1;
}
}
/** Simple converter from Reader to InputStream using UTF8 encoding that will work
* on both JME and JSE.
*/
static class UTF8Stream extends InputStream {
final char[] c = new char[32];
final byte[] b = new byte[96];
int i = 0, j = 0;
final Reader r;
UTF8Stream(Reader r) {
this.r = r;
}
public int read() throws IOException {
if (i < j)
return c[i++];
int n = r.read(c);
if (n < 0)
return -1;
j = LuaString.encodeToUtf8(c, n, b, i = 0);
return b[i++];
}
}
/** Simple InputStream that supports mark.
* Used to examine an InputStream for a 4-byte binary lua signature,
* and fall back to text input when the signature is not found.
*/
static class MarkStream extends InputStream {
private int[] b;
private int i = 0, j = 0;
private final InputStream s;
MarkStream(InputStream s) {
this.s = s;
}
public int read() throws IOException {
if (i < j)
return b[i++];
final int c = s.read();
if (c < 0)
return -1;
if (j < b.length) {
b[j++] = c;
i = j;
}
return c;
}
public synchronized void mark(int n) {
b = new int[n];
i = j = 0;
}
public boolean markSupported() {
return true;
}
public synchronized void reset() throws IOException {
i = 0;
}
}
}

View File

@@ -35,10 +35,10 @@ import java.io.InputStream;
* <p>
* A simple pattern for loading and executing code is
* <pre> {@code
* LuaValue _G = JsePlatform.standardGlobals();
* LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
* Globals _G = JsePlatform.standardGlobals();
* _G.load(new FileReader("main.lua"), "main.lua", _G ).call();
* } </pre>
* This should work regardless of which {@link LuaCompiler}
* This should work regardless of which {@link Globals.Compiler}
* has been installed.
* <p>
*
@@ -52,7 +52,7 @@ import java.io.InputStream;
* for example:
* <pre> {@code
* LuaValue _G = JsePlatform.standardGlobals();
* LuaJC.install();
* LuaJC.install(_G);
* LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call();
* } </pre>
*
@@ -64,7 +64,10 @@ import java.io.InputStream;
* @see LuaC
* @see LuaJC
*/
public class LoadState {
public class LoadState implements Globals.Undumper {
/** Shared instance of Globals.Undumper to use loading prototypes from binary lua files */
public static final Globals.Undumper instance = new LoadState();
/** format corresponding to non-number-patched lua, all numbers are floats or doubles */
public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
@@ -89,21 +92,8 @@ public class LoadState {
public static final int LUA_TTHREAD = 8;
public static final int LUA_TVALUE = 9;
/** Interface for the compiler, if it is installed.
* <p>
* See the {@link LuaClosure} documentation for examples of how to use the compiler.
* @see LuaClosure
* @see #load(InputStream, String, LuaValue)
* */
public interface LuaCompiler {
/** Load into a Closure or LuaFunction from a Stream and initializes the environment
* @throws IOException */
public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException;
}
/** Compiler instance, if installed */
public static LuaCompiler compiler = null;
/** The character encoding to use for file encoding. Null means the default encoding */
public static String encoding = null;
/** Signature byte indicating the file is a compiled binary chunk */
public static final byte[] LUA_SIGNATURE = { '\033', 'L', 'u', 'a' };
@@ -151,6 +141,10 @@ public class LoadState {
/** Read buffer */
private byte[] buf = new byte[512];
/** Install this class as the standard Globals.Undumper for the supplied Globals */
public static void install(Globals globals) {
globals.undumper = instance;
}
/** Load a 4-byte int value from the input stream
* @return the int value laoded.
@@ -369,60 +363,22 @@ public class LoadState {
}
/**
* Load lua in either binary or text from an input stream.
* @param firstByte the first byte of the input stream
* Load input stream as a lua binary chunk if the first 4 bytes are the lua binary signature.
* @param stream InputStream to read, after having read the first byte already
* @param name Name to apply to the loaded chunk
* @param mode "b" for binary only, "t" for text only, "bt" for binary or text.
* @return {@link Prototype} that was loaded
* @throws IllegalArgumentException if the signature is bac
* @return {@link Prototype} that was loaded, or null if the first 4 bytes were not the lua signature.
* @throws IOException if an IOException occurs
*/
public static LuaFunction load( InputStream stream, String name, String mode, LuaValue env ) throws IOException {
if ( compiler != null )
return compiler.load(stream, name, env);
else {
int firstByte = stream.read();
if ( firstByte != LUA_SIGNATURE[0] )
throw new LuaError("no compiler");
Prototype p = loadBinaryChunk( firstByte, stream, name );
return new LuaClosure( p, env );
}
}
/**
* Load lua in the default mode "bt" from an input stream.
* @param firstByte the first byte of the input stream
* @param stream InputStream to read, after having read the first byte already
* @param name Name to apply to the loaded chunk
* @return {@link Prototype} that was loaded
* @throws IllegalArgumentException if the signature is bac
* @throws IOException if an IOException occurs
*/
public static LuaFunction load( InputStream stream, String name, LuaValue env ) throws IOException {
return load(stream, name, "bt", env);
}
/**
* Load lua thought to be a binary chunk from its first byte from an input stream.
* @param firstByte the first byte of the input stream
* @param stream InputStream to read, after having read the first byte already
* @param name Name to apply to the loaded chunk
* @return {@link Prototype} that was loaded
* @throws IllegalArgumentException if the signature is bac
* @throws IOException if an IOException occurs
*/
public static Prototype loadBinaryChunk( int firstByte, InputStream stream, String name ) throws IOException {
public Prototype undump(InputStream stream, String chunkname) throws IOException {
// check rest of signature
if ( firstByte != LUA_SIGNATURE[0]
if ( stream.read() != LUA_SIGNATURE[0]
|| stream.read() != LUA_SIGNATURE[1]
|| stream.read() != LUA_SIGNATURE[2]
|| stream.read() != LUA_SIGNATURE[3] )
throw new IllegalArgumentException("bad signature");
return null;
// load file as a compiled chunk
String sname = getSourceName(name);
String sname = getSourceName(chunkname);
LoadState s = new LoadState( stream, sname );
s.loadHeader();
@@ -457,4 +413,9 @@ public class LoadState {
this.name = name;
this.is = new DataInputStream( stream );
}
private LoadState() {
this.name = "";
this.is = null;
}
}

View File

@@ -26,6 +26,7 @@ import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import org.luaj.vm2.lib.MathLib;
import org.luaj.vm2.lib.StringLib;
@@ -48,7 +49,7 @@ import org.luaj.vm2.lib.StringLib;
* When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.
* The functions
* {@link LuaString#lengthAsUtf8(char[]),
* {@link LuaString#encodeToUtf8(char[], byte[], int)}, and
* {@link LuaString#encodeToUtf8(char[], int, byte[], int)}, and
* {@link LuaString#decodeAsUtf8(byte[], int, int)
* are used to convert back and forth between UTF8 byte arrays and character arrays.
*
@@ -108,7 +109,7 @@ public class LuaString extends LuaValue {
public static LuaString valueOf(String string) {
char[] c = string.toCharArray();
byte[] b = new byte[lengthAsUtf8(c)];
encodeToUtf8(c, b, 0);
encodeToUtf8(c, c.length, b, 0);
return valueOf(b, 0, b.length);
}
@@ -143,18 +144,29 @@ public class LuaString extends LuaValue {
/** Construct a {@link LuaString} using the supplied characters as byte values.
* <p>
* Only th elow-order 8-bits of each character are used, the remainder is ignored.
* Only the low-order 8-bits of each character are used, the remainder is ignored.
* <p>
* This is most useful for constructing byte sequences that do not conform to UTF8.
* @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array.
* @return {@link LuaString} wrapping a copy of the byte buffer
*/
public static LuaString valueOf(char[] bytes) {
int n = bytes.length;
byte[] b = new byte[n];
for ( int i=0; i<n; i++ )
b[i] = (byte) bytes[i];
return valueOf(b, 0, b.length);
return valueOf(bytes, 0, bytes.length);
}
/** Construct a {@link LuaString} using the supplied characters as byte values.
* <p>
* Only the low-order 8-bits of each character are used, the remainder is ignored.
* <p>
* This is most useful for constructing byte sequences that do not conform to UTF8.
* @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array.
* @return {@link LuaString} wrapping a copy of the byte buffer
*/
public static LuaString valueOf(char[] bytes, int off, int len) {
byte[] b = new byte[len];
for ( int i=0; i<len; i++ )
b[i] = (byte) bytes[i + off];
return valueOf(b, 0, len);
}
@@ -556,7 +568,7 @@ public class LuaString extends LuaValue {
* @param length number of bytes to convert
* @return Java String corresponding to the value of bytes interpreted using UTF8
* @see #lengthAsUtf8(char[])
* @see #encodeToUtf8(char[], byte[], int)
* @see #encodeToUtf8(char[], int, byte[], int)
* @see #isValidUtf8()
*/
public static String decodeAsUtf8(byte[] bytes, int offset, int length) {
@@ -581,7 +593,7 @@ public class LuaString extends LuaValue {
* Count the number of bytes required to encode the string as UTF-8.
* @param chars Array of unicode characters to be encoded as UTF-8
* @return count of bytes needed to encode using UTF-8
* @see #encodeToUtf8(char[], byte[], int)
* @see #encodeToUtf8(char[], int, byte[], int)
* @see #decodeAsUtf8(byte[], int, int)
* @see #isValidUtf8()
*/
@@ -601,16 +613,18 @@ public class LuaString extends LuaValue {
* The string should be measured first with lengthAsUtf8
* to make sure the given byte array is large enough.
* @param chars Array of unicode characters to be encoded as UTF-8
* @param nchars Number of characters in the array to convert.
* @param bytes byte array to hold the result
* @param off offset into the byte array to start writing
* @return number of bytes converted.
* @see #lengthAsUtf8(char[])
* @see #decodeAsUtf8(byte[], int, int)
* @see #isValidUtf8()
*/
public static void encodeToUtf8(char[] chars, byte[] bytes, int off) {
final int n = chars.length;
public static int encodeToUtf8(char[] chars, int nchars, byte[] bytes, int off) {
char c;
for ( int i=0, j=off; i<n; i++ ) {
int j = off;
for ( int i=0; i<nchars; i++ ) {
if ( (c = chars[i]) < 0x80 ) {
bytes[j++] = (byte) c;
} else if ( c < 0x800 ) {
@@ -622,12 +636,13 @@ public class LuaString extends LuaValue {
bytes[j++] = (byte) (0x80 | ( c & 0x3f));
}
}
return j - off;
}
/** Check that a byte sequence is valid UTF-8
* @return true if it is valid UTF-8, otherwise false
* @see #lengthAsUtf8(char[])
* @see #encodeToUtf8(char[], byte[], int)
* @see #encodeToUtf8(char[], int, byte[], int)
* @see #decodeAsUtf8(byte[], int, int)
*/
public boolean isValidUtf8() {
@@ -759,4 +774,15 @@ public class LuaString extends LuaValue {
}
}
/**
* Print the bytes of the LuaString to a PrintStream as if it were
* an ASCII string, quoting and escaping control characters.
* @param ps PrintStream to print to.
*/
public void printToStream(PrintStream ps) {
for (int i = 0, n = m_length; i < n; i++) {
int c = m_bytes[m_offset+i];
ps.print((char) c);
}
}
}

View File

@@ -23,6 +23,7 @@ package org.luaj.vm2.compiler;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Hashtable;
import org.luaj.vm2.LocVars;
@@ -136,7 +137,7 @@ public class LexState {
FuncState fs; /* `FuncState' is private to the parser */
LuaC L;
InputStream z; /* input stream */
byte[] buff; /* buffer for tokens */
char[] buff; /* buffer for tokens */
int nbuff; /* length of buffer */
Dyndata dyd = new Dyndata(); /* dynamic structures used by the parser */
LuaString source; /* current source name */
@@ -204,7 +205,7 @@ public class LexState {
public LexState(LuaC state, InputStream stream) {
this.z = stream;
this.buff = new byte[32];
this.buff = new char[32];
this.L = state;
}
@@ -229,7 +230,7 @@ public class LexState {
void save(int c) {
if ( buff == null || nbuff + 1 > buff.length )
buff = LuaC.realloc( buff, nbuff*2+1 );
buff[nbuff++] = (byte) c;
buff[nbuff++] = (char) c;
}
@@ -272,12 +273,11 @@ public class LexState {
// only called by new_localvarliteral() for var names.
LuaString newstring( String s ) {
byte[] b = s.getBytes();
return L.newTString(b, 0, b.length);
return L.newTString(s);
}
LuaString newstring( byte[] bytes, int offset, int len ) {
return L.newTString( bytes, offset, len );
LuaString newstring( char[] chars, int offset, int len ) {
return L.newTString(new String(chars, offset, len));
}
void inclinenumber() {
@@ -327,9 +327,9 @@ public class LexState {
return true;
}
void buffreplace(byte from, byte to) {
void buffreplace(char from, char to) {
int n = nbuff;
byte[] p = buff;
char[] p = buff;
while ((--n) >= 0)
if (p[n] == from)
p[n] = to;
@@ -477,7 +477,7 @@ public class LexState {
}
}
if (seminfo != null)
seminfo.ts = newstring(buff, 2 + sep, nbuff - 2 * (2 + sep));
seminfo.ts = L.newTString(LuaString.valueOf(buff, 2 + sep, nbuff - 2 * (2 + sep)));
}
int hexvalue(int c) {
@@ -574,7 +574,7 @@ public class LexState {
}
}
save_and_next(); /* skip delimiter */
seminfo.ts = newstring(buff, 1, nbuff - 2);
seminfo.ts = L.newTString(LuaString.valueOf(buff, 1, nbuff-2));
}
int llex(SemInfo seminfo) {
@@ -845,7 +845,7 @@ public class LexState {
if (t.token == TK_NAME || t.token == TK_STRING) {
LuaString ts = t.seminfo.ts;
// TODO: is this necessary?
newstring(ts.m_bytes, 0, ts.m_length);
L.cachedLuaString(t.seminfo.ts);
}
}

View File

@@ -25,7 +25,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LocVars;
import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaClosure;
@@ -35,7 +35,7 @@ import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Upvaldesc;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.lib.BaseLib;
/**
* Compiler for Lua.
@@ -45,7 +45,7 @@ import org.luaj.vm2.LoadState.LuaCompiler;
* and optionaly instantiates a {@link LuaClosure} around the result
* using a user-supplied environment.
* <p>
* Implements the {@link LuaCompiler} interface for loading
* Implements the {@link Globals.Compiler} interface for loading
* initialized chunks, which is an interface common to
* lua bytecode compiling and java bytecode compiling.
* <p>
@@ -66,7 +66,7 @@ import org.luaj.vm2.LoadState.LuaCompiler;
* @see LuaCompiler
* @see Prototype
*/
public class LuaC extends Lua implements LuaCompiler {
public class LuaC extends Lua implements Globals.Compiler, Globals.Loader {
public static final LuaC instance = new LuaC();
@@ -74,8 +74,9 @@ public class LuaC extends Lua implements LuaCompiler {
* try to use it when handed bytes that are
* not already a compiled lua chunk.
*/
public static void install() {
org.luaj.vm2.LoadState.compiler = instance;
public static void install(Globals g) {
g.compiler = instance;
g.loader = instance;
}
protected static void _assert(boolean b) {
@@ -213,6 +214,13 @@ public class LuaC extends Lua implements LuaCompiler {
return a;
}
static char[] realloc(char[] v, int n) {
char[] a = new char[n];
if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a;
}
public int nCcalls;
Hashtable strings;
@@ -222,28 +230,24 @@ public class LuaC extends Lua implements LuaCompiler {
this.strings = strings;
}
/** Load into a Closure or LuaFunction, with the supplied initial environment */
public LuaFunction load(InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = compile( stream, name );
return new LuaClosure( p, env );
}
/** Compile a prototype or load as a binary chunk */
public static Prototype compile(InputStream stream, String name) throws IOException {
int firstByte = stream.read();
return ( firstByte == '\033' )?
LoadState.loadBinaryChunk(firstByte, stream, name):
(new LuaC(new Hashtable())).luaY_parser(firstByte, stream, name);
/** Compile lua source into a Prototype.
* @param stream InputStream representing the text source conforming to lua source syntax.
* @param chunkname String name of the chunk to use.
* @return Prototype representing the lua chunk for this source.
* @throws IOException
*/
public Prototype compile(InputStream stream, String chunkname) throws IOException {
return (new LuaC(new Hashtable())).luaY_parser(stream, chunkname);
}
/** Parse the input */
private Prototype luaY_parser(int firstByte, InputStream z, String name) {
private Prototype luaY_parser(InputStream z, String name) throws IOException{
LexState lexstate = new LexState(this, z);
FuncState funcstate = new FuncState();
// lexstate.buff = buff;
lexstate.fs = funcstate;
lexstate.setinput( this, firstByte, z, (LuaString) LuaValue.valueOf(name) );
lexstate.setinput( this, z.read(), z, (LuaString) LuaValue.valueOf(name) );
/* main func. is always vararg */
funcstate.f = new Prototype();
funcstate.f.source = (LuaString) LuaValue.valueOf(name);
@@ -256,25 +260,28 @@ public class LuaC extends Lua implements LuaCompiler {
}
// look up and keep at most one copy of each string
public LuaString newTString(byte[] bytes, int offset, int len) {
LuaString tmp = LuaString.valueOf(bytes, offset, len);
LuaString v = (LuaString) strings.get(tmp);
if ( v == null ) {
// must copy bytes, since bytes could be from reusable buffer
byte[] copy = new byte[len];
System.arraycopy(bytes, offset, copy, 0, len);
v = LuaString.valueOf(copy);
strings.put(v, v);
}
return v;
public LuaString newTString(String s) {
return cachedLuaString(LuaString.valueOf(s));
}
// look up and keep at most one copy of each string
public LuaString newTString(LuaString s) {
return cachedLuaString(s);
}
public LuaString cachedLuaString(LuaString s) {
LuaString c = (LuaString) strings.get(s);
if (c != null)
return c;
strings.put(s, s);
return s;
}
public String pushfstring(String string) {
return string;
}
public LuaFunction load(Prototype p, String filename, LuaValue env) {
return new LuaClosure( p, env );
public LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException {
return new LuaClosure(prototype, env);
}
}

View File

@@ -228,9 +228,9 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
public Varargs invoke(Varargs args) {
LuaValue tostring = globals.get("tostring");
for ( int i=1, n=args.narg(); i<=n; i++ ) {
if ( i>1 ) globals.STDOUT.write( '\t' );
if ( i>1 ) globals.STDOUT.print( '\t' );
LuaString s = tostring.call( args.arg(i) ).strvalue();
globals.STDOUT.write( s.m_bytes, s.m_offset, s.m_length );
globals.STDOUT.print(s.tojstring());
}
globals.STDOUT.println();
return NONE;
@@ -438,7 +438,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
try {
if ( is == null )
return varargsOf(NIL, valueOf("not found: "+chunkname));
return LoadState.load(is, chunkname, mode, env);
return globals.load(is, chunkname, mode, env);
} catch (Exception e) {
return varargsOf(NIL, valueOf(e.getMessage()));
}

View File

@@ -22,7 +22,6 @@
package org.luaj.vm2.lib;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaBoolean;
import org.luaj.vm2.LuaClosure;

View File

@@ -151,7 +151,7 @@ public class OsLib extends TwoArgFunction {
tbl.set("min", LuaValue.valueOf(d.get(Calendar.MINUTE)));
tbl.set("sec", LuaValue.valueOf(d.get(Calendar.SECOND)));
tbl.set("wday", LuaValue.valueOf(d.get(Calendar.DAY_OF_WEEK)));
tbl.set("yday", LuaValue.valueOf(d.get(Calendar.DAY_OF_YEAR)));
tbl.set("yday", LuaValue.valueOf(d.get(0x6))); // Day of year
tbl.set("isdst", LuaValue.valueOf(isDaylightSavingsTime(d)));
return tbl;
}

View File

@@ -240,7 +240,7 @@ public class PackageLib extends TwoArgFunction {
LuaString filename = v.arg1().strvalue();
// Try to load the file.
v = globals.loadFile(filename.tojstring());
v = globals.loadfile(filename.tojstring());
if ( v.arg1().isfunction() )
return LuaValue.varargsOf(v.arg1(), filename);

View File

@@ -24,7 +24,6 @@ package org.luaj.vm2.lib.jme;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.BaseLib;
@@ -114,8 +113,8 @@ public class JmePlatform {
_G.load(new StringLib());
_G.load(new CoroutineLib());
_G.load(new JmeIoLib());
LuaC.install();
_G.compiler = LuaC.instance;
LoadState.install(_G);
LuaC.install(_G);
return _G;
}

View File

@@ -56,6 +56,7 @@ public class lua {
" -b use luajc bytecode-to-bytecode compiler (requires bcel on class path)\n" +
" -n nodebug - do not load debug library by default\n" +
" -p print the prototype\n" +
" -c enc use the supplied encoding 'enc' for input files\n" +
" -- stop handling options\n" +
" - execute stdin and stop handling options";
@@ -66,6 +67,7 @@ public class lua {
private static Globals _G;
private static boolean print = false;
private static String encoding = null;
public static void main( String[] args ) throws IOException {
@@ -113,6 +115,11 @@ public class lua {
case 'p':
print = true;
break;
case 'c':
if ( ++i >= args.length )
usageExit();
encoding = args[i];
break;
case '-':
if ( args[i].length() > 2 )
usageExit();
@@ -131,7 +138,7 @@ public class lua {
// new lua state
_G = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals();
if ( luajc ) LuaJC.install();
if ( luajc ) LuaJC.install(_G);
for ( int i=0, n=libs!=null? libs.size(): 0; i<n; i++ )
loadLibrary( (String) libs.elementAt(i) );
@@ -147,6 +154,7 @@ public class lua {
} else {
switch ( args[i].charAt(1) ) {
case 'l':
case 'c':
++i;
break;
case 'e':
@@ -187,9 +195,11 @@ public class lua {
private static void processScript( InputStream script, String chunkname, String[] args, int firstarg ) throws IOException {
try {
LuaFunction c;
LuaValue c;
try {
c = LoadState.load(script, chunkname, "bt", _G);
c = encoding != null?
_G.load(new InputStreamReader(script, encoding), chunkname):
_G.load(script, chunkname, "bt", _G);
} finally {
script.close();
}

View File

@@ -24,13 +24,14 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.luaj.vm2.Globals;
import org.luaj.vm2.Lua;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.DumpState;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.JsePlatform;
@@ -51,6 +52,7 @@ public class luac {
" -e little endian format for numbers\n" +
" -i<n> number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" +
" -v show version information\n" +
" -c enc use the supplied encoding 'enc' for input files\n" +
" -- stop handling options\n";
private static void usageExit() {
@@ -66,6 +68,7 @@ public class luac {
private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT;
private boolean versioninfo = false;
private boolean processing = true;
private String encoding = null;
public static void main( String[] args ) throws IOException {
new luac( args );
@@ -108,6 +111,11 @@ public class luac {
case 'v':
versioninfo = true;
break;
case 'c':
if ( ++i >= args.length )
usageExit();
encoding = args[i];
break;
case '-':
if ( args[i].length() > 2 )
usageExit();
@@ -129,17 +137,18 @@ public class luac {
// process input files
try {
JsePlatform.standardGlobals();
Globals globals = JsePlatform.standardGlobals();
processing = true;
for ( int i=0; i<args.length; i++ ) {
if ( ! processing || ! args[i].startsWith("-") ) {
String chunkname = args[i].substring(0,args[i].length()-4);
processScript( new FileInputStream(args[i]), chunkname, fos );
processScript( globals, new FileInputStream(args[i]), chunkname, fos );
} else if ( args[i].length() <= 1 ) {
processScript( System.in, "=stdin", fos );
processScript( globals, System.in, "=stdin", fos );
} else {
switch ( args[i].charAt(1) ) {
case 'o':
case 'c':
++i;
break;
case '-':
@@ -158,10 +167,12 @@ public class luac {
}
}
private void processScript( InputStream script, String chunkname, OutputStream out ) throws IOException {
private void processScript( Globals globals, InputStream script, String chunkname, OutputStream out ) throws IOException {
try {
// create the chunk
Prototype chunk = LuaC.instance.compile(script, chunkname);
Prototype chunk = encoding != null?
globals.compilePrototype(new InputStreamReader(script, encoding), chunkname):
globals.compilePrototype(script, chunkname);
// list the chunk
if (list)

View File

@@ -24,11 +24,13 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import org.luaj.vm2.Globals;
import org.luaj.vm2.Lua;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.luajc.LuaJC;
@@ -49,6 +51,7 @@ public class luajc {
" -m generate main(String[]) function for JSE\n" +
" -r recursively compile all\n" +
" -l load classes to verify generated bytecode\n" +
" -c enc use the supplied encoding 'enc' for input files\n" +
" -v verbose\n";
private static void usageExit() {
@@ -62,8 +65,10 @@ public class luajc {
private boolean recurse = false;
private boolean verbose = false;
private boolean loadclasses = false;
private String encoding = null;
private String pkgprefix = null;
private List files = new ArrayList();
private Globals globals;
public static void main( String[] args ) throws IOException {
new luajc( args );
@@ -104,6 +109,11 @@ public class luajc {
case 'r':
recurse = true;
break;
case 'c':
if ( ++i >= args.length )
usageExit();
encoding = args[i];
break;
case 'v':
verbose = true;
break;
@@ -140,7 +150,7 @@ public class luajc {
}
// process input files
JsePlatform.standardGlobals();
globals = JsePlatform.standardGlobals();
for ( int i=0,n=files.size(); i<n; i++ )
processFile( (InputFile) files.get(i) );
}
@@ -197,7 +207,9 @@ public class luajc {
// create the chunk
FileInputStream fis = new FileInputStream( inf.infile );
final Hashtable t = LuaJC.getInstance().compileAll(fis, inf.luachunkname, inf.srcfilename, genmain);
final Hashtable t = encoding != null?
LuaJC.instance.compileAll( new InputStreamReader(fis, encoding), inf.luachunkname, inf.srcfilename, globals, genmain):
LuaJC.instance.compileAll( fis, inf.luachunkname, inf.srcfilename, globals, genmain);
fis.close();
// write out the chunk

View File

@@ -22,6 +22,7 @@
package org.luaj.vm2.lib.jse;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.compiler.LuaC;
@@ -101,8 +102,8 @@ public class JsePlatform {
_G.load(new JseIoLib());
_G.load(new JseOsLib());
_G.load(new LuajavaLib());
LuaC.install();
_G.compiler = LuaC.instance;
LoadState.install(_G);
LuaC.install(_G);
return _G;
}

View File

@@ -23,14 +23,15 @@ package org.luaj.vm2.luajc;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Hashtable;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.LoadState.LuaCompiler;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.BaseLib;
/**
* Implementation of {@link LuaCompiler} which does direct
@@ -46,45 +47,44 @@ import org.luaj.vm2.compiler.LuaC;
* as in the following:
* <pre> {@code
* LuaValue _G = JsePlatform.standardGlobals();
* LuaJC.install();
* LoadState.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call();
* LuaJC.install(_G);
* _G.loadString("print 'hello'").call();
* } </pre>
* @see LuaCompiler
* @see LuaC
* @see JsePlatform
* @see JmePlatform
* @see BaseLib
* @see LuaValue
*/
public class LuaJC implements LuaCompiler {
public class LuaJC implements Globals.Loader {
private static final String NON_IDENTIFIER = "[^a-zA-Z0-9_$/.\\-]";
private static LuaJC instance;
public static LuaJC getInstance() {
if ( instance == null )
instance = new LuaJC();
return instance;
}
public static final LuaJC instance = new LuaJC();
/**
* Install the compiler as the main compiler to use.
* Install the compiler as the main Globals.Loader to use in a set of globals.
* Will fall back to the LuaC prototype compiler.
*/
public static final void install() {
LoadState.compiler = getInstance();
public static final void install(Globals G) {
G.loader = instance;
}
public LuaJC() {
protected LuaJC() {}
public Hashtable compileAll(InputStream script, String chunkname, String filename, Globals globals, boolean genmain) throws IOException {
final String classname = toStandardJavaClassName( chunkname );
final Prototype p = globals.loadPrototype(script, classname, "bt");
return compileProtoAndSubProtos(p, classname, filename, genmain);
}
public Hashtable compileAll(InputStream script, String chunkname, String filename, boolean genmain) throws IOException {
String classname = toStandardJavaClassName( chunkname );
String luaname = toStandardLuaFileName( filename );
Hashtable h = new Hashtable();
Prototype p = LuaC.instance.compile(script, classname);
JavaGen gen = new JavaGen(p, classname, luaname, genmain);
public Hashtable compileAll(Reader script, String chunkname, String filename, Globals globals, boolean genmain) throws IOException {
final String classname = toStandardJavaClassName( chunkname );
final Prototype p = globals.compilePrototype(script, classname);
return compileProtoAndSubProtos(p, classname, filename, genmain);
}
private Hashtable compileProtoAndSubProtos(Prototype p, String classname, String filename, boolean genmain) throws IOException {
final String luaname = toStandardLuaFileName( filename );
final Hashtable h = new Hashtable();
final JavaGen gen = new JavaGen(p, classname, luaname, genmain);
insert( h, gen );
return h;
}
@@ -95,12 +95,11 @@ public class LuaJC implements LuaCompiler {
insert(h, gen.inners[i]);
}
public LuaFunction load(InputStream stream, String name, LuaValue env) throws IOException {
Prototype p = LuaC.instance.compile(stream, name);
public LuaFunction load(Prototype p, String name, LuaValue globals) throws IOException {
String luaname = toStandardLuaFileName( name );
String classname = toStandardJavaClassName( luaname );
JavaLoader loader = new JavaLoader();
return loader.load(p, classname, luaname, env);
return loader.load(p, classname, luaname, globals);
}
private static String toStandardJavaClassName( String luachunkname ) {

View File

@@ -83,7 +83,7 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
InputStream is = new Utf8Encoder(script);
try {
final Globals g = context.globals;
final LuaFunction f = LoadState.load(is, "script", "bt", g);
final LuaFunction f = g.load(script, "script").checkfunction();
return new LuajCompiledScript(f, g);
} catch ( LuaError lee ) {
throw new ScriptException(lee.getMessage() );

View File

@@ -38,7 +38,6 @@ public class LuaScriptEngineFactory implements ScriptEngineFactory {
};
private static final String [] MIMETYPES = {
"text/plain",
"text/lua",
"application/lua"
};

View File

@@ -28,12 +28,12 @@ import java.io.PrintStream;
import java.io.Reader;
import java.io.Writer;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.SimpleScriptContext;
import org.luaj.vm2.Globals;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.luajc.LuaJC;
/**
* Context for LuaScriptEngine execution which maintains its own Globals,
@@ -61,11 +61,13 @@ public class LuajContext extends SimpleScriptContext implements ScriptContext {
* have negative impact on performance.
*/
public LuajContext() {
this("true".equals(System.getProperty("org.luaj.debug")));
this("true".equals(System.getProperty("org.luaj.debug")),
"true".equals(System.getProperty("org.luaj.luajc")));
}
/** Construct a LuajContext with its own globals, which
* which optionally are debug globals.
* which optionally are debug globals, and optionally use the
* luajc direct lua to java bytecode compiler.
* <p>
* If createDebugGlobals is set, the globals
* created will be a debug globals that includes the debug
@@ -73,11 +75,15 @@ public class LuajContext extends SimpleScriptContext implements ScriptContext {
* have negative impact on performance.
* @param createDebugGlobals true to create debug globals,
* false for standard globals.
* @param useLuaJCCompiler true to use the luajc compiler,
* reqwuires bcel to be on the class path.
*/
public LuajContext(boolean createDebugGlobals) {
public LuajContext(boolean createDebugGlobals, boolean useLuaJCCompiler) {
globals = createDebugGlobals?
JsePlatform.debugGlobals():
JsePlatform.standardGlobals();
if (useLuaJCCompiler)
LuaJC.install(globals);
stdin = globals.STDIN;
stdout = globals.STDOUT;
stderr = globals.STDERR;

View File

@@ -21,14 +21,10 @@
******************************************************************************/
package org.luaj.luajc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.JsePlatform;
/** Test the plain old bytecode interpreter */
@@ -51,11 +47,10 @@ public class TestLuaJ {
System.out.println(script);
// create an environment to run in
LuaTable _G = JsePlatform.standardGlobals();
Globals _G = JsePlatform.standardGlobals();
// compile into a chunk, or load as a class
InputStream is = new ByteArrayInputStream( script.getBytes() );
LuaValue chunk = LuaC.instance.load(is, "script", _G);
LuaValue chunk = _G.load(script, "script");
// The loaded chunk should be a closure, which contains the prototype.
print( chunk.checkclosure().p );

View File

@@ -51,14 +51,14 @@ public class TestLuaJC {
_G = JsePlatform.standardGlobals();
// print the chunk as a closure, and pretty-print the closure.
LuaValue f = _G.loadFile(filename).arg1();
LuaValue f = _G.loadfile(filename).arg1();
Prototype p = f.checkclosure().p;
Print.print(p);
// load into a luajc java-bytecode based chunk by installing the LuaJC compiler first
if ( ! (args.length>0 && args[0].equals("nocompile")) ) {
LuaJC.install();
f = _G.loadFile(filename).arg1();
LuaJC.install(_G);
f = _G.loadfile(filename).arg1();
}
// call with arguments
@@ -80,7 +80,7 @@ public class TestLuaJC {
String destdir = ".";
InputStream is = _G.FINDER.findResource(filename);
Hashtable t = LuaJC.getInstance().compileAll(is, filename, filename, true);
Hashtable t = LuaJC.instance.compileAll(is, filename, filename, _G, true);
// write out the chunk
for ( Enumeration e = t.keys(); e.hasMoreElements(); ) {

View File

@@ -107,7 +107,7 @@ public class CompatibiltyTest extends TestSuite {
protected void setUp() throws Exception {
super.setUp();
System.setProperty("JME", "false");
LuaJC.install();
LuaJC.install(globals);
}
// not supported on this platform - don't test
public void testDebugLib() {}

View File

@@ -21,13 +21,13 @@
******************************************************************************/
package org.luaj.vm2;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.luajc.LuaJC;
/**
@@ -64,16 +64,18 @@ public class FragmentsTest extends TestSuite {
public void runFragment( Varargs expected, String script ) {
try {
String name = getName();
Globals _G = org.luaj.vm2.lib.jse.JsePlatform.debugGlobals();
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
Globals _G = JsePlatform.debugGlobals();
Reader reader = new StringReader(script);
LuaValue chunk ;
switch ( TEST_TYPE ) {
case TEST_TYPE_LUAJC:
chunk = LuaJC.getInstance().load(is,name,_G);
LuaJC.install(_G);
chunk = _G.load(reader, name);
break;
default:
chunk = LuaC.instance.load( is, name, _G );
Print.print(((LuaClosure)chunk).p);
Prototype p = _G.compilePrototype(reader, name);
chunk = new LuaClosure(p, _G);
Print.print(p);
break;
}
Varargs actual = chunk.invoke();

View File

@@ -21,8 +21,8 @@
******************************************************************************/
package org.luaj.vm2;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import junit.framework.TestCase;
@@ -130,9 +130,9 @@ public class LuaOperationsTest extends TestCase {
public Prototype createPrototype( String script, String name ) {
try {
LuaTable _G = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals();
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
return LuaC.instance.compile(is, name);
Globals _G = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals();
Reader reader = new StringReader(script);
return _G.compilePrototype(reader, name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();

View File

@@ -21,15 +21,10 @@
******************************************************************************/
package org.luaj.vm2;
import java.io.ByteArrayInputStream;
import java.lang.ref.WeakReference;
import junit.framework.TestCase;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
@@ -74,8 +69,7 @@ public class OrphanedThreadTest extends TestCase {
"arg = coroutine.yield(0)\n" +
"print('leakage in closure.3, arg is '..arg)\n" +
"return 'done'\n";
LuaC.install();
function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", globals);
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@@ -90,8 +84,7 @@ public class OrphanedThreadTest extends TestCase {
" return 'done'\n" +
"end\n" +
"print( 'pcall-closre.result:', pcall( f, ... ) )\n";
LuaC.install();
function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", globals);
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@@ -107,8 +100,7 @@ public class OrphanedThreadTest extends TestCase {
" return t[i]\n" +
"end\n" +
"load(f)()\n";
LuaC.install();
function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", globals);
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ONE);
}

View File

@@ -177,7 +177,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
}
}
protected LuaValue loadScript(String name, LuaTable _G) throws IOException {
protected LuaValue loadScript(String name, Globals _G) throws IOException {
InputStream script = this.findResource(name+".lua");
if ( script == null )
fail("Could not load script for test case: " + name);
@@ -188,10 +188,11 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder {
LuaValue c = (LuaValue) Class.forName(name).newInstance();
return c;
} else {
return LuaJC.getInstance().load( script, name, _G);
LuaJC.install(_G);
return _G.load(script, name, "bt", _G);
}
default:
return LoadState.load(script, "@"+name+".lua", "bt", _G);
return _G.load(script, "@"+name+".lua", "bt", _G);
}
} catch ( Exception e ) {
e.printStackTrace();

View File

@@ -11,8 +11,8 @@ import java.net.URL;
import junit.framework.TestCase;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.lib.jse.JsePlatform;
@@ -21,7 +21,7 @@ abstract public class AbstractUnitTests extends TestCase {
private final String dir;
private final String jar;
private LuaTable _G;
private Globals _G;
public AbstractUnitTests(String zipdir, String zipfile, String dir) {
URL zip = null;
@@ -67,7 +67,7 @@ abstract public class AbstractUnitTests extends TestCase {
// compile in memory
InputStream is = new ByteArrayInputStream(lua);
Prototype p = LuaC.instance.compile(is, "@" + file);
Prototype p = _G.loadPrototype(is, "@" + file, "bt");
String actual = protoToString(p);
// load expected value from jar
@@ -109,7 +109,7 @@ abstract public class AbstractUnitTests extends TestCase {
protected Prototype loadFromBytes(byte[] bytes, String script)
throws IOException {
InputStream is = new ByteArrayInputStream(bytes);
return LoadState.loadBinaryChunk(is.read(), is, script);
return _G.loadPrototype(is, script, "b");
}
protected String protoToString(Prototype p) {

View File

@@ -6,13 +6,15 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import junit.framework.TestCase;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.lib.jse.JsePlatform;
@@ -28,7 +30,7 @@ public class DumpLoadEndianIntTest extends TestCase {
private static final String withdoubles = "1234-#!-23.75";
private static final String withints = "1234-#!-23";
private LuaTable _G;
private Globals _G;
protected void setUp() throws Exception {
super.setUp();
@@ -83,8 +85,8 @@ public class DumpLoadEndianIntTest extends TestCase {
try {
// compile into prototype
InputStream is = new ByteArrayInputStream(script.getBytes());
Prototype p = LuaC.instance.compile(is, "script");
Reader reader = new StringReader(script);
Prototype p = _G.compilePrototype(reader, "script");
// double check script result before dumping
LuaFunction f = new LuaClosure(p, _G);
@@ -107,8 +109,8 @@ public class DumpLoadEndianIntTest extends TestCase {
byte[] dumped = baos.toByteArray();
// load again using compiler
is = new ByteArrayInputStream(dumped);
f = LoadState.load(is, "dumped", "bt", _G);
InputStream is = new ByteArrayInputStream(dumped);
f = _G.load(is, "dumped", "b", _G).checkfunction();
r = f.call();
actual = r.tojstring();
assertEquals( expectedPostDump, actual );

View File

@@ -1,20 +1,16 @@
package org.luaj.vm2.compiler;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import junit.framework.TestCase;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
public class SimpleTests extends TestCase {
private LuaTable _G;
private Globals _G;
protected void setUp() throws Exception {
super.setUp();
@@ -23,8 +19,7 @@ public class SimpleTests extends TestCase {
private void doTest( String script ) {
try {
InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") );
LuaFunction c = LuaC.instance.load( is, "script", _G );
LuaValue c = _G.load(script, "script");
c.call();
} catch ( Exception e ) {
fail("i/o exception: "+e );

View File

@@ -1,20 +1,13 @@
package org.luaj.vm2.lib.jse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.Permission;
import junit.framework.TestCase;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.JsePlatform;
public class LuajavaAccessibleMembersTest extends TestCase {
private LuaTable _G;
private Globals _G;
protected void setUp() throws Exception {
super.setUp();
@@ -23,8 +16,7 @@ public class LuajavaAccessibleMembersTest extends TestCase {
private String invokeScript(String script) {
try {
InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") );
LuaFunction c = LuaC.instance.load( is, "script", _G );
LuaValue c = _G.load(script, "script");
return c.call().tojstring();
} catch ( Exception e ) {
fail("exception: "+e );

View File

@@ -21,7 +21,6 @@
******************************************************************************/
package org.luaj.vm2.script;
import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.Reader;
@@ -100,8 +99,8 @@ public class ScriptEngineTests extends TestSuite {
return new SimpleBindings();
}
public void setUp() {
System.setProperty("org.luaj.luajc", "true");
super.setUp();
org.luaj.vm2.luajc.LuaJC.install();
}
public void testCompiledFunctionIsNotClosure() throws ScriptException {
CompiledScript cs = ((Compilable)e).compile("return 'foo'");