-
-It relies on the cobertura code coverage library.
+The maven build creates the coverage report in the luaj-test/target/site folder
+during the verify phase.
- * The buffer can begin initially as a wrapped {@link LuaValue}
- * and only when concatenation actually occurs are the bytes first copied.
- *
- * To convert back to a {@link LuaValue} again,
- * the function {@link Buffer#value()} is used.
+ * The buffer can begin initially as a wrapped {@link LuaValue} and only when
+ * concatenation actually occurs are the bytes first copied.
+ *
+ * To convert back to a {@link LuaValue} again, the function
+ * {@link Buffer#value()} is used.
+ *
* @see LuaValue
* @see LuaValue#buffer()
* @see LuaString
*/
public final class Buffer {
-
+
/** Default capacity for a buffer: 64 */
private static final int DEFAULT_CAPACITY = 64;
-
+
/** Shared static array with no bytes */
private static final byte[] NOBYTES = {};
/** Bytes in this buffer */
private byte[] bytes;
-
+
/** Length of this buffer */
private int length;
-
+
/** Offset into the byte array */
private int offset;
-
+
/** Value of this buffer, when not represented in bytes */
private LuaValue value;
-
+
/**
* Create buffer with default capacity
+ *
* @see #DEFAULT_CAPACITY
*/
public Buffer() {
this(DEFAULT_CAPACITY);
}
-
+
/**
* Create buffer with specified initial capacity
+ *
* @param initialCapacity the initial capacity
*/
- public Buffer( int initialCapacity ) {
- bytes = new byte[ initialCapacity ];
+ public Buffer(int initialCapacity) {
+ bytes = new byte[initialCapacity];
length = 0;
offset = 0;
value = null;
}
-
+
/**
* Create buffer with specified initial value
+ *
* @param value the initial value
*/
public Buffer(LuaValue value) {
@@ -84,16 +87,18 @@ public final class Buffer {
this.value = value;
}
- /**
+ /**
* Get buffer contents as a {@link LuaValue}
+ *
* @return value as a {@link LuaValue}, converting as necessary
*/
public LuaValue value() {
return value != null? value: this.tostring();
}
- /**
+ /**
* Set buffer contents as a {@link LuaValue}
+ *
* @param value value to set
*/
public Buffer setvalue(LuaValue value) {
@@ -102,145 +107,171 @@ public final class Buffer {
this.value = value;
return this;
}
-
- /**
+
+ /**
* Convert the buffer to a {@link LuaString}
+ *
* @return the value as a {@link LuaString}
*/
- public final LuaString tostring() {
- realloc( length, 0 );
- return LuaString.valueOf( bytes, offset, length );
+ public LuaString tostring() {
+ realloc(length, 0);
+ return LuaString.valueOf(bytes, offset, length);
}
-
- /**
+
+ /**
* Convert the buffer to a Java String
+ *
* @return the value as a Java String
*/
public String tojstring() {
return value().tojstring();
}
-
- /**
+
+ /**
* Convert the buffer to a Java String
+ *
* @return the value as a Java String
*/
+ @Override
public String toString() {
return tojstring();
}
- /**
+ /**
* Append a single byte to the buffer.
+ *
* @return {@code this} to allow call chaining
*/
- public final Buffer append( byte b ) {
- makeroom( 0, 1 );
- bytes[ offset + length++ ] = b;
+ public Buffer append(byte b) {
+ makeroom(0, 1);
+ bytes[offset+length++] = b;
return this;
}
- /**
+ /**
* Append a {@link LuaValue} to the buffer.
+ *
* @return {@code this} to allow call chaining
*/
- public final Buffer append( LuaValue val ) {
- append( val.strvalue() );
+ public Buffer append(LuaValue val) {
+ append(val.strvalue());
return this;
}
-
- /**
+
+ /**
* Append a {@link LuaString} to the buffer.
+ *
* @return {@code this} to allow call chaining
*/
- public final Buffer append( LuaString str ) {
+ public Buffer append(LuaString str) {
final int n = str.m_length;
- makeroom( 0, n );
- str.copyInto( 0, bytes, offset + length, n );
+ makeroom(0, n);
+ str.copyInto(0, bytes, offset+length, n);
length += n;
return this;
}
-
- /**
- * Append a Java String to the buffer.
- * The Java string will be converted to bytes using the UTF8 encoding.
+
+ /**
+ * 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[], int, byte[], int)
*/
- public final Buffer append( String str ) {
+ public Buffer append(String str) {
char[] c = str.toCharArray();
- final int n = LuaString.lengthAsUtf8( c );
- makeroom( 0, n );
- LuaString.encodeToUtf8( c, c.length, bytes, offset + length );
+ final int n = LuaString.lengthAsUtf8(c);
+ makeroom(0, n);
+ LuaString.encodeToUtf8(c, c.length, bytes, offset+length);
length += n;
return this;
}
- /** Concatenate this buffer onto a {@link LuaValue}
- * @param lhs the left-hand-side value onto which we are concatenating {@code this}
+ /**
+ * Concatenate this buffer onto a {@link LuaValue}
+ *
+ * @param lhs the left-hand-side value onto which we are concatenating
+ * {@code this}
* @return {@link Buffer} for use in call chaining.
*/
public Buffer concatTo(LuaValue lhs) {
return setvalue(lhs.concat(value()));
}
- /** Concatenate this buffer onto a {@link LuaString}
- * @param lhs the left-hand-side value onto which we are concatenating {@code this}
+ /**
+ * Concatenate this buffer onto a {@link LuaString}
+ *
+ * @param lhs the left-hand-side value onto which we are concatenating
+ * {@code this}
* @return {@link Buffer} for use in call chaining.
*/
public Buffer concatTo(LuaString lhs) {
- return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs);
+ return value != null && !value.isstring()? setvalue(lhs.concat(value)): prepend(lhs);
}
- /** Concatenate this buffer onto a {@link LuaNumber}
+ /**
+ * Concatenate this buffer onto a {@link LuaNumber}
*
- * The {@link LuaNumber} will be converted to a string before concatenating.
- * @param lhs the left-hand-side value onto which we are concatenating {@code this}
+ * The {@link LuaNumber} will be converted to a string before concatenating.
+ *
+ * @param lhs the left-hand-side value onto which we are concatenating
+ * {@code this}
* @return {@link Buffer} for use in call chaining.
*/
public Buffer concatTo(LuaNumber lhs) {
- return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue());
+ return value != null && !value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue());
}
- /** Concatenate bytes from a {@link LuaString} onto the front of this buffer
- * @param s the left-hand-side value which we will concatenate onto the front of {@code this}
+ /**
+ * Concatenate bytes from a {@link LuaString} onto the front of this buffer
+ *
+ * @param s the left-hand-side value which we will concatenate onto the
+ * front of {@code this}
* @return {@link Buffer} for use in call chaining.
*/
public Buffer prepend(LuaString s) {
int n = s.m_length;
- makeroom( n, 0 );
- System.arraycopy( s.m_bytes, s.m_offset, bytes, offset-n, n );
+ makeroom(n, 0);
+ System.arraycopy(s.m_bytes, s.m_offset, bytes, offset-n, n);
offset -= n;
length += n;
value = null;
return this;
}
- /** Ensure there is enough room before and after the bytes.
- * @param nbefore number of unused bytes which must precede the data after this completes
- * @param nafter number of unused bytes which must follow the data after this completes
+ /**
+ * Ensure there is enough room before and after the bytes.
+ *
+ * @param nbefore number of unused bytes which must precede the data after
+ * this completes
+ * @param nafter number of unused bytes which must follow the data after
+ * this completes
*/
- public final void makeroom( int nbefore, int nafter ) {
- if ( value != null ) {
+ public void makeroom(int nbefore, int nafter) {
+ if (value != null) {
LuaString s = value.strvalue();
value = null;
length = s.m_length;
offset = nbefore;
bytes = new byte[nbefore+length+nafter];
System.arraycopy(s.m_bytes, s.m_offset, bytes, offset, length);
- } else if ( offset+length+nafter > bytes.length || offset bytes.length || offset < nbefore) {
int n = nbefore+length+nafter;
- int m = n<32? 32: n
- *
- *
Constructing and Initializing Instances
- * Typically, this is constructed indirectly by a call to
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
- * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()},
- * and then used to load lua scripts for execution as in the following example.
- *
Typically, this is
+ * constructed indirectly by a call to
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}, and then used to
+ * load lua scripts for execution as in the following example.
+ *
+ *
- * Executable LuaFunctions are created from lua code in several steps
+ * For specialized circumstances, the Globals may be constructed directly and
+ * loaded with only those libraries that are needed, for example.
+ *
+ *
Executable
+ * LuaFunctions are created from lua code in several steps
*
*
find the resource using the platform's {@link ResourceFinder}
*
compile lua to lua bytecode using {@link Compiler}
*
load lua bytecode to a {@link Prototype} using {@link Undumper}
- *
construct {@link LuaClosure} from {@link Prototype} with {@link Globals} using {@link Loader}
+ *
construct {@link LuaClosure} from {@link Prototype} with {@link Globals}
+ * using {@link Loader}
*
*
- * There are alternate flows when the direct lua-to-Java bytecode compiling {@link org.luaj.vm2.luajc.LuaJC} is used.
+ * There are alternate flows when the direct lua-to-Java bytecode compiling
+ * {@link org.luaj.vm2.luajc.LuaJC} is used.
*
- *
compile lua to lua bytecode using {@link Compiler} or load precompiled code using {@link Undumper}
- *
convert lua bytecode to equivalent Java bytecode using {@link org.luaj.vm2.luajc.LuaJC} that implements {@link Loader} directly
+ *
compile lua to lua bytecode using {@link Compiler} or load precompiled
+ * code using {@link Undumper}
+ *
convert lua bytecode to equivalent Java bytecode using
+ * {@link org.luaj.vm2.luajc.LuaJC} that implements {@link Loader} directly
*
- *
- *
Java Field
- * Certain public fields are provided that contain the current values of important global state:
+ *
+ *
Java Field
Certain public fields are provided that contain the
+ * current values of important global state:
*
- *
{@link #STDIN} Current value for standard input in the laaded {@link IoLib}, if any.
- *
{@link #STDOUT} Current value for standard output in the loaded {@link IoLib}, if any.
- *
{@link #STDERR} Current value for standard error in the loaded {@link IoLib}, if any.
+ *
{@link #STDIN} Current value for standard input in the laaded
+ * {@link IoLib}, if any.
+ *
{@link #STDOUT} Current value for standard output in the loaded
+ * {@link IoLib}, if any.
+ *
{@link #STDERR} Current value for standard error in the loaded
+ * {@link IoLib}, if any.
*
{@link #finder} Current loaded {@link ResourceFinder}, if any.
*
{@link #compiler} Current loaded {@link Compiler}, if any.
*
{@link #undumper} Current loaded {@link Undumper}, if any.
*
{@link #loader} Current loaded {@link Loader}, if any.
*
- *
- *
Lua Environment Variables
- * When using {@link org.luaj.vm2.lib.jse.JsePlatform} or {@link org.luaj.vm2.lib.jme.JmePlatform},
- * these environment variables are created within the Globals.
+ *
+ *
Lua Environment Variables
When using
+ * {@link org.luaj.vm2.lib.jse.JsePlatform} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform}, these environment variables are
+ * created within the Globals.
*
*
"_G" Pointer to this Globals.
*
"_VERSION" String containing the version of luaj.
*
- *
- *
Use in Multithreaded Environments
- * In a multi-threaded server environment, each server thread should create one Globals instance,
- * which will be logically distinct and not interfere with each other, but share certain
- * static immutable resources such as class data and string data.
+ *
+ *
Use in Multithreaded Environments
In a multi-threaded server
+ * environment, each server thread should create one Globals instance, which
+ * will be logically distinct and not interfere with each other, but share
+ * certain static immutable resources such as class data and string data.
*
- *
+ *
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see LuaValue
@@ -115,7 +136,7 @@ import org.luaj.vm2.lib.ResourceFinder;
public class Globals extends LuaTable {
/** The current default input stream. */
- public InputStream STDIN = null;
+ public InputStream STDIN = null;
/** The current default output stream. */
public PrintStream STDOUT = System.out;
@@ -125,28 +146,42 @@ public class Globals extends LuaTable {
/** The installed ResourceFinder for looking files by name. */
public ResourceFinder finder;
-
- /** The currently running thread. Should not be changed by non-library code. */
+
+ /**
+ * The currently running thread. Should not be changed by non-library code.
+ */
public LuaThread running = new LuaThread(this);
/** The BaseLib instance loaded into this Globals */
public BaseLib baselib;
-
+
/** The PackageLib instance loaded into this Globals */
public PackageLib package_;
-
- /** The DebugLib instance loaded into this Globals, or null if debugging is not enabled */
+
+ /**
+ * The DebugLib instance loaded into this Globals, or null if debugging is
+ * not enabled
+ */
public DebugLib debuglib;
- /** Interface for module that converts a Prototype into a LuaFunction with an environment. */
+ /**
+ * 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. */
+ /**
+ * 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. */
+ /**
+ * Compile lua source into a Prototype. The InputStream is assumed to be
+ * in UTF-8.
+ */
Prototype compile(InputStream stream, String chunkname) throws IOException;
}
@@ -155,100 +190,143 @@ public class Globals extends LuaTable {
/** 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. */
+
+ /**
+ * Check that this object is a Globals object, and return it, otherwise
+ * throw an error.
+ */
+ @Override
public Globals checkglobals() {
return this;
}
-
- /** The installed loader.
- * @see Loader */
+
+ /**
+ * The installed loader.
+ *
+ * @see Loader
+ */
public Loader loader;
- /** The installed compiler.
- * @see Compiler */
+ /**
+ * The installed compiler.
+ *
+ * @see Compiler
+ */
public Compiler compiler;
- /** The installed undumper.
- * @see Undumper */
+ /**
+ * The installed undumper.
+ *
+ * @see Undumper
+ */
public Undumper undumper;
- /** Convenience function for loading a file that is either binary lua or lua source.
+ /**
+ * 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) {
try {
- return load(finder.findResource(filename), "@"+filename, "bt", this);
+ return load(finder.findResource(filename), "@" + filename, "bt", this);
} catch (Exception e) {
- return error("load "+filename+": "+e);
+ return error("load " + filename + ": " + e);
}
}
- /** 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.'"
+ /**
+ * 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.
+ * @return LuaValue that may be executed via .call(), .invoke(), or
+ * .method() calls.
* @throws LuaError if the script could not be compiled.
*/
public LuaValue load(String script, String chunkname) {
return load(new StrReader(script), chunkname);
}
-
- /** Convenience function to load a string value as a script. Must be lua source.
+
+ /**
+ * 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.'"
- * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
+ * @return LuaValue that may be executed via .call(), .invoke(), or
+ * .method() calls.
* @throws LuaError if the script could not be compiled.
*/
public LuaValue load(String script) {
return load(new StrReader(script), script);
}
- /** Convenience function to load a string value as a script with a custom environment.
- * 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.
- * @param environment LuaTable to be used as the environment for the loaded function.
- * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
+ /**
+ * Convenience function to load a string value as a script with a custom
+ * environment. 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.
+ * @param environment LuaTable to be used as the environment for the loaded
+ * function.
+ * @return LuaValue that may be executed via .call(), .invoke(), or
+ * .method() calls.
* @throws LuaError if the script could not be compiled.
*/
public LuaValue load(String script, String chunkname, LuaTable environment) {
return load(new StrReader(script), chunkname, environment);
}
- /** 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.
- * @param reader Reader containing text of a lua script, such as "print 'hello, world.'"
+ /**
+ * 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.
+ *
+ * @param reader Reader containing text 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.
+ * @return LuaValue that may be executed via .call(), .invoke(), or
+ * .method() calls.
* @throws LuaError if the script could not be compiled.
- */
+ */
public LuaValue load(Reader reader, String chunkname) {
return load(new UTF8Stream(reader), chunkname, "t", this);
}
- /** Load the content form a reader as a text file, supplying a custom environment.
- * 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.
- * @param reader Reader containing text of a lua script, such as "print 'hello, world.'"
- * @param chunkname Name that will be used within the chunk as the source.
- * @param environment LuaTable to be used as the environment for the loaded function.
- * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
+ /**
+ * Load the content form a reader as a text file, supplying a custom
+ * environment. 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.
+ *
+ * @param reader Reader containing text of a lua script, such as "print
+ * 'hello, world.'"
+ * @param chunkname Name that will be used within the chunk as the source.
+ * @param environment LuaTable to be used as the environment for the loaded
+ * function.
+ * @return LuaValue that may be executed via .call(), .invoke(), or
+ * .method() calls.
* @throws LuaError if the script could not be compiled.
- */
+ */
public LuaValue load(Reader reader, String chunkname, LuaTable environment) {
return load(new UTF8Stream(reader), chunkname, "t", environment);
- }
+ }
- /** Load the content form an input stream as a binary chunk or text file.
- * @param is InputStream containing a lua script or compiled lua"
- * @param chunkname Name that will be used within the chunk as the source.
- * @param mode String containing 'b' or 't' or both to control loading as binary or text or either.
- * @param environment LuaTable to be used as the environment for the loaded function.
- * */
+ /**
+ * Load the content form an input stream as a binary chunk or text file.
+ *
+ * @param is InputStream containing a lua script or compiled lua"
+ * @param chunkname Name that will be used within the chunk as the source.
+ * @param mode String containing 'b' or 't' or both to control
+ * loading as binary or text or either.
+ * @param environment LuaTable to be used as the environment for the loaded
+ * function.
+ */
public LuaValue load(InputStream is, String chunkname, String mode, LuaValue environment) {
try {
Prototype p = loadPrototype(is, chunkname, mode);
@@ -256,16 +334,20 @@ public class Globals extends LuaTable {
} catch (LuaError l) {
throw l;
} catch (Exception e) {
- return error("load "+chunkname+": "+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.
- * @param is Input stream containing a lua script or compiled lua"
+ /**
+ * 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.
+ *
+ * @param is Input stream containing a lua script or compiled lua"
* @param chunkname Name that will be used within the chunk as the source.
- * @param mode String containing 'b' or 't' or both to control loading as binary or text or either.
+ * @param mode String containing 'b' or 't' or both to control loading
+ * as binary or text or either.
*/
public Prototype loadPrototype(InputStream is, String chunkname, String mode) throws IOException {
if (mode.indexOf('b') >= 0) {
@@ -282,21 +364,25 @@ public class Globals extends LuaTable {
if (mode.indexOf('t') >= 0) {
return compilePrototype(is, chunkname);
}
- error("Failed to load prototype "+chunkname+" using mode '"+mode+"'");
+ 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.
+
+ /**
+ * 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.
+
+ /**
+ * 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)
@@ -304,9 +390,13 @@ public class Globals extends LuaTable {
return compiler.compile(stream, chunkname);
}
- /** Function which yields the current thread.
- * @param args Arguments to supply as return values in the resume function of the resuming thread.
- * @return Values supplied as arguments to the resume() call that reactivates this thread.
+ /**
+ * Function which yields the current thread.
+ *
+ * @param args Arguments to supply as return values in the resume function
+ * of the resuming thread.
+ * @return Values supplied as arguments to the resume() call that
+ * reactivates this thread.
*/
public Varargs yield(Varargs args) {
if (running == null || running.isMainThread())
@@ -318,23 +408,30 @@ public class Globals extends LuaTable {
/** Reader implementation to read chars from a String in JME or JSE. */
static class StrReader extends Reader {
final String s;
- int i = 0;
- final int n;
+ int i = 0;
+ final int n;
+
StrReader(String s) {
this.s = s;
n = s.length();
}
+
+ @Override
public void close() throws IOException {
i = n;
}
+
+ @Override
public int read() throws IOException {
- return i < n ? s.charAt(i++) : -1;
+ return i < n? s.charAt(i++): -1;
}
+
+ @Override
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;
+ return j > 0 || len == 0? j: -1;
}
}
@@ -343,49 +440,67 @@ public class Globals extends LuaTable {
*/
abstract static class AbstractBufferedStream extends InputStream {
protected byte[] b;
- protected int i = 0, j = 0;
+ protected int i = 0, j = 0;
+
protected AbstractBufferedStream(int buflen) {
this.b = new byte[buflen];
}
+
abstract protected int avail() throws IOException;
+
+ @Override
public int read() throws IOException {
int a = avail();
- return (a <= 0 ? -1 : 0xff & b[i++]);
+ return a <= 0? -1: 0xff & b[i++];
}
+
+ @Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
+
+ @Override
public int read(byte[] b, int i0, int n) throws IOException {
int a = avail();
- if (a <= 0) return -1;
+ if (a <= 0)
+ return -1;
final int n_read = Math.min(a, n);
- System.arraycopy(this.b, i, b, i0, n_read);
+ System.arraycopy(this.b, i, b, i0, n_read);
i += n_read;
return n_read;
}
+
+ @Override
public long skip(long n) throws IOException {
- final long k = Math.min(n, j - i);
+ final long k = Math.min(n, j-i);
i += k;
return k;
- }
+ }
+
+ @Override
public int available() throws IOException {
- return j - i;
+ return j-i;
}
}
- /** Simple converter from Reader to InputStream using UTF8 encoding that will work
- * on both JME and JSE.
- * This class may be moved to its own package in the future.
+ /**
+ * Simple converter from Reader to InputStream using UTF8 encoding that will
+ * work on both JME and JSE. This class may be moved to its own package in
+ * the future.
*/
static class UTF8Stream extends AbstractBufferedStream {
private final char[] c = new char[32];
private final Reader r;
+
UTF8Stream(Reader r) {
super(96);
this.r = r;
}
+
+ @Override
protected int avail() throws IOException {
- if (i < j) return j - i;
+ if (i < j)
+ return j-i;
int n = r.read(c);
if (n < 0)
return -1;
@@ -399,31 +514,40 @@ public class Globals extends LuaTable {
j = LuaString.encodeToUtf8(c, n, b, i = 0);
return j;
}
+
+ @Override
public void close() throws IOException {
r.close();
}
}
-
- /** Simple buffered 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,
- * as well as speed up normal compilation and reading of lua scripts.
- * This class may be moved to its own package in the future.
+
+ /**
+ * Simple buffered 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, as well as speed up normal
+ * compilation and reading of lua scripts. This class may be moved to its
+ * own package in the future.
*/
static class BufferedStream extends AbstractBufferedStream {
private final InputStream s;
+
public BufferedStream(InputStream s) {
this(128, s);
}
+
BufferedStream(int buflen, InputStream s) {
super(buflen);
this.s = s;
}
+
+ @Override
protected int avail() throws IOException {
- if (i < j) return j - i;
- if (j >= b.length) i = j = 0;
+ if (i < j)
+ return j-i;
+ if (j >= b.length)
+ i = j = 0;
// leave previous bytes in place to implement mark()/reset().
- int n = s.read(b, j, b.length - j);
+ int n = s.read(b, j, b.length-j);
if (n < 0)
return -1;
if (n == 0) {
@@ -436,21 +560,29 @@ public class Globals extends LuaTable {
j += n;
return n;
}
+
+ @Override
public void close() throws IOException {
s.close();
}
+
+ @Override
public synchronized void mark(int n) {
if (i > 0 || n > b.length) {
- byte[] dest = n > b.length ? new byte[n] : b;
- System.arraycopy(b, i, dest, 0, j - i);
+ byte[] dest = n > b.length? new byte[n]: b;
+ System.arraycopy(b, i, dest, 0, j-i);
j -= i;
i = 0;
b = dest;
}
}
+
+ @Override
public boolean markSupported() {
return true;
}
+
+ @Override
public synchronized void reset() throws IOException {
i = 0;
}
diff --git a/src/core/org/luaj/vm2/LoadState.java b/luaj-core/src/main/java/org/luaj/vm2/LoadState.java
similarity index 51%
rename from src/core/org/luaj/vm2/LoadState.java
rename to luaj-core/src/main/java/org/luaj/vm2/LoadState.java
index 8d71a74a..3dd25cff 100644
--- a/src/core/org/luaj/vm2/LoadState.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LoadState.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,116 +25,141 @@ import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
-
/**
-* Class to undump compiled lua bytecode into a {@link Prototype} instances.
-*
-* The {@link LoadState} class provides the default {@link Globals.Undumper}
-* which is used to undump a string of bytes that represent a lua binary file
-* using either the C-based lua compiler, or luaj's
-* {@link org.luaj.vm2.compiler.LuaC} compiler.
-*
-* The canonical method to load and execute code is done
-* indirectly using the Globals:
-*
-* This should work regardless of which {@link Globals.Compiler} or {@link Globals.Undumper}
-* have been installed.
-*
-* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
-* {@link org.luaj.vm2.lib.jme.JmePlatform}
-* to construct globals, the {@link LoadState} default undumper is installed
-* as the default {@link Globals.Undumper}.
-*
-*
-* A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState} class
-:
-*
{@code
-* Globals globals = JsePlatform.standardGlobals();
-* Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
-* ByteArrayOutputStream o = new ByteArrayOutputStream();
-* org.luaj.vm2.compiler.DumpState.dump(p, o, false);
-* byte[] lua_binary_file_bytes = o.toByteArray();
-* }
-*
-* The {@link LoadState}'s default undumper {@link #instance}
-* may be used directly to undump these bytes:
-*
{@code
+ * Class to undump compiled lua bytecode into a {@link Prototype} instances.
+ *
+ * The {@link LoadState} class provides the default {@link Globals.Undumper}
+ * which is used to undump a string of bytes that represent a lua binary file
+ * using either the C-based lua compiler, or luaj's
+ * {@link org.luaj.vm2.compiler.LuaC} compiler.
+ *
+ * The canonical method to load and execute code is done indirectly using the
+ * Globals:
+ *
+ *
+ *
+ * This should work regardless of which {@link Globals.Compiler} or
+ * {@link Globals.Undumper} have been installed.
+ *
+ * By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform} to construct globals, the
+ * {@link LoadState} default undumper is installed as the default
+ * {@link Globals.Undumper}.
+ *
+ *
+ * A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState}
+ * class :
+ *
+ *
+ *
+ * @see Globals.Compiler
+ * @see Globals.Undumper
+ * @see LuaClosure
+ * @see LuaFunction
+ * @see org.luaj.vm2.compiler.LuaC
+ * @see org.luaj.vm2.luajc.LuaJC
+ * @see Globals#compiler
+ * @see Globals#load(InputStream, String, LuaValue)
+ */
public class LoadState {
- /** Shared instance of Globals.Undumper to use loading prototypes from binary lua files */
+ /**
+ * Shared instance of Globals.Undumper to use loading prototypes from binary
+ * lua files
+ */
public static final Globals.Undumper instance = new GlobalsUndumper();
-
- /** format corresponding to non-number-patched lua, all numbers are floats or doubles */
- public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
+
+ /**
+ * format corresponding to non-number-patched lua, all numbers are floats or
+ * doubles
+ */
+ public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
/** format corresponding to non-number-patched lua, all numbers are ints */
- public static final int NUMBER_FORMAT_INTS_ONLY = 1;
-
- /** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
- public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
-
+ public static final int NUMBER_FORMAT_INTS_ONLY = 1;
+
+ /**
+ * format corresponding to number-patched lua, all numbers are 32-bit (4
+ * byte) ints
+ */
+ public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
+
// type constants
- public static final int LUA_TINT = (-2);
- public static final int LUA_TNONE = (-1);
- public static final int LUA_TNIL = 0;
- public static final int LUA_TBOOLEAN = 1;
- public static final int LUA_TLIGHTUSERDATA = 2;
- public static final int LUA_TNUMBER = 3;
- public static final int LUA_TSTRING = 4;
- public static final int LUA_TTABLE = 5;
- public static final int LUA_TFUNCTION = 6;
- public static final int LUA_TUSERDATA = 7;
- public static final int LUA_TTHREAD = 8;
- public static final int LUA_TVALUE = 9;
-
- /** The character encoding to use for file encoding. Null means the default encoding */
+ public static final int LUA_TINT = -2;
+ public static final int LUA_TNONE = -1;
+ public static final int LUA_TNIL = 0;
+ public static final int LUA_TBOOLEAN = 1;
+ public static final int LUA_TLIGHTUSERDATA = 2;
+ public static final int LUA_TNUMBER = 3;
+ public static final int LUA_TSTRING = 4;
+ public static final int LUA_TTABLE = 5;
+ public static final int LUA_TFUNCTION = 6;
+ public static final int LUA_TUSERDATA = 7;
+ public static final int LUA_TTHREAD = 8;
+ public static final int LUA_TVALUE = 9;
+
+ /**
+ * 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' };
+ public static final byte[] LUA_SIGNATURE = { '\033', 'L', 'u', 'a' };
/** Data to catch conversion errors */
public static final byte[] LUAC_TAIL = { (byte) 0x19, (byte) 0x93, '\r', '\n', (byte) 0x1a, '\n', };
-
/** Name for compiled chunks */
public static final String SOURCE_BINARY_STRING = "binary string";
-
/** for header of binary files -- this is Lua 5.2 */
- public static final int LUAC_VERSION = 0x52;
+ public static final int LUAC_VERSION = 0x52;
/** for header of binary files -- this is the official format */
- public static final int LUAC_FORMAT = 0;
+ public static final int LUAC_FORMAT = 0;
/** size of header of binary files */
- public static final int LUAC_HEADERSIZE = 12;
+ public static final int LUAC_HEADERSIZE = 12;
// values read from the header
private int luacVersion;
@@ -144,7 +169,7 @@ public class LoadState {
private int luacSizeofSizeT;
private int luacSizeofInstruction;
private int luacSizeofLuaNumber;
- private int luacNumberFormat;
+ private int luacNumberFormat;
/** input stream from which we are loading */
public final DataInputStream is;
@@ -152,135 +177,148 @@ public class LoadState {
/** Name of what is being loaded? */
String name;
- private static final LuaValue[] NOVALUES = {};
- private static final Prototype[] NOPROTOS = {};
- private static final LocVars[] NOLOCVARS = {};
- private static final Upvaldesc[] NOUPVALDESCS = {};
- private static final int[] NOINTS = {};
-
+ private static final LuaValue[] NOVALUES = {};
+ private static final Prototype[] NOPROTOS = {};
+ private static final LocVars[] NOLOCVARS = {};
+ private static final Upvaldesc[] NOUPVALDESCS = {};
+ private static final int[] NOINTS = {};
+
/** Read buffer */
private byte[] buf = new byte[512];
- /** Install this class as the standard Globals.Undumper for the supplied Globals */
+ /**
+ * 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
+
+ /**
+ * Load a 4-byte int value from the input stream
+ *
* @return the int value laoded.
**/
int loadInt() throws IOException {
- is.readFully(buf,0,4);
- return luacLittleEndian?
- (buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]):
- (buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]);
+ is.readFully(buf, 0, 4);
+ return luacLittleEndian? buf[3]<<24 | (0xff & buf[2])<<16 | (0xff & buf[1])<<8 | 0xff & buf[0]
+ : buf[0]<<24 | (0xff & buf[1])<<16 | (0xff & buf[2])<<8 | 0xff & buf[3];
}
-
- /** Load an array of int values from the input stream
+
+ /**
+ * Load an array of int values from the input stream
+ *
* @return the array of int values laoded.
**/
int[] loadIntArray() throws IOException {
int n = loadInt();
- if ( n == 0 )
+ if (n == 0)
return NOINTS;
-
+
// read all data at once
- int m = n << 2;
- if ( buf.length < m )
+ int m = n<<2;
+ if (buf.length < m)
buf = new byte[m];
- is.readFully(buf,0,m);
+ is.readFully(buf, 0, m);
int[] array = new int[n];
- for ( int i=0, j=0; i> 52) & 0x7ffL) - 1023;
-
- if ( e >= 0 && e < 31 ) {
+
+ int e = (int) (bits>>52 & 0x7ffL)-1023;
+
+ if (e >= 0 && e < 31) {
long f = bits & 0xFFFFFFFFFFFFFL;
- int shift = 52 - e;
- long intPrecMask = ( 1L << shift ) - 1;
- if ( ( f & intPrecMask ) == 0 ) {
- int intValue = (int)( f >> shift ) | ( 1 << e );
- return LuaInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue );
+ int shift = 52-e;
+ long intPrecMask = (1L<>shift) | 1<>63 != 0? -intValue: intValue);
}
}
-
- return LuaValue.valueOf( Double.longBitsToDouble(bits) );
+
+ return LuaValue.valueOf(Double.longBitsToDouble(bits));
}
-
+
/**
* Load a number from a binary chunk
+ *
* @return the {@link LuaValue} loaded
* @throws IOException if an i/o exception occurs
*/
LuaValue loadNumber() throws IOException {
- if ( luacNumberFormat == NUMBER_FORMAT_INTS_ONLY ) {
- return LuaInteger.valueOf( loadInt() );
+ if (luacNumberFormat == NUMBER_FORMAT_INTS_ONLY) {
+ return LuaInteger.valueOf(loadInt());
} else {
- return longBitsToLuaNumber( loadInt64() );
+ return longBitsToLuaNumber(loadInt64());
}
}
/**
* Load a list of constants from a binary chunk
+ *
* @param f the function prototype
* @throws IOException if an i/o exception occurs
*/
void loadConstants(Prototype f) throws IOException {
int n = loadInt();
- LuaValue[] values = n>0? new LuaValue[n]: NOVALUES;
- for ( int i=0; i 0? new LuaValue[n]: NOVALUES;
+ for (int i = 0; i < n; i++) {
+ switch (is.readByte()) {
case LUA_TNIL:
values[i] = LuaValue.NIL;
break;
case LUA_TBOOLEAN:
- values[i] = (0 != is.readUnsignedByte()? LuaValue.TRUE: LuaValue.FALSE);
+ values[i] = 0 != is.readUnsignedByte()? LuaValue.TRUE: LuaValue.FALSE;
break;
case LUA_TINT:
- values[i] = LuaInteger.valueOf( loadInt() );
+ values[i] = LuaInteger.valueOf(loadInt());
break;
case LUA_TNUMBER:
values[i] = loadNumber();
@@ -293,49 +331,50 @@ public class LoadState {
}
}
f.k = values;
-
+
n = loadInt();
- Prototype[] protos = n>0? new Prototype[n]: NOPROTOS;
- for ( int i=0; i 0? new Prototype[n]: NOPROTOS;
+ for (int i = 0; i < n; i++)
protos[i] = loadFunction(f.source);
f.p = protos;
}
-
void loadUpvalues(Prototype f) throws IOException {
int n = loadInt();
- f.upvalues = n>0? new Upvaldesc[n]: NOUPVALDESCS;
- for (int i=0; i 0? new Upvaldesc[n]: NOUPVALDESCS;
+ for (int i = 0; i < n; i++) {
boolean instack = is.readByte() != 0;
- int idx = ((int) is.readByte()) & 0xff;
+ int idx = is.readByte() & 0xff;
f.upvalues[i] = new Upvaldesc(null, instack, idx);
}
}
/**
* Load the debug info for a function prototype
+ *
* @param f the function Prototype
* @throws IOException if there is an i/o exception
*/
- void loadDebug( Prototype f ) throws IOException {
+ void loadDebug(Prototype f) throws IOException {
f.source = loadString();
f.lineinfo = loadIntArray();
int n = loadInt();
- f.locvars = n>0? new LocVars[n]: NOLOCVARS;
- for ( int i=0; i 0? new LocVars[n]: NOLOCVARS;
+ for (int i = 0; i < n; i++) {
LuaString varname = loadString();
int startpc = loadInt();
int endpc = loadInt();
f.locvars[i] = new LocVars(varname, startpc, endpc);
}
-
+
n = loadInt();
- for ( int i=0; i
- * This is a direct translation of C lua distribution header file constants
- * for bytecode creation and processing.
+ * This is a direct translation of C lua distribution header file constants for
+ * bytecode creation and processing.
*/
public class Lua {
/** version is supplied by ant build task */
public static final String _VERSION = "Luaj 0.0";
-
+
/** use return values from previous op */
public static final int LUA_MULTRET = -1;
@@ -46,7 +45,7 @@ public class Lua {
`C' : 9 bits
`Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx
-
+
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
@@ -54,46 +53,44 @@ public class Lua {
unsigned argument.
===========================================================================*/
-
/* basic instruction format */
- public static final int iABC = 0;
- public static final int iABx = 1;
- public static final int iAsBx = 2;
- public static final int iAx = 3;
-
+ public static final int iABC = 0;
+ public static final int iABx = 1;
+ public static final int iAsBx = 2;
+ public static final int iAx = 3;
/*
** size and position of opcode arguments.
*/
- public static final int SIZE_C = 9;
- public static final int SIZE_B = 9;
- public static final int SIZE_Bx = (SIZE_C + SIZE_B);
- public static final int SIZE_A = 8;
- public static final int SIZE_Ax = (SIZE_C + SIZE_B + SIZE_A);
+ public static final int SIZE_C = 9;
+ public static final int SIZE_B = 9;
+ public static final int SIZE_Bx = SIZE_C+SIZE_B;
+ public static final int SIZE_A = 8;
+ public static final int SIZE_Ax = SIZE_C+SIZE_B+SIZE_A;
- public static final int SIZE_OP = 6;
+ public static final int SIZE_OP = 6;
- public static final int POS_OP = 0;
- public static final int POS_A = (POS_OP + SIZE_OP);
- public static final int POS_C = (POS_A + SIZE_A);
- public static final int POS_B = (POS_C + SIZE_C);
- public static final int POS_Bx = POS_C;
- public static final int POS_Ax = POS_A;
+ public static final int POS_OP = 0;
+ public static final int POS_A = POS_OP+SIZE_OP;
+ public static final int POS_C = POS_A+SIZE_A;
+ public static final int POS_B = POS_C+SIZE_C;
+ public static final int POS_Bx = POS_C;
+ public static final int POS_Ax = POS_A;
- public static final int MAX_OP = ((1<>1); /* `sBx' is signed */
- public static final int MAXARG_Ax = ((1<>1; /* `sBx' is signed */
+ public static final int MAXARG_Ax = (1<> POS_OP) & MAX_OP;
+ return i>>POS_OP & MAX_OP;
}
public static int GETARG_A(int i) {
- return (i >> POS_A) & MAXARG_A;
+ return i>>POS_A & MAXARG_A;
}
public static int GETARG_Ax(int i) {
- return (i >> POS_Ax) & MAXARG_Ax;
+ return i>>POS_Ax & MAXARG_Ax;
}
public static int GETARG_B(int i) {
- return (i >> POS_B) & MAXARG_B;
+ return i>>POS_B & MAXARG_B;
}
public static int GETARG_C(int i) {
- return (i >> POS_C) & MAXARG_C;
+ return i>>POS_C & MAXARG_C;
}
public static int GETARG_Bx(int i) {
- return (i >> POS_Bx) & MAXARG_Bx;
+ return i>>POS_Bx & MAXARG_Bx;
}
public static int GETARG_sBx(int i) {
- return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx;
+ return (i>>POS_Bx & MAXARG_Bx)-MAXARG_sBx;
}
-
/*
** Macros to operate RK indices
*/
/** this bit 1 means constant (0 means register) */
- public static final int BITRK = (1 << (SIZE_B - 1));
+ public static final int BITRK = 1<= R(A - 1) */
- public static final int OP_EQ = 24; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
- public static final int OP_LT = 25; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
- public static final int OP_LE = 26; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
+ public static final int OP_EQ = 24; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
+ public static final int OP_LT = 25; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
+ public static final int OP_LE = 26; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
- public static final int OP_TEST = 27; /* A C if not (R(A) <=> C) then pc++ */
+ public static final int OP_TEST = 27; /* A C if not (R(A) <=> C) then pc++ */
public static final int OP_TESTSET = 28; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
- public static final int OP_CALL = 29; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+ public static final int OP_CALL = 29; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_TAILCALL = 30; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
- public static final int OP_RETURN = 31; /* A B return R(A), ... ,R(A+B-2) (see note) */
+ public static final int OP_RETURN = 31; /* A B return R(A), ... ,R(A+B-2) (see note) */
public static final int OP_FORLOOP = 32; /* A sBx R(A)+=R(A+2);
- if R(A) = R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+ if R(A) = R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
public static final int OP_FORPREP = 33; /* A sBx R(A)-=R(A+2); pc+=sBx */
public static final int OP_TFORCALL = 34; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
public static final int OP_TFORLOOP = 35; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
- public static final int OP_SETLIST = 36; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
+ public static final int OP_SETLIST = 36; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
public static final int OP_CLOSURE = 37; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
@@ -234,7 +227,7 @@ public class Lua {
public static final int OP_EXTRAARG = 39; /* Ax extra (larger) argument for previous opcode */
- public static final int NUM_OPCODES = OP_EXTRAARG + 1;
+ public static final int NUM_OPCODES = OP_EXTRAARG+1;
/* pseudo-opcodes used in parsing only. */
public static final int OP_GT = 63; // >
@@ -242,28 +235,27 @@ public class Lua {
public static final int OP_NEQ = 61; // ~=
public static final int OP_AND = 60; // and
public static final int OP_OR = 59; // or
-
+
/*===========================================================================
Notes:
(*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
and can be 0: OP_CALL then sets `top' to last_result+1, so
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
-
+
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
-
+
(*) In OP_RETURN, if (B == 0) then return up to `top'
-
+
(*) In OP_SETLIST, if (B == 0) then B = `top';
if (C == 0) then next `instruction' is real C
-
+
(*) For comparisons, A specifies what condition the test should accept
(true or false).
-
+
(*) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/
-
/*
** masks for instruction properties. The format is:
** bits 0-1: op mode
@@ -273,69 +265,73 @@ public class Lua {
** bit 7: operator is a test
*/
- public static final int OpArgN = 0; /* argument is not used */
- public static final int OpArgU = 1; /* argument is used */
- public static final int OpArgR = 2; /* argument is a register or a jump offset */
- public static final int OpArgK = 3; /* argument is a constant or register/constant */
+ public static final int OpArgN = 0; /* argument is not used */
+ public static final int OpArgU = 1; /* argument is used */
+ public static final int OpArgR = 2; /* argument is a register or a jump offset */
+ public static final int OpArgK = 3; /* argument is a constant or register/constant */
- public static final int[] luaP_opmodes = {
- /* T A B C mode opcode */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_MOVE */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_LOADK */
- (0<<7) | (1<<6) | (OpArgN<<4) | (OpArgN<<2) | (iABx), /* OP_LOADKX */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_LOADBOOL */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_LOADNIL */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_GETUPVAL */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABUP */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABLE */
- (0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABUP */
- (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_SETUPVAL */
- (0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABLE */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_NEWTABLE */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_SELF */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_ADD */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */
- (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */
- (0<<7) | (0<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_JMP */
- (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_EQ */
- (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LT */
- (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LE */
- (1<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TEST */
- (1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TESTSET */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_CALL */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_TAILCALL */
- (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_RETURN */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORLOOP */
- (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORPREP */
- (0<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TFORCALL */
- (1<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_TFORLOOP */
- (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_SETLIST */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABx), /* OP_CLOSURE */
- (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_VARARG */
- (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iAx), /* OP_EXTRAARG */
- };
+ public static final int[] luaP_opmodes = {
+ /* T A B C mode opcode */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iABC, /* OP_MOVE */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgN<<2 | iABx, /* OP_LOADK */
+ 0<<7 | 1<<6 | OpArgN<<4 | OpArgN<<2 | iABx, /* OP_LOADKX */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgU<<2 | iABC, /* OP_LOADBOOL */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgN<<2 | iABC, /* OP_LOADNIL */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgN<<2 | iABC, /* OP_GETUPVAL */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgK<<2 | iABC, /* OP_GETTABUP */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgK<<2 | iABC, /* OP_GETTABLE */
+ 0<<7 | 0<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_SETTABUP */
+ 0<<7 | 0<<6 | OpArgU<<4 | OpArgN<<2 | iABC, /* OP_SETUPVAL */
+ 0<<7 | 0<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_SETTABLE */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgU<<2 | iABC, /* OP_NEWTABLE */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgK<<2 | iABC, /* OP_SELF */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_ADD */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_SUB */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_MUL */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_DIV */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_MOD */
+ 0<<7 | 1<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_POW */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iABC, /* OP_UNM */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iABC, /* OP_NOT */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iABC, /* OP_LEN */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgR<<2 | iABC, /* OP_CONCAT */
+ 0<<7 | 0<<6 | OpArgR<<4 | OpArgN<<2 | iAsBx, /* OP_JMP */
+ 1<<7 | 0<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_EQ */
+ 1<<7 | 0<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_LT */
+ 1<<7 | 0<<6 | OpArgK<<4 | OpArgK<<2 | iABC, /* OP_LE */
+ 1<<7 | 0<<6 | OpArgN<<4 | OpArgU<<2 | iABC, /* OP_TEST */
+ 1<<7 | 1<<6 | OpArgR<<4 | OpArgU<<2 | iABC, /* OP_TESTSET */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgU<<2 | iABC, /* OP_CALL */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgU<<2 | iABC, /* OP_TAILCALL */
+ 0<<7 | 0<<6 | OpArgU<<4 | OpArgN<<2 | iABC, /* OP_RETURN */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iAsBx, /* OP_FORLOOP */
+ 0<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iAsBx, /* OP_FORPREP */
+ 0<<7 | 0<<6 | OpArgN<<4 | OpArgU<<2 | iABC, /* OP_TFORCALL */
+ 1<<7 | 1<<6 | OpArgR<<4 | OpArgN<<2 | iAsBx, /* OP_TFORLOOP */
+ 0<<7 | 0<<6 | OpArgU<<4 | OpArgU<<2 | iABC, /* OP_SETLIST */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgN<<2 | iABx, /* OP_CLOSURE */
+ 0<<7 | 1<<6 | OpArgU<<4 | OpArgN<<2 | iABC, /* OP_VARARG */
+ 0<<7 | 0<<6 | OpArgU<<4 | OpArgU<<2 | iAx, /* OP_EXTRAARG */
+ };
public static int getOpMode(int m) {
return luaP_opmodes[m] & 3;
}
+
public static int getBMode(int m) {
- return (luaP_opmodes[m] >> 4) & 3;
+ return luaP_opmodes[m]>>4 & 3;
}
+
public static int getCMode(int m) {
- return (luaP_opmodes[m] >> 2) & 3;
+ return luaP_opmodes[m]>>2 & 3;
}
+
public static boolean testAMode(int m) {
- return 0 != (luaP_opmodes[m] & (1 << 6));
+ return 0 != (luaP_opmodes[m] & 1<<6);
}
+
public static boolean testTMode(int m) {
- return 0 != (luaP_opmodes[m] & (1 << 7));
+ return 0 != (luaP_opmodes[m] & 1<<7);
}
/* number of list items to accumulate before a SETLIST instruction */
@@ -343,19 +339,19 @@ public class Lua {
private static final int MAXSRC = 80;
- public static String chunkid( String source ) {
- if ( source.startsWith("=") )
- return source.substring(1);
- String end = "";
- if ( source.startsWith("@") ) {
- source = source.substring(1);
- } else {
- source = "[string \""+source;
- end = "\"]";
- }
- int n = source.length() + end.length();
- if ( n > MAXSRC )
- source = source.substring(0,MAXSRC-end.length()-3) + "...";
- return source + end;
+ public static String chunkid(String source) {
+ if (source.startsWith("="))
+ return source.substring(1);
+ String end = "";
+ if (source.startsWith("@")) {
+ source = source.substring(1);
+ } else {
+ source = "[string \"" + source;
+ end = "\"]";
+ }
+ int n = source.length()+end.length();
+ if (n > MAXSRC)
+ source = source.substring(0, MAXSRC-end.length()-3) + "...";
+ return source+end;
}
}
diff --git a/src/core/org/luaj/vm2/LuaBoolean.java b/luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java
similarity index 78%
rename from src/core/org/luaj/vm2/LuaBoolean.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java
index 33103415..fe50a61f 100644
--- a/src/core/org/luaj/vm2/LuaBoolean.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,18 +22,18 @@
package org.luaj.vm2;
/**
- * Extension of {@link LuaValue} which can hold a Java boolean as its value.
+ * Extension of {@link LuaValue} which can hold a Java boolean as its value.
*
- * These instance are not instantiated directly by clients.
- * Instead, there are exactly twon instances of this class,
- * {@link LuaValue#TRUE} and {@link LuaValue#FALSE}
- * representing the lua values {@code true} and {@code false}.
- * The function {@link LuaValue#valueOf(boolean)} will always
- * return one of these two values.
+ * These instance are not instantiated directly by clients. Instead, there are
+ * exactly twon instances of this class, {@link LuaValue#TRUE} and
+ * {@link LuaValue#FALSE} representing the lua values {@code true} and
+ * {@code false}. The function {@link LuaValue#valueOf(boolean)} will always
+ * return one of these two values.
*
- * Any {@link LuaValue} can be converted to its equivalent
- * boolean representation using {@link LuaValue#toboolean()}
+ * Any {@link LuaValue} can be converted to its equivalent boolean
+ * representation using {@link LuaValue#toboolean()}
*
+ *
* @see LuaValue
* @see LuaValue#valueOf(boolean)
* @see LuaValue#TRUE
@@ -43,10 +43,10 @@ public final class LuaBoolean extends LuaValue {
/** The singleton instance representing lua {@code true} */
static final LuaBoolean _TRUE = new LuaBoolean(true);
-
+
/** The singleton instance representing lua {@code false} */
static final LuaBoolean _FALSE = new LuaBoolean(false);
-
+
/** Shared static metatable for boolean values represented in lua. */
public static LuaValue s_metatable;
@@ -57,47 +57,57 @@ public final class LuaBoolean extends LuaValue {
this.v = b;
}
+ @Override
public int type() {
return LuaValue.TBOOLEAN;
}
+ @Override
public String typename() {
return "boolean";
}
+ @Override
public boolean isboolean() {
return true;
}
+ @Override
public LuaValue not() {
- return v ? FALSE : LuaValue.TRUE;
+ return v? FALSE: LuaValue.TRUE;
}
/**
* Return the boolean value for this boolean
+ *
* @return value as a Java boolean
*/
public boolean booleanValue() {
return v;
}
+ @Override
public boolean toboolean() {
return v;
}
+ @Override
public String tojstring() {
- return v ? "true" : "false";
+ return v? "true": "false";
}
+ @Override
public boolean optboolean(boolean defval) {
return this.v;
}
-
+
+ @Override
public boolean checkboolean() {
return v;
}
-
- public LuaValue getmetatable() {
- return s_metatable;
+
+ @Override
+ public LuaValue getmetatable() {
+ return s_metatable;
}
}
diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java
similarity index 52%
rename from src/core/org/luaj/vm2/LuaClosure.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java
index 46a3556f..7ceb0dd8 100644
--- a/src/core/org/luaj/vm2/LuaClosure.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,44 +26,56 @@ import org.luaj.vm2.lib.DebugLib.CallFrame;
/**
* Extension of {@link LuaFunction} which executes lua bytecode.
*
- * A {@link LuaClosure} is a combination of a {@link Prototype}
- * and a {@link LuaValue} to use as an environment for execution.
- * Normally the {@link LuaValue} is a {@link Globals} in which case the environment
- * will contain standard lua libraries.
- *
+ * A {@link LuaClosure} is a combination of a {@link Prototype} and a
+ * {@link LuaValue} to use as an environment for execution. Normally the
+ * {@link LuaValue} is a {@link Globals} in which case the environment will
+ * contain standard lua libraries.
+ *
*
* There are three main ways {@link LuaClosure} instances are created:
*
*
Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}
- *
Construct it indirectly by loading a chunk via {@link Globals#load(java.io.Reader, String)}
- *
Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing
+ *
Construct it indirectly by loading a chunk via
+ * {@link Globals#load(java.io.Reader, String)}
+ *
Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode
+ * processing
*
*
- * To construct it directly, the {@link Prototype} is typically created via a compiler such as
- * {@link org.luaj.vm2.compiler.LuaC}:
- *
{@code
- * String script = "print( 'hello, world' )";
- * InputStream is = new ByteArrayInputStream(script.getBytes());
- * Prototype p = LuaC.instance.compile(is, "script");
- * LuaValue globals = JsePlatform.standardGlobals();
- * LuaClosure f = new LuaClosure(p, globals);
- * f.call();
- * }
+ * To construct it directly, the {@link Prototype} is typically created via a
+ * compiler such as {@link org.luaj.vm2.compiler.LuaC}:
+ *
+ *
- * To construct it indirectly, the {@link Globals#load(java.io.Reader, String)} method may be used:
- *
{@code
- * Globals globals = JsePlatform.standardGlobals();
- * LuaFunction f = globals.load(new StringReader(script), "script");
- * LuaClosure c = f.checkclosure(); // This may fail if LuaJC is installed.
- * c.call();
- * }
+ * To construct it indirectly, the {@link Globals#load(java.io.Reader, String)}
+ * method may be used:
+ *
+ *
+ * {
+ * @code
+ * Globals globals = JsePlatform.standardGlobals();
+ * LuaFunction f = globals.load(new StringReader(script), "script");
+ * LuaClosure c = f.checkclosure(); // This may fail if LuaJC is installed.
+ * c.call();
+ * }
+ *
*
* In this example, the "checkclosure()" may fail if direct lua-to-java-bytecode
- * compiling using LuaJC is installed, because no LuaClosure is created in that case
- * and the value returned is a {@link LuaFunction} but not a {@link LuaClosure}.
+ * compiling using LuaJC is installed, because no LuaClosure is created in that
+ * case and the value returned is a {@link LuaFunction} but not a
+ * {@link LuaClosure}.
*
- * Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue},
- * all the value operations can be used directly such as:
+ * Since a {@link LuaClosure} is a {@link LuaFunction} which is a
+ * {@link LuaValue}, all the value operations can be used directly such as:
*
+ *
* @see LuaValue
* @see LuaFunction
* @see LuaValue#isclosure()
@@ -84,17 +97,20 @@ import org.luaj.vm2.lib.DebugLib.CallFrame;
* @see Globals#compiler
*/
public class LuaClosure extends LuaFunction {
- private static final UpValue[] NOUPVALUES = new UpValue[0];
-
+ private static final UpValue[] NOUPVALUES = {};
+
public final Prototype p;
public UpValue[] upValues;
-
+
final Globals globals;
-
- /** Create a closure around a Prototype with a specific environment.
- * If the prototype has upvalues, the environment will be written into the first upvalue.
- * @param p the Prototype to construct this Closure for.
+
+ /**
+ * Create a closure around a Prototype with a specific environment. If the
+ * prototype has upvalues, the environment will be written into the first
+ * upvalue.
+ *
+ * @param p the Prototype to construct this Closure for.
* @param env the environment to associate with the closure.
*/
public LuaClosure(Prototype p, LuaValue env) {
@@ -102,401 +118,467 @@ public class LuaClosure extends LuaFunction {
this.initupvalue1(env);
globals = env instanceof Globals? (Globals) env: null;
}
-
+
+ @Override
public void initupvalue1(LuaValue env) {
if (p.upvalues == null || p.upvalues.length == 0)
this.upValues = NOUPVALUES;
else {
this.upValues = new UpValue[p.upvalues.length];
- this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
+ this.upValues[0] = new UpValue(new LuaValue[] { env }, 0);
}
}
-
+ @Override
public boolean isclosure() {
return true;
}
-
+
+ @Override
public LuaClosure optclosure(LuaClosure defval) {
return this;
}
+ @Override
public LuaClosure checkclosure() {
return this;
}
-
+
+ @Override
public String tojstring() {
return "function: " + p.toString();
}
-
+
private LuaValue[] getNewStack() {
int max = p.maxstacksize;
LuaValue[] stack = new LuaValue[max];
System.arraycopy(NILS, 0, stack, 0, max);
return stack;
}
-
+
+ @Override
public final LuaValue call() {
LuaValue[] stack = getNewStack();
- return execute(stack,NONE).arg1();
+ return execute(stack, NONE).arg1();
}
+ @Override
public final LuaValue call(LuaValue arg) {
LuaValue[] stack = getNewStack();
- switch ( p.numparams ) {
- default: stack[0]=arg; return execute(stack,NONE).arg1();
- case 0: return execute(stack,arg).arg1();
+ switch (p.numparams) {
+ default:
+ stack[0] = arg;
+ return execute(stack, NONE).arg1();
+ case 0:
+ return execute(stack, arg).arg1();
}
}
-
+
+ @Override
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
LuaValue[] stack = getNewStack();
- switch ( p.numparams ) {
- default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1();
- case 1: stack[0]=arg1; return execute(stack,arg2).arg1();
- case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1();
+ switch (p.numparams) {
+ default:
+ stack[0] = arg1;
+ stack[1] = arg2;
+ return execute(stack, NONE).arg1();
+ case 1:
+ stack[0] = arg1;
+ return execute(stack, arg2).arg1();
+ case 0:
+ return execute(stack, p.is_vararg != 0? varargsOf(arg1, arg2): NONE).arg1();
}
}
+ @Override
public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
LuaValue[] stack = getNewStack();
- switch ( p.numparams ) {
- default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1();
- case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1();
- case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1();
- case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1();
+ switch (p.numparams) {
+ default:
+ stack[0] = arg1;
+ stack[1] = arg2;
+ stack[2] = arg3;
+ return execute(stack, NONE).arg1();
+ case 2:
+ stack[0] = arg1;
+ stack[1] = arg2;
+ return execute(stack, arg3).arg1();
+ case 1:
+ stack[0] = arg1;
+ return execute(stack, p.is_vararg != 0? varargsOf(arg2, arg3): NONE).arg1();
+ case 0:
+ return execute(stack, p.is_vararg != 0? varargsOf(arg1, arg2, arg3): NONE).arg1();
}
}
+ @Override
public final Varargs invoke(Varargs varargs) {
return onInvoke(varargs).eval();
}
-
+
+ @Override
public final Varargs onInvoke(Varargs varargs) {
LuaValue[] stack = getNewStack();
- for ( int i=0; i0? new UpValue[stack.length]: null;
-
+ UpValue[] openups = p.p.length > 0? new UpValue[stack.length]: null;
+
// allow for debug hooks
if (globals != null && globals.debuglib != null)
- globals.debuglib.onCall( this, varargs, stack );
+ globals.debuglib.onCall(this, varargs, stack);
// process instructions
try {
for (; true; ++pc) {
if (globals != null && globals.debuglib != null)
- globals.debuglib.onInstruction( pc, v, top );
-
+ globals.debuglib.onInstruction(pc, v, top);
+
// pull out instruction
i = code[pc];
- a = ((i>>6) & 0xff);
-
+ a = i>>6 & 0xff;
+
// process the op code
- switch ( i & 0x3f ) {
-
+ switch (i & 0x3f) {
+
case Lua.OP_MOVE:/* A B R(A):= R(B) */
stack[a] = stack[i>>>23];
continue;
-
+
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
stack[a] = k[i>>>14];
continue;
-
+
case Lua.OP_LOADKX:/* A R(A) := Kst(extra arg) */
++pc;
i = code[pc];
if ((i & 0x3f) != Lua.OP_EXTRAARG) {
int op = i & 0x3f;
- throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got " +
- (op < Print.OPNAMES.length - 1 ? Print.OPNAMES[op] : "UNKNOWN_OP_" + op));
+ throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got "
+ + (op < Print.OPNAMES.length-1? Print.OPNAMES[op]: "UNKNOWN_OP_" + op));
}
stack[a] = k[i>>>6];
continue;
-
+
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
- stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
- if ((i&(0x1ff<<14)) != 0)
- ++pc; /* skip next instruction (if C) */
- continue;
-
+ stack[a] = i>>>23 != 0? LuaValue.TRUE: LuaValue.FALSE;
+ if ((i & 0x1ff<<14) != 0)
+ ++pc; /* skip next instruction (if C) */
+ continue;
+
case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(A+B):= nil */
- for ( b=i>>>23; b-->=0; )
+ for (b = i>>>23; b-- >= 0;)
stack[a++] = LuaValue.NIL;
continue;
-
+
case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
- stack[a] = upValues[i>>>23].getValue();
- continue;
-
+ stack[a] = upValues[i>>>23].getValue();
+ continue;
+
case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
- stack[a] = upValues[i>>>23].getValue().get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = upValues[i>>>23].getValue().get((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
- stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = stack[i>>>23].get((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
- upValues[a].getValue().set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ upValues[a].getValue().set((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b],
+ (c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
upValues[i>>>23].setValue(stack[a]);
continue;
-
+
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
- stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a].set((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b],
+ (c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
- stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff);
+ stack[a] = new LuaTable(i>>>23, i>>14 & 0x1ff);
continue;
-
+
case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
- stack[a+1] = (o = stack[i>>>23]);
- stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a+1] = o = stack[i>>>23];
+ stack[a] = o.get((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .add((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .sub((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .mul((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .div((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .mod((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .pow((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
continue;
-
+
case Lua.OP_UNM: /* A B R(A):= -R(B) */
stack[a] = stack[i>>>23].neg();
continue;
-
+
case Lua.OP_NOT: /* A B R(A):= not R(B) */
stack[a] = stack[i>>>23].not();
continue;
-
+
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
stack[a] = stack[i>>>23].len();
continue;
-
+
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
b = i>>>23;
- c = (i>>14)&0x1ff;
- {
- if ( c > b+1 ) {
- Buffer sb = stack[c].buffer();
- while ( --c>=b )
- sb.concatTo(stack[c]);
- stack[a] = sb.value();
- } else {
- stack[a] = stack[c-1].concat(stack[c]);
- }
+ c = i>>14 & 0x1ff; {
+ if (c > b+1) {
+ Buffer sb = stack[c].buffer();
+ while ( --c >= b )
+ sb.concatTo(stack[c]);
+ stack[a] = sb.value();
+ } else {
+ stack[a] = stack[c-1].concat(stack[c]);
}
+ }
continue;
-
+
case Lua.OP_JMP: /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
- pc += (i>>>14)-0x1ffff;
+ pc += (i>>>14)-0x1ffff;
if (a > 0) {
- for (--a, b = openups.length; --b>=0; )
+ for (--a, b = openups.length; --b >= 0;)
if (openups[b] != null && openups[b].index >= a) {
openups[b].close();
openups[b] = null;
}
}
continue;
-
+
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
- if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
+ if (((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .eq_b((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]) != (a != 0))
++pc;
continue;
-
+
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
- if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
+ if (((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .lt_b((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]) != (a != 0))
++pc;
continue;
-
+
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
- if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
+ if (((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
+ .lteq_b((c = i>>14 & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]) != (a != 0))
++pc;
continue;
-
+
case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
- if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
+ if (stack[a].toboolean() != ((i & 0x1ff<<14) != 0))
++pc;
continue;
-
+
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
/* note: doc appears to be reversed */
- if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) )
+ if ((o = stack[i>>>23]).toboolean() != ((i & 0x1ff<<14) != 0))
++pc;
else
stack[a] = o; // TODO: should be sBx?
continue;
-
+
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
- switch ( i & (Lua.MASK_B | Lua.MASK_C) ) {
- case (1<>>23;
- c = (i>>14)&0x1ff;
- v = stack[a].invoke(b>0?
- varargsOf(stack, a+1, b-1): // exact arg count
- varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
- if ( c > 0 ) {
+ c = i>>14 & 0x1ff;
+ v = stack[a].invoke(b > 0? varargsOf(stack, a+1, b-1): // exact arg count
+ varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
+ if (c > 0) {
v.copyto(stack, a, c-1);
v = NONE;
} else {
- top = a + v.narg();
+ top = a+v.narg();
v = v.dealias();
}
continue;
}
-
+
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
- switch ( i & Lua.MASK_B ) {
- case (1<>>23;
- v = b>0?
- varargsOf(stack,a+1,b-1): // exact arg count
+ v = b > 0? varargsOf(stack, a+1, b-1): // exact arg count
varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
- return new TailcallVarargs( stack[a], v );
+ return new TailcallVarargs(stack[a], v);
}
-
+
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
b = i>>>23;
- switch ( b ) {
- case 0: return varargsOf(stack, a, top-v.narg()-a, v);
- case 1: return NONE;
- case 2: return stack[a];
+ switch (b) {
+ case 0:
+ return varargsOf(stack, a, top-v.narg()-a, v);
+ case 1:
+ return NONE;
+ case 2:
+ return stack[a];
default:
return varargsOf(stack, a, b-1);
}
-
+
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) = R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
- {
- LuaValue limit = stack[a + 1];
- LuaValue step = stack[a + 2];
- LuaValue idx = stack[a].add(step);
- if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
- stack[a] = idx;
- stack[a + 3] = idx;
- pc += (i>>>14)-0x1ffff;
- }
- }
- continue;
-
- case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
- {
- LuaValue init = stack[a].checknumber("'for' initial value must be a number");
- LuaValue limit = stack[a + 1].checknumber("'for' limit must be a number");
- LuaValue step = stack[a + 2].checknumber("'for' step must be a number");
- stack[a] = init.sub(step);
- stack[a + 1] = limit;
- stack[a + 2] = step;
+ {
+ LuaValue limit = stack[a+1];
+ LuaValue step = stack[a+2];
+ LuaValue idx = stack[a].add(step);
+ if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
+ stack[a] = idx;
+ stack[a+3] = idx;
pc += (i>>>14)-0x1ffff;
}
+ }
+ continue;
+
+ case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
+ {
+ LuaValue init = stack[a].checknumber("'for' initial value must be a number");
+ LuaValue limit = stack[a+1].checknumber("'for' limit must be a number");
+ LuaValue step = stack[a+2].checknumber("'for' step must be a number");
+ stack[a] = init.sub(step);
+ stack[a+1] = limit;
+ stack[a+2] = step;
+ pc += (i>>>14)-0x1ffff;
+ }
continue;
case Lua.OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
- v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2]));
- c = (i>>14) & 0x1ff;
- while (--c >= 0)
+ v = stack[a].invoke(varargsOf(stack[a+1], stack[a+2]));
+ c = i>>14 & 0x1ff;
+ while ( --c >= 0 )
stack[a+3+c] = v.arg(c+1);
v = NONE;
continue;
case Lua.OP_TFORLOOP: /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx */
if (!stack[a+1].isnil()) { /* continue loop? */
- stack[a] = stack[a+1]; /* save control varible. */
+ stack[a] = stack[a+1]; /* save control varible. */
pc += (i>>>14)-0x1ffff;
}
continue;
-
+
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
- {
- if ( (c=(i>>14)&0x1ff) == 0 )
- c = code[++pc];
- int offset = (c-1) * Lua.LFIELDS_PER_FLUSH;
- o = stack[a];
- if ( (b=i>>>23) == 0 ) {
- b = top - a - 1;
- int m = b - v.narg();
- int j=1;
- for ( ;j<=m; j++ )
- o.set(offset+j, stack[a + j]);
- for ( ;j<=b; j++ )
- o.set(offset+j, v.arg(j-m));
- } else {
- o.presize( offset + b );
- for (int j=1; j<=b; j++)
- o.set(offset+j, stack[a + j]);
- }
+ {
+ if ((c = i>>14 & 0x1ff) == 0)
+ c = code[++pc];
+ int offset = (c-1)*Lua.LFIELDS_PER_FLUSH;
+ o = stack[a];
+ if ((b = i>>>23) == 0) {
+ b = top-a-1;
+ int m = b-v.narg();
+ int j = 1;
+ for (; j <= m; j++)
+ o.set(offset+j, stack[a+j]);
+ for (; j <= b; j++)
+ o.set(offset+j, v.arg(j-m));
+ } else {
+ o.presize(offset+b);
+ for (int j = 1; j <= b; j++)
+ o.set(offset+j, stack[a+j]);
}
+ }
continue;
-
+
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
- {
- Prototype newp = p.p[i>>>14];
- LuaClosure ncl = new LuaClosure(newp, globals);
- Upvaldesc[] uv = newp.upvalues;
- for ( int j=0, nup=uv.length; j>>14];
+ LuaClosure ncl = new LuaClosure(newp, globals);
+ Upvaldesc[] uv = newp.upvalues;
+ for (int j = 0, nup = uv.length; j < nup; ++j) {
+ if (uv[j].instack) /* upvalue refes to local variable? */
+ ncl.upValues[j] = findupval(stack, uv[j].idx, openups);
+ else /* get upvalue from enclosing function */
+ ncl.upValues[j] = upValues[uv[j].idx];
}
+ stack[a] = ncl;
+ }
continue;
-
+
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
b = i>>>23;
- if ( b == 0 ) {
- top = a + (b = varargs.narg());
+ if (b == 0) {
+ top = a+(b = varargs.narg());
v = varargs;
} else {
- for ( int j=1; j=0; )
- if ( openups[u] != null )
+ if (openups != null)
+ for (int u = openups.length; --u >= 0;)
+ if (openups[u] != null)
openups[u].close();
if (globals != null && globals.debuglib != null)
globals.debuglib.onReturn();
@@ -527,21 +609,21 @@ public class LuaClosure extends LuaFunction {
}
/**
- * Run the error hook if there is one
- * @param msg the message to use in error hook processing.
- * */
+ * Run the error hook if there is one
+ *
+ * @param msg the message to use in error hook processing.
+ */
String errorHook(String msg, int level) {
- if (globals == null ) return msg;
+ if (globals == null)
+ return msg;
final LuaThread r = globals.running;
if (r.errorfunc == null)
- return globals.debuglib != null?
- msg + "\n" + globals.debuglib.traceback(level):
- msg;
+ return globals.debuglib != null? msg + "\n" + globals.debuglib.traceback(level): msg;
final LuaValue e = r.errorfunc;
r.errorfunc = null;
try {
- return e.call( LuaValue.valueOf(msg) ).tojstring();
- } catch ( Throwable t ) {
+ return e.call(LuaValue.valueOf(msg)).tojstring();
+ } catch (Throwable t) {
return "error in error handling";
} finally {
r.errorfunc = e;
@@ -557,19 +639,19 @@ public class LuaClosure extends LuaFunction {
frame = globals.debuglib.getCallFrame(le.level);
if (frame != null) {
String src = frame.shortsource();
- file = src != null ? src : "?";
+ file = src != null? src: "?";
line = frame.currentline();
}
}
if (frame == null) {
file = p.source != null? p.source.tojstring(): "?";
- line = p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length ? p.lineinfo[pc] : -1;
+ line = p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? p.lineinfo[pc]: -1;
}
}
- le.fileline = file + ":" + line;
+ le.fileline = file + ": " + line;
le.traceback = errorHook(le.getMessage(), le.level);
}
-
+
private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) {
final int n = openups.length;
for (int i = 0; i < n; ++i)
@@ -585,14 +667,14 @@ public class LuaClosure extends LuaFunction {
protected LuaValue getUpvalue(int i) {
return upValues[i].getValue();
}
-
+
protected void setUpvalue(int i, LuaValue v) {
upValues[i].setValue(v);
}
+ @Override
public String name() {
- return "<"+p.shortsource()+":"+p.linedefined+">";
+ return "<" + p.shortsource() + ":" + p.linedefined + ">";
}
-
-
+
}
diff --git a/src/core/org/luaj/vm2/LuaDouble.java b/luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java
similarity index 94%
rename from src/core/org/luaj/vm2/LuaDouble.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java
index 0c5cdd66..c23e7849 100644
--- a/src/core/org/luaj/vm2/LuaDouble.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java
@@ -21,6 +21,7 @@
******************************************************************************/
package org.luaj.vm2;
+import org.luaj.vm2.compat.JavaCompat;
import org.luaj.vm2.lib.MathLib;
/**
@@ -33,9 +34,9 @@ import org.luaj.vm2.lib.MathLib;
*
* Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}.
*
- * However the constants {@link #NAN}, {@link #POSINF}, {@link #NEGINF},
- * {@link #JSTR_NAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful
- * when dealing with Nan or Infinite values.
+ * However the constants {@link #NAN}, {@link #NEGNAN}, {@link #POSINF}, {@link #NEGINF},
+ * {@link #JSTR_NAN}, {@link #JSTR_NEGNAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful
+ * when dealing with Nan or Infinite values.
*
* LuaDouble also defines functions for handling the unique math rules of lua devision and modulo in
*
@@ -55,7 +56,10 @@ public class LuaDouble extends LuaNumber {
/** Constant LuaDouble representing NaN (not a number) */
public static final LuaDouble NAN = new LuaDouble( Double.NaN );
-
+
+ /** Constant LuaDouble representing negative NaN (not a number) */
+ public static final LuaDouble NEGNAN = new LuaDouble( -Double.NaN );
+
/** Constant LuaDouble representing positive infinity */
public static final LuaDouble POSINF = new LuaDouble( Double.POSITIVE_INFINITY );
@@ -64,7 +68,10 @@ public class LuaDouble extends LuaNumber {
/** Constant String representation for NaN (not a number), "nan" */
public static final String JSTR_NAN = "nan";
-
+
+ /** Constant String representation for negative NaN (not a number), "-nan" */
+ public static final String JSTR_NEGNAN = "-nan";
+
/** Constant String representation for positive infinity, "inf" */
public static final String JSTR_POSINF = "inf";
@@ -235,18 +242,14 @@ public class LuaDouble extends LuaNumber {
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
public String tojstring() {
- /*
- if ( v == 0.0 ) { // never occurs in J2me
- long bits = Double.doubleToLongBits( v );
- return ( bits >> 63 == 0 ) ? "0" : "-0";
- }
- */
+ if ( v == 0.0 ) // never occurs on J2ME
+ return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? "-0": "0");
long l = (long) v;
if ( l == v )
return Long.toString(l);
if ( Double.isNaN(v) )
- return JSTR_NAN;
- if ( Double.isInfinite(v) )
+ return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? JSTR_NEGNAN: JSTR_NAN);
+ if ( Double.isInfinite(v) )
return (v<0? JSTR_NEGINF: JSTR_POSINF);
return Float.toString((float)v);
}
diff --git a/src/core/org/luaj/vm2/LuaError.java b/luaj-core/src/main/java/org/luaj/vm2/LuaError.java
similarity index 66%
rename from src/core/org/luaj/vm2/LuaError.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaError.java
index 37a8df8d..a4c71110 100644
--- a/src/core/org/luaj/vm2/LuaError.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaError.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,39 +21,40 @@
******************************************************************************/
package org.luaj.vm2;
-
/**
- * RuntimeException that is thrown and caught in response to a lua error.
+ * RuntimeException that is thrown and caught in response to a lua error.
*
- * {@link LuaError} is used wherever a lua call to {@code error()}
- * would be used within a script.
+ * {@link LuaError} is used wherever a lua call to {@code error()} would be used
+ * within a script.
*
* Since it is an unchecked exception inheriting from {@link RuntimeException},
- * Java method signatures do notdeclare this exception, althoug it can
- * be thrown on almost any luaj Java operation.
- * This is analagous to the fact that any lua script can throw a lua error at any time.
- *
- * The LuaError may be constructed with a message object, in which case the message
- * is the string representation of that object. getMessageObject will get the object
- * supplied at construct time, or a LuaString containing the message of an object
- * was not supplied.
+ * Java method signatures do notdeclare this exception, althoug it can be thrown
+ * on almost any luaj Java operation. This is analagous to the fact that any lua
+ * script can throw a lua error at any time.
+ *
+ * The LuaError may be constructed with a message object, in which case the
+ * message is the string representation of that object. getMessageObject will
+ * get the object supplied at construct time, or a LuaString containing the
+ * message of an object was not supplied.
*/
public class LuaError extends RuntimeException {
private static final long serialVersionUID = 1L;
-
+
protected int level;
-
+
protected String fileline;
-
+
protected String traceback;
-
+
protected Throwable cause;
private LuaValue object;
-
- /** Get the string message if it was supplied, or a string
- * representation of the message object if that was supplied.
+
+ /**
+ * Get the string message if it was supplied, or a string representation of
+ * the message object if that was supplied.
*/
+ @Override
public String getMessage() {
if (traceback != null)
return traceback;
@@ -61,70 +62,75 @@ public class LuaError extends RuntimeException {
if (m == null)
return null;
if (fileline != null)
- return fileline + " " + m;
+ return fileline + m;
return m;
}
- /** Get the LuaValue that was provided in the constructor, or
- * a LuaString containing the message if it was a string error argument.
+ /**
+ * Get the LuaValue that was provided in the constructor, or a LuaString
+ * containing the message if it was a string error argument.
+ *
* @return LuaValue which was used in the constructor, or a LuaString
- * containing the message.
+ * containing the message.
*/
public LuaValue getMessageObject() {
- if (object != null) return object;
+ if (object != null)
+ return object;
String m = getMessage();
- return m != null ? LuaValue.valueOf(m): null;
+ return m != null? LuaValue.valueOf(m): null;
}
-
- /** Construct LuaError when a program exception occurs.
- *
+
+ /**
+ * Construct LuaError when a program exception occurs.
+ *
* All errors generated from lua code should throw LuaError(String) instead.
- * @param cause the Throwable that caused the error, if known.
+ *
+ * @param cause the Throwable that caused the error, if known.
*/
public LuaError(Throwable cause) {
- super( "vm error: "+cause );
+ super("vm error: " + cause);
this.cause = cause;
this.level = 1;
}
/**
- * Construct a LuaError with a specific message.
- *
+ * Construct a LuaError with a specific message.
+ *
* @param message message to supply
*/
public LuaError(String message) {
- super( message );
+ super(message);
this.level = 1;
- }
+ }
/**
- * Construct a LuaError with a message, and level to draw line number information from.
+ * Construct a LuaError with a message, and level to draw line number
+ * information from.
+ *
* @param message message to supply
- * @param level where to supply line info from in call stack
+ * @param level where to supply line info from in call stack
*/
public LuaError(String message, int level) {
- super( message );
+ super(message);
this.level = level;
- }
+ }
/**
- * Construct a LuaError with a LuaValue as the message object,
- * and level to draw line number information from.
+ * Construct a LuaError with a LuaValue as the message object, and level to
+ * draw line number information from.
+ *
* @param message_object message string or object to supply
*/
public LuaError(LuaValue message_object) {
- super( message_object.tojstring() );
+ super(message_object.tojstring());
this.object = message_object;
this.level = 1;
- }
-
-
- /**
- * Get the cause, if any.
- */
- public Throwable getCause() {
- return cause;
}
+ /**
+ * Get the cause, if any.
+ */
+ @Override
+ public Throwable getCause() { return cause; }
}
diff --git a/src/core/org/luaj/vm2/LuaFunction.java b/luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java
similarity index 67%
rename from src/core/org/luaj/vm2/LuaFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java
index 83bee86d..38403bd7 100644
--- a/src/core/org/luaj/vm2/LuaFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,71 +21,86 @@
******************************************************************************/
package org.luaj.vm2;
-
/**
* Base class for functions implemented in Java.
*
- * Direct subclass include {@link org.luaj.vm2.lib.LibFunction}
- * which is the base class for
- * all built-in library functions coded in Java,
- * and {@link LuaClosure}, which represents a lua closure
- * whose bytecode is interpreted when the function is invoked.
+ * Direct subclass include {@link org.luaj.vm2.lib.LibFunction} which is the
+ * base class for all built-in library functions coded in Java, and
+ * {@link LuaClosure}, which represents a lua closure whose bytecode is
+ * interpreted when the function is invoked.
+ *
* @see LuaValue
* @see LuaClosure
* @see org.luaj.vm2.lib.LibFunction
*/
-abstract
-public class LuaFunction extends LuaValue {
-
+abstract public class LuaFunction extends LuaValue {
+
/** Shared static metatable for all functions and closures. */
public static LuaValue s_metatable;
+ @Override
public int type() {
return TFUNCTION;
}
-
+
+ @Override
public String typename() {
return "function";
}
-
+
+ @Override
public boolean isfunction() {
return true;
}
- public LuaFunction checkfunction() {
+ @Override
+ public LuaFunction checkfunction() {
return this;
}
-
+
+ @Override
public LuaFunction optfunction(LuaFunction defval) {
return this;
}
+ @Override
public LuaValue getmetatable() {
return s_metatable;
}
+ @Override
public String tojstring() {
return "function: " + classnamestub();
}
+ @Override
public LuaString strvalue() {
return valueOf(tojstring());
}
- /** Return the last part of the class name, to be used as a function name in tojstring and elsewhere.
- * @return String naming the last part of the class name after the last dot (.) or dollar sign ($).
- * If the first character is '_', it is skipped.
+ /**
+ * Return the last part of the class name, to be used as a function name in
+ * tojstring and elsewhere.
+ *
+ * @return String naming the last part of the class name after the last dot
+ * (.) or dollar sign ($). If the first character is '_', it is
+ * skipped.
*/
public String classnamestub() {
String s = getClass().getName();
- int offset = Math.max(s.lastIndexOf('.'), s.lastIndexOf('$')) + 1;
- if (s.charAt(offset) == '_') offset++;
+ int offset = Math.max(s.lastIndexOf('.'), s.lastIndexOf('$'))+1;
+ if (s.charAt(offset) == '_')
+ offset++;
return s.substring(offset);
}
-
- /** Return a human-readable name for this function. Returns the last part of the class name by default.
- * Is overridden by LuaClosure to return the source file and line, and by LibFunctions to return the name.
- * @return common name for this function. */
+
+ /**
+ * Return a human-readable name for this function. Returns the last part of
+ * the class name by default. Is overridden by LuaClosure to return the
+ * source file and line, and by LibFunctions to return the name.
+ *
+ * @return common name for this function.
+ */
public String name() {
return classnamestub();
}
diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaInteger.java b/luaj-core/src/main/java/org/luaj/vm2/LuaInteger.java
new file mode 100644
index 00000000..ac41cb9b
--- /dev/null
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaInteger.java
@@ -0,0 +1,372 @@
+/*******************************************************************************
+* Copyright (c) 2009 Luaj.org. 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.vm2;
+
+import org.luaj.vm2.lib.MathLib;
+
+/**
+ * Extension of {@link LuaNumber} which can hold a Java int as its value.
+ *
+ * These instance are not instantiated directly by clients, but indirectly via
+ * the static functions {@link LuaValue#valueOf(int)} or
+ * {@link LuaValue#valueOf(double)} functions. This ensures that policies
+ * regarding pooling of instances are encapsulated.
+ *
+ * There are no API's specific to LuaInteger that are useful beyond what is
+ * already exposed in {@link LuaValue}.
+ *
+ * @see LuaValue
+ * @see LuaNumber
+ * @see LuaDouble
+ * @see LuaValue#valueOf(int)
+ * @see LuaValue#valueOf(double)
+ */
+public class LuaInteger extends LuaNumber {
+
+ private static final LuaInteger[] intValues = new LuaInteger[512];
+ static {
+ for (int i = 0; i < 512; i++)
+ intValues[i] = new LuaInteger(i-256);
+ }
+
+ public static LuaInteger valueOf(int i) {
+ return i <= 255 && i >= -256? intValues[i+256]: new LuaInteger(i);
+ }
+
+ // TODO consider moving this to LuaValue
+ /**
+ * Return a LuaNumber that represents the value provided
+ *
+ * @param l long value to represent.
+ * @return LuaNumber that is eithe LuaInteger or LuaDouble representing l
+ * @see LuaValue#valueOf(int)
+ * @see LuaValue#valueOf(double)
+ */
+ public static LuaNumber valueOf(long l) {
+ int i = (int) l;
+ return l == i? i <= 255 && i >= -256? intValues[i+256]: (LuaNumber) new LuaInteger(i)
+ : (LuaNumber) LuaDouble.valueOf(l);
+ }
+
+ /** The value being held by this instance. */
+ public final int v;
+
+ /**
+ * Package protected constructor.
+ *
+ * @see LuaValue#valueOf(int)
+ **/
+ LuaInteger(int i) {
+ this.v = i;
+ }
+
+ @Override
+ public boolean isint() { return true; }
+
+ @Override
+ public boolean isinttype() { return true; }
+
+ @Override
+ public boolean islong() { return true; }
+
+ @Override
+ public byte tobyte() { return (byte) v; }
+
+ @Override
+ public char tochar() { return (char) v; }
+
+ @Override
+ public double todouble() { return v; }
+
+ @Override
+ public float tofloat() { return v; }
+
+ @Override
+ public int toint() { return v; }
+
+ @Override
+ public long tolong() { return v; }
+
+ @Override
+ public short toshort() { return (short) v; }
+
+ @Override
+ public double optdouble(double defval) { return v; }
+
+ @Override
+ public int optint(int defval) { return v; }
+
+ @Override
+ public LuaInteger optinteger(LuaInteger defval) { return this; }
+
+ @Override
+ public long optlong(long defval) { return v; }
+
+ @Override
+ public String tojstring() {
+ return Integer.toString(v);
+ }
+
+ @Override
+ public LuaString strvalue() {
+ return LuaString.valueOf(Integer.toString(v));
+ }
+
+ @Override
+ public LuaString optstring(LuaString defval) {
+ return LuaString.valueOf(Integer.toString(v));
+ }
+
+ @Override
+ public LuaValue tostring() {
+ return LuaString.valueOf(Integer.toString(v));
+ }
+
+ @Override
+ public String optjstring(String defval) {
+ return Integer.toString(v);
+ }
+
+ @Override
+ public LuaInteger checkinteger() {
+ return this;
+ }
+
+ @Override
+ public boolean isstring() {
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return v;
+ }
+
+ public static int hashCode(int x) {
+ return x;
+ }
+
+ // unary operators
+ @Override
+ public LuaValue neg() { return valueOf(-(long) v); }
+
+ // object equality, used for key comparison
+ @Override
+ public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger) o).v == v: false; }
+
+ // equality w/ metatable processing
+ @Override
+ public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; }
+
+ @Override
+ public boolean eq_b(LuaValue val) { return val.raweq(v); }
+
+ // equality w/o metatable processing
+ @Override
+ public boolean raweq(LuaValue val) { return val.raweq(v); }
+
+ @Override
+ public boolean raweq(double val) { return v == val; }
+
+ @Override
+ public boolean raweq(int val) { return v == val; }
+
+ // arithmetic operators
+ @Override
+ public LuaValue add(LuaValue rhs) { return rhs.add(v); }
+
+ @Override
+ public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); }
+
+ @Override
+ public LuaValue add(int lhs) { return LuaInteger.valueOf(lhs+(long) v); }
+
+ @Override
+ public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); }
+
+ @Override
+ public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); }
+
+ @Override
+ public LuaValue sub(int rhs) { return LuaValue.valueOf(v-rhs); }
+
+ @Override
+ public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); }
+
+ @Override
+ public LuaValue subFrom(int lhs) { return LuaInteger.valueOf(lhs-(long) v); }
+
+ @Override
+ public LuaValue mul(LuaValue rhs) { return rhs.mul(v); }
+
+ @Override
+ public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); }
+
+ @Override
+ public LuaValue mul(int lhs) { return LuaInteger.valueOf(lhs*(long) v); }
+
+ @Override
+ public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); }
+
+ @Override
+ public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); }
+
+ @Override
+ public LuaValue pow(int rhs) { return MathLib.dpow(v, rhs); }
+
+ @Override
+ public LuaValue powWith(double lhs) { return MathLib.dpow(lhs, v); }
+
+ @Override
+ public LuaValue powWith(int lhs) { return MathLib.dpow(lhs, v); }
+
+ @Override
+ public LuaValue div(LuaValue rhs) { return rhs.divInto(v); }
+
+ @Override
+ public LuaValue div(double rhs) { return LuaDouble.ddiv(v, rhs); }
+
+ @Override
+ public LuaValue div(int rhs) { return LuaDouble.ddiv(v, rhs); }
+
+ @Override
+ public LuaValue divInto(double lhs) { return LuaDouble.ddiv(lhs, v); }
+
+ @Override
+ public LuaValue mod(LuaValue rhs) { return rhs.modFrom(v); }
+
+ @Override
+ public LuaValue mod(double rhs) { return LuaDouble.dmod(v, rhs); }
+
+ @Override
+ public LuaValue mod(int rhs) { return LuaDouble.dmod(v, rhs); }
+
+ @Override
+ public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); }
+
+ // relational operators
+ @Override
+ public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v)? TRUE: FALSE: super.lt(rhs); }
+
+ @Override
+ public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; }
+
+ @Override
+ public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; }
+
+ @Override
+ public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); }
+
+ @Override
+ public boolean lt_b(int rhs) { return v < rhs; }
+
+ @Override
+ public boolean lt_b(double rhs) { return v < rhs; }
+
+ @Override
+ public LuaValue lteq(LuaValue rhs) {
+ return rhs instanceof LuaNumber? rhs.gteq_b(v)? TRUE: FALSE: super.lteq(rhs);
+ }
+
+ @Override
+ public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; }
+
+ @Override
+ public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; }
+
+ @Override
+ public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); }
+
+ @Override
+ public boolean lteq_b(int rhs) { return v <= rhs; }
+
+ @Override
+ public boolean lteq_b(double rhs) { return v <= rhs; }
+
+ @Override
+ public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v)? TRUE: FALSE: super.gt(rhs); }
+
+ @Override
+ public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; }
+
+ @Override
+ public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; }
+
+ @Override
+ public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); }
+
+ @Override
+ public boolean gt_b(int rhs) { return v > rhs; }
+
+ @Override
+ public boolean gt_b(double rhs) { return v > rhs; }
+
+ @Override
+ public LuaValue gteq(LuaValue rhs) {
+ return rhs instanceof LuaNumber? rhs.lteq_b(v)? TRUE: FALSE: super.gteq(rhs);
+ }
+
+ @Override
+ public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; }
+
+ @Override
+ public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; }
+
+ @Override
+ public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); }
+
+ @Override
+ public boolean gteq_b(int rhs) { return v >= rhs; }
+
+ @Override
+ public boolean gteq_b(double rhs) { return v >= rhs; }
+
+ // string comparison
+ @Override
+ public int strcmp(LuaString rhs) { typerror("attempt to compare number with string"); return 0; }
+
+ @Override
+ public int checkint() {
+ return v;
+ }
+
+ @Override
+ public long checklong() {
+ return v;
+ }
+
+ @Override
+ public double checkdouble() {
+ return v;
+ }
+
+ @Override
+ public String checkjstring() {
+ return String.valueOf(v);
+ }
+
+ @Override
+ public LuaString checkstring() {
+ return valueOf(String.valueOf(v));
+ }
+
+}
diff --git a/src/core/org/luaj/vm2/LuaNil.java b/luaj-core/src/main/java/org/luaj/vm2/LuaNil.java
similarity index 53%
rename from src/core/org/luaj/vm2/LuaNil.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaNil.java
index 1b247cbd..ace94717 100644
--- a/src/core/org/luaj/vm2/LuaNil.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaNil.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,87 +22,127 @@
package org.luaj.vm2;
/**
- * Class to encapsulate behavior of the singleton instance {@code nil}
+ * Class to encapsulate behavior of the singleton instance {@code nil}
*
- * There will be one instance of this class, {@link LuaValue#NIL},
- * per Java virtual machine.
- * However, the {@link Varargs} instance {@link LuaValue#NONE}
- * which is the empty list,
- * is also considered treated as a nil value by default.
+ * There will be one instance of this class, {@link LuaValue#NIL}, per Java
+ * virtual machine. However, the {@link Varargs} instance {@link LuaValue#NONE}
+ * which is the empty list, is also considered treated as a nil value by
+ * default.
*
- * Although it is possible to test for nil using Java == operator,
- * the recommended approach is to use the method {@link LuaValue#isnil()}
- * instead. By using that any ambiguities between
- * {@link LuaValue#NIL} and {@link LuaValue#NONE} are avoided.
+ * Although it is possible to test for nil using Java == operator, the
+ * recommended approach is to use the method {@link LuaValue#isnil()} instead.
+ * By using that any ambiguities between {@link LuaValue#NIL} and
+ * {@link LuaValue#NONE} are avoided.
+ *
* @see LuaValue
* @see LuaValue#NIL
*/
public class LuaNil extends LuaValue {
-
+
static final LuaNil _NIL = new LuaNil();
-
+
public static LuaValue s_metatable;
-
+
LuaNil() {}
+ @Override
public int type() {
return LuaValue.TNIL;
}
+ @Override
public String toString() {
- return "nil";
+ return "nil";
}
-
+
+ @Override
public String typename() {
return "nil";
}
-
+
+ @Override
public String tojstring() {
return "nil";
}
- public LuaValue not() {
- return LuaValue.TRUE;
+ @Override
+ public LuaValue not() {
+ return LuaValue.TRUE;
}
-
- public boolean toboolean() {
- return false;
+
+ @Override
+ public boolean toboolean() {
+ return false;
}
-
+
+ @Override
public boolean isnil() {
return true;
}
-
- public LuaValue getmetatable() {
- return s_metatable;
+
+ @Override
+ public LuaValue getmetatable() {
+ return s_metatable;
}
-
+
+ @Override
public boolean equals(Object o) {
return o instanceof LuaNil;
}
- public LuaValue checknotnil() {
+ @Override
+ public LuaValue checknotnil() {
return argerror("value");
}
-
+
+ @Override
public boolean isvalidkey() {
return false;
}
// optional argument conversions - nil alwas falls badk to default value
- public boolean optboolean(boolean defval) { return defval; }
- public LuaClosure optclosure(LuaClosure defval) { return defval; }
- public double optdouble(double defval) { return defval; }
- public LuaFunction optfunction(LuaFunction defval) { return defval; }
- public int optint(int defval) { return defval; }
- public LuaInteger optinteger(LuaInteger defval) { return defval; }
- public long optlong(long defval) { return defval; }
- public LuaNumber optnumber(LuaNumber defval) { return defval; }
- public LuaTable opttable(LuaTable defval) { return defval; }
- public LuaThread optthread(LuaThread defval) { return defval; }
- public String optjstring(String defval) { return defval; }
- public LuaString optstring(LuaString defval) { return defval; }
- public Object optuserdata(Object defval) { return defval; }
- public Object optuserdata(Class c, Object defval) { return defval; }
- public LuaValue optvalue(LuaValue defval) { return defval; }
+ @Override
+ public boolean optboolean(boolean defval) { return defval; }
+
+ @Override
+ public LuaClosure optclosure(LuaClosure defval) { return defval; }
+
+ @Override
+ public double optdouble(double defval) { return defval; }
+
+ @Override
+ public LuaFunction optfunction(LuaFunction defval) { return defval; }
+
+ @Override
+ public int optint(int defval) { return defval; }
+
+ @Override
+ public LuaInteger optinteger(LuaInteger defval) { return defval; }
+
+ @Override
+ public long optlong(long defval) { return defval; }
+
+ @Override
+ public LuaNumber optnumber(LuaNumber defval) { return defval; }
+
+ @Override
+ public LuaTable opttable(LuaTable defval) { return defval; }
+
+ @Override
+ public LuaThread optthread(LuaThread defval) { return defval; }
+
+ @Override
+ public String optjstring(String defval) { return defval; }
+
+ @Override
+ public LuaString optstring(LuaString defval) { return defval; }
+
+ @Override
+ public Object optuserdata(Object defval) { return defval; }
+
+ @Override
+ public Object optuserdata(Class c, Object defval) { return defval; }
+
+ @Override
+ public LuaValue optvalue(LuaValue defval) { return defval; }
}
diff --git a/src/core/org/luaj/vm2/LuaNumber.java b/luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java
similarity index 71%
rename from src/core/org/luaj/vm2/LuaNumber.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java
index ef972218..b1dd89f2 100644
--- a/src/core/org/luaj/vm2/LuaNumber.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,61 +21,77 @@
******************************************************************************/
package org.luaj.vm2;
-/**
- * Base class for representing numbers as lua values directly.
+/**
+ * Base class for representing numbers as lua values directly.
*
- * The main subclasses are {@link LuaInteger} which holds values that fit in a java int,
- * and {@link LuaDouble} which holds all other number values.
+ * The main subclasses are {@link LuaInteger} which holds values that fit in a
+ * java int, and {@link LuaDouble} which holds all other number values.
+ *
* @see LuaInteger
* @see LuaDouble
* @see LuaValue
- *
+ *
*/
-abstract
-public class LuaNumber extends LuaValue {
+abstract public class LuaNumber extends LuaValue {
/** Shared static metatable for all number values represented in lua. */
public static LuaValue s_metatable;
-
+
+ @Override
public int type() {
return TNUMBER;
}
-
+
+ @Override
public String typename() {
return "number";
}
-
+
+ @Override
public LuaNumber checknumber() {
- return this;
+ return this;
}
-
+
+ @Override
public LuaNumber checknumber(String errmsg) {
- return this;
+ return this;
}
-
+
+ @Override
public LuaNumber optnumber(LuaNumber defval) {
- return this;
+ return this;
}
-
+
+ @Override
public LuaValue tonumber() {
return this;
}
-
+
+ @Override
public boolean isnumber() {
return true;
}
-
+
+ @Override
public boolean isstring() {
return true;
}
-
- public LuaValue getmetatable() {
- return s_metatable;
+
+ @Override
+ public LuaValue getmetatable() {
+ return s_metatable;
}
- public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
- public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
- public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); }
- public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); }
+ @Override
+ public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
+
+ @Override
+ public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
+
+ @Override
+ public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); }
+
+ @Override
+ public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); }
}
diff --git a/src/core/org/luaj/vm2/LuaString.java b/luaj-core/src/main/java/org/luaj/vm2/LuaString.java
similarity index 88%
rename from src/core/org/luaj/vm2/LuaString.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaString.java
index 08c1022b..6c64d559 100644
--- a/src/core/org/luaj/vm2/LuaString.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaString.java
@@ -639,9 +639,15 @@ public class LuaString extends LuaValue {
public static String decodeAsUtf8(byte[] bytes, int offset, int length) {
int i,j,n,b;
for ( i=offset,j=offset+length,n=0; i=0; )
- if ( (c=chars[i]) >=0x80 )
- b += (c>=0x800)? 2: 1;
+ for (i = 0, b = 0; i < chars.length; i++) {
+ if ((c = chars[i]) < 0x80 || (c >= 0xdc00 && c < 0xe000)) {
+ b += 1;
+ } else if (c < 0x800) {
+ b += 2;
+ } else if (c >= 0xd800 && c < 0xdc00) {
+ if (i + 1 < chars.length && chars[i+1] >= 0xdc00 && chars[i+1] < 0xe000) {
+ b += 4;
+ i++;
+ } else {
+ b += 1;
+ }
+ } else {
+ b += 3;
+ }
+ }
return b;
}
@@ -689,16 +708,28 @@ public class LuaString extends LuaValue {
public static int encodeToUtf8(char[] chars, int nchars, byte[] bytes, int off) {
char c;
int j = off;
- for ( int i=0; i>6) & 0x1f));
- bytes[j++] = (byte) (0x80 | ( c & 0x3f));
+ } else if (c < 0x800) {
+ bytes[j++] = (byte) (0xC0 | ((c >> 6)));
+ bytes[j++] = (byte) (0x80 | (c & 0x3f));
+ } else if (c >= 0xd800 && c < 0xdc00) {
+ if (i + 1 < nchars && chars[i+1] >= 0xdc00 && chars[i+1] < 0xe000) {
+ int uc = 0x10000 + (((c & 0x3ff) << 10) | (chars[++i] & 0x3ff));
+ bytes[j++] = (byte) (0xF0 | ((uc >> 18)));
+ bytes[j++] = (byte) (0x80 | ((uc >> 12) & 0x3f));
+ bytes[j++] = (byte) (0x80 | ((uc >> 6) & 0x3f));
+ bytes[j++] = (byte) (0x80 | (uc & 0x3f));
+ } else {
+ bytes[j++] = (byte) '?';
+ }
+ } else if (c >= 0xdc00 && c < 0xe000) {
+ bytes[j++] = (byte) '?';
} else {
- bytes[j++] = (byte) (0xE0 | ((c>>12) & 0x0f));
- bytes[j++] = (byte) (0x80 | ((c>>6) & 0x3f));
- bytes[j++] = (byte) (0x80 | ( c & 0x3f));
+ bytes[j++] = (byte) (0xE0 | ((c >> 12)));
+ bytes[j++] = (byte) (0x80 | ((c >> 6) & 0x3f));
+ bytes[j++] = (byte) (0x80 | (c & 0x3f));
}
}
return j - off;
@@ -711,16 +742,16 @@ public class LuaString extends LuaValue {
* @see #decodeAsUtf8(byte[], int, int)
*/
public boolean isValidUtf8() {
- for (int i=m_offset,j=m_offset+m_length; i= 0 ) continue;
- if ( ((c & 0xE0) == 0xC0)
- && i= 0)
+ continue;
+ if (((c & 0xE0) == 0xC0) && i < j && (m_bytes[i++] & 0xC0) == 0x80)
+ continue;
+ if (((c & 0xF0) == 0xE0) && i + 1 < j && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80)
+ continue;
+ if (((c & 0xF8) == 0xF0) && i + 2 < j && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80)
+ continue;
return false;
}
return true;
@@ -749,22 +780,87 @@ public class LuaString extends LuaValue {
double d = scannumber( base );
return Double.isNaN(d)? NIL: valueOf(d);
}
-
- /**
- * Convert to a number in base 10, or base 16 if the string starts with '0x',
+
+ private boolean isspace(byte c) {
+ return c == ' ' || (c >= '\t' && c <= '\r');
+ }
+
+ private boolean isdigit(byte c) {
+ return (c >= '0' && c <= '9');
+ }
+
+ private boolean isxdigit(byte c) {
+ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+ }
+
+ private int hexvalue(byte c) {
+ return c <= '9' ? c - '0' : c <= 'F' ? c + 10 - 'A' : c + 10 - 'a';
+ }
+
+ /**
+ * Convert to a number in base 10, or base 16 if the string starts with '0x',
* or return Double.NaN if it cannot be converted to a number.
* @return double value if conversion is valid, or Double.NaN if not
*/
public double scannumber() {
- int i=m_offset,j=m_offset+m_length;
- while ( i=j )
+ int i = m_offset, j = m_offset + m_length;
+ while (i < j && isspace(m_bytes[i]))
+ ++i;
+ while (i < j && isspace(m_bytes[j - 1]))
+ --j;
+ if (i >= j)
return Double.NaN;
- if ( m_bytes[i]=='0' && i+1= end)
+ return Double.NaN;
+ if (m_bytes[start++] != '0')
+ return Double.NaN;
+ if (m_bytes[start] != 'x' && m_bytes[start] != 'X')
+ return Double.NaN;
+ ++start;
+ double m = 0;
+ int e = 0;
+ boolean i = isxdigit(m_bytes[start]);
+ while (start < end && isxdigit(m_bytes[start]))
+ m = (m * 16) + hexvalue(m_bytes[start++]);
+ if (start < end && m_bytes[start] == '.') {
+ ++start;
+ while (start < end && isxdigit(m_bytes[start])) {
+ m = (m * 16) + hexvalue(m_bytes[start++]);
+ e -= 4;
+ }
+ }
+ if (!i && e == 0)
+ return Double.NaN;
+ if (start < end && (m_bytes[start] == 'p' || m_bytes[start] == 'P')) {
+ ++start;
+ int exp1 = 0;
+ boolean neg1 = false;
+ if (start < end) {
+ if (m_bytes[start] == '-')
+ neg1 = true;
+ if (neg1 || m_bytes[start] == '+')
+ ++start;
+ }
+ if (start >= end || !isdigit(m_bytes[start]))
+ return Double.NaN;
+ while (start < end && isdigit(m_bytes[start]))
+ exp1 = exp1 * 10 + m_bytes[start++] - '0';
+ if (neg1)
+ exp1 = -exp1;
+ e += exp1;
+ }
+ if (start != end)
+ return Double.NaN;
+ return sgn * m * MathLib.dpow_d(2.0, e);
}
/**
@@ -776,8 +872,8 @@ public class LuaString extends LuaValue {
if ( base < 2 || base > 36 )
return Double.NaN;
int i=m_offset,j=m_offset+m_length;
- while ( i=j )
return Double.NaN;
return scanlong( base, i, j );
@@ -794,7 +890,8 @@ public class LuaString extends LuaValue {
private double scanlong( int base, int start, int end ) {
long x = 0;
boolean neg = (m_bytes[start] == '-');
- for ( int i=(neg?start+1:start); i='0'&&m_bytes[i]<='9')? '0':
m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10));
if ( digit < 0 || digit >= base )
diff --git a/src/core/org/luaj/vm2/LuaTable.java b/luaj-core/src/main/java/org/luaj/vm2/LuaTable.java
similarity index 58%
rename from src/core/org/luaj/vm2/LuaTable.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaTable.java
index a35dcc3f..6f689024 100644
--- a/src/core/org/luaj/vm2/LuaTable.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaTable.java
@@ -10,7 +10,7 @@
*
* 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
@@ -27,25 +27,27 @@ import java.util.Vector;
/**
* Subclass of {@link LuaValue} for representing lua tables.
*
- * Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}.
+ * Almost all API's implemented in {@link LuaTable} are defined and documented
+ * in {@link LuaValue}.
*
- * If a table is needed, the one of the type-checking functions can be used such as
- * {@link #istable()},
- * {@link #checktable()}, or
- * {@link #opttable(LuaTable)}
+ * If a table is needed, the one of the type-checking functions can be used such
+ * as {@link #istable()}, {@link #checktable()}, or {@link #opttable(LuaTable)}
*
- * The main table operations are defined on {@link LuaValue}
- * for getting and setting values with and without metatag processing:
+ * The main table operations are defined on {@link LuaValue} for getting and
+ * setting values with and without metatag processing:
*
*
{@link #get(LuaValue)}
*
{@link #set(LuaValue,LuaValue)}
*
{@link #rawget(LuaValue)}
*
{@link #rawset(LuaValue,LuaValue)}
- *
plus overloads such as {@link #get(String)}, {@link #get(int)}, and so on
+ *
plus overloads such as {@link #get(String)}, {@link #get(int)}, and so
+ * on
*
*
* To iterate over key-value pairs from Java, use
- *
{@code
+ *
+ *
+ * {@code
* LuaValue k = LuaValue.NIL;
* while ( true ) {
* Varargs n = table.next(k);
@@ -53,11 +55,12 @@ import java.util.Vector;
* break;
* LuaValue v = n.arg(2)
* process( k, v )
- * }}
- *
+ * }}
+ *
+ *
*
- * As with other types, {@link LuaTable} instances should be constructed via one of the table constructor
- * methods on {@link LuaValue}:
+ * As with other types, {@link LuaTable} instances should be constructed via one
+ * of the table constructor methods on {@link LuaValue}:
*
*
{@link LuaValue#tableOf()} empty table
*
{@link LuaValue#tableOf(int, int)} table with capacity
@@ -65,37 +68,41 @@ import java.util.Vector;
*
{@link LuaValue#listOf(LuaValue[], Varargs)} initialize array part
*
{@link LuaValue#tableOf(LuaValue[])} initialize named hash part
*
{@link LuaValue#tableOf(Varargs, int)} initialize named hash part
- *
{@link LuaValue#tableOf(LuaValue[], LuaValue[])} initialize array and named parts
- *
{@link LuaValue#tableOf(LuaValue[], LuaValue[], Varargs)} initialize array and named parts
+ *
{@link LuaValue#tableOf(LuaValue[], LuaValue[])} initialize array and
+ * named parts
+ *
{@link LuaValue#tableOf(LuaValue[], LuaValue[], Varargs)} initialize
+ * array and named parts
*
+ *
* @see LuaValue
*/
public class LuaTable extends LuaValue implements Metatable {
- private static final int MIN_HASH_CAPACITY = 2;
- private static final LuaString N = valueOf("n");
-
+ private static final int MIN_HASH_CAPACITY = 2;
+ private static final LuaString N = valueOf("n");
+
/** the array values */
protected LuaValue[] array;
-
+
/** the hash part */
protected Slot[] hash;
-
+
/** the number of hash entries */
protected int hashEntries;
-
+
/** metatable for this table, or null */
protected Metatable m_metatable;
-
+
/** Construct empty table */
public LuaTable() {
array = NOVALS;
hash = NOBUCKETS;
}
-
+
/**
* Construct table with preset capacity.
+ *
* @param narray capacity of array part
- * @param nhash capacity of hash part
+ * @param nhash capacity of hash part
*/
public LuaTable(int narray, int nhash) {
presize(narray, nhash);
@@ -103,155 +110,171 @@ public class LuaTable extends LuaValue implements Metatable {
/**
* Construct table with named and unnamed parts.
- * @param named Named elements in order {@code key-a, value-a, key-b, value-b, ... }
+ *
+ * @param named Named elements in order
+ * {@code key-a, value-a, key-b, value-b, ... }
* @param unnamed Unnamed elements in order {@code value-1, value-2, ... }
* @param lastarg Additional unnamed values beyond {@code unnamed.length}
*/
public LuaTable(LuaValue[] named, LuaValue[] unnamed, Varargs lastarg) {
- int nn = (named!=null? named.length: 0);
- int nu = (unnamed!=null? unnamed.length: 0);
- int nl = (lastarg!=null? lastarg.narg(): 0);
+ int nn = named != null? named.length: 0;
+ int nu = unnamed != null? unnamed.length: 0;
+ int nl = lastarg != null? lastarg.narg(): 0;
presize(nu+nl, nn>>1);
- for ( int i=0; i array.length )
- array = resize( array, 1 << log2(narray) );
+
+ @Override
+ public void presize(int narray) {
+ if (narray > array.length)
+ array = resize(array, 1< 0 && nhash < MIN_HASH_CAPACITY )
+ if (nhash > 0 && nhash < MIN_HASH_CAPACITY)
nhash = MIN_HASH_CAPACITY;
// Size of both parts must be a power of two.
- array = (narray>0? new LuaValue[1 << log2(narray)]: NOVALS);
- hash = (nhash>0? new Slot[1 << log2(nhash)]: NOBUCKETS);
+ array = narray > 0? new LuaValue[1< 0? new Slot[1<0 && key<=array.length ) {
- LuaValue v = m_metatable == null ? array[key-1] : m_metatable.arrayget(array, key-1);
- return v != null ? v : NIL;
+ @Override
+ public LuaValue get(LuaValue key) {
+ LuaValue v = rawget(key);
+ return v.isnil() && m_metatable != null? gettable(this, key): v;
+ }
+
+ @Override
+ public LuaValue rawget(int key) {
+ if (key > 0 && key <= array.length) {
+ LuaValue v = m_metatable == null? array[key-1]: m_metatable.arrayget(array, key-1);
+ return v != null? v: NIL;
}
- return hashget( LuaInteger.valueOf(key) );
+ return hashget(LuaInteger.valueOf(key));
}
- public LuaValue rawget( LuaValue key ) {
- if ( key.isinttype() ) {
+ @Override
+ public LuaValue rawget(LuaValue key) {
+ if (key.isinttype()) {
int ikey = key.toint();
- if ( ikey>0 && ikey<=array.length ) {
- LuaValue v = m_metatable == null
- ? array[ikey-1] : m_metatable.arrayget(array, ikey-1);
- return v != null ? v : NIL;
+ if (ikey > 0 && ikey <= array.length) {
+ LuaValue v = m_metatable == null? array[ikey-1]: m_metatable.arrayget(array, ikey-1);
+ return v != null? v: NIL;
}
}
- return hashget( key );
+ return hashget(key);
}
protected LuaValue hashget(LuaValue key) {
- if ( hashEntries > 0 ) {
- for ( Slot slot = hash[ hashSlot(key) ]; slot != null; slot = slot.rest() ) {
+ if (hashEntries > 0) {
+ for (Slot slot = hash[hashSlot(key)]; slot != null; slot = slot.rest()) {
StrongSlot foundSlot;
- if ( ( foundSlot = slot.find(key) ) != null ) {
+ if ((foundSlot = slot.find(key)) != null) {
return foundSlot.value();
}
}
@@ -259,119 +282,129 @@ public class LuaTable extends LuaValue implements Metatable {
return NIL;
}
- public void set( int key, LuaValue value ) {
- if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,LuaInteger.valueOf(key),value) )
+ @Override
+ public void set(int key, LuaValue value) {
+ if (m_metatable == null || !rawget(key).isnil() || !settable(this, LuaInteger.valueOf(key), value))
rawset(key, value);
}
/** caller must ensure key is not nil */
- public void set( LuaValue key, LuaValue value ) {
+ @Override
+ public void set(LuaValue key, LuaValue value) {
if (key == null || !key.isvalidkey() && !metatag(NEWINDEX).isfunction())
throw new LuaError("value ('" + key + "') can not be used as a table index");
- if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,key,value) )
+ if (m_metatable == null || !rawget(key).isnil() || !settable(this, key, value))
rawset(key, value);
}
- public void rawset( int key, LuaValue value ) {
- if ( ! arrayset(key, value) )
- hashset( LuaInteger.valueOf(key), value );
+ @Override
+ public void rawset(int key, LuaValue value) {
+ if (!arrayset(key, value))
+ hashset(LuaInteger.valueOf(key), value);
}
/** caller must ensure key is not nil */
- public void rawset( LuaValue key, LuaValue value ) {
- if ( !key.isinttype() || !arrayset(key.toint(), value) )
- hashset( key, value );
+ @Override
+ public void rawset(LuaValue key, LuaValue value) {
+ if (!key.isinttype() || !arrayset(key.toint(), value))
+ hashset(key, value);
}
/** Set an array element */
- private boolean arrayset( int key, LuaValue value ) {
- if ( key>0 && key<=array.length ) {
- array[key - 1] = value.isnil() ? null :
- (m_metatable != null ? m_metatable.wrap(value) : value);
+ private boolean arrayset(int key, LuaValue value) {
+ if (key > 0 && key <= array.length) {
+ array[key-1] = value.isnil()? null: m_metatable != null? m_metatable.wrap(value): value;
return true;
}
return false;
}
- /** Remove the element at a position in a list-table
- *
+ /**
+ * Remove the element at a position in a list-table
+ *
* @param pos the position to remove
* @return The removed item, or {@link #NONE} if not removed
*/
public LuaValue remove(int pos) {
int n = length();
- if ( pos == 0 )
+ if (pos == 0)
pos = n;
else if (pos > n)
return NONE;
LuaValue v = get(pos);
- for ( LuaValue r=v; !r.isnil(); ) {
+ for (LuaValue r = v; !r.isnil();) {
r = get(pos+1);
set(pos++, r);
}
return v.isnil()? NONE: v;
}
- /** Insert an element at a position in a list-table
- *
- * @param pos the position to remove
+ /**
+ * Insert an element at a position in a list-table
+ *
+ * @param pos the position to remove
* @param value The value to insert
*/
public void insert(int pos, LuaValue value) {
- if ( pos == 0 )
+ if (pos == 0)
pos = length()+1;
- while ( ! value.isnil() ) {
- LuaValue v = get( pos );
+ while ( !value.isnil() ) {
+ LuaValue v = get(pos);
set(pos++, value);
value = v;
}
}
- /** Concatenate the contents of a table efficiently, using {@link Buffer}
- *
+ /**
+ * Concatenate the contents of a table efficiently, using {@link Buffer}
+ *
* @param sep {@link LuaString} separater to apply between elements
- * @param i the first element index
- * @param j the last element index, inclusive
+ * @param i the first element index
+ * @param j the last element index, inclusive
* @return {@link LuaString} value of the concatenation
*/
public LuaValue concat(LuaString sep, int i, int j) {
- Buffer sb = new Buffer ();
- if ( i<=j ) {
- sb.append( get(i).checkstring() );
- while ( ++i<=j ) {
- sb.append( sep );
- sb.append( get(i).checkstring() );
+ Buffer sb = new Buffer();
+ if (i <= j) {
+ sb.append(get(i).checkstring());
+ while ( ++i <= j ) {
+ sb.append(sep);
+ sb.append(get(i).checkstring());
}
}
return sb.tostring();
}
+ @Override
public int length() {
if (m_metatable != null) {
LuaValue len = len();
- if (!len.isint()) throw new LuaError("table length is not an integer: " + len);
+ if (!len.isint())
+ throw new LuaError("table length is not an integer: " + len);
return len.toint();
}
return rawlen();
}
-
- public LuaValue len() {
+
+ @Override
+ public LuaValue len() {
final LuaValue h = metatag(LEN);
if (h.toboolean())
return h.call(this);
return LuaInteger.valueOf(rawlen());
}
+ @Override
public int rawlen() {
int a = getArrayLength();
- int n = a+1,m=0;
+ int n = a+1, m = 0;
while ( !rawget(n).isnil() ) {
m = n;
n += a+getHashLength()+1;
}
while ( n > m+1 ) {
- int k = (n+m) / 2;
- if ( !rawget(k).isnil() )
+ int k = (n+m)/2;
+ if (!rawget(k).isnil())
m = k;
else
n = k;
@@ -381,159 +414,164 @@ public class LuaTable extends LuaValue implements Metatable {
/**
* Get the next element after a particular key in the table
+ *
* @return key,value or nil
*/
- public Varargs next( LuaValue key ) {
+ @Override
+ public Varargs next(LuaValue key) {
int i = 0;
do {
// find current key index
- if ( ! key.isnil() ) {
- if ( key.isinttype() ) {
+ if (!key.isnil()) {
+ if (key.isinttype()) {
i = key.toint();
- if ( i>0 && i<=array.length ) {
+ if (i > 0 && i <= array.length) {
break;
}
}
- if ( hash.length == 0 )
- error( "invalid key to 'next' 1: " + key );
- i = hashSlot( key );
+ if (hash.length == 0)
+ error("invalid key to 'next' 1: " + key);
+ i = hashSlot(key);
boolean found = false;
- for ( Slot slot = hash[i]; slot != null; slot = slot.rest() ) {
- if ( found ) {
+ for (Slot slot = hash[i]; slot != null; slot = slot.rest()) {
+ if (found) {
StrongSlot nextEntry = slot.first();
- if ( nextEntry != null ) {
+ if (nextEntry != null) {
return nextEntry.toVarargs();
}
- } else if ( slot.keyeq( key ) ) {
+ } else if (slot.keyeq(key)) {
found = true;
}
}
- if ( !found ) {
- error( "invalid key to 'next' 2: " + key );
+ if (!found) {
+ error("invalid key to 'next' 2: " + key);
}
i += 1+array.length;
}
} while ( false );
// check array part
- for ( ; i 0 ) {
- index = hashSlot( key );
- for ( Slot slot = hash[ index ]; slot != null; slot = slot.rest() ) {
+ if (hash.length > 0) {
+ index = hashSlot(key);
+ for (Slot slot = hash[index]; slot != null; slot = slot.rest()) {
StrongSlot foundSlot;
- if ( ( foundSlot = slot.find( key ) ) != null ) {
- hash[index] = hash[index].set( foundSlot, value );
+ if ((foundSlot = slot.find(key)) != null) {
+ hash[index] = hash[index].set(foundSlot, value);
return;
}
}
}
- if ( checkLoadFactor() ) {
- if ( (m_metatable == null || !m_metatable.useWeakValues())
- && key.isinttype() && key.toint() > 0 ) {
+ if (checkLoadFactor()) {
+ if ((m_metatable == null || !m_metatable.useWeakValues()) && key.isinttype() && key.toint() > 0) {
// a rehash might make room in the array portion for this key.
- rehash( key.toint() );
- if ( arrayset(key.toint(), value) )
+ rehash(key.toint());
+ if (arrayset(key.toint(), value))
return;
} else {
- rehash( -1 );
+ rehash(-1);
}
- index = hashSlot( key );
+ index = hashSlot(key);
}
- Slot entry = ( m_metatable != null )
- ? m_metatable.entry( key, value )
- : defaultEntry( key, value );
- hash[ index ] = ( hash[index] != null ) ? hash[index].add( entry ) : entry;
+ Slot entry = m_metatable != null? m_metatable.entry(key, value): defaultEntry(key, value);
+ hash[index] = hash[index] != null? hash[index].add(entry): entry;
++hashEntries;
}
}
- public static int hashpow2( int hashCode, int mask ) {
+ public static int hashpow2(int hashCode, int mask) {
return hashCode & mask;
}
- public static int hashmod( int hashCode, int mask ) {
- return ( hashCode & 0x7FFFFFFF ) % mask;
+ public static int hashmod(int hashCode, int mask) {
+ return (hashCode & 0x7FFFFFFF)%mask;
}
/**
* Find the hashtable slot index to use.
- * @param key the key to look for
- * @param hashMask N-1 where N is the number of hash slots (must be power of 2)
+ *
+ * @param key the key to look for
+ * @param hashMask N-1 where N is the number of hash slots (must be power of
+ * 2)
* @return the slot index
*/
- public static int hashSlot( LuaValue key, int hashMask ) {
- switch ( key.type() ) {
+ public static int hashSlot(LuaValue key, int hashMask) {
+ switch (key.type()) {
case TNUMBER:
case TTABLE:
case TTHREAD:
case TLIGHTUSERDATA:
case TUSERDATA:
- return hashmod( key.hashCode(), hashMask );
+ return hashmod(key.hashCode(), hashMask);
default:
- return hashpow2( key.hashCode(), hashMask );
+ return hashpow2(key.hashCode(), hashMask);
}
}
-
+
/**
* Find the hashtable slot to use
+ *
* @param key key to look for
* @return slot to use
*/
private int hashSlot(LuaValue key) {
- return hashSlot( key, hash.length - 1 );
+ return hashSlot(key, hash.length-1);
}
- private void hashRemove( LuaValue key ) {
- if ( hash.length > 0 ) {
+ private void hashRemove(LuaValue key) {
+ if (hash.length > 0) {
int index = hashSlot(key);
- for ( Slot slot = hash[index]; slot != null; slot = slot.rest() ) {
+ for (Slot slot = hash[index]; slot != null; slot = slot.rest()) {
StrongSlot foundSlot;
- if ( ( foundSlot = slot.find( key ) ) != null ) {
- hash[index] = hash[index].remove( foundSlot );
+ if ((foundSlot = slot.find(key)) != null) {
+ hash[index] = hash[index].remove(foundSlot);
--hashEntries;
return;
}
@@ -547,9 +585,9 @@ public class LuaTable extends LuaValue implements Metatable {
private int countHashKeys() {
int keys = 0;
- for ( int i = 0; i < hash.length; ++i ) {
- for ( Slot slot = hash[i]; slot != null; slot = slot.rest() ) {
- if ( slot.first() != null )
+ for (Slot element : hash) {
+ for (Slot slot = element; slot != null; slot = slot.rest()) {
+ if (slot.first() != null)
keys++;
}
}
@@ -557,7 +595,7 @@ public class LuaTable extends LuaValue implements Metatable {
}
private void dropWeakArrayValues() {
- for ( int i = 0; i < array.length; ++i ) {
+ for (int i = 0; i < array.length; ++i) {
m_metatable.arrayget(array, i);
}
}
@@ -567,13 +605,13 @@ public class LuaTable extends LuaValue implements Metatable {
int i = 1;
// Count integer keys in array part
- for ( int bit = 0; bit < 31; ++bit ) {
- if ( i > array.length )
+ for (int bit = 0; bit < 31; ++bit) {
+ if (i > array.length)
break;
- int j = Math.min(array.length, 1 << bit);
+ int j = Math.min(array.length, 1< 0 ) {
+ if ((k = s.arraykey(Integer.MAX_VALUE)) > 0) {
nums[log2(k)]++;
total++;
}
@@ -598,38 +636,69 @@ public class LuaTable extends LuaValue implements Metatable {
static int log2(int x) {
int lg = 0;
x -= 1;
- if ( x < 0 )
+ if (x < 0)
// 2^(-(2^31)) is approximately 0
return Integer.MIN_VALUE;
- if ( ( x & 0xFFFF0000 ) != 0 ) {
+ if ((x & 0xFFFF0000) != 0) {
lg = 16;
x >>>= 16;
}
- if ( ( x & 0xFF00 ) != 0 ) {
+ if ((x & 0xFF00) != 0) {
lg += 8;
x >>>= 8;
}
- if ( ( x & 0xF0 ) != 0 ) {
+ if ((x & 0xF0) != 0) {
lg += 4;
x >>>= 4;
}
switch (x) {
- case 0x0: return 0;
- case 0x1: lg += 1; break;
- case 0x2: lg += 2; break;
- case 0x3: lg += 2; break;
- case 0x4: lg += 3; break;
- case 0x5: lg += 3; break;
- case 0x6: lg += 3; break;
- case 0x7: lg += 3; break;
- case 0x8: lg += 4; break;
- case 0x9: lg += 4; break;
- case 0xA: lg += 4; break;
- case 0xB: lg += 4; break;
- case 0xC: lg += 4; break;
- case 0xD: lg += 4; break;
- case 0xE: lg += 4; break;
- case 0xF: lg += 4; break;
+ case 0x0:
+ return 0;
+ case 0x1:
+ lg += 1;
+ break;
+ case 0x2:
+ lg += 2;
+ break;
+ case 0x3:
+ lg += 2;
+ break;
+ case 0x4:
+ lg += 3;
+ break;
+ case 0x5:
+ lg += 3;
+ break;
+ case 0x6:
+ lg += 3;
+ break;
+ case 0x7:
+ lg += 3;
+ break;
+ case 0x8:
+ lg += 4;
+ break;
+ case 0x9:
+ lg += 4;
+ break;
+ case 0xA:
+ lg += 4;
+ break;
+ case 0xB:
+ lg += 4;
+ break;
+ case 0xC:
+ lg += 4;
+ break;
+ case 0xD:
+ lg += 4;
+ break;
+ case 0xE:
+ lg += 4;
+ break;
+ case 0xF:
+ lg += 4;
+ break;
}
return lg;
}
@@ -640,16 +709,16 @@ public class LuaTable extends LuaValue implements Metatable {
* newKey < 0 next key will go in hash part
*/
private void rehash(int newKey) {
- if ( m_metatable != null && ( m_metatable.useWeakKeys() || m_metatable.useWeakValues() )) {
+ if (m_metatable != null && (m_metatable.useWeakKeys() || m_metatable.useWeakValues())) {
// If this table has weak entries, hashEntries is just an upper bound.
hashEntries = countHashKeys();
- if ( m_metatable.useWeakValues() ) {
+ if (m_metatable.useWeakValues()) {
dropWeakArrayValues();
}
}
int[] nums = new int[32];
int total = countIntKeys(nums);
- if ( newKey > 0 ) {
+ if (newKey > 0) {
total++;
nums[log2(newKey)]++;
}
@@ -657,13 +726,13 @@ public class LuaTable extends LuaValue implements Metatable {
// Choose N such that N <= sum(nums[0..log(N)]) < 2N
int keys = nums[0];
int newArraySize = 0;
- for ( int log = 1; log < 32; ++log ) {
+ for (int log = 1; log < 32; ++log) {
keys += nums[log];
- if (total * 2 < 1 << log) {
+ if (total*2 < 1<= (1 << (log - 1))) {
- newArraySize = 1 << log;
+ } else if (keys >= 1< 0 && newKey <= newArraySize ) {
+ if (newKey > 0 && newKey <= newArraySize) {
movingToArray--;
}
if (newArraySize != oldArray.length) {
newArray = new LuaValue[newArraySize];
if (newArraySize > oldArray.length) {
- for (int i = log2(oldArray.length + 1), j = log2(newArraySize) + 1; i < j; ++i) {
+ for (int i = log2(oldArray.length+1), j = log2(newArraySize)+1; i < j; ++i) {
movingToArray += nums[i];
}
} else if (oldArray.length > newArraySize) {
- for (int i = log2(newArraySize + 1), j = log2(oldArray.length) + 1; i < j; ++i) {
+ for (int i = log2(newArraySize+1), j = log2(oldArray.length)+1; i < j; ++i) {
movingToArray -= nums[i];
}
}
@@ -693,19 +762,16 @@ public class LuaTable extends LuaValue implements Metatable {
newArray = array;
}
- final int newHashSize = hashEntries - movingToArray
- + ((newKey < 0 || newKey > newArraySize) ? 1 : 0); // Make room for the new entry
+ final int newHashSize = hashEntries-movingToArray+(newKey < 0 || newKey > newArraySize? 1: 0); // Make room for the new entry
final int oldCapacity = oldHash.length;
final int newCapacity;
final int newHashMask;
if (newHashSize > 0) {
// round up to next power of 2.
- newCapacity = ( newHashSize < MIN_HASH_CAPACITY )
- ? MIN_HASH_CAPACITY
- : 1 << log2(newHashSize);
- newHashMask = newCapacity - 1;
- newHash = new Slot[ newCapacity ];
+ newCapacity = newHashSize < MIN_HASH_CAPACITY? MIN_HASH_CAPACITY: 1< 0 ) {
+ if ((k = slot.arraykey(newArraySize)) > 0) {
StrongSlot entry = slot.first();
if (entry != null)
- newArray[ k - 1 ] = entry.value();
- } else if ( !(slot instanceof DeadSlot) ) {
- int j = slot.keyindex( newHashMask );
- newHash[j] = slot.relink( newHash[j] );
+ newArray[k-1] = entry.value();
+ } else if (!(slot instanceof DeadSlot)) {
+ int j = slot.keyindex(newHashMask);
+ newHash[j] = slot.relink(newHash[j]);
}
}
}
// Move array values into hash portion
- for ( int i = newArraySize; i < oldArray.length; ) {
+ for (int i = newArraySize; i < oldArray.length;) {
LuaValue v;
- if ( ( v = oldArray[ i++ ] ) != null ) {
- int slot = hashmod( LuaInteger.hashCode( i ), newHashMask );
+ if ((v = oldArray[i++]) != null) {
+ int slot = hashmod(LuaInteger.hashCode(i), newHashMask);
Slot newEntry;
- if ( m_metatable != null ) {
- newEntry = m_metatable.entry( valueOf(i), v );
- if ( newEntry == null )
+ if (m_metatable != null) {
+ newEntry = m_metatable.entry(valueOf(i), v);
+ if (newEntry == null)
continue;
} else {
- newEntry = defaultEntry( valueOf(i), v );
+ newEntry = defaultEntry(valueOf(i), v);
}
- newHash[ slot ] = ( newHash[slot] != null )
- ? newHash[slot].add( newEntry ) : newEntry;
+ newHash[slot] = newHash[slot] != null? newHash[slot].add(newEntry): newEntry;
}
}
@@ -750,8 +815,9 @@ public class LuaTable extends LuaValue implements Metatable {
hashEntries -= movingToArray;
}
- public Slot entry( LuaValue key, LuaValue value ) {
- return defaultEntry( key, value );
+ @Override
+ public Slot entry(LuaValue key, LuaValue value) {
+ return defaultEntry(key, value);
}
protected static boolean isLargeKey(LuaValue key) {
@@ -767,12 +833,12 @@ public class LuaTable extends LuaValue implements Metatable {
}
protected static Entry defaultEntry(LuaValue key, LuaValue value) {
- if ( key.isinttype() ) {
- return new IntKeyEntry( key.toint(), value );
+ if (key.isinttype()) {
+ return new IntKeyEntry(key.toint(), value);
} else if (value.type() == TNUMBER) {
- return new NumberValueEntry( key, value.todouble() );
+ return new NumberValueEntry(key, value.todouble());
} else {
- return new NormalEntry( key, value );
+ return new NormalEntry(key, value);
}
}
@@ -782,22 +848,25 @@ public class LuaTable extends LuaValue implements Metatable {
//
// Only sorts the contiguous array part.
//
- /** Sort the table using a comparator.
+ /**
+ * Sort the table using a comparator.
+ *
* @param comparator {@link LuaValue} to be called to compare elements.
*/
public void sort(LuaValue comparator) {
- if (len().tolong() >= (long)Integer.MAX_VALUE) throw new LuaError("array too big: " + len().tolong());
+ if (len().tolong() >= Integer.MAX_VALUE)
+ throw new LuaError("array too big: " + len().tolong());
if (m_metatable != null && m_metatable.useWeakValues()) {
dropWeakArrayValues();
}
int n = length();
- if ( n > 1 )
- heapSort(n, comparator.isnil() ? null : comparator);
+ if (n > 1)
+ heapSort(n, comparator.isnil()? null: comparator);
}
private void heapSort(int count, LuaValue cmpfunc) {
heapify(count, cmpfunc);
- for ( int end=count; end>1; ) {
+ for (int end = count; end > 1;) {
LuaValue a = get(end); // swap(end, 1)
set(end, get(1));
set(1, a);
@@ -806,14 +875,14 @@ public class LuaTable extends LuaValue implements Metatable {
}
private void heapify(int count, LuaValue cmpfunc) {
- for ( int start=count/2; start>0; --start )
+ for (int start = count/2; start > 0; --start)
siftDown(start, count, cmpfunc);
}
private void siftDown(int start, int end, LuaValue cmpfunc) {
- for ( int root=start; root*2 <= end; ) {
+ for (int root = start; root*2 <= end;) {
int child = root*2;
- if (child < end && compare(child, child + 1, cmpfunc))
+ if (child < end && compare(child, child+1, cmpfunc))
++child;
if (compare(root, child, cmpfunc)) {
LuaValue a = get(root); // swap(root, child)
@@ -827,53 +896,62 @@ public class LuaTable extends LuaValue implements Metatable {
private boolean compare(int i, int j, LuaValue cmpfunc) {
LuaValue a = get(i), b = get(j);
- if ( a == null || b == null )
+ if (a == null || b == null)
return false;
- if ( cmpfunc != null ) {
- return cmpfunc.call(a,b).toboolean();
+ if (cmpfunc != null) {
+ return cmpfunc.call(a, b).toboolean();
} else {
return a.lt_b(b);
}
}
-
- /** This may be deprecated in a future release.
- * It is recommended to count via iteration over next() instead
+
+ /**
+ * This may be deprecated in a future release. It is recommended to count
+ * via iteration over next() instead
+ *
* @return count of keys in the table
- * */
+ */
public int keyCount() {
LuaValue k = LuaValue.NIL;
- for ( int i=0; true; i++ ) {
+ for (int i = 0; true; i++) {
Varargs n = next(k);
- if ( (k = n.arg1()).isnil() )
+ if ((k = n.arg1()).isnil())
return i;
}
}
-
- /** This may be deprecated in a future release.
- * It is recommended to use next() instead
+
+ /**
+ * This may be deprecated in a future release. It is recommended to use
+ * next() instead
+ *
* @return array of keys in the table
- * */
+ */
public LuaValue[] keys() {
Vector l = new Vector();
LuaValue k = LuaValue.NIL;
while ( true ) {
Varargs n = next(k);
- if ( (k = n.arg1()).isnil() )
+ if ((k = n.arg1()).isnil())
break;
- l.addElement( k );
+ l.addElement(k);
}
LuaValue[] a = new LuaValue[l.size()];
l.copyInto(a);
return a;
}
-
+
// equality w/ metatable processing
- public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
- public boolean eq_b( LuaValue val ) {
- if ( this == val ) return true;
- if ( m_metatable == null || !val.istable() ) return false;
+ @Override
+ public LuaValue eq(LuaValue val) { return eq_b(val)? TRUE: FALSE; }
+
+ @Override
+ public boolean eq_b(LuaValue val) {
+ if (this == val)
+ return true;
+ if (m_metatable == null || !val.istable())
+ return false;
LuaValue valmt = val.getmetatable();
- return valmt!=null && LuaValue.eqmtcall(this, m_metatable.toLuaValue(), val, valmt);
+ return valmt != null && LuaValue.eqmtcall(this, m_metatable.toLuaValue(), val, valmt);
}
/** Unpack all the elements of this table */
@@ -888,22 +966,28 @@ public class LuaTable extends LuaValue implements Metatable {
/** Unpack the elements from i to j inclusive */
public Varargs unpack(int i, int j) {
- if (j < i) return NONE;
- int count = j - i;
- if (count < 0) throw new LuaError("too many results to unpack: greater " + Integer.MAX_VALUE); // integer overflow
+ if (j < i)
+ return NONE;
+ int count = j-i;
+ if (count < 0)
+ throw new LuaError("too many results to unpack: greater " + Integer.MAX_VALUE); // integer overflow
int max = 0x00ffffff;
- if (count >= max) throw new LuaError("too many results to unpack: " + count + " (max is " + max + ')');
- int n = j + 1 - i;
+ if (count >= max)
+ throw new LuaError("too many results to unpack: " + count + " (max is " + max + ')');
+ int n = j+1-i;
switch (n) {
- case 0: return NONE;
- case 1: return get(i);
- case 2: return varargsOf(get(i), get(i+1));
+ case 0:
+ return NONE;
+ case 1:
+ return get(i);
+ case 2:
+ return varargsOf(get(i), get(i+1));
default:
if (n < 0)
return NONE;
try {
LuaValue[] v = new LuaValue[n];
- while (--n >= 0)
+ while ( --n >= 0 )
v[n] = get(i+n);
return varargsOf(v);
} catch (OutOfMemoryError e) {
@@ -918,19 +1002,19 @@ public class LuaTable extends LuaValue implements Metatable {
interface Slot {
/** Return hash{pow2,mod}( first().key().hashCode(), sizeMask ) */
- int keyindex( int hashMask );
+ int keyindex(int hashMask);
/** Return first Entry, if still present, or null. */
StrongSlot first();
/** Compare given key with first()'s key; return first() if equal. */
- StrongSlot find( LuaValue key );
+ StrongSlot find(LuaValue key);
/**
* Compare given key with first()'s key; return true if equal. May
* return true for keys no longer present in the table.
*/
- boolean keyeq( LuaValue key );
+ boolean keyeq(LuaValue key);
/** Return rest of elements */
Slot rest();
@@ -939,30 +1023,30 @@ public class LuaTable extends LuaValue implements Metatable {
* Return first entry's key, iff it is an integer between 1 and max,
* inclusive, or zero otherwise.
*/
- int arraykey( int max );
+ int arraykey(int max);
/**
* Set the value of this Slot's first Entry, if possible, or return a
* new Slot whose first entry has the given value.
*/
- Slot set( StrongSlot target, LuaValue value );
+ Slot set(StrongSlot target, LuaValue value);
/**
* Link the given new entry to this slot.
*/
- Slot add( Slot newEntry );
+ Slot add(Slot newEntry);
/**
* Return a Slot with the given value set to nil; must not return null
* for next() to behave correctly.
*/
- Slot remove( StrongSlot target );
+ Slot remove(StrongSlot target);
/**
* Return a Slot with the same first key and value (if still present)
* and rest() equal to rest.
*/
- Slot relink( Slot rest );
+ Slot relink(Slot rest);
}
/**
@@ -982,79 +1066,92 @@ public class LuaTable extends LuaValue implements Metatable {
private static class LinkSlot implements StrongSlot {
private Entry entry;
- private Slot next;
+ private Slot next;
- LinkSlot( Entry entry, Slot next ) {
+ LinkSlot(Entry entry, Slot next) {
this.entry = entry;
this.next = next;
}
+ @Override
public LuaValue key() {
return entry.key();
}
- public int keyindex( int hashMask ) {
- return entry.keyindex( hashMask );
+ @Override
+ public int keyindex(int hashMask) {
+ return entry.keyindex(hashMask);
}
+ @Override
public LuaValue value() {
return entry.value();
}
+ @Override
public Varargs toVarargs() {
return entry.toVarargs();
}
+ @Override
public StrongSlot first() {
return entry;
}
+ @Override
public StrongSlot find(LuaValue key) {
- return entry.keyeq(key) ? this : null;
+ return entry.keyeq(key)? this: null;
}
+ @Override
public boolean keyeq(LuaValue key) {
return entry.keyeq(key);
}
+ @Override
public Slot rest() {
return next;
}
- public int arraykey( int max ) {
- return entry.arraykey( max );
+ @Override
+ public int arraykey(int max) {
+ return entry.arraykey(max);
}
+ @Override
public Slot set(StrongSlot target, LuaValue value) {
- if ( target == this ) {
- entry = entry.set( value );
+ if (target == this) {
+ entry = entry.set(value);
return this;
} else {
- return setnext(next.set( target, value ));
+ return setnext(next.set(target, value));
}
}
- public Slot add( Slot entry ) {
- return setnext(next.add( entry ));
+ @Override
+ public Slot add(Slot entry) {
+ return setnext(next.add(entry));
}
- public Slot remove( StrongSlot target ) {
- if ( this == target ) {
- return new DeadSlot( key(), next );
+ @Override
+ public Slot remove(StrongSlot target) {
+ if (this == target) {
+ return new DeadSlot(key(), next);
} else {
- this.next = next.remove( target );
+ this.next = next.remove(target);
}
return this;
}
+ @Override
public Slot relink(Slot rest) {
// This method is (only) called during rehash, so it must not change this.next.
- return ( rest != null ) ? new LinkSlot(entry, rest) : (Slot)entry;
+ return rest != null? new LinkSlot(entry, rest): (Slot) entry;
}
// this method ensures that this.next is never set to null.
private Slot setnext(Slot next) {
- if ( next != null ) {
+ if (next != null) {
this.next = next;
return this;
} else {
@@ -1062,6 +1159,7 @@ public class LuaTable extends LuaValue implements Metatable {
}
}
+ @Override
public String toString() {
return entry + "; " + next;
}
@@ -1069,30 +1167,43 @@ public class LuaTable extends LuaValue implements Metatable {
/**
* Base class for regular entries.
- *
+ *
*
* If the key may be an integer, the {@link #arraykey(int)} method must be
* overridden to handle that case.
*/
static abstract class Entry extends Varargs implements StrongSlot {
+ @Override
public abstract LuaValue key();
- public abstract LuaValue value();
- abstract Entry set(LuaValue value);
- public abstract boolean keyeq( LuaValue key );
- public abstract int keyindex( int hashMask );
- public int arraykey( int max ) {
+ @Override
+ public abstract LuaValue value();
+
+ abstract Entry set(LuaValue value);
+
+ @Override
+ public abstract boolean keyeq(LuaValue key);
+
+ @Override
+ public abstract int keyindex(int hashMask);
+
+ @Override
+ public int arraykey(int max) {
return 0;
}
+ @Override
public LuaValue arg(int i) {
switch (i) {
- case 1: return key();
- case 2: return value();
+ case 1:
+ return key();
+ case 2:
+ return value();
}
return NIL;
}
+ @Override
public int narg() {
return 2;
}
@@ -1100,81 +1211,99 @@ public class LuaTable extends LuaValue implements Metatable {
/**
* Subclasses should redefine as "return this;" whenever possible.
*/
+ @Override
public Varargs toVarargs() {
return varargsOf(key(), value());
}
+ @Override
public LuaValue arg1() {
return key();
}
+ @Override
public Varargs subargs(int start) {
switch (start) {
- case 1: return this;
- case 2: return value();
+ case 1:
+ return this;
+ case 2:
+ return value();
}
return NONE;
}
+ @Override
public StrongSlot first() {
return this;
}
+ @Override
public Slot rest() {
return null;
}
+ @Override
public StrongSlot find(LuaValue key) {
- return keyeq(key) ? this : null;
+ return keyeq(key)? this: null;
}
+ @Override
public Slot set(StrongSlot target, LuaValue value) {
- return set( value );
+ return set(value);
}
- public Slot add( Slot entry ) {
- return new LinkSlot( this, entry );
+ @Override
+ public Slot add(Slot entry) {
+ return new LinkSlot(this, entry);
}
+ @Override
public Slot remove(StrongSlot target) {
- return new DeadSlot( key(), null );
+ return new DeadSlot(key(), null);
}
- public Slot relink( Slot rest ) {
- return ( rest != null ) ? new LinkSlot( this, rest ) : (Slot)this;
+ @Override
+ public Slot relink(Slot rest) {
+ return rest != null? new LinkSlot(this, rest): (Slot) this;
}
}
static class NormalEntry extends Entry {
private final LuaValue key;
- private LuaValue value;
+ private LuaValue value;
- NormalEntry( LuaValue key, LuaValue value ) {
+ NormalEntry(LuaValue key, LuaValue value) {
this.key = key;
this.value = value;
}
+ @Override
public LuaValue key() {
return key;
}
+ @Override
public LuaValue value() {
return value;
}
+ @Override
public Entry set(LuaValue value) {
this.value = value;
return this;
}
+ @Override
public Varargs toVarargs() {
return this;
}
- public int keyindex( int hashMask ) {
- return hashSlot( key, hashMask );
+ @Override
+ public int keyindex(int hashMask) {
+ return hashSlot(key, hashMask);
}
+ @Override
public boolean keyeq(LuaValue key) {
return key.raweq(this.key);
}
@@ -1182,44 +1311,51 @@ public class LuaTable extends LuaValue implements Metatable {
private static class IntKeyEntry extends Entry {
private final int key;
- private LuaValue value;
+ private LuaValue value;
IntKeyEntry(int key, LuaValue value) {
this.key = key;
this.value = value;
}
+ @Override
public LuaValue key() {
- return valueOf( key );
+ return valueOf(key);
}
+ @Override
public int arraykey(int max) {
- return ( key >= 1 && key <= max ) ? key : 0;
+ return key >= 1 && key <= max? key: 0;
}
+ @Override
public LuaValue value() {
return value;
}
+ @Override
public Entry set(LuaValue value) {
this.value = value;
return this;
}
- public int keyindex( int mask ) {
- return hashmod( LuaInteger.hashCode( key ), mask );
+ @Override
+ public int keyindex(int mask) {
+ return hashmod(LuaInteger.hashCode(key), mask);
}
+ @Override
public boolean keyeq(LuaValue key) {
- return key.raweq( this.key );
+ return key.raweq(this.key);
}
}
/**
- * Entry class used with numeric values, but only when the key is not an integer.
+ * Entry class used with numeric values, but only when the key is not an
+ * integer.
*/
private static class NumberValueEntry extends Entry {
- private double value;
+ private double value;
private final LuaValue key;
NumberValueEntry(LuaValue key, double value) {
@@ -1227,14 +1363,17 @@ public class LuaTable extends LuaValue implements Metatable {
this.value = value;
}
+ @Override
public LuaValue key() {
return key;
}
+ @Override
public LuaValue value() {
return valueOf(value);
}
+ @Override
public Entry set(LuaValue value) {
if (value.type() == TNUMBER) {
LuaValue n = value.tonumber();
@@ -1243,65 +1382,74 @@ public class LuaTable extends LuaValue implements Metatable {
return this;
}
}
- return new NormalEntry( this.key, value );
+ return new NormalEntry(this.key, value);
}
- public int keyindex( int mask ) {
- return hashSlot( key, mask );
+ @Override
+ public int keyindex(int mask) {
+ return hashSlot(key, mask);
}
+ @Override
public boolean keyeq(LuaValue key) {
return key.raweq(this.key);
}
}
/**
- * A Slot whose value has been set to nil. The key is kept in a weak reference so that
- * it can be found by next().
+ * A Slot whose value has been set to nil. The key is kept in a weak
+ * reference so that it can be found by next().
*/
private static class DeadSlot implements Slot {
private final Object key;
- private Slot next;
+ private Slot next;
- private DeadSlot( LuaValue key, Slot next ) {
- this.key = isLargeKey(key) ? new WeakReference( key ) : (Object)key;
+ private DeadSlot(LuaValue key, Slot next) {
+ this.key = isLargeKey(key)? new WeakReference(key): (Object) key;
this.next = next;
}
private LuaValue key() {
- return (LuaValue) (key instanceof WeakReference ? ((WeakReference) key).get() : key);
+ return (LuaValue) (key instanceof WeakReference? ((WeakReference) key).get(): key);
}
+ @Override
public int keyindex(int hashMask) {
// Not needed: this entry will be dropped during rehash.
return 0;
}
+ @Override
public StrongSlot first() {
return null;
}
+ @Override
public StrongSlot find(LuaValue key) {
return null;
}
+ @Override
public boolean keyeq(LuaValue key) {
LuaValue k = key();
return k != null && key.raweq(k);
}
+ @Override
public Slot rest() {
return next;
}
+ @Override
public int arraykey(int max) {
return -1;
}
+ @Override
public Slot set(StrongSlot target, LuaValue value) {
- Slot next = ( this.next != null ) ? this.next.set( target, value ) : null;
- if ( key() != null ) {
+ Slot next = this.next != null? this.next.set(target, value): null;
+ if (key() != null) {
// if key hasn't been garbage collected, it is still potentially a valid argument
// to next(), so we can't drop this entry yet.
this.next = next;
@@ -1311,12 +1459,14 @@ public class LuaTable extends LuaValue implements Metatable {
}
}
+ @Override
public Slot add(Slot newEntry) {
- return ( next != null ) ? next.add(newEntry) : newEntry;
+ return next != null? next.add(newEntry): newEntry;
}
+ @Override
public Slot remove(StrongSlot target) {
- if ( key() != null ) {
+ if (key() != null) {
next = next.remove(target);
return this;
} else {
@@ -1324,10 +1474,12 @@ public class LuaTable extends LuaValue implements Metatable {
}
}
+ @Override
public Slot relink(Slot rest) {
return rest;
}
+ @Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("
- * A LuaThread is typically created in response to a scripted call to
+ * A LuaThread is typically created in response to a scripted call to
* {@code coroutine.create()}
*
- * The threads must be initialized with the globals, so that
- * the global environment may be passed along according to rules of lua.
- * This is done via the constructor arguments {@link #LuaThread(Globals)} or
+ * The threads must be initialized with the globals, so that the global
+ * environment may be passed along according to rules of lua. This is done via
+ * the constructor arguments {@link #LuaThread(Globals)} or
* {@link #LuaThread(Globals, LuaValue)}.
- *
- * The utility classes {@link org.luaj.vm2.lib.jse.JsePlatform} and
- * {@link org.luaj.vm2.lib.jme.JmePlatform}
- * see to it that this {@link Globals} are initialized properly.
*
- * The behavior of coroutine threads matches closely the behavior
- * of C coroutine library. However, because of the use of Java threads
- * to manage call state, it is possible to yield from anywhere in luaj.
+ * The utility classes {@link org.luaj.vm2.lib.jse.JsePlatform} and
+ * {@link org.luaj.vm2.lib.jme.JmePlatform} see to it that this {@link Globals}
+ * are initialized properly.
*
- * Each Java thread wakes up at regular intervals and checks a weak reference
- * to determine if it can ever be resumed. If not, it throws
- * {@link OrphanedThread} which is an {@link java.lang.Error}.
- * Applications should not catch {@link OrphanedThread}, because it can break
- * the thread safety of luaj. The value controlling the polling interval
- * is {@link #thread_orphan_check_interval} and may be set by the user.
- *
- * There are two main ways to abandon a coroutine. The first is to call
- * {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)},
- * and arrange to have it never resumed possibly by values passed to yield.
- * The second is to throw {@link OrphanedThread}, which should put the thread
- * in a dead state. In either case all references to the thread must be
- * dropped, and the garbage collector must run for the thread to be
- * garbage collected.
+ * The behavior of coroutine threads matches closely the behavior of C coroutine
+ * library. However, because of the use of Java threads to manage call state, it
+ * is possible to yield from anywhere in luaj.
+ *
+ * Each Java thread wakes up at regular intervals and checks a weak reference to
+ * determine if it can ever be resumed. If not, it throws {@link OrphanedThread}
+ * which is an {@link java.lang.Error}. Applications should not catch
+ * {@link OrphanedThread}, because it can break the thread safety of luaj. The
+ * value controlling the polling interval is
+ * {@link #thread_orphan_check_interval} and may be set by the user.
+ *
+ * There are two main ways to abandon a coroutine. The first is to call
+ * {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)}, and
+ * arrange to have it never resumed possibly by values passed to yield. The
+ * second is to throw {@link OrphanedThread}, which should put the thread in a
+ * dead state. In either case all references to the thread must be dropped, and
+ * the garbage collector must run for the thread to be garbage collected.
+ *
*
- *
* @see LuaValue
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
@@ -70,107 +68,108 @@ public class LuaThread extends LuaValue {
/** Shared metatable for lua threads. */
public static LuaValue s_metatable;
- /** The current number of coroutines. Should not be set. */
+ /** The current number of coroutines. Should not be set. */
public static int coroutine_count = 0;
- /** Polling interval, in milliseconds, which each thread uses while waiting to
- * return from a yielded state to check if the lua threads is no longer
- * referenced and therefore should be garbage collected.
- * A short polling interval for many threads will consume server resources.
- * Orphaned threads cannot be detected and collected unless garbage
- * collection is run. This can be changed by Java startup code if desired.
+ /**
+ * Polling interval, in milliseconds, which each thread uses while waiting
+ * to return from a yielded state to check if the lua threads is no longer
+ * referenced and therefore should be garbage collected. A short polling
+ * interval for many threads will consume server resources. Orphaned threads
+ * cannot be detected and collected unless garbage collection is run. This
+ * can be changed by Java startup code if desired.
*/
public static long thread_orphan_check_interval = 5000;
-
- public static final int STATUS_INITIAL = 0;
- public static final int STATUS_SUSPENDED = 1;
- public static final int STATUS_RUNNING = 2;
- public static final int STATUS_NORMAL = 3;
- public static final int STATUS_DEAD = 4;
- public static final String[] STATUS_NAMES = {
- "suspended",
- "suspended",
- "running",
- "normal",
- "dead",};
-
+
+ public static final int STATUS_INITIAL = 0;
+ public static final int STATUS_SUSPENDED = 1;
+ public static final int STATUS_RUNNING = 2;
+ public static final int STATUS_NORMAL = 3;
+ public static final int STATUS_DEAD = 4;
+ public static final String[] STATUS_NAMES = { "suspended", "suspended", "running", "normal", "dead", };
+
public final State state;
- public static final int MAX_CALLSTACK = 256;
+ public static final int MAX_CALLSTACK = 256;
- /** Thread-local used by DebugLib to store debugging state.
- * This is an opaque value that should not be modified by applications. */
+ /**
+ * Thread-local used by DebugLib to store debugging state. This is an opaque
+ * value that should not be modified by applications.
+ */
public Object callstack;
public final Globals globals;
- /** Error message handler for this thread, if any. */
+ /** Error message handler for this thread, if any. */
public LuaValue errorfunc;
-
+
/** Private constructor for main thread only */
public LuaThread(Globals globals) {
state = new State(globals, this, null);
state.status = STATUS_RUNNING;
this.globals = globals;
}
-
- /**
+
+ /**
* Create a LuaThread around a function and environment
+ *
* @param func The function to execute
*/
- public LuaThread(Globals globals, LuaValue func) {
+ public LuaThread(Globals globals, LuaValue func) {
LuaValue.assert_(func != null, "function cannot be null");
state = new State(globals, this, func);
this.globals = globals;
}
-
+
+ @Override
public int type() {
return LuaValue.TTHREAD;
}
-
+
+ @Override
public String typename() {
return "thread";
}
-
+
+ @Override
public boolean isthread() {
return true;
}
-
+
+ @Override
public LuaThread optthread(LuaThread defval) {
return this;
}
-
+
+ @Override
public LuaThread checkthread() {
return this;
}
-
- public LuaValue getmetatable() {
- return s_metatable;
- }
-
- public String getStatus() {
- return STATUS_NAMES[state.status];
+
+ @Override
+ public LuaValue getmetatable() {
+ return s_metatable;
}
- public boolean isMainThread() {
- return this.state.function == null;
- }
+ public String getStatus() { return STATUS_NAMES[state.status]; }
+
+ public boolean isMainThread() { return this.state.function == null; }
public Varargs resume(Varargs args) {
final LuaThread.State s = this.state;
if (s.status > LuaThread.STATUS_SUSPENDED)
- return LuaValue.varargsOf(LuaValue.FALSE,
- LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine"));
+ return LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(
+ "cannot resume " + (s.status == LuaThread.STATUS_DEAD? "dead": "non-suspended") + " coroutine"));
return s.lua_resume(this, args);
}
public static class State implements Runnable {
private final Globals globals;
- final WeakReference lua_thread;
+ final WeakReference lua_thread;
public final LuaValue function;
- Varargs args = LuaValue.NONE;
- Varargs result = LuaValue.NONE;
- String error = null;
+ Varargs args = LuaValue.NONE;
+ Varargs result = LuaValue.NONE;
+ String error = null;
/** Hook function control state used by debug lib. */
public LuaValue hookfunc;
@@ -178,11 +177,11 @@ public class LuaThread extends LuaValue {
public boolean hookline;
public boolean hookcall;
public boolean hookrtrn;
- public int hookcount;
+ public int hookcount;
public boolean inhook;
- public int lastline;
- public int bytecodes;
-
+ public int lastline;
+ public int bytecodes;
+
public int status = LuaThread.STATUS_INITIAL;
State(Globals globals, LuaThread lua_thread, LuaValue function) {
@@ -190,7 +189,8 @@ public class LuaThread extends LuaValue {
this.lua_thread = new WeakReference(lua_thread);
this.function = function;
}
-
+
+ @Override
public synchronized void run() {
try {
Varargs a = this.args;
@@ -210,8 +210,8 @@ public class LuaThread extends LuaValue {
globals.running = new_thread;
this.args = args;
if (this.status == STATUS_INITIAL) {
- this.status = STATUS_RUNNING;
- new Thread(this, "Coroutine-"+(++coroutine_count)).start();
+ this.status = STATUS_RUNNING;
+ new Thread(this, "Coroutine-" + (++coroutine_count)).start();
} else {
this.notify();
}
@@ -219,9 +219,8 @@ public class LuaThread extends LuaValue {
previous_thread.state.status = STATUS_NORMAL;
this.status = STATUS_RUNNING;
this.wait();
- return (this.error != null?
- LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)):
- LuaValue.varargsOf(LuaValue.TRUE, this.result));
+ return this.error != null? LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error))
+ : LuaValue.varargsOf(LuaValue.TRUE, this.result);
} catch (InterruptedException ie) {
throw new OrphanedThread();
} finally {
@@ -230,7 +229,7 @@ public class LuaThread extends LuaValue {
this.error = null;
globals.running = previous_thread;
if (previous_thread != null)
- globals.running.state.status =STATUS_RUNNING;
+ globals.running.state.status = STATUS_RUNNING;
}
}
@@ -245,7 +244,7 @@ public class LuaThread extends LuaValue {
this.status = STATUS_DEAD;
throw new OrphanedThread();
}
- } while (this.status == STATUS_SUSPENDED);
+ } while ( this.status == STATUS_SUSPENDED );
return this.args;
} catch (InterruptedException ie) {
this.status = STATUS_DEAD;
@@ -256,5 +255,5 @@ public class LuaThread extends LuaValue {
}
}
}
-
+
}
diff --git a/src/core/org/luaj/vm2/LuaUserdata.java b/luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java
similarity index 58%
rename from src/core/org/luaj/vm2/LuaUserdata.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java
index b6f58e09..7b36212c 100644
--- a/src/core/org/luaj/vm2/LuaUserdata.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,106 +21,136 @@
******************************************************************************/
package org.luaj.vm2;
-
public class LuaUserdata extends LuaValue {
-
- public Object m_instance;
+
+ public Object m_instance;
public LuaValue m_metatable;
-
+
public LuaUserdata(Object obj) {
m_instance = obj;
}
-
+
public LuaUserdata(Object obj, LuaValue metatable) {
m_instance = obj;
m_metatable = metatable;
}
-
+
+ @Override
public String tojstring() {
return String.valueOf(m_instance);
}
-
+
+ @Override
public int type() {
return LuaValue.TUSERDATA;
}
-
+
+ @Override
public String typename() {
return "userdata";
}
+ @Override
public int hashCode() {
return m_instance.hashCode();
}
-
+
public Object userdata() {
return m_instance;
}
-
- public boolean isuserdata() { return true; }
- public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); }
- public Object touserdata() { return m_instance; }
- public Object touserdata(Class c) { return c.isAssignableFrom(m_instance.getClass())? m_instance: null; }
- public Object optuserdata(Object defval) { return m_instance; }
+
+ @Override
+ public boolean isuserdata() { return true; }
+
+ @Override
+ public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); }
+
+ @Override
+ public Object touserdata() { return m_instance; }
+
+ @Override
+ public Object touserdata(Class c) { return c.isAssignableFrom(m_instance.getClass())? m_instance: null; }
+
+ @Override
+ public Object optuserdata(Object defval) { return m_instance; }
+
+ @Override
public Object optuserdata(Class c, Object defval) {
if (!c.isAssignableFrom(m_instance.getClass()))
typerror(c.getName());
return m_instance;
}
-
+
+ @Override
public LuaValue getmetatable() {
return m_metatable;
}
+ @Override
public LuaValue setmetatable(LuaValue metatable) {
this.m_metatable = metatable;
return this;
}
+ @Override
public Object checkuserdata() {
return m_instance;
}
-
- public Object checkuserdata(Class c) {
- if ( c.isAssignableFrom(m_instance.getClass()) )
- return m_instance;
+
+ @Override
+ public Object checkuserdata(Class c) {
+ if (c.isAssignableFrom(m_instance.getClass()))
+ return m_instance;
return typerror(c.getName());
}
-
- public LuaValue get( LuaValue key ) {
- return m_metatable!=null? gettable(this,key): NIL;
- }
-
- public void set( LuaValue key, LuaValue value ) {
- if ( m_metatable==null || ! settable(this,key,value) )
- error( "cannot set "+key+" for userdata" );
+
+ @Override
+ public LuaValue get(LuaValue key) {
+ return m_metatable != null? gettable(this, key): NIL;
}
- public boolean equals( Object val ) {
- if ( this == val )
+ @Override
+ public void set(LuaValue key, LuaValue value) {
+ if (m_metatable == null || !settable(this, key, value))
+ error("cannot set " + key + " for userdata");
+ }
+
+ @Override
+ public boolean equals(Object val) {
+ if (this == val)
return true;
- if ( ! (val instanceof LuaUserdata) )
+ if (!(val instanceof LuaUserdata))
return false;
LuaUserdata u = (LuaUserdata) val;
return m_instance.equals(u.m_instance);
}
// equality w/ metatable processing
- public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
- public boolean eq_b( LuaValue val ) {
- if ( val.raweq(this) ) return true;
- if ( m_metatable == null || !val.isuserdata() ) return false;
+ @Override
+ public LuaValue eq(LuaValue val) { return eq_b(val)? TRUE: FALSE; }
+
+ @Override
+ public boolean eq_b(LuaValue val) {
+ if (val.raweq(this))
+ return true;
+ if (m_metatable == null || !val.isuserdata())
+ return false;
LuaValue valmt = val.getmetatable();
- return valmt!=null && LuaValue.eqmtcall(this, m_metatable, val, valmt);
+ return valmt != null && LuaValue.eqmtcall(this, m_metatable, val, valmt);
}
-
+
// equality w/o metatable processing
- public boolean raweq( LuaValue val ) { return val.raweq(this); }
- public boolean raweq( LuaUserdata val ) {
- return this == val || (m_metatable == val.m_metatable && m_instance.equals(val.m_instance));
+ @Override
+ public boolean raweq(LuaValue val) { return val.raweq(this); }
+
+ @Override
+ public boolean raweq(LuaUserdata val) {
+ return this == val || m_metatable == val.m_metatable && m_instance.equals(val.m_instance);
}
-
+
// __eq metatag processing
- public boolean eqmt( LuaValue val ) {
- return m_metatable!=null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable()): false;
+ public boolean eqmt(LuaValue val) {
+ return m_metatable != null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable())
+ : false;
}
}
diff --git a/src/core/org/luaj/vm2/LuaValue.java b/luaj-core/src/main/java/org/luaj/vm2/LuaValue.java
similarity index 99%
rename from src/core/org/luaj/vm2/LuaValue.java
rename to luaj-core/src/main/java/org/luaj/vm2/LuaValue.java
index 9d3af18d..fff03897 100644
--- a/src/core/org/luaj/vm2/LuaValue.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/LuaValue.java
@@ -99,7 +99,7 @@ package org.luaj.vm2;
* {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE},
* {@link #ADD}, {@link #SUB}, {@link #DIV}, {@link #MUL}, {@link #POW},
* {@link #MOD}, {@link #UNM}, {@link #LEN}, {@link #EQ}, {@link #LT},
- * {@link #LE}, {@link #TOSTRING}, and {@link #CONCAT}.
+ * {@link #LE}, {@link #TOSTRING}, {@link #CONCAT}, {@link PAIRS} and {@link IPAIRS}.
*
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
@@ -242,7 +242,13 @@ public class LuaValue extends Varargs {
/** LuaString constant with value "__concat" for use as metatag */
public static final LuaString CONCAT = valueOf("__concat");
-
+
+ /** LuaString constant with value "__pairs" for use as metatag */
+ public static final LuaString PAIRS = valueOf("__pairs");
+
+ /** LuaString constant with value "__ipairs" for use as metatag */
+ public static final LuaString IPAIRS = valueOf("__ipairs");
+
/** LuaString constant with value "" */
public static final LuaString EMPTYSTRING = valueOf("");
@@ -529,7 +535,7 @@ public class LuaValue extends Varargs {
* @see #isstring()
* @see #TSTRING
*/
- public String tojstring() { return typename() + ": " + Integer.toHexString(hashCode()); }
+ public String tojstring() { return typename() + ": 0x" + Integer.toHexString(hashCode()); }
/** Convert to userdata instance, or null.
* @return userdata instance if userdata, or null if not {@link LuaUserdata}
@@ -625,7 +631,7 @@ public class LuaValue extends Varargs {
* @see #isclosure()
* @see #TFUNCTION
*/
- public LuaClosure optclosure(LuaClosure defval) { argerror("closure"); return null; }
+ public LuaClosure optclosure(LuaClosure defval) { argerror("function"); return null; }
/** Check that optional argument is a number or string convertible to number and return as double
* @param defval double to return if {@code this} is nil or none
@@ -737,7 +743,7 @@ public class LuaValue extends Varargs {
* @see #toString()
* @see #TSTRING
*/
- public String optjstring(String defval) { argerror("String"); return null; }
+ public String optjstring(String defval) { argerror("string"); return null; }
/** Check that optional argument is a string or number and return as {@link LuaString}
* @param defval {@link LuaString} to return if {@code this} is nil or none
@@ -888,7 +894,7 @@ public class LuaValue extends Varargs {
* @see #optint(int)
* @see #TNUMBER
*/
- public int checkint() { argerror("int"); return 0; }
+ public int checkint() { argerror("number"); return 0; }
/** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric
*
@@ -1053,7 +1059,7 @@ public class LuaValue extends Varargs {
* @param expected String naming the type that was expected
* @throws LuaError in all cases
*/
- protected LuaValue argerror(String expected) { throw new LuaError("bad argument: "+expected+" expected, got "+typename()); }
+ protected LuaValue argerror(String expected) { throw new LuaError("bad argument ("+expected+" expected, got "+typename()+")"); }
/**
* Throw a {@link LuaError} indicating an invalid argument was supplied to a function
@@ -2985,7 +2991,7 @@ public class LuaValue extends Varargs {
return h.call(this, op1);
if (LuaValue.LE.raweq(tag) && (!(h = metatag(LT)).isnil() || !(h = op1.metatag(LT)).isnil()))
return h.call(op1, this).not();
- return error("attempt to compare "+tag+" on "+typename()+" and "+op1.typename());
+ return error("bad argument: attempt to compare "+tag+" on "+typename()+" and "+op1.typename());
}
/** Perform string comparison with another value
diff --git a/src/core/org/luaj/vm2/Metatable.java b/luaj-core/src/main/java/org/luaj/vm2/Metatable.java
similarity index 86%
rename from src/core/org/luaj/vm2/Metatable.java
rename to luaj-core/src/main/java/org/luaj/vm2/Metatable.java
index 49c639b6..f57b3647 100644
--- a/src/core/org/luaj/vm2/Metatable.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/Metatable.java
@@ -10,7 +10,7 @@
*
* 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
@@ -29,23 +29,23 @@ import org.luaj.vm2.LuaTable.Slot;
interface Metatable {
/** Return whether or not this table's keys are weak. */
- public boolean useWeakKeys();
+ boolean useWeakKeys();
/** Return whether or not this table's values are weak. */
- public boolean useWeakValues();
+ boolean useWeakValues();
/** Return this metatable as a LuaValue. */
- public LuaValue toLuaValue();
+ LuaValue toLuaValue();
/** Return an instance of Slot appropriate for the given key and value. */
- public Slot entry( LuaValue key, LuaValue value );
+ Slot entry(LuaValue key, LuaValue value);
/** Returns the given value wrapped in a weak reference if appropriate. */
- public LuaValue wrap( LuaValue value );
+ LuaValue wrap(LuaValue value);
/**
- * Returns the value at the given index in the array, or null if it is a weak reference that
- * has been dropped.
+ * Returns the value at the given index in the array, or null if it is a
+ * weak reference that has been dropped.
*/
- public LuaValue arrayget(LuaValue[] array, int index);
+ LuaValue arrayget(LuaValue[] array, int index);
}
diff --git a/src/core/org/luaj/vm2/NonTableMetatable.java b/luaj-core/src/main/java/org/luaj/vm2/NonTableMetatable.java
similarity index 90%
rename from src/core/org/luaj/vm2/NonTableMetatable.java
rename to luaj-core/src/main/java/org/luaj/vm2/NonTableMetatable.java
index 4cf112a8..6fa72761 100644
--- a/src/core/org/luaj/vm2/NonTableMetatable.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/NonTableMetatable.java
@@ -10,26 +10,32 @@ class NonTableMetatable implements Metatable {
this.value = value;
}
+ @Override
public boolean useWeakKeys() {
return false;
}
+ @Override
public boolean useWeakValues() {
return false;
}
+ @Override
public LuaValue toLuaValue() {
return value;
}
+ @Override
public Slot entry(LuaValue key, LuaValue value) {
return LuaTable.defaultEntry(key, value);
}
+ @Override
public LuaValue wrap(LuaValue value) {
return value;
}
+ @Override
public LuaValue arrayget(LuaValue[] array, int index) {
return array[index];
}
diff --git a/src/core/org/luaj/vm2/OrphanedThread.java b/luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java
similarity index 98%
rename from src/core/org/luaj/vm2/OrphanedThread.java
rename to luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java
index b3c931f1..24337a32 100644
--- a/src/core/org/luaj/vm2/OrphanedThread.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java
@@ -10,7 +10,7 @@
*
* 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
@@ -29,7 +29,8 @@ package org.luaj.vm2;
* {@link LuaThread} being used as a coroutine that could not possibly be
* resumed again because there are no more references to the LuaThread with
* which it is associated. Rather than locking up resources forever, this error
- * is thrown, and should fall through all the way to the thread's {@link Thread#run()} method.
+ * is thrown, and should fall through all the way to the thread's
+ * {@link Thread#run()} method.
*
* Java code mixed with the luaj vm should not catch this error because it may
* occur when the coroutine is not running, so any processing done during error
diff --git a/src/core/org/luaj/vm2/Print.java b/luaj-core/src/main/java/org/luaj/vm2/Print.java
similarity index 62%
rename from src/core/org/luaj/vm2/Print.java
rename to luaj-core/src/main/java/org/luaj/vm2/Print.java
index 8b0bd572..08ca99be 100644
--- a/src/core/org/luaj/vm2/Print.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/Print.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,131 +25,96 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
/**
- * Debug helper class to pretty-print lua bytecodes.
+ * Debug helper class to pretty-print lua bytecodes.
+ *
* @see Prototype
- * @see LuaClosure
+ * @see LuaClosure
*/
public class Print extends Lua {
/** opcode names */
private static final String STRING_FOR_NULL = "null";
- public static PrintStream ps = System.out;
+ public static PrintStream ps = System.out;
/** String names for each lua opcode value. */
- public static final String[] OPNAMES = {
- "MOVE",
- "LOADK",
- "LOADKX",
- "LOADBOOL",
- "LOADNIL",
- "GETUPVAL",
- "GETTABUP",
- "GETTABLE",
- "SETTABUP",
- "SETUPVAL",
- "SETTABLE",
- "NEWTABLE",
- "SELF",
- "ADD",
- "SUB",
- "MUL",
- "DIV",
- "MOD",
- "POW",
- "UNM",
- "NOT",
- "LEN",
- "CONCAT",
- "JMP",
- "EQ",
- "LT",
- "LE",
- "TEST",
- "TESTSET",
- "CALL",
- "TAILCALL",
- "RETURN",
- "FORLOOP",
- "FORPREP",
- "TFORCALL",
- "TFORLOOP",
- "SETLIST",
- "CLOSURE",
- "VARARG",
- "EXTRAARG",
- null,
- };
-
+ public static final String[] OPNAMES = { "MOVE", "LOADK", "LOADKX", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETTABUP",
+ "GETTABLE", "SETTABUP", "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", "MOD",
+ "POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL",
+ "RETURN", "FORLOOP", "FORPREP", "TFORCALL", "TFORLOOP", "SETLIST", "CLOSURE", "VARARG", "EXTRAARG", null, };
static void printString(PrintStream ps, final LuaString s) {
-
+
ps.print('"');
for (int i = 0, n = s.m_length; i < n; i++) {
int c = s.m_bytes[s.m_offset+i];
- if ( c >= ' ' && c <= '~' && c != '\"' && c != '\\' )
+ if (c >= ' ' && c <= '~' && c != '\"' && c != '\\')
ps.print((char) c);
else {
switch (c) {
- case '"':
- ps.print("\\\"");
- break;
- case '\\':
- ps.print("\\\\");
- break;
- case 0x0007: /* bell */
- ps.print("\\a");
- break;
- case '\b': /* backspace */
- ps.print("\\b");
- break;
- case '\f': /* form feed */
- ps.print("\\f");
- break;
- case '\t': /* tab */
- ps.print("\\t");
- break;
- case '\r': /* carriage return */
- ps.print("\\r");
- break;
- case '\n': /* newline */
- ps.print("\\n");
- break;
- case 0x000B: /* vertical tab */
- ps.print("\\v");
- break;
- default:
- ps.print('\\');
- ps.print(Integer.toString(1000 + 0xff&c).substring(1));
- break;
+ case '"':
+ ps.print("\\\"");
+ break;
+ case '\\':
+ ps.print("\\\\");
+ break;
+ case 0x0007: /* bell */
+ ps.print("\\a");
+ break;
+ case '\b': /* backspace */
+ ps.print("\\b");
+ break;
+ case '\f': /* form feed */
+ ps.print("\\f");
+ break;
+ case '\t': /* tab */
+ ps.print("\\t");
+ break;
+ case '\r': /* carriage return */
+ ps.print("\\r");
+ break;
+ case '\n': /* newline */
+ ps.print("\\n");
+ break;
+ case 0x000B: /* vertical tab */
+ ps.print("\\v");
+ break;
+ default:
+ ps.print('\\');
+ ps.print(Integer.toString(1000+0xff & c).substring(1));
+ break;
}
}
}
ps.print('"');
}
- static void printValue( PrintStream ps, LuaValue v ) {
+ static void printValue(PrintStream ps, LuaValue v) {
if (v == null) {
ps.print("null");
return;
}
- switch ( v.type() ) {
- case LuaValue.TSTRING: printString( ps, (LuaString) v ); break;
- default: ps.print( v.tojstring() );
-
+ switch (v.type()) {
+ case LuaValue.TSTRING:
+ printString(ps, (LuaString) v);
+ break;
+ default:
+ ps.print(v.tojstring());
+
}
}
-
+
static void printConstant(PrintStream ps, Prototype f, int i) {
- printValue( ps, i < f.k.length ? f.k[i] : LuaValue.valueOf("UNKNOWN_CONST_" + i) );
+ printValue(ps, i < f.k.length? f.k[i]: LuaValue.valueOf("UNKNOWN_CONST_" + i));
}
static void printUpvalue(PrintStream ps, Upvaldesc u) {
- ps.print( u.idx + " " );
- printValue( ps, u.name );
+ ps.print(u.idx + " ");
+ printValue(ps, u.name);
}
- /**
+ /**
* Print the code in a prototype
+ *
* @param f the {@link Prototype}
*/
public static void printCode(Prototype f) {
@@ -161,20 +126,22 @@ public class Print extends Lua {
}
}
- /**
+ /**
* Print an opcode in a prototype
- * @param f the {@link Prototype}
+ *
+ * @param f the {@link Prototype}
* @param pc the program counter to look up and print
* @return pc same as above or changed
*/
public static int printOpCode(Prototype f, int pc) {
- return printOpCode(ps,f,pc);
+ return printOpCode(ps, f, pc);
}
-
- /**
+
+ /**
* Print an opcode in a prototype
+ *
* @param ps the {@link PrintStream} to print to
- * @param f the {@link Prototype}
+ * @param f the {@link Prototype}
* @param pc the program counter to look up and print
* @return pc same as above or changed
*/
@@ -188,33 +155,33 @@ public class Print extends Lua {
int bx = GETARG_Bx(i);
int sbx = GETARG_sBx(i);
int line = getline(f, pc);
- ps.print(" " + (pc + 1) + " ");
+ ps.print(" " + (pc+1) + " ");
if (line > 0)
ps.print("[" + line + "] ");
else
ps.print("[-] ");
- if (o >= OPNAMES.length - 1) {
+ if (o >= OPNAMES.length-1) {
ps.print("UNKNOWN_OP_" + o + " ");
} else {
ps.print(OPNAMES[o] + " ");
switch (getOpMode(o)) {
case iABC:
- ps.print( a );
+ ps.print(a);
if (getBMode(o) != OpArgN)
- ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b));
+ ps.print(" " + (ISK(b)? -1-INDEXK(b): b));
if (getCMode(o) != OpArgN)
- ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c));
+ ps.print(" " + (ISK(c)? -1-INDEXK(c): c));
break;
case iABx:
if (getBMode(o) == OpArgK) {
- ps.print(a + " " + (-1 - bx));
+ ps.print(a + " " + (-1-bx));
} else {
- ps.print(a + " " + (bx));
+ ps.print(a + " " + bx);
}
break;
case iAsBx:
if (o == OP_JMP)
- ps.print( sbx );
+ ps.print(sbx);
else
ps.print(a + " " + sbx);
break;
@@ -231,7 +198,7 @@ public class Print extends Lua {
printUpvalue(ps, f.upvalues[b]);
} else {
ps.print("UNKNOWN_UPVALUE_" + b);
- }
+ }
break;
case OP_GETTABUP:
ps.print(" ; ");
@@ -296,7 +263,7 @@ public class Print extends Lua {
case OP_JMP:
case OP_FORLOOP:
case OP_FORPREP:
- ps.print(" ; to " + (sbx + pc + 2));
+ ps.print(" ; to " + (sbx+pc+2));
break;
case OP_CLOSURE:
if (bx < f.p.length) {
@@ -307,13 +274,13 @@ public class Print extends Lua {
break;
case OP_SETLIST:
if (c == 0)
- ps.print(" ; " + ((int) code[++pc]) + " (stored in the next OP)");
+ ps.print(" ; " + code[++pc] + " (stored in the next OP)");
else
- ps.print(" ; " + ((int) c));
+ ps.print(" ; " + c);
break;
case OP_VARARG:
- ps.print( " ; is_vararg="+ f.is_vararg );
- break;
+ ps.print(" ; is_vararg=" + f.is_vararg);
+ break;
default:
break;
}
@@ -322,7 +289,7 @@ public class Print extends Lua {
}
private static int getline(Prototype f, int pc) {
- return pc>0 && f.lineinfo!=null && pc 0 && f.lineinfo != null && pc < f.lineinfo.length? f.lineinfo[pc]: -1;
}
static void printHeader(Prototype f) {
@@ -333,23 +300,20 @@ public class Print extends Lua {
s = "(bstring)";
else
s = "(string)";
- String a = (f.linedefined == 0) ? "main" : "function";
- ps.print("\n%" + a + " <" + s + ":" + f.linedefined + ","
- + f.lastlinedefined + "> (" + f.code.length + " instructions, "
- + f.code.length * 4 + " bytes at " + id(f) + ")\n");
- ps.print(f.numparams + " param, " + f.maxstacksize + " slot, "
- + f.upvalues.length + " upvalue, ");
- ps.print(f.locvars.length + " local, " + f.k.length
- + " constant, " + f.p.length + " function\n");
+ String a = f.linedefined == 0? "main": "function";
+ ps.print("\n%" + a + " <" + s + ":" + f.linedefined + "," + f.lastlinedefined + "> (" + f.code.length
+ + " instructions, " + f.code.length*4 + " bytes at " + id(f) + ")\n");
+ ps.print(f.numparams + " param, " + f.maxstacksize + " slot, " + f.upvalues.length + " upvalue, ");
+ ps.print(f.locvars.length + " local, " + f.k.length + " constant, " + f.p.length + " function\n");
}
static void printConstants(Prototype f) {
int i, n = f.k.length;
ps.print("constants (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) {
- ps.print(" " + (i + 1) + " ");
- printValue( ps, f.k[i] );
- ps.print( "\n");
+ ps.print(" " + (i+1) + " ");
+ printValue(ps, f.k[i]);
+ ps.print("\n");
}
}
@@ -357,7 +321,8 @@ public class Print extends Lua {
int i, n = f.locvars.length;
ps.print("locals (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) {
- ps.println(" "+i+" "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1));
+ ps.println(
+ " " + i + " " + f.locvars[i].varname + " " + (f.locvars[i].startpc+1) + " " + (f.locvars[i].endpc+1));
}
}
@@ -369,18 +334,20 @@ public class Print extends Lua {
}
}
- /** Pretty-prints contents of a Prototype.
- *
+ /**
+ * Pretty-prints contents of a Prototype.
+ *
* @param prototype Prototype to print.
*/
public static void print(Prototype prototype) {
printFunction(prototype, true);
}
-
- /** Pretty-prints contents of a Prototype in short or long form.
- *
+
+ /**
+ * Pretty-prints contents of a Prototype in short or long form.
+ *
* @param prototype Prototype to print.
- * @param full true to print all fields, false to print short form.
+ * @param full true to print all fields, false to print short form.
*/
public static void printFunction(Prototype prototype, boolean full) {
int i, n = prototype.p.length;
@@ -395,43 +362,45 @@ public class Print extends Lua {
printFunction(prototype.p[i], full);
}
- private static void format( String s, int maxcols ) {
+ private static void format(String s, int maxcols) {
int n = s.length();
- if ( n > maxcols )
- ps.print( s.substring(0,maxcols) );
+ if (n > maxcols)
+ ps.print(s.substring(0, maxcols));
else {
- ps.print( s );
- for ( int i=maxcols-n; --i>=0; )
- ps.print( ' ' );
+ ps.print(s);
+ for (int i = maxcols-n; --i >= 0;)
+ ps.print(' ');
}
}
private static String id(Prototype f) {
return "Proto";
}
+
private void _assert(boolean b) {
- if ( !b )
+ if (!b)
throw new NullPointerException("_assert failed");
}
/**
* Print the state of a {@link LuaClosure} that is being executed
- * @param cl the {@link LuaClosure}
- * @param pc the program counter
- * @param stack the stack of {@link LuaValue}
- * @param top the top of the stack
+ *
+ * @param cl the {@link LuaClosure}
+ * @param pc the program counter
+ * @param stack the stack of {@link LuaValue}
+ * @param top the top of the stack
* @param varargs any {@link Varargs} value that may apply
*/
public static void printState(LuaClosure cl, int pc, LuaValue[] stack, int top, Varargs varargs) {
// print opcode into buffer
PrintStream previous = ps;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ps = new PrintStream( baos );
- printOpCode( cl.p, pc );
+ ps = new PrintStream(baos);
+ printOpCode(cl.p, pc);
ps.flush();
ps.close();
ps = previous;
- format( baos.toString(), 50 );
+ format(baos.toString(), 50);
printStack(stack, top, varargs);
ps.println();
}
@@ -439,38 +408,38 @@ public class Print extends Lua {
public static void printStack(LuaValue[] stack, int top, Varargs varargs) {
// print stack
ps.print('[');
- for ( int i=0; i
+ * This is both a straight translation of the corresponding C type, and the main
+ * data structure for execution of compiled lua bytecode.
+ *
+ *
+ * Generally, the {@link Prototype} is not constructed directly is an
+ * intermediate result as lua code is loaded using
+ * {@link Globals#load(java.io.Reader, String)}:
+ *
+ *
+ *
+ * To un-dump a binary file known to be a binary lua file that has been dumped
+ * to a string, the {@link Globals.Undumper} interface may be used:
+ *
+ *
+ * {
+ * @code
+ * FileInputStream lua_binary_file = new FileInputStream("foo.lc"); // Known to be compiled lua.
+ * Prototype p = globals.undumper.undump(lua_binary_file, "foo.lua");
+ * }
+ *
+ *
+ * To execute the code represented by the {@link Prototype} it must be supplied
+ * to the constructor of a {@link LuaClosure}:
+ *
+ *
+ *
+ * To simplify the debugging of prototype values, the contents may be printed
+ * using {@link Print#print}:
+ *
+ *
+ * {@code
+ * Print.print(p);
+ * }
+ *
+ *
+ *
+ * @see LuaClosure
+ * @see Globals
+ * @see Globals#undumper
+ * @see Globals#compiler
+ * @see Print#print
+ */
+
+public class Prototype {
+ /* constants used by the function */
+ public LuaValue[] k;
+ public int[] code;
+ /* functions defined inside the function */
+ public Prototype[] p;
+ /* map from opcodes to source lines */
+ public int[] lineinfo;
+ /* information about local variables */
+ public LocVars[] locvars;
+ /* upvalue information */
+ public Upvaldesc[] upvalues;
+ public LuaString source;
+ public int linedefined;
+ public int lastlinedefined;
+ public int numparams;
+ public int is_vararg;
+ public int maxstacksize;
+ private static final Upvaldesc[] NOUPVALUES = {};
+ private static final Prototype[] NOSUBPROTOS = {};
+
+ public Prototype() {
+ p = NOSUBPROTOS;
+ upvalues = NOUPVALUES;
+ }
+
+ public Prototype(int n_upvalues) {
+ p = NOSUBPROTOS;
+ upvalues = new Upvaldesc[n_upvalues];
+ }
+
+ @Override
+ public String toString() {
+ return source + ":" + linedefined + "-" + lastlinedefined;
+ }
+
+ /**
+ * Get the name of a local variable.
+ *
+ * @param number the local variable number to look up
+ * @param pc the program counter
+ * @return the name, or null if not found
+ */
+ public LuaString getlocalname(int number, int pc) {
+ int i;
+ for (i = 0; i < locvars.length && locvars[i].startpc <= pc; i++) {
+ if (pc < locvars[i].endpc) { /* is variable active? */
+ number--;
+ if (number == 0)
+ return locvars[i].varname;
+ }
+ }
+ return null; /* not found */
+ }
+
+ public String shortsource() {
+ String name = source.tojstring();
+ if (name.startsWith("@") || name.startsWith("="))
+ name = name.substring(1);
+ else if (name.startsWith("\033"))
+ name = "binary string";
+ return name;
+ }
+}
diff --git a/src/core/org/luaj/vm2/TailcallVarargs.java b/luaj-core/src/main/java/org/luaj/vm2/TailcallVarargs.java
similarity index 73%
rename from src/core/org/luaj/vm2/TailcallVarargs.java
rename to luaj-core/src/main/java/org/luaj/vm2/TailcallVarargs.java
index 69eebc5b..bdd9e914 100644
--- a/src/core/org/luaj/vm2/TailcallVarargs.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/TailcallVarargs.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,44 +22,43 @@
package org.luaj.vm2;
/**
- * Subclass of {@link Varargs} that represents a lua tail call
- * in a Java library function execution environment.
+ * Subclass of {@link Varargs} that represents a lua tail call in a Java library
+ * function execution environment.
*
- * Since Java doesn't have direct support for tail calls,
- * any lua function whose {@link Prototype} contains the
- * {@link Lua#OP_TAILCALL} bytecode needs a mechanism
- * for tail calls when converting lua-bytecode to java-bytecode.
+ * Since Java doesn't have direct support for tail calls, any lua function whose
+ * {@link Prototype} contains the {@link Lua#OP_TAILCALL} bytecode needs a
+ * mechanism for tail calls when converting lua-bytecode to java-bytecode.
*
- * The tail call holds the next function and arguments,
- * and the client a call to {@link #eval()} executes the function
- * repeatedly until the tail calls are completed.
+ * The tail call holds the next function and arguments, and the client a call to
+ * {@link #eval()} executes the function repeatedly until the tail calls are
+ * completed.
*
- * Normally, users of luaj need not concern themselves with the
- * details of this mechanism, as it is built into the core
- * execution framework.
- * @see Prototype
+ * Normally, users of luaj need not concern themselves with the details of this
+ * mechanism, as it is built into the core execution framework.
+ *
+ * @see Prototype
* @see org.luaj.vm2.luajc.LuaJC
*/
public class TailcallVarargs extends Varargs {
private LuaValue func;
- private Varargs args;
- private Varargs result;
-
+ private Varargs args;
+ private Varargs result;
+
public TailcallVarargs(LuaValue f, Varargs args) {
this.func = f;
this.args = args;
}
-
+
public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) {
this.func = object.get(methodname);
this.args = LuaValue.varargsOf(object, args);
}
-
- public boolean isTailcall() {
- return true;
- }
-
+
+ @Override
+ public boolean isTailcall() { return true; }
+
+ @Override
public Varargs eval() {
while ( result == null ) {
Varargs r = func.onInvoke(args);
@@ -67,37 +66,40 @@ public class TailcallVarargs extends Varargs {
TailcallVarargs t = (TailcallVarargs) r;
func = t.func;
args = t.args;
- }
- else {
- result = r;
+ } else {
+ result = r;
func = null;
args = null;
}
}
return result;
}
-
- public LuaValue arg( int i ) {
- if ( result == null )
+
+ @Override
+ public LuaValue arg(int i) {
+ if (result == null)
eval();
return result.arg(i);
}
-
+
+ @Override
public LuaValue arg1() {
if (result == null)
eval();
return result.arg1();
}
-
+
+ @Override
public int narg() {
if (result == null)
eval();
return result.narg();
}
+ @Override
public Varargs subargs(int start) {
if (result == null)
eval();
return result.subargs(start);
}
-}
\ No newline at end of file
+}
diff --git a/src/core/org/luaj/vm2/UpValue.java b/luaj-core/src/main/java/org/luaj/vm2/UpValue.java
similarity index 84%
rename from src/core/org/luaj/vm2/UpValue.java
rename to luaj-core/src/main/java/org/luaj/vm2/UpValue.java
index 8fa8186b..3e746974 100644
--- a/src/core/org/luaj/vm2/UpValue.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/UpValue.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,60 +21,62 @@
******************************************************************************/
package org.luaj.vm2;
-
-/** Upvalue used with Closure formulation
+/**
+ * Upvalue used with Closure formulation
*
+ *
* @see LuaClosure
* @see Prototype
*/
public final class UpValue {
- LuaValue[] array; // initially the stack, becomes a holder
- int index;
+ LuaValue[] array; // initially the stack, becomes a holder
+ int index;
/**
- * Create an upvalue relative to a stack
+ * Create an upvalue relative to a stack
+ *
* @param stack the stack
* @param index the index on the stack for the upvalue
*/
- public UpValue( LuaValue[] stack, int index) {
+ public UpValue(LuaValue[] stack, int index) {
this.array = stack;
this.index = index;
}
+ @Override
public String toString() {
return index + "/" + array.length + " " + array[index];
}
-
- /**
+
+ /**
* Convert this upvalue to a Java String
+ *
* @return the Java String for this upvalue.
* @see LuaValue#tojstring()
*/
public String tojstring() {
return array[index].tojstring();
}
-
+
/**
* Get the value of the upvalue
+ *
* @return the {@link LuaValue} for this upvalue
*/
- public final LuaValue getValue() {
- return array[index];
- }
-
+ public LuaValue getValue() { return array[index]; }
+
/**
* Set the value of the upvalue
+ *
* @param value the {@link LuaValue} to set it to
*/
- public final void setValue( LuaValue value ) {
- array[index] = value;
- }
-
+ public void setValue(LuaValue value) { array[index] = value; }
+
/**
* Close this upvalue so it is no longer on the stack
*/
- public final void close() {
+ public void close() {
LuaValue[] old = array;
array = new LuaValue[] { old[index] };
old[index] = null;
diff --git a/src/core/org/luaj/vm2/Upvaldesc.java b/luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java
similarity index 95%
rename from src/core/org/luaj/vm2/Upvaldesc.java
rename to luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java
index c1e44974..26233892 100644
--- a/src/core/org/luaj/vm2/Upvaldesc.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,20 +25,21 @@ public class Upvaldesc {
/* upvalue name (for debug information) */
public LuaString name;
-
+
/* whether it is in stack */
public final boolean instack;
-
+
/* index of upvalue (in stack or in outer function's list) */
public final short idx;
-
+
public Upvaldesc(LuaString name, boolean instack, int idx) {
this.name = name;
this.instack = instack;
this.idx = (short) idx;
}
-
+
+ @Override
public String toString() {
- return idx + (instack? " instack ": " closed ") + String.valueOf(name);
+ return idx+(instack? " instack ": " closed ")+String.valueOf(name);
}
}
diff --git a/src/core/org/luaj/vm2/Varargs.java b/luaj-core/src/main/java/org/luaj/vm2/Varargs.java
similarity index 52%
rename from src/core/org/luaj/vm2/Varargs.java
rename to luaj-core/src/main/java/org/luaj/vm2/Varargs.java
index e56d8dcf..2d4b92cb 100644
--- a/src/core/org/luaj/vm2/Varargs.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/Varargs.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,21 +22,23 @@
package org.luaj.vm2;
/**
- * Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
+ * Class to encapsulate varargs values, either as part of a variable argument
+ * list, or multiple return values.
*
* To construct varargs, use one of the static methods such as
* {@code LuaValue.varargsOf(LuaValue,LuaValue)}
*
*
- * Any LuaValue can be used as a stand-in for Varargs, for both calls and return values.
- * When doing so, nargs() will return 1 and arg1() or arg(1) will return this.
- * This simplifies the case when calling or implementing varargs functions with only
- * 1 argument or 1 return value.
+ * Any LuaValue can be used as a stand-in for Varargs, for both calls and return
+ * values. When doing so, nargs() will return 1 and arg1() or arg(1) will return
+ * this. This simplifies the case when calling or implementing varargs functions
+ * with only 1 argument or 1 return value.
*
- * Varargs can also be derived from other varargs by appending to the front with a call
- * such as {@code LuaValue.varargsOf(LuaValue,Varargs)}
- * or by taking a portion of the args using {@code Varargs.subargs(int start)}
+ * Varargs can also be derived from other varargs by appending to the front with
+ * a call such as {@code LuaValue.varargsOf(LuaValue,Varargs)} or by taking a
+ * portion of the args using {@code Varargs.subargs(int start)}
*
+ *
* @see LuaValue#varargsOf(LuaValue[])
* @see LuaValue#varargsOf(LuaValue, Varargs)
* @see LuaValue#varargsOf(LuaValue[], Varargs)
@@ -49,22 +51,26 @@ public abstract class Varargs {
/**
* Get the n-th argument value (1-based).
+ *
* @param i the index of the argument to get, 1 is the first argument
* @return Value at position i, or LuaValue.NIL if there is none.
* @see Varargs#arg1()
* @see LuaValue#NIL
*/
- abstract public LuaValue arg( int i );
-
+ abstract public LuaValue arg(int i);
+
/**
* Get the number of arguments, or 0 if there are none.
+ *
* @return number of arguments.
*/
abstract public int narg();
-
+
/**
* Get the first argument in the list.
- * @return LuaValue which is first in the list, or LuaValue.NIL if there are no values.
+ *
+ * @return LuaValue which is first in the list, or LuaValue.NIL if there are
+ * no values.
* @see Varargs#arg(int)
* @see LuaValue#NIL
*/
@@ -72,25 +78,28 @@ public abstract class Varargs {
/**
* Evaluate any pending tail call and return result.
+ *
* @return the evaluated tail call result
*/
public Varargs eval() { return this; }
-
+
/**
* Return true if this is a TailcallVarargs
+ *
* @return true if a tail call, false otherwise
*/
- public boolean isTailcall() {
- return false;
- }
-
+ public boolean isTailcall() { return false; }
+
// -----------------------------------------------------------------------
// utilities to get specific arguments and type-check them.
// -----------------------------------------------------------------------
-
- /** Gets the type of argument {@code i}
+
+ /**
+ * Gets the type of argument {@code i}
+ *
* @param i the index of the argument to convert, 1 is the first argument
- * @return int value corresponding to one of the LuaValue integer type values
+ * @return int value corresponding to one of the LuaValue integer type
+ * values
* @see LuaValue#TNIL
* @see LuaValue#TBOOLEAN
* @see LuaValue#TNUMBER
@@ -99,438 +108,626 @@ public abstract class Varargs {
* @see LuaValue#TFUNCTION
* @see LuaValue#TUSERDATA
* @see LuaValue#TTHREAD
- * */
- public int type(int i) { return arg(i).type(); }
-
- /** Tests if argument i is nil.
+ */
+ public int type(int i) { return arg(i).type(); }
+
+ /**
+ * Tests if argument i is nil.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if the argument is nil or does not exist, false otherwise
* @see LuaValue#TNIL
- * */
- public boolean isnil(int i) { return arg(i).isnil(); }
+ */
+ public boolean isnil(int i) { return arg(i).isnil(); }
- /** Tests if argument i is a function.
+ /**
+ * Tests if argument i is a function.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return true if the argument exists and is a function or closure, false otherwise
+ * @return true if the argument exists and is a function or closure, false
+ * otherwise
* @see LuaValue#TFUNCTION
- * */
- public boolean isfunction(int i) { return arg(i).isfunction(); }
+ */
+ public boolean isfunction(int i) { return arg(i).isfunction(); }
- /** Tests if argument i is a number.
- * Since anywhere a number is required, a string can be used that
- * is a number, this will return true for both numbers and
- * strings that can be interpreted as numbers.
+ /**
+ * Tests if argument i is a number. Since anywhere a number is required, a
+ * string can be used that is a number, this will return true for both
+ * numbers and strings that can be interpreted as numbers.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return true if the argument exists and is a number or
- * string that can be interpreted as a number, false otherwise
+ * @return true if the argument exists and is a number or string that can be
+ * interpreted as a number, false otherwise
* @see LuaValue#TNUMBER
* @see LuaValue#TSTRING
- * */
- public boolean isnumber(int i) { return arg(i).isnumber(); }
+ */
+ public boolean isnumber(int i) { return arg(i).isnumber(); }
- /** Tests if argument i is a string.
- * Since all lua numbers can be used where strings are used,
- * this will return true for both strings and numbers.
+ /**
+ * Tests if argument i is a string. Since all lua numbers can be used where
+ * strings are used, this will return true for both strings and numbers.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return true if the argument exists and is a string or number, false otherwise
+ * @return true if the argument exists and is a string or number, false
+ * otherwise
* @see LuaValue#TNUMBER
* @see LuaValue#TSTRING
- * */
- public boolean isstring(int i) { return arg(i).isstring(); }
+ */
+ public boolean isstring(int i) { return arg(i).isstring(); }
- /** Tests if argument i is a table.
+ /**
+ * Tests if argument i is a table.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if the argument exists and is a lua table, false otherwise
* @see LuaValue#TTABLE
- * */
- public boolean istable(int i) { return arg(i).istable(); }
+ */
+ public boolean istable(int i) { return arg(i).istable(); }
- /** Tests if argument i is a thread.
+ /**
+ * Tests if argument i is a thread.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if the argument exists and is a lua thread, false otherwise
* @see LuaValue#TTHREAD
- * */
- public boolean isthread(int i) { return arg(i).isthread(); }
+ */
+ public boolean isthread(int i) { return arg(i).isthread(); }
- /** Tests if argument i is a userdata.
+ /**
+ * Tests if argument i is a userdata.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if the argument exists and is a userdata, false otherwise
* @see LuaValue#TUSERDATA
- * */
- public boolean isuserdata(int i) { return arg(i).isuserdata(); }
+ */
+ public boolean isuserdata(int i) { return arg(i).isuserdata(); }
- /** Tests if a value exists at argument i.
+ /**
+ * Tests if a value exists at argument i.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if the argument exists, false otherwise
- * */
- public boolean isvalue(int i) { return i>0 && i<=narg(); }
-
- /** Return argument i as a boolean value, {@code defval} if nil, or throw a LuaError if any other type.
+ */
+ public boolean isvalue(int i) { return i > 0 && i <= narg(); }
+
+ /**
+ * Return argument i as a boolean value, {@code defval} if nil, or throw a
+ * LuaError if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return true if argument i is boolean true, false if it is false, or defval if not supplied or nil
+ * @return true if argument i is boolean true, false if it is false, or
+ * defval if not supplied or nil
* @exception LuaError if the argument is not a lua boolean
- * */
- public boolean optboolean(int i, boolean defval) { return arg(i).optboolean(defval); }
+ */
+ public boolean optboolean(int i, boolean defval) { return arg(i).optboolean(defval); }
- /** Return argument i as a closure, {@code defval} if nil, or throw a LuaError if any other type.
+ /**
+ * Return argument i as a closure, {@code defval} if nil, or throw a
+ * LuaError if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return LuaClosure if argument i is a closure, or defval if not supplied or nil
+ * @return LuaClosure if argument i is a closure, or defval if not supplied
+ * or nil
* @exception LuaError if the argument is not a lua closure
- * */
- public LuaClosure optclosure(int i, LuaClosure defval) { return arg(i).optclosure(defval); }
+ */
+ public LuaClosure optclosure(int i, LuaClosure defval) { return arg(i).optclosure(defval); }
- /** Return argument i as a double, {@code defval} if nil, or throw a LuaError if it cannot be converted to one.
+ /**
+ * Return argument i as a double, {@code defval} if nil, or throw a LuaError
+ * if it cannot be converted to one.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return java double value if argument i is a number or string that converts to a number, or defval if not supplied or nil
+ * @return java double value if argument i is a number or string that
+ * converts to a number, or defval if not supplied or nil
* @exception LuaError if the argument is not a number
- * */
- public double optdouble(int i, double defval) { return arg(i).optdouble(defval); }
+ */
+ public double optdouble(int i, double defval) { return arg(i).optdouble(defval); }
- /** Return argument i as a function, {@code defval} if nil, or throw a LuaError if an incompatible type.
+ /**
+ * Return argument i as a function, {@code defval} if nil, or throw a
+ * LuaError if an incompatible type.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return LuaValue that can be called if argument i is lua function or closure, or defval if not supplied or nil
+ * @return LuaValue that can be called if argument i is lua function or
+ * closure, or defval if not supplied or nil
* @exception LuaError if the argument is not a lua function or closure
- * */
- public LuaFunction optfunction(int i, LuaFunction defval) { return arg(i).optfunction(defval); }
+ */
+ public LuaFunction optfunction(int i, LuaFunction defval) { return arg(i).optfunction(defval); }
- /** Return argument i as a java int value, discarding any fractional part, {@code defval} if nil, or throw a LuaError if not a number.
+ /**
+ * Return argument i as a java int value, discarding any fractional part,
+ * {@code defval} if nil, or throw a LuaError if not a number.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return int value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil
+ * @return int value with fraction discarded and truncated if necessary if
+ * argument i is number, or defval if not supplied or nil
* @exception LuaError if the argument is not a number
- * */
- public int optint(int i, int defval) { return arg(i).optint(defval); }
+ */
+ public int optint(int i, int defval) { return arg(i).optint(defval); }
- /** Return argument i as a java int value, {@code defval} if nil, or throw a LuaError if not a number or is not representable by a java int.
+ /**
+ * Return argument i as a java int value, {@code defval} if nil, or throw a
+ * LuaError if not a number or is not representable by a java int.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return LuaInteger value that fits in a java int without rounding, or defval if not supplied or nil
- * @exception LuaError if the argument cannot be represented by a java int value
- * */
- public LuaInteger optinteger(int i, LuaInteger defval) { return arg(i).optinteger(defval); }
+ * @return LuaInteger value that fits in a java int without rounding, or
+ * defval if not supplied or nil
+ * @exception LuaError if the argument cannot be represented by a java int
+ * value
+ */
+ public LuaInteger optinteger(int i, LuaInteger defval) { return arg(i).optinteger(defval); }
- /** Return argument i as a java long value, discarding any fractional part, {@code defval} if nil, or throw a LuaError if not a number.
+ /**
+ * Return argument i as a java long value, discarding any fractional part,
+ * {@code defval} if nil, or throw a LuaError if not a number.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return long value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil
+ * @return long value with fraction discarded and truncated if necessary if
+ * argument i is number, or defval if not supplied or nil
* @exception LuaError if the argument is not a number
- * */
- public long optlong(int i, long defval) { return arg(i).optlong(defval); }
+ */
+ public long optlong(int i, long defval) { return arg(i).optlong(defval); }
- /** Return argument i as a LuaNumber, {@code defval} if nil, or throw a LuaError if not a number or string that can be converted to a number.
- * @param i the index of the argument to test, 1 is the first argument, or defval if not supplied or nil
+ /**
+ * Return argument i as a LuaNumber, {@code defval} if nil, or throw a
+ * LuaError if not a number or string that can be converted to a number.
+ *
+ * @param i the index of the argument to test, 1 is the first argument, or
+ * defval if not supplied or nil
* @return LuaNumber if argument i is number or can be converted to a number
* @exception LuaError if the argument is not a number
- * */
- public LuaNumber optnumber(int i, LuaNumber defval) { return arg(i).optnumber(defval); }
+ */
+ public LuaNumber optnumber(int i, LuaNumber defval) { return arg(i).optnumber(defval); }
- /** Return argument i as a java String if a string or number, {@code defval} if nil, or throw a LuaError if any other type
+ /**
+ * Return argument i as a java String if a string or number, {@code defval}
+ * if nil, or throw a LuaError if any other type
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return String value if argument i is a string or number, or defval if not supplied or nil
+ * @return String value if argument i is a string or number, or defval if
+ * not supplied or nil
* @exception LuaError if the argument is not a string or number
- * */
- public String optjstring(int i, String defval) { return arg(i).optjstring(defval); }
+ */
+ public String optjstring(int i, String defval) { return arg(i).optjstring(defval); }
- /** Return argument i as a LuaString if a string or number, {@code defval} if nil, or throw a LuaError if any other type
+ /**
+ * Return argument i as a LuaString if a string or number, {@code defval} if
+ * nil, or throw a LuaError if any other type
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return LuaString value if argument i is a string or number, or defval if not supplied or nil
+ * @return LuaString value if argument i is a string or number, or defval if
+ * not supplied or nil
* @exception LuaError if the argument is not a string or number
- * */
- public LuaString optstring(int i, LuaString defval) { return arg(i).optstring(defval); }
+ */
+ public LuaString optstring(int i, LuaString defval) { return arg(i).optstring(defval); }
- /** Return argument i as a LuaTable if a lua table, {@code defval} if nil, or throw a LuaError if any other type.
+ /**
+ * Return argument i as a LuaTable if a lua table, {@code defval} if nil, or
+ * throw a LuaError if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaTable value if a table, or defval if not supplied or nil
* @exception LuaError if the argument is not a lua table
- * */
- public LuaTable opttable(int i, LuaTable defval) { return arg(i).opttable(defval); }
+ */
+ public LuaTable opttable(int i, LuaTable defval) { return arg(i).opttable(defval); }
- /** Return argument i as a LuaThread if a lua thread, {@code defval} if nil, or throw a LuaError if any other type.
+ /**
+ * Return argument i as a LuaThread if a lua thread, {@code defval} if nil,
+ * or throw a LuaError if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaThread value if a thread, or defval if not supplied or nil
* @exception LuaError if the argument is not a lua thread
- * */
- public LuaThread optthread(int i, LuaThread defval) { return arg(i).optthread(defval); }
+ */
+ public LuaThread optthread(int i, LuaThread defval) { return arg(i).optthread(defval); }
- /** Return argument i as a java Object if a userdata, {@code defval} if nil, or throw a LuaError if any other type.
+ /**
+ * Return argument i as a java Object if a userdata, {@code defval} if nil,
+ * or throw a LuaError if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return java Object value if argument i is a userdata, or defval if not supplied or nil
+ * @return java Object value if argument i is a userdata, or defval if not
+ * supplied or nil
* @exception LuaError if the argument is not a userdata
- * */
- public Object optuserdata(int i, Object defval) { return arg(i).optuserdata(defval); }
+ */
+ public Object optuserdata(int i, Object defval) { return arg(i).optuserdata(defval); }
- /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
- * {@code defval} if nil, or throw a LuaError if any other type.
+ /**
+ * Return argument i as a java Object if it is a userdata whose instance
+ * Class c or a subclass, {@code defval} if nil, or throw a LuaError if any
+ * other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @param c the class to which the userdata instance must be assignable
- * @return java Object value if argument i is a userdata whose instance Class c or a subclass, or defval if not supplied or nil
- * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable
- * */
- public Object optuserdata(int i, Class c, Object defval) { return arg(i).optuserdata(c,defval); }
+ * @return java Object value if argument i is a userdata whose instance
+ * Class c or a subclass, or defval if not supplied or nil
+ * @exception LuaError if the argument is not a userdata or from whose
+ * instance c is not assignable
+ */
+ public Object optuserdata(int i, Class c, Object defval) { return arg(i).optuserdata(c, defval); }
- /** Return argument i as a LuaValue if it exists, or {@code defval}.
+ /**
+ * Return argument i as a LuaValue if it exists, or {@code defval}.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaValue value if the argument exists, defval if not
* @exception LuaError if the argument does not exist.
- * */
- public LuaValue optvalue(int i, LuaValue defval) { return i>0 && i<=narg()? arg(i): defval; }
+ */
+ public LuaValue optvalue(int i, LuaValue defval) { return i > 0 && i <= narg()? arg(i): defval; }
- /** Return argument i as a boolean value, or throw an error if any other type.
+ /**
+ * Return argument i as a boolean value, or throw an error if any other
+ * type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if argument i is boolean true, false if it is false
* @exception LuaError if the argument is not a lua boolean
- * */
- public boolean checkboolean(int i) { return arg(i).checkboolean(); }
+ */
+ public boolean checkboolean(int i) { return arg(i).checkboolean(); }
- /** Return argument i as a closure, or throw an error if any other type.
+ /**
+ * Return argument i as a closure, or throw an error if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaClosure if argument i is a closure.
* @exception LuaError if the argument is not a lua closure
- * */
- public LuaClosure checkclosure(int i) { return arg(i).checkclosure(); }
+ */
+ public LuaClosure checkclosure(int i) { return arg(i).checkclosure(); }
- /** Return argument i as a double, or throw an error if it cannot be converted to one.
+ /**
+ * Return argument i as a double, or throw an error if it cannot be
+ * converted to one.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return java double value if argument i is a number or string that converts to a number
+ * @return java double value if argument i is a number or string that
+ * converts to a number
* @exception LuaError if the argument is not a number
- * */
- public double checkdouble(int i) { return arg(i).checkdouble(); }
+ */
+ public double checkdouble(int i) { return arg(i).checkdouble(); }
- /** Return argument i as a function, or throw an error if an incompatible type.
+ /**
+ * Return argument i as a function, or throw an error if an incompatible
+ * type.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return LuaValue that can be called if argument i is lua function or closure
+ * @return LuaValue that can be called if argument i is lua function or
+ * closure
* @exception LuaError if the argument is not a lua function or closure
- * */
- public LuaFunction checkfunction(int i) { return arg(i).checkfunction(); }
+ */
+ public LuaFunction checkfunction(int i) { return arg(i).checkfunction(); }
- /** Return argument i as a java int value, or throw an error if it cannot be converted to one.
+ /**
+ * Return argument i as a java int value, or throw an error if it cannot be
+ * converted to one.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return int value if argument i is a number or string that converts to a number
- * @exception LuaError if the argument cannot be represented by a java int value
- * */
- public int checkint(int i) { return arg(i).checkint(); }
+ * @return int value if argument i is a number or string that converts to a
+ * number
+ * @exception LuaError if the argument cannot be represented by a java int
+ * value
+ */
+ public int checkint(int i) { return arg(i).checkint(); }
- /** Return argument i as a java int value, or throw an error if not a number or is not representable by a java int.
+ /**
+ * Return argument i as a java int value, or throw an error if not a number
+ * or is not representable by a java int.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaInteger value that fits in a java int without rounding
- * @exception LuaError if the argument cannot be represented by a java int value
- * */
- public LuaInteger checkinteger(int i) { return arg(i).checkinteger(); }
+ * @exception LuaError if the argument cannot be represented by a java int
+ * value
+ */
+ public LuaInteger checkinteger(int i) { return arg(i).checkinteger(); }
- /** Return argument i as a java long value, or throw an error if it cannot be converted to one.
+ /**
+ * Return argument i as a java long value, or throw an error if it cannot be
+ * converted to one.
+ *
* @param i the index of the argument to test, 1 is the first argument
- * @return long value if argument i is a number or string that converts to a number
- * @exception LuaError if the argument cannot be represented by a java long value
- * */
- public long checklong(int i) { return arg(i).checklong(); }
+ * @return long value if argument i is a number or string that converts to a
+ * number
+ * @exception LuaError if the argument cannot be represented by a java long
+ * value
+ */
+ public long checklong(int i) { return arg(i).checklong(); }
- /** Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number.
+ /**
+ * Return argument i as a LuaNumber, or throw an error if not a number or
+ * string that can be converted to a number.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaNumber if argument i is number or can be converted to a number
* @exception LuaError if the argument is not a number
- * */
- public LuaNumber checknumber(int i) { return arg(i).checknumber(); }
+ */
+ public LuaNumber checknumber(int i) { return arg(i).checknumber(); }
- /** Return argument i as a java String if a string or number, or throw an error if any other type
+ /**
+ * Return argument i as a java String if a string or number, or throw an
+ * error if any other type
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return String value if argument i is a string or number
* @exception LuaError if the argument is not a string or number
- * */
- public String checkjstring(int i) { return arg(i).checkjstring(); }
+ */
+ public String checkjstring(int i) { return arg(i).checkjstring(); }
- /** Return argument i as a LuaString if a string or number, or throw an error if any other type
+ /**
+ * Return argument i as a LuaString if a string or number, or throw an error
+ * if any other type
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaString value if argument i is a string or number
* @exception LuaError if the argument is not a string or number
- * */
- public LuaString checkstring(int i) { return arg(i).checkstring(); }
+ */
+ public LuaString checkstring(int i) { return arg(i).checkstring(); }
- /** Return argument i as a LuaTable if a lua table, or throw an error if any other type.
+ /**
+ * Return argument i as a LuaTable if a lua table, or throw an error if any
+ * other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaTable value if a table
* @exception LuaError if the argument is not a lua table
- * */
- public LuaTable checktable(int i) { return arg(i).checktable(); }
+ */
+ public LuaTable checktable(int i) { return arg(i).checktable(); }
- /** Return argument i as a LuaThread if a lua thread, or throw an error if any other type.
+ /**
+ * Return argument i as a LuaThread if a lua thread, or throw an error if
+ * any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaThread value if a thread
* @exception LuaError if the argument is not a lua thread
- * */
- public LuaThread checkthread(int i) { return arg(i).checkthread(); }
+ */
+ public LuaThread checkthread(int i) { return arg(i).checkthread(); }
- /** Return argument i as a java Object if a userdata, or throw an error if any other type.
+ /**
+ * Return argument i as a java Object if a userdata, or throw an error if
+ * any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return java Object value if argument i is a userdata
* @exception LuaError if the argument is not a userdata
- * */
- public Object checkuserdata(int i) { return arg(i).checkuserdata(); }
+ */
+ public Object checkuserdata(int i) { return arg(i).checkuserdata(); }
- /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
- * or throw an error if any other type.
+ /**
+ * Return argument i as a java Object if it is a userdata whose instance
+ * Class c or a subclass, or throw an error if any other type.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @param c the class to which the userdata instance must be assignable
- * @return java Object value if argument i is a userdata whose instance Class c or a subclass
- * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable
- * */
- public Object checkuserdata(int i,Class c) { return arg(i).checkuserdata(c); }
+ * @return java Object value if argument i is a userdata whose instance
+ * Class c or a subclass
+ * @exception LuaError if the argument is not a userdata or from whose
+ * instance c is not assignable
+ */
+ public Object checkuserdata(int i, Class c) { return arg(i).checkuserdata(c); }
- /** Return argument i as a LuaValue if it exists, or throw an error.
+ /**
+ * Return argument i as a LuaValue if it exists, or throw an error.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaValue value if the argument exists
* @exception LuaError if the argument does not exist.
- * */
- public LuaValue checkvalue(int i) { return i<=narg()? arg(i): LuaValue.argerror(i,"value expected"); }
+ */
+ public LuaValue checkvalue(int i) { return i <= narg()? arg(i): LuaValue.argerror(i, "value expected"); }
- /** Return argument i as a LuaValue if it is not nil, or throw an error if it is nil.
+ /**
+ * Return argument i as a LuaValue if it is not nil, or throw an error if it
+ * is nil.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return LuaValue value if the argument is not nil
* @exception LuaError if the argument doesn't exist or evaluates to nil.
- * */
- public LuaValue checknotnil(int i) { return arg(i).checknotnil(); }
-
- /** Performs test on argument i as a LuaValue when a user-supplied assertion passes, or throw an error.
- * Returns normally if the value of {@code test} is {@code true}, otherwise throws and argument error with
- * the supplied message, {@code msg}.
+ */
+ public LuaValue checknotnil(int i) { return arg(i).checknotnil(); }
+
+ /**
+ * Performs test on argument i as a LuaValue when a user-supplied assertion
+ * passes, or throw an error. Returns normally if the value of {@code test}
+ * is {@code true}, otherwise throws and argument error with the supplied
+ * message, {@code msg}.
+ *
* @param test user supplied assertion to test against
- * @param i the index to report in any error message
- * @param msg the error message to use when the test fails
+ * @param i the index to report in any error message
+ * @param msg the error message to use when the test fails
* @exception LuaError if the the value of {@code test} is {@code false}
- * */
- public void argcheck(boolean test, int i, String msg) { if (!test) LuaValue.argerror(i,msg); }
-
- /** Return true if there is no argument or nil at argument i.
+ */
+ public void argcheck(boolean test, int i, String msg) {
+ if (!test)
+ LuaValue.argerror(i, msg);
+ }
+
+ /**
+ * Return true if there is no argument or nil at argument i.
+ *
* @param i the index of the argument to test, 1 is the first argument
* @return true if argument i contains either no argument or nil
- * */
+ */
public boolean isnoneornil(int i) {
- return i>narg() || arg(i).isnil();
+ return i > narg() || arg(i).isnil();
}
-
- /** Convert argument {@code i} to java boolean based on lua rules for boolean evaluation.
- * @param i the index of the argument to convert, 1 is the first argument
- * @return {@code false} if argument i is nil or false, otherwise {@code true}
- * */
- public boolean toboolean(int i) { return arg(i).toboolean(); }
- /** Return argument i as a java byte value, discarding any fractional part and truncating,
- * or 0 if not a number.
+ /**
+ * Convert argument {@code i} to java boolean based on lua rules for boolean
+ * evaluation.
+ *
* @param i the index of the argument to convert, 1 is the first argument
- * @return byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
- * */
- public byte tobyte(int i) { return arg(i).tobyte(); }
-
- /** Return argument i as a java char value, discarding any fractional part and truncating,
- * or 0 if not a number.
- * @param i the index of the argument to convert, 1 is the first argument
- * @return char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
- * */
- public char tochar(int i) { return arg(i).tochar(); }
+ * @return {@code false} if argument i is nil or false, otherwise
+ * {@code true}
+ */
+ public boolean toboolean(int i) { return arg(i).toboolean(); }
- /** Return argument i as a java double value or 0 if not a number.
+ /**
+ * Return argument i as a java byte value, discarding any fractional part
+ * and truncating, or 0 if not a number.
+ *
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return byte value with fraction discarded and truncated if necessary if
+ * argument i is number, otherwise 0
+ */
+ public byte tobyte(int i) { return arg(i).tobyte(); }
+
+ /**
+ * Return argument i as a java char value, discarding any fractional part
+ * and truncating, or 0 if not a number.
+ *
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return char value with fraction discarded and truncated if necessary if
+ * argument i is number, otherwise 0
+ */
+ public char tochar(int i) { return arg(i).tochar(); }
+
+ /**
+ * Return argument i as a java double value or 0 if not a number.
+ *
* @param i the index of the argument to convert, 1 is the first argument
* @return double value if argument i is number, otherwise 0
- * */
- public double todouble(int i) { return arg(i).todouble(); }
+ */
+ public double todouble(int i) { return arg(i).todouble(); }
- /** Return argument i as a java float value, discarding excess fractional part and truncating,
- * or 0 if not a number.
+ /**
+ * Return argument i as a java float value, discarding excess fractional
+ * part and truncating, or 0 if not a number.
+ *
* @param i the index of the argument to convert, 1 is the first argument
- * @return float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0
- * */
- public float tofloat(int i) { return arg(i).tofloat(); }
-
- /** Return argument i as a java int value, discarding any fractional part and truncating,
- * or 0 if not a number.
- * @param i the index of the argument to convert, 1 is the first argument
- * @return int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
- * */
- public int toint(int i) { return arg(i).toint(); }
+ * @return float value with excess fraction discarded and truncated if
+ * necessary if argument i is number, otherwise 0
+ */
+ public float tofloat(int i) { return arg(i).tofloat(); }
- /** Return argument i as a java long value, discarding any fractional part and truncating,
- * or 0 if not a number.
+ /**
+ * Return argument i as a java int value, discarding any fractional part and
+ * truncating, or 0 if not a number.
+ *
* @param i the index of the argument to convert, 1 is the first argument
- * @return long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
- * */
- public long tolong(int i) { return arg(i).tolong(); }
+ * @return int value with fraction discarded and truncated if necessary if
+ * argument i is number, otherwise 0
+ */
+ public int toint(int i) { return arg(i).toint(); }
- /** Return argument i as a java String based on the type of the argument.
+ /**
+ * Return argument i as a java long value, discarding any fractional part
+ * and truncating, or 0 if not a number.
+ *
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return long value with fraction discarded and truncated if necessary if
+ * argument i is number, otherwise 0
+ */
+ public long tolong(int i) { return arg(i).tolong(); }
+
+ /**
+ * Return argument i as a java String based on the type of the argument.
+ *
* @param i the index of the argument to convert, 1 is the first argument
* @return String value representing the type
- * */
- public String tojstring(int i) { return arg(i).tojstring(); }
-
- /** Return argument i as a java short value, discarding any fractional part and truncating,
- * or 0 if not a number.
- * @param i the index of the argument to convert, 1 is the first argument
- * @return short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
- * */
- public short toshort(int i) { return arg(i).toshort(); }
+ */
+ public String tojstring(int i) { return arg(i).tojstring(); }
- /** Return argument i as a java Object if a userdata, or null.
+ /**
+ * Return argument i as a java short value, discarding any fractional part
+ * and truncating, or 0 if not a number.
+ *
+ * @param i the index of the argument to convert, 1 is the first argument
+ * @return short value with fraction discarded and truncated if necessary if
+ * argument i is number, otherwise 0
+ */
+ public short toshort(int i) { return arg(i).toshort(); }
+
+ /**
+ * Return argument i as a java Object if a userdata, or null.
+ *
* @param i the index of the argument to convert, 1 is the first argument
* @return java Object value if argument i is a userdata, otherwise null
- * */
- public Object touserdata(int i) { return arg(i).touserdata(); }
+ */
+ public Object touserdata(int i) { return arg(i).touserdata(); }
- /** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null.
+ /**
+ * Return argument i as a java Object if it is a userdata whose instance
+ * Class c or a subclass, or null.
+ *
* @param i the index of the argument to convert, 1 is the first argument
* @param c the class to which the userdata instance must be assignable
- * @return java Object value if argument i is a userdata whose instance Class c or a subclass, otherwise null
- * */
- public Object touserdata(int i,Class c) { return arg(i).touserdata(c); }
-
- /** Convert the list of varargs values to a human readable java String.
+ * @return java Object value if argument i is a userdata whose instance
+ * Class c or a subclass, otherwise null
+ */
+ public Object touserdata(int i, Class c) { return arg(i).touserdata(c); }
+
+ /**
+ * Convert the list of varargs values to a human readable java String.
+ *
* @return String value in human readable form such as {1,2}.
*/
public String tojstring() {
Buffer sb = new Buffer();
- sb.append( "(" );
- for ( int i=1,n=narg(); i<=n; i++ ) {
- if (i>1) sb.append( "," );
- sb.append( arg(i).tojstring() );
+ sb.append("(");
+ for (int i = 1, n = narg(); i <= n; i++) {
+ if (i > 1)
+ sb.append(",");
+ sb.append(arg(i).tojstring());
}
- sb.append( ")" );
+ sb.append(")");
return sb.tojstring();
}
-
- /** Convert the value or values to a java String using Varargs.tojstring()
+
+ /**
+ * Convert the value or values to a java String using Varargs.tojstring()
+ *
* @return String value in human readable form.
* @see Varargs#tojstring()
*/
+ @Override
public String toString() { return tojstring(); }
/**
- * Create a {@code Varargs} instance containing arguments starting at index {@code start}
- * @param start the index from which to include arguments, where 1 is the first argument.
- * @return Varargs containing argument { start, start+1, ... , narg-start-1 }
+ * Create a {@code Varargs} instance containing arguments starting at index
+ * {@code start}
+ *
+ * @param start the index from which to include arguments, where 1 is the
+ * first argument.
+ * @return Varargs containing argument { start, start+1, ... , narg-start-1
+ * }
*/
abstract public Varargs subargs(final int start);
/**
* Implementation of Varargs for use in the Varargs.subargs() function.
+ *
* @see Varargs#subargs(int)
*/
static class SubVarargs extends Varargs {
private final Varargs v;
- private final int start;
- private final int end;
+ private final int start;
+ private final int end;
+
public SubVarargs(Varargs varargs, int start, int end) {
this.v = varargs;
this.start = start;
this.end = end;
}
+
+ @Override
public LuaValue arg(int i) {
i += start-1;
- return i>=start && i<=end? v.arg(i): LuaValue.NIL;
+ return i >= start && i <= end? v.arg(i): LuaValue.NIL;
}
+
+ @Override
public LuaValue arg1() {
return v.arg(start);
}
+
+ @Override
public int narg() {
return end+1-start;
}
+
+ @Override
public Varargs subargs(final int start) {
if (start == 1)
return this;
- final int newstart = this.start + start - 1;
+ final int newstart = this.start+start-1;
if (start > 0) {
if (newstart >= this.end)
return LuaValue.NONE;
@@ -544,111 +741,138 @@ public abstract class Varargs {
}
}
- /** Varargs implemenation backed by two values.
+ /**
+ * Varargs implemenation backed by two values.
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static method on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead use
+ * the corresponding static method on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue, Varargs)
*/
static final class PairVarargs extends Varargs {
private final LuaValue v1;
- private final Varargs v2;
- /** Construct a Varargs from an two LuaValue.
+ private final Varargs v2;
+
+ /**
+ * Construct a Varargs from an two LuaValue.
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static method on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead
+ * use the corresponding static method on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue, Varargs)
*/
PairVarargs(LuaValue v1, Varargs v2) {
this.v1 = v1;
this.v2 = v2;
}
+
+ @Override
public LuaValue arg(int i) {
- return i==1? v1: v2.arg(i-1);
+ return i == 1? v1: v2.arg(i-1);
}
+
+ @Override
public int narg() {
return 1+v2.narg();
}
+
+ @Override
public LuaValue arg1() {
return v1;
}
+
+ @Override
public Varargs subargs(final int start) {
if (start == 1)
return this;
if (start == 2)
return v2;
if (start > 2)
- return v2.subargs(start - 1);
+ return v2.subargs(start-1);
return LuaValue.argerror(1, "start must be > 0");
}
}
- /** Varargs implemenation backed by an array of LuaValues
+ /**
+ * Varargs implemenation backed by an array of LuaValues
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static methods on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead use
+ * the corresponding static methods on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue[])
* @see LuaValue#varargsOf(LuaValue[], Varargs)
*/
static final class ArrayVarargs extends Varargs {
private final LuaValue[] v;
- private final Varargs r;
- /** Construct a Varargs from an array of LuaValue.
+ private final Varargs r;
+
+ /**
+ * Construct a Varargs from an array of LuaValue.
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static methods on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead
+ * use the corresponding static methods on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue[])
* @see LuaValue#varargsOf(LuaValue[], Varargs)
*/
ArrayVarargs(LuaValue[] v, Varargs r) {
this.v = v;
- this.r = r ;
+ this.r = r;
}
+
+ @Override
public LuaValue arg(int i) {
- return i < 1 ? LuaValue.NIL: i <= v.length? v[i - 1]: r.arg(i-v.length);
+ return i < 1? LuaValue.NIL: i <= v.length? v[i-1]: r.arg(i-v.length);
}
+
+ @Override
public int narg() {
return v.length+r.narg();
}
- public LuaValue arg1() { return v.length>0? v[0]: r.arg1(); }
+
+ @Override
+ public LuaValue arg1() { return v.length > 0? v[0]: r.arg1(); }
+
+ @Override
public Varargs subargs(int start) {
if (start <= 0)
LuaValue.argerror(1, "start must be > 0");
if (start == 1)
return this;
if (start > v.length)
- return r.subargs(start - v.length);
- return LuaValue.varargsOf(v, start - 1, v.length - (start - 1), r);
+ return r.subargs(start-v.length);
+ return LuaValue.varargsOf(v, start-1, v.length-(start-1), r);
}
+
+ @Override
void copyto(LuaValue[] dest, int offset, int length) {
int n = Math.min(v.length, length);
System.arraycopy(v, 0, dest, offset, n);
- r.copyto(dest, offset + n, length - n);
+ r.copyto(dest, offset+n, length-n);
}
}
- /** Varargs implemenation backed by an array of LuaValues
+ /**
+ * Varargs implemenation backed by an array of LuaValues
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static methods on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead use
+ * the corresponding static methods on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue[], int, int)
* @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
*/
static final class ArrayPartVarargs extends Varargs {
- private final int offset;
+ private final int offset;
private final LuaValue[] v;
- private final int length;
- private final Varargs more;
- /** Construct a Varargs from an array of LuaValue.
+ private final int length;
+ private final Varargs more;
+
+ /**
+ * Construct a Varargs from an array of LuaValue.
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static methods on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead
+ * use the corresponding static methods on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue[], int, int)
*/
ArrayPartVarargs(LuaValue[] v, int offset, int length) {
@@ -657,11 +881,14 @@ public abstract class Varargs {
this.length = length;
this.more = LuaValue.NONE;
}
- /** Construct a Varargs from an array of LuaValue and additional arguments.
+
+ /**
+ * Construct a Varargs from an array of LuaValue and additional
+ * arguments.
*
- * This is an internal class not intended to be used directly.
- * Instead use the corresponding static method on LuaValue.
- *
+ * This is an internal class not intended to be used directly. Instead
+ * use the corresponding static method on LuaValue.
+ *
* @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
*/
public ArrayPartVarargs(LuaValue[] v, int offset, int length, Varargs more) {
@@ -670,52 +897,71 @@ public abstract class Varargs {
this.length = length;
this.more = more;
}
+
+ @Override
public LuaValue arg(final int i) {
return i < 1? LuaValue.NIL: i <= length? v[offset+i-1]: more.arg(i-length);
}
+
+ @Override
public int narg() {
- return length + more.narg();
+ return length+more.narg();
}
+
+ @Override
public LuaValue arg1() {
- return length>0? v[offset]: more.arg1();
+ return length > 0? v[offset]: more.arg1();
}
+
+ @Override
public Varargs subargs(int start) {
if (start <= 0)
LuaValue.argerror(1, "start must be > 0");
if (start == 1)
return this;
if (start > length)
- return more.subargs(start - length);
- return LuaValue.varargsOf(v, offset + start - 1, length - (start - 1), more);
+ return more.subargs(start-length);
+ return LuaValue.varargsOf(v, offset+start-1, length-(start-1), more);
}
+
+ @Override
void copyto(LuaValue[] dest, int offset, int length) {
int n = Math.min(this.length, length);
System.arraycopy(this.v, this.offset, dest, offset, n);
- more.copyto(dest, offset + n, length - n);
+ more.copyto(dest, offset+n, length-n);
}
}
- /** Copy values in a varargs into a destination array.
- * Internal utility method not intended to be called directly from user code.
+ /**
+ * Copy values in a varargs into a destination array. Internal utility
+ * method not intended to be called directly from user code.
+ *
* @return Varargs containing same values, but flattened.
*/
void copyto(LuaValue[] dest, int offset, int length) {
- for (int i=0; i
- * Normally these are not created directly, but indirectly when changing the mode
- * of a {@link LuaTable} as lua script executes.
+ * Subclass of {@link LuaTable} that provides weak key and weak value semantics.
*
- * However, calling the constructors directly when weak tables are required from
- * Java will reduce overhead.
+ * Normally these are not created directly, but indirectly when changing the
+ * mode of a {@link LuaTable} as lua script executes.
+ *
+ * However, calling the constructors directly when weak tables are required from
+ * Java will reduce overhead.
*/
public class WeakTable implements Metatable {
- private boolean weakkeys, weakvalues;
- private LuaValue backing;
+ private final boolean weakkeys, weakvalues;
+ private final LuaValue backing;
public static LuaTable make(boolean weakkeys, boolean weakvalues) {
LuaString mode;
- if ( weakkeys && weakvalues ) {
+ if (weakkeys && weakvalues) {
mode = LuaString.valueOf("kv");
- } else if ( weakkeys ) {
+ } else if (weakkeys) {
mode = LuaString.valueOf("k");
- } else if ( weakvalues ) {
+ } else if (weakvalues) {
mode = LuaString.valueOf("v");
} else {
- return LuaTable.tableOf();
+ return LuaValue.tableOf();
}
- LuaTable table = LuaTable.tableOf();
- LuaTable mt = LuaTable.tableOf(new LuaValue[] { LuaValue.MODE, mode });
+ LuaTable table = LuaValue.tableOf();
+ LuaTable mt = LuaValue.tableOf(new LuaValue[] { LuaValue.MODE, mode });
table.setmetatable(mt);
return table;
}
/**
* Construct a table with weak keys, weak values, or both
- * @param weakkeys true to let the table have weak keys
+ *
+ * @param weakkeys true to let the table have weak keys
* @param weakvalues true to let the table have weak values
*/
public WeakTable(boolean weakkeys, boolean weakvalues, LuaValue backing) {
@@ -68,40 +69,44 @@ public class WeakTable implements Metatable {
this.backing = backing;
}
+ @Override
public boolean useWeakKeys() {
return weakkeys;
}
+ @Override
public boolean useWeakValues() {
return weakvalues;
}
+ @Override
public LuaValue toLuaValue() {
return backing;
}
+ @Override
public Slot entry(LuaValue key, LuaValue value) {
value = value.strongvalue();
- if ( value == null )
+ if (value == null)
return null;
- if ( weakkeys && !( key.isnumber() || key.isstring() || key.isboolean() )) {
- if ( weakvalues && !( value.isnumber() || value.isstring() || value.isboolean() )) {
- return new WeakKeyAndValueSlot( key, value, null );
+ if (weakkeys && !(key.isnumber() || key.isstring() || key.isboolean())) {
+ if (weakvalues && !(value.isnumber() || value.isstring() || value.isboolean())) {
+ return new WeakKeyAndValueSlot(key, value, null);
} else {
- return new WeakKeySlot( key, value, null );
+ return new WeakKeySlot(key, value, null);
}
}
- if ( weakvalues && ! (value.isnumber() || value.isstring() || value.isboolean() )) {
- return new WeakValueSlot( key, value, null );
+ if (weakvalues && !(value.isnumber() || value.isstring() || value.isboolean())) {
+ return new WeakValueSlot(key, value, null);
}
- return LuaTable.defaultEntry( key, value );
+ return LuaTable.defaultEntry(key, value);
}
public static abstract class WeakSlot implements Slot {
protected Object key;
protected Object value;
- protected Slot next;
+ protected Slot next;
protected WeakSlot(Object key, Object value, Slot next) {
this.key = key;
@@ -109,14 +114,16 @@ public class WeakTable implements Metatable {
this.next = next;
}
- public abstract int keyindex( int hashMask );
+ @Override
+ public abstract int keyindex(int hashMask);
public abstract Slot set(LuaValue value);
+ @Override
public StrongSlot first() {
LuaValue key = strongkey();
LuaValue value = strongvalue();
- if ( key != null && value != null ) {
+ if (key != null && value != null) {
return new LuaTable.NormalEntry(key, value);
} else {
this.key = null;
@@ -125,67 +132,75 @@ public class WeakTable implements Metatable {
}
}
+ @Override
public StrongSlot find(LuaValue key) {
StrongSlot first = first();
- return ( first != null ) ? first.find( key ) : null;
+ return first != null? first.find(key): null;
}
+ @Override
public boolean keyeq(LuaValue key) {
StrongSlot first = first();
- return ( first != null ) && first.keyeq( key );
+ return first != null && first.keyeq(key);
}
+ @Override
public Slot rest() {
return next;
}
+ @Override
public int arraykey(int max) {
// Integer keys can never be weak.
return 0;
}
+ @Override
public Slot set(StrongSlot target, LuaValue value) {
LuaValue key = strongkey();
- if ( key != null && target.find( key ) != null ) {
- return set( value );
- } else if ( key != null ) {
+ if (key != null && target.find(key) != null) {
+ return set(value);
+ } else if (key != null) {
// Our key is still good.
- next = next.set( target, value );
+ next = next.set(target, value);
return this;
} else {
// our key was dropped, remove ourselves from the chain.
- return next.set( target, value );
+ return next.set(target, value);
}
}
- public Slot add( Slot entry ) {
- next = ( next != null ) ? next.add( entry ) : entry;
- if ( strongkey() != null && strongvalue() != null ) {
+ @Override
+ public Slot add(Slot entry) {
+ next = next != null? next.add(entry): entry;
+ if (strongkey() != null && strongvalue() != null) {
return this;
} else {
return next;
}
}
- public Slot remove( StrongSlot target ) {
+ @Override
+ public Slot remove(StrongSlot target) {
LuaValue key = strongkey();
- if ( key == null ) {
- return next.remove( target );
- } else if ( target.keyeq( key ) ) {
+ if (key == null) {
+ return next.remove(target);
+ } else if (target.keyeq(key)) {
this.value = null;
return this;
} else {
- next = next.remove( target );
+ next = next.remove(target);
return this;
}
}
- public Slot relink( Slot rest ) {
- if ( strongkey() != null && strongvalue() != null ) {
- if ( rest == null && this.next == null ) {
+ @Override
+ public Slot relink(Slot rest) {
+ if (strongkey() != null && strongvalue() != null) {
+ if (rest == null && this.next == null) {
return this;
} else {
- return copy( rest );
+ return copy(rest);
}
} else {
return rest;
@@ -200,66 +215,74 @@ public class WeakTable implements Metatable {
return (LuaValue) value;
}
- protected abstract WeakSlot copy( Slot next );
+ protected abstract WeakSlot copy(Slot next);
}
static class WeakKeySlot extends WeakSlot {
private final int keyhash;
- protected WeakKeySlot( LuaValue key, LuaValue value, Slot next ) {
+ protected WeakKeySlot(LuaValue key, LuaValue value, Slot next) {
super(weaken(key), value, next);
keyhash = key.hashCode();
}
- protected WeakKeySlot( WeakKeySlot copyFrom, Slot next ) {
- super( copyFrom.key, copyFrom.value, next );
+ protected WeakKeySlot(WeakKeySlot copyFrom, Slot next) {
+ super(copyFrom.key, copyFrom.value, next);
this.keyhash = copyFrom.keyhash;
}
- public int keyindex( int mask ) {
- return LuaTable.hashmod( keyhash, mask );
+ @Override
+ public int keyindex(int mask) {
+ return LuaTable.hashmod(keyhash, mask);
}
+ @Override
public Slot set(LuaValue value) {
this.value = value;
return this;
}
+ @Override
public LuaValue strongkey() {
- return strengthen( key );
+ return strengthen(key);
}
- protected WeakSlot copy( Slot rest ) {
- return new WeakKeySlot( this, rest );
+ @Override
+ protected WeakSlot copy(Slot rest) {
+ return new WeakKeySlot(this, rest);
}
}
static class WeakValueSlot extends WeakSlot {
- protected WeakValueSlot( LuaValue key, LuaValue value, Slot next ) {
- super( key, weaken(value), next);
+ protected WeakValueSlot(LuaValue key, LuaValue value, Slot next) {
+ super(key, weaken(value), next);
}
- protected WeakValueSlot( WeakValueSlot copyFrom, Slot next ) {
- super( copyFrom.key, copyFrom.value, next );
+ protected WeakValueSlot(WeakValueSlot copyFrom, Slot next) {
+ super(copyFrom.key, copyFrom.value, next);
}
- public int keyindex( int mask ) {
- return LuaTable.hashSlot( strongkey(), mask );
+ @Override
+ public int keyindex(int mask) {
+ return LuaTable.hashSlot(strongkey(), mask);
}
+ @Override
public Slot set(LuaValue value) {
this.value = weaken(value);
return this;
}
+ @Override
public LuaValue strongvalue() {
- return strengthen( value );
+ return strengthen(value);
}
+ @Override
protected WeakSlot copy(Slot next) {
- return new WeakValueSlot( this, next );
+ return new WeakValueSlot(this, next);
}
}
@@ -267,73 +290,83 @@ public class WeakTable implements Metatable {
private final int keyhash;
- protected WeakKeyAndValueSlot( LuaValue key, LuaValue value, Slot next ) {
- super( weaken(key), weaken(value), next );
+ protected WeakKeyAndValueSlot(LuaValue key, LuaValue value, Slot next) {
+ super(weaken(key), weaken(value), next);
keyhash = key.hashCode();
}
protected WeakKeyAndValueSlot(WeakKeyAndValueSlot copyFrom, Slot next) {
- super( copyFrom.key, copyFrom.value, next );
+ super(copyFrom.key, copyFrom.value, next);
keyhash = copyFrom.keyhash;
}
- public int keyindex( int hashMask ) {
- return LuaTable.hashmod( keyhash, hashMask );
+ @Override
+ public int keyindex(int hashMask) {
+ return LuaTable.hashmod(keyhash, hashMask);
}
+ @Override
public Slot set(LuaValue value) {
this.value = weaken(value);
return this;
}
+ @Override
public LuaValue strongkey() {
- return strengthen( key );
+ return strengthen(key);
}
+ @Override
public LuaValue strongvalue() {
- return strengthen( value );
+ return strengthen(value);
}
- protected WeakSlot copy( Slot next ) {
- return new WeakKeyAndValueSlot( this, next );
+ @Override
+ protected WeakSlot copy(Slot next) {
+ return new WeakKeyAndValueSlot(this, next);
}
}
/**
* Self-sent message to convert a value to its weak counterpart
+ *
* @param value value to convert
- * @return {@link LuaValue} that is a strong or weak reference, depending on type of {@code value}
+ * @return {@link LuaValue} that is a strong or weak reference, depending on
+ * type of {@code value}
*/
- protected static LuaValue weaken( LuaValue value ) {
- switch ( value.type() ) {
- case LuaValue.TFUNCTION:
- case LuaValue.TTHREAD:
- case LuaValue.TTABLE:
- return new WeakValue(value);
- case LuaValue.TUSERDATA:
- return new WeakUserdata(value);
- default:
- return value;
+ protected static LuaValue weaken(LuaValue value) {
+ switch (value.type()) {
+ case LuaValue.TFUNCTION:
+ case LuaValue.TTHREAD:
+ case LuaValue.TTABLE:
+ return new WeakValue(value);
+ case LuaValue.TUSERDATA:
+ return new WeakUserdata(value);
+ default:
+ return value;
}
}
/**
* Unwrap a LuaValue from a WeakReference and/or WeakUserdata.
+ *
* @param ref reference to convert
* @return LuaValue or null
* @see #weaken(LuaValue)
*/
protected static LuaValue strengthen(Object ref) {
- if ( ref instanceof WeakReference ) {
+ if (ref instanceof WeakReference) {
ref = ((WeakReference) ref).get();
}
- if ( ref instanceof WeakValue ) {
+ if (ref instanceof WeakValue) {
return ((WeakValue) ref).strongvalue();
}
return (LuaValue) ref;
}
- /** Internal class to implement weak values.
+ /**
+ * Internal class to implement weak values.
+ *
* @see WeakTable
*/
static class WeakValue extends LuaValue {
@@ -343,37 +376,44 @@ public class WeakTable implements Metatable {
ref = new WeakReference(value);
}
+ @Override
public int type() {
- illegal("type","weak value");
+ illegal("type", "weak value");
return 0;
}
+ @Override
public String typename() {
- illegal("typename","weak value");
+ illegal("typename", "weak value");
return null;
}
+ @Override
public String toString() {
- return "weak<"+ref.get()+">";
+ return "weak<" + ref.get() + ">";
}
+ @Override
public LuaValue strongvalue() {
Object o = ref.get();
- return (LuaValue)o;
+ return (LuaValue) o;
}
+ @Override
public boolean raweq(LuaValue rhs) {
Object o = ref.get();
- return o!=null && rhs.raweq((LuaValue)o);
+ return o != null && rhs.raweq((LuaValue) o);
}
}
- /** Internal class to implement weak userdata values.
+ /**
+ * Internal class to implement weak userdata values.
+ *
* @see WeakTable
*/
static final class WeakUserdata extends WeakValue {
private final WeakReference ob;
- private final LuaValue mt;
+ private final LuaValue mt;
private WeakUserdata(LuaValue value) {
super(value);
@@ -381,13 +421,14 @@ public class WeakTable implements Metatable {
mt = value.getmetatable();
}
+ @Override
public LuaValue strongvalue() {
Object u = ref.get();
- if ( u != null )
+ if (u != null)
return (LuaValue) u;
Object o = ob.get();
- if ( o != null ) {
- LuaValue ud = LuaValue.userdataOf(o,mt);
+ if (o != null) {
+ LuaValue ud = LuaValue.userdataOf(o, mt);
ref = new WeakReference(ud);
return ud;
} else {
@@ -396,10 +437,12 @@ public class WeakTable implements Metatable {
}
}
+ @Override
public LuaValue wrap(LuaValue value) {
- return weakvalues ? weaken( value ) : value;
+ return weakvalues? weaken(value): value;
}
+ @Override
public LuaValue arrayget(LuaValue[] array, int index) {
LuaValue value = array[index];
if (value != null) {
diff --git a/luaj-core/src/main/java/org/luaj/vm2/compat/JavaCompat.java b/luaj-core/src/main/java/org/luaj/vm2/compat/JavaCompat.java
new file mode 100644
index 00000000..07b0be29
--- /dev/null
+++ b/luaj-core/src/main/java/org/luaj/vm2/compat/JavaCompat.java
@@ -0,0 +1,19 @@
+package org.luaj.vm2.compat;
+
+public class JavaCompat {
+ public static final JavaCompat INSTANCE;
+
+ static {
+ JavaCompat instance;
+ try {
+ instance = (JavaCompat) Class.forName("org.luaj.vm2.lib.jse.JavaCompatJSE").newInstance();
+ } catch (Throwable t) {
+ instance = new JavaCompat();
+ }
+ INSTANCE = instance;
+ }
+
+ public long doubleToRawLongBits(double x) {
+ return Double.doubleToLongBits(x);
+ }
+}
diff --git a/src/core/org/luaj/vm2/compiler/Constants.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java
similarity index 59%
rename from src/core/org/luaj/vm2/compiler/Constants.java
rename to luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java
index fc505b49..143d952d 100644
--- a/src/core/org/luaj/vm2/compiler/Constants.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java
@@ -10,7 +10,7 @@
*
* 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
@@ -31,158 +31,146 @@ import org.luaj.vm2.Upvaldesc;
/**
* Constants used by the LuaC compiler and related classes.
- *
+ *
* @see LuaC
* @see FuncState
*/
public class Constants extends Lua {
-
+
/** Maximum stack size of a luaj vm interpreter instance. */
public static final int MAXSTACK = 250;
static final int LUAI_MAXUPVAL = 0xff;
- static final int LUAI_MAXVARS = 200;
- static final int NO_REG = MAXARG_A;
-
+ static final int LUAI_MAXVARS = 200;
+ static final int NO_REG = MAXARG_A;
/* OpMode - basic instruction format */
- static final int
- iABC = 0,
- iABx = 1,
- iAsBx = 2;
+ static final int iABC = 0, iABx = 1, iAsBx = 2;
/* OpArgMask */
- static final int
- OpArgN = 0, /* argument is not used */
- OpArgU = 1, /* argument is used */
- OpArgR = 2, /* argument is a register or a jump offset */
- OpArgK = 3; /* argument is a constant or register/constant */
-
+ static final int OpArgN = 0, /* argument is not used */
+ OpArgU = 1, /* argument is used */
+ OpArgR = 2, /* argument is a register or a jump offset */
+ OpArgK = 3; /* argument is a constant or register/constant */
protected static void _assert(boolean b) {
if (!b)
throw new LuaError("compiler assert failed");
}
- static void SET_OPCODE(InstructionPtr i,int o) {
- i.set( ( i.get() & (MASK_NOT_OP)) | ((o << POS_OP) & MASK_OP) );
+ static void SET_OPCODE(InstructionPtr i, int o) {
+ i.set(i.get() & MASK_NOT_OP | o<
- * Generally, this class is not used directly, but rather indirectly via a command
- * line interface tool such as {@link luac}.
+ * Generally, this class is not used directly, but rather indirectly via a
+ * command line interface tool such as {@link luac}.
*
* A lua binary file is created via {@link DumpState#dump}:
- *
{@code
- * Globals globals = JsePlatform.standardGlobals();
- * Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
- * ByteArrayOutputStream o = new ByteArrayOutputStream();
- * DumpState.dump(p, o, false);
- * byte[] lua_binary_file_bytes = o.toByteArray();
- * }
+ *
* @see luac
* @see LoadState
* @see Globals
@@ -71,33 +83,39 @@ public class DumpState {
/** set true to allow integer compilation */
public static boolean ALLOW_INTEGER_CASTING = false;
-
- /** format corresponding to non-number-patched lua, all numbers are floats or doubles */
- public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
+
+ /**
+ * format corresponding to non-number-patched lua, all numbers are floats or
+ * doubles
+ */
+ public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
/** format corresponding to non-number-patched lua, all numbers are ints */
- public static final int NUMBER_FORMAT_INTS_ONLY = 1;
-
- /** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
- public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
-
+ public static final int NUMBER_FORMAT_INTS_ONLY = 1;
+
+ /**
+ * format corresponding to number-patched lua, all numbers are 32-bit (4
+ * byte) ints
+ */
+ public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
+
/** default number format */
public static final int NUMBER_FORMAT_DEFAULT = NUMBER_FORMAT_FLOATS_OR_DOUBLES;
// header fields
- private boolean IS_LITTLE_ENDIAN = true;
- private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT;
- private int SIZEOF_LUA_NUMBER = 8;
- private static final int SIZEOF_INT = 4;
- private static final int SIZEOF_SIZET = 4;
+ private boolean IS_LITTLE_ENDIAN = true;
+ private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT;
+ private int SIZEOF_LUA_NUMBER = 8;
+ private static final int SIZEOF_INT = 4;
+ private static final int SIZEOF_SIZET = 4;
private static final int SIZEOF_INSTRUCTION = 4;
DataOutputStream writer;
- boolean strip;
- int status;
+ boolean strip;
+ int status;
public DumpState(OutputStream w, boolean strip) {
- this.writer = new DataOutputStream( w );
+ this.writer = new DataOutputStream(w);
this.strip = strip;
this.status = 0;
}
@@ -107,58 +125,58 @@ public class DumpState {
}
void dumpChar(int b) throws IOException {
- writer.write( b );
+ writer.write(b);
}
void dumpInt(int x) throws IOException {
- if ( IS_LITTLE_ENDIAN ) {
- writer.writeByte(x&0xff);
- writer.writeByte((x>>8)&0xff);
- writer.writeByte((x>>16)&0xff);
- writer.writeByte((x>>24)&0xff);
+ if (IS_LITTLE_ENDIAN) {
+ writer.writeByte(x & 0xff);
+ writer.writeByte(x>>8 & 0xff);
+ writer.writeByte(x>>16 & 0xff);
+ writer.writeByte(x>>24 & 0xff);
} else {
writer.writeInt(x);
}
}
-
+
void dumpString(LuaString s) throws IOException {
final int len = s.len().toint();
- dumpInt( len+1 );
- s.write( writer, 0, len );
- writer.write( 0 );
+ dumpInt(len+1);
+ s.write(writer, 0, len);
+ writer.write(0);
}
-
+
void dumpDouble(double d) throws IOException {
long l = Double.doubleToLongBits(d);
- if ( IS_LITTLE_ENDIAN ) {
- dumpInt( (int) l );
- dumpInt( (int) (l>>32) );
+ if (IS_LITTLE_ENDIAN) {
+ dumpInt((int) l);
+ dumpInt((int) (l>>32));
} else {
writer.writeLong(l);
}
}
- void dumpCode( final Prototype f ) throws IOException {
+ void dumpCode(final Prototype f) throws IOException {
final int[] code = f.code;
int n = code.length;
- dumpInt( n );
- for ( int i=0; i l )
- errorlimit( l, msg );
+ if (v > l)
+ errorlimit(l, msg);
}
-
- void errorlimit (int limit, String what) {
+
+ void errorlimit(int limit, String what) {
// TODO: report message logic.
- String msg = (f.linedefined == 0) ?
- ls.L.pushfstring("main function has more than "+limit+" "+what) :
- ls.L.pushfstring("function at line "+f.linedefined+" has more than "+limit+" "+what);
- ls.lexerror(msg, 0);
+ String msg = f.linedefined == 0? ls.L.pushfstring("main function has more than " + limit + " " + what)
+ : ls.L.pushfstring("function at line " + f.linedefined + " has more than " + limit + " " + what);
+ ls.lexerror(msg, 0);
}
LocVars getlocvar(int i) {
- int idx = ls.dyd.actvar[firstlocal + i].idx;
+ int idx = ls.dyd.actvar[firstlocal+i].idx;
_assert(idx < nlocvars);
return f.locvars[idx];
}
- void removevars (int tolevel) {
- ls.dyd.n_actvar -= (nactvar - tolevel);
- while (nactvar > tolevel)
- getlocvar(--nactvar).endpc = pc;
+ void removevars(int tolevel) {
+ ls.dyd.n_actvar -= nactvar-tolevel;
+ while ( nactvar > tolevel )
+ getlocvar(--nactvar).endpc = pc;
}
-
- int searchupvalue (LuaString name) {
- int i;
- Upvaldesc[] up = f.upvalues;
- for (i = 0; i < nups; i++)
- if (up[i].name.eq_b(name))
- return i;
- return -1; /* not found */
+ int searchupvalue(LuaString name) {
+ int i;
+ Upvaldesc[] up = f.upvalues;
+ for (i = 0; i < nups; i++)
+ if (up[i].name.eq_b(name))
+ return i;
+ return -1; /* not found */
}
- int newupvalue (LuaString name, expdesc v) {
- checklimit(nups + 1, LUAI_MAXUPVAL, "upvalues");
- if (f.upvalues == null || nups + 1 > f.upvalues.length)
- f.upvalues = realloc( f.upvalues, nups > 0 ? nups*2 : 1 );
+ int newupvalue(LuaString name, expdesc v) {
+ checklimit(nups+1, LUAI_MAXUPVAL, "upvalues");
+ if (f.upvalues == null || nups+1 > f.upvalues.length)
+ f.upvalues = realloc(f.upvalues, nups > 0? nups*2: 1);
f.upvalues[nups] = new Upvaldesc(name, v.k == LexState.VLOCAL, v.u.info);
- return nups++;
+ return nups++;
}
-
+
int searchvar(LuaString n) {
int i;
- for (i = nactvar - 1; i >= 0; i--) {
+ for (i = nactvar-1; i >= 0; i--) {
if (n.eq_b(getlocvar(i).varname))
return i;
}
return -1; /* not found */
}
-
+
void markupval(int level) {
BlockCnt bl = this.bl;
- while (bl.nactvar > level)
+ while ( bl.nactvar > level )
bl = bl.previous;
bl.upval = true;
}
-
+
static int singlevaraux(FuncState fs, LuaString n, expdesc var, int base) {
- if (fs == null) /* no more levels? */
- return LexState.VVOID; /* default is global */
+ if (fs == null) /* no more levels? */
+ return LexState.VVOID; /* default is global */
int v = fs.searchvar(n); /* look up at current level */
if (v >= 0) {
var.init(LexState.VLOCAL, v);
@@ -173,15 +166,15 @@ public class FuncState extends Constants {
fs.markupval(v); /* local will be used as an upval */
return LexState.VLOCAL;
} else { /* not found at current level; try upvalues */
- int idx = fs.searchupvalue(n); /* try existing upvalues */
- if (idx < 0) { /* not found? */
- if (singlevaraux(fs.prev, n, var, 0) == LexState.VVOID) /* try upper levels */
- return LexState.VVOID; /* not found; is a global */
- /* else was LOCAL or UPVAL */
- idx = fs.newupvalue(n, var); /* will be a new upvalue */
- }
- var.init(LexState.VUPVAL, idx);
- return LexState.VUPVAL;
+ int idx = fs.searchupvalue(n); /* try existing upvalues */
+ if (idx < 0) { /* not found? */
+ if (singlevaraux(fs.prev, n, var, 0) == LexState.VVOID) /* try upper levels */
+ return LexState.VVOID; /* not found; is a global */
+ /* else was LOCAL or UPVAL */
+ idx = fs.newupvalue(n, var); /* will be a new upvalue */
+ }
+ var.init(LexState.VUPVAL, idx);
+ return LexState.VUPVAL;
}
}
@@ -196,7 +189,7 @@ public class FuncState extends Constants {
final LexState.Labeldesc[] gl = ls.dyd.gt;
/* correct pending gotos to current block and try to close it
with visible labels */
- while (i < ls.dyd.n_gt) {
+ while ( i < ls.dyd.n_gt ) {
LexState.Labeldesc gt = gl[i];
if (gt.nactvar > bl.nactvar) {
if (bl.upval)
@@ -207,37 +200,37 @@ public class FuncState extends Constants {
i++; /* move to next one */
}
}
-
- void enterblock (BlockCnt bl, boolean isloop) {
- bl.isloop = isloop;
- bl.nactvar = nactvar;
- bl.firstlabel = (short) ls.dyd.n_label;
- bl.firstgoto = (short) ls.dyd.n_gt;
- bl.upval = false;
- bl.previous = this.bl;
- this.bl = bl;
- _assert(this.freereg == this.nactvar);
+
+ void enterblock(BlockCnt bl, boolean isloop) {
+ bl.isloop = isloop;
+ bl.nactvar = nactvar;
+ bl.firstlabel = (short) ls.dyd.n_label;
+ bl.firstgoto = (short) ls.dyd.n_gt;
+ bl.upval = false;
+ bl.previous = this.bl;
+ this.bl = bl;
+ _assert(this.freereg == this.nactvar);
}
void leaveblock() {
BlockCnt bl = this.bl;
if (bl.previous != null && bl.upval) {
- /* create a 'jump to here' to close upvalues */
- int j = this.jump();
- this.patchclose(j, bl.nactvar);
- this.patchtohere(j);
+ /* create a 'jump to here' to close upvalues */
+ int j = this.jump();
+ this.patchclose(j, bl.nactvar);
+ this.patchtohere(j);
}
if (bl.isloop)
- ls.breaklabel(); /* close pending breaks */
+ ls.breaklabel(); /* close pending breaks */
this.bl = bl.previous;
this.removevars(bl.nactvar);
_assert(bl.nactvar == this.nactvar);
- this.freereg = this.nactvar; /* free registers */
- ls.dyd.n_label = bl.firstlabel; /* remove local labels */
- if (bl.previous != null) /* inner block? */
- this.movegotosout(bl); /* update pending gotos to outer block */
- else if (bl.firstgoto < ls.dyd.n_gt) /* pending gotos in outer block? */
- ls.undefgoto(ls.dyd.gt[bl.firstgoto]); /* error */
+ this.freereg = this.nactvar; /* free registers */
+ ls.dyd.n_label = bl.firstlabel; /* remove local labels */
+ if (bl.previous != null) /* inner block? */
+ this.movegotosout(bl); /* update pending gotos to outer block */
+ else if (bl.firstgoto < ls.dyd.n_gt) /* pending gotos in outer block? */
+ ls.undefgoto(ls.dyd.gt[bl.firstgoto]); /* error */
}
void closelistfield(ConsControl cc) {
@@ -252,53 +245,52 @@ public class FuncState extends Constants {
}
boolean hasmultret(int k) {
- return ((k) == LexState.VCALL || (k) == LexState.VVARARG);
+ return k == LexState.VCALL || k == LexState.VVARARG;
}
- void lastlistfield (ConsControl cc) {
- if (cc.tostore == 0) return;
+ void lastlistfield(ConsControl cc) {
+ if (cc.tostore == 0)
+ return;
if (hasmultret(cc.v.k)) {
- this.setmultret(cc.v);
- this.setlist(cc.t.u.info, cc.na, LUA_MULTRET);
- cc.na--; /** do not count last expression (unknown number of elements) */
- }
- else {
- if (cc.v.k != LexState.VVOID)
- this.exp2nextreg(cc.v);
- this.setlist(cc.t.u.info, cc.na, cc.tostore);
+ this.setmultret(cc.v);
+ this.setlist(cc.t.u.info, cc.na, LUA_MULTRET);
+ cc.na--; /**
+ * do not count last expression (unknown number of
+ * elements)
+ */
+ } else {
+ if (cc.v.k != LexState.VVOID)
+ this.exp2nextreg(cc.v);
+ this.setlist(cc.t.u.info, cc.na, cc.tostore);
}
}
-
-
-
+
// =============================================================
// from lcode.c
// =============================================================
void nil(int from, int n) {
- int l = from + n - 1; /* last register to set nil */
- if (this.pc > this.lasttarget && pc > 0) { /* no jumps to current position? */
- final int previous_code = f.code[pc - 1];
+ int l = from+n-1; /* last register to set nil */
+ if (this.pc > this.lasttarget && pc > 0) { /* no jumps to current position? */
+ final int previous_code = f.code[pc-1];
if (GET_OPCODE(previous_code) == OP_LOADNIL) {
int pfrom = GETARG_A(previous_code);
- int pl = pfrom + GETARG_B(previous_code);
- if ((pfrom <= from && from <= pl + 1)
- || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */
+ int pl = pfrom+GETARG_B(previous_code);
+ if (pfrom <= from && from <= pl+1 || from <= pfrom && pfrom <= l+1) { /* can connect both? */
if (pfrom < from)
from = pfrom; /* from = min(from, pfrom) */
if (pl > l)
l = pl; /* l = max(l, pl) */
- InstructionPtr previous = new InstructionPtr(this.f.code, this.pc - 1);
+ InstructionPtr previous = new InstructionPtr(this.f.code, this.pc-1);
SETARG_A(previous, from);
- SETARG_B(previous, l - from);
+ SETARG_B(previous, l-from);
return;
}
- } /* else go through */
+ } /* else go through */
}
- this.codeABC(OP_LOADNIL, from, n - 1, 0);
+ this.codeABC(OP_LOADNIL, from, n-1, 0);
}
-
int jump() {
int jpc = this.jpc.i; /* save list of jumps to here */
this.jpc.i = LexState.NO_JUMP;
@@ -308,24 +300,23 @@ public class FuncState extends Constants {
}
void ret(int first, int nret) {
- this.codeABC(OP_RETURN, first, nret + 1, 0);
+ this.codeABC(OP_RETURN, first, nret+1, 0);
}
- int condjump(int /* OpCode */op, int A, int B, int C) {
+ int condjump(int /* OpCode */ op, int A, int B, int C) {
this.codeABC(op, A, B, C);
return this.jump();
}
void fixjump(int pc, int dest) {
InstructionPtr jmp = new InstructionPtr(this.f.code, pc);
- int offset = dest - (pc + 1);
- _assert (dest != LexState.NO_JUMP);
+ int offset = dest-(pc+1);
+ _assert(dest != LexState.NO_JUMP);
if (Math.abs(offset) > MAXARG_sBx)
ls.syntaxerror("control structure too long");
SETARG_sBx(jmp, offset);
}
-
/*
* * returns current `pc' and marks it as a jump target (to avoid wrong *
* optimizations with consecutive instructions not in the same basic block).
@@ -335,7 +326,6 @@ public class FuncState extends Constants {
return this.pc;
}
-
int getjump(int pc) {
int offset = GETARG_sBx(this.f.code[pc]);
/* point to itself represents end of list */
@@ -344,19 +334,17 @@ public class FuncState extends Constants {
return LexState.NO_JUMP;
else
/* turn offset into absolute position */
- return (pc + 1) + offset;
+ return pc+1+offset;
}
-
InstructionPtr getjumpcontrol(int pc) {
InstructionPtr pi = new InstructionPtr(this.f.code, pc);
- if (pc >= 1 && testTMode(GET_OPCODE(pi.code[pi.idx - 1])))
- return new InstructionPtr(pi.code, pi.idx - 1);
+ if (pc >= 1 && testTMode(GET_OPCODE(pi.code[pi.idx-1])))
+ return new InstructionPtr(pi.code, pi.idx-1);
else
return pi;
}
-
/*
* * check whether list has any jump that do not produce a value * (or
* produce an inverted value)
@@ -370,7 +358,6 @@ public class FuncState extends Constants {
return false; /* not found */
}
-
boolean patchtestreg(int node, int reg) {
InstructionPtr i = this.getjumpcontrol(node);
if (GET_OPCODE(i.get()) != OP_TESTSET)
@@ -385,14 +372,13 @@ public class FuncState extends Constants {
return true;
}
-
void removevalues(int list) {
for (; list != LexState.NO_JUMP; list = this.getjump(list))
this.patchtestreg(list, NO_REG);
}
void patchlistaux(int list, int vtarget, int reg, int dtarget) {
- while (list != LexState.NO_JUMP) {
+ while ( list != LexState.NO_JUMP ) {
int next = this.getjump(list);
if (this.patchtestreg(list, reg))
this.fixjump(list, vtarget);
@@ -411,17 +397,17 @@ public class FuncState extends Constants {
if (target == this.pc)
this.patchtohere(list);
else {
- _assert (target < this.pc);
+ _assert(target < this.pc);
this.patchlistaux(list, target, NO_REG, target);
}
}
void patchclose(int list, int level) {
level++; /* argument is +1 to reserve 0 as non-op */
- while (list != LexState.NO_JUMP) {
+ while ( list != LexState.NO_JUMP ) {
int next = getjump(list);
- _assert(GET_OPCODE(f.code[list]) == OP_JMP
- && (GETARG_A(f.code[list]) == 0 || GETARG_A(f.code[list]) >= level));
+ _assert(
+ GET_OPCODE(f.code[list]) == OP_JMP && (GETARG_A(f.code[list]) == 0 || GETARG_A(f.code[list]) >= level));
SETARG_A(f.code, list, level);
list = next;
}
@@ -440,7 +426,7 @@ public class FuncState extends Constants {
else {
int list = l1.i;
int next;
- while ((next = this.getjump(list)) != LexState.NO_JUMP)
+ while ( (next = this.getjump(list)) != LexState.NO_JUMP )
/* find last element */
list = next;
this.fixjump(list, l2);
@@ -448,7 +434,7 @@ public class FuncState extends Constants {
}
void checkstack(int n) {
- int newstack = this.freereg + n;
+ int newstack = this.freereg+n;
if (newstack > this.f.maxstacksize) {
if (newstack >= MAXSTACK)
ls.syntaxerror("function or expression too complex");
@@ -464,7 +450,7 @@ public class FuncState extends Constants {
void freereg(int reg) {
if (!ISK(reg) && reg >= this.nactvar) {
this.freereg--;
- _assert (reg == this.freereg);
+ _assert(reg == this.freereg);
}
}
@@ -472,6 +458,7 @@ public class FuncState extends Constants {
if (e.k == LexState.VNONRELOC)
this.freereg(e.u.info);
}
+
int addk(LuaValue v) {
if (this.h == null) {
this.h = new Hashtable();
@@ -479,10 +466,10 @@ public class FuncState extends Constants {
return ((Integer) h.get(v)).intValue();
}
final int idx = this.nk;
- this.h.put(v, new Integer(idx));
+ this.h.put(v, Integer.valueOf(idx));
final Prototype f = this.f;
- if (f.k == null || nk + 1 >= f.k.length)
- f.k = realloc( f.k, nk*2 + 1 );
+ if (f.k == null || nk+1 >= f.k.length)
+ f.k = realloc(f.k, nk*2+1);
f.k[this.nk++] = v;
return idx;
}
@@ -492,17 +479,17 @@ public class FuncState extends Constants {
}
int numberK(LuaValue r) {
- if ( r instanceof LuaDouble ) {
+ if (r instanceof LuaDouble) {
double d = r.todouble();
int i = (int) d;
- if ( d == (double) i )
+ if (d == i)
r = LuaInteger.valueOf(i);
}
return this.addk(r);
}
int boolK(boolean b) {
- return this.addk((b ? LuaValue.TRUE : LuaValue.FALSE));
+ return this.addk(b? LuaValue.TRUE: LuaValue.FALSE);
}
int nilK() {
@@ -511,9 +498,9 @@ public class FuncState extends Constants {
void setreturns(expdesc e, int nresults) {
if (e.k == LexState.VCALL) { /* expression is an open function call? */
- SETARG_C(this.getcodePtr(e), nresults + 1);
+ SETARG_C(this.getcodePtr(e), nresults+1);
} else if (e.k == LexState.VVARARG) {
- SETARG_B(this.getcodePtr(e), nresults + 1);
+ SETARG_B(this.getcodePtr(e), nresults+1);
SETARG_A(this.getcodePtr(e), this.freereg);
this.reserveregs(1);
}
@@ -541,9 +528,9 @@ public class FuncState extends Constants {
break;
}
case LexState.VINDEXED: {
- int op = OP_GETTABUP; /* assume 't' is in an upvalue */
+ int op = OP_GETTABUP; /* assume 't' is in an upvalue */
this.freereg(e.u.ind_idx);
- if (e.u.ind_vt == LexState.VLOCAL) { /* 't' is in a register? */
+ if (e.u.ind_vt == LexState.VLOCAL) { /* 't' is in a register? */
this.freereg(e.u.ind_t);
op = OP_GETTABLE;
}
@@ -575,8 +562,7 @@ public class FuncState extends Constants {
}
case LexState.VFALSE:
case LexState.VTRUE: {
- this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE ? 1 : 0),
- 0);
+ this.codeABC(OP_LOADBOOL, reg, e.k == LexState.VTRUE? 1: 0, 0);
break;
}
case LexState.VK: {
@@ -598,7 +584,7 @@ public class FuncState extends Constants {
break;
}
default: {
- _assert (e.k == LexState.VVOID || e.k == LexState.VJMP);
+ _assert(e.k == LexState.VVOID || e.k == LexState.VJMP);
return; /* nothing to do... */
}
}
@@ -609,7 +595,7 @@ public class FuncState extends Constants {
void discharge2anyreg(expdesc e) {
if (e.k != LexState.VNONRELOC) {
this.reserveregs(1);
- this.discharge2reg(e, this.freereg - 1);
+ this.discharge2reg(e, this.freereg-1);
}
}
@@ -622,8 +608,7 @@ public class FuncState extends Constants {
int p_f = LexState.NO_JUMP; /* position of an eventual LOAD false */
int p_t = LexState.NO_JUMP; /* position of an eventual LOAD true */
if (this.need_value(e.t.i) || this.need_value(e.f.i)) {
- int fj = (e.k == LexState.VJMP) ? LexState.NO_JUMP : this
- .jump();
+ int fj = e.k == LexState.VJMP? LexState.NO_JUMP: this.jump();
p_f = this.code_label(reg, 0, 1);
p_t = this.code_label(reg, 1, 0);
this.patchtohere(fj);
@@ -641,7 +626,7 @@ public class FuncState extends Constants {
this.dischargevars(e);
this.freeexp(e);
this.reserveregs(1);
- this.exp2reg(e, this.freereg - 1);
+ this.exp2reg(e, this.freereg-1);
}
int exp2anyreg(expdesc e) {
@@ -658,7 +643,7 @@ public class FuncState extends Constants {
return e.u.info;
}
- void exp2anyregup (expdesc e) {
+ void exp2anyregup(expdesc e) {
if (e.k != LexState.VUPVAL || e.hasjumps())
exp2anyreg(e);
}
@@ -677,17 +662,16 @@ public class FuncState extends Constants {
case LexState.VFALSE:
case LexState.VNIL: {
if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */
- e.u.info = (e.k == LexState.VNIL) ? this.nilK()
- : this.boolK((e.k == LexState.VTRUE));
+ e.u.info = e.k == LexState.VNIL? this.nilK(): this.boolK(e.k == LexState.VTRUE);
e.k = LexState.VK;
return RKASK(e.u.info);
} else
break;
}
case LexState.VKNUM: {
- e.u.info = this.numberK(e.u.nval());
- e.k = LexState.VK;
- /* go through */
+ e.u.info = this.numberK(e.u.nval());
+ e.k = LexState.VK;
+ /* go through */
}
case LexState.VK: {
if (e.u.info <= MAXINDEXRK) /* constant fit in argC? */
@@ -715,13 +699,13 @@ public class FuncState extends Constants {
break;
}
case LexState.VINDEXED: {
- int op = (var.u.ind_vt == LexState.VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
+ int op = var.u.ind_vt == LexState.VLOCAL? OP_SETTABLE: OP_SETTABUP;
int e = this.exp2RK(ex);
- this.codeABC(op, var.u.ind_t, var.u.ind_idx, e);
+ this.codeABC(op, var.u.ind_t, var.u.ind_idx, e);
break;
}
default: {
- _assert (false); /* invalid var kind to store */
+ _assert(false); /* invalid var kind to store */
break;
}
}
@@ -742,12 +726,11 @@ public class FuncState extends Constants {
void invertjump(expdesc e) {
InstructionPtr pc = this.getjumpcontrol(e.u.info);
- _assert (testTMode(GET_OPCODE(pc.get()))
- && GET_OPCODE(pc.get()) != OP_TESTSET && Lua
- .GET_OPCODE(pc.get()) != OP_TEST);
+ _assert(testTMode(GET_OPCODE(pc.get())) && GET_OPCODE(pc.get()) != OP_TESTSET
+ && Lua.GET_OPCODE(pc.get()) != OP_TEST);
// SETARG_A(pc, !(GETARG_A(pc.get())));
int a = GETARG_A(pc.get());
- int nota = (a!=0? 0: 1);
+ int nota = a != 0? 0: 1;
SETARG_A(pc, nota);
}
@@ -756,7 +739,7 @@ public class FuncState extends Constants {
int ie = this.getcode(e);
if (GET_OPCODE(ie) == OP_NOT) {
this.pc--; /* remove previous OP_NOT */
- return this.condjump(OP_TEST, GETARG_B(ie), 0, (cond!=0? 0: 1));
+ return this.condjump(OP_TEST, GETARG_B(ie), 0, cond != 0? 0: 1);
}
/* else go through */
}
@@ -840,7 +823,7 @@ public class FuncState extends Constants {
break;
}
default: {
- _assert (false); /* cannot happen */
+ _assert(false); /* cannot happen */
break;
}
}
@@ -855,14 +838,14 @@ public class FuncState extends Constants {
}
static boolean vkisinreg(int k) {
- return ((k) == LexState.VNONRELOC || (k) == LexState.VLOCAL);
+ return k == LexState.VNONRELOC || k == LexState.VLOCAL;
}
void indexed(expdesc t, expdesc k) {
t.u.ind_t = (short) t.u.info;
t.u.ind_idx = (short) this.exp2RK(k);
- LuaC._assert(t.k == LexState.VUPVAL || vkisinreg(t.k));
- t.u.ind_vt = (short) ((t.k == LexState.VUPVAL) ? LexState.VUPVAL : LexState.VLOCAL);
+ Constants._assert(t.k == LexState.VUPVAL || vkisinreg(t.k));
+ t.u.ind_vt = (short) (t.k == LexState.VUPVAL? LexState.VUPVAL: LexState.VLOCAL);
t.k = LexState.VINDEXED;
}
@@ -871,7 +854,7 @@ public class FuncState extends Constants {
if (!e1.isnumeral() || !e2.isnumeral())
return false;
if ((op == OP_DIV || op == OP_MOD) && e2.u.nval().eq_b(LuaValue.ZERO))
- return false; /* do not attempt to divide by 0 */
+ return false; /* do not attempt to divide by 0 */
v1 = e1.u.nval();
v2 = e2.u.nval();
switch (op) {
@@ -901,22 +884,20 @@ public class FuncState extends Constants {
// break;
return false; /* no constant folding for 'len' */
default:
- _assert (false);
+ _assert(false);
r = null;
break;
}
- if ( Double.isNaN(r.todouble()) )
+ if (Double.isNaN(r.todouble()))
return false; /* do not attempt to produce NaN */
- e1.u.setNval( r );
+ e1.u.setNval(r);
return true;
}
void codearith(int op, expdesc e1, expdesc e2, int line) {
- if (constfolding(op, e1, e2))
- return;
- else {
- int o2 = (op != OP_UNM && op != OP_LEN) ? this.exp2RK(e2)
- : 0;
+ if (constfolding(op, e1, e2)) {
+ } else {
+ int o2 = op != OP_UNM && op != OP_LEN? this.exp2RK(e2): 0;
int o1 = this.exp2RK(e1);
if (o1 > o2) {
this.freeexp(e1);
@@ -931,7 +912,7 @@ public class FuncState extends Constants {
}
}
- void codecomp(int /* OpCode */op, int cond, expdesc e1, expdesc e2) {
+ void codecomp(int /* OpCode */ op, int cond, expdesc e1, expdesc e2) {
int o1 = this.exp2RK(e1);
int o2 = this.exp2RK(e2);
this.freeexp(e2);
@@ -947,17 +928,17 @@ public class FuncState extends Constants {
e1.k = LexState.VJMP;
}
- void prefix(int /* UnOpr */op, expdesc e, int line) {
+ void prefix(int /* UnOpr */ op, expdesc e, int line) {
expdesc e2 = new expdesc();
e2.init(LexState.VKNUM, 0);
switch (op) {
case LexState.OPR_MINUS: {
- if (e.isnumeral()) /* minus constant? */
- e.u.setNval(e.u.nval().neg()); /* fold it */
- else {
- this.exp2anyreg(e);
- this.codearith(OP_UNM, e, e2, line);
- }
+ if (e.isnumeral()) /* minus constant? */
+ e.u.setNval(e.u.nval().neg()); /* fold it */
+ else {
+ this.exp2anyreg(e);
+ this.codearith(OP_UNM, e, e2, line);
+ }
break;
}
case LexState.OPR_NOT:
@@ -969,11 +950,11 @@ public class FuncState extends Constants {
break;
}
default:
- _assert (false);
+ _assert(false);
}
}
- void infix(int /* BinOpr */op, expdesc v) {
+ void infix(int /* BinOpr */ op, expdesc v) {
switch (op) {
case LexState.OPR_AND: {
this.goiftrue(v);
@@ -1004,11 +985,10 @@ public class FuncState extends Constants {
}
}
-
void posfix(int op, expdesc e1, expdesc e2, int line) {
switch (op) {
case LexState.OPR_AND: {
- _assert (e1.t.i == LexState.NO_JUMP); /* list must be closed */
+ _assert(e1.t.i == LexState.NO_JUMP); /* list must be closed */
this.dischargevars(e2);
this.concat(e2.f, e1.f.i);
// *e1 = *e2;
@@ -1016,7 +996,7 @@ public class FuncState extends Constants {
break;
}
case LexState.OPR_OR: {
- _assert (e1.f.i == LexState.NO_JUMP); /* list must be closed */
+ _assert(e1.f.i == LexState.NO_JUMP); /* list must be closed */
this.dischargevars(e2);
this.concat(e2.t, e1.t.i);
// *e1 = *e2;
@@ -1025,9 +1005,8 @@ public class FuncState extends Constants {
}
case LexState.OPR_CONCAT: {
this.exp2val(e2);
- if (e2.k == LexState.VRELOCABLE
- && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) {
- _assert (e1.u.info == GETARG_B(this.getcode(e2)) - 1);
+ if (e2.k == LexState.VRELOCABLE && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) {
+ _assert(e1.u.info == GETARG_B(this.getcode(e2))-1);
this.freeexp(e1);
SETARG_B(this.getcodePtr(e2), e1.u.info);
e1.k = LexState.VRELOCABLE;
@@ -1075,44 +1054,39 @@ public class FuncState extends Constants {
this.codecomp(OP_LE, 0, e1, e2);
break;
default:
- _assert (false);
+ _assert(false);
}
}
-
void fixline(int line) {
- this.f.lineinfo[this.pc - 1] = line;
+ this.f.lineinfo[this.pc-1] = line;
}
-
int code(int instruction, int line) {
Prototype f = this.f;
this.dischargejpc(); /* `pc' will change */
/* put new instruction in code array */
- if (f.code == null || this.pc + 1 > f.code.length)
- f.code = LuaC.realloc(f.code, this.pc * 2 + 1);
+ if (f.code == null || this.pc+1 > f.code.length)
+ f.code = Constants.realloc(f.code, this.pc*2+1);
f.code[this.pc] = instruction;
/* save corresponding line information */
- if (f.lineinfo == null || this.pc + 1 > f.lineinfo.length)
- f.lineinfo = LuaC.realloc(f.lineinfo,
- this.pc * 2 + 1);
+ if (f.lineinfo == null || this.pc+1 > f.lineinfo.length)
+ f.lineinfo = Constants.realloc(f.lineinfo, this.pc*2+1);
f.lineinfo[this.pc] = line;
return this.pc++;
}
-
int codeABC(int o, int a, int b, int c) {
- _assert (getOpMode(o) == iABC);
- _assert (getBMode(o) != OpArgN || b == 0);
- _assert (getCMode(o) != OpArgN || c == 0);
+ _assert(getOpMode(o) == iABC);
+ _assert(getBMode(o) != OpArgN || b == 0);
+ _assert(getCMode(o) != OpArgN || c == 0);
return this.code(CREATE_ABC(o, a, b, c), this.ls.lastline);
}
-
int codeABx(int o, int a, int bc) {
- _assert (getOpMode(o) == iABx || getOpMode(o) == iAsBx);
- _assert (getCMode(o) == OpArgN);
- _assert (bc >= 0 && bc <= Lua.MAXARG_Bx);
+ _assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+ _assert(getCMode(o) == OpArgN);
+ _assert(bc >= 0 && bc <= Lua.MAXARG_Bx);
return this.code(CREATE_ABx(o, a, bc), this.ls.lastline);
}
@@ -1132,16 +1106,16 @@ public class FuncState extends Constants {
}
void setlist(int base, int nelems, int tostore) {
- int c = (nelems - 1) / LFIELDS_PER_FLUSH + 1;
- int b = (tostore == LUA_MULTRET) ? 0 : tostore;
- _assert (tostore != 0);
+ int c = (nelems-1)/LFIELDS_PER_FLUSH+1;
+ int b = tostore == LUA_MULTRET? 0: tostore;
+ _assert(tostore != 0);
if (c <= MAXARG_C)
this.codeABC(OP_SETLIST, base, b, c);
else {
this.codeABC(OP_SETLIST, base, b, 0);
this.code(c, this.ls.lastline);
}
- this.freereg = (short) (base + 1); /* free registers with list values */
+ this.freereg = (short) (base+1); /* free registers with list values */
}
-
+
}
diff --git a/src/core/org/luaj/vm2/compiler/InstructionPtr.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java
similarity index 95%
rename from src/core/org/luaj/vm2/compiler/InstructionPtr.java
rename to luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java
index fbdf061a..6536737c 100644
--- a/src/core/org/luaj/vm2/compiler/InstructionPtr.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java
@@ -10,7 +10,7 @@
*
* 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
@@ -23,15 +23,18 @@ package org.luaj.vm2.compiler;
class InstructionPtr {
final int[] code;
- final int idx;
- InstructionPtr(int[] code, int idx ) {
+ final int idx;
+
+ InstructionPtr(int[] code, int idx) {
this.code = code;
this.idx = idx;
}
+
int get() {
return code[idx];
}
+
void set(int value) {
code[idx] = value;
}
-}
\ No newline at end of file
+}
diff --git a/src/core/org/luaj/vm2/compiler/IntPtr.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java
similarity index 99%
rename from src/core/org/luaj/vm2/compiler/IntPtr.java
rename to luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java
index 0f42cb0e..3e9fd16d 100644
--- a/src/core/org/luaj/vm2/compiler/IntPtr.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java
@@ -10,7 +10,7 @@
*
* 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
@@ -23,8 +23,10 @@ package org.luaj.vm2.compiler;
public class IntPtr {
int i;
+
IntPtr() {
}
+
IntPtr(int value) {
this.i = value;
}
diff --git a/src/core/org/luaj/vm2/compiler/LexState.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java
similarity index 67%
rename from src/core/org/luaj/vm2/compiler/LexState.java
rename to luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java
index 0192de05..57af5f6e 100644
--- a/src/core/org/luaj/vm2/compiler/LexState.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java
@@ -10,7 +10,7 @@
*
* 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
@@ -35,113 +35,100 @@ import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.FuncState.BlockCnt;
import org.luaj.vm2.lib.MathLib;
-
public class LexState extends Constants {
-
- 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_GENERATOR = "(for generator)";
- protected static final String RESERVED_LOCAL_VAR_FOR_STEP = "(for step)";
- protected static final String RESERVED_LOCAL_VAR_FOR_LIMIT = "(for limit)";
- protected static final String RESERVED_LOCAL_VAR_FOR_INDEX = "(for index)";
-
- // keywords array
- protected static final String[] RESERVED_LOCAL_VAR_KEYWORDS = new String[] {
- RESERVED_LOCAL_VAR_FOR_CONTROL,
- RESERVED_LOCAL_VAR_FOR_GENERATOR,
- RESERVED_LOCAL_VAR_FOR_INDEX,
- RESERVED_LOCAL_VAR_FOR_LIMIT,
- RESERVED_LOCAL_VAR_FOR_STATE,
- RESERVED_LOCAL_VAR_FOR_STEP
- };
- private static final Hashtable RESERVED_LOCAL_VAR_KEYWORDS_TABLE = new Hashtable();
- static {
- for ( int i=0; i=", "<=", "~=",
- "::", "", "", "", "", "",
+ "::", "", "", "", ""
};
final static int
- /* terminal symbols denoted by reserved words */
- TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261,
- TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_GOTO=266, TK_IF=267,
- TK_IN=268, TK_LOCAL=269, TK_NIL=270, TK_NOT=271, TK_OR=272, TK_REPEAT=273,
- TK_RETURN=274, TK_THEN=275, TK_TRUE=276, TK_UNTIL=277, TK_WHILE=278,
+ /* terminal symbols denoted by reserved words */
+ TK_AND = 257, TK_BREAK = 258, TK_DO = 259, TK_ELSE = 260, TK_ELSEIF = 261, TK_END = 262, TK_FALSE = 263,
+ TK_FOR = 264, TK_FUNCTION = 265, TK_GOTO = 266, TK_IF = 267, TK_IN = 268, TK_LOCAL = 269, TK_NIL = 270,
+ TK_NOT = 271, TK_OR = 272, TK_REPEAT = 273, TK_RETURN = 274, TK_THEN = 275, TK_TRUE = 276, TK_UNTIL = 277,
+ TK_WHILE = 278,
/* other terminal symbols */
TK_CONCAT=279, TK_DOTS=280, TK_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284,
- TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289;
-
+ TK_DBCOLON=285, TK_EOF=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289;
+
final static int FIRST_RESERVED = TK_AND;
- final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED;
-
+ final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED;
+
final static Hashtable RESERVED = new Hashtable();
static {
- for ( int i=0; i= '0' && c <= '9')
- || (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c == '_');
+ return c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_';
// return Character.isLetterOrDigit(c);
}
-
+
private boolean isalpha(int c) {
- return (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z');
+ return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
-
+
private boolean isdigit(int c) {
- return (c >= '0' && c <= '9');
+ return c >= '0' && c <= '9';
}
-
+
private boolean isxdigit(int c) {
- return (c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'f')
- || (c >= 'A' && c <= 'F');
+ return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F';
}
-
+
private boolean isspace(int c) {
- return (c >= 0 && c <= ' ');
+ return c >= 0 && c <= ' ';
}
-
-
+
public LexState(LuaC.CompileState state, InputStream stream) {
this.z = stream;
this.buff = new char[32];
@@ -210,8 +190,8 @@ public class LexState extends Constants {
void nextChar() {
try {
- current = z.read();
- } catch ( IOException e ) {
+ current = z.read();
+ } catch (IOException e) {
e.printStackTrace();
current = EOZ;
}
@@ -222,22 +202,19 @@ public class LexState extends Constants {
}
void save_and_next() {
- save( current );
+ save(current);
nextChar();
}
void save(int c) {
- if ( buff == null || nbuff + 1 > buff.length )
- buff = realloc( buff, nbuff*2+1 );
+ if (buff == null || nbuff+1 > buff.length)
+ buff = realloc(buff, nbuff*2+1);
buff[nbuff++] = (char) c;
}
-
- String token2str( int token ) {
- if ( token < FIRST_RESERVED ) {
- return iscntrl(token)?
- L.pushfstring( "char("+((int)token)+")" ):
- L.pushfstring( String.valueOf( (char) token ) );
+ String token2str(int token) {
+ if (token < FIRST_RESERVED) {
+ return iscntrl(token)? L.pushfstring("char(" + token + ")"): L.pushfstring(String.valueOf((char) token));
} else {
return luaX_tokens[token-FIRST_RESERVED];
}
@@ -248,69 +225,67 @@ public class LexState extends Constants {
}
String txtToken(int token) {
- switch ( token ) {
+ switch (token) {
case TK_NAME:
case TK_STRING:
case TK_NUMBER:
- return new String( buff, 0, nbuff );
+ return new String(buff, 0, nbuff);
default:
- return token2str( token );
+ return token2str(token);
}
}
- void lexerror( String msg, int token ) {
- String cid = Lua.chunkid( source.tojstring() );
- L.pushfstring( cid+":"+linenumber+": "+msg );
- if ( token != 0 )
- L.pushfstring( "syntax error: "+msg+" near "+txtToken(token) );
- throw new LuaError(cid+":"+linenumber+": "+msg);
+ void lexerror(String msg, int token) {
+ String cid = Lua.chunkid(source.tojstring());
+ L.pushfstring(cid + ":" + linenumber + ": " + msg);
+ if (token != 0)
+ L.pushfstring("syntax error: " + msg + " near " + txtToken(token));
+ throw new LuaError(cid + ":" + linenumber + ": " + msg);
}
- void syntaxerror( String msg ) {
- lexerror( msg, t.token );
+ void syntaxerror(String msg) {
+ lexerror(msg, t.token);
}
// only called by new_localvarliteral() for var names.
- LuaString newstring( String s ) {
+ LuaString newstring(String s) {
return L.newTString(s);
}
- LuaString newstring( char[] chars, int offset, int len ) {
+ LuaString newstring(char[] chars, int offset, int len) {
return L.newTString(new String(chars, offset, len));
}
void inclinenumber() {
int old = current;
- _assert( currIsNewline() );
+ _assert(currIsNewline());
nextChar(); /* skip '\n' or '\r' */
- if ( currIsNewline() && current != old )
+ if (currIsNewline() && current != old)
nextChar(); /* skip '\n\r' or '\r\n' */
- if ( ++linenumber >= MAX_INT )
+ if (++linenumber >= MAX_INT)
syntaxerror("chunk has too many lines");
}
void setinput(LuaC.CompileState L, int firstByte, InputStream z, LuaString source) {
this.decpoint = '.';
this.L = L;
- this.lookahead.token = TK_EOS; /* no look-ahead token */
+ this.lookahead.token = TK_EOF; /* no look-ahead token */
this.z = z;
this.fs = null;
this.linenumber = 1;
this.lastline = 1;
this.source = source;
- this.envn = LuaValue.ENV; /* environment variable name */
- this.nbuff = 0; /* initialize buffer */
+ this.envn = LuaValue.ENV; /* environment variable name */
+ this.nbuff = 0; /* initialize buffer */
this.current = firstByte; /* read first char */
this.skipShebang();
}
-
+
private void skipShebang() {
- if ( current == '#' )
- while (!currIsNewline() && current != EOZ)
+ if (current == '#')
+ while ( !currIsNewline() && current != EOZ )
nextChar();
}
-
-
/*
** =======================================================
@@ -318,7 +293,6 @@ public class LexState extends Constants {
** =======================================================
*/
-
boolean check_next(String set) {
if (set.indexOf(current) < 0)
return false;
@@ -329,7 +303,7 @@ public class LexState extends Constants {
void buffreplace(char from, char to) {
int n = nbuff;
char[] p = buff;
- while ((--n) >= 0)
+ while ( --n >= 0 )
if (p[n] == from)
p[n] = to;
}
@@ -337,7 +311,7 @@ public class LexState extends Constants {
LuaValue strx2number(String str, SemInfo seminfo) {
char[] c = str.toCharArray();
int s = 0;
- while ( s < c.length && isspace(c[s]))
+ while ( s < c.length && isspace(c[s]) )
++s;
// Check for negative sign
double sgn = 1.0;
@@ -346,24 +320,20 @@ public class LexState extends Constants {
++s;
}
/* Check for "0x" */
- if (s + 2 >= c.length )
- return LuaValue.ZERO;
- if (c[s++] != '0')
- return LuaValue.ZERO;
- if (c[s] != 'x' && c[s] != 'X')
+ if (s+2 >= c.length || c[s++] != '0' || c[s] != 'x' && c[s] != 'X')
return LuaValue.ZERO;
++s;
// read integer part.
double m = 0;
int e = 0;
- while (s < c.length && isxdigit(c[s]))
- m = (m * 16) + hexvalue(c[s++]);
+ while ( s < c.length && isxdigit(c[s]) )
+ m = m*16+hexvalue(c[s++]);
if (s < c.length && c[s] == '.') {
- ++s; // skip dot
- while (s < c.length && isxdigit(c[s])) {
- m = (m * 16) + hexvalue(c[s++]);
- e -= 4; // Each fractional part shifts right by 2^4
+ ++s; // skip dot
+ while ( s < c.length && isxdigit(c[s]) ) {
+ m = m*16+hexvalue(c[s++]);
+ e -= 4; // Each fractional part shifts right by 2^4
}
}
if (s < c.length && (c[s] == 'p' || c[s] == 'P')) {
@@ -374,19 +344,19 @@ public class LexState extends Constants {
neg1 = true;
++s;
}
- while (s < c.length && isdigit(c[s]))
- exp1 = exp1 * 10 + c[s++] - '0';
+ while ( s < c.length && isdigit(c[s]) )
+ exp1 = exp1*10+c[s++]-'0';
if (neg1)
exp1 = -exp1;
e += exp1;
}
- return LuaValue.valueOf(sgn * m * MathLib.dpow_d(2.0, e));
+ return LuaValue.valueOf(sgn*m*MathLib.dpow_d(2.0, e));
}
-
+
boolean str2d(String str, SemInfo seminfo) {
- if (str.indexOf('n')>=0 || str.indexOf('N')>=0)
+ if (str.indexOf('n') >= 0 || str.indexOf('N') >= 0)
seminfo.r = LuaValue.ZERO;
- else if (str.indexOf('x')>=0 || str.indexOf('X')>=0)
+ else if (str.indexOf('x') >= 0 || str.indexOf('X') >= 0)
seminfo.r = strx2number(str, seminfo);
else {
try {
@@ -401,14 +371,14 @@ public class LexState extends Constants {
void read_numeral(SemInfo seminfo) {
String expo = "Ee";
int first = current;
- _assert (isdigit(current));
+ _assert(isdigit(current));
save_and_next();
if (first == '0' && check_next("Xx"))
expo = "Pp";
- while (true) {
+ while ( true ) {
if (check_next(expo))
check_next("+-");
- if(isxdigit(current) || current == '.')
+ if (isxdigit(current) || current == '.')
save_and_next();
else
break;
@@ -420,13 +390,13 @@ public class LexState extends Constants {
int skip_sep() {
int count = 0;
int s = current;
- _assert (s == '[' || s == ']');
+ _assert(s == '[' || s == ']');
save_and_next();
- while (current == '=') {
+ while ( current == '=' ) {
save_and_next();
count++;
}
- return (current == s) ? count : (-count) - 1;
+ return current == s? count: (-count)-1;
}
void read_long_string(SemInfo seminfo, int sep) {
@@ -438,7 +408,7 @@ public class LexState extends Constants {
switch (current) {
case EOZ:
lexerror((seminfo != null) ? "unfinished long string"
- : "unfinished long comment", TK_EOS);
+ : "unfinished long comment", TK_EOF);
break; /* to avoid warnings */
case '[': {
if (skip_sep() == sep) {
@@ -480,11 +450,11 @@ public class LexState extends Constants {
}
}
if (seminfo != null)
- seminfo.ts = L.newTString(LuaString.valueOf(buff, 2 + sep, nbuff - 2 * (2 + sep)));
+ seminfo.ts = L.newTString(LuaString.valueOf(buff, 2+sep, nbuff-2*(2+sep)));
}
int hexvalue(int c) {
- return c <= '9'? c - '0': c <= 'F'? c + 10 - 'A': c + 10 - 'a';
+ return c <= '9'? c-'0': c <= 'F'? c+10-'A': c+10-'a';
}
int readhexaesc() {
@@ -493,16 +463,16 @@ public class LexState extends Constants {
nextChar();
int c2 = current;
if (!isxdigit(c1) || !isxdigit(c2))
- lexerror("hexadecimal digit expected 'x"+((char)c1)+((char)c2), TK_STRING);
- return (hexvalue(c1) << 4) + hexvalue(c2);
+ lexerror("hexadecimal digit expected 'x" + (char) c1 + (char) c2, TK_STRING);
+ return (hexvalue(c1)<<4)+hexvalue(c2);
}
void read_string(int del, SemInfo seminfo) {
save_and_next();
- while (current != del) {
+ while ( current != del ) {
switch (current) {
case EOZ:
- lexerror("unfinished string", TK_EOS);
+ lexerror("unfinished string", TK_EOF);
continue; /* to avoid warnings */
case '\n':
case '\r':
@@ -543,14 +513,16 @@ public class LexState extends Constants {
continue;
case EOZ:
continue; /* will raise an error next loop */
- case 'z': { /* zap following span of spaces */
- nextChar(); /* skip the 'z' */
- while (isspace(current)) {
- if (currIsNewline()) inclinenumber();
- else nextChar();
- }
- continue;
- }
+ case 'z': { /* zap following span of spaces */
+ nextChar(); /* skip the 'z' */
+ while ( isspace(current) ) {
+ if (currIsNewline())
+ inclinenumber();
+ else
+ nextChar();
+ }
+ continue;
+ }
default: {
if (!isdigit(current))
save_and_next(); /* handles \\, \", \', and \? */
@@ -558,9 +530,9 @@ public class LexState extends Constants {
int i = 0;
c = 0;
do {
- c = 10 * c + (current - '0');
+ c = 10*c+current-'0';
nextChar();
- } while (++i < 3 && isdigit(current));
+ } while ( ++i < 3 && isdigit(current) );
if (c > UCHAR_MAX)
lexerror("escape sequence too large", TK_STRING);
save(c);
@@ -582,7 +554,7 @@ public class LexState extends Constants {
int llex(SemInfo seminfo) {
nbuff = 0;
- while (true) {
+ while ( true ) {
switch (current) {
case '\n':
case '\r': {
@@ -612,7 +584,7 @@ public class LexState extends Constants {
}
}
/* else short comment */
- while (!currIsNewline() && current != EOZ)
+ while ( !currIsNewline() && current != EOZ )
nextChar();
continue;
}
@@ -696,7 +668,7 @@ public class LexState extends Constants {
return TK_NUMBER;
}
case EOZ: {
- return TK_EOS;
+ return TK_EOF;
}
default: {
if (isalpha(current) || current == '_') {
@@ -704,10 +676,10 @@ public class LexState extends Constants {
LuaString ts;
do {
save_and_next();
- } while (isalnum(current));
+ } while ( isalnum(current) );
ts = newstring(buff, 0, nbuff);
- if ( RESERVED.containsKey(ts) )
- return ((Integer)RESERVED.get(ts)).intValue();
+ if (RESERVED.containsKey(ts))
+ return ((Integer) RESERVED.get(ts)).intValue();
else {
seminfo.ts = ts;
return TK_NAME;
@@ -724,54 +696,56 @@ public class LexState extends Constants {
void next() {
lastline = linenumber;
- if (lookahead.token != TK_EOS) { /* is there a look-ahead token? */
+ if (lookahead.token != TK_EOF) { /* is there a look-ahead token? */
t.set( lookahead ); /* use this one */
- lookahead.token = TK_EOS; /* and discharge it */
+ lookahead.token = TK_EOF; /* and discharge it */
} else
t.token = llex(t.seminfo); /* read next token */
}
void lookahead() {
- _assert (lookahead.token == TK_EOS);
+ _assert (lookahead.token == TK_EOF);
lookahead.token = llex(lookahead.seminfo);
}
// =============================================================
// from lcode.h
// =============================================================
-
-
+
// =============================================================
// from lparser.c
// =============================================================
static final boolean vkisvar(final int k) {
- return (VLOCAL <= (k) && (k) <= VINDEXED);
+ return VLOCAL <= k && k <= VINDEXED;
}
static final boolean vkisinreg(final int k) {
- return ((k) == VNONRELOC || (k) == VLOCAL);
+ return k == VNONRELOC || k == VLOCAL;
}
static class expdesc {
int k; // expkind, from enumerated list, above
+
static class U { // originally a union
- short ind_idx; // index (R/K)
- short ind_t; // table(register or upvalue)
- short ind_vt; // whether 't' is register (VLOCAL) or (UPVALUE)
+ short ind_idx; // index (R/K)
+ short ind_t; // table(register or upvalue)
+ short ind_vt; // whether 't' is register (VLOCAL) or (UPVALUE)
private LuaValue _nval;
- int info;
- public void setNval(LuaValue r) {
- _nval = r;
- }
+ int info;
+
+ public void setNval(LuaValue r) { _nval = r; }
+
public LuaValue nval() {
- return (_nval == null? LuaInteger.valueOf(info): _nval);
+ return _nval == null? LuaInteger.valueOf(info): _nval;
}
- };
- final U u = new U();
+ }
+
+ final U u = new U();
final IntPtr t = new IntPtr(); /* patch list of `exit when true' */
final IntPtr f = new IntPtr(); /* patch list of `exit when false' */
- void init( int k, int i ) {
+
+ void init(int k, int i) {
this.f.i = NO_JUMP;
this.t.i = NO_JUMP;
this.k = k;
@@ -779,11 +753,11 @@ public class LexState extends Constants {
}
boolean hasjumps() {
- return (t.i != f.i);
+ return t.i != f.i;
}
boolean isnumeral() {
- return (k == VKNUM && t.i == NO_JUMP && f.i == NO_JUMP);
+ return k == VKNUM && t.i == NO_JUMP && f.i == NO_JUMP;
}
public void setvalue(expdesc other) {
@@ -798,44 +772,42 @@ public class LexState extends Constants {
}
}
-
/* description of active local variable */
static class Vardesc {
- final short idx; /* variable index in stack */
+ final short idx; /* variable index in stack */
+
Vardesc(int idx) {
this.idx = (short) idx;
}
- };
-
+ }
/* description of pending goto statements and label statements */
static class Labeldesc {
- LuaString name; /* label identifier */
- int pc; /* position in code */
- int line; /* line where it appeared */
- short nactvar; /* local level where it appears in current block */
+ LuaString name; /* label identifier */
+ int pc; /* position in code */
+ int line; /* line where it appeared */
+ short nactvar; /* local level where it appears in current block */
+
public Labeldesc(LuaString name, int pc, int line, short nactvar) {
this.name = name;
this.pc = pc;
this.line = line;
this.nactvar = nactvar;
}
- };
-
+ }
/* dynamic structures used by the parser */
static class Dyndata {
- Vardesc[] actvar; /* list of active local variables */
- int n_actvar = 0;
- Labeldesc[] gt; /* list of pending gotos */
- int n_gt = 0;
- Labeldesc[] label; /* list of active labels */
- int n_label = 0;
- };
-
-
+ Vardesc[] actvar; /* list of active local variables */
+ int n_actvar = 0;
+ Labeldesc[] gt; /* list of pending gotos */
+ int n_gt = 0;
+ Labeldesc[] label; /* list of active labels */
+ int n_label = 0;
+ }
+
boolean hasmultret(int k) {
- return ((k) == VCALL || (k) == VVARARG);
+ return k == VCALL || k == VVARARG;
}
/*----------------------------------------------------------------------
@@ -843,8 +815,8 @@ public class LexState extends Constants {
------------------------------------------------------------------------*/
void anchor_token () {
- /* last token from outer function must be EOS */
- _assert(fs != null || t.token == TK_EOS);
+ /* last token from outer function must be EOF */
+ _assert(fs != null || t.token == TK_EOF);
if (t.token == TK_NAME || t.token == TK_STRING) {
LuaString ts = t.seminfo.ts;
// TODO: is this necessary?
@@ -853,8 +825,8 @@ public class LexState extends Constants {
}
/* semantic error */
- void semerror (String msg) {
- t.token = 0; /* remove 'near to' from final message */
+ void semerror(String msg) {
+ t.token = 0; /* remove 'near to' from final message */
syntaxerror(msg);
}
@@ -875,25 +847,23 @@ public class LexState extends Constants {
error_expected(c);
}
- void checknext (int c) {
- check(c);
- next();
+ void checknext(int c) {
+ check(c);
+ next();
}
void check_condition(boolean c, String msg) {
- if (!(c))
+ if (!c)
syntaxerror(msg);
}
-
void check_match(int what, int who, int where) {
if (!testnext(what)) {
if (where == linenumber)
error_expected(what);
else {
- syntaxerror(L.pushfstring(LUA_QS(token2str(what))
- + " expected " + "(to close " + LUA_QS(token2str(who))
- + " at line " + where + ")"));
+ syntaxerror(L.pushfstring(LUA_QS(token2str(what)) + " expected " + "(to close " + LUA_QS(token2str(who))
+ + " at line " + where + ")"));
}
}
}
@@ -905,7 +875,7 @@ public class LexState extends Constants {
next();
return ts;
}
-
+
void codestring(expdesc e, LuaString s) {
e.init(VK, fs.stringK(s));
}
@@ -914,21 +884,20 @@ public class LexState extends Constants {
codestring(e, str_checkname());
}
-
int registerlocalvar(LuaString varname) {
FuncState fs = this.fs;
Prototype f = fs.f;
- if (f.locvars == null || fs.nlocvars + 1 > f.locvars.length)
- f.locvars = realloc( f.locvars, fs.nlocvars*2+1 );
- f.locvars[fs.nlocvars] = new LocVars(varname,0,0);
+ if (f.locvars == null || fs.nlocvars+1 > f.locvars.length)
+ f.locvars = realloc(f.locvars, fs.nlocvars*2+1);
+ f.locvars[fs.nlocvars] = new LocVars(varname, 0, 0);
return fs.nlocvars++;
}
-
+
void new_localvar(LuaString name) {
int reg = registerlocalvar(name);
- fs.checklimit(dyd.n_actvar + 1, FuncState.LUAI_MAXVARS, "local variables");
- if (dyd.actvar == null || dyd.n_actvar + 1 > dyd.actvar.length)
- dyd.actvar = realloc(dyd.actvar, Math.max(1, dyd.n_actvar * 2));
+ fs.checklimit(dyd.n_actvar+1, Constants.LUAI_MAXVARS, "local variables");
+ if (dyd.actvar == null || dyd.n_actvar+1 > dyd.actvar.length)
+ dyd.actvar = realloc(dyd.actvar, Math.max(1, dyd.n_actvar*2));
dyd.actvar[dyd.n_actvar++] = new Vardesc(reg);
}
@@ -939,33 +908,33 @@ public class LexState extends Constants {
void adjustlocalvars(int nvars) {
FuncState fs = this.fs;
- fs.nactvar = (short) (fs.nactvar + nvars);
+ fs.nactvar = (short) (fs.nactvar+nvars);
for (; nvars > 0; nvars--) {
- fs.getlocvar(fs.nactvar - nvars).startpc = fs.pc;
+ fs.getlocvar(fs.nactvar-nvars).startpc = fs.pc;
}
}
void removevars(int tolevel) {
FuncState fs = this.fs;
- while (fs.nactvar > tolevel)
+ while ( fs.nactvar > tolevel )
fs.getlocvar(--fs.nactvar).endpc = fs.pc;
}
-
+
void singlevar(expdesc var) {
LuaString varname = this.str_checkname();
FuncState fs = this.fs;
if (FuncState.singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */
expdesc key = new expdesc();
- FuncState.singlevaraux(fs, this.envn, var, 1); /* get environment variable */
- _assert(var.k == VLOCAL || var.k == VUPVAL);
- this.codestring(key, varname); /* key is variable name */
- fs.indexed(var, key); /* env[varname] */
+ FuncState.singlevaraux(fs, this.envn, var, 1); /* get environment variable */
+ _assert(var.k == VLOCAL || var.k == VUPVAL);
+ this.codestring(key, varname); /* key is variable name */
+ fs.indexed(var, key); /* env[varname] */
}
}
-
+
void adjust_assign(int nvars, int nexps, expdesc e) {
FuncState fs = this.fs;
- int extra = nvars - nexps;
+ int extra = nvars-nexps;
if (hasmultret(e.k)) {
/* includes call itself */
extra++;
@@ -974,7 +943,7 @@ public class LexState extends Constants {
/* last exp. provides the difference */
fs.setreturns(e, extra);
if (extra > 1)
- fs.reserveregs(extra - 1);
+ fs.reserveregs(extra-1);
} else {
/* close last expression */
if (e.k != VVOID)
@@ -986,12 +955,12 @@ public class LexState extends Constants {
}
}
}
-
+
void enterlevel() {
if (++L.nCcalls > LUAI_MAXCCALLS)
lexerror("chunk has too many syntax levels", 0);
}
-
+
void leavelevel() {
L.nCcalls--;
}
@@ -1003,21 +972,20 @@ public class LexState extends Constants {
_assert(gt.name.eq_b(label.name));
if (gt.nactvar < label.nactvar) {
LuaString vname = fs.getlocvar(gt.nactvar).varname;
- String msg = L.pushfstring(" at line "
- + gt.line + " jumps into the scope of local '"
- + vname.tojstring() + "'");
+ String msg = L.pushfstring(" at line " + gt.line + " jumps into the scope of local '"
+ + vname.tojstring() + "'");
semerror(msg);
}
fs.patchlist(gt.pc, label.pc);
/* remove goto from pending list */
- System.arraycopy(gl, g + 1, gl, g, this.dyd.n_gt - g - 1);
+ System.arraycopy(gl, g+1, gl, g, this.dyd.n_gt-g-1);
gl[--this.dyd.n_gt] = null;
}
/*
** try to close a goto with existing labels; this solves backward jumps
*/
- boolean findlabel (int g) {
+ boolean findlabel(int g) {
int i;
BlockCnt bl = fs.bl;
Dyndata dyd = this.dyd;
@@ -1025,15 +993,14 @@ public class LexState extends Constants {
/* check labels in current block for a match */
for (i = bl.firstlabel; i < dyd.n_label; i++) {
Labeldesc lb = dyd.label[i];
- if (lb.name.eq_b(gt.name)) { /* correct label? */
- if (gt.nactvar > lb.nactvar &&
- (bl.upval || dyd.n_label > bl.firstlabel))
+ if (lb.name.eq_b(gt.name)) { /* correct label? */
+ if (gt.nactvar > lb.nactvar && (bl.upval || dyd.n_label > bl.firstlabel))
fs.patchclose(gt.pc, lb.nactvar);
- closegoto(g, lb); /* close it */
+ closegoto(g, lb); /* close it */
return true;
}
}
- return false; /* label not found; cannot close goto */
+ return false; /* label not found; cannot close goto */
}
/* Caller must grow() the vector before calling this. */
@@ -1046,24 +1013,23 @@ public class LexState extends Constants {
** check whether new label 'lb' matches any pending gotos in current
** block; solves forward jumps
*/
- void findgotos (Labeldesc lb) {
+ void findgotos(Labeldesc lb) {
Labeldesc[] gl = dyd.gt;
int i = fs.bl.firstgoto;
- while (i < dyd.n_gt) {
+ while ( i < dyd.n_gt ) {
if (gl[i].name.eq_b(lb.name))
closegoto(i, lb);
else
i++;
}
}
-
/*
** create a label named "break" to resolve break statements
*/
- void breaklabel () {
+ void breaklabel() {
LuaString n = LuaString.valueOf("break");
- int l = newlabelentry(dyd.label=grow(dyd.label, dyd.n_label+1), dyd.n_label++, n, 0, fs.pc);
+ int l = newlabelentry(dyd.label = grow(dyd.label, dyd.n_label+1), dyd.n_label++, n, 0, fs.pc);
findgotos(dyd.label[l]);
}
@@ -1071,47 +1037,47 @@ public class LexState extends Constants {
** generates an error for an undefined 'goto'; choose appropriate
** message when label name is a reserved word (which can only be 'break')
*/
- void undefgoto (Labeldesc gt) {
- String msg = L.pushfstring(isReservedKeyword(gt.name.tojstring())
- ? "<"+gt.name+"> at line "+gt.line+" not inside a loop"
- : "no visible label '"+gt.name+"' for at line "+gt.line);
- semerror(msg);
+ void undefgoto(Labeldesc gt) {
+ String msg = L.pushfstring(
+ isReservedKeyword(gt.name.tojstring())? "<" + gt.name + "> at line " + gt.line + " not inside a loop"
+ : "no visible label '" + gt.name + "' for at line " + gt.line);
+ semerror(msg);
}
- Prototype addprototype () {
- Prototype clp;
- Prototype f = fs.f; /* prototype of current function */
- if (f.p == null || fs.np >= f.p.length) {
- f.p = realloc(f.p, Math.max(1, fs.np * 2));
- }
- f.p[fs.np++] = clp = new Prototype();
- return clp;
+ Prototype addprototype() {
+ Prototype clp;
+ Prototype f = fs.f; /* prototype of current function */
+ if (f.p == null || fs.np >= f.p.length) {
+ f.p = realloc(f.p, Math.max(1, fs.np*2));
+ }
+ f.p[fs.np++] = clp = new Prototype();
+ return clp;
}
- void codeclosure (expdesc v) {
- FuncState fs = this.fs.prev;
- v.init(VRELOCABLE, fs.codeABx(OP_CLOSURE, 0, fs.np - 1));
- fs.exp2nextreg(v); /* fix it at stack top (for GC) */
+ void codeclosure(expdesc v) {
+ FuncState fs = this.fs.prev;
+ v.init(VRELOCABLE, fs.codeABx(OP_CLOSURE, 0, fs.np-1));
+ fs.exp2nextreg(v); /* fix it at stack top (for GC) */
}
- void open_func (FuncState fs, BlockCnt bl) {
- fs.prev = this.fs; /* linked list of funcstates */
- fs.ls = this;
- this.fs = fs;
- fs.pc = 0;
- fs.lasttarget = -1;
- fs.jpc = new IntPtr( NO_JUMP );
- fs.freereg = 0;
- fs.nk = 0;
- fs.np = 0;
- fs.nups = 0;
- fs.nlocvars = 0;
- fs.nactvar = 0;
- fs.firstlocal = dyd.n_actvar;
- fs.bl = null;
- fs.f.source = this.source;
- fs.f.maxstacksize = 2; /* registers 0/1 are always valid */
- fs.enterblock(bl, false);
+ void open_func(FuncState fs, BlockCnt bl) {
+ fs.prev = this.fs; /* linked list of funcstates */
+ fs.ls = this;
+ this.fs = fs;
+ fs.pc = 0;
+ fs.lasttarget = -1;
+ fs.jpc = new IntPtr(NO_JUMP);
+ fs.freereg = 0;
+ fs.nk = 0;
+ fs.np = 0;
+ fs.nups = 0;
+ fs.nlocvars = 0;
+ fs.nactvar = 0;
+ fs.firstlocal = dyd.n_actvar;
+ fs.bl = null;
+ fs.f.source = this.source;
+ fs.f.maxstacksize = 2; /* registers 0/1 are always valid */
+ fs.enterblock(bl, false);
}
void close_func() {
@@ -1125,7 +1091,7 @@ public class LexState extends Constants {
f.p = realloc(f.p, fs.np);
f.locvars = realloc(f.locvars, fs.nlocvars);
f.upvalues = realloc(f.upvalues, fs.nups);
- _assert (fs.bl == null);
+ _assert(fs.bl == null);
this.fs = fs.prev;
// last token read was anchored in defunct function; must reanchor it
// ls.anchor_token();
@@ -1144,7 +1110,7 @@ public class LexState extends Constants {
this.checkname(key);
fs.indexed(v, key);
}
-
+
void yindex(expdesc v) {
/* index -> '[' expr ']' */
this.next(); /* skip the '[' */
@@ -1153,22 +1119,19 @@ public class LexState extends Constants {
this.checknext(']');
}
-
- /*
+ /*
** {======================================================================
** Rules for Constructors
** =======================================================================
*/
-
static class ConsControl {
expdesc v = new expdesc(); /* last list item read */
- expdesc t; /* table descriptor */
- int nh; /* total number of `record' elements */
- int na; /* total number of array elements */
- int tostore; /* number of array elements pending to be stored */
- };
-
+ expdesc t; /* table descriptor */
+ int nh; /* total number of `record' elements */
+ int na; /* total number of array elements */
+ int tostore; /* number of array elements pending to be stored */
+ }
void recfield(ConsControl cc) {
/* recfield -> (NAME | `['exp1`]') = exp1 */
@@ -1188,17 +1151,16 @@ public class LexState extends Constants {
rkkey = fs.exp2RK(key);
this.expr(val);
fs.codeABC(Lua.OP_SETTABLE, cc.t.u.info, rkkey, fs.exp2RK(val));
- fs.freereg = (short)reg; /* free registers */
+ fs.freereg = (short) reg; /* free registers */
}
- void listfield (ConsControl cc) {
- this.expr(cc.v);
- fs.checklimit(cc.na, MAX_INT, "items in a constructor");
- cc.na++;
- cc.tostore++;
+ void listfield(ConsControl cc) {
+ this.expr(cc.v);
+ fs.checklimit(cc.na, MAX_INT, "items in a constructor");
+ cc.na++;
+ cc.tostore++;
}
-
void constructor(expdesc t) {
/* constructor -> ?? */
FuncState fs = this.fs;
@@ -1212,7 +1174,7 @@ public class LexState extends Constants {
fs.exp2nextreg(t); /* fix it at stack top (for gc) */
this.checknext('{');
do {
- _assert (cc.v.k == VVOID || cc.tostore > 0);
+ _assert(cc.v.k == VVOID || cc.tostore > 0);
if (this.t.token == '}')
break;
fs.closelistfield(cc);
@@ -1234,61 +1196,62 @@ public class LexState extends Constants {
break;
}
}
- } while (this.testnext(',') || this.testnext(';'));
+ } while ( this.testnext(',') || this.testnext(';') );
this.check_match('}', '{', line);
fs.lastlistfield(cc);
InstructionPtr i = new InstructionPtr(fs.f.code, pc);
SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
- SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
+ SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
}
-
+
/*
** converts an integer to a "floating point byte", represented as
** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
** eeeee != 0 and (xxx) otherwise.
*/
- static int luaO_int2fb (int x) {
- int e = 0; /* expoent */
- while (x >= 16) {
- x = (x+1) >> 1;
- e++;
- }
- if (x < 8) return x;
- else return ((e+1) << 3) | (((int)x) - 8);
+ static int luaO_int2fb(int x) {
+ int e = 0; /* expoent */
+ while ( x >= 16 ) {
+ x = x+1>>1;
+ e++;
+ }
+ if (x < 8)
+ return x;
+ else
+ return e+1<<3 | x-8;
}
-
/* }====================================================================== */
- void parlist () {
- /* parlist -> [ param { `,' param } ] */
- FuncState fs = this.fs;
- Prototype f = fs.f;
- int nparams = 0;
- f.is_vararg = 0;
- if (this.t.token != ')') { /* is `parlist' not empty? */
- do {
- switch (this.t.token) {
- case TK_NAME: { /* param . NAME */
- this.new_localvar(this.str_checkname());
- ++nparams;
- break;
- }
- case TK_DOTS: { /* param . `...' */
- this.next();
- f.is_vararg = 1;
- break;
- }
- default: this.syntaxerror(" or " + LUA_QL("...") + " expected");
- }
- } while ((f.is_vararg==0) && this.testnext(','));
- }
- this.adjustlocalvars(nparams);
- f.numparams = fs.nactvar;
- fs.reserveregs(fs.nactvar); /* reserve register for parameters */
+ void parlist() {
+ /* parlist -> [ param { `,' param } ] */
+ FuncState fs = this.fs;
+ Prototype f = fs.f;
+ int nparams = 0;
+ f.is_vararg = 0;
+ if (this.t.token != ')') { /* is `parlist' not empty? */
+ do {
+ switch (this.t.token) {
+ case TK_NAME: { /* param . NAME */
+ this.new_localvar(this.str_checkname());
+ ++nparams;
+ break;
+ }
+ case TK_DOTS: { /* param . `...' */
+ this.next();
+ f.is_vararg = 1;
+ break;
+ }
+ default:
+ this.syntaxerror(" or " + LUA_QL("...") + " expected");
+ }
+ } while ( f.is_vararg == 0 && this.testnext(',') );
+ }
+ this.adjustlocalvars(nparams);
+ f.numparams = fs.nactvar;
+ fs.reserveregs(fs.nactvar); /* reserve register for parameters */
}
-
void body(expdesc e, boolean needself, int line) {
/* body -> `(' parlist `)' chunk END */
FuncState new_fs = new FuncState();
@@ -1309,12 +1272,12 @@ public class LexState extends Constants {
this.codeclosure(e);
this.close_func();
}
-
+
int explist(expdesc v) {
/* explist1 -> expr { `,' expr } */
int n = 1; /* at least one expression */
this.expr(v);
- while (this.testnext(',')) {
+ while ( this.testnext(',') ) {
fs.exp2nextreg(v);
this.expr(v);
n++;
@@ -1322,7 +1285,6 @@ public class LexState extends Constants {
return n;
}
-
void funcargs(expdesc f, int line) {
FuncState fs = this.fs;
expdesc args = new expdesc();
@@ -1353,29 +1315,28 @@ public class LexState extends Constants {
return;
}
}
- _assert (f.k == VNONRELOC);
+ _assert(f.k == VNONRELOC);
base = f.u.info; /* base register for call */
if (hasmultret(args.k))
nparams = Lua.LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
fs.exp2nextreg(args); /* close last argument */
- nparams = fs.freereg - (base + 1);
+ nparams = fs.freereg-(base+1);
}
- f.init(VCALL, fs.codeABC(Lua.OP_CALL, base, nparams + 1, 2));
+ f.init(VCALL, fs.codeABC(Lua.OP_CALL, base, nparams+1, 2));
fs.fixline(line);
- fs.freereg = (short)(base+1); /* call remove function and arguments and leaves
- * (unless changed) one result */
+ fs.freereg = (short) (base+1); /* call remove function and arguments and leaves
+ * (unless changed) one result */
}
-
/*
** {======================================================================
** Expression parsing
** =======================================================================
*/
- void primaryexp (expdesc v) {
+ void primaryexp(expdesc v) {
/* primaryexp -> NAME | '(' expr ')' */
switch (t.token) {
case '(': {
@@ -1391,16 +1352,14 @@ public class LexState extends Constants {
return;
}
default: {
- this.syntaxerror("unexpected symbol " + t.token + " (" + ((char) t.token) + ")");
- return;
+ this.syntaxerror("unexpected symbol " + t.token + " (" + (char) t.token + ")");
}
}
}
-
- void suffixedexp (expdesc v) {
+ void suffixedexp(expdesc v) {
/* suffixedexp ->
- primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
+ primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
int line = linenumber;
primaryexp(v);
for (;;) {
@@ -1435,8 +1394,7 @@ public class LexState extends Constants {
return;
}
}
- }
-
+ }
void simpleexp(expdesc v) {
/*
@@ -1467,8 +1425,7 @@ public class LexState extends Constants {
}
case TK_DOTS: { /* vararg */
FuncState fs = this.fs;
- this.check_condition(fs.f.is_vararg!=0, "cannot use " + LUA_QL("...")
- + " outside a vararg function");
+ this.check_condition(fs.f.is_vararg != 0, "cannot use " + LUA_QL("...") + " outside a vararg function");
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
break;
}
@@ -1489,7 +1446,6 @@ public class LexState extends Constants {
this.next();
}
-
int getunopr(int op) {
switch (op) {
case TK_NOT:
@@ -1503,7 +1459,6 @@ public class LexState extends Constants {
}
}
-
int getbinopr(int op) {
switch (op) {
case '+':
@@ -1550,18 +1505,18 @@ public class LexState extends Constants {
left = (byte) i;
right = (byte) j;
}
- };
-
- static Priority[] priority = { /* ORDER OPR */
- new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), /* `+' `-' `/' `%' */
- new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */
- new Priority(3, 3), new Priority(3, 3), /* equality and inequality */
- new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */
- new Priority(2, 2), new Priority(1, 1) /* logical (and/or) */
+ }
+
+ static Priority[] priority = { /* ORDER OPR */
+ new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7),
+ new Priority(7, 7), /* `+' `-' `/' `%' */
+ new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */
+ new Priority(3, 3), new Priority(3, 3), /* equality and inequality */
+ new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */
+ new Priority(2, 2), new Priority(1, 1) /* logical (and/or) */
};
- static final int UNARY_PRIORITY = 8; /* priority for unary operators */
-
+ static final int UNARY_PRIORITY = 8; /* priority for unary operators */
/*
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
@@ -1573,7 +1528,7 @@ public class LexState extends Constants {
this.enterlevel();
uop = getunopr(this.t.token);
if (uop != OPR_NOUNOPR) {
- int line = linenumber;
+ int line = linenumber;
this.next();
this.subexpr(v, UNARY_PRIORITY);
fs.prefix(uop, v, line);
@@ -1581,7 +1536,7 @@ public class LexState extends Constants {
this.simpleexp(v);
/* expand while operators have priorities higher than `limit' */
op = getbinopr(this.t.token);
- while (op != OPR_NOBINOPR && priority[op].left > limit) {
+ while ( op != OPR_NOBINOPR && priority[op].left > limit ) {
expdesc v2 = new expdesc();
int line = linenumber;
this.next();
@@ -1601,18 +1556,15 @@ public class LexState extends Constants {
/* }==================================================================== */
-
-
/*
** {======================================================================
** Rules for Statements
** =======================================================================
*/
-
- boolean block_follow (boolean withuntil) {
+ boolean block_follow(boolean withuntil) {
switch (t.token) {
- case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS:
+ case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOF:
return true;
case TK_UNTIL:
return withuntil;
@@ -1620,17 +1572,15 @@ public class LexState extends Constants {
}
}
-
- void block () {
- /* block -> chunk */
- FuncState fs = this.fs;
- BlockCnt bl = new BlockCnt();
- fs.enterblock(bl, false);
- this.statlist();
- fs.leaveblock();
+ void block() {
+ /* block -> chunk */
+ FuncState fs = this.fs;
+ BlockCnt bl = new BlockCnt();
+ fs.enterblock(bl, false);
+ this.statlist();
+ fs.leaveblock();
}
-
/*
** structure to chain all variables in the left-hand side of an
** assignment
@@ -1639,8 +1589,7 @@ public class LexState extends Constants {
LHS_assign prev;
/* variable (global, local, upvalue, or indexed) */
expdesc v = new expdesc();
- };
-
+ }
/*
** check whether, in an assignment to a local variable, the local variable
@@ -1648,66 +1597,61 @@ public class LexState extends Constants {
** local value in a safe place and use this safe copy in the previous
** assignment.
*/
- void check_conflict (LHS_assign lh, expdesc v) {
+ void check_conflict(LHS_assign lh, expdesc v) {
FuncState fs = this.fs;
- short extra = (short) fs.freereg; /* eventual position to save local variable */
+ short extra = fs.freereg; /* eventual position to save local variable */
boolean conflict = false;
- for (; lh!=null; lh = lh.prev) {
+ for (; lh != null; lh = lh.prev) {
if (lh.v.k == VINDEXED) {
/* table is the upvalue/local being assigned now? */
if (lh.v.u.ind_vt == v.k && lh.v.u.ind_t == v.u.info) {
conflict = true;
lh.v.u.ind_vt = VLOCAL;
- lh.v.u.ind_t = extra; /* previous assignment will use safe copy */
+ lh.v.u.ind_t = extra; /* previous assignment will use safe copy */
}
/* index is the local being assigned? (index cannot be upvalue) */
if (v.k == VLOCAL && lh.v.u.ind_idx == v.u.info) {
conflict = true;
- lh.v.u.ind_idx = extra; /* previous assignment will use safe copy */
+ lh.v.u.ind_idx = extra; /* previous assignment will use safe copy */
}
}
}
if (conflict) {
- /* copy upvalue/local value to a temporary (in position 'extra') */
- int op = (v.k == VLOCAL) ? Lua.OP_MOVE : Lua.OP_GETUPVAL;
- fs.codeABC(op, extra, v.u.info, 0);
- fs.reserveregs(1);
+ /* copy upvalue/local value to a temporary (in position 'extra') */
+ int op = v.k == VLOCAL? Lua.OP_MOVE: Lua.OP_GETUPVAL;
+ fs.codeABC(op, extra, v.u.info, 0);
+ fs.reserveregs(1);
}
}
-
- void assignment (LHS_assign lh, int nvars) {
+ void assignment(LHS_assign lh, int nvars) {
expdesc e = new expdesc();
- this.check_condition(VLOCAL <= lh.v.k && lh.v.k <= VINDEXED,
- "syntax error");
- if (this.testnext(',')) { /* assignment -> `,' primaryexp assignment */
- LHS_assign nv = new LHS_assign();
- nv.prev = lh;
- this.suffixedexp(nv.v);
- if (nv.v.k != VINDEXED)
- this.check_conflict(lh, nv.v);
- this.assignment(nv, nvars+1);
+ this.check_condition(VLOCAL <= lh.v.k && lh.v.k <= VINDEXED, "syntax error");
+ if (this.testnext(',')) { /* assignment -> `,' primaryexp assignment */
+ LHS_assign nv = new LHS_assign();
+ nv.prev = lh;
+ this.suffixedexp(nv.v);
+ if (nv.v.k != VINDEXED)
+ this.check_conflict(lh, nv.v);
+ this.assignment(nv, nvars+1);
+ } else { /* assignment . `=' explist1 */
+ int nexps;
+ this.checknext('=');
+ nexps = this.explist(e);
+ if (nexps != nvars) {
+ this.adjust_assign(nvars, nexps, e);
+ if (nexps > nvars)
+ this.fs.freereg -= nexps-nvars; /* remove extra values */
+ } else {
+ fs.setoneret(e); /* close last expression */
+ fs.storevar(lh.v, e);
+ return; /* avoid default */
+ }
}
- else { /* assignment . `=' explist1 */
- int nexps;
- this.checknext('=');
- nexps = this.explist(e);
- if (nexps != nvars) {
- this.adjust_assign(nvars, nexps, e);
- if (nexps > nvars)
- this.fs.freereg -= nexps - nvars; /* remove extra values */
- }
- else {
- fs.setoneret(e); /* close last expression */
- fs.storevar(lh.v, e);
- return; /* avoid default */
- }
- }
- e.init(VNONRELOC, this.fs.freereg-1); /* default assignment */
- fs.storevar(lh.v, e);
+ e.init(VNONRELOC, this.fs.freereg-1); /* default assignment */
+ fs.storevar(lh.v, e);
}
-
int cond() {
/* cond -> exp */
expdesc v = new expdesc();
@@ -1727,44 +1671,41 @@ public class LexState extends Constants {
if (testnext(TK_GOTO))
label = str_checkname();
else {
- next(); /* skip break */
+ next(); /* skip break */
label = LuaString.valueOf("break");
}
- g = newlabelentry(dyd.gt =grow(dyd.gt, dyd.n_gt+1), dyd.n_gt++, label, line, pc);
- findlabel(g); /* close it if label already defined */
+ g = newlabelentry(dyd.gt = grow(dyd.gt, dyd.n_gt+1), dyd.n_gt++, label, line, pc);
+ findlabel(g); /* close it if label already defined */
}
-
/* skip no-op statements */
- void skipnoopstat () {
- while (t.token == ';' || t.token == TK_DBCOLON)
+ void skipnoopstat() {
+ while ( t.token == ';' || t.token == TK_DBCOLON )
statement();
}
-
- void labelstat (LuaString label, int line) {
+ void labelstat(LuaString label, int line) {
/* label -> '::' NAME '::' */
- int l; /* index of new label being created */
- fs.checkrepeated(dyd.label, dyd.n_label, label); /* check for repeated labels */
- checknext(TK_DBCOLON); /* skip double colon */
+ int l; /* index of new label being created */
+ fs.checkrepeated(dyd.label, dyd.n_label, label); /* check for repeated labels */
+ checknext(TK_DBCOLON); /* skip double colon */
/* create new entry for this label */
- l = newlabelentry(dyd.label=grow(dyd.label, dyd.n_label+1), dyd.n_label++, label, line, fs.getlabel());
- skipnoopstat(); /* skip other no-op statements */
- if (block_follow(false)) { /* label is last no-op statement in the block? */
+ l = newlabelentry(dyd.label = grow(dyd.label, dyd.n_label+1), dyd.n_label++, label, line, fs.getlabel());
+ skipnoopstat(); /* skip other no-op statements */
+ if (block_follow(false)) { /* label is last no-op statement in the block? */
/* assume that locals are already out of scope */
dyd.label[l].nactvar = fs.bl.nactvar;
}
findgotos(dyd.label[l]);
-}
+ }
-
- void whilestat (int line) {
+ void whilestat(int line) {
/* whilestat -> WHILE cond DO block END */
FuncState fs = this.fs;
int whileinit;
int condexit;
BlockCnt bl = new BlockCnt();
- this.next(); /* skip WHILE */
+ this.next(); /* skip WHILE */
whileinit = fs.getlabel();
condexit = this.cond();
fs.enterblock(bl, true);
@@ -1773,7 +1714,7 @@ public class LexState extends Constants {
fs.patchlist(fs.jump(), whileinit);
this.check_match(TK_END, TK_WHILE, line);
fs.leaveblock();
- fs.patchtohere(condexit); /* false conditions finish the loop */
+ fs.patchtohere(condexit); /* false conditions finish the loop */
}
void repeatstat(int line) {
@@ -1790,14 +1731,13 @@ public class LexState extends Constants {
this.check_match(TK_UNTIL, TK_REPEAT, line);
condexit = this.cond(); /* read condition (inside scope block) */
if (bl2.upval) { /* upvalues? */
- fs.patchclose(condexit, bl2.nactvar);
+ fs.patchclose(condexit, bl2.nactvar);
}
fs.leaveblock(); /* finish scope */
fs.patchlist(condexit, repeat_init); /* close the loop */
fs.leaveblock(); /* finish loop */
}
-
int exp1() {
expdesc e = new expdesc();
int k;
@@ -1807,7 +1747,6 @@ public class LexState extends Constants {
return k;
}
-
void forbody(int base, int line, int nvars, boolean isnum) {
/* forbody -> DO block */
BlockCnt bl = new BlockCnt();
@@ -1815,25 +1754,24 @@ public class LexState extends Constants {
int prep, endfor;
this.adjustlocalvars(3); /* control variables */
this.checknext(TK_DO);
- prep = isnum ? fs.codeAsBx(Lua.OP_FORPREP, base, NO_JUMP) : fs.jump();
+ prep = isnum? fs.codeAsBx(Lua.OP_FORPREP, base, NO_JUMP): fs.jump();
fs.enterblock(bl, false); /* scope for declared variables */
this.adjustlocalvars(nvars);
fs.reserveregs(nvars);
this.block();
fs.leaveblock(); /* end of scope for declared variables */
fs.patchtohere(prep);
- if (isnum) /* numeric for? */
+ if (isnum) /* numeric for? */
endfor = fs.codeAsBx(Lua.OP_FORLOOP, base, NO_JUMP);
- else { /* generic for */
+ else { /* generic for */
fs.codeABC(Lua.OP_TFORCALL, base, 0, nvars);
fs.fixline(line);
- endfor = fs.codeAsBx(Lua.OP_TFORLOOP, base + 2, NO_JUMP);
+ endfor = fs.codeAsBx(Lua.OP_TFORLOOP, base+2, NO_JUMP);
}
- fs.patchlist(endfor, prep + 1);
+ fs.patchlist(endfor, prep+1);
fs.fixline(line);
}
-
void fornum(LuaString varname, int line) {
/* fornum -> NAME = exp1,exp1[,exp1] forbody */
FuncState fs = this.fs;
@@ -1855,12 +1793,11 @@ public class LexState extends Constants {
this.forbody(base, line, 1, true);
}
-
void forlist(LuaString indexname) {
/* forlist -> NAME {,NAME} IN explist1 forbody */
FuncState fs = this.fs;
expdesc e = new expdesc();
- int nvars = 4; /* gen, state, control, plus at least one declared var */
+ int nvars = 4; /* gen, state, control, plus at least one declared var */
int line;
int base = fs.freereg;
/* create control variables */
@@ -1869,7 +1806,7 @@ public class LexState extends Constants {
this.new_localvarliteral(RESERVED_LOCAL_VAR_FOR_CONTROL);
/* create declared variables */
this.new_localvar(indexname);
- while (this.testnext(',')) {
+ while ( this.testnext(',') ) {
this.new_localvar(this.str_checkname());
++nvars;
}
@@ -1877,10 +1814,9 @@ public class LexState extends Constants {
line = this.linenumber;
this.adjust_assign(3, this.explist(e), e);
fs.checkstack(3); /* extra space to call generator */
- this.forbody(base, line, nvars - 3, false);
+ this.forbody(base, line, nvars-3, false);
}
-
void forstat(int line) {
/* forstat -> FOR (fornum | forlist) END */
FuncState fs = this.fs;
@@ -1904,14 +1840,13 @@ public class LexState extends Constants {
fs.leaveblock(); /* loop scope (`break' jumps to this point) */
}
-
void test_then_block(IntPtr escapelist) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
expdesc v = new expdesc();
BlockCnt bl = new BlockCnt();
- int jf; /* instruction to skip 'then' code (if condition is false) */
+ int jf; /* instruction to skip 'then' code (if condition is false) */
this.next(); /* skip IF or ELSEIF */
- expr(v); /* read expression */
+ expr(v); /* read expression */
this.checknext(TK_THEN);
if (t.token == TK_GOTO || t.token == TK_BREAK) {
fs.goiffalse(v); /* will jump to label if condition is true */
@@ -1936,16 +1871,15 @@ public class LexState extends Constants {
fs.patchtohere(jf);
}
-
void ifstat(int line) {
- IntPtr escapelist = new IntPtr(NO_JUMP); /* exit list for finished parts */
- test_then_block(escapelist); /* IF cond THEN block */
- while (t.token == TK_ELSEIF)
- test_then_block(escapelist); /* ELSEIF cond THEN block */
+ IntPtr escapelist = new IntPtr(NO_JUMP); /* exit list for finished parts */
+ test_then_block(escapelist); /* IF cond THEN block */
+ while ( t.token == TK_ELSEIF )
+ test_then_block(escapelist); /* ELSEIF cond THEN block */
if (testnext(TK_ELSE))
- block(); /* `else' part */
+ block(); /* `else' part */
check_match(TK_END, TK_IF, line);
- fs.patchtohere(escapelist.i); /* patch escape list to 'if' end */
+ fs.patchtohere(escapelist.i); /* patch escape list to 'if' end */
}
void localfunc() {
@@ -1955,10 +1889,9 @@ public class LexState extends Constants {
this.adjustlocalvars(1);
this.body(b, false, this.linenumber);
/* debug information will only see the variable after this point! */
- fs.getlocvar(fs.nactvar - 1).startpc = fs.pc;
+ fs.getlocvar(fs.nactvar-1).startpc = fs.pc;
}
-
void localstat() {
/* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
int nvars = 0;
@@ -1967,7 +1900,7 @@ public class LexState extends Constants {
do {
this.new_localvar(this.str_checkname());
++nvars;
- } while (this.testnext(','));
+ } while ( this.testnext(',') );
if (this.testnext('='))
nexps = this.explist(e);
else {
@@ -1978,12 +1911,11 @@ public class LexState extends Constants {
this.adjustlocalvars(nvars);
}
-
boolean funcname(expdesc v) {
/* funcname -> NAME {field} [`:' NAME] */
boolean ismethod = false;
this.singlevar(v);
- while (this.t.token == '.')
+ while ( this.t.token == '.' )
this.fieldsel(v);
if (this.t.token == ':') {
ismethod = true;
@@ -1992,7 +1924,6 @@ public class LexState extends Constants {
return ismethod;
}
-
void funcstat(int line) {
/* funcstat -> FUNCTION funcname body */
boolean needself;
@@ -2005,7 +1936,6 @@ public class LexState extends Constants {
fs.fixline(line); /* definition `happens' in the first line */
}
-
void exprstat() {
/* stat -> func | assignment */
FuncState fs = this.fs;
@@ -2014,10 +1944,9 @@ public class LexState extends Constants {
if (t.token == '=' || t.token == ',') { /* stat -> assignment ? */
v.prev = null;
assignment(v, 1);
- }
- else { /* stat -> func */
+ } else { /* stat -> func */
check_condition(v.v.k == VCALL, "syntax error");
- SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
+ SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
}
}
@@ -2034,7 +1963,7 @@ public class LexState extends Constants {
fs.setmultret(e);
if (e.k == VCALL && nret == 1) { /* tail call? */
SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
- _assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
+ _assert(Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
}
first = fs.nactvar;
nret = Lua.LUA_MULTRET; /* return all values */
@@ -2044,12 +1973,12 @@ public class LexState extends Constants {
else {
fs.exp2nextreg(e); /* values must go to the `stack' */
first = fs.nactvar; /* return all `active' values */
- _assert (nret == fs.freereg - first);
+ _assert(nret == fs.freereg-first);
}
}
}
fs.ret(first, nret);
- testnext(';'); /* skip optional semicolon */
+ testnext(';'); /* skip optional semicolon */
}
void statement() {
@@ -2100,7 +2029,7 @@ public class LexState extends Constants {
break;
}
case TK_RETURN: { /* stat -> retstat */
- next(); /* skip RETURN */
+ next(); /* skip RETURN */
this.retstat();
break;
}
@@ -2114,15 +2043,14 @@ public class LexState extends Constants {
break;
}
}
- _assert(fs.f.maxstacksize >= fs.freereg
- && fs.freereg >= fs.nactvar);
+ _assert(fs.f.maxstacksize >= fs.freereg && fs.freereg >= fs.nactvar);
fs.freereg = fs.nactvar; /* free registers */
leavelevel();
}
void statlist() {
/* statlist -> { stat [`;'] } */
- while (!block_follow(true)) {
+ while ( !block_follow(true) ) {
if (t.token == TK_RETURN) {
statement();
return; /* 'return' must be last statement */
@@ -2144,10 +2072,10 @@ public class LexState extends Constants {
fs.newupvalue(envn, v); /* ...set environment upvalue */
next(); /* read first token */
statlist(); /* parse main body */
- check(TK_EOS);
+ check(TK_EOF);
close_func();
}
-
+
/* }====================================================================== */
-
+
}
diff --git a/src/core/org/luaj/vm2/compiler/LuaC.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java
similarity index 70%
rename from src/core/org/luaj/vm2/compiler/LuaC.java
rename to luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java
index 1e53636d..fadc20a3 100644
--- a/src/core/org/luaj/vm2/compiler/LuaC.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java
@@ -10,7 +10,7 @@
*
* 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
@@ -35,33 +35,40 @@ import org.luaj.vm2.lib.BaseLib;
/**
* Compiler for Lua.
- *
+ *
*
- * Compiles lua source files into lua bytecode within a {@link Prototype},
- * loads lua binary files directly into a {@link Prototype},
- * and optionaly instantiates a {@link LuaClosure} around the result
- * using a user-supplied environment.
- *
+ * Compiles lua source files into lua bytecode within a {@link Prototype}, loads
+ * lua binary files directly into a {@link Prototype}, and optionaly
+ * instantiates a {@link LuaClosure} around the result using a user-supplied
+ * environment.
+ *
*
- * Implements the {@link org.luaj.vm2.Globals.Compiler} interface for loading
- * initialized chunks, which is an interface common to
- * lua bytecode compiling and java bytecode compiling.
- *
- *
- * The {@link LuaC} compiler is installed by default by both the
- * {@link org.luaj.vm2.lib.jse.JsePlatform} and {@link org.luaj.vm2.lib.jme.JmePlatform} classes,
- * so in the following example, the default {@link LuaC} compiler
- * will be used:
- *
- *
+ * Implements the {@link org.luaj.vm2.Globals.Compiler} interface for loading
+ * initialized chunks, which is an interface common to lua bytecode compiling
+ * and java bytecode compiling.
+ *
+ *
+ * The {@link LuaC} compiler is installed by default by both the
+ * {@link org.luaj.vm2.lib.jse.JsePlatform} and
+ * {@link org.luaj.vm2.lib.jme.JmePlatform} classes, so in the following
+ * example, the default {@link LuaC} compiler will be used:
+ *
+ *
+ *
* To load the LuaC compiler manually, use the install method:
- *
{@code
+ *
+ *
+ * {@code
* LuaC.install(globals);
- * }
- *
+ * }
+ *
+ *
* @see #install(Globals)
* @see Globals#compiler
* @see Globals#loader
@@ -76,10 +83,11 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
/** A sharable instance of the LuaC compiler. */
public static final LuaC instance = new LuaC();
-
- /** Install the compiler so that LoadState will first
- * try to use it when handed bytes that are
- * not already a compiled lua chunk.
+
+ /**
+ * Install the compiler so that LoadState will first try to use it when
+ * handed bytes that are not already a compiled lua chunk.
+ *
* @param globals the Globals into which this is to be installed.
*/
public static void install(Globals globals) {
@@ -89,69 +97,77 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
protected LuaC() {}
- /** Compile lua source into a Prototype.
- * @param stream InputStream representing the text source conforming to lua source syntax.
+ /**
+ * 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
*/
+ @Override
public Prototype compile(InputStream stream, String chunkname) throws IOException {
- return (new CompileState()).luaY_parser(stream, chunkname);
+ return new CompileState().luaY_parser(stream, chunkname);
}
+ @Override
public LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException {
return new LuaClosure(prototype, env);
}
- /** @deprecated
- * Use Globals.load(InputString, String, String) instead,
- * or LuaC.compile(InputStream, String) and construct LuaClosure directly.
+ /**
+ * @deprecated Use Globals.load(InputString, String, String) instead, or
+ * LuaC.compile(InputStream, String) and construct LuaClosure
+ * directly.
*/
+ @Deprecated
public LuaValue load(InputStream stream, String chunkname, Globals globals) throws IOException {
return new LuaClosure(compile(stream, chunkname), globals);
}
static class CompileState {
- int nCcalls = 0;
- private Hashtable strings = new Hashtable();
+ int nCcalls = 0;
+ private final Hashtable strings = new Hashtable();
+
protected CompileState() {}
-
+
/** Parse the input */
- Prototype luaY_parser(InputStream z, String name) throws IOException{
+ 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, z.read(), z, (LuaString) LuaValue.valueOf(name) );
+ lexstate.setinput(this, z.read(), z, LuaValue.valueOf(name));
/* main func. is always vararg */
funcstate.f = new Prototype();
- funcstate.f.source = (LuaString) LuaValue.valueOf(name);
+ funcstate.f.source = LuaValue.valueOf(name);
lexstate.mainfunc(funcstate);
- LuaC._assert (funcstate.prev == null);
+ Constants._assert(funcstate.prev == null);
/* all scopes should be correctly finished */
- LuaC._assert (lexstate.dyd == null
- || (lexstate.dyd.n_actvar == 0 && lexstate.dyd.n_gt == 0 && lexstate.dyd.n_label == 0));
+ Constants._assert(lexstate.dyd == null
+ || lexstate.dyd.n_actvar == 0 && lexstate.dyd.n_gt == 0 && lexstate.dyd.n_label == 0);
return funcstate.f;
}
-
+
// look up and keep at most one copy of each string
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)
+ if (c != null)
return c;
strings.put(s, s);
return s;
}
-
+
public String pushfstring(String string) {
return string;
}
diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java
similarity index 86%
rename from src/core/org/luaj/vm2/lib/BaseLib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java
index fb86825b..9b072bd9 100644
--- a/src/core/org/luaj/vm2/lib/BaseLib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java
@@ -1,485 +1,513 @@
-/*******************************************************************************
-* Copyright (c) 2009 Luaj.org. 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.vm2.lib;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.luaj.vm2.Globals;
-import org.luaj.vm2.Lua;
-import org.luaj.vm2.LuaError;
-import org.luaj.vm2.LuaString;
-import org.luaj.vm2.LuaTable;
-import org.luaj.vm2.LuaThread;
-import org.luaj.vm2.LuaValue;
-import org.luaj.vm2.Varargs;
-
-/**
- * Subclass of {@link LibFunction} which implements the lua basic library functions.
- *
- * This contains all library functions listed as "basic functions" in the lua documentation for JME.
- * The functions dofile and loadfile use the
- * {@link Globals#finder} instance to find resource files.
- * Since JME has no file system by default, {@link BaseLib} implements
- * {@link ResourceFinder} using {@link Class#getResource(String)},
- * which is the closest equivalent on JME.
- * The default loader chain in {@link PackageLib} will use these as well.
- *
- * To use basic library functions that include a {@link ResourceFinder} based on
- * directory lookup, use {@link org.luaj.vm2.lib.jse.JseBaseLib} instead.
- *
- * Typically, this library is included as part of a call to either
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
- * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
- * For special cases where the smallest possible footprint is desired,
- * a minimal set of libraries could be loaded
- * directly via {@link Globals#load(LuaValue)} using code such as:
- *
- * Doing so will ensure the library is properly initialized
- * and loaded into the globals table.
- *
- * This is a direct port of the corresponding library in C.
- * @see org.luaj.vm2.lib.jse.JseBaseLib
- * @see ResourceFinder
- * @see Globals#finder
- * @see LibFunction
- * @see org.luaj.vm2.lib.jse.JsePlatform
- * @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Base Lib Reference
- */
-public class BaseLib extends TwoArgFunction implements ResourceFinder {
-
- Globals globals;
-
-
- /** Perform one-time initialization on the library by adding base functions
- * to the supplied environment, and returning it as the return value.
- * @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, which must be a Globals instance.
- */
- public LuaValue call(LuaValue modname, LuaValue env) {
- globals = env.checkglobals();
- globals.finder = this;
- globals.baselib = this;
- env.set( "_G", env );
- env.set( "_VERSION", Lua._VERSION );
- env.set("assert", new _assert());
- env.set("collectgarbage", new collectgarbage());
- env.set("dofile", new dofile());
- env.set("error", new error());
- env.set("getmetatable", new getmetatable());
- env.set("load", new load());
- env.set("loadfile", new loadfile());
- env.set("pcall", new pcall());
- env.set("print", new print(this));
- env.set("rawequal", new rawequal());
- env.set("rawget", new rawget());
- env.set("rawlen", new rawlen());
- env.set("rawset", new rawset());
- env.set("select", new select());
- env.set("setmetatable", new setmetatable());
- env.set("tonumber", new tonumber());
- env.set("tostring", new tostring());
- env.set("type", new type());
- env.set("xpcall", new xpcall());
-
- next next;
- env.set("next", next = new next());
- env.set("pairs", new pairs(next));
- env.set("ipairs", new ipairs());
-
- return env;
- }
-
- /** ResourceFinder implementation
- *
- * Tries to open the file as a resource, which can work for JSE and JME.
- */
- public InputStream findResource(String filename) {
- return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/"+filename);
- }
-
-
- // "assert", // ( v [,message] ) -> v, message | ERR
- static final class _assert extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- if ( !args.arg1().toboolean() )
- error( args.narg()>1? args.optjstring(2,"assertion failed!"): "assertion failed!" );
- return args;
- }
- }
-
- // "collectgarbage", // ( opt [,arg] ) -> value
- static final class collectgarbage extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- String s = args.optjstring(1, "collect");
- if ( "collect".equals(s) ) {
- System.gc();
- return ZERO;
- } else if ( "count".equals(s) ) {
- Runtime rt = Runtime.getRuntime();
- long used = rt.totalMemory() - rt.freeMemory();
- return varargsOf(valueOf(used/1024.), valueOf(used%1024));
- } else if ( "step".equals(s) ) {
- System.gc();
- return LuaValue.TRUE;
- } else {
- argerror(1, "invalid option '" + s + "'");
- }
- return NIL;
- }
- }
-
- // "dofile", // ( filename ) -> result1, ...
- final class dofile extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
- String filename = args.isstring(1)? args.tojstring(1): null;
- Varargs v = filename == null?
- loadStream( globals.STDIN, "=stdin", "bt", globals ):
- loadFile( args.checkjstring(1), "bt", globals );
- return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
- }
- }
-
- // "error", // ( message [,level] ) -> ERR
- static final class error extends TwoArgFunction {
- public LuaValue call(LuaValue arg1, LuaValue arg2) {
- if (arg1.isnil()) throw new LuaError(NIL);
- if (!arg1.isstring() || arg2.optint(1) == 0) throw new LuaError(arg1);
- throw new LuaError(arg1.tojstring(), arg2.optint(1));
- }
- }
-
- // "getmetatable", // ( object ) -> table
- static final class getmetatable extends LibFunction {
- public LuaValue call() {
- return argerror(1, "value expected");
- }
- public LuaValue call(LuaValue arg) {
- LuaValue mt = arg.getmetatable();
- return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL;
- }
- }
- // "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
- final class load extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- LuaValue ld = args.arg1();
- if (!ld.isstring() && !ld.isfunction()) {
- throw new LuaError("bad argument #1 to 'load' (string or function expected, got " + ld.typename() + ")");
- }
- String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
- String mode = args.optjstring(3, "bt");
- LuaValue env = args.optvalue(4, globals);
- return loadStream(ld.isstring()? ld.strvalue().toInputStream():
- new StringInputStream(ld.checkfunction()), source, mode, env);
- }
- }
-
- // "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg
- final class loadfile extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
- String filename = args.isstring(1)? args.tojstring(1): null;
- String mode = args.optjstring(2, "bt");
- LuaValue env = args.optvalue(3, globals);
- return filename == null?
- loadStream( globals.STDIN, "=stdin", mode, env ):
- loadFile( filename, mode, env );
- }
- }
-
- // "pcall", // (f, arg1, ...) -> status, result1, ...
- final class pcall extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- LuaValue func = args.checkvalue(1);
- if (globals != null && globals.debuglib != null)
- globals.debuglib.onCall(this);
- try {
- return varargsOf(TRUE, func.invoke(args.subargs(2)));
- } catch ( LuaError le ) {
- final LuaValue m = le.getMessageObject();
- return varargsOf(FALSE, m!=null? m: NIL);
- } catch ( Exception e ) {
- final String m = e.getMessage();
- return varargsOf(FALSE, valueOf(m!=null? m: e.toString()));
- } finally {
- if (globals != null && globals.debuglib != null)
- globals.debuglib.onReturn();
- }
- }
- }
-
- // "print", // (...) -> void
- final class print extends VarArgFunction {
- final BaseLib baselib;
- print(BaseLib baselib) {
- this.baselib = baselib;
- }
- 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.print( '\t' );
- LuaString s = tostring.call( args.arg(i) ).strvalue();
- globals.STDOUT.print(s.tojstring());
- }
- globals.STDOUT.print('\n');
- return NONE;
- }
- }
-
-
- // "rawequal", // (v1, v2) -> boolean
- static final class rawequal extends LibFunction {
- public LuaValue call() {
- return argerror(1, "value expected");
- }
- public LuaValue call(LuaValue arg) {
- return argerror(2, "value expected");
- }
- public LuaValue call(LuaValue arg1, LuaValue arg2) {
- return valueOf(arg1.raweq(arg2));
- }
- }
-
- // "rawget", // (table, index) -> value
- static final class rawget extends TableLibFunction {
- public LuaValue call(LuaValue arg) {
- return argerror(2, "value expected");
- }
- public LuaValue call(LuaValue arg1, LuaValue arg2) {
- return arg1.checktable().rawget(arg2);
- }
- }
-
-
- // "rawlen", // (v) -> value
- static final class rawlen extends LibFunction {
- public LuaValue call(LuaValue arg) {
- return valueOf(arg.rawlen());
- }
- }
-
- // "rawset", // (table, index, value) -> table
- static final class rawset extends TableLibFunction {
- public LuaValue call(LuaValue table) {
- return argerror(2,"value expected");
- }
- public LuaValue call(LuaValue table, LuaValue index) {
- return argerror(3,"value expected");
- }
- public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
- LuaTable t = table.checktable();
- if (!index.isvalidkey()) argerror(2, "table index is nil");
- t.rawset(index, value);
- return t;
- }
- }
-
- // "select", // (f, ...) -> value1, ...
- static final class select extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- int n = args.narg()-1;
- if ( args.arg1().equals(valueOf("#")) )
- return valueOf(n);
- int i = args.checkint(1);
- if ( i == 0 || i < -n )
- argerror(1,"index out of range");
- return args.subargs(i<0? n+i+2: i+1);
- }
- }
-
- // "setmetatable", // (table, metatable) -> table
- static final class setmetatable extends TableLibFunction {
- public LuaValue call(LuaValue table) {
- return argerror(2,"nil or table expected");
- }
- public LuaValue call(LuaValue table, LuaValue metatable) {
- final LuaValue mt0 = table.checktable().getmetatable();
- if ( mt0!=null && !mt0.rawget(METATABLE).isnil() )
- error("cannot change a protected metatable");
- return table.setmetatable(metatable.isnil()? null: metatable.checktable());
- }
- }
-
- // "tonumber", // (e [,base]) -> value
- static final class tonumber extends LibFunction {
- public LuaValue call(LuaValue e) {
- return e.tonumber();
- }
- public LuaValue call(LuaValue e, LuaValue base) {
- if (base.isnil())
- return e.tonumber();
- final int b = base.checkint();
- if ( b < 2 || b > 36 )
- argerror(2, "base out of range");
- return e.checkstring().tonumber(b);
- }
- }
-
- // "tostring", // (e) -> value
- static final class tostring extends LibFunction {
- public LuaValue call(LuaValue arg) {
- LuaValue h = arg.metatag(TOSTRING);
- if ( ! h.isnil() )
- return h.call(arg);
- LuaValue v = arg.tostring();
- if ( ! v.isnil() )
- return v;
- return valueOf(arg.tojstring());
- }
- }
-
- // "type", // (v) -> value
- static final class type extends LibFunction {
- public LuaValue call(LuaValue arg) {
- return valueOf(arg.typename());
- }
- }
-
- // "xpcall", // (f, err) -> result1, ...
- final class xpcall extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- final LuaThread t = globals.running;
- final LuaValue preverror = t.errorfunc;
- t.errorfunc = args.checkvalue(2);
- try {
- if (globals != null && globals.debuglib != null)
- globals.debuglib.onCall(this);
- try {
- return varargsOf(TRUE, args.arg1().invoke(args.subargs(3)));
- } catch ( LuaError le ) {
- final LuaValue m = le.getMessageObject();
- return varargsOf(FALSE, m!=null? m: NIL);
- } catch ( Exception e ) {
- final String m = e.getMessage();
- return varargsOf(FALSE, valueOf(m!=null? m: e.toString()));
- } finally {
- if (globals != null && globals.debuglib != null)
- globals.debuglib.onReturn();
- }
- } finally {
- t.errorfunc = preverror;
- }
- }
- }
-
- // "pairs" (t) -> iter-func, t, nil
- static final class pairs extends VarArgFunction {
- final next next;
- pairs(next next) {
- this.next = next;
- }
- public Varargs invoke(Varargs args) {
- return varargsOf( next, args.checktable(1), NIL );
- }
- }
-
- // // "ipairs", // (t) -> iter-func, t, 0
- static final class ipairs extends VarArgFunction {
- inext inext = new inext();
- public Varargs invoke(Varargs args) {
- return varargsOf( inext, args.checktable(1), ZERO );
- }
- }
-
- // "next" ( table, [index] ) -> next-index, next-value
- static final class next extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- return args.checktable(1).next(args.arg(2));
- }
- }
-
- // "inext" ( table, [int-index] ) -> next-index, next-value
- static final class inext extends VarArgFunction {
- public Varargs invoke(Varargs args) {
- return args.checktable(1).inext(args.arg(2));
- }
- }
-
- /**
- * Load from a named file, returning the chunk or nil,error of can't load
- * @param env
- * @param mode
- * @return Varargs containing chunk, or NIL,error-text on error
- */
- public Varargs loadFile(String filename, String mode, LuaValue env) {
- InputStream is = globals.finder.findResource(filename);
- if ( is == null )
- return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory"));
- try {
- return loadStream(is, "@"+filename, mode, env);
- } finally {
- try {
- is.close();
- } catch ( Exception e ) {
- e.printStackTrace();
- }
- }
- }
-
- public Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) {
- try {
- if ( is == null )
- return varargsOf(NIL, valueOf("not found: "+chunkname));
- return globals.load(is, chunkname, mode, env);
- } catch (Exception e) {
- return varargsOf(NIL, valueOf(e.getMessage()));
- }
- }
-
-
- private static class StringInputStream extends InputStream {
- final LuaValue func;
- byte[] bytes;
- int offset, remaining = 0;
- StringInputStream(LuaValue func) {
- this.func = func;
- }
- public int read() throws IOException {
- if ( remaining < 0 )
- return -1;
- if ( remaining == 0 ) {
- LuaValue s = func.call();
- if ( s.isnil() )
- return remaining = -1;
- LuaString ls = s.strvalue();
- bytes = ls.m_bytes;
- offset = ls.m_offset;
- remaining = ls.m_length;
- if (remaining <= 0)
- return -1;
- }
- --remaining;
- return 0xFF&bytes[offset++];
- }
- }
-}
+/*******************************************************************************
+* Copyright (c) 2009 Luaj.org. 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.vm2.lib;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.Lua;
+import org.luaj.vm2.LuaError;
+import org.luaj.vm2.LuaString;
+import org.luaj.vm2.LuaTable;
+import org.luaj.vm2.LuaThread;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Varargs;
+
+/**
+ * Subclass of {@link LibFunction} which implements the lua basic library
+ * functions.
+ *
+ * This contains all library functions listed as "basic functions" in the lua
+ * documentation for JME. The functions dofile and loadfile use the
+ * {@link Globals#finder} instance to find resource files. Since JME has no file
+ * system by default, {@link BaseLib} implements {@link ResourceFinder} using
+ * {@link Class#getResource(String)}, which is the closest equivalent on JME.
+ * The default loader chain in {@link PackageLib} will use these as well.
+ *
+ * To use basic library functions that include a {@link ResourceFinder} based on
+ * directory lookup, use {@link org.luaj.vm2.lib.jse.JseBaseLib} instead.
+ *
+ * Typically, this library is included as part of a call to either
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
+ *
+ *
+ * For special cases where the smallest possible footprint is desired, a minimal
+ * set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
+ * using code such as:
+ *
+ *
+ *
+ * Doing so will ensure the library is properly initialized and loaded into the
+ * globals table.
+ *
+ * This is a direct port of the corresponding library in C.
+ *
+ * @see org.luaj.vm2.lib.jse.JseBaseLib
+ * @see ResourceFinder
+ * @see Globals#finder
+ * @see LibFunction
+ * @see org.luaj.vm2.lib.jse.JsePlatform
+ * @see org.luaj.vm2.lib.jme.JmePlatform
+ * @see Lua 5.2 Base Lib
+ * Reference
+ */
+public class BaseLib extends TwoArgFunction implements ResourceFinder {
+
+ Globals globals;
+
+ /**
+ * Perform one-time initialization on the library by adding base functions
+ * to the supplied environment, and returning it as the return value.
+ *
+ * @param modname the module name supplied if this is loaded via 'require'.
+ * @param env the environment to load into, which must be a Globals
+ * instance.
+ */
+ @Override
+ public LuaValue call(LuaValue modname, LuaValue env) {
+ globals = env.checkglobals();
+ globals.finder = this;
+ globals.baselib = this;
+ env.set("_G", env);
+ env.set("_VERSION", Lua._VERSION);
+ env.set("assert", new _assert());
+ env.set("collectgarbage", new collectgarbage());
+ env.set("dofile", new dofile());
+ env.set("error", new error());
+ env.set("getmetatable", new getmetatable());
+ env.set("load", new load());
+ env.set("loadfile", new loadfile());
+ env.set("pcall", new pcall());
+ env.set("print", new print(this));
+ env.set("rawequal", new rawequal());
+ env.set("rawget", new rawget());
+ env.set("rawlen", new rawlen());
+ env.set("rawset", new rawset());
+ env.set("select", new select());
+ env.set("setmetatable", new setmetatable());
+ env.set("tonumber", new tonumber());
+ env.set("tostring", new tostring());
+ env.set("type", new type());
+ env.set("xpcall", new xpcall());
+
+ next next;
+ env.set("next", next = new next());
+ env.set("pairs", new pairsbase(PAIRS, NIL, next));
+ env.set("ipairs", new pairsbase(IPAIRS, ZERO, new inext()));
+
+ return env;
+ }
+
+ /** ResourceFinder implementation
+ *
+ * Tries to open the file as a resource, which can work for JSE and JME.
+ */
+ public InputStream findResource(String filename) {
+ return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/"+filename);
+ }
+
+
+ // "assert", // ( v [,message] ) -> v, message | ERR
+ static final class _assert extends VarArgFunction {
+ public Varargs invoke(Varargs args) {
+ if ( !args.arg1().toboolean() )
+ error( args.narg()>1? args.optjstring(2,"assertion failed!"): "assertion failed!" );
+ return args;
+ }
+ }
+
+ // "collectgarbage", // ( opt [,arg] ) -> value
+ static final class collectgarbage extends VarArgFunction {
+ public Varargs invoke(Varargs args) {
+ String s = args.optjstring(1, "collect");
+ if ( "collect".equals(s) ) {
+ System.gc();
+ return ZERO;
+ } else if ( "count".equals(s) ) {
+ Runtime rt = Runtime.getRuntime();
+ long used = rt.totalMemory() - rt.freeMemory();
+ return varargsOf(valueOf(used/1024.), valueOf(used%1024));
+ } else if ( "step".equals(s) ) {
+ System.gc();
+ return LuaValue.TRUE;
+ } else {
+ argerror(1, "invalid option '" + s + "'");
+ }
+ return NIL;
+ }
+ }
+
+ // "dofile", // ( filename ) -> result1, ...
+ final class dofile extends VarArgFunction {
+ public Varargs invoke(Varargs args) {
+ args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
+ String filename = args.isstring(1)? args.tojstring(1): null;
+ Varargs v = filename == null?
+ loadStream( globals.STDIN, "=stdin", "bt", globals ):
+ loadFile( args.checkjstring(1), "bt", globals );
+ return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
+ }
+ }
+
+ // "error", // ( message [,level] ) -> ERR
+ static final class error extends TwoArgFunction {
+ public LuaValue call(LuaValue arg1, LuaValue arg2) {
+ if (arg1.isnil()) throw new LuaError(NIL);
+ if (!arg1.isstring() || arg2.optint(1) == 0) throw new LuaError(arg1);
+ throw new LuaError(arg1.tojstring(), arg2.optint(1));
+ }
+ }
+
+ // "getmetatable", // ( object ) -> table
+ static final class getmetatable extends LibFunction {
+ public LuaValue call() {
+ return argerror(1, "value expected");
+ }
+ public LuaValue call(LuaValue arg) {
+ LuaValue mt = arg.getmetatable();
+ return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL;
+ }
+ }
+ // "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
+ final class load extends VarArgFunction {
+ public Varargs invoke(Varargs args) {
+ LuaValue ld = args.arg1();
+ if (!ld.isstring() && !ld.isfunction()) {
+ throw new LuaError("bad argument #1 to 'load' (string or function expected, got " + ld.typename() + ")");
+ }
+ String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
+ String mode = args.optjstring(3, "bt");
+ LuaValue env = args.optvalue(4, globals);
+ return loadStream(ld.isstring()? ld.strvalue().toInputStream():
+ new StringInputStream(ld.checkfunction()), source, mode, env);
+ }
+ }
+
+ // "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg
+ final class loadfile extends VarArgFunction {
+ @Override
+ public Varargs invoke(Varargs args) {
+ args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
+ String filename = args.isstring(1)? args.tojstring(1): null;
+ String mode = args.optjstring(2, "bt");
+ LuaValue env = args.optvalue(3, globals);
+ return filename == null?
+ loadStream( globals.STDIN, "=stdin", mode, env ):
+ loadFile( filename, mode, env );
+ }
+ }
+
+ // "pcall", // (f, arg1, ...) -> status, result1, ...
+ final class pcall extends VarArgFunction {
+ @Override
+ public Varargs invoke(Varargs args) {
+ LuaValue func = args.checkvalue(1);
+ if (globals != null && globals.debuglib != null)
+ globals.debuglib.onCall(this);
+ try {
+ return varargsOf(TRUE, func.invoke(args.subargs(2)));
+ } catch ( LuaError le ) {
+ final LuaValue m = le.getMessageObject();
+ return varargsOf(FALSE, m!=null? m: NIL);
+ } catch ( Exception e ) {
+ final String m = e.getMessage();
+ return varargsOf(FALSE, valueOf(m!=null? m: e.toString()));
+ } finally {
+ if (globals != null && globals.debuglib != null)
+ globals.debuglib.onReturn();
+ }
+ }
+ }
+
+ // "print", // (...) -> void
+ final class print extends VarArgFunction {
+ final BaseLib baselib;
+ print(BaseLib baselib) {
+ this.baselib = baselib;
+ }
+
+ @Override
+ 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.print( '\t' );
+ LuaString s = tostring.call( args.arg(i) ).strvalue();
+ globals.STDOUT.print(s.tojstring());
+ }
+ globals.STDOUT.print('\n');
+ return NONE;
+ }
+ }
+
+ // "rawequal", // (v1, v2) -> boolean
+ static final class rawequal extends LibFunction {
+ public LuaValue call() {
+ return argerror(1, "value expected");
+ }
+ public LuaValue call(LuaValue arg) {
+ return argerror(2, "value expected");
+ }
+ public LuaValue call(LuaValue arg1, LuaValue arg2) {
+ return valueOf(arg1.raweq(arg2));
+ }
+ }
+
+ // "rawget", // (table, index) -> value
+ static final class rawget extends TableLibFunction {
+ public LuaValue call() {
+ return argerror(1, "value expected");
+ }
+ public LuaValue call(LuaValue arg) {
+ return argerror(2, "value expected");
+ }
+ public LuaValue call(LuaValue arg1, LuaValue arg2) {
+ return arg1.checktable().rawget(arg2);
+ }
+ }
+
+
+ // "rawlen", // (v) -> value
+ static final class rawlen extends LibFunction {
+ public LuaValue call(LuaValue arg) {
+ return valueOf(arg.rawlen());
+ }
+ }
+
+ // "rawset", // (table, index, value) -> table
+ static final class rawset extends TableLibFunction {
+ public LuaValue call(LuaValue table) {
+ return argerror(2,"value expected");
+ }
+ public LuaValue call(LuaValue table, LuaValue index) {
+ return argerror(3,"value expected");
+ }
+ public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
+ LuaTable t = table.checktable();
+ if (!index.isvalidkey()) argerror(2, "table index is nil");
+ t.rawset(index, value);
+ return t;
+ }
+ }
+
+ // "select", // (f, ...) -> value1, ...
+ static final class select extends VarArgFunction {
+ public Varargs invoke(Varargs args) {
+ int n = args.narg()-1;
+ if ( args.arg1().equals(valueOf("#")) )
+ return valueOf(n);
+ int i = args.checkint(1);
+ if ( i == 0 || i < -n )
+ argerror(1,"index out of range");
+ return args.subargs(i<0? n+i+2: i+1);
+ }
+ }
+
+ // "setmetatable", // (table, metatable) -> table
+ static final class setmetatable extends TableLibFunction {
+ public LuaValue call(LuaValue table) {
+ return argerror(2,"nil or table expected");
+ }
+ public LuaValue call(LuaValue table, LuaValue metatable) {
+ final LuaValue mt0 = table.checktable().getmetatable();
+ if ( mt0!=null && !mt0.rawget(METATABLE).isnil() )
+ error("cannot change a protected metatable");
+ return table.setmetatable(metatable.isnil()? null: metatable.checktable());
+ }
+ }
+
+ // "tonumber", // (e [,base]) -> value
+ static final class tonumber extends LibFunction {
+ public LuaValue call(LuaValue e) {
+ return e.tonumber();
+ }
+ public LuaValue call(LuaValue e, LuaValue base) {
+ if (base.isnil())
+ return e.tonumber();
+ final int b = base.checkint();
+ if (b < 2 || b > 36)
+ argerror(2, "base out of range");
+ return e.checkstring().tonumber(b);
+ }
+ }
+
+ // "tostring", // (e) -> value
+ static final class tostring extends LibFunction {
+ public LuaValue call(LuaValue arg) {
+ LuaValue h = arg.metatag(TOSTRING);
+ if ( ! h.isnil() ) {
+ LuaValue v = h.call(arg);
+ LuaValue vs = v.tostring();
+ return !vs.isnil() ? vs : v;
+ }
+ LuaValue v = arg.tostring();
+ if ( ! v.isnil() )
+ return v;
+ return valueOf(arg.tojstring());
+ }
+ }
+
+ // "type", // (v) -> value
+ static final class type extends LibFunction {
+ @Override
+ public LuaValue call(LuaValue arg) {
+ return valueOf(arg.typename());
+ }
+ }
+
+ // "xpcall", // (f, err) -> result1, ...
+ final class xpcall extends VarArgFunction {
+ @Override
+ public Varargs invoke(Varargs args) {
+ final LuaThread t = globals.running;
+ final LuaValue preverror = t.errorfunc;
+ t.errorfunc = args.checkvalue(2);
+ try {
+ if (globals != null && globals.debuglib != null)
+ globals.debuglib.onCall(this);
+ try {
+ return varargsOf(TRUE, args.arg1().invoke(args.subargs(3)));
+ } catch ( LuaError le ) {
+ final LuaValue m = le.getMessageObject();
+ return varargsOf(FALSE, m!=null? m: NIL);
+ } catch ( Exception e ) {
+ final String m = e.getMessage();
+ return varargsOf(FALSE, valueOf(m!=null? m: e.toString()));
+ } finally {
+ if (globals != null && globals.debuglib != null)
+ globals.debuglib.onReturn();
+ }
+ } finally {
+ t.errorfunc = preverror;
+ }
+ }
+ }
+
+ // pairsbase, // (t) -> iter-func, t, initial
+ static final class pairsbase extends VarArgFunction {
+ final LuaString method;
+ final LuaValue initial;
+ final VarArgFunction iter;
+
+ pairsbase(LuaString method, LuaValue initial, VarArgFunction iter) {
+ this.method = method;
+ this.initial = initial;
+ this.iter = iter;
+ }
+
+ public Varargs invoke(Varargs args) {
+ LuaValue arg = args.arg1();
+ LuaValue t = arg.metatag(method);
+ if (!t.isnil())
+ // TODO: This can return more than 3 results.
+ return t.invoke(args.isvalue(1) ? arg : t);
+ return varargsOf(iter, args.checktable(1), initial);
+ }
+ }
+
+ // "next" ( table, [index] ) -> next-index, next-value
+ static final class next extends VarArgFunction {
+ public Varargs invoke(Varargs args) {
+ return args.checktable(1).next(args.arg(2));
+ }
+ }
+
+ // "inext" ( table, [int-index] ) -> next-index, next-value
+ static final class inext extends VarArgFunction {
+ @Override
+ public Varargs invoke(Varargs args) {
+ return args.checktable(1).inext(args.arg(2));
+ }
+ }
+
+ /**
+ * Load from a named file, returning the chunk or nil,error of can't load
+ * @param env
+ * @param mode
+ * @return Varargs containing chunk, or NIL,error-text on error
+ */
+ public Varargs loadFile(String filename, String mode, LuaValue env) {
+ InputStream is = globals.finder.findResource(filename);
+ if ( is == null )
+ return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory"));
+ try {
+ return loadStream(is, "@"+filename, mode, env);
+ } finally {
+ try {
+ is.close();
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) {
+ try {
+ if ( is == null )
+ return varargsOf(NIL, valueOf("not found: "+chunkname));
+ return globals.load(is, chunkname, mode, env);
+ } catch (Exception e) {
+ return varargsOf(NIL, valueOf(e.getMessage()));
+ }
+ }
+
+ private static class StringInputStream extends InputStream {
+ final LuaValue func;
+ byte[] bytes;
+ int offset, remaining = 0;
+ StringInputStream(LuaValue func) {
+ this.func = func;
+ }
+ public int read() throws IOException {
+ if ( remaining < 0 )
+ return -1;
+ if ( remaining == 0 ) {
+ LuaValue s = func.call();
+ if ( s.isnil() )
+ return remaining = -1;
+ LuaString ls = s.strvalue();
+ bytes = ls.m_bytes;
+ offset = ls.m_offset;
+ remaining = ls.m_length;
+ if (remaining <= 0)
+ return -1;
+ }
+ --remaining;
+ return 0xFF & bytes[offset++];
+ }
+ }
+}
diff --git a/src/core/org/luaj/vm2/lib/Bit32Lib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java
similarity index 54%
rename from src/core/org/luaj/vm2/lib/Bit32Lib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java
index 699c6945..477e7317 100644
--- a/src/core/org/luaj/vm2/lib/Bit32Lib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,68 +26,88 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
- * Subclass of LibFunction that implements the Lua standard {@code bit32} library.
+ * Subclass of LibFunction that implements the Lua standard {@code bit32}
+ * library.
*
* Typically, this library is included as part of a call to either
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Bitwise Operation Lib Reference
+ * @see Lua 5.2 Bitwise
+ * Operation Lib Reference
*/
public class Bit32Lib extends TwoArgFunction {
public Bit32Lib() {
}
- /** Perform one-time initialization on the library by creating a table
- * containing the library functions, adding that table to the supplied environment,
- * adding the table to package.loaded, and returning table as the return value.
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, which must be a Globals instance.
+ * @param env the environment to load into, which must be a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
LuaTable t = new LuaTable();
- bind(t, Bit32LibV.class, new String[] {
- "band", "bnot", "bor", "btest", "bxor", "extract", "replace"
- });
- bind(t, Bit32Lib2.class, new String[] {
- "arshift", "lrotate", "lshift", "rrotate", "rshift"
- });
+ bind(t, Bit32LibV.class, new String[] { "band", "bnot", "bor", "btest", "bxor", "extract", "replace" });
+ bind(t, Bit32Lib2.class, new String[] { "arshift", "lrotate", "lshift", "rrotate", "rshift" });
env.set("bit32", t);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("bit32", t);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("bit32", t);
return t;
}
static final class Bit32LibV extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- switch ( opcode ) {
- case 0: return Bit32Lib.band( args );
- case 1: return Bit32Lib.bnot( args );
- case 2: return Bit32Lib.bor( args );
- case 3: return Bit32Lib.btest( args );
- case 4: return Bit32Lib.bxor( args );
+ switch (opcode) {
+ case 0:
+ return Bit32Lib.band(args);
+ case 1:
+ return Bit32Lib.bnot(args);
+ case 2:
+ return Bit32Lib.bor(args);
+ case 3:
+ return Bit32Lib.btest(args);
+ case 4:
+ return Bit32Lib.bxor(args);
case 5:
- return Bit32Lib.extract( args.checkint(1), args.checkint(2), args.optint(3, 1) );
+ return Bit32Lib.extract(args.checkint(1), args.checkint(2), args.optint(3, 1));
case 6:
- return Bit32Lib.replace( args.checkint(1), args.checkint(2),
- args.checkint(3), args.optint(4, 1) );
+ return Bit32Lib.replace(args.checkint(1), args.checkint(2), args.checkint(3), args.optint(4, 1));
}
return NIL;
}
@@ -95,24 +115,30 @@ public class Bit32Lib extends TwoArgFunction {
static final class Bit32Lib2 extends TwoArgFunction {
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
- switch ( opcode ) {
- case 0: return Bit32Lib.arshift(arg1.checkint(), arg2.checkint());
- case 1: return Bit32Lib.lrotate(arg1.checkint(), arg2.checkint());
- case 2: return Bit32Lib.lshift(arg1.checkint(), arg2.checkint());
- case 3: return Bit32Lib.rrotate(arg1.checkint(), arg2.checkint());
- case 4: return Bit32Lib.rshift(arg1.checkint(), arg2.checkint());
+ switch (opcode) {
+ case 0:
+ return Bit32Lib.arshift(arg1.checkint(), arg2.checkint());
+ case 1:
+ return Bit32Lib.lrotate(arg1.checkint(), arg2.checkint());
+ case 2:
+ return Bit32Lib.lshift(arg1.checkint(), arg2.checkint());
+ case 3:
+ return Bit32Lib.rrotate(arg1.checkint(), arg2.checkint());
+ case 4:
+ return Bit32Lib.rshift(arg1.checkint(), arg2.checkint());
}
return NIL;
}
-
+
}
static LuaValue arshift(int x, int disp) {
if (disp >= 0) {
- return bitsToValue(x >> disp);
+ return bitsToValue(x>>disp);
} else {
- return bitsToValue(x << -disp);
+ return bitsToValue(x<<-disp);
}
}
@@ -120,9 +146,9 @@ public class Bit32Lib extends TwoArgFunction {
if (disp >= 32 || disp <= -32) {
return ZERO;
} else if (disp >= 0) {
- return bitsToValue(x >>> disp);
+ return bitsToValue(x>>>disp);
} else {
- return bitsToValue(x << -disp);
+ return bitsToValue(x<<-disp);
}
}
@@ -130,46 +156,46 @@ public class Bit32Lib extends TwoArgFunction {
if (disp >= 32 || disp <= -32) {
return ZERO;
} else if (disp >= 0) {
- return bitsToValue(x << disp);
+ return bitsToValue(x<>> -disp);
+ return bitsToValue(x>>>-disp);
}
}
- static Varargs band( Varargs args ) {
+ static Varargs band(Varargs args) {
int result = -1;
- for ( int i = 1; i <= args.narg(); i++ ) {
+ for (int i = 1; i <= args.narg(); i++) {
result &= args.checkint(i);
}
- return bitsToValue( result );
+ return bitsToValue(result);
}
- static Varargs bnot( Varargs args ) {
- return bitsToValue( ~args.checkint(1) );
+ static Varargs bnot(Varargs args) {
+ return bitsToValue(~args.checkint(1));
}
- static Varargs bor( Varargs args ) {
+ static Varargs bor(Varargs args) {
int result = 0;
- for ( int i = 1; i <= args.narg(); i++ ) {
+ for (int i = 1; i <= args.narg(); i++) {
result |= args.checkint(i);
}
- return bitsToValue( result );
+ return bitsToValue(result);
}
- static Varargs btest( Varargs args ) {
+ static Varargs btest(Varargs args) {
int bits = -1;
- for ( int i = 1; i <= args.narg(); i++ ) {
+ for (int i = 1; i <= args.narg(); i++) {
bits &= args.checkint(i);
}
- return valueOf( bits != 0 );
+ return valueOf(bits != 0);
}
- static Varargs bxor( Varargs args ) {
+ static Varargs bxor(Varargs args) {
int result = 0;
- for ( int i = 1; i <= args.narg(); i++ ) {
+ for (int i = 1; i <= args.narg(); i++) {
result ^= args.checkint(i);
}
- return bitsToValue( result );
+ return bitsToValue(result);
}
static LuaValue lrotate(int x, int disp) {
@@ -177,7 +203,7 @@ public class Bit32Lib extends TwoArgFunction {
return rrotate(x, -disp);
} else {
disp = disp & 31;
- return bitsToValue((x << disp) | (x >>> (32 - disp)));
+ return bitsToValue(x<>>32-disp);
}
}
@@ -186,7 +212,7 @@ public class Bit32Lib extends TwoArgFunction {
return lrotate(x, -disp);
} else {
disp = disp & 31;
- return bitsToValue((x >>> disp) | (x << (32 - disp)));
+ return bitsToValue(x>>>disp | x<<32-disp);
}
}
@@ -197,10 +223,10 @@ public class Bit32Lib extends TwoArgFunction {
if (width < 0) {
argerror(3, "width must be postive");
}
- if (field + width > 32) {
+ if (field+width > 32) {
error("trying to access non-existent bits");
}
- return bitsToValue((n >>> field) & (-1 >>> (32 - width)));
+ return bitsToValue(n>>>field & -1>>>32-width);
}
static LuaValue replace(int n, int v, int field, int width) {
@@ -210,15 +236,15 @@ public class Bit32Lib extends TwoArgFunction {
if (width < 0) {
argerror(4, "width must be postive");
}
- if (field + width > 32) {
+ if (field+width > 32) {
error("trying to access non-existent bits");
}
- int mask = (-1 >>> (32 - width)) << field;
- n = (n & ~mask) | ((v << field) & mask);
+ int mask = -1>>>32-width<
- * The coroutine library in luaj has the same behavior as the
- * coroutine library in C, but is implemented using Java Threads to maintain
- * the call state between invocations. Therefore it can be yielded from anywhere,
- * similar to the "Coco" yield-from-anywhere patch available for C-based lua.
- * However, coroutines that are yielded but never resumed to complete their execution
- * may not be collected by the garbage collector.
+ * The coroutine library in luaj has the same behavior as the coroutine library
+ * in C, but is implemented using Java Threads to maintain the call state
+ * between invocations. Therefore it can be yielded from anywhere, similar to
+ * the "Coco" yield-from-anywhere patch available for C-based lua. However,
+ * coroutines that are yielded but never resumed to complete their execution may
+ * not be collected by the garbage collector.
*
* Typically, this library is included as part of a call to either
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Coroutine Lib Reference
+ * @see Lua 5.2
+ * Coroutine Lib Reference
*/
public class CoroutineLib extends TwoArgFunction {
static int coroutine_count = 0;
Globals globals;
-
- /** Perform one-time initialization on the library by creating a table
- * containing the library functions, adding that table to the supplied environment,
- * adding the table to package.loaded, and returning table as the return value.
+
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, which must be a Globals instance.
+ * @param env the environment to load into, which must be a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
globals = env.checkglobals();
LuaTable coroutine = new LuaTable();
@@ -82,24 +98,28 @@ public class CoroutineLib extends TwoArgFunction {
coroutine.set("yield", new yield());
coroutine.set("wrap", new wrap());
env.set("coroutine", coroutine);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("coroutine", coroutine);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("coroutine", coroutine);
return coroutine;
}
final class create extends LibFunction {
+ @Override
public LuaValue call(LuaValue f) {
return new LuaThread(globals, f.checkfunction());
}
}
static final class resume extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
final LuaThread t = args.checkthread(1);
- return t.resume( args.subargs(2) );
+ return t.resume(args.subargs(2));
}
}
final class running extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
final LuaThread r = globals.running;
return varargsOf(r, valueOf(r.isMainThread()));
@@ -107,19 +127,22 @@ public class CoroutineLib extends TwoArgFunction {
}
static final class status extends LibFunction {
+ @Override
public LuaValue call(LuaValue t) {
LuaThread lt = t.checkthread();
- return valueOf( lt.getStatus() );
+ return valueOf(lt.getStatus());
}
}
-
+
final class yield extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- return globals.yield( args );
+ return globals.yield(args);
}
}
final class wrap extends LibFunction {
+ @Override
public LuaValue call(LuaValue f) {
final LuaValue func = f.checkfunction();
final LuaThread thread = new LuaThread(globals, func);
@@ -129,15 +152,18 @@ public class CoroutineLib extends TwoArgFunction {
static final class wrapper extends VarArgFunction {
final LuaThread luathread;
+
wrapper(LuaThread luathread) {
this.luathread = luathread;
}
+
+ @Override
public Varargs invoke(Varargs args) {
final Varargs result = luathread.resume(args);
- if ( result.arg1().toboolean() ) {
+ if (result.arg1().toboolean()) {
return result.subargs(2);
} else {
- return error( result.arg(2).tojstring() );
+ return error(result.arg(2).tojstring());
}
}
}
diff --git a/src/core/org/luaj/vm2/lib/DebugLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java
similarity index 60%
rename from src/core/org/luaj/vm2/lib/DebugLib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java
index 167ea36c..db138151 100644
--- a/src/core/org/luaj/vm2/lib/DebugLib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -39,58 +39,73 @@ import org.luaj.vm2.Prototype;
import org.luaj.vm2.Varargs;
/**
- * Subclass of {@link LibFunction} which implements the lua standard {@code debug}
- * library.
+ * Subclass of {@link LibFunction} which implements the lua standard
+ * {@code debug} library.
*
- * The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library.
- * To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction}
- * instances.
- * Especially when lua-to-java bytecode compiling is being used
- * via a {@link org.luaj.vm2.Globals.Compiler} such as {@link org.luaj.vm2.luajc.LuaJC},
- * this cannot be done in all cases.
+ * The debug library in luaj tries to emulate the behavior of the corresponding
+ * C-based lua library. To do this, it must maintain a separate stack of calls
+ * to {@link LuaClosure} and {@link LibFunction} instances. Especially when
+ * lua-to-java bytecode compiling is being used via a
+ * {@link org.luaj.vm2.Globals.Compiler} such as
+ * {@link org.luaj.vm2.luajc.LuaJC}, this cannot be done in all cases.
*
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#debugGlobals()} or
* {@link org.luaj.vm2.lib.jme.JmePlatform#debugGlobals()}
- *
- * This library exposes the entire state of lua code, and provides method to see and modify
- * all underlying lua values within a Java VM so should not be exposed to client code
- * in a shared server environment.
- *
+ * This library exposes the entire state of lua code, and provides method to see
+ * and modify all underlying lua values within a Java VM so should not be
+ * exposed to client code in a shared server environment.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Debug Lib Reference
+ * @see Lua 5.2 Debug
+ * Lib Reference
*/
public class DebugLib extends TwoArgFunction {
public static boolean CALLS;
public static boolean TRACE;
static {
- try { CALLS = (null != System.getProperty("CALLS")); } catch (Exception e) {}
- try { TRACE = (null != System.getProperty("TRACE")); } catch (Exception e) {}
+ try {
+ CALLS = null != System.getProperty("CALLS");
+ } catch (Exception e) {
+ }
+ try {
+ TRACE = null != System.getProperty("TRACE");
+ } catch (Exception e) {
+ }
}
-
- static final LuaString LUA = valueOf("Lua");
- private static final LuaString QMARK = valueOf("?");
- private static final LuaString CALL = valueOf("call");
- private static final LuaString LINE = valueOf("line");
- private static final LuaString COUNT = valueOf("count");
- private static final LuaString RETURN = valueOf("return");
-
+
+ static final LuaString LUA = valueOf("Lua");
+ private static final LuaString QMARK = valueOf("?");
+ private static final LuaString CALL = valueOf("call");
+ private static final LuaString LINE = valueOf("line");
+ private static final LuaString COUNT = valueOf("count");
+ private static final LuaString RETURN = valueOf("return");
+
static final LuaString FUNC = valueOf("func");
static final LuaString ISTAILCALL = valueOf("istailcall");
static final LuaString ISVARARG = valueOf("isvararg");
@@ -107,13 +122,18 @@ public class DebugLib extends TwoArgFunction {
static final LuaString ACTIVELINES = valueOf("activelines");
Globals globals;
-
- /** Perform one-time initialization on the library by creating a table
- * containing the library functions, adding that table to the supplied environment,
- * adding the table to package.loaded, and returning table as the return value.
+
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, which must be a Globals instance.
+ * @param env the environment to load into, which must be a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
globals = env.checkglobals();
globals.debuglib = this;
@@ -135,12 +155,14 @@ public class DebugLib extends TwoArgFunction {
debug.set("upvalueid", new upvalueid());
debug.set("upvaluejoin", new upvaluejoin());
env.set("debug", debug);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("debug", debug);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("debug", debug);
return debug;
}
// debug.debug()
static final class debug extends ZeroArgFunction {
+ @Override
public LuaValue call() {
return NONE;
}
@@ -148,20 +170,20 @@ public class DebugLib extends TwoArgFunction {
// debug.gethook ([thread])
final class gethook extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- LuaThread t = args.narg() > 0 ? args.checkthread(1): globals.running;
+ LuaThread t = args.narg() > 0? args.checkthread(1): globals.running;
LuaThread.State s = t.state;
- return varargsOf(
- s.hookfunc != null? s.hookfunc: NIL,
- valueOf((s.hookcall?"c":"")+(s.hookline?"l":"")+(s.hookrtrn?"r":"")),
- valueOf(s.hookcount));
+ return varargsOf(s.hookfunc != null? s.hookfunc: NIL,
+ valueOf((s.hookcall? "c": "")+(s.hookline? "l": "")+(s.hookrtrn? "r": "")), valueOf(s.hookcount));
}
}
// debug.getinfo ([thread,] f [, what])
final class getinfo extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- int a=1;
+ int a = 1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
LuaValue func = args.arg(a++);
String what = args.optjstring(a++, "flnStu");
@@ -169,12 +191,12 @@ public class DebugLib extends TwoArgFunction {
// find the stack info
DebugLib.CallFrame frame;
- if ( func.isnumber() ) {
+ if (func.isnumber()) {
frame = callstack.getCallFrame(func.toint());
if (frame == null)
return NONE;
func = frame.f;
- } else if ( func.isfunction() ) {
+ } else if (func.isfunction()) {
frame = callstack.findCallFrame(func);
} else {
return argerror(a-2, "function or level");
@@ -191,7 +213,7 @@ public class DebugLib extends TwoArgFunction {
info.set(LASTLINEDEFINED, valueOf(ar.lastlinedefined));
}
if (what.indexOf('l') >= 0) {
- info.set( CURRENTLINE, valueOf(ar.currentline) );
+ info.set(CURRENTLINE, valueOf(ar.currentline));
}
if (what.indexOf('u') >= 0) {
info.set(NUPS, valueOf(ar.nups));
@@ -199,7 +221,7 @@ public class DebugLib extends TwoArgFunction {
info.set(ISVARARG, ar.isvararg? ONE: ZERO);
}
if (what.indexOf('n') >= 0) {
- info.set(NAME, LuaValue.valueOf(ar.name!=null? ar.name: "?"));
+ info.set(NAME, LuaValue.valueOf(ar.name != null? ar.name: "?"));
info.set(NAMEWHAT, LuaValue.valueOf(ar.namewhat));
}
if (what.indexOf('t') >= 0) {
@@ -209,13 +231,13 @@ public class DebugLib extends TwoArgFunction {
LuaTable lines = new LuaTable();
info.set(ACTIVELINES, lines);
DebugLib.CallFrame cf;
- for (int l = 1; (cf=callstack.getCallFrame(l)) != null; ++l)
+ for (int l = 1; (cf = callstack.getCallFrame(l)) != null; ++l)
if (cf.f == func)
lines.insert(-1, valueOf(cf.currentline()));
}
if (what.indexOf('f') >= 0) {
if (func != null)
- info.set( FUNC, func );
+ info.set(FUNC, func);
}
return info;
}
@@ -223,18 +245,27 @@ public class DebugLib extends TwoArgFunction {
// debug.getlocal ([thread,] f, local)
final class getlocal extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- int a=1;
+ int a = 1;
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running;
- int level = args.checkint(a++);
- int local = args.checkint(a++);
- CallFrame f = callstack(thread).getCallFrame(level);
- return f != null? f.getLocal(local): NONE;
+ LuaValue func = args.arg(a++);
+ int local = args.checkint(a);
+
+ if (func.isfunction())
+ return func.checkclosure().p.getlocalname(local, 0);
+
+ // find the stack info
+ DebugLib.CallFrame frame = callstack(thread).getCallFrame(func.checkint());
+ if (frame == null)
+ return argerror(a, "level out of range");
+ return frame.getLocal(local);
}
}
// debug.getmetatable (value)
static final class getmetatable extends LibFunction {
+ @Override
public LuaValue call(LuaValue v) {
LuaValue mt = v.getmetatable();
return mt != null? mt: NIL;
@@ -243,6 +274,7 @@ public class DebugLib extends TwoArgFunction {
// debug.getregistry ()
final class getregistry extends ZeroArgFunction {
+ @Override
public LuaValue call() {
return globals;
}
@@ -250,14 +282,15 @@ public class DebugLib extends TwoArgFunction {
// debug.getupvalue (f, up)
static final class getupvalue extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaValue func = args.checkfunction(1);
int up = args.checkint(2);
- if ( func instanceof LuaClosure ) {
+ if (func instanceof LuaClosure) {
LuaClosure c = (LuaClosure) func;
LuaString name = findupvalue(c, up);
- if ( name != null ) {
- return varargsOf(name, c.upValues[up-1].getValue() );
+ if (name != null) {
+ return varargsOf(name, c.upValues[up-1].getValue());
}
}
return NIL;
@@ -266,26 +299,33 @@ public class DebugLib extends TwoArgFunction {
// debug.getuservalue (u)
static final class getuservalue extends LibFunction {
+ @Override
public LuaValue call(LuaValue u) {
return u.isuserdata()? u: NIL;
}
}
-
-
+
// debug.sethook ([thread,] hook, mask [, count])
final class sethook extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- int a=1;
+ int a = 1;
LuaThread t = args.isthread(a)? args.checkthread(a++): globals.running;
- LuaValue func = args.optfunction(a++, null);
- String str = args.optjstring(a++,"");
- int count = args.optint(a++,0);
- boolean call=false,line=false,rtrn=false;
- for ( int i=0; i 0 && up <= c.upValues.length ) {
+ if (c.upValues != null && up > 0 && up <= c.upValues.length) {
return valueOf(c.upValues[up-1].hashCode());
}
}
@@ -386,11 +445,12 @@ public class DebugLib extends TwoArgFunction {
// debug.upvaluejoin (f1, n1, f2, n2)
static final class upvaluejoin extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- LuaClosure f1 = args.checkclosure(1);
int n1 = args.checkint(2);
- LuaClosure f2 = args.checkclosure(3);
+ LuaClosure f1 = args.checkclosure(1);
int n2 = args.checkint(4);
+ LuaClosure f2 = args.checkclosure(3);
if (n1 < 1 || n1 > f1.upValues.length)
argerror("index out of range");
if (n2 < 1 || n2 > f2.upValues.length)
@@ -402,29 +462,35 @@ public class DebugLib extends TwoArgFunction {
public void onCall(LuaFunction f) {
LuaThread.State s = globals.running.state;
- if (s.inhook) return;
+ if (s.inhook)
+ return;
callstack().onCall(f);
- if (s.hookcall) callHook(s, CALL, NIL);
+ if (s.hookcall)
+ callHook(s, CALL, NIL);
}
public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) {
LuaThread.State s = globals.running.state;
- if (s.inhook) return;
+ if (s.inhook)
+ return;
callstack().onCall(c, varargs, stack);
- if (s.hookcall) callHook(s, CALL, NIL);
+ if (s.hookcall)
+ callHook(s, CALL, NIL);
}
public void onInstruction(int pc, Varargs v, int top) {
LuaThread.State s = globals.running.state;
- if (s.inhook) return;
+ if (s.inhook)
+ return;
callstack().onInstruction(pc, v, top);
- if (s.hookfunc == null) return;
+ if (s.hookfunc == null)
+ return;
if (s.hookcount > 0)
- if (++s.bytecodes % s.hookcount == 0)
+ if (++s.bytecodes%s.hookcount == 0)
callHook(s, COUNT, NIL);
if (s.hookline) {
int newline = callstack().currentline();
- if ( newline != s.lastline ) {
+ if (newline != s.lastline) {
s.lastline = newline;
callHook(s, LINE, LuaValue.valueOf(newline));
}
@@ -433,21 +499,24 @@ public class DebugLib extends TwoArgFunction {
public void onReturn() {
LuaThread.State s = globals.running.state;
- if (s.inhook) return;
+ if (s.inhook)
+ return;
callstack().onReturn();
- if (s.hookrtrn) callHook(s, RETURN, NIL);
+ if (s.hookrtrn)
+ callHook(s, RETURN, NIL);
}
public String traceback(int level) {
return callstack().traceback(level);
}
-
+
public CallFrame getCallFrame(int level) {
return callstack().getCallFrame(level);
}
-
+
void callHook(LuaThread.State s, LuaValue type, LuaValue arg) {
- if (s.inhook || s.hookfunc == null) return;
+ if (s.inhook || s.hookfunc == null)
+ return;
s.inhook = true;
try {
s.hookfunc.call(type, arg);
@@ -459,7 +528,7 @@ public class DebugLib extends TwoArgFunction {
s.inhook = false;
}
}
-
+
CallStack callstack() {
return callstack(globals.running);
}
@@ -471,27 +540,27 @@ public class DebugLib extends TwoArgFunction {
}
static class DebugInfo {
- String name; /* (n) */
- String namewhat; /* (n) 'global', 'local', 'field', 'method' */
- String what; /* (S) 'Lua', 'C', 'main', 'tail' */
- String source; /* (S) */
- int currentline; /* (l) */
- int linedefined; /* (S) */
- int lastlinedefined; /* (S) */
- short nups; /* (u) number of upvalues */
- short nparams;/* (u) number of parameters */
- boolean isvararg; /* (u) */
- boolean istailcall; /* (t) */
- String short_src; /* (S) */
- CallFrame cf; /* active function */
+ String name; /* (n) */
+ String namewhat; /* (n) 'global', 'local', 'field', 'method' */
+ String what; /* (S) 'Lua', 'C', 'main', 'tail' */
+ String source; /* (S) */
+ int currentline; /* (l) */
+ int linedefined; /* (S) */
+ int lastlinedefined; /* (S) */
+ short nups; /* (u) number of upvalues */
+ short nparams; /* (u) number of parameters */
+ boolean isvararg; /* (u) */
+ boolean istailcall; /* (t) */
+ String short_src; /* (S) */
+ CallFrame cf; /* active function */
public void funcinfo(LuaFunction f) {
if (f.isclosure()) {
Prototype p = f.checkclosure().p;
- this.source = p.source != null ? p.source.tojstring() : "=?";
+ this.source = p.source != null? p.source.tojstring(): "=?";
this.linedefined = p.linedefined;
this.lastlinedefined = p.lastlinedefined;
- this.what = (this.linedefined == 0) ? "main" : "Lua";
+ this.what = this.linedefined == 0? "main": "Lua";
this.short_src = p.shortsource();
} else {
this.source = "=[Java]";
@@ -502,21 +571,21 @@ public class DebugLib extends TwoArgFunction {
}
}
}
-
+
public static class CallStack {
final static CallFrame[] EMPTY = {};
- CallFrame[] frame = EMPTY;
- int calls = 0;
+ CallFrame[] frame = EMPTY;
+ int calls = 0;
CallStack() {}
-
+
synchronized int currentline() {
return calls > 0? frame[calls-1].currentline(): -1;
}
private synchronized CallFrame pushcall() {
if (calls >= frame.length) {
- int n = Math.max(4, frame.length * 3 / 2);
+ int n = Math.max(4, frame.length*3/2);
CallFrame[] f = new CallFrame[n];
System.arraycopy(frame, 0, f, 0, frame.length);
for (int i = frame.length; i < n; ++i)
@@ -527,7 +596,7 @@ public class DebugLib extends TwoArgFunction {
}
return frame[calls++];
}
-
+
final synchronized void onCall(LuaFunction function) {
pushcall().set(function);
}
@@ -535,12 +604,12 @@ public class DebugLib extends TwoArgFunction {
final synchronized void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) {
pushcall().set(function, varargs, stack);
}
-
+
final synchronized void onReturn() {
if (calls > 0)
frame[--calls].reset();
}
-
+
final synchronized void onInstruction(int pc, Varargs v, int top) {
if (calls > 0)
frame[calls-1].instr(pc, v, top);
@@ -548,32 +617,33 @@ public class DebugLib extends TwoArgFunction {
/**
* Get the traceback starting at a specific level.
+ *
* @param level
* @return String containing the traceback.
*/
synchronized String traceback(int level) {
StringBuffer sb = new StringBuffer();
- sb.append( "stack traceback:" );
- for (DebugLib.CallFrame c; (c = getCallFrame(level++)) != null; ) {
+ sb.append("stack traceback:");
+ for (DebugLib.CallFrame c; (c = getCallFrame(level++)) != null;) {
sb.append("\n\t");
- sb.append( c.shortsource() );
- sb.append( ':' );
+ sb.append(c.shortsource());
+ sb.append(':');
if (c.currentline() > 0)
- sb.append( c.currentline()+":" );
- sb.append( " in " );
+ sb.append(c.currentline() + ":");
+ sb.append(" in ");
DebugInfo ar = auxgetinfo("n", c.f, c);
if (c.linedefined() == 0)
sb.append("main chunk");
- else if ( ar.name != null ) {
- sb.append( "function '" );
- sb.append( ar.name );
- sb.append( '\'' );
+ else if (ar.name != null) {
+ sb.append("function '");
+ sb.append(ar.name);
+ sb.append('\'');
} else {
- sb.append( "function <" );
- sb.append( c.shortsource() );
- sb.append( ':' );
- sb.append( c.linedefined() );
- sb.append( '>' );
+ sb.append("function <");
+ sb.append(c.shortsource());
+ sb.append(':');
+ sb.append(c.linedefined());
+ sb.append('>');
}
}
sb.append("\n\t[Java]: in ?");
@@ -593,55 +663,54 @@ public class DebugLib extends TwoArgFunction {
return null;
}
-
synchronized DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) {
DebugInfo ar = new DebugInfo();
for (int i = 0, n = what.length(); i < n; ++i) {
switch (what.charAt(i)) {
- case 'S':
- ar.funcinfo(f);
- break;
- case 'l':
- ar.currentline = ci != null && ci.f.isclosure()? ci.currentline(): -1;
- break;
- case 'u':
- if (f != null && f.isclosure()) {
- Prototype p = f.checkclosure().p;
- ar.nups = (short) p.upvalues.length;
- ar.nparams = (short) p.numparams;
- ar.isvararg = p.is_vararg != 0;
- } else {
- ar.nups = 0;
- ar.isvararg = true;
- ar.nparams = 0;
- }
- break;
- case 't':
- ar.istailcall = false;
- break;
- case 'n': {
- /* calling function is a known Lua function? */
- if (ci != null && ci.previous != null) {
- if (ci.previous.f.isclosure()) {
- NameWhat nw = getfuncname(ci.previous);
- if (nw != null) {
- ar.name = nw.name;
- ar.namewhat = nw.namewhat;
- }
- }
- }
- if (ar.namewhat == null) {
- ar.namewhat = ""; /* not found */
- ar.name = null;
- }
- break;
- }
- case 'L':
- case 'f':
- break;
- default:
- // TODO: return bad status.
- break;
+ case 'S':
+ ar.funcinfo(f);
+ break;
+ case 'l':
+ ar.currentline = ci != null && ci.f.isclosure()? ci.currentline(): -1;
+ break;
+ case 'u':
+ if (f != null && f.isclosure()) {
+ Prototype p = f.checkclosure().p;
+ ar.nups = (short) p.upvalues.length;
+ ar.nparams = (short) p.numparams;
+ ar.isvararg = p.is_vararg != 0;
+ } else {
+ ar.nups = 0;
+ ar.isvararg = true;
+ ar.nparams = 0;
+ }
+ break;
+ case 't':
+ ar.istailcall = false;
+ break;
+ case 'n': {
+ /* calling function is a known Lua function? */
+ if (ci != null && ci.previous != null) {
+ if (ci.previous.f.isclosure()) {
+ NameWhat nw = getfuncname(ci.previous);
+ if (nw != null) {
+ ar.name = nw.name;
+ ar.namewhat = nw.namewhat;
+ }
+ }
+ }
+ if (ar.namewhat == null) {
+ ar.namewhat = ""; /* not found */
+ ar.name = null;
+ }
+ break;
+ }
+ case 'L':
+ case 'f':
+ break;
+ default:
+ // TODO: return bad status.
+ break;
}
}
return ar;
@@ -650,28 +719,35 @@ public class DebugLib extends TwoArgFunction {
}
public static class CallFrame {
+ static final LuaValue[] EMPTY = {};
+
LuaFunction f;
- int pc;
- int top;
- Varargs v;
- LuaValue[] stack;
- CallFrame previous;
+ int pc;
+ int top;
+ Varargs v;
+ LuaValue[] stack = EMPTY;
+ CallFrame previous;
+
void set(LuaClosure function, Varargs varargs, LuaValue[] stack) {
this.f = function;
this.v = varargs;
this.stack = stack;
}
+
public String shortsource() {
return f.isclosure()? f.checkclosure().p.shortsource(): "[Java]";
}
+
void set(LuaFunction function) {
this.f = function;
}
+
void reset() {
this.f = null;
this.v = null;
- this.stack = null;
+ this.stack = EMPTY;
}
+
void instr(int pc, Varargs v, int top) {
this.pc = pc;
this.v = v;
@@ -679,57 +755,68 @@ public class DebugLib extends TwoArgFunction {
if (TRACE)
Print.printState(f.checkclosure(), pc, stack, top, v);
}
+
Varargs getLocal(int i) {
LuaString name = getlocalname(i);
- if ( i >= 1 && i <= stack.length && stack[i-1] != null )
- return varargsOf( name == null ? NIL : name, stack[i-1] );
+ if (i >= 1 && i <= stack.length && stack[i-1] != null)
+ return varargsOf(name == null? NIL: name, stack[i-1]);
else
return NIL;
}
+
Varargs setLocal(int i, LuaValue value) {
LuaString name = getlocalname(i);
- if ( i >= 1 && i <= stack.length && stack[i-1] != null ) {
+ if (i >= 1 && i <= stack.length && stack[i-1] != null) {
stack[i-1] = value;
- return name == null ? NIL : name;
+ return name == null? NIL: name;
} else {
return NIL;
}
}
+
public int currentline() {
- if ( !f.isclosure() ) return -1;
+ if (!f.isclosure())
+ return -1;
int[] li = f.checkclosure().p.lineinfo;
- return li==null || pc<0 || pc>=li.length? -1: li[pc];
+ return li == null || pc < 0 || pc >= li.length? -1: li[pc];
}
+
String sourceline() {
- if ( !f.isclosure() ) return f.tojstring();
+ if (!f.isclosure())
+ return f.tojstring();
return f.checkclosure().p.shortsource() + ":" + currentline();
}
+
int linedefined() {
return f.isclosure()? f.checkclosure().p.linedefined: -1;
}
+
LuaString getlocalname(int index) {
- if ( !f.isclosure() ) return null;
+ if (!f.isclosure())
+ return null;
return f.checkclosure().p.getlocalname(index, pc);
}
}
static LuaString findupvalue(LuaClosure c, int up) {
- if ( c.upValues != null && up > 0 && up <= c.upValues.length ) {
- if ( c.p.upvalues != null && up <= c.p.upvalues.length )
+ if (c.upValues != null && up > 0 && up <= c.upValues.length) {
+ if (c.p.upvalues != null && up <= c.p.upvalues.length)
return c.p.upvalues[up-1].name;
else
- return LuaString.valueOf( "."+up );
+ return LuaString.valueOf("." + up);
}
return null;
}
-
+
static void lua_assert(boolean x) {
- if (!x) throw new RuntimeException("lua_assert failed");
+ if (!x)
+ throw new RuntimeException("lua_assert failed");
}
-
+
static class NameWhat {
final String name;
final String namewhat;
+
NameWhat(String name, String namewhat) {
this.name = name;
this.namewhat = namewhat;
@@ -745,41 +832,69 @@ public class DebugLib extends TwoArgFunction {
int i = p.code[pc]; /* calling instruction */
LuaString tm;
switch (Lua.GET_OPCODE(i)) {
- case Lua.OP_CALL:
- case Lua.OP_TAILCALL: /* get function name */
- return getobjname(p, pc, Lua.GETARG_A(i));
- case Lua.OP_TFORCALL: /* for iterator */
- return new NameWhat("(for iterator)", "(for iterator");
- /* all other instructions can call only through metamethods */
- case Lua.OP_SELF:
- case Lua.OP_GETTABUP:
- case Lua.OP_GETTABLE: tm = LuaValue.INDEX; break;
- case Lua.OP_SETTABUP:
- case Lua.OP_SETTABLE: tm = LuaValue.NEWINDEX; break;
- case Lua.OP_EQ: tm = LuaValue.EQ; break;
- case Lua.OP_ADD: tm = LuaValue.ADD; break;
- case Lua.OP_SUB: tm = LuaValue.SUB; break;
- case Lua.OP_MUL: tm = LuaValue.MUL; break;
- case Lua.OP_DIV: tm = LuaValue.DIV; break;
- case Lua.OP_MOD: tm = LuaValue.MOD; break;
- case Lua.OP_POW: tm = LuaValue.POW; break;
- case Lua.OP_UNM: tm = LuaValue.UNM; break;
- case Lua.OP_LEN: tm = LuaValue.LEN; break;
- case Lua.OP_LT: tm = LuaValue.LT; break;
- case Lua.OP_LE: tm = LuaValue.LE; break;
- case Lua.OP_CONCAT: tm = LuaValue.CONCAT; break;
- default:
- return null; /* else no useful name can be found */
+ case Lua.OP_CALL:
+ case Lua.OP_TAILCALL: /* get function name */
+ return getobjname(p, pc, Lua.GETARG_A(i));
+ case Lua.OP_TFORCALL: /* for iterator */
+ return new NameWhat("(for iterator)", "(for iterator");
+ /* all other instructions can call only through metamethods */
+ case Lua.OP_SELF:
+ case Lua.OP_GETTABUP:
+ case Lua.OP_GETTABLE:
+ tm = LuaValue.INDEX;
+ break;
+ case Lua.OP_SETTABUP:
+ case Lua.OP_SETTABLE:
+ tm = LuaValue.NEWINDEX;
+ break;
+ case Lua.OP_EQ:
+ tm = LuaValue.EQ;
+ break;
+ case Lua.OP_ADD:
+ tm = LuaValue.ADD;
+ break;
+ case Lua.OP_SUB:
+ tm = LuaValue.SUB;
+ break;
+ case Lua.OP_MUL:
+ tm = LuaValue.MUL;
+ break;
+ case Lua.OP_DIV:
+ tm = LuaValue.DIV;
+ break;
+ case Lua.OP_MOD:
+ tm = LuaValue.MOD;
+ break;
+ case Lua.OP_POW:
+ tm = LuaValue.POW;
+ break;
+ case Lua.OP_UNM:
+ tm = LuaValue.UNM;
+ break;
+ case Lua.OP_LEN:
+ tm = LuaValue.LEN;
+ break;
+ case Lua.OP_LT:
+ tm = LuaValue.LT;
+ break;
+ case Lua.OP_LE:
+ tm = LuaValue.LE;
+ break;
+ case Lua.OP_CONCAT:
+ tm = LuaValue.CONCAT;
+ break;
+ default:
+ return null; /* else no useful name can be found */
}
- return new NameWhat( tm.tojstring(), "metamethod" );
+ return new NameWhat(tm.tojstring(), "metamethod");
}
-
+
// return NameWhat if found, null if not
public static NameWhat getobjname(Prototype p, int lastpc, int reg) {
int pc = lastpc; // currentpc(L, ci);
- LuaString name = p.getlocalname(reg + 1, pc);
+ LuaString name = p.getlocalname(reg+1, pc);
if (name != null) /* is a local? */
- return new NameWhat( name.tojstring(), "local" );
+ return new NameWhat(name.tojstring(), "local");
/* else try symbolic execution */
pc = findsetreg(p, lastpc, reg);
@@ -797,31 +912,30 @@ public class DebugLib extends TwoArgFunction {
case Lua.OP_GETTABLE: {
int k = Lua.GETARG_C(i); /* key index */
int t = Lua.GETARG_B(i); /* table index */
- LuaString vn = (Lua.GET_OPCODE(i) == Lua.OP_GETTABLE) /* name of indexed variable */
- ? p.getlocalname(t + 1, pc)
- : (t < p.upvalues.length ? p.upvalues[t].name : QMARK);
+ LuaString vn = Lua.GET_OPCODE(i) == Lua.OP_GETTABLE /* name of indexed variable */
+ ? p.getlocalname(t+1, pc)
+ : t < p.upvalues.length? p.upvalues[t].name: QMARK;
String jname = kname(p, pc, k);
- return new NameWhat( jname, vn != null && vn.eq_b(ENV)? "global": "field" );
+ return new NameWhat(jname, vn != null && vn.eq_b(ENV)? "global": "field");
}
case Lua.OP_GETUPVAL: {
int u = Lua.GETARG_B(i); /* upvalue index */
- name = u < p.upvalues.length ? p.upvalues[u].name : QMARK;
- return name == null ? null : new NameWhat( name.tojstring(), "upvalue" );
+ name = u < p.upvalues.length? p.upvalues[u].name: QMARK;
+ return name == null? null: new NameWhat(name.tojstring(), "upvalue");
+ }
+ case Lua.OP_LOADK:
+ case Lua.OP_LOADKX: {
+ int b = Lua.GET_OPCODE(i) == Lua.OP_LOADK? Lua.GETARG_Bx(i): Lua.GETARG_Ax(p.code[pc+1]);
+ if (p.k[b].isstring()) {
+ name = p.k[b].strvalue();
+ return new NameWhat(name.tojstring(), "constant");
+ }
+ break;
}
- case Lua.OP_LOADK:
- case Lua.OP_LOADKX: {
- int b = (Lua.GET_OPCODE(i) == Lua.OP_LOADK) ? Lua.GETARG_Bx(i)
- : Lua.GETARG_Ax(p.code[pc + 1]);
- if (p.k[b].isstring()) {
- name = p.k[b].strvalue();
- return new NameWhat( name.tojstring(), "constant" );
- }
- break;
- }
case Lua.OP_SELF: {
int k = Lua.GETARG_C(i); /* key index */
String jname = kname(p, pc, k);
- return new NameWhat( jname, "method" );
+ return new NameWhat(jname, "method");
}
default:
break;
@@ -831,69 +945,73 @@ public class DebugLib extends TwoArgFunction {
}
static String kname(Prototype p, int pc, int c) {
- if (Lua.ISK(c)) { /* is 'c' a constant? */
+ if (Lua.ISK(c)) { /* is 'c' a constant? */
LuaValue k = p.k[Lua.INDEXK(c)];
- if (k.isstring()) { /* literal constant? */
- return k.tojstring(); /* it is its own name */
+ if (k.isstring()) { /* literal constant? */
+ return k.tojstring(); /* it is its own name */
} /* else no reasonable name found */
- } else { /* 'c' is a register */
+ } else { /* 'c' is a register */
NameWhat what = getobjname(p, pc, c); /* search for 'c' */
- if (what != null && "constant".equals(what.namewhat)) { /* found a constant name? */
- return what.name; /* 'name' already filled */
- }
- /* else no reasonable name found */
+ if (what != null && "constant".equals(what.namewhat)) { /* found a constant name? */
+ return what.name; /* 'name' already filled */
+ }
+ /* else no reasonable name found */
}
- return "?"; /* no reasonable name found */
+ return "?"; /* no reasonable name found */
}
/*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
- static int findsetreg (Prototype p, int lastpc, int reg) {
- int pc;
- int setreg = -1; /* keep last instruction that changed 'reg' */
- for (pc = 0; pc < lastpc; pc++) {
- int i = p.code[pc];
- int op = Lua.GET_OPCODE(i);
- int a = Lua.GETARG_A(i);
- switch (op) {
- case Lua.OP_LOADNIL: {
- int b = Lua.GETARG_B(i);
- if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
- setreg = pc;
- break;
- }
- case Lua.OP_TFORCALL: {
- if (reg >= a + 2) setreg = pc; /* affect all regs above its base */
- break;
- }
- case Lua.OP_CALL:
- case Lua.OP_TAILCALL: {
- if (reg >= a) setreg = pc; /* affect all registers above base */
- break;
- }
- case Lua.OP_JMP: {
- int b = Lua.GETARG_sBx(i);
- int dest = pc + 1 + b;
- /* jump is forward and do not skip `lastpc'? */
- if (pc < dest && dest <= lastpc)
- pc += b; /* do the jump */
- break;
- }
- case Lua.OP_TEST: {
- if (reg == a) setreg = pc; /* jumped code can change 'a' */
- break;
- }
- case Lua.OP_SETLIST: { // Lua.testAMode(Lua.OP_SETLIST) == false
- if ( ((i>>14)&0x1ff) == 0 ) pc++; // if c == 0 then c stored in next op -> skip
- break;
- }
- default:
- if (Lua.testAMode(op) && reg == a) /* any instruction that set A */
- setreg = pc;
- break;
- }
- }
- return setreg;
+ static int findsetreg(Prototype p, int lastpc, int reg) {
+ int pc;
+ int setreg = -1; /* keep last instruction that changed 'reg' */
+ for (pc = 0; pc < lastpc; pc++) {
+ int i = p.code[pc];
+ int op = Lua.GET_OPCODE(i);
+ int a = Lua.GETARG_A(i);
+ switch (op) {
+ case Lua.OP_LOADNIL: {
+ int b = Lua.GETARG_B(i);
+ if (a <= reg && reg <= a+b) /* set registers from 'a' to 'a+b' */
+ setreg = pc;
+ break;
+ }
+ case Lua.OP_TFORCALL: {
+ if (reg >= a+2)
+ setreg = pc; /* affect all regs above its base */
+ break;
+ }
+ case Lua.OP_CALL:
+ case Lua.OP_TAILCALL: {
+ if (reg >= a)
+ setreg = pc; /* affect all registers above base */
+ break;
+ }
+ case Lua.OP_JMP: {
+ int b = Lua.GETARG_sBx(i);
+ int dest = pc+1+b;
+ /* jump is forward and do not skip `lastpc'? */
+ if (pc < dest && dest <= lastpc)
+ pc += b; /* do the jump */
+ break;
+ }
+ case Lua.OP_TEST: {
+ if (reg == a)
+ setreg = pc; /* jumped code can change 'a' */
+ break;
+ }
+ case Lua.OP_SETLIST: { // Lua.testAMode(Lua.OP_SETLIST) == false
+ if ((i>>14 & 0x1ff) == 0)
+ pc++; // if c == 0 then c stored in next op -> skip
+ break;
+ }
+ default:
+ if (Lua.testAMode(op) && reg == a) /* any instruction that set A */
+ setreg = pc;
+ break;
+ }
+ }
+ return setreg;
}
}
diff --git a/src/core/org/luaj/vm2/lib/IoLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java
similarity index 55%
rename from src/core/org/luaj/vm2/lib/IoLib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java
index 13f6f986..9983c0ec 100644
--- a/src/core/org/luaj/vm2/lib/IoLib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -32,113 +32,144 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
- * Abstract base class extending {@link LibFunction} which implements the
- * core of the lua standard {@code io} library.
+ * Abstract base class extending {@link LibFunction} which implements the core
+ * of the lua standard {@code io} library.
*
* It contains the implementation of the io library support that is common to
- * the JSE and JME platforms.
- * In practice on of the concrete IOLib subclasses is chosen:
- * {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and
+ * the JSE and JME platforms. In practice on of the concrete IOLib subclasses is
+ * chosen: {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and
* {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform.
*
* The JSE implementation conforms almost completely to the C-based lua library,
- * while the JME implementation follows closely except in the area of random-access files,
- * which are difficult to support properly on JME.
+ * while the JME implementation follows closely except in the area of
+ * random-access files, which are difficult to support properly on JME.
*
* Typically, this library is included as part of a call to either
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
- * In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseIoLib} library will be loaded, which will include
- * the base functionality provided by this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load the
- * {@link org.luaj.vm2.lib.jse.JseIoLib}.
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
+ *
+ *
+ *
+ * In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseIoLib}
+ * library will be loaded, which will include the base functionality provided by
+ * this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load
+ * the {@link org.luaj.vm2.lib.jse.JseIoLib}.
*
- * To instantiate and use it directly,
- * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
- *
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see org.luaj.vm2.lib.jse.JseIoLib
* @see org.luaj.vm2.lib.jme.JmeIoLib
- * @see http://www.lua.org/manual/5.1/manual.html#5.7
+ * @see http://www.lua.org/manual/5.1/manual.html#5.7
*/
-abstract
-public class IoLib extends TwoArgFunction {
+public abstract class IoLib extends TwoArgFunction {
+
+ protected abstract class File extends LuaValue {
+ public abstract void write(LuaString string) throws IOException;
+
+ public abstract void flush() throws IOException;
+
+ public abstract boolean isstdfile();
+
+ public abstract void close() throws IOException;
+
+ public abstract boolean isclosed();
- abstract
- protected class File extends LuaValue{
- abstract public void write( LuaString string ) throws IOException;
- abstract public void flush() throws IOException;
- abstract public boolean isstdfile();
- abstract public void close() throws IOException;
- abstract public boolean isclosed();
// returns new position
- abstract public int seek(String option, int bytecount) throws IOException;
- abstract public void setvbuf(String mode, int size);
+ public abstract int seek(String option, int bytecount) throws IOException;
+
+ public abstract void setvbuf(String mode, int size);
+
// get length remaining to read
- abstract public int remaining() throws IOException;
+ public abstract int remaining() throws IOException;
+
// peek ahead one character
- abstract public int peek() throws IOException, EOFException;
+ public abstract int peek() throws IOException, EOFException;
+
// return char if read, -1 if eof, throw IOException on other exception
- abstract public int read() throws IOException, EOFException;
+ public abstract int read() throws IOException, EOFException;
+
// return number of bytes read if positive, false if eof, throw IOException on other exception
- abstract public int read(byte[] bytes, int offset, int length) throws IOException;
-
+ public abstract int read(byte[] bytes, int offset, int length) throws IOException;
+
public boolean eof() throws IOException {
try {
return peek() < 0;
- } catch (EOFException e) { return true; }
+ } catch (EOFException e) {
+ return true;
+ }
}
-
+
// delegate method access to file methods table
- public LuaValue get( LuaValue key ) {
+ @Override
+ public LuaValue get(LuaValue key) {
return filemethods.get(key);
}
// essentially a userdata instance
+ @Override
public int type() {
return LuaValue.TUSERDATA;
}
+
+ @Override
public String typename() {
return "userdata";
}
-
+
// displays as "file" type
+ @Override
public String tojstring() {
return "file: " + Integer.toHexString(hashCode());
}
-
+
+ @Override
public void finalize() {
if (!isclosed()) {
try {
close();
- } catch (IOException ignore) {}
+ } catch (IOException ignore) {
+ }
}
}
}
/** Enumerated value representing stdin */
- protected static final int FTYPE_STDIN = 0;
+ protected static final int FTYPE_STDIN = 0;
/** Enumerated value representing stdout */
protected static final int FTYPE_STDOUT = 1;
/** Enumerated value representing stderr */
protected static final int FTYPE_STDERR = 2;
/** Enumerated value representing a file type for a named file */
- protected static final int FTYPE_NAMED = 3;
+ protected static final int FTYPE_NAMED = 3;
/**
* Wrap the standard input.
+ *
* @return File
* @throws IOException
*/
@@ -146,32 +177,37 @@ public class IoLib extends TwoArgFunction {
/**
* Wrap the standard output.
+ *
* @return File
* @throws IOException
*/
abstract protected File wrapStdout() throws IOException;
-
+
/**
* Wrap the standard error output.
+ *
* @return File
* @throws IOException
*/
abstract protected File wrapStderr() throws IOException;
-
+
/**
* Open a file in a particular mode.
+ *
* @param filename
- * @param readMode true if opening in read mode
+ * @param readMode true if opening in read mode
* @param appendMode true if opening in append mode
* @param updateMode true if opening in update mode
* @param binaryMode true if opening in binary mode
* @return File object if successful
* @throws IOException if could not be opened
*/
- abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException;
+ abstract protected File openFile(String filename, boolean readMode, boolean appendMode, boolean updateMode,
+ boolean binaryMode) throws IOException;
/**
* Open a temporary file.
+ *
* @return File object if successful
* @throws IOException if could not be opened
*/
@@ -179,6 +215,7 @@ public class IoLib extends TwoArgFunction {
/**
* Start a new process and return a file for input or output
+ *
* @param prog the program to execute
* @param mode "r" to read, "w" to write
* @return File to read to or write from
@@ -195,152 +232,158 @@ public class IoLib extends TwoArgFunction {
private static final LuaValue STDERR = valueOf("stderr");
private static final LuaValue FILE = valueOf("file");
private static final LuaValue CLOSED_FILE = valueOf("closed file");
-
- private static final int IO_CLOSE = 0;
- private static final int IO_FLUSH = 1;
- private static final int IO_INPUT = 2;
- private static final int IO_LINES = 3;
- private static final int IO_OPEN = 4;
- private static final int IO_OUTPUT = 5;
- private static final int IO_POPEN = 6;
- private static final int IO_READ = 7;
- private static final int IO_TMPFILE = 8;
- private static final int IO_TYPE = 9;
- private static final int IO_WRITE = 10;
- private static final int FILE_CLOSE = 11;
- private static final int FILE_FLUSH = 12;
- private static final int FILE_LINES = 13;
- private static final int FILE_READ = 14;
- private static final int FILE_SEEK = 15;
- private static final int FILE_SETVBUF = 16;
- private static final int FILE_WRITE = 17;
-
- private static final int IO_INDEX = 18;
- private static final int LINES_ITER = 19;
+ private static final int IO_CLOSE = 0;
+ private static final int IO_FLUSH = 1;
+ private static final int IO_INPUT = 2;
+ private static final int IO_LINES = 3;
+ private static final int IO_OPEN = 4;
+ private static final int IO_OUTPUT = 5;
+ private static final int IO_POPEN = 6;
+ private static final int IO_READ = 7;
+ private static final int IO_TMPFILE = 8;
+ private static final int IO_TYPE = 9;
+ private static final int IO_WRITE = 10;
- public static final String[] IO_NAMES = {
- "close",
- "flush",
- "input",
- "lines",
- "open",
- "output",
- "popen",
- "read",
- "tmpfile",
- "type",
- "write",
- };
-
- public static final String[] FILE_NAMES = {
- "close",
- "flush",
- "lines",
- "read",
- "seek",
- "setvbuf",
- "write",
- };
+ private static final int FILE_CLOSE = 11;
+ private static final int FILE_FLUSH = 12;
+ private static final int FILE_LINES = 13;
+ private static final int FILE_READ = 14;
+ private static final int FILE_SEEK = 15;
+ private static final int FILE_SETVBUF = 16;
+ private static final int FILE_WRITE = 17;
+
+ private static final int IO_INDEX = 18;
+ private static final int LINES_ITER = 19;
+
+ public static final String[] IO_NAMES = { "close", "flush", "input", "lines", "open", "output", "popen", "read",
+ "tmpfile", "type", "write", };
+
+ public static final String[] FILE_NAMES = { "close", "flush", "lines", "read", "seek", "setvbuf", "write", };
LuaTable filemethods;
-
+
protected Globals globals;
-
+
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
globals = env.checkglobals();
-
+
// io lib functions
LuaTable t = new LuaTable();
- bind(t, IoLibV.class, IO_NAMES );
-
+ bind(t, IoLibV.class, IO_NAMES);
+
// create file methods table
filemethods = new LuaTable();
- bind(filemethods, IoLibV.class, FILE_NAMES, FILE_CLOSE );
+ bind(filemethods, IoLibV.class, FILE_NAMES, FILE_CLOSE);
// set up file metatable
LuaTable mt = new LuaTable();
- bind(mt, IoLibV.class, new String[] { "__index" }, IO_INDEX );
- t.setmetatable( mt );
-
+ bind(mt, IoLibV.class, new String[] { "__index" }, IO_INDEX);
+ t.setmetatable(mt);
+
// all functions link to library instance
- setLibInstance( t );
- setLibInstance( filemethods );
- setLibInstance( mt );
-
+ setLibInstance(t);
+ setLibInstance(filemethods);
+ setLibInstance(mt);
+
// return the table
env.set("io", t);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("io", t);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("io", t);
return t;
}
private void setLibInstance(LuaTable t) {
LuaValue[] k = t.keys();
- for ( int i=0, n=k.length; i bool
public Varargs _io_flush() throws IOException {
checkopen(output());
@@ -362,31 +405,28 @@ public class IoLib extends TwoArgFunction {
// io.input([file]) -> file
public Varargs _io_input(LuaValue file) {
- infile = file.isnil()? input():
- file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(),"r"):
- checkfile(file);
+ infile = file.isnil()? input()
+ : file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(), "r"): checkfile(file);
return infile;
}
// io.output(filename) -> file
public Varargs _io_output(LuaValue filename) {
- outfile = filename.isnil()? output():
- filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(),"w"):
- checkfile(filename);
+ outfile = filename.isnil()? output()
+ : filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(), "w"): checkfile(filename);
return outfile;
}
// io.type(obj) -> "file" | "closed file" | nil
public Varargs _io_type(LuaValue obj) {
File f = optfile(obj);
- return f!=null?
- f.isclosed()? CLOSED_FILE: FILE:
- NIL;
+ return f != null? f.isclosed()? CLOSED_FILE: FILE: NIL;
}
// io.popen(prog, [mode]) -> file
public Varargs _io_popen(String prog, String mode) throws IOException {
- if (!"r".equals(mode) && !"w".equals(mode)) argerror(2, "invalid value: '" + mode + "'; must be one of 'r' or 'w'");
+ if (!"r".equals(mode) && !"w".equals(mode))
+ argerror(2, "invalid value: '" + mode + "'; must be one of 'r' or 'w'");
return openProgram(prog, mode);
}
@@ -398,7 +438,7 @@ public class IoLib extends TwoArgFunction {
// io.lines(filename, ...) -> iterator
public Varargs _io_lines(Varargs args) {
String filename = args.optjstring(1, null);
- File infile = filename==null? input(): ioopenfile(FTYPE_NAMED, filename,"r");
+ File infile = filename == null? input(): ioopenfile(FTYPE_NAMED, filename, "r");
checkopen(infile);
return lines(infile, filename != null, args.subargs(2));
}
@@ -406,13 +446,13 @@ public class IoLib extends TwoArgFunction {
// io.read(...) -> (...)
public Varargs _io_read(Varargs args) throws IOException {
checkopen(input());
- return ioread(infile,args);
+ return ioread(infile, args);
}
// io.write(...) -> void
public Varargs _io_write(Varargs args) throws IOException {
checkopen(output());
- return iowrite(outfile,args);
+ return iowrite(outfile, args);
}
// file:close() -> void
@@ -434,7 +474,7 @@ public class IoLib extends TwoArgFunction {
} else {
argerror(1, "invalid value: '" + mode + "'; must be one of 'no', 'full' or 'line'");
}
- checkfile(file).setvbuf(mode,size);
+ checkfile(file).setvbuf(mode, size);
return LuaValue.TRUE;
}
@@ -445,7 +485,7 @@ public class IoLib extends TwoArgFunction {
// file:read(...) -> (...)
public Varargs _file_read(LuaValue file, Varargs subargs) throws IOException {
- return ioread(checkfile(file),subargs);
+ return ioread(checkfile(file), subargs);
}
// file:seek([whence][,offset]) -> pos | nil,error
@@ -456,50 +496,51 @@ public class IoLib extends TwoArgFunction {
} else {
argerror(1, "invalid value: '" + whence + "'; must be one of 'set', 'cur' or 'end'");
}
- return valueOf( checkfile(file).seek(whence,offset) );
+ return valueOf(checkfile(file).seek(whence, offset));
}
// file:write(...) -> void
public Varargs _file_write(LuaValue file, Varargs subargs) throws IOException {
- return iowrite(checkfile(file),subargs);
+ return iowrite(checkfile(file), subargs);
}
// __index, returns a field
public Varargs _io_index(LuaValue v) {
- return v.equals(STDOUT)?output():
- v.equals(STDIN)? input():
- v.equals(STDERR)? errput(): NIL;
+ return v.equals(STDOUT)? output(): v.equals(STDIN)? input(): v.equals(STDERR)? errput(): NIL;
}
// lines iterator(s,var) -> var'
public Varargs _lines_iter(LuaValue file, boolean toclose, Varargs args) throws IOException {
File f = optfile(file);
- if ( f == null ) argerror(1, "not a file: " + file);
- if ( f.isclosed() ) error("file is already closed");
+ if (f == null)
+ argerror(1, "not a file: " + file);
+ if (f.isclosed())
+ error("file is already closed");
Varargs ret = ioread(f, args);
- if (toclose && ret.isnil(1) && f.eof()) f.close();
+ if (toclose && ret.isnil(1) && f.eof())
+ f.close();
return ret;
}
private File output() {
- return outfile!=null? outfile: (outfile=ioopenfile(FTYPE_STDOUT,"-","w"));
+ return outfile != null? outfile: (outfile = ioopenfile(FTYPE_STDOUT, "-", "w"));
}
-
+
private File errput() {
- return errfile!=null? errfile: (errfile=ioopenfile(FTYPE_STDERR,"-","w"));
+ return errfile != null? errfile: (errfile = ioopenfile(FTYPE_STDERR, "-", "w"));
}
-
+
private File ioopenfile(int filetype, String filename, String mode) {
try {
return rawopenfile(filetype, filename, mode);
- } catch ( Exception e ) {
- error("io error: "+e.getMessage());
+ } catch (Exception e) {
+ error("io error: " + e.getMessage());
return null;
}
}
private static Varargs ioclose(File f) throws IOException {
- if ( f.isstdfile() )
+ if (f.isstdfile())
return errorresult("cannot close standard file");
else {
f.close();
@@ -513,71 +554,80 @@ public class IoLib extends TwoArgFunction {
static Varargs errorresult(Exception ioe) {
String s = ioe.getMessage();
- return errorresult("io error: "+(s!=null? s: ioe.toString()));
+ return errorresult("io error: " + (s != null? s: ioe.toString()));
}
-
+
private static Varargs errorresult(String errortext) {
return varargsOf(NIL, valueOf(errortext));
}
private Varargs lines(final File f, boolean toclose, Varargs args) {
try {
- return new IoLibV(f,"lnext",LINES_ITER,this,toclose,args);
- } catch ( Exception e ) {
- return error("lines: "+e);
+ return new IoLibV(f, "lnext", LINES_ITER, this, toclose, args);
+ } catch (Exception e) {
+ return error("lines: " + e);
}
}
private static Varargs iowrite(File f, Varargs args) throws IOException {
- for ( int i=1, n=args.narg(); i<=n; i++ )
- f.write( args.checkstring(i) );
+ for (int i = 1, n = args.narg(); i <= n; i++)
+ f.write(args.checkstring(i));
return f;
}
private Varargs ioread(File f, Varargs args) throws IOException {
- int i,n=args.narg();
- if (n == 0) return freadline(f,false);
+ int i, n = args.narg();
+ if (n == 0)
+ return freadline(f, false);
LuaValue[] v = new LuaValue[n];
- LuaValue ai,vi;
+ LuaValue ai, vi;
LuaString fmt;
- for ( i=0; i= 2 && fmt.m_bytes[fmt.m_offset] == '*' ) {
- switch ( fmt.m_bytes[fmt.m_offset+1] ) {
- case 'n': vi = freadnumber(f); break item;
- case 'l': vi = freadline(f,false); break item;
- case 'L': vi = freadline(f,true); break item;
- case 'a': vi = freadall(f); break item;
- }
+ for (i = 0; i < n;) {
+ item: switch ((ai = args.arg(i+1)).type()) {
+ case LuaValue.TNUMBER:
+ vi = freadbytes(f, ai.toint());
+ break item;
+ case LuaValue.TSTRING:
+ fmt = ai.checkstring();
+ if (fmt.m_length >= 2 && fmt.m_bytes[fmt.m_offset] == '*') {
+ switch (fmt.m_bytes[fmt.m_offset+1]) {
+ case 'n':
+ vi = freadnumber(f);
+ break item;
+ case 'l':
+ vi = freadline(f, false);
+ break item;
+ case 'L':
+ vi = freadline(f, true);
+ break item;
+ case 'a':
+ vi = freadall(f);
+ break item;
}
- default:
- return argerror( i+1, "(invalid format)" );
+ }
+ default:
+ return argerror(i+1, "(invalid format)");
}
- if ( (v[i++] = vi).isnil() )
+ if ((v[i++] = vi).isnil())
break;
}
- return i==0? NIL: varargsOf(v, 0, i);
+ return i == 0? NIL: varargsOf(v, 0, i);
}
private static File checkfile(LuaValue val) {
File f = optfile(val);
- if ( f == null )
- argerror(1,"file");
- checkopen( f );
+ if (f == null)
+ argerror(1, "file");
+ checkopen(f);
return f;
}
-
+
private static File optfile(LuaValue val) {
return (val instanceof File)? (File) val: null;
}
-
+
private static File checkopen(File file) {
- if ( file.isclosed() )
+ if (file.isclosed())
error("attempt to use a closed file");
return file;
}
@@ -586,99 +636,113 @@ public class IoLib extends TwoArgFunction {
int len = mode.length();
for (int i = 0; i < len; i++) { // [rwa][+]?b*
char ch = mode.charAt(i);
- if (i == 0 && "rwa".indexOf(ch) >= 0) continue;
- if (i == 1 && ch == '+') continue;
- if (i >= 1 && ch == 'b') continue;
+ if ((i == 0 && "rwa".indexOf(ch) >= 0) || (i == 1 && ch == '+'))
+ continue;
+ if (i >= 1 && ch == 'b')
+ continue;
len = -1;
break;
}
- if (len <= 0) argerror(2, "invalid mode: '" + mode + "'");
-
+ if (len <= 0)
+ argerror(2, "invalid mode: '" + mode + "'");
+
switch (filetype) {
- case FTYPE_STDIN: return wrapStdin();
- case FTYPE_STDOUT: return wrapStdout();
- case FTYPE_STDERR: return wrapStderr();
+ case FTYPE_STDIN:
+ return wrapStdin();
+ case FTYPE_STDOUT:
+ return wrapStdout();
+ case FTYPE_STDERR:
+ return wrapStderr();
}
boolean isreadmode = mode.startsWith("r");
boolean isappend = mode.startsWith("a");
boolean isupdate = mode.indexOf('+') > 0;
boolean isbinary = mode.endsWith("b");
- return openFile( filename, isreadmode, isappend, isupdate, isbinary );
+ return openFile(filename, isreadmode, isappend, isupdate, isbinary);
}
-
// ------------- file reading utilitied ------------------
-
+
public static LuaValue freadbytes(File f, int count) throws IOException {
- if (count == 0) return f.eof() ? NIL : EMPTYSTRING;
+ if (count == 0)
+ return f.eof()? NIL: EMPTYSTRING;
byte[] b = new byte[count];
int r;
- if ( ( r = f.read(b,0,b.length) ) < 0 )
+ if ((r = f.read(b, 0, b.length)) < 0)
return NIL;
return LuaString.valueUsing(b, 0, r);
}
- public static LuaValue freaduntil(File f,boolean lineonly,boolean withend) throws IOException {
+
+ public static LuaValue freaduntil(File f, boolean lineonly, boolean withend) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
try {
- if ( lineonly ) {
+ if (lineonly) {
loop: while ( (c = f.read()) >= 0 ) {
- switch ( c ) {
- case '\r': if (withend) baos.write(c); break;
- case '\n': if (withend) baos.write(c); break loop;
- default: baos.write(c); break;
+ switch (c) {
+ case '\r':
+ if (withend)
+ baos.write(c);
+ break;
+ case '\n':
+ if (withend)
+ baos.write(c);
+ break loop;
+ default:
+ baos.write(c);
+ break;
}
}
} else {
while ( (c = f.read()) >= 0 )
baos.write(c);
}
- } catch ( EOFException e ) {
+ } catch (EOFException e) {
c = -1;
}
- return ( c < 0 && baos.size() == 0 )?
- (LuaValue) NIL:
- (LuaValue) LuaString.valueUsing(baos.toByteArray());
+ return (c < 0 && baos.size() == 0)? (LuaValue) NIL: (LuaValue) LuaString.valueUsing(baos.toByteArray());
}
- public static LuaValue freadline(File f,boolean withend) throws IOException {
- return freaduntil(f,true,withend);
+
+ public static LuaValue freadline(File f, boolean withend) throws IOException {
+ return freaduntil(f, true, withend);
}
+
public static LuaValue freadall(File f) throws IOException {
int n = f.remaining();
- if ( n >= 0 ) {
- return n == 0 ? EMPTYSTRING : freadbytes(f, n);
+ if (n >= 0) {
+ return n == 0? EMPTYSTRING: freadbytes(f, n);
} else {
- return freaduntil(f,false,false);
+ return freaduntil(f, false, false);
}
}
+
public static LuaValue freadnumber(File f) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- freadchars(f," \t\r\n",null);
- freadchars(f,"-+",baos);
+ freadchars(f, " \t\r\n", null);
+ freadchars(f, "-+", baos);
//freadchars(f,"0",baos);
//freadchars(f,"xX",baos);
- freadchars(f,"0123456789",baos);
- freadchars(f,".",baos);
- freadchars(f,"0123456789",baos);
+ freadchars(f, "0123456789", baos);
+ freadchars(f, ".", baos);
+ freadchars(f, "0123456789", baos);
//freadchars(f,"eEfFgG",baos);
// freadchars(f,"+-",baos);
//freadchars(f,"0123456789",baos);
String s = baos.toString();
- return s.length()>0? valueOf( Double.parseDouble(s) ): NIL;
+ return s.length() > 0? valueOf(Double.parseDouble(s)): NIL;
}
+
private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException {
int c;
while ( true ) {
c = f.peek();
- if ( chars.indexOf(c) < 0 ) {
+ if (chars.indexOf(c) < 0) {
return;
}
f.read();
- if ( baos != null )
- baos.write( c );
+ if (baos != null)
+ baos.write(c);
}
}
-
-
-
+
}
diff --git a/src/core/org/luaj/vm2/lib/LibFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java
similarity index 56%
rename from src/core/org/luaj/vm2/lib/LibFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java
index eba56072..5bec4601 100644
--- a/src/core/org/luaj/vm2/lib/LibFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -29,20 +29,20 @@ import org.luaj.vm2.Varargs;
/**
* Subclass of {@link LuaFunction} common to Java functions exposed to lua.
*
- * To provide for common implementations in JME and JSE,
- * library functions are typically grouped on one or more library classes
- * and an opcode per library function is defined and used to key the switch
- * to the correct function within the library.
+ * To provide for common implementations in JME and JSE, library functions are
+ * typically grouped on one or more library classes and an opcode per library
+ * function is defined and used to key the switch to the correct function within
+ * the library.
*
- * Since lua functions can be called with too few or too many arguments,
- * and there are overloaded {@link LuaValue#call()} functions with varying
- * number of arguments, a Java function exposed in lua needs to handle the
- * argument fixup when a function is called with a number of arguments
- * differs from that expected.
+ * Since lua functions can be called with too few or too many arguments, and
+ * there are overloaded {@link LuaValue#call()} functions with varying number of
+ * arguments, a Java function exposed in lua needs to handle the argument fixup
+ * when a function is called with a number of arguments differs from that
+ * expected.
*
- * To simplify the creation of library functions,
- * there are 5 direct subclasses to handle common cases based on number of
- * argument values and number of return return values.
+ * To simplify the creation of library functions, there are 5 direct subclasses
+ * to handle common cases based on number of argument values and number of
+ * return return values.
*
- * To be a Java library that can be loaded via {@code require}, it should have
- * a public constructor that returns a {@link LuaValue} that, when executed,
+ * To be a Java library that can be loaded via {@code require}, it should have a
+ * public constructor that returns a {@link LuaValue} that, when executed,
* initializes the library.
*
* For example, the following code will implement a library called "hyperbolic"
* with two functions, "sinh", and "cosh":
-
- * The default constructor is used to instantiate the library
- * in response to {@code require 'hyperbolic'} statement,
- * provided it is on Java"s class path.
- * This instance is then invoked with 2 arguments: the name supplied to require(),
- * and the environment for this function. The library may ignore these, or use
- * them to leave side effects in the global environment, for example.
- * In the previous example, two functions are created, 'sinh', and 'cosh', and placed
- * into a global table called 'hyperbolic' using the supplied 'env' argument.
+ *}
+ *
+ *
+ * The default constructor is used to instantiate the library in response to
+ * {@code require 'hyperbolic'} statement, provided it is on Java"s class
+ * path. This instance is then invoked with 2 arguments: the name supplied to
+ * require(), and the environment for this function. The library may ignore
+ * these, or use them to leave side effects in the global environment, for
+ * example. In the previous example, two functions are created, 'sinh', and
+ * 'cosh', and placed into a global table called 'hyperbolic' using the supplied
+ * 'env' argument.
*
* To test it, a script such as this can be used:
- *
{@code
+ *
+ *
+ * {@code
* local t = require('hyperbolic')
* print( 't', t )
* print( 'hyperbolic', hyperbolic )
@@ -105,118 +111,153 @@ import org.luaj.vm2.Varargs;
* end
* print( 'sinh(.5)', hyperbolic.sinh(.5) )
* print( 'cosh(.5)', hyperbolic.cosh(.5) )
- * }
- * See the source code in any of the library functions
- * such as {@link BaseLib} or {@link TableLib} for other examples.
+ * See the source code in any of the library functions such as {@link BaseLib}
+ * or {@link TableLib} for other examples.
*/
abstract public class LibFunction extends LuaFunction {
-
- /** User-defined opcode to differentiate between instances of the library function class.
+
+ /**
+ * User-defined opcode to differentiate between instances of the library
+ * function class.
*
- * Subclass will typicall switch on this value to provide the specific behavior for each function.
+ * Subclass will typicall switch on this value to provide the specific
+ * behavior for each function.
*/
protected int opcode;
-
- /** The common name for this function, useful for debugging.
+
+ /**
+ * The common name for this function, useful for debugging.
*
* Binding functions initialize this to the name to which it is bound.
*/
protected String name;
-
+
/** Default constructor for use by subclasses */
protected LibFunction() {
}
-
+
+ @Override
public String tojstring() {
- return name != null ? "function: " + name : super.tojstring();
+ return name != null? "function: " + name: super.tojstring();
}
-
+
/**
* Bind a set of library functions.
*
- * An array of names is provided, and the first name is bound
- * with opcode = 0, second with 1, etc.
- * @param env The environment to apply to each bound function
+ * An array of names is provided, and the first name is bound with opcode =
+ * 0, second with 1, etc.
+ *
+ * @param env The environment to apply to each bound function
* @param factory the Class to instantiate for each bound function
- * @param names array of String names, one for each function.
+ * @param names array of String names, one for each function.
* @see #bind(LuaValue, Class, String[], int)
*/
- protected void bind(LuaValue env, Class factory, String[] names ) {
- bind( env, factory, names, 0 );
+ protected void bind(LuaValue env, Class factory, String[] names) {
+ bind(env, factory, names, 0);
}
-
+
/**
* Bind a set of library functions, with an offset
*
- * An array of names is provided, and the first name is bound
- * with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc.
- * @param env The environment to apply to each bound function
- * @param factory the Class to instantiate for each bound function
- * @param names array of String names, one for each function.
+ * An array of names is provided, and the first name is bound with opcode =
+ * {@code firstopcode}, second with {@code firstopcode+1}, etc.
+ *
+ * @param env The environment to apply to each bound function
+ * @param factory the Class to instantiate for each bound function
+ * @param names array of String names, one for each function.
* @param firstopcode the first opcode to use
* @see #bind(LuaValue, Class, String[])
*/
- protected void bind(LuaValue env, Class factory, String[] names, int firstopcode ) {
+ protected void bind(LuaValue env, Class factory, String[] names, int firstopcode) {
try {
- for ( int i=0, n=names.length; i
- * It contains only the math library support that is possible on JME.
- * For a more complete implementation based on math functions specific to JSE
- * use {@link org.luaj.vm2.lib.jse.JseMathLib}.
- * In Particular the following math functions are not implemented by this library:
+ * It contains only the math library support that is possible on JME. For a more
+ * complete implementation based on math functions specific to JSE use
+ * {@link org.luaj.vm2.lib.jse.JseMathLib}. In Particular the following math
+ * functions are not implemented by this library:
*
* The implementations of {@code exp()} and {@code pow()} are constructed by
- * hand for JME, so will be slower and less accurate than when executed on the JSE platform.
+ * hand for JME, so will be slower and less accurate than when executed on the
+ * JSE platform.
*
* Typically, this library is included as part of a call to either
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
- * When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example,
- * the subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will
- * be included, which also includes this base functionality.
+ *
+ *
+ *
+ * When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example, the
+ * subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will be included, which also
+ * includes this base functionality.
*
- * To instantiate and use it directly,
- * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
- *
- * Doing so will ensure the library is properly initialized
- * and loaded into the globals table.
+ * To instantiate and use it directly, link it into your globals table via
+ * {@link LuaValue#load(LuaValue)} using code such as:
+ *
+ *
+ *
+ * Doing so will ensure the library is properly initialized and loaded into the
+ * globals table.
*
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see org.luaj.vm2.lib.jse.JseMathLib
- * @see Lua 5.2 Math Lib Reference
+ * @see Lua 5.2 Math Lib
+ * Reference
*/
public class MathLib extends TwoArgFunction {
- /** Pointer to the latest MathLib instance, used only to dispatch
- * math.exp to tha correct platform math library.
+ /**
+ * Pointer to the latest MathLib instance, used only to dispatch math.exp to
+ * tha correct platform math library.
*/
public static MathLib MATHLIB = null;
- /** Construct a MathLib, which can be initialized by calling it with a
+ /**
+ * Construct a MathLib, which can be initialized by calling it with a
* modname string, and a global environment table as arguments using
- * {@link #call(LuaValue, LuaValue)}. */
+ * {@link #call(LuaValue, LuaValue)}.
+ */
public MathLib() {
MATHLIB = this;
}
- /** Perform one-time initialization on the library by creating a table
- * containing the library functions, adding that table to the supplied environment,
- * adding the table to package.loaded, and returning table as the return value.
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, typically a Globals instance.
+ * @param env the environment to load into, typically a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
- LuaTable math = new LuaTable(0,30);
+ LuaTable math = new LuaTable(0, 30);
math.set("abs", new abs());
math.set("ceil", new ceil());
math.set("cos", new cos());
@@ -110,12 +132,12 @@ public class MathLib extends TwoArgFunction {
math.set("floor", new floor());
math.set("fmod", new fmod());
math.set("frexp", new frexp());
- math.set("huge", LuaDouble.POSINF );
+ math.set("huge", LuaDouble.POSINF);
math.set("ldexp", new ldexp());
math.set("max", new max());
math.set("min", new min());
math.set("modf", new modf());
- math.set("pi", Math.PI );
+ math.set("pi", Math.PI);
math.set("pow", new pow());
random r;
math.set("random", r = new random());
@@ -125,178 +147,246 @@ public class MathLib extends TwoArgFunction {
math.set("sqrt", new sqrt());
math.set("tan", new tan());
env.set("math", math);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("math", math);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("math", math);
return math;
}
-
+
abstract protected static class UnaryOp extends OneArgFunction {
+ @Override
public LuaValue call(LuaValue arg) {
return valueOf(call(arg.checkdouble()));
}
+
abstract protected double call(double d);
}
abstract protected static class BinaryOp extends TwoArgFunction {
+ @Override
public LuaValue call(LuaValue x, LuaValue y) {
return valueOf(call(x.checkdouble(), y.checkdouble()));
}
+
abstract protected double call(double x, double y);
}
- static final class abs extends UnaryOp { protected double call(double d) { return Math.abs(d); } }
- static final class ceil extends UnaryOp { protected double call(double d) { return Math.ceil(d); } }
- static final class cos extends UnaryOp { protected double call(double d) { return Math.cos(d); } }
- static final class deg extends UnaryOp { protected double call(double d) { return Math.toDegrees(d); } }
- static final class floor extends UnaryOp { protected double call(double d) { return Math.floor(d); } }
- static final class rad extends UnaryOp { protected double call(double d) { return Math.toRadians(d); } }
- static final class sin extends UnaryOp { protected double call(double d) { return Math.sin(d); } }
- static final class sqrt extends UnaryOp { protected double call(double d) { return Math.sqrt(d); } }
- static final class tan extends UnaryOp { protected double call(double d) { return Math.tan(d); } }
+ static final class abs extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.abs(d); }
+ }
+
+ static final class ceil extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.ceil(d); }
+ }
+
+ static final class cos extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.cos(d); }
+ }
+
+ static final class deg extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.toDegrees(d); }
+ }
+
+ static final class floor extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.floor(d); }
+ }
+
+ static final class rad extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.toRadians(d); }
+ }
+
+ static final class sin extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.sin(d); }
+ }
+
+ static final class sqrt extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.sqrt(d); }
+ }
+
+ static final class tan extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.tan(d); }
+ }
static final class exp extends UnaryOp {
final MathLib mathlib;
+
exp(MathLib mathlib) {
this.mathlib = mathlib;
}
+
+ @Override
protected double call(double d) {
- return mathlib.dpow_lib(Math.E,d);
+ return mathlib.dpow_lib(Math.E, d);
}
}
-
+
static final class fmod extends TwoArgFunction {
+ @Override
public LuaValue call(LuaValue xv, LuaValue yv) {
+ if (yv.checkdouble() == 0.0d)
+ return LuaDouble.NAN;
if (xv.islong() && yv.islong()) {
- return valueOf(xv.tolong() % yv.tolong());
+ return valueOf(xv.tolong()%yv.tolong());
}
- return valueOf(xv.checkdouble() % yv.checkdouble());
+ return valueOf(xv.checkdouble()%yv.checkdouble());
}
}
+
static final class ldexp extends BinaryOp {
+ @Override
protected double call(double x, double y) {
// This is the behavior on os-x, windows differs in rounding behavior.
- return x * Double.longBitsToDouble((((long) y) + 1023) << 52);
+ return x*Double.longBitsToDouble((long) y+1023<<52);
}
}
+
static final class pow extends BinaryOp {
+ @Override
protected double call(double x, double y) {
return MathLib.dpow_default(x, y);
}
}
static class frexp extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
double x = args.checkdouble(1);
- if ( x == 0 ) return varargsOf(ZERO,ZERO);
- long bits = Double.doubleToLongBits( x );
- double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52)));
- double e = (((int) (bits >> 52)) & 0x7ff) - 1022;
- return varargsOf( valueOf(m), valueOf(e) );
+ if (x == 0)
+ return varargsOf(ZERO, ZERO);
+ long bits = Double.doubleToLongBits(x);
+ double m = ((bits & ~(-1L<<52))+(1L<<52))*(bits >= 0? .5/(1L<<52): -.5/(1L<<52));
+ double e = ((int) (bits>>52) & 0x7ff)-1022;
+ return varargsOf(valueOf(m), valueOf(e));
}
}
static class max extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- LuaValue m = args.checkvalue(1);
- for ( int i=2,n=args.narg(); i<=n; ++i ) {
- LuaValue v = args.checkvalue(i);
- if (m.lt_b(v)) m = v;
+ LuaValue m = args.checknumber(1);
+ for (int i = 2, n = args.narg(); i <= n; ++i) {
+ LuaValue v = args.checknumber(i);
+ if (m.lt_b(v))
+ m = v;
}
return m;
}
}
-
+
static class min extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- LuaValue m = args.checkvalue(1);
- for ( int i=2,n=args.narg(); i<=n; ++i ) {
- LuaValue v = args.checkvalue(i);
- if (v.lt_b(m)) m = v;
+ LuaValue m = args.checknumber(1);
+ for (int i = 2, n = args.narg(); i <= n; ++i) {
+ LuaValue v = args.checknumber(i);
+ if (v.lt_b(m))
+ m = v;
}
return m;
}
}
-
+
static class modf extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaValue n = args.arg1();
/* number is its own integer part, no fractional part */
- if (n.islong()) return varargsOf(n, valueOf(0.0));
+ if (n.islong())
+ return varargsOf(n.tonumber(), valueOf(0.0));
double x = n.checkdouble();
/* integer part (rounds toward zero) */
- double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
+ double intPart = x > 0? Math.floor(x): Math.ceil(x);
/* fractional part (test needed for inf/-inf) */
- double fracPart = x == intPart ? 0.0 : x - intPart;
- return varargsOf( valueOf(intPart), valueOf(fracPart) );
+ double fracPart = x == intPart? 0.0: x-intPart;
+ return varargsOf(valueOf(intPart), valueOf(fracPart));
}
}
-
+
static class random extends LibFunction {
Random random = new Random();
+
+ @Override
public LuaValue call() {
- return valueOf( random.nextDouble() );
+ return valueOf(random.nextDouble());
}
+
+ @Override
public LuaValue call(LuaValue a) {
int m = a.checkint();
- if (m<1) argerror(1, "interval is empty");
- return valueOf( 1 + random.nextInt(m) );
+ if (m < 1)
+ argerror(1, "interval is empty");
+ return valueOf(1+random.nextInt(m));
}
+
+ @Override
public LuaValue call(LuaValue a, LuaValue b) {
int m = a.checkint();
int n = b.checkint();
- if (n 0; whole>>=1, v*=v )
- if ( (whole & 1) != 0 )
+ for (double v = a; whole > 0; whole >>= 1, v *= v)
+ if ((whole & 1) != 0)
p *= v;
- if ( (b -= whole) > 0 ) {
- int frac = (int) (0x10000 * b);
- for ( ; (frac&0xffff)!=0; frac<<=1 ) {
+ if ((b -= whole) > 0) {
+ int frac = (int) (0x10000*b);
+ for (; (frac & 0xffff) != 0; frac <<= 1) {
a = Math.sqrt(a);
- if ( (frac & 0x8000) != 0 )
+ if ((frac & 0x8000) != 0)
p *= a;
}
}
diff --git a/src/core/org/luaj/vm2/lib/OneArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java
similarity index 79%
rename from src/core/org/luaj/vm2/lib/OneArgFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java
index 3db6a321..2a946761 100644
--- a/src/core/org/luaj/vm2/lib/OneArgFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,21 +24,23 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
-/** Abstract base class for Java function implementations that take one argument and
- * return one value.
+/**
+ * Abstract base class for Java function implementations that take one argument
+ * and return one value.
*
- * Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete this class,
- * simplifying development.
- * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,
- * are routed through this method by this class,
+ * Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete
+ * this class, simplifying development. All other uses of {@link #call()},
+ * {@link #invoke(Varargs)},etc, are routed through this method by this class,
* dropping or extending arguments with {@code nil} values as required.
*
- * If more than one argument are required, or no arguments are required,
- * or variable argument or variable return values,
- * then use one of the related function
- * {@link ZeroArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
+ * If more than one argument are required, or no arguments are required, or
+ * variable argument or variable return values, then use one of the related
+ * function {@link ZeroArgFunction}, {@link TwoArgFunction},
+ * {@link ThreeArgFunction}, or {@link VarArgFunction}.
*
- * See {@link LibFunction} for more information on implementation libraries and library functions.
+ * See {@link LibFunction} for more information on implementation libraries and
+ * library functions.
+ *
* @see #call(LuaValue)
* @see LibFunction
* @see ZeroArgFunction
@@ -48,25 +50,30 @@ import org.luaj.vm2.Varargs;
*/
abstract public class OneArgFunction extends LibFunction {
+ @Override
abstract public LuaValue call(LuaValue arg);
-
+
/** Default constructor */
public OneArgFunction() {
}
-
+
+ @Override
public final LuaValue call() {
return call(NIL);
}
+ @Override
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
return call(arg1);
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return call(arg1);
}
+ @Override
public Varargs invoke(Varargs varargs) {
return call(varargs.arg1());
}
-}
+}
diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/OsLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/OsLib.java
new file mode 100644
index 00000000..e87cafed
--- /dev/null
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/OsLib.java
@@ -0,0 +1,522 @@
+/*******************************************************************************
+* Copyright (c) 2009 Luaj.org. 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.vm2.lib;
+
+import java.io.IOException;
+import java.time.format.TextStyle;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.luaj.vm2.Buffer;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaTable;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Varargs;
+
+/**
+ * Subclass of {@link LibFunction} which implements the standard lua {@code os}
+ * library.
+ *
+ * It is a usable base with simplified stub functions for library functions that
+ * cannot be implemented uniformly on Jse and Jme.
+ *
+ * This can be installed as-is on either platform, or extended and refined to be
+ * used in a complete Jse implementation.
+ *
+ * Because the nature of the {@code os} library is to encapsulate os-specific
+ * features, the behavior of these functions varies considerably from their
+ * counterparts in the C platform.
+ *
+ * The following functions have limited implementations of features that are not
+ * supported well on Jme:
+ *
+ *
{@code execute()}
+ *
{@code remove()}
+ *
{@code rename()}
+ *
{@code tmpname()}
+ *
+ *
+ * Typically, this library is included as part of a call to either
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
+ *
+ *
+ *
+ * In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseOsLib}
+ * library will be loaded, which will include the base functionality provided by
+ * this class.
+ *
+ * To instantiate and use it directly, link it into your globals table via
+ * {@link LuaValue#load(LuaValue)} using code such as:
+ *
+ *
+ *
+ * @see LibFunction
+ * @see org.luaj.vm2.lib.jse.JseOsLib
+ * @see org.luaj.vm2.lib.jse.JsePlatform
+ * @see org.luaj.vm2.lib.jme.JmePlatform
+ * @see http://www.lua.org/manual/5.1/manual.html#5.8
+ */
+public class OsLib extends TwoArgFunction {
+ public static final String TMP_PREFIX = ".luaj";
+ public static final String TMP_SUFFIX = "tmp";
+
+ private static final int CLOCK = 0;
+ private static final int DATE = 1;
+ private static final int DIFFTIME = 2;
+ private static final int EXECUTE = 3;
+ private static final int EXIT = 4;
+ private static final int GETENV = 5;
+ private static final int REMOVE = 6;
+ private static final int RENAME = 7;
+ private static final int SETLOCALE = 8;
+ private static final int TIME = 9;
+ private static final int TMPNAME = 10;
+
+ private static final String[] NAMES = { "clock", "date", "difftime", "execute", "exit", "getenv", "remove",
+ "rename", "setlocale", "time", "tmpname", };
+
+ private static final long t0 = System.currentTimeMillis();
+ private static long tmpnames = t0;
+
+ protected Globals globals;
+
+ /**
+ * Create and OsLib instance.
+ */
+ public OsLib() {
+ }
+
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
+ * @param modname the module name supplied if this is loaded via 'require'.
+ * @param env the environment to load into, typically a Globals
+ * instance.
+ */
+ @Override
+ public LuaValue call(LuaValue modname, LuaValue env) {
+ globals = env.checkglobals();
+ LuaTable os = new LuaTable();
+ for (int i = 0; i < NAMES.length; ++i)
+ os.set(NAMES[i], new OsLibFunc(i, NAMES[i]));
+ env.set("os", os);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("os", os);
+ return os;
+ }
+
+ class OsLibFunc extends VarArgFunction {
+ public OsLibFunc(int opcode, String name) {
+ this.opcode = opcode;
+ this.name = name;
+ }
+
+ @Override
+ public Varargs invoke(Varargs args) {
+ try {
+ switch (opcode) {
+ case CLOCK:
+ return valueOf(clock());
+ case DATE: {
+ String s = args.optjstring(1, "%c");
+ long t = args.isnumber(2)? args.tolong(2): time(null);
+ if (s.equals("*t")) {
+ Calendar d = Calendar.getInstance();
+ d.setTime(new Date(t*1000));
+ LuaTable tbl = LuaValue.tableOf();
+ tbl.set("year", LuaValue.valueOf(d.get(Calendar.YEAR)));
+ tbl.set("month", LuaValue.valueOf(d.get(Calendar.MONTH)+1));
+ tbl.set("day", LuaValue.valueOf(d.get(Calendar.DAY_OF_MONTH)));
+ tbl.set("hour", LuaValue.valueOf(d.get(Calendar.HOUR_OF_DAY)));
+ 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(0x6))); // Day of year
+ tbl.set("isdst", LuaValue.valueOf(isDaylightSavingsTime(d)));
+ return tbl;
+ }
+ return valueOf(date(s, t == -1? time(null): t));
+ }
+ case DIFFTIME:
+ return valueOf(difftime(args.checkdouble(1), args.checkdouble(2)));
+ case EXECUTE:
+ return execute(args.optjstring(1, null));
+ case EXIT:
+ exit(args.optint(1, 0));
+ return NONE;
+ case GETENV: {
+ final String val = getenv(args.checkjstring(1));
+ return val != null? valueOf(val): NIL;
+ }
+ case REMOVE:
+ remove(args.checkjstring(1));
+ return LuaValue.TRUE;
+ case RENAME:
+ rename(args.checkjstring(1), args.checkjstring(2));
+ return LuaValue.TRUE;
+ case SETLOCALE: {
+ String s = setlocale(args.optjstring(1, null), args.optjstring(2, "all"));
+ return s != null? valueOf(s): NIL;
+ }
+ case TIME:
+ return valueOf(time(args.opttable(1, null)));
+ case TMPNAME:
+ return valueOf(tmpname());
+ }
+ return NONE;
+ } catch (IOException e) {
+ return varargsOf(NIL, valueOf(e.getMessage()));
+ }
+ }
+ }
+
+ /**
+ * @return an approximation of the amount in seconds of CPU time used by the
+ * program. For luaj this simple returns the elapsed time since the
+ * OsLib class was loaded.
+ */
+ protected double clock() {
+ return (System.currentTimeMillis()-t0)/1000.;
+ }
+
+ /**
+ * Returns the number of seconds from time t1 to time t2. In POSIX, Windows,
+ * and some other systems, this value is exactly t2-t1.
+ *
+ * @param t2
+ * @param t1
+ * @return diffeence in time values, in seconds
+ */
+ protected double difftime(double t2, double t1) {
+ return t2-t1;
+ }
+
+ /**
+ * If the time argument is present, this is the time to be formatted (see
+ * the os.time function for a description of this value). Otherwise, date
+ * formats the current time.
+ *
+ * Date returns the date as a string, formatted according to the same rules
+ * as ANSII strftime, but without support for %g, %G, or %V.
+ *
+ * When called without arguments, date returns a reasonable date and time
+ * representation that depends on the host system and on the current locale
+ * (that is, os.date() is equivalent to os.date("%c")).
+ *
+ * @param format
+ * @param timeInSec time since epoch, or -1 if not supplied
+ * @return a LString or a LTable containing date and time, formatted
+ * according to the given string format.
+ */
+ private static String date(String format, long timeInSec) {
+ Calendar d = Calendar.getInstance();
+ d.setTime(new Date(timeInSec*1000));
+ if (format.startsWith("!")) {
+ timeInSec -= timeZoneOffset(d);
+ d.setTime(new Date(timeInSec*1000));
+ format = format.substring(1);
+ }
+ byte[] fmt = format.getBytes();
+ final int n = fmt.length;
+
+ Buffer result = new Buffer(n);
+ for (int i = 0; i < n; i++) {
+ byte c = fmt[i];
+ switch (c) {
+ case '\n':
+ result.append("\n");
+ break;
+ case '%':
+ if (++i >= n)
+ break;
+ String conv = Character.toString((char) fmt[i]);
+ if (CONVERTERS.containsKey(conv)) {
+ result.append(CONVERTERS.get(conv).convert(d));
+ } else {
+ LuaValue.argerror(1, "invalid conversion specifier '%" + conv + "'");
+ }
+ break;
+ default:
+ result.append(c);
+ break;
+ }
+ }
+ return result.tojstring();
+ }
+
+ private static final String[] WeekdayNameAbbrev = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+ private static final String[] WeekdayName = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday" };
+ private static final String[] MonthNameAbbrev = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec" };
+ private static final String[] MonthName = { "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December" };
+
+ private static interface DateConversion {
+ public String convert(Calendar d);
+ }
+
+ private static final Map CONVERTERS = new HashMap<>();
+ static {
+ CONVERTERS.put("%", d -> "%");
+ CONVERTERS.put("a", d -> WeekdayNameAbbrev[d.get(Calendar.DAY_OF_WEEK)-1]);
+ CONVERTERS.put("A", d -> WeekdayName[d.get(Calendar.DAY_OF_WEEK)-1]);
+ CONVERTERS.put("b", d -> MonthNameAbbrev[d.get(Calendar.MONTH)]);
+ CONVERTERS.put("B", d -> MonthName[d.get(Calendar.MONTH)]);
+ CONVERTERS.put("c", d -> date("%a %b %e %H:%M:%S %Y", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("C", d -> String.valueOf(d.get(Calendar.YEAR)).substring(0, 2));
+ CONVERTERS.put("d", d -> String.valueOf(100+d.get(Calendar.DAY_OF_MONTH)).substring(1));
+ CONVERTERS.put("D", d -> date("%m/%d/%y", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("e", d -> String.format("%2d", d.get(Calendar.DAY_OF_MONTH)));
+ CONVERTERS.put("F", d -> date("%Y-%m-%d", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("g", d -> String.valueOf(d.get(Calendar.YEAR)).substring(2));
+ CONVERTERS.put("G", d -> String.valueOf(d.get(Calendar.YEAR)));
+ CONVERTERS.put("h", d -> MonthNameAbbrev[d.get(Calendar.MONTH)]);
+ CONVERTERS.put("H", d -> String.valueOf(100+d.get(Calendar.HOUR_OF_DAY)).substring(1));
+ CONVERTERS.put("I", d -> String.valueOf(100+d.get(Calendar.HOUR_OF_DAY)%12).substring(1));
+ // day of year
+ CONVERTERS.put("j", d -> {
+ Calendar y0 = beginningOfYear(d);
+ int dayOfYear = (int) ((d.getTimeInMillis()-y0.getTimeInMillis())/(24*3600L*1000L));
+ return String.valueOf(1001+dayOfYear).substring(1);
+ });
+ CONVERTERS.put("m", d -> String.valueOf(101+d.get(Calendar.MONTH)).substring(1));
+ CONVERTERS.put("M", d -> String.valueOf(100+d.get(Calendar.MINUTE)).substring(1));
+ CONVERTERS.put("n", d -> "\n");
+ CONVERTERS.put("p", d -> d.get(Calendar.HOUR_OF_DAY) < 12? "AM": "PM");
+ CONVERTERS.put("r", d -> date("%I:%M:%S %p", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("R", d -> date("%H:%M", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("S", d -> String.valueOf(100+d.get(Calendar.SECOND)).substring(1));
+ CONVERTERS.put("t", d -> "\t");
+ CONVERTERS.put("T", d -> date("%H:%M:%S", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("u", d -> String.valueOf((d.get(Calendar.DAY_OF_WEEK)+6)%7));
+ CONVERTERS.put("U", d -> String.valueOf(weekNumber(d, 0)));
+ CONVERTERS.put("V", d -> String.valueOf(weekNumber(d, 0)));
+ CONVERTERS.put("w", d -> String.valueOf((d.get(Calendar.DAY_OF_WEEK)+6)%7));
+ CONVERTERS.put("W", d -> String.valueOf(weekNumber(d, 1)));
+ CONVERTERS.put("x", d -> date("%m/%d/%y", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("X", d -> date("%H:%M:%S", d.getTimeInMillis()/1000L));
+ CONVERTERS.put("y", d -> String.valueOf(d.get(Calendar.YEAR)).substring(2));
+ CONVERTERS.put("Y", d -> String.valueOf(d.get(Calendar.YEAR)));
+ CONVERTERS.put("z", d -> {
+ final int tzo = timeZoneOffset(d)/60;
+ final int a = Math.abs(tzo);
+ final String h = String.valueOf(100+a/60).substring(1);
+ final String m = String.valueOf(100+a%60).substring(1);
+ return (tzo >= 0? "+": "-")+h+m;
+ });
+ CONVERTERS.put("Z", d -> d.getTimeZone().toZoneId().getDisplayName(TextStyle.SHORT, Locale.getDefault()));
+ }
+
+ private static Calendar beginningOfYear(Calendar d) {
+ Calendar y0 = Calendar.getInstance();
+ y0.setTime(d.getTime());
+ y0.set(Calendar.MONTH, 0);
+ y0.set(Calendar.DAY_OF_MONTH, 1);
+ y0.set(Calendar.HOUR_OF_DAY, 0);
+ y0.set(Calendar.MINUTE, 0);
+ y0.set(Calendar.SECOND, 0);
+ y0.set(Calendar.MILLISECOND, 0);
+ return y0;
+ }
+
+ private static int weekNumber(Calendar d, int startDay) {
+ Calendar y0 = beginningOfYear(d);
+ y0.set(Calendar.DAY_OF_MONTH, 1+(startDay+8-y0.get(Calendar.DAY_OF_WEEK))%7);
+ if (y0.after(d)) {
+ y0.set(Calendar.YEAR, y0.get(Calendar.YEAR)-1);
+ y0.set(Calendar.DAY_OF_MONTH, 1+(startDay+8-y0.get(Calendar.DAY_OF_WEEK))%7);
+ }
+ long dt = d.getTime().getTime()-y0.getTime().getTime();
+ return 1+(int) (dt/(7L*24L*3600L*1000L));
+ }
+
+ private static int timeZoneOffset(Calendar d) {
+ int localStandarTimeMillis = (d.get(Calendar.HOUR_OF_DAY)*3600+d.get(Calendar.MINUTE)*60+d.get(Calendar.SECOND))
+ *1000;
+ return d.getTimeZone().getOffset(1, d.get(Calendar.YEAR), d.get(Calendar.MONTH), d.get(Calendar.DAY_OF_MONTH),
+ d.get(Calendar.DAY_OF_WEEK), localStandarTimeMillis)/1000;
+ }
+
+ private boolean isDaylightSavingsTime(Calendar d) {
+ return timeZoneOffset(d) != d.getTimeZone().getRawOffset()/1000;
+ }
+
+ /**
+ * This function is equivalent to the C function system. It passes command
+ * to be executed by an operating system shell. It returns a status code,
+ * which is system-dependent. If command is absent, then it returns nonzero
+ * if a shell is available and zero otherwise.
+ *
+ * @param command command to pass to the system
+ */
+ protected Varargs execute(String command) {
+ return varargsOf(NIL, valueOf("exit"), ONE);
+ }
+
+ /**
+ * Calls the C function exit, with an optional code, to terminate the host
+ * program.
+ *
+ * @param code
+ */
+ protected void exit(int code) {
+ System.exit(code);
+ }
+
+ /**
+ * Returns the value of the process environment variable varname, or the
+ * System property value for varname, or null if the variable is not defined
+ * in either environment.
+ *
+ * The default implementation, which is used by the JmePlatform, only
+ * queryies System.getProperty().
+ *
+ * The JsePlatform overrides this behavior and returns the environment
+ * variable value using System.getenv() if it exists, or the System property
+ * value if it does not.
+ *
+ * A SecurityException may be thrown if access is not allowed for 'varname'.
+ *
+ * @param varname
+ * @return String value, or null if not defined
+ */
+ protected String getenv(String varname) {
+ return System.getProperty(varname);
+ }
+
+ /**
+ * Deletes the file or directory with the given name. Directories must be
+ * empty to be removed. If this function fails, it throws and IOException
+ *
+ * @param filename
+ * @throws IOException if it fails
+ */
+ protected void remove(String filename) throws IOException {
+ throw new IOException("not implemented");
+ }
+
+ /**
+ * Renames file or directory named oldname to newname. If this function
+ * fails,it throws and IOException
+ *
+ * @param oldname old file name
+ * @param newname new file name
+ * @throws IOException if it fails
+ */
+ protected void rename(String oldname, String newname) throws IOException {
+ throw new IOException("not implemented");
+ }
+
+ /**
+ * Sets the current locale of the program. locale is a string specifying a
+ * locale; category is an optional string describing which category to
+ * change: "all", "collate", "ctype", "monetary", "numeric", or "time"; the
+ * default category is "all".
+ *
+ * If locale is the empty string, the current locale is set to an
+ * implementation- defined native locale. If locale is the string "C", the
+ * current locale is set to the standard C locale.
+ *
+ * When called with null as the first argument, this function only returns
+ * the name of the current locale for the given category.
+ *
+ * @param locale
+ * @param category
+ * @return the name of the new locale, or null if the request cannot be
+ * honored.
+ */
+ protected String setlocale(String locale, String category) {
+ return "C";
+ }
+
+ /**
+ * Returns the current time when called without arguments, or a time
+ * representing the date and time specified by the given table. This table
+ * must have fields year, month, and day, and may have fields hour, min,
+ * sec, and isdst (for a description of these fields, see the os.date
+ * function).
+ *
+ * @param table
+ * @return long value for the time
+ */
+ protected long time(LuaTable table) {
+ java.util.Date d;
+ if (table == null) {
+ d = new java.util.Date();
+ } else {
+ Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, table.get("year").checkint());
+ c.set(Calendar.MONTH, table.get("month").checkint()-1);
+ c.set(Calendar.DAY_OF_MONTH, table.get("day").checkint());
+ c.set(Calendar.HOUR_OF_DAY, table.get("hour").optint(12));
+ c.set(Calendar.MINUTE, table.get("min").optint(0));
+ c.set(Calendar.SECOND, table.get("sec").optint(0));
+ c.set(Calendar.MILLISECOND, 0);
+ d = c.getTime();
+ }
+ return d.getTime()/1000L;
+ }
+
+ /**
+ * Returns a string with a file name that can be used for a temporary file.
+ * The file must be explicitly opened before its use and explicitly removed
+ * when no longer needed.
+ *
+ * On some systems (POSIX), this function also creates a file with that
+ * name, to avoid security risks. (Someone else might create the file with
+ * wrong permissions in the time between getting the name and creating the
+ * file.) You still have to open the file to use it and to remove it (even
+ * if you do not use it).
+ *
+ * @return String filename to use
+ */
+ protected String tmpname() {
+ synchronized (OsLib.class) {
+ return TMP_PREFIX+tmpnames+++TMP_SUFFIX;
+ }
+ }
+}
diff --git a/src/core/org/luaj/vm2/lib/PackageLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java
similarity index 53%
rename from src/core/org/luaj/vm2/lib/PackageLib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java
index 4c2147c9..0eb74daf 100644
--- a/src/core/org/luaj/vm2/lib/PackageLib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,6 +22,7 @@
package org.luaj.vm2.lib;
import java.io.InputStream;
+import java.nio.file.FileSystems;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaFunction;
@@ -31,56 +32,73 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
- * Subclass of {@link LibFunction} which implements the lua standard package and module
- * library functions.
- *
- *
Lua Environment Variables
- * The following variables are available to lua scrips when this library has been loaded:
+ * Subclass of {@link LibFunction} which implements the lua standard package and
+ * module library functions.
+ *
+ *
Lua Environment Variables
The following variables are available to
+ * lua scrips when this library has been loaded:
*
*
"package.loaded" Lua table of loaded modules.
*
"package.path" Search path for lua scripts.
- *
"package.preload" Lua table of uninitialized preload functions.
- *
"package.searchers" Lua table of functions that search for object to load.
+ *
"package.searchers" Lua table of functions that search for
+ * object to load.
*
- *
- *
Java Environment Variables
- * These Java environment variables affect the library behavior:
+ *
+ *
Java Environment Variables
These Java environment variables affect
+ * the library behavior:
*
- *
"luaj.package.path" Initial value for "package.path". Default value is "?.lua"
+ *
"luaj.package.path" Initial value for
+ * "package.path". Default value is "?.lua"
*
- *
- *
Loading
- * Typically, this library is included as part of a call to either
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
{@code
+ *
+ *
Loading
Typically, this library is included as part of a call to
+ * either {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
+ *
+ *
- * This library has been implemented to match as closely as possible the behavior in the corresponding library in C.
- * However, the default filesystem search semantics are different and delegated to the bas library
- * as outlined in the {@link BaseLib} and {@link org.luaj.vm2.lib.jse.JseBaseLib} documentation.
+ * To instantiate and use it directly, link it into your globals table via
+ * {@link LuaValue#load(LuaValue)} using code such as:
+ *
+ *
This library has been implemented to match as closely as
+ * possible the behavior in the corresponding library in C. However, the default
+ * filesystem search semantics are different and delegated to the bas library as
+ * outlined in the {@link BaseLib} and {@link org.luaj.vm2.lib.jse.JseBaseLib}
+ * documentation.
*
+ *
* @see LibFunction
* @see BaseLib
* @see org.luaj.vm2.lib.jse.JseBaseLib
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Package Lib Reference
+ * @see Lua 5.2 Package
+ * Lib Reference
*/
public class PackageLib extends TwoArgFunction {
- /** The default value to use for package.path. This can be set with the system property
- * "luaj.package.path", and is "?.lua" by default. */
+ /**
+ * The default value to use for package.path. This can be set with the
+ * system property "luaj.package.path", and is
+ * "?.lua" by default.
+ */
public static final String DEFAULT_LUA_PATH;
static {
String path = null;
@@ -95,41 +113,52 @@ public class PackageLib extends TwoArgFunction {
DEFAULT_LUA_PATH = path;
}
- static final LuaString _LOADED = valueOf("loaded");
- private static final LuaString _LOADLIB = valueOf("loadlib");
- static final LuaString _PRELOAD = valueOf("preload");
- static final LuaString _PATH = valueOf("path");
- static final LuaString _SEARCHPATH = valueOf("searchpath");
- static final LuaString _SEARCHERS = valueOf("searchers");
-
+ static final LuaString _LOADED = valueOf("loaded");
+ private static final LuaString _LOADLIB = valueOf("loadlib");
+ static final LuaString _PRELOAD = valueOf("preload");
+ static final LuaString _PATH = valueOf("path");
+ static final LuaString _SEARCHPATH = valueOf("searchpath");
+ static final LuaString _SEARCHERS = valueOf("searchers");
+ static final LuaString _SEEALL = valueOf("seeall");
+
/** The globals that were used to load this library. */
Globals globals;
/** The table for this package. */
LuaTable package_;
-
+
/** Loader that loads from {@code preload} table if found there */
public preload_searcher preload_searcher;
-
- /** Loader that loads as a lua script using the lua path currently in {@link path} */
+
+ /**
+ * Loader that loads as a lua script using the lua path currently in
+ * {@link path}
+ */
public lua_searcher lua_searcher;
-
- /** Loader that loads as a Java class. Class must have public constructor and be a LuaValue. */
+
+ /**
+ * Loader that loads as a Java class. Class must have public constructor and
+ * be a LuaValue.
+ */
public java_searcher java_searcher;
- private static final LuaString _SENTINEL = valueOf("\u0001");
-
- private static final String FILE_SEP = System.getProperty("file.separator");
+ private static final LuaString _SENTINEL = valueOf("\u0001");
+
+ private static final String FILE_SEP = FileSystems.getDefault().getSeparator();
public PackageLib() {}
- /** Perform one-time initialization on the library by adding package functions
- * to the supplied environment, and returning it as the return value.
- * It also creates the package.preload and package.loaded tables for use by
- * other libraries.
+ /**
+ * Perform one-time initialization on the library by adding package
+ * functions to the supplied environment, and returning it as the return
+ * value. It also creates the package.preload and package.loaded tables for
+ * use by other libraries.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, typically a Globals instance.
+ * @param env the environment to load into, typically a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
globals = env.checkglobals();
globals.set("require", new require());
@@ -139,10 +168,11 @@ public class PackageLib extends TwoArgFunction {
package_.set(_PATH, LuaValue.valueOf(DEFAULT_LUA_PATH));
package_.set(_LOADLIB, new loadlib());
package_.set(_SEARCHPATH, new searchpath());
+ package_.set(_SEEALL, new seeall());
LuaTable searchers = new LuaTable();
searchers.set(1, preload_searcher = new preload_searcher());
- searchers.set(2, lua_searcher = new lua_searcher());
- searchers.set(3, java_searcher = new java_searcher());
+ searchers.set(2, lua_searcher = new lua_searcher());
+ searchers.set(3, java_searcher = new java_searcher());
package_.set(_SEARCHERS, searchers);
package_.set("config", FILE_SEP + "\n;\n?\n!\n-\n");
package_.get(_LOADED).set("package", package_);
@@ -150,226 +180,248 @@ public class PackageLib extends TwoArgFunction {
globals.package_ = this;
return env;
}
-
+
/** Allow packages to mark themselves as loaded */
public void setIsLoaded(String name, LuaTable value) {
package_.get(_LOADED).set(name, value);
}
-
- /** Set the lua path used by this library instance to a new value.
- * Merely sets the value of {@link path} to be used in subsequent searches. */
- public void setLuaPath( String newLuaPath ) {
+ /**
+ * Set the lua path used by this library instance to a new value. Merely
+ * sets the value of {@link path} to be used in subsequent searches.
+ */
+ public void setLuaPath(String newLuaPath) {
package_.set(_PATH, LuaValue.valueOf(newLuaPath));
}
-
+
+ @Override
public String tojstring() {
return "package";
}
-
+
// ======================== Package loading =============================
/**
* require (modname)
- *
- * Loads the given module. The function starts by looking into the package.loaded table
- * to determine whether modname is already loaded. If it is, then require returns the value
- * stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module.
- *
- * To find a loader, require is guided by the package.searchers sequence.
- * By changing this sequence, we can change how require looks for a module.
- * The following explanation is based on the default configuration for package.searchers.
- *
- * First require queries package.preload[modname]. If it has a value, this value
- * (which should be a function) is the loader. Otherwise require searches for a Lua loader using
- * the path stored in package.path. If that also fails, it searches for a Java loader using
- * the classpath, using the public default constructor, and casting the instance to LuaFunction.
- *
- * Once a loader is found, require calls the loader with two arguments: modname and an extra value
- * dependent on how it got the loader. If the loader came from a file, this extra value is the file name.
- * If the loader is a Java instance of LuaFunction, this extra value is the environment.
- * If the loader returns any non-nil value, require assigns the returned value to package.loaded[modname].
- * If the loader does not return a non-nil value and has not assigned any value to package.loaded[modname],
- * then require assigns true to this entry.
- * In any case, require returns the final value of package.loaded[modname].
- *
- * If there is any error loading or running the module, or if it cannot find any loader for the module,
- * then require raises an error.
+ *
+ * Loads the given module. The function starts by looking into the
+ * package.loaded table to determine whether modname is already loaded. If
+ * it is, then require returns the value stored at package.loaded[modname].
+ * Otherwise, it tries to find a loader for the module.
+ *
+ * To find a loader, require is guided by the package.searchers sequence. By
+ * changing this sequence, we can change how require looks for a module. The
+ * following explanation is based on the default configuration for
+ * package.searchers.
+ *
+ * First require queries package.preload[modname]. If it has a value, this
+ * value (which should be a function) is the loader. Otherwise require
+ * searches for a Lua loader using the path stored in package.path. If that
+ * also fails, it searches for a Java loader using the classpath, using the
+ * public default constructor, and casting the instance to LuaFunction.
+ *
+ * Once a loader is found, require calls the loader with two arguments:
+ * modname and an extra value dependent on how it got the loader. If the
+ * loader came from a file, this extra value is the file name. If the loader
+ * is a Java instance of LuaFunction, this extra value is the environment.
+ * If the loader returns any non-nil value, require assigns the returned
+ * value to package.loaded[modname]. If the loader does not return a non-nil
+ * value and has not assigned any value to package.loaded[modname], then
+ * require assigns true to this entry. In any case, require returns the
+ * final value of package.loaded[modname].
+ *
+ * If there is any error loading or running the module, or if it cannot find
+ * any loader for the module, then require raises an error.
*/
public class require extends OneArgFunction {
- public LuaValue call( LuaValue arg ) {
+ @Override
+ public LuaValue call(LuaValue arg) {
LuaString name = arg.checkstring();
LuaValue loaded = package_.get(_LOADED);
LuaValue result = loaded.get(name);
- if ( result.toboolean() ) {
- if ( result == _SENTINEL )
- error("loop or previous error loading module '"+name+"'");
+ if (result.toboolean()) {
+ if (result == _SENTINEL)
+ error("loop or previous error loading module '" + name + "'");
return result;
}
-
+
/* else must load it; iterate over available loaders */
LuaTable tbl = package_.get(_SEARCHERS).checktable();
StringBuffer sb = new StringBuffer();
Varargs loader = null;
- for ( int i=1; true; i++ ) {
+ for (int i = 1; true; i++) {
LuaValue searcher = tbl.get(i);
- if ( searcher.isnil() ) {
- error( "module '"+name+"' not found: "+name+sb );
- }
-
- /* call loader with module name as argument */
+ if (searcher.isnil()) {
+ error("module '" + name + "' not found: " + name + sb);
+ }
+
+ /* call loader with module name as argument */
loader = searcher.invoke(name);
- if ( loader.isfunction(1) )
+ if (loader.isfunction(1))
break;
- if ( loader.isstring(1) )
- sb.append( loader.tojstring(1) );
+ if (loader.isstring(1))
+ sb.append(loader.tojstring(1));
}
-
+
// load the module using the loader
loaded.set(name, _SENTINEL);
result = loader.arg1().call(name, loader.arg(2));
- if ( ! result.isnil() )
- loaded.set( name, result );
- else if ( (result = loaded.get(name)) == _SENTINEL )
- loaded.set( name, result = LuaValue.TRUE );
+ if (!result.isnil())
+ loaded.set(name, result);
+ else if ((result = loaded.get(name)) == _SENTINEL)
+ loaded.set(name, result = LuaValue.TRUE);
return result;
}
}
public static class loadlib extends VarArgFunction {
- public Varargs invoke( Varargs args ) {
+ @Override
+ public Varargs invoke(Varargs args) {
args.checkstring(1);
return varargsOf(NIL, valueOf("dynamic libraries not enabled"), valueOf("absent"));
}
}
public class preload_searcher extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaString name = args.checkstring(1);
LuaValue val = package_.get(_PRELOAD).get(name);
- return val.isnil()?
- valueOf("\n\tno field package.preload['"+name+"']"):
- val;
+ return val.isnil()? valueOf("\n\tno field package.preload['" + name + "']"): val;
}
}
public class lua_searcher extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaString name = args.checkstring(1);
-
+
// get package path
LuaValue path = package_.get(_PATH);
- if ( ! path.isstring() )
+ if (!path.isstring())
return valueOf("package.path is not a string");
-
+
// get the searchpath function.
Varargs v = package_.get(_SEARCHPATH).invoke(varargsOf(name, path));
-
+
// Did we get a result?
if (!v.isstring(1))
return v.arg(2).tostring();
LuaString filename = v.arg1().strvalue();
-
+
// Try to load the file.
v = globals.loadfile(filename.tojstring());
- if ( v.arg1().isfunction() )
+ if (v.arg1().isfunction())
return LuaValue.varargsOf(v.arg1(), filename);
-
+
// report error
- return varargsOf(NIL, valueOf("'"+filename+"': "+v.arg(2).tojstring()));
+ return varargsOf(NIL, valueOf("'" + filename + "': " + v.arg(2).tojstring()));
}
}
public class searchpath extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
String name = args.checkjstring(1);
String path = args.checkjstring(2);
String sep = args.optjstring(3, ".");
String rep = args.optjstring(4, FILE_SEP);
-
+
// check the path elements
int e = -1;
int n = path.length();
StringBuffer sb = null;
name = name.replace(sep.charAt(0), rep.charAt(0));
while ( e < n ) {
-
+
// find next template
int b = e+1;
- e = path.indexOf(';',b);
- if ( e < 0 )
+ e = path.indexOf(';', b);
+ if (e < 0)
e = path.length();
- String template = path.substring(b,e);
-
+ String template = path.substring(b, e);
+
// create filename
int q = template.indexOf('?');
String filename = template;
- if ( q >= 0 ) {
- filename = template.substring(0,q) + name + template.substring(q+1);
+ if (q >= 0) {
+ filename = template.substring(0, q)+name+template.substring(q+1);
}
-
+
// try opening the file
InputStream is = globals.finder.findResource(filename);
if (is != null) {
- try { is.close(); } catch ( java.io.IOException ioe ) {}
+ try {
+ is.close();
+ } catch (java.io.IOException ioe) {
+ }
return valueOf(filename);
}
-
+
// report error
- if ( sb == null )
+ if (sb == null)
sb = new StringBuffer();
- sb.append( "\n\t"+filename );
+ sb.append("\n\t" + filename);
}
return varargsOf(NIL, valueOf(sb.toString()));
}
}
-
+
+ public class seeall extends OneArgFunction {
+ @Override
+ public LuaValue call(LuaValue arg) {
+ LuaTable mt = new LuaTable();
+ mt.set(LuaValue.INDEX, globals);
+ arg.checktable().setmetatable(mt);
+ return LuaValue.NONE;
+ }
+ }
+
public class java_searcher extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
String name = args.checkjstring(1);
- String classname = toClassname( name );
+ String classname = toClassname(name);
Class c = null;
LuaValue v = null;
try {
c = Class.forName(classname);
v = (LuaValue) c.newInstance();
if (v.isfunction())
- ((LuaFunction)v).initupvalue1(globals);
+ ((LuaFunction) v).initupvalue1(globals);
return varargsOf(v, globals);
- } catch ( ClassNotFoundException cnfe ) {
- return valueOf("\n\tno class '"+classname+"'" );
- } catch ( Exception e ) {
- return valueOf("\n\tjava load failed on '"+classname+"', "+e );
+ } catch (ClassNotFoundException cnfe) {
+ return valueOf("\n\tno class '" + classname + "'");
+ } catch (Exception e) {
+ return valueOf("\n\tjava load failed on '" + classname + "', " + e);
}
}
}
-
+
/** Convert lua filename to valid class name */
- public static final String toClassname( String filename ) {
- int n=filename.length();
- int j=n;
- if ( filename.endsWith(".lua") )
+ public static final String toClassname(String filename) {
+ int n = filename.length();
+ int j = n;
+ if (filename.endsWith(".lua"))
j -= 4;
- for ( int k=0; k='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') )
+ if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9')
return true;
- switch ( c ) {
+ switch (c) {
case '.':
case '$':
case '_':
diff --git a/src/core/org/luaj/vm2/lib/ResourceFinder.java b/luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java
similarity index 75%
rename from src/core/org/luaj/vm2/lib/ResourceFinder.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java
index 3a7b38a6..af145f72 100644
--- a/src/core/org/luaj/vm2/lib/ResourceFinder.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,35 +25,36 @@ import java.io.InputStream;
import org.luaj.vm2.Globals;
-/**
- * Interface for opening application resource files such as scripts sources.
+/**
+ * Interface for opening application resource files such as scripts sources.
*
- * This is used by required to load files that are part of
- * the application, and implemented by BaseLib
- * for both the Jme and Jse platforms.
+ * This is used by required to load files that are part of the application, and
+ * implemented by BaseLib for both the Jme and Jse platforms.
*
- * The Jme version of base lib {@link BaseLib}
- * implements {@link Globals#finder} via {@link Class#getResourceAsStream(String)},
- * while the Jse version {@link org.luaj.vm2.lib.jse.JseBaseLib} implements it using {@link java.io.File#File(String)}.
+ * The Jme version of base lib {@link BaseLib} implements {@link Globals#finder}
+ * via {@link Class#getResourceAsStream(String)}, while the Jse version
+ * {@link org.luaj.vm2.lib.jse.JseBaseLib} implements it using
+ * {@link java.io.File#File(String)}.
*
* The io library does not use this API for file manipulation.
*
+ *
* @see BaseLib
* @see Globals#finder
* @see org.luaj.vm2.lib.jse.JseBaseLib
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see org.luaj.vm2.lib.jse.JsePlatform
+ * @see org.luaj.vm2.lib.jse.JsePlatform
*/
public interface ResourceFinder {
-
- /**
+
+ /**
* Try to open a file, or return null if not found.
- *
+ *
* @see org.luaj.vm2.lib.BaseLib
* @see org.luaj.vm2.lib.jse.JseBaseLib
- *
+ *
* @param filename
- * @return InputStream, or null if not found.
+ * @return InputStream, or null if not found.
*/
- public InputStream findResource( String filename );
-}
\ No newline at end of file
+ InputStream findResource(String filename);
+}
diff --git a/src/core/org/luaj/vm2/lib/StringLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java
similarity index 89%
rename from src/core/org/luaj/vm2/lib/StringLib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java
index 8011459a..a7de0ef1 100644
--- a/src/core/org/luaj/vm2/lib/StringLib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java
@@ -24,12 +24,8 @@ package org.luaj.vm2.lib;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import org.luaj.vm2.Buffer;
-import org.luaj.vm2.LuaClosure;
-import org.luaj.vm2.LuaString;
-import org.luaj.vm2.LuaTable;
-import org.luaj.vm2.LuaValue;
-import org.luaj.vm2.Varargs;
+import org.luaj.vm2.*;
+import org.luaj.vm2.compat.JavaCompat;
import org.luaj.vm2.compiler.DumpState;
/**
@@ -274,16 +270,63 @@ public class StringLib extends TwoArgFunction {
case 'f':
case 'g':
case 'G':
- fdsc.format( result, args.checkdouble( arg ) );
- break;
+ case 'a':
+ case 'A':
+ double j = args.checkdouble(arg);
+ if (Double.isNaN(j) || Double.isInfinite(j)) {
+ String nprefix = "";
+ if (JavaCompat.INSTANCE.doubleToRawLongBits(j) < 0)
+ nprefix = "-";
+ else if (fdsc.explicitPlus)
+ nprefix = "+";
+ else if (fdsc.space)
+ nprefix = " ";
+ String bstr = Double.isNaN(j) ? LuaDouble.JSTR_NAN : LuaDouble.JSTR_POSINF;
+ if (fdsc.conversion == 'E' || fdsc.conversion == 'G')
+ bstr = bstr.toUpperCase();
+ fdsc.precision = -1;
+ fdsc.zeroPad = false;
+ fdsc.format(result, valueOf(nprefix + bstr));
+ } else if ((fdsc.conversion == 'g' || fdsc.conversion == 'G') && fdsc.precision == -1) {
+ //TODO: This gives a slightly different format but is better than nothing
+ String nprefix = "";
+ if (j >= 0) {
+ if (fdsc.explicitPlus)
+ nprefix = "+";
+ else if (fdsc.space)
+ nprefix = " ";
+ }
+ String bstr = Double.toString(j);
+ if (fdsc.conversion == 'G')
+ bstr = bstr.toUpperCase();
+ else
+ bstr = bstr.toLowerCase();
+ fdsc.format(result, valueOf(nprefix + bstr));
+ } else
+ fdsc.format(result, args.checkdouble(arg));
+ break;
case 'q':
addquoted( result, args.checkstring( arg ) );
break;
case 's': {
- LuaString s = args.checkstring( arg );
+ LuaValue argv = args.checkvalue( arg );
+ LuaString s;
+ LuaValue h = argv.metatag(TOSTRING);
+ if ( ! h.isnil() ) {
+ LuaValue v = h.call(argv).tostring();
+ return !v.isnil() ? v : StringLib.valueOf("(null)");
+ } else {
+ LuaValue v = argv.tostring();
+ if ( ! v.isnil() ) {
+ s = v.checkstring();
+ } else {
+ s = StringLib.valueOf(argv.tojstring());
+ }
+ }
if ( fdsc.precision == -1 && s.length() >= 100 ) {
result.append( s );
} else {
+ fdsc.zeroPad = false;
fdsc.format( result, s );
}
} break;
@@ -374,9 +417,9 @@ public class StringLib extends TwoArgFunction {
c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 );
}
}
-
- precision = -1;
+
if ( c == '.' ) {
+ precision = 0;
c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 );
if ( Character.isDigit( (char) c ) ) {
precision = c - '0';
@@ -386,20 +429,32 @@ public class StringLib extends TwoArgFunction {
c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 );
}
}
- }
-
+ } else
+ precision = -1;
+
if ( Character.isDigit( (char) c ) )
error("invalid format (width or precision too long)");
-
- zeroPad &= !leftAdjust; // '-' overrides '0'
+
+ if ( width == -1 ) {
+ // default width overrides '-' and '0'
+ leftAdjust = false;
+ zeroPad = false;
+ } else
+ zeroPad &= !leftAdjust; // '-' overrides '0'
+ space &= !explicitPlus; // '+' overrides ' '
conversion = c;
length = p - start;
src = strfrmt.substring(start - 1, p).tojstring();
}
public void format(Buffer buf, byte c) {
- // TODO: not clear that any of width, precision, or flags apply here.
+ if (!leftAdjust)
+ pad(buf, ' ', width - 1);
+
buf.append(c);
+
+ if (leftAdjust)
+ pad(buf, ' ', width - 1);
}
public void format(Buffer buf, long number) {
@@ -429,10 +484,12 @@ public class StringLib extends TwoArgFunction {
int minwidth = digits.length();
int ndigits = minwidth;
int nzeros;
+
+ boolean allowPlusSpace = conversion == 'd' || conversion == 'i';
if ( number < 0 ) {
ndigits--;
- } else if ( explicitPlus || space ) {
+ } else if ( allowPlusSpace && (explicitPlus || space) ) {
minwidth++;
}
@@ -454,12 +511,26 @@ public class StringLib extends TwoArgFunction {
buf.append( (byte)'-' );
digits = digits.substring( 1 );
}
- } else if ( explicitPlus ) {
+ } else if ( allowPlusSpace && explicitPlus ) {
buf.append( (byte)'+' );
- } else if ( space ) {
+ } else if ( allowPlusSpace && space ) {
buf.append( (byte)' ' );
}
-
+
+ if (alternateForm) {
+ switch (conversion) {
+ case 'o':
+ buf.append((byte) '0');
+ break;
+ case 'x':
+ buf.append("0x");
+ break;
+ case 'X':
+ buf.append("0X");
+ break;
+ }
+ }
+
if ( nzeros > 0 )
pad( buf, '0', nzeros );
@@ -470,14 +541,40 @@ public class StringLib extends TwoArgFunction {
}
public void format(Buffer buf, double x) {
- buf.append( StringLib.this.format(src, x) );
+ // TODO: Java does not support alternateForm with 'g'
+ String sFormat = "%";
+ if (leftAdjust)
+ sFormat += ("-");
+ if (explicitPlus)
+ sFormat += ("+");
+ if (space)
+ sFormat += (" ");
+ if (alternateForm && conversion != 'g' && conversion != 'G')
+ sFormat += ("#");
+ if (zeroPad)
+ sFormat += ("0");
+ if (width != -1)
+ sFormat += (width);
+ if (precision != -1)
+ sFormat += (".") + (precision);
+ sFormat += ((char) conversion);
+ buf.append( StringLib.this.format(sFormat, x) );
}
public void format(Buffer buf, LuaString s) {
int nullindex = s.indexOf( (byte)'\0', 0 );
if ( nullindex != -1 )
s = s.substring( 0, nullindex );
+
+ int newLength = precision == -1 ? s.length() : Math.min(precision, s.length());
+
+ if (!leftAdjust)
+ pad(buf, zeroPad ? '0' : ' ', width - newLength);
+
buf.append(s);
+
+ if (leftAdjust)
+ pad(buf, ' ', width - newLength);
}
public final void pad(Buffer buf, char c, int n) {
@@ -602,6 +699,8 @@ public class StringLib extends TwoArgFunction {
int lastmatch = -1; /* end of last match */
LuaValue repl = args.arg( 3 );
int max_s = args.optint( 4, srclen + 1 );
+ if (max_s < 0)
+ max_s = srclen+1;
final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^';
Buffer lbuf = new Buffer( srclen );
@@ -666,22 +765,35 @@ public class StringLib extends TwoArgFunction {
return str_find_aux( args, false );
}
}
-
+
/**
- * string.rep (s, n)
- *
- * Returns a string that is the concatenation of n copies of the string s.
+ * string.rep (s, n [, sep])
+ *
+ * Returns a string that is the concatenation of n copies of the string s
+ * separated by the string sep. The default value for sep is the empty
+ * string (that is, no separator).
*/
static final class rep extends VarArgFunction {
public Varargs invoke(Varargs args) {
- LuaString s = args.checkstring( 1 );
- int n = args.checkint( 2 );
- final byte[] bytes = new byte[ s.length() * n ];
+ LuaString s = args.checkstring(1);
+ int n = args.checkint(2);
+ LuaString sep = args.optstring(3, EMPTYSTRING);
+ if (n <= 0)
+ return EMPTYSTRING;
int len = s.length();
- for ( int offset = 0; offset < bytes.length; offset += len ) {
- s.copyInto( 0, bytes, offset, len );
+ int lsep = sep.length();
+ final byte[] bytes = new byte[len * n + lsep * (n - 1)];
+ int offset = 0;
+ while (n-- > 1) {
+ s.copyInto(0, bytes, offset, len);
+ offset += len;
+ if (lsep > 0) {
+ sep.copyInto(0, bytes, offset, lsep);
+ offset += lsep;
+ }
}
- return LuaString.valueUsing( bytes );
+ s.copyInto(0, bytes, offset, len);
+ return LuaString.valueUsing(bytes);
}
}
diff --git a/src/core/org/luaj/vm2/lib/TableLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java
similarity index 68%
rename from src/core/org/luaj/vm2/lib/TableLib.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java
index 64959277..3c5cc258 100644
--- a/src/core/org/luaj/vm2/lib/TableLib.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,41 +26,58 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
/**
- * Subclass of {@link LibFunction} which implements the lua standard {@code table}
- * library.
- *
+ * Subclass of {@link LibFunction} which implements the lua standard
+ * {@code table} library.
+ *
*
* Typically, this library is included as part of a call to either
- * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Table Lib Reference
+ * @see Lua 5.2 Table
+ * Lib Reference
*/
public class TableLib extends TwoArgFunction {
- /** Perform one-time initialization on the library by creating a table
- * containing the library functions, adding that table to the supplied environment,
- * adding the table to package.loaded, and returning table as the return value.
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, typically a Globals instance.
+ * @param env the environment to load into, typically a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
LuaTable table = new LuaTable();
table.set("concat", new concat());
@@ -70,40 +87,50 @@ public class TableLib extends TwoArgFunction {
table.set("sort", new sort());
table.set("unpack", new unpack());
env.set("table", table);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("table", table);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("table", table);
return NIL;
}
-
+
// "concat" (table [, sep [, i [, j]]]) -> string
static class concat extends TableLibFunction {
+ @Override
public LuaValue call(LuaValue list) {
- return list.checktable().concat(EMPTYSTRING,1,list.length());
+ return list.checktable().concat(EMPTYSTRING, 1, list.length());
}
+
+ @Override
public LuaValue call(LuaValue list, LuaValue sep) {
- return list.checktable().concat(sep.checkstring(),1,list.length());
+ return list.checktable().concat(sep.checkstring(), 1, list.length());
}
+
+ @Override
public LuaValue call(LuaValue list, LuaValue sep, LuaValue i) {
- return list.checktable().concat(sep.checkstring(),i.checkint(),list.length());
+ return list.checktable().concat(sep.checkstring(), i.checkint(), list.length());
}
+
+ @Override
public LuaValue call(LuaValue list, LuaValue sep, LuaValue i, LuaValue j) {
- return list.checktable().concat(sep.checkstring(),i.checkint(),j.checkint());
+ return list.checktable().concat(sep.checkstring(), i.checkint(), j.checkint());
}
}
// "insert" (table, [pos,] value)
static class insert extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
switch (args.narg()) {
case 2: {
LuaTable table = args.checktable(1);
- table.insert(table.length()+1,args.arg(2));
+ table.insert(table.length()+1, args.arg(2));
return NONE;
}
case 3: {
LuaTable table = args.checktable(1);
int pos = args.checkint(2);
- int max = table.length() + 1;
- if (pos < 1 || pos > max) argerror(2, "position out of bounds: " + pos + " not between 1 and " + max);
+ int max = table.length()+1;
+ if (pos < 1 || pos > max)
+ argerror(2, "position out of bounds: " + pos + " not between 1 and " + max);
table.insert(pos, args.arg(3));
return NONE;
}
@@ -113,9 +140,10 @@ public class TableLib extends TwoArgFunction {
}
}
}
-
+
// "pack" (...) -> table
static class pack extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaValue t = tableOf(args, 1);
t.set("n", args.narg());
@@ -125,12 +153,13 @@ public class TableLib extends TwoArgFunction {
// "remove" (table [, pos]) -> removed-ele
static class remove extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaTable table = args.checktable(1);
int size = table.length();
int pos = args.optint(2, size);
- if (pos != size && (pos < 1 || pos > size + 1)) {
- argerror(2, "position out of bounds: " + pos + " not between 1 and " + (size + 1));
+ if (pos != size && (pos < 1 || pos > size+1)) {
+ argerror(2, "position out of bounds: " + pos + " not between 1 and " + (size+1));
}
return table.remove(pos);
}
@@ -138,20 +167,20 @@ public class TableLib extends TwoArgFunction {
// "sort" (table [, comp])
static class sort extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
- args.checktable(1).sort(
- args.isnil(2)? NIL: args.checkfunction(2));
+ args.checktable(1).sort(args.isnil(2)? NIL: args.checkfunction(2));
return NONE;
}
}
-
// "unpack", // (list [,i [,j]]) -> result1, ...
static class unpack extends VarArgFunction {
+ @Override
public Varargs invoke(Varargs args) {
LuaTable t = args.checktable(1);
// do not waste resource for calc rawlen if arg3 is not nil
- int len = args.arg(3).isnil() ? t.length() : 0;
+ int len = args.arg(3).isnil()? t.length(): 0;
return t.unpack(args.optint(2, 1), args.optint(3, len));
}
}
diff --git a/src/core/org/luaj/vm2/lib/TableLibFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/TableLibFunction.java
similarity index 94%
rename from src/core/org/luaj/vm2/lib/TableLibFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/TableLibFunction.java
index 5fabef7e..f9286b0a 100644
--- a/src/core/org/luaj/vm2/lib/TableLibFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/TableLibFunction.java
@@ -3,6 +3,7 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaValue;
class TableLibFunction extends LibFunction {
+ @Override
public LuaValue call() {
return argerror(1, "table expected, got no value");
}
diff --git a/src/core/org/luaj/vm2/lib/ThreeArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java
similarity index 75%
rename from src/core/org/luaj/vm2/lib/ThreeArgFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java
index 68ceb243..05a6b3a1 100644
--- a/src/core/org/luaj/vm2/lib/ThreeArgFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,21 +24,24 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
-/** Abstract base class for Java function implementations that take two arguments and
- * return one value.
+/**
+ * Abstract base class for Java function implementations that take two arguments
+ * and return one value.
*
- * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class,
- * simplifying development.
- * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,
- * are routed through this method by this class,
+ * Subclasses need only implement
+ * {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class,
+ * simplifying development. All other uses of {@link #call()},
+ * {@link #invoke(Varargs)},etc, are routed through this method by this class,
* dropping or extending arguments with {@code nil} values as required.
*
- * If more or less than three arguments are required,
- * or variable argument or variable return values,
- * then use one of the related function
- * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link VarArgFunction}.
+ * If more or less than three arguments are required, or variable argument or
+ * variable return values, then use one of the related function
+ * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or
+ * {@link VarArgFunction}.
*
- * See {@link LibFunction} for more information on implementation libraries and library functions.
+ * See {@link LibFunction} for more information on implementation libraries and
+ * library functions.
+ *
* @see #call(LuaValue,LuaValue,LuaValue)
* @see LibFunction
* @see ZeroArgFunction
@@ -48,26 +51,31 @@ import org.luaj.vm2.Varargs;
*/
abstract public class ThreeArgFunction extends LibFunction {
+ @Override
abstract public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3);
-
+
/** Default constructor */
public ThreeArgFunction() {
}
-
+
+ @Override
public final LuaValue call() {
return call(NIL, NIL, NIL);
}
+ @Override
public final LuaValue call(LuaValue arg) {
return call(arg, NIL, NIL);
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return call(arg1, arg2, NIL);
}
-
+
+ @Override
public Varargs invoke(Varargs varargs) {
- return call(varargs.arg1(),varargs.arg(2),varargs.arg(3));
+ return call(varargs.arg1(), varargs.arg(2), varargs.arg(3));
}
-
-}
+
+}
diff --git a/src/core/org/luaj/vm2/lib/TwoArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java
similarity index 75%
rename from src/core/org/luaj/vm2/lib/TwoArgFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java
index 8a97f6fb..f7ef431d 100644
--- a/src/core/org/luaj/vm2/lib/TwoArgFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,21 +24,24 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
-/** Abstract base class for Java function implementations that take two arguments and
- * return one value.
+/**
+ * Abstract base class for Java function implementations that take two arguments
+ * and return one value.
*
- * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to complete this class,
- * simplifying development.
- * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,
- * are routed through this method by this class,
- * dropping or extending arguments with {@code nil} values as required.
+ * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to
+ * complete this class, simplifying development. All other uses of
+ * {@link #call()}, {@link #invoke(Varargs)},etc, are routed through this method
+ * by this class, dropping or extending arguments with {@code nil} values as
+ * required.
*
- * If more or less than two arguments are required,
- * or variable argument or variable return values,
- * then use one of the related function
- * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
+ * If more or less than two arguments are required, or variable argument or
+ * variable return values, then use one of the related function
+ * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or
+ * {@link VarArgFunction}.
*
- * See {@link LibFunction} for more information on implementation libraries and library functions.
+ * See {@link LibFunction} for more information on implementation libraries and
+ * library functions.
+ *
* @see #call(LuaValue,LuaValue)
* @see LibFunction
* @see ZeroArgFunction
@@ -48,26 +51,31 @@ import org.luaj.vm2.Varargs;
*/
abstract public class TwoArgFunction extends LibFunction {
+ @Override
abstract public LuaValue call(LuaValue arg1, LuaValue arg2);
-
+
/** Default constructor */
public TwoArgFunction() {
}
-
+
+ @Override
public final LuaValue call() {
return call(NIL, NIL);
}
+ @Override
public final LuaValue call(LuaValue arg) {
return call(arg, NIL);
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return call(arg1, arg2);
}
-
+
+ @Override
public Varargs invoke(Varargs varargs) {
- return call(varargs.arg1(),varargs.arg(2));
+ return call(varargs.arg1(), varargs.arg(2));
}
-
-}
+
+}
diff --git a/src/core/org/luaj/vm2/lib/VarArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java
similarity index 70%
rename from src/core/org/luaj/vm2/lib/VarArgFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java
index 8e2bd614..e286bdd2 100644
--- a/src/core/org/luaj/vm2/lib/VarArgFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,20 +24,23 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
-/** Abstract base class for Java function implementations that takes varaiable arguments and
- * returns multiple return values.
+/**
+ * Abstract base class for Java function implementations that takes varaiable
+ * arguments and returns multiple return values.
*
- * Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete this class,
- * simplifying development.
- * All other uses of {@link #call(LuaValue)}, {@link #invoke()},etc,
- * are routed through this method by this class,
- * converting arguments to {@link Varargs} and
- * dropping or extending return values with {@code nil} values as required.
+ * Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete
+ * this class, simplifying development. All other uses of
+ * {@link #call(LuaValue)}, {@link #invoke()},etc, are routed through this
+ * method by this class, converting arguments to {@link Varargs} and dropping or
+ * extending return values with {@code nil} values as required.
*
- * If between one and three arguments are required, and only one return value is returned,
- * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link ThreeArgFunction}.
+ * If between one and three arguments are required, and only one return value is
+ * returned, {@link ZeroArgFunction}, {@link OneArgFunction},
+ * {@link TwoArgFunction}, or {@link ThreeArgFunction}.
*
- * See {@link LibFunction} for more information on implementation libraries and library functions.
+ * See {@link LibFunction} for more information on implementation libraries and
+ * library functions.
+ *
* @see #invoke(Varargs)
* @see LibFunction
* @see ZeroArgFunction
@@ -49,35 +52,41 @@ abstract public class VarArgFunction extends LibFunction {
public VarArgFunction() {
}
-
+
+ @Override
public LuaValue call() {
return invoke(NONE).arg1();
}
+ @Override
public LuaValue call(LuaValue arg) {
return invoke(arg).arg1();
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
- return invoke(varargsOf(arg1,arg2)).arg1();
+ return invoke(varargsOf(arg1, arg2)).arg1();
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
- return invoke(varargsOf(arg1,arg2,arg3)).arg1();
+ return invoke(varargsOf(arg1, arg2, arg3)).arg1();
}
- /**
- * Subclass responsibility.
- * May not have expected behavior for tail calls.
- * Should not be used if:
- * - function has a possibility of returning a TailcallVarargs
+ /**
+ * Subclass responsibility. May not have expected behavior for tail calls.
+ * Should not be used if: - function has a possibility of returning a
+ * TailcallVarargs
+ *
* @param args the arguments to the function call.
*/
+ @Override
public Varargs invoke(Varargs args) {
return onInvoke(args).eval();
}
-
+
+ @Override
public Varargs onInvoke(Varargs args) {
return invoke(args);
}
-}
+}
diff --git a/src/core/org/luaj/vm2/lib/ZeroArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java
similarity index 79%
rename from src/core/org/luaj/vm2/lib/ZeroArgFunction.java
rename to luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java
index 06169d74..9841a869 100644
--- a/src/core/org/luaj/vm2/lib/ZeroArgFunction.java
+++ b/luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,19 +24,21 @@ package org.luaj.vm2.lib;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
-/** Abstract base class for Java function implementations that take no arguments and
- * return one value.
+/**
+ * Abstract base class for Java function implementations that take no arguments
+ * and return one value.
*
- * Subclasses need only implement {@link LuaValue#call()} to complete this class,
- * simplifying development.
- * All other uses of {@link #call(LuaValue)}, {@link #invoke(Varargs)},etc,
- * are routed through this method by this class.
+ * Subclasses need only implement {@link LuaValue#call()} to complete this
+ * class, simplifying development. All other uses of {@link #call(LuaValue)},
+ * {@link #invoke(Varargs)},etc, are routed through this method by this class.
*
- * If one or more arguments are required, or variable argument or variable return values,
- * then use one of the related function
- * {@link OneArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
+ * If one or more arguments are required, or variable argument or variable
+ * return values, then use one of the related function {@link OneArgFunction},
+ * {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
*
- * The implementation of the is based on CLDC 1.0 and StreamConnection.
- * However, seek is not supported.
+/**
+ * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements
+ * the lua standard {@code io} library for the JSE platform.
*
- * Typically, this library is included as part of a call to
+ * The implementation of the is based on CLDC 1.0 and StreamConnection. However,
+ * seek is not supported.
+ *
+ * Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
- *
- * For special cases where the smallest possible footprint is desired,
- * a minimal set of libraries could be loaded
- * directly via {@link Globals#load(LuaValue)} using code such as:
- *
However, other libraries such as MathLib are not loaded in this case.
+ * For special cases where the smallest possible footprint is desired, a minimal
+ * set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
+ * using code such as:
+ *
+ *
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * However, other libraries such as MathLib are not loaded in this
+ * case.
+ *
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see IoLib
* @see org.luaj.vm2.lib.jse.JseIoLib
- * @see Lua 5.2 I/O Lib Reference
+ * @see Lua 5.2 I/O Lib
+ * Reference
*/
public class JmeIoLib extends IoLib {
-
+
+ @Override
protected File wrapStdin() throws IOException {
return new FileImpl(globals.STDIN);
}
-
+
+ @Override
protected File wrapStdout() throws IOException {
return new FileImpl(globals.STDOUT);
}
-
+
+ @Override
protected File wrapStderr() throws IOException {
return new FileImpl(globals.STDERR);
}
-
- protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
+
+ @Override
+ protected File openFile(String filename, boolean readMode, boolean appendMode, boolean updateMode,
+ boolean binaryMode) throws IOException {
String url = "file:///" + filename;
- int mode = readMode? Connector.READ: Connector.READ_WRITE;
- StreamConnection conn = (StreamConnection) Connector.open( url, mode );
- File f = readMode?
- new FileImpl(conn, conn.openInputStream(), null):
- new FileImpl(conn, conn.openInputStream(), conn.openOutputStream());
+ int mode = readMode? Connector.READ: Connector.READ_WRITE;
+ StreamConnection conn = (StreamConnection) Connector.open(url, mode);
+
/*
if ( appendMode ) {
f.seek("end",0);
@@ -97,68 +113,88 @@ public class JmeIoLib extends IoLib {
conn.truncate(0);
}
*/
- return f;
+ return readMode? new FileImpl(conn, conn.openInputStream(), null)
+ : new FileImpl(conn, conn.openInputStream(), conn.openOutputStream());
}
-
+
private static void notimplemented() throws IOException {
throw new IOException("not implemented");
}
-
+
+ @Override
protected File openProgram(String prog, String mode) throws IOException {
notimplemented();
return null;
}
+ @Override
protected File tmpFile() throws IOException {
notimplemented();
return null;
}
-
+
private final class FileImpl extends File {
private final StreamConnection conn;
- private final InputStream is;
- private final OutputStream os;
- private boolean closed = false;
- private boolean nobuffer = false;
- private int lookahead = -1;
- private FileImpl( StreamConnection conn, InputStream is, OutputStream os ) {
+ private final InputStream is;
+ private final OutputStream os;
+ private boolean closed = false;
+ private boolean nobuffer = false;
+ private int lookahead = -1;
+
+ private FileImpl(StreamConnection conn, InputStream is, OutputStream os) {
this.conn = conn;
this.is = is;
this.os = os;
}
- private FileImpl( InputStream i ) {
- this( null, i, null );
+
+ private FileImpl(InputStream i) {
+ this(null, i, null);
}
- private FileImpl( OutputStream o ) {
- this( null, null, o );
+
+ private FileImpl(OutputStream o) {
+ this(null, null, o);
}
+
+ @Override
public String tojstring() {
- return "file ("+this.hashCode()+")";
+ return "file (" + this.hashCode() + ")";
}
+
+ @Override
public boolean isstdfile() {
return conn == null;
}
- public void close() throws IOException {
+
+ @Override
+ public void close() throws IOException {
closed = true;
- if ( conn != null ) {
+ if (conn != null) {
conn.close();
}
}
+
+ @Override
public void flush() throws IOException {
- if ( os != null )
+ if (os != null)
os.flush();
}
+
+ @Override
public void write(LuaString s) throws IOException {
- if ( os != null )
- os.write( s.m_bytes, s.m_offset, s.m_length );
+ if (os != null)
+ os.write(s.m_bytes, s.m_offset, s.m_length);
else
notimplemented();
- if ( nobuffer )
+ if (nobuffer)
flush();
}
+
+ @Override
public boolean isclosed() {
return closed;
}
+
+ @Override
public int seek(String option, int pos) throws IOException {
/*
if ( conn != null ) {
@@ -177,48 +213,54 @@ public class JmeIoLib extends IoLib {
notimplemented();
return 0;
}
+
+ @Override
public void setvbuf(String mode, int size) {
nobuffer = "no".equals(mode);
}
// get length remaining to read
+ @Override
public int remaining() throws IOException {
return -1;
}
-
+
// peek ahead one character
+ @Override
public int peek() throws IOException {
- if ( lookahead < 0 )
+ if (lookahead < 0)
lookahead = is.read();
return lookahead;
- }
-
- // return char if read, -1 if eof, throw IOException on other exception
+ }
+
+ // return char if read, -1 if eof, throw IOException on other exception
+ @Override
public int read() throws IOException {
- if ( lookahead >= 0 ) {
+ if (lookahead >= 0) {
int c = lookahead;
lookahead = -1;
return c;
}
- if ( is != null )
+ if (is != null)
return is.read();
notimplemented();
return 0;
}
// return number of bytes read if positive, -1 if eof, throws IOException
+ @Override
public int read(byte[] bytes, int offset, int length) throws IOException {
- int n,i=0;
- if (is!=null) {
- if ( length > 0 && lookahead >= 0 ) {
+ int n, i = 0;
+ if (is != null) {
+ if (length > 0 && lookahead >= 0) {
bytes[offset] = (byte) lookahead;
lookahead = -1;
i += 1;
}
- for ( ; i 0 ? i : -1 );
+ if (n < 0)
+ return i > 0? i: -1;
i += n;
}
} else {
diff --git a/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java b/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java
similarity index 81%
rename from src/jme/org/luaj/vm2/lib/jme/JmePlatform.java
rename to luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java
index c7c8bb66..9b30e276 100644
--- a/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java
+++ b/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java
@@ -10,7 +10,7 @@
*
* 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
@@ -23,8 +23,6 @@ package org.luaj.vm2.lib.jme;
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;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.Bit32Lib;
@@ -37,40 +35,60 @@ import org.luaj.vm2.lib.ResourceFinder;
import org.luaj.vm2.lib.StringLib;
import org.luaj.vm2.lib.TableLib;
-/** The {@link org.luaj.vm2.lib.jme.JmePlatform} class is a convenience class to standardize
- * how globals tables are initialized for the JME platform.
+/**
+ * The {@link org.luaj.vm2.lib.jme.JmePlatform} class is a convenience class to
+ * standardize how globals tables are initialized for the JME platform.
*
- * The JME platform, being limited, cannot implement all libraries in all aspects. The main limitations are
+ * The JME platform, being limited, cannot implement all libraries in all
+ * aspects. The main limitations are
*
- *
Some math functions are not implemented, see {@link MathLib} for details
- *
Scripts are loaded via Class.getResourceAsStream(), see {@link BaseLib} for details
- *
OS functions execute(), remove(), rename(), and tmpname() vary, see {@link OsLib} for details
- *
I/O seek is not implemented, see {@link org.luaj.vm2.lib.jme.JmeIoLib} for details
- *
luajava is not available, see {@link org.luaj.vm2.lib.jse.LuajavaLib} for details
+ *
Some math functions are not implemented, see {@link MathLib} for
+ * details
+ *
Scripts are loaded via Class.getResourceAsStream(), see {@link BaseLib}
+ * for details
+ *
OS functions execute(), remove(), rename(), and tmpname() vary, see
+ * {@link OsLib} for details
+ *
I/O seek is not implemented, see {@link org.luaj.vm2.lib.jme.JmeIoLib}
+ * for details
+ *
luajava is not available, see {@link org.luaj.vm2.lib.jse.LuajavaLib} for
+ * details
*
*
- * It is used to allocate either a set of standard globals using
+ * It is used to allocate either a set of standard globals using
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
*
* A simple example of initializing globals and using them from Java is:
- *
- * For this to succeed, the file "main.lua" must be a resource in the class path.
- * See {@link BaseLib} for details on finding scripts using {@link ResourceFinder}.
+ * }
+ *
+ *
+ * For this to succeed, the file "main.lua" must be a resource in the class
+ * path. See {@link BaseLib} for details on finding scripts using
+ * {@link ResourceFinder}.
*
- * The standard globals will contain all standard libraries in their JME flavors:
+ * The standard globals will contain all standard libraries in their JME
+ * flavors:
*
- * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
- *
- * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}.
+ * In addition, the {@link LuaC} compiler is installed so lua files may be
+ * loaded in their source form.
+ *
+ * The debug globals are simply the standard globals plus the {@code debug}
+ * library {@link DebugLib}.
*
*
- * The class ensures that initialization is done in the correct order.
- *
+ * The class ensures that initialization is done in the correct order.
+ *
* @see Globals
* @see org.luaj.vm2.lib.jse.JsePlatform
*/
@@ -97,7 +117,7 @@ public class JmePlatform {
/**
* Create a standard set of globals for JME including all the libraries.
- *
+ *
* @return Table of globals initialized with the standard JME libraries
* @see #debugGlobals()
* @see org.luaj.vm2.lib.jse.JsePlatform
@@ -116,12 +136,14 @@ public class JmePlatform {
globals.load(new JmeIoLib());
LoadState.install(globals);
LuaC.install(globals);
- return globals;
+ return globals;
}
-
- /** Create standard globals including the {@link DebugLib} library.
- *
- * @return Table of globals initialized with the standard JSE and debug libraries
+
+ /**
+ * Create standard globals including the {@link DebugLib} library.
+ *
+ * @return Table of globals initialized with the standard JSE and debug
+ * libraries
* @see #standardGlobals()
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
diff --git a/luaj-jme/src/main/resources/.keep b/luaj-jme/src/main/resources/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/luaj-jme/src/test/java/org/luaj/vm2/lib/jme/OsLibTest.java b/luaj-jme/src/test/java/org/luaj/vm2/lib/jme/OsLibTest.java
new file mode 100644
index 00000000..39adf903
--- /dev/null
+++ b/luaj-jme/src/test/java/org/luaj/vm2/lib/jme/OsLibTest.java
@@ -0,0 +1,136 @@
+package org.luaj.vm2.lib.jme;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaValue;
+
+class OsLibTest {
+
+ LuaValue jme_lib;
+ double time;
+
+ @BeforeEach
+ public void setUp() {
+ jme_lib = JmePlatform.standardGlobals().get("os");
+ time = 998571302000L/1000.0;
+ }
+
+ void test(String format, String expected) {
+ String actual = jme_lib.get("date").call(LuaValue.valueOf(format), LuaValue.valueOf(time)).tojstring();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void testStringDateChars() { test("foo", "foo"); }
+
+ @Test
+ void testStringDate_a() { test("%a", "Thu"); }
+
+ @Test
+ void testStringDate_A() { test("%A", "Thursday"); }
+
+ @Test
+ void testStringDate_b() { test("%b", "Aug"); }
+
+ @Test
+ void testStringDate_B() { test("%B", "August"); }
+
+ @Test
+ void testStringDate_c() { test("%c", "Thu Aug 23 14:55:02 2001"); }
+
+ @Test
+ void testStringDate_d() { test("%d", "23"); }
+
+ @Test
+ void testStringDate_H() { test("%H", "14"); }
+
+ @Test
+ void testStringDate_I() { test("%I", "02"); }
+
+ @Test
+ void testStringDate_j() { test("%j", "235"); }
+
+ @Test
+ void testStringDate_m() { test("%m", "08"); }
+
+ @Test
+ void testStringDate_M() { test("%M", "55"); }
+
+ @Test
+ void testStringDate_p() { test("%p", "PM"); }
+
+ @Test
+ void testStringDate_S() { test("%S", "02"); }
+
+ @Test
+ void testStringDate_U() { test("%U", "33"); }
+
+ @Test
+ void testStringDate_w() { test("%w", "4"); }
+
+ @Test
+ void testStringDate_W() { test("%W", "34"); }
+
+ @Test
+ void testStringDate_x() { test("%x", "08/23/01"); }
+
+ @Test
+ void testStringDate_X() { test("%X", "14:55:02"); }
+
+ @Test
+ void testStringDate_y() { test("%y", "01"); }
+
+ @Test
+ void testStringDate_Y() { test("%Y", "2001"); }
+
+ @Test
+ void testStringDate_Pct() { test("%%", "%"); }
+
+ static final double DAY = 24.*3600.;
+
+ @Test
+ void testStringDate_UW_neg4() { time -= 4*DAY; test("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); }
+
+ @Test
+ void testStringDate_UW_neg3() { time -= 3*DAY; test("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_neg2() { time -= 2*DAY; test("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_neg1() { time -= DAY; test("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos0() { time += 0; test("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos1() { time += DAY; test("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos2() { time += 2*DAY; test("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos3() { time += 3*DAY; test("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); }
+
+ @Test
+ void testStringDate_UW_pos4() { time += 4*DAY; test("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); }
+
+ @Test
+ void testJseOsGetenvForEnvVariables() {
+ LuaValue USER = LuaValue.valueOf("USER");
+ LuaValue jme_user = jme_lib.get("getenv").call(USER);
+ assertTrue(jme_user.isnil());
+ System.out.println("User: " + jme_user);
+ }
+
+ void testJseOsGetenvForSystemProperties() {
+// System.setProperty("test.key.foo", "test.value.bar");
+ LuaValue key = LuaValue.valueOf("test.key.foo");
+ LuaValue value = LuaValue.valueOf("test.value.bar");
+ LuaValue jme_value = jme_lib.get("getenv").call(key);
+ assertEquals(value, jme_value);
+ }
+}
diff --git a/luaj-jme/src/test/resources/.keep b/luaj-jme/src/test/resources/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/luaj-jse-3.0.2.jar b/luaj-jse-3.0.2.jar
new file mode 100644
index 00000000..070e1c98
Binary files /dev/null and b/luaj-jse-3.0.2.jar differ
diff --git a/luaj-jse/pom.xml b/luaj-jse/pom.xml
new file mode 100644
index 00000000..cba44a6a
--- /dev/null
+++ b/luaj-jse/pom.xml
@@ -0,0 +1,77 @@
+
+ 4.0.0
+
+
+ org.luaj
+ luaj-parent
+ 3.0-SNAPSHOT
+
+
+ luaj-jse
+
+ luaj-jse
+ LuaJ for Java SE
+
+
+
+ org.luaj
+ luaj-core
+ ${project.version}
+
+
+ org.apache.bcel
+ bcel
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ com.helger.maven
+ ph-javacc-maven-plugin
+
+
+ generate-grammar
+ generate-sources
+
+ javacc
+
+
+ 1.8
+ true
+ org.luaj.vm2.parser
+ src/main/javacc
+ ${project.build.directory}/generated-sources/javacc
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+ ${project.build.directory}/generated-sources/javacc
+
+
+
+
+
+
+
+
+
diff --git a/src/jse/lua.java b/luaj-jse/src/main/java/lua.java
similarity index 59%
rename from src/jse/lua.java
rename to luaj-jse/src/main/java/lua.java
index 39e488f2..1961a951 100644
--- a/src/jse/lua.java
+++ b/luaj-jse/src/main/java/lua.java
@@ -1,3 +1,4 @@
+
/*******************************************************************************
* Copyright (c) 2009-2012 Luaj.org. All rights reserved.
*
@@ -10,7 +11,7 @@
*
* 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
@@ -38,40 +39,33 @@ import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.luajc.LuaJC;
-
/**
* lua command for use in JSE environments.
*/
public class lua {
private static final String version = Lua._VERSION + " Copyright (c) 2012 Luaj.org.org";
- private static final String usage =
- "usage: java -cp luaj-jse.jar lua [options] [script [args]].\n" +
- "Available options are:\n" +
- " -e stat execute string 'stat'\n" +
- " -l name require library 'name'\n" +
- " -i enter interactive mode after executing 'script'\n" +
- " -v show version information\n" +
- " -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";
+ private static final String usage = "usage: java -cp luaj-jse.jar lua [options] [script [args]].\n"
+ + "Available options are:\n" + " -e stat execute string 'stat'\n" + " -l name require library 'name'\n"
+ + " -i enter interactive mode after executing 'script'\n" + " -v show version information\n"
+ + " -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";
private static void usageExit() {
System.out.println(usage);
- System.exit(-1);
+ System.exit(-1);
}
private static Globals globals;
- private static boolean print = false;
- private static String encoding = null;
-
- public static void main( String[] args ) throws IOException {
+ private static boolean print = false;
+ private static String encoding = null;
+
+ public static void main(String[] args) throws IOException {
// process args
- boolean interactive = (args.length == 0);
+ boolean interactive = args.length == 0;
boolean versioninfo = false;
boolean processing = true;
boolean nodebug = false;
@@ -79,17 +73,17 @@ public class lua {
Vector libs = null;
try {
// stateful argument processing
- for ( int i=0; i= args.length )
+ if (++i >= args.length)
usageExit();
// input script - defer to last stage
break;
@@ -97,10 +91,10 @@ public class lua {
luajc = true;
break;
case 'l':
- if ( ++i >= args.length )
+ if (++i >= args.length)
usageExit();
- libs = libs!=null? libs: new Vector();
- libs.addElement( args[i] );
+ libs = libs != null? libs: new Vector();
+ libs.addElement(args[i]);
break;
case 'i':
interactive = true;
@@ -115,12 +109,12 @@ public class lua {
print = true;
break;
case 'c':
- if ( ++i >= args.length )
+ if (++i >= args.length)
usageExit();
encoding = args[i];
break;
case '-':
- if ( args[i].length() > 2 )
+ if (args[i].length() > 2)
usageExit();
processing = false;
break;
@@ -132,33 +126,34 @@ public class lua {
}
// echo version
- if ( versioninfo )
+ if (versioninfo)
System.out.println(version);
-
+
// new lua state
globals = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals();
- if ( luajc ) LuaJC.install(globals);
- for ( int i=0, n=libs!=null? libs.size(): 0; i ");
System.out.flush();
String line = reader.readLine();
- if ( line == null )
+ if (line == null)
return;
- processScript( new ByteArrayInputStream(line.getBytes()), "=stdin", null, 0 );
+ processScript(new ByteArrayInputStream(line.getBytes()), "=stdin", null, 0);
}
}
}
diff --git a/src/jse/luac.java b/luaj-jse/src/main/java/luac.java
similarity index 54%
rename from src/jse/luac.java
rename to luaj-jse/src/main/java/luac.java
index f0af43fe..43122dfb 100644
--- a/src/jse/luac.java
+++ b/luaj-jse/src/main/java/luac.java
@@ -1,3 +1,4 @@
+
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
@@ -10,7 +11,7 @@
*
* 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
@@ -35,63 +36,56 @@ import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.DumpState;
import org.luaj.vm2.lib.jse.JsePlatform;
-
/**
- * Compiler for lua files to lua bytecode.
+ * Compiler for lua files to lua bytecode.
*/
public class luac {
private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org";
- private static final String usage =
- "usage: java -cp luaj-jse.jar luac [options] [filenames].\n" +
- "Available options are:\n" +
- " - process stdin\n" +
- " -l list\n" +
- " -o name output to file 'name' (default is \"luac.out\")\n" +
- " -p parse only\n" +
- " -s strip debug information\n" +
- " -e little endian format for numbers\n" +
- " -i 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 final String usage = "usage: java -cp luaj-jse.jar luac [options] [filenames].\n"
+ + "Available options are:\n" + " - process stdin\n" + " -l list\n"
+ + " -o name output to file 'name' (default is \"luac.out\")\n" + " -p parse only\n"
+ + " -s strip debug information\n" + " -e little endian format for numbers\n"
+ + " -i 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() {
System.out.println(usage);
- System.exit(-1);
+ System.exit(-1);
}
- private boolean list = false;
- private String output = "luac.out";
- private boolean parseonly = false;
- private boolean stripdebug = false;
+ private boolean list = false;
+ private String output = "luac.out";
+ private boolean parseonly = false;
+ private boolean stripdebug = false;
private boolean littleendian = false;
- private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT;
- private boolean versioninfo = false;
- private boolean processing = true;
- private String encoding = null;
+ 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 );
+ public static void main(String[] args) throws IOException {
+ new luac(args);
}
- private luac( String[] args ) throws IOException {
-
+ private luac(String[] args) throws IOException {
+
// process args
try {
// get stateful args
- for ( int i=0; i= args.length )
+ if (++i >= args.length)
usageExit();
output = args[i];
break;
@@ -105,7 +99,7 @@ public class luac {
littleendian = true;
break;
case 'i':
- if ( args[i].length() <= 2 )
+ if (args[i].length() <= 2)
usageExit();
numberformat = Integer.parseInt(args[i].substring(2));
break;
@@ -113,12 +107,12 @@ public class luac {
versioninfo = true;
break;
case 'c':
- if ( ++i >= args.length )
+ if (++i >= args.length)
usageExit();
encoding = args[i];
break;
case '-':
- if ( args[i].length() > 2 )
+ if (args[i].length() > 2)
usageExit();
processing = false;
break;
@@ -128,26 +122,24 @@ public class luac {
}
}
}
-
+
// echo version
- if ( versioninfo )
+ if (versioninfo)
System.out.println(version);
// open output file
- OutputStream fos = new FileOutputStream( output );
-
// process input files
- try {
+ try (OutputStream fos = new FileOutputStream(output)) {
Globals globals = JsePlatform.standardGlobals();
processing = true;
- for ( int i=0; i= args.length)
+ usageExit();
+ srcdir = args[i];
+ break;
+ case 'd':
+ if (++i >= args.length)
+ usageExit();
+ destdir = args[i];
+ break;
+ case 'l':
+ loadclasses = true;
+ break;
+ case 'p':
+ if (++i >= args.length)
+ usageExit();
+ pkgprefix = args[i];
+ break;
+ case 'm':
+ genmain = true;
+ break;
+ case 'r':
+ recurse = true;
+ break;
+ case 'c':
+ if (++i >= args.length)
+ usageExit();
+ encoding = args[i];
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ usageExit();
+ break;
+ }
+ }
+ }
+
+ // echo version
+ if (verbose) {
+ System.out.println(version);
+ System.out.println("srcdir: " + srcdir);
+ System.out.println("destdir: " + destdir);
+ System.out.println("files: " + seeds);
+ System.out.println("recurse: " + recurse);
+ }
+
+ // need at least one seed
+ if (seeds.size() <= 0) {
+ System.err.println(usage);
+ System.exit(-1);
+ }
+
+ // collect up files to process
+ for (Object seed : seeds)
+ collectFiles(srcdir + "/" + seed);
+
+ // check for at least one file
+ if (files.size() <= 0) {
+ System.err.println("no files found in " + seeds);
+ System.exit(-1);
+ }
+
+ // process input files
+ globals = JsePlatform.standardGlobals();
+ for (Object file : files)
+ processFile((InputFile) file);
+ }
+
+ private void collectFiles(String path) {
+ File f = new File(path);
+ if (f.isDirectory() && recurse)
+ scandir(f, pkgprefix);
+ else if (f.isFile()) {
+ File dir = f.getAbsoluteFile().getParentFile();
+ if (dir != null)
+ scanfile(dir, f, pkgprefix);
+ }
+ }
+
+ private void scandir(File dir, String javapackage) {
+ File[] f = dir.listFiles();
+ for (File element : f)
+ scanfile(dir, element, javapackage);
+ }
+
+ private void scanfile(File dir, File f, String javapackage) {
+ if (f.exists()) {
+ if (f.isDirectory() && recurse)
+ scandir(f, javapackage != null? javapackage + "." + f.getName(): f.getName());
+ else if (f.isFile() && f.getName().endsWith(".lua"))
+ files.add(new InputFile(dir, f, javapackage));
+ }
+ }
+
+ private static final class LocalClassLoader extends ClassLoader {
+ private final Hashtable t;
+
+ private LocalClassLoader(Hashtable t) {
+ this.t = t;
+ }
+
+ @Override
+ public Class findClass(String classname) throws ClassNotFoundException {
+ byte[] bytes = (byte[]) t.get(classname);
+ if (bytes != null)
+ return defineClass(classname, bytes, 0, bytes.length);
+ return super.findClass(classname);
+ }
+ }
+
+ class InputFile {
+ public String luachunkname;
+ public String srcfilename;
+ public File infile;
+ public File outdir;
+ public String javapackage;
+
+ public InputFile(File dir, File f, String javapackage) {
+ this.infile = f;
+ String subdir = javapackage != null? javapackage.replace('.', '/'): null;
+ String outdirpath = subdir != null? destdir + "/" + subdir: destdir;
+ this.javapackage = javapackage;
+ this.srcfilename = (subdir != null? subdir + "/": "")+infile.getName();
+ this.luachunkname = (subdir != null? subdir + "/": "")
+ +infile.getName().substring(0, infile.getName().lastIndexOf('.'));
+ this.infile = f;
+ this.outdir = new File(outdirpath);
+ }
+ }
+
+ private void processFile(InputFile inf) {
+ inf.outdir.mkdirs();
+ try {
+ if (verbose)
+ System.out.println("chunk=" + inf.luachunkname + " srcfile=" + inf.srcfilename);
+
+ // create the chunk
+ FileInputStream fis = new FileInputStream(inf.infile);
+ 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
+ for (Enumeration e = t.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ byte[] bytes = (byte[]) t.get(key);
+ if (key.indexOf('/') >= 0) {
+ String d = (destdir != null? destdir + "/": "")+key.substring(0, key.lastIndexOf('/'));
+ new File(d).mkdirs();
+ }
+ String destpath = (destdir != null? destdir + "/": "") + key + ".class";
+ if (verbose)
+ System.out.println(" " + destpath + " (" + bytes.length + " bytes)");
+ FileOutputStream fos = new FileOutputStream(destpath);
+ fos.write(bytes);
+ fos.close();
+ }
+
+ // try to load the files
+ if (loadclasses) {
+ ClassLoader loader = new LocalClassLoader(t);
+ for (Enumeration e = t.keys(); e.hasMoreElements();) {
+ String classname = (String) e.nextElement();
+ try {
+ Class c = loader.loadClass(classname);
+ Object o = c.newInstance();
+ if (verbose)
+ System.out.println(" loaded " + classname + " as " + o);
+ } catch (Exception ex) {
+ System.out.flush();
+ System.err.println(" failed to load " + classname + ": " + ex);
+ System.err.flush();
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ System.err.println(" failed to load " + inf.srcfilename + ": " + e);
+ e.printStackTrace(System.err);
+ System.err.flush();
+ }
+ }
+}
diff --git a/src/jse/org/luaj/vm2/ast/Block.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java
similarity index 93%
rename from src/jse/org/luaj/vm2/ast/Block.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java
index d63df608..af0b4383 100644
--- a/src/jse/org/luaj/vm2/ast/Block.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,16 +25,17 @@ import java.util.ArrayList;
import java.util.List;
public class Block extends Stat {
-
- public List stats = new ArrayList();
- public NameScope scope;
-
+
+ public List stats = new ArrayList<>();
+ public NameScope scope;
+
public void add(Stat s) {
- if ( s == null )
+ if (s == null)
return;
stats.add(s);
}
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
diff --git a/src/jse/org/luaj/vm2/ast/Chunk.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java
similarity index 95%
rename from src/jse/org/luaj/vm2/ast/Chunk.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java
index f09ff461..0e584a6d 100644
--- a/src/jse/org/luaj/vm2/ast/Chunk.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java
@@ -10,7 +10,7 @@
*
* 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
@@ -23,12 +23,12 @@ package org.luaj.vm2.ast;
public class Chunk extends SyntaxElement {
public final Block block;
-
+
public Chunk(Block b) {
this.block = b;
}
-
- public void accept( Visitor visitor ) {
- visitor.visit( this );
+
+ public void accept(Visitor visitor) {
+ visitor.visit(this);
}
}
diff --git a/src/jse/org/luaj/vm2/ast/Exp.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java
similarity index 76%
rename from src/jse/org/luaj/vm2/ast/Exp.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java
index 7b41b60b..4908b32f 100644
--- a/src/jse/org/luaj/vm2/ast/Exp.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,16 +24,15 @@ package org.luaj.vm2.ast;
import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaValue;
-abstract
-public class Exp extends SyntaxElement {
+abstract public class Exp extends SyntaxElement {
abstract public void accept(Visitor visitor);
public static Exp constant(LuaValue value) {
return new Constant(value);
}
- public static Exp numberconstant(String token) {
- return new Constant( LuaValue.valueOf(token).tonumber() );
+ public static Exp numberconstant(String token) {
+ return new Constant(LuaValue.valueOf(token).tonumber());
}
public static Exp varargs() {
@@ -45,59 +44,78 @@ public class Exp extends SyntaxElement {
}
public static Exp unaryexp(int op, Exp rhs) {
- if ( rhs instanceof BinopExp ) {
+ if (rhs instanceof BinopExp) {
BinopExp b = (BinopExp) rhs;
- if ( precedence(op) > precedence(b.op) )
- return binaryexp( unaryexp(op, b.lhs), b.op, b.rhs );
+ if (precedence(op) > precedence(b.op))
+ return binaryexp(unaryexp(op, b.lhs), b.op, b.rhs);
}
return new UnopExp(op, rhs);
}
public static Exp binaryexp(Exp lhs, int op, Exp rhs) {
- if ( lhs instanceof UnopExp ) {
+ if (lhs instanceof UnopExp) {
UnopExp u = (UnopExp) lhs;
- if ( precedence(op) > precedence(u.op) )
- return unaryexp( u.op, binaryexp( u.rhs, op, rhs ) );
+ if (precedence(op) > precedence(u.op))
+ return unaryexp(u.op, binaryexp(u.rhs, op, rhs));
}
// TODO: cumulate string concatenations together
// TODO: constant folding
- if ( lhs instanceof BinopExp ) {
+ if (lhs instanceof BinopExp) {
BinopExp b = (BinopExp) lhs;
- if ( (precedence(op) > precedence(b.op)) ||
- ((precedence(op) == precedence(b.op)) && isrightassoc(op)) )
- return binaryexp( b.lhs, b.op, binaryexp( b.rhs, op, rhs ) );
+ if (precedence(op) > precedence(b.op) || precedence(op) == precedence(b.op) && isrightassoc(op))
+ return binaryexp(b.lhs, b.op, binaryexp(b.rhs, op, rhs));
}
- if ( rhs instanceof BinopExp ) {
+ if (rhs instanceof BinopExp) {
BinopExp b = (BinopExp) rhs;
- if ( (precedence(op) > precedence(b.op)) ||
- ((precedence(op) == precedence(b.op)) && ! isrightassoc(op)) )
- return binaryexp( binaryexp( lhs, op, b.lhs ), b.op, b.rhs );
+ if (precedence(op) > precedence(b.op) || precedence(op) == precedence(b.op) && !isrightassoc(op))
+ return binaryexp(binaryexp(lhs, op, b.lhs), b.op, b.rhs);
}
return new BinopExp(lhs, op, rhs);
}
static boolean isrightassoc(int op) {
- switch ( op ) {
+ switch (op) {
case Lua.OP_CONCAT:
- case Lua.OP_POW: return true;
- default: return false;
+ case Lua.OP_POW:
+ return true;
+ default:
+ return false;
}
}
-
+
static int precedence(int op) {
- switch ( op ) {
- case Lua.OP_OR: return 0;
- case Lua.OP_AND: return 1;
- case Lua.OP_LT: case Lua.OP_GT: case Lua.OP_LE: case Lua.OP_GE: case Lua.OP_NEQ: case Lua.OP_EQ: return 2;
- case Lua.OP_CONCAT: return 3;
- case Lua.OP_ADD: case Lua.OP_SUB: return 4;
- case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_MOD: return 5;
- case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6;
- case Lua.OP_POW: return 7;
- default: throw new IllegalStateException("precedence of bad op "+op);
+ switch (op) {
+ case Lua.OP_OR:
+ return 0;
+ case Lua.OP_AND:
+ return 1;
+ case Lua.OP_LT:
+ case Lua.OP_GT:
+ case Lua.OP_LE:
+ case Lua.OP_GE:
+ case Lua.OP_NEQ:
+ case Lua.OP_EQ:
+ return 2;
+ case Lua.OP_CONCAT:
+ return 3;
+ case Lua.OP_ADD:
+ case Lua.OP_SUB:
+ return 4;
+ case Lua.OP_MUL:
+ case Lua.OP_DIV:
+ case Lua.OP_MOD:
+ return 5;
+ case Lua.OP_NOT:
+ case Lua.OP_UNM:
+ case Lua.OP_LEN:
+ return 6;
+ case Lua.OP_POW:
+ return 7;
+ default:
+ throw new IllegalStateException("precedence of bad op " + op);
}
- }
-
+ }
+
public static Exp anonymousfunction(FuncBody funcbody) {
return new AnonFuncDef(funcbody);
}
@@ -143,108 +161,129 @@ public class Exp extends SyntaxElement {
public boolean isvarargexp() {
return false;
}
-
+
abstract public static class PrimaryExp extends Exp {
+ @Override
public boolean isvarexp() {
return false;
}
+
+ @Override
public boolean isfunccall() {
return false;
}
}
abstract public static class VarExp extends PrimaryExp {
+ @Override
public boolean isvarexp() {
return true;
}
+
public void markHasAssignment() {
}
}
-
+
public static class NameExp extends VarExp {
public final Name name;
+
public NameExp(String name) {
this.name = new Name(name);
}
+
+ @Override
public void markHasAssignment() {
name.variable.hasassignments = true;
}
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
-
+
public static class ParensExp extends PrimaryExp {
public final Exp exp;
+
public ParensExp(Exp exp) {
this.exp = exp;
}
-
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
-
+
public static class FieldExp extends VarExp {
public final PrimaryExp lhs;
- public final Name name;
+ public final Name name;
+
public FieldExp(PrimaryExp lhs, String name) {
this.lhs = lhs;
this.name = new Name(name);
}
-
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
-
+
public static class IndexExp extends VarExp {
public final PrimaryExp lhs;
- public final Exp exp;
+ public final Exp exp;
+
public IndexExp(PrimaryExp lhs, Exp exp) {
this.lhs = lhs;
this.exp = exp;
}
-
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
-
+
public static class FuncCall extends PrimaryExp {
public final PrimaryExp lhs;
- public final FuncArgs args;
-
+ public final FuncArgs args;
+
public FuncCall(PrimaryExp lhs, FuncArgs args) {
this.lhs = lhs;
this.args = args;
}
+ @Override
public boolean isfunccall() {
return true;
}
-
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
-
+
+ @Override
public boolean isvarargexp() {
return true;
}
}
-
+
public static class MethodCall extends FuncCall {
public final String name;
-
+
public MethodCall(PrimaryExp lhs, String name, FuncArgs args) {
super(lhs, args);
this.name = new String(name);
}
+ @Override
public boolean isfunccall() {
return true;
}
-
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@@ -252,62 +291,72 @@ public class Exp extends SyntaxElement {
public static class Constant extends Exp {
public final LuaValue value;
+
public Constant(LuaValue value) {
this.value = value;
}
- public void accept(Visitor visitor) {
- visitor.visit(this);
- }
- }
-
- public static class VarargsExp extends Exp {
-
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
-
+ }
+
+ public static class VarargsExp extends Exp {
+
+ @Override
+ public void accept(Visitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
public boolean isvarargexp() {
return true;
}
}
-
+
public static class UnopExp extends Exp {
public final int op;
public final Exp rhs;
+
public UnopExp(int op, Exp rhs) {
this.op = op;
this.rhs = rhs;
}
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
- }
+ }
}
-
+
public static class BinopExp extends Exp {
- public final Exp lhs,rhs;
+ public final Exp lhs, rhs;
public final int op;
+
public BinopExp(Exp lhs, int op, Exp rhs) {
this.lhs = lhs;
this.op = op;
this.rhs = rhs;
}
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
- }
+ }
}
-
+
public static class AnonFuncDef extends Exp {
public final FuncBody body;
+
public AnonFuncDef(FuncBody funcbody) {
this.body = funcbody;
}
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
- }
+ }
}
}
diff --git a/src/jse/org/luaj/vm2/ast/FuncArgs.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java
similarity index 93%
rename from src/jse/org/luaj/vm2/ast/FuncArgs.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java
index 8c34cfc7..56768a15 100644
--- a/src/jse/org/luaj/vm2/ast/FuncArgs.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java
@@ -10,7 +10,7 @@
*
* 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
@@ -29,7 +29,7 @@ import org.luaj.vm2.LuaString;
public class FuncArgs extends SyntaxElement {
public final List exps;
-
+
/** exp1,exp2... */
public static FuncArgs explist(List explist) {
return new FuncArgs(explist);
@@ -50,13 +50,13 @@ public class FuncArgs extends SyntaxElement {
}
public FuncArgs(LuaString string) {
- this.exps = new ArrayList();
- this.exps.add( Exp.constant(string) );
+ this.exps = new ArrayList<>();
+ this.exps.add(Exp.constant(string));
}
public FuncArgs(TableConstructor table) {
- this.exps = new ArrayList();
- this.exps.add( table );
+ this.exps = new ArrayList<>();
+ this.exps.add(table);
}
public void accept(Visitor visitor) {
diff --git a/src/jse/org/luaj/vm2/ast/FuncBody.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java
similarity index 92%
rename from src/jse/org/luaj/vm2/ast/FuncBody.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java
index 41d37ff3..8b4f2335 100644
--- a/src/jse/org/luaj/vm2/ast/FuncBody.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,14 +22,15 @@
package org.luaj.vm2.ast;
public class FuncBody extends SyntaxElement {
- public ParList parlist;
- public Block block;
+ public ParList parlist;
+ public Block block;
public NameScope scope;
public FuncBody(ParList parlist, Block block) {
- this.parlist = parlist!=null? parlist: ParList.EMPTY_PARLIST;
+ this.parlist = parlist != null? parlist: ParList.EMPTY_PARLIST;
this.block = block;
}
+
public void accept(Visitor visitor) {
visitor.visit(this);
}
diff --git a/src/jse/org/luaj/vm2/ast/FuncName.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java
similarity index 94%
rename from src/jse/org/luaj/vm2/ast/FuncName.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java
index e0f8cb90..1aaba111 100644
--- a/src/jse/org/luaj/vm2/ast/FuncName.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,24 +26,24 @@ import java.util.List;
public class FuncName extends SyntaxElement {
// example: a.b.c.d:e
-
+
// initial base name: "a"
public final Name name;
-
+
// intermediate field accesses: "b", "c", "d"
public List dots;
-
+
// optional final method name: "e"
public String method;
-
- public FuncName( String name ) {
+
+ public FuncName(String name) {
this.name = new Name(name);
}
-
+
public void adddot(String dot) {
- if ( dots == null )
- dots = new ArrayList();
+ if (dots == null)
+ dots = new ArrayList<>();
dots.add(dot);
}
-
+
}
diff --git a/src/jse/org/luaj/vm2/ast/Name.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java
similarity index 97%
rename from src/jse/org/luaj/vm2/ast/Name.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java
index 11b4acc2..b24d6461 100644
--- a/src/jse/org/luaj/vm2/ast/Name.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,10 +21,10 @@
******************************************************************************/
package org.luaj.vm2.ast;
-
public class Name {
public final String name;
- public Variable variable;
+ public Variable variable;
+
public Name(String name) {
this.name = name;
}
diff --git a/src/jse/org/luaj/vm2/ast/NameResolver.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/NameResolver.java
similarity index 67%
rename from src/jse/org/luaj/vm2/ast/NameResolver.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/NameResolver.java
index 73ea1ede..aef1e663 100644
--- a/src/jse/org/luaj/vm2/ast/NameResolver.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/NameResolver.java
@@ -13,10 +13,10 @@ import org.luaj.vm2.ast.Stat.LocalAssign;
import org.luaj.vm2.ast.Stat.LocalFuncDef;
import org.luaj.vm2.ast.Stat.NumericFor;
-/**
- * Visitor that resolves names to scopes.
- * Each Name is resolved to a NamedVarible, possibly in a NameScope
- * if it is a local, or in no named scope if it is a global.
+/**
+ * Visitor that resolves names to scopes. Each Name is resolved to a
+ * NamedVarible, possibly in a NameScope if it is a local, or in no named scope
+ * if it is a global.
*/
public class NameResolver extends Visitor {
@@ -25,20 +25,24 @@ public class NameResolver extends Visitor {
private void pushScope() {
scope = new NameScope(scope);
}
+
private void popScope() {
scope = scope.outerScope;
}
-
- public void visit(NameScope scope) {
- }
+ @Override
+ public void visit(NameScope scope) {
+ }
+
+ @Override
public void visit(Block block) {
pushScope();
block.scope = scope;
super.visit(block);
popScope();
}
-
+
+ @Override
public void visit(FuncBody body) {
pushScope();
scope.functionNestingCount++;
@@ -46,12 +50,14 @@ public class NameResolver extends Visitor {
super.visit(body);
popScope();
}
-
+
+ @Override
public void visit(LocalFuncDef stat) {
defineLocalVar(stat.name);
super.visit(stat);
}
+ @Override
public void visit(NumericFor stat) {
pushScope();
stat.scope = scope;
@@ -60,67 +66,73 @@ public class NameResolver extends Visitor {
popScope();
}
+ @Override
public void visit(GenericFor stat) {
pushScope();
stat.scope = scope;
- defineLocalVars( stat.names );
+ defineLocalVars(stat.names);
super.visit(stat);
popScope();
}
+ @Override
public void visit(NameExp exp) {
exp.name.variable = resolveNameReference(exp.name);
super.visit(exp);
}
-
+
+ @Override
public void visit(FuncDef stat) {
stat.name.name.variable = resolveNameReference(stat.name.name);
stat.name.name.variable.hasassignments = true;
super.visit(stat);
}
-
+
+ @Override
public void visit(Assign stat) {
super.visit(stat);
- for ( int i=0, n=stat.vars.size(); i0 && m 0 && m < n && stat.values.get(m-1).isvarargexp();
+ for (int i = 0; i < n && i < (isvarlist? m-1: m); i++)
+ if (stat.values.get(i) instanceof Constant)
+ stat.names.get(i).variable.initialValue = ((Constant) stat.values.get(i)).value;
+ if (!isvarlist)
+ for (int i = m; i < n; i++)
+ stat.names.get(i).variable.initialValue = LuaValue.NIL;
}
+ @Override
public void visit(ParList pars) {
- if ( pars.names != null )
+ if (pars.names != null)
defineLocalVars(pars.names);
- if ( pars.isvararg )
+ if (pars.isvararg)
scope.define("arg");
super.visit(pars);
}
-
+
protected void defineLocalVars(List names) {
- for ( int i=0, n=names.size(); i LUA_KEYWORDS = new HashSet();
-
- static {
- String[] k = new String[] {
- "and", "break", "do", "else", "elseif", "end",
- "false", "for", "function", "if", "in", "local",
- "nil", "not", "or", "repeat", "return",
- "then", "true", "until", "while" };
- for ( int i=0; i LUA_KEYWORDS = new HashSet<>();
+
+ static {
+ String[] k = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local",
+ "nil", "not", "or", "repeat", "return", "then", "true", "until", "while" };
+ for (String element : k)
+ LUA_KEYWORDS.add(element);
}
-
- public final Map namedVariables = new HashMap();
+
+ public final Map namedVariables = new HashMap<>();
public final NameScope outerScope;
public int functionNestingCount;
-
+
/** Construct default names scope */
public NameScope() {
this.outerScope = null;
this.functionNestingCount = 0;
}
-
- /** Construct name scope within another scope*/
+
+ /** Construct name scope within another scope */
public NameScope(NameScope outerScope) {
this.outerScope = outerScope;
- this.functionNestingCount = outerScope!=null? outerScope.functionNestingCount: 0;
+ this.functionNestingCount = outerScope != null? outerScope.functionNestingCount: 0;
}
-
- /** Look up a name. If it is a global name, then throw IllegalArgumentException. */
- public Variable find( String name ) throws IllegalArgumentException {
+
+ /**
+ * Look up a name. If it is a global name, then throw
+ * IllegalArgumentException.
+ */
+ public Variable find(String name) throws IllegalArgumentException {
validateIsNotKeyword(name);
- for ( NameScope n = this; n!=null; n=n.outerScope )
- if ( n.namedVariables.containsKey(name) )
- return (Variable)n.namedVariables.get(name);
+ for (NameScope n = this; n != null; n = n.outerScope)
+ if (n.namedVariables.containsKey(name))
+ return n.namedVariables.get(name);
Variable value = new Variable(name);
this.namedVariables.put(name, value);
return value;
}
-
- /** Define a name in this scope. If it is a global name, then throw IllegalArgumentException. */
- public Variable define( String name ) throws IllegalStateException, IllegalArgumentException {
+
+ /**
+ * Define a name in this scope. If it is a global name, then throw
+ * IllegalArgumentException.
+ */
+ public Variable define(String name) throws IllegalStateException, IllegalArgumentException {
validateIsNotKeyword(name);
Variable value = new Variable(name, this);
this.namedVariables.put(name, value);
return value;
}
-
+
private void validateIsNotKeyword(String name) {
- if ( LUA_KEYWORDS.contains(name) )
- throw new IllegalArgumentException("name is a keyword: '"+name+"'");
+ if (LUA_KEYWORDS.contains(name))
+ throw new IllegalArgumentException("name is a keyword: '" + name + "'");
}
}
diff --git a/src/jse/org/luaj/vm2/ast/ParList.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java
similarity index 89%
rename from src/jse/org/luaj/vm2/ast/ParList.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java
index 76044806..87281c31 100644
--- a/src/jse/org/luaj/vm2/ast/ParList.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,11 +25,11 @@ import java.util.ArrayList;
import java.util.List;
public class ParList extends SyntaxElement {
- public static final List EMPTY_NAMELIST = new ArrayList();
- public static final ParList EMPTY_PARLIST = new ParList(EMPTY_NAMELIST,false);
-
+ public static final List EMPTY_NAMELIST = new ArrayList<>();
+ public static final ParList EMPTY_PARLIST = new ParList(EMPTY_NAMELIST, false);
+
public final List names;
- public final boolean isvararg;
+ public final boolean isvararg;
public ParList(List names, boolean isvararg) {
this.names = names;
diff --git a/src/jse/org/luaj/vm2/ast/Stat.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java
similarity index 80%
rename from src/jse/org/luaj/vm2/ast/Stat.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java
index 275fdfeb..3dbd3636 100644
--- a/src/jse/org/luaj/vm2/ast/Stat.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,8 +25,7 @@ import java.util.List;
import org.luaj.vm2.ast.Exp.VarExp;
-abstract
-public class Stat extends SyntaxElement {
+abstract public class Stat extends SyntaxElement {
public abstract void accept(Visitor visitor);
public static Stat block(Block block) {
@@ -39,8 +38,8 @@ public class Stat extends SyntaxElement {
public static Stat repeatuntil(Block block, Exp exp) {
return new RepeatUntil(block, exp);
- }
-
+ }
+
public static Stat breakstat() {
return new Break();
}
@@ -50,7 +49,7 @@ public class Stat extends SyntaxElement {
}
public static Stat assignment(List vars, List exps) {
- return new Assign(vars,exps);
+ return new Assign(vars, exps);
}
public static Stat functioncall(Exp.FuncCall funccall) {
@@ -66,18 +65,19 @@ public class Stat extends SyntaxElement {
}
public static Stat functiondef(FuncName funcname, FuncBody funcbody) {
- return new FuncDef( funcname, funcbody );
+ return new FuncDef(funcname, funcbody);
}
public static Stat forgeneric(List names, List exps, Block block) {
- return new GenericFor(names, exps, block);
+ return new GenericFor(names, exps, block);
}
public static Stat localassignment(List names, List values) {
return new LocalAssign(names, values);
}
- public static Stat ifthenelse(Exp ifexp, Block ifblock, List elseifexps, List elseifblocks, Block elseblock) {
+ public static Stat ifthenelse(Exp ifexp, Block ifblock, List elseifexps, List elseifblocks,
+ Block elseblock) {
return new IfThenElse(ifexp, ifblock, elseifexps, elseifblocks, elseblock);
}
@@ -91,9 +91,12 @@ public class Stat extends SyntaxElement {
public static class Goto extends Stat {
public final String name;
+
public Goto(String name) {
this.name = name;
}
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@@ -101,9 +104,12 @@ public class Stat extends SyntaxElement {
public static class Label extends Stat {
public final String name;
+
public Label(String name) {
this.name = name;
}
+
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@@ -111,13 +117,14 @@ public class Stat extends SyntaxElement {
public static class Assign extends Stat {
public final List vars;
- public final List exps;
-
+ public final List exps;
+
public Assign(List vars, List exps) {
this.vars = vars;
this.exps = exps;
}
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@@ -125,111 +132,129 @@ public class Stat extends SyntaxElement {
}
public static class WhileDo extends Stat {
- public final Exp exp;
+ public final Exp exp;
public final Block block;
- public WhileDo( Exp exp, Block block ) {
+
+ public WhileDo(Exp exp, Block block) {
this.exp = exp;
this.block = block;
}
+
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
- }
-
+ }
+
public static class RepeatUntil extends Stat {
public final Block block;
- public final Exp exp;
- public RepeatUntil( Block block, Exp exp ) {
+ public final Exp exp;
+
+ public RepeatUntil(Block block, Exp exp) {
this.block = block;
this.exp = exp;
}
+
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class Break extends Stat {
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class Return extends Stat {
public final List values;
+
public Return(List values) {
this.values = values;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
-
+
public int nreturns() {
- int n = values!=null? values.size(): 0;
- if ( n>0 && ((Exp)values.get(n-1)).isvarargexp() )
+ int n = values != null? values.size(): 0;
+ if (n > 0 && values.get(n-1).isvarargexp())
n = -1;
- return n;
+ return n;
}
}
public static class FuncCallStat extends Stat {
public final Exp.FuncCall funccall;
+
public FuncCallStat(Exp.FuncCall funccall) {
this.funccall = funccall;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class LocalFuncDef extends Stat {
- public final Name name;
+ public final Name name;
public final FuncBody body;
+
public LocalFuncDef(String name, FuncBody body) {
this.name = new Name(name);
this.body = body;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class FuncDef extends Stat {
public final FuncName name;
public final FuncBody body;
+
public FuncDef(FuncName name, FuncBody body) {
this.name = name;
this.body = body;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class GenericFor extends Stat {
public List names;
- public List exps;
- public Block block;
- public NameScope scope;
+ public List exps;
+ public Block block;
+ public NameScope scope;
+
public GenericFor(List names, List exps, Block block) {
this.names = names;
this.exps = exps;
this.block = block;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class NumericFor extends Stat {
- public final Name name;
- public final Exp initial,limit,step;
+ public final Name name;
+ public final Exp initial, limit, step;
public final Block block;
- public NameScope scope;
+ public NameScope scope;
+
public NumericFor(String name, Exp initial, Exp limit, Exp step, Block block) {
this.name = new Name(name);
this.initial = initial;
@@ -238,32 +263,35 @@ public class Stat extends SyntaxElement {
this.block = block;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class LocalAssign extends Stat {
public final List names;
- public final List values;
+ public final List values;
+
public LocalAssign(List names, List values) {
this.names = names;
this.values = values;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
public static class IfThenElse extends Stat {
- public final Exp ifexp;
- public final Block ifblock;
- public final List elseifexps;
+ public final Exp ifexp;
+ public final Block ifblock;
+ public final List elseifexps;
public final List elseifblocks;
- public final Block elseblock;
- public IfThenElse(Exp ifexp, Block ifblock, List elseifexps,
- List elseifblocks, Block elseblock) {
+ public final Block elseblock;
+
+ public IfThenElse(Exp ifexp, Block ifblock, List elseifexps, List elseifblocks, Block elseblock) {
this.ifexp = ifexp;
this.ifblock = ifblock;
this.elseifexps = elseifexps;
@@ -271,8 +299,9 @@ public class Stat extends SyntaxElement {
this.elseblock = elseblock;
}
+ @Override
public void accept(Visitor visitor) {
- visitor.visit( this );
+ visitor.visit(this);
}
}
}
diff --git a/src/jse/org/luaj/vm2/ast/Str.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java
similarity index 67%
rename from src/jse/org/luaj/vm2/ast/Str.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java
index dd682291..db78662c 100644
--- a/src/jse/org/luaj/vm2/ast/Str.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java
@@ -10,7 +10,7 @@
*
* 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
@@ -27,65 +27,95 @@ import java.io.UnsupportedEncodingException;
import org.luaj.vm2.LuaString;
public class Str {
-
+
private Str() {}
-
+
public static LuaString quoteString(String image) {
String s = image.substring(1, image.length()-1);
byte[] bytes = unquote(s);
return LuaString.valueUsing(bytes);
}
-
+
public static LuaString charString(String image) {
String s = image.substring(1, image.length()-1);
byte[] bytes = unquote(s);
return LuaString.valueUsing(bytes);
}
-
+
public static LuaString longString(String image) {
int i = image.indexOf('[', image.indexOf('[')+1)+1;
- String s = image.substring(i,image.length()-i);
+ String s = image.substring(i, image.length()-i);
byte[] b = iso88591bytes(s);
return LuaString.valueUsing(b);
}
-
- public static byte[] iso88591bytes( String s ) {
+
+ public static byte[] iso88591bytes(String s) {
try {
return s.getBytes("ISO8859-1");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("ISO8859-1 not supported");
}
}
-
+
public static byte[] unquote(String s) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
char[] c = s.toCharArray();
int n = c.length;
- for ( int i=0; i='0' && c[i]<='9'; i++, j++ )
- d = d * 10 + (int) (c[i]-'0');
- baos.write( (byte) d );
+ for (int i = 0; i < n; i++) {
+ if (c[i] == '\\' && i < n) {
+ switch (c[++i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ int d = c[i++]-'0';
+ for (int j = 0; i < n && j < 2 && c[i] >= '0' && c[i] <= '9'; i++, j++)
+ d = d*10+c[i]-'0';
+ baos.write((byte) d);
--i;
continue;
- case 'a': baos.write( (byte) 7 ); continue;
- case 'b': baos.write( (byte) '\b' ); continue;
- case 'f': baos.write( (byte) '\f' ); continue;
- case 'n': baos.write( (byte) '\n' ); continue;
- case 'r': baos.write( (byte) '\r' ); continue;
- case 't': baos.write( (byte) '\t' ); continue;
- case 'v': baos.write( (byte) 11 ); continue;
- case '"': baos.write( (byte) '"' ); continue;
- case '\'': baos.write( (byte) '\'' ); continue;
- case '\\': baos.write( (byte) '\\' ); continue;
- default: baos.write( (byte) c[i] ); break;
+ case 'a':
+ baos.write((byte) 7);
+ continue;
+ case 'b':
+ baos.write((byte) '\b');
+ continue;
+ case 'f':
+ baos.write((byte) '\f');
+ continue;
+ case 'n':
+ baos.write((byte) '\n');
+ continue;
+ case 'r':
+ baos.write((byte) '\r');
+ continue;
+ case 't':
+ baos.write((byte) '\t');
+ continue;
+ case 'v':
+ baos.write((byte) 11);
+ continue;
+ case '"':
+ baos.write((byte) '"');
+ continue;
+ case '\'':
+ baos.write((byte) '\'');
+ continue;
+ case '\\':
+ baos.write((byte) '\\');
+ continue;
+ default:
+ baos.write((byte) c[i]);
+ break;
}
} else {
- baos.write( (byte) c[i] );
+ baos.write((byte) c[i]);
}
}
return baos.toByteArray();
diff --git a/src/jse/org/luaj/vm2/ast/SyntaxElement.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java
similarity index 94%
rename from src/jse/org/luaj/vm2/ast/SyntaxElement.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java
index 8cd790e6..767ec6c1 100644
--- a/src/jse/org/luaj/vm2/ast/SyntaxElement.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,17 +21,18 @@
******************************************************************************/
package org.luaj.vm2.ast;
-/** Base class for syntax elements of the parse tree that appear in source files.
- * The LuaParser class will fill these values out during parsing for use in
+/**
+ * Base class for syntax elements of the parse tree that appear in source files.
+ * The LuaParser class will fill these values out during parsing for use in
* syntax highlighting, for example.
*/
public class SyntaxElement {
/** The line number on which the element begins. */
public int beginLine;
-
+
/** The column at which the element begins. */
public short beginColumn;
-
+
/** The line number on which the element ends. */
public int endLine;
diff --git a/src/jse/org/luaj/vm2/ast/TableConstructor.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/TableConstructor.java
similarity index 99%
rename from src/jse/org/luaj/vm2/ast/TableConstructor.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/TableConstructor.java
index 69fd480b..dea98b82 100644
--- a/src/jse/org/luaj/vm2/ast/TableConstructor.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/TableConstructor.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,6 +26,7 @@ import java.util.List;
public class TableConstructor extends Exp {
public List fields;
+ @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
diff --git a/src/jse/org/luaj/vm2/ast/TableField.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java
similarity index 96%
rename from src/jse/org/luaj/vm2/ast/TableField.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java
index 2793f02d..0384fdf7 100644
--- a/src/jse/org/luaj/vm2/ast/TableField.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java
@@ -10,7 +10,7 @@
*
* 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
@@ -23,16 +23,16 @@ package org.luaj.vm2.ast;
public class TableField extends SyntaxElement {
- public final Exp index;
+ public final Exp index;
public final String name;
- public final Exp rhs;
-
+ public final Exp rhs;
+
public TableField(Exp index, String name, Exp rhs) {
this.index = index;
this.name = name;
this.rhs = rhs;
}
-
+
public static TableField keyedField(Exp index, Exp rhs) {
return new TableField(index, null, rhs);
}
diff --git a/src/jse/org/luaj/vm2/ast/Variable.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java
similarity index 78%
rename from src/jse/org/luaj/vm2/ast/Variable.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java
index 7405be42..cee1ddaf 100644
--- a/src/jse/org/luaj/vm2/ast/Variable.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java
@@ -10,7 +10,7 @@
*
* 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
@@ -23,40 +23,43 @@ package org.luaj.vm2.ast;
import org.luaj.vm2.LuaValue;
-/** Variable is created lua name scopes, and is a named, lua variable that
- * either refers to a lua local, global, or upvalue storage location.
+/**
+ * Variable is created lua name scopes, and is a named, lua variable that either
+ * refers to a lua local, global, or upvalue storage location.
*/
public class Variable {
-
+
/** The name as it appears in lua source code */
public final String name;
-
- /** The lua scope in which this variable is defined. */
+
+ /** The lua scope in which this variable is defined. */
public final NameScope definingScope;
-
+
/** true if this variable is an upvalue */
public boolean isupvalue;
-
+
/** true if there are assignments made to this variable */
public boolean hasassignments;
- /** When hasassignments == false, and the initial value is a constant, this is the initial value */
+ /**
+ * When hasassignments == false, and the initial value is a constant, this
+ * is the initial value
+ */
public LuaValue initialValue;
-
+
/** Global is named variable not associated with a defining scope */
public Variable(String name) {
this.name = name;
this.definingScope = null;
}
+
public Variable(String name, NameScope definingScope) {
- /** Local variable is defined in a particular scope. */
+ /** Local variable is defined in a particular scope. */
this.name = name;
this.definingScope = definingScope;
}
- public boolean isLocal() {
- return this.definingScope != null;
- }
- public boolean isConstant() {
- return ! hasassignments && initialValue != null;
- }
-}
\ No newline at end of file
+
+ public boolean isLocal() { return this.definingScope != null; }
+
+ public boolean isConstant() { return !hasassignments && initialValue != null; }
+}
diff --git a/src/jse/org/luaj/vm2/ast/Visitor.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java
similarity index 80%
rename from src/jse/org/luaj/vm2/ast/Visitor.java
rename to luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java
index 8f49a566..d3da74ac 100644
--- a/src/jse/org/luaj/vm2/ast/Visitor.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,155 +26,192 @@ import java.util.List;
import org.luaj.vm2.ast.Exp.VarExp;
abstract public class Visitor {
- public void visit(Chunk chunk) {
- chunk.block.accept(this);
- };
+ public void visit(Chunk chunk) {
+ chunk.block.accept(this);
+ }
+
public void visit(Block block) {
visit(block.scope);
- if ( block.stats != null )
- for ( int i=0, n=block.stats.size(); i vars) {
- if ( vars != null )
- for ( int i=0, n=vars.size(); i exps) {
- if ( exps != null )
- for ( int i=0, n=exps.size(); i names) {
- if ( names != null )
- for ( int i=0, n=names.size(); i
- * This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
- * but can also be used directly when working with Java/lua bindings.
+ * This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
+ * but can also be used directly when working with Java/lua bindings.
*
- * To coerce scalar types, the various, generally the {@code valueOf(type)} methods
- * on {@link LuaValue} may be used:
+ * To coerce scalar types, the various, generally the {@code valueOf(type)}
+ * methods on {@link LuaValue} may be used:
*
- * To coerce arrays of objects and lists, the {@code listOf(..)} and {@code tableOf(...)} methods
- * on {@link LuaValue} may be used:
+ * To coerce arrays of objects and lists, the {@code listOf(..)} and
+ * {@code tableOf(...)} methods on {@link LuaValue} may be used:
*
- * The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and dimesioning
- * of the argument and tries to guess the best fit for corrsponding lua scalar,
- * table, or table of tables.
- *
+ * The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and
+ * dimesioning of the argument and tries to guess the best fit for corrsponding
+ * lua scalar, table, or table of tables.
+ *
* @see CoerceJavaToLua#coerce(Object)
* @see org.luaj.vm2.lib.jse.LuajavaLib
*/
public class CoerceJavaToLua {
- static interface Coercion {
- public LuaValue coerce( Object javaValue );
- };
-
+ interface Coercion {
+ LuaValue coerce(Object javaValue);
+ }
+
private static final class BoolCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
Boolean b = (Boolean) javaValue;
return b.booleanValue()? LuaValue.TRUE: LuaValue.FALSE;
}
}
-
+
private static final class IntCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
Number n = (Number) javaValue;
- return LuaInteger.valueOf( n.intValue() );
+ return LuaInteger.valueOf(n.intValue());
}
}
private static final class CharCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
Character c = (Character) javaValue;
- return LuaInteger.valueOf( c.charValue() );
+ return LuaInteger.valueOf(c.charValue());
}
}
private static final class DoubleCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
Number n = (Number) javaValue;
- return LuaDouble.valueOf( n.doubleValue() );
+ return LuaDouble.valueOf(n.doubleValue());
}
}
private static final class StringCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
- return LuaString.valueOf( javaValue.toString() );
+ @Override
+ public LuaValue coerce(Object javaValue) {
+ return LuaString.valueOf(javaValue.toString());
}
}
private static final class BytesCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
return LuaValue.valueOf((byte[]) javaValue);
}
}
private static final class ClassCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
return JavaClass.forClass((Class) javaValue);
}
}
private static final class InstanceCoercion implements Coercion {
+ @Override
public LuaValue coerce(Object javaValue) {
return new JavaInstance(javaValue);
}
}
private static final class ArrayCoercion implements Coercion {
+ @Override
public LuaValue coerce(Object javaValue) {
- // should be userdata?
+ // should be userdata?
return new JavaArray(javaValue);
}
}
private static final class LuaCoercion implements Coercion {
- public LuaValue coerce( Object javaValue ) {
+ @Override
+ public LuaValue coerce(Object javaValue) {
return (LuaValue) javaValue;
}
}
-
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
-
+
static {
- Coercion boolCoercion = new BoolCoercion() ;
- Coercion intCoercion = new IntCoercion() ;
- Coercion charCoercion = new CharCoercion() ;
- Coercion doubleCoercion = new DoubleCoercion() ;
- Coercion stringCoercion = new StringCoercion() ;
- Coercion bytesCoercion = new BytesCoercion() ;
- Coercion classCoercion = new ClassCoercion() ;
- COERCIONS.put( Boolean.class, boolCoercion );
- COERCIONS.put( Byte.class, intCoercion );
- COERCIONS.put( Character.class, charCoercion );
- COERCIONS.put( Short.class, intCoercion );
- COERCIONS.put( Integer.class, intCoercion );
- COERCIONS.put( Long.class, doubleCoercion );
- COERCIONS.put( Float.class, doubleCoercion );
- COERCIONS.put( Double.class, doubleCoercion );
- COERCIONS.put( String.class, stringCoercion );
- COERCIONS.put( byte[].class, bytesCoercion );
- COERCIONS.put( Class.class, classCoercion );
+ Coercion boolCoercion = new BoolCoercion();
+ Coercion intCoercion = new IntCoercion();
+ Coercion charCoercion = new CharCoercion();
+ Coercion doubleCoercion = new DoubleCoercion();
+ Coercion stringCoercion = new StringCoercion();
+ Coercion bytesCoercion = new BytesCoercion();
+ Coercion classCoercion = new ClassCoercion();
+ COERCIONS.put(Boolean.class, boolCoercion);
+ COERCIONS.put(Byte.class, intCoercion);
+ COERCIONS.put(Character.class, charCoercion);
+ COERCIONS.put(Short.class, intCoercion);
+ COERCIONS.put(Integer.class, intCoercion);
+ COERCIONS.put(Long.class, doubleCoercion);
+ COERCIONS.put(Float.class, doubleCoercion);
+ COERCIONS.put(Double.class, doubleCoercion);
+ COERCIONS.put(String.class, stringCoercion);
+ COERCIONS.put(byte[].class, bytesCoercion);
+ COERCIONS.put(Class.class, classCoercion);
}
/**
- * Coerse a Java object to a corresponding lua value.
+ * Coerse a Java object to a corresponding lua value.
*
- * Integral types {@code boolean}, {@code byte}, {@code char}, and {@code int}
- * will become {@link LuaInteger};
- * {@code long}, {@code float}, and {@code double} will become {@link LuaDouble};
- * {@code String} and {@code byte[]} will become {@link LuaString};
- * types inheriting from {@link LuaValue} will be returned without coercion;
- * other types will become {@link LuaUserdata}.
+ * Integral types {@code boolean}, {@code byte}, {@code char}, and
+ * {@code int} will become {@link LuaInteger}; {@code long}, {@code float},
+ * and {@code double} will become {@link LuaDouble}; {@code String} and
+ * {@code byte[]} will become {@link LuaString}; types inheriting from
+ * {@link LuaValue} will be returned without coercion; other types will
+ * become {@link LuaUserdata}.
+ *
* @param o Java object needing conversion
- * @return {@link LuaValue} corresponding to the supplied Java value.
+ * @return {@link LuaValue} corresponding to the supplied Java value.
* @see LuaValue
* @see LuaInteger
* @see LuaDouble
@@ -175,22 +185,20 @@ public class CoerceJavaToLua {
* @see LuaUserdata
*/
public static LuaValue coerce(Object o) {
- if ( o == null )
+ if (o == null)
return LuaValue.NIL;
Class clazz = o.getClass();
- Coercion c = (Coercion) COERCIONS.get( clazz );
- if ( c == null ) {
- c = clazz.isArray()? arrayCoercion:
- o instanceof LuaValue ? luaCoercion:
- instanceCoercion;
- COERCIONS.put( clazz, c );
+ Coercion c = (Coercion) COERCIONS.get(clazz);
+ if (c == null) {
+ c = clazz.isArray()? arrayCoercion: o instanceof LuaValue? luaCoercion: instanceCoercion;
+ COERCIONS.put(clazz, c);
}
return c.coerce(o);
}
static final Coercion instanceCoercion = new InstanceCoercion();
-
- static final Coercion arrayCoercion = new ArrayCoercion();
- static final Coercion luaCoercion = new LuaCoercion() ;
+ static final Coercion arrayCoercion = new ArrayCoercion();
+
+ static final Coercion luaCoercion = new LuaCoercion();
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
similarity index 52%
rename from src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
index c658aacc..c413f16d 100644
--- a/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java
@@ -10,7 +10,7 @@
*
* 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
@@ -31,13 +31,13 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
/**
- * Helper class to coerce values from lua to Java within the luajava library.
+ * Helper class to coerce values from lua to Java within the luajava library.
*
- * This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
- * but can also be used directly when working with Java/lua bindings.
+ * This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
+ * but can also be used directly when working with Java/lua bindings.
*
- * To coerce to specific Java values, generally the {@code toType()} methods
- * on {@link LuaValue} may be used:
+ * To coerce to specific Java values, generally the {@code toType()} methods on
+ * {@link LuaValue} may be used:
*
- * For data in lua tables, the various methods on {@link LuaTable} can be used directly
- * to convert data to something more useful.
- *
+ * For data in lua tables, the various methods on {@link LuaTable} can be used
+ * directly to convert data to something more useful.
+ *
* @see org.luaj.vm2.lib.jse.LuajavaLib
* @see CoerceJavaToLua
*/
public class CoerceLuaToJava {
- static int SCORE_NULL_VALUE = 0x10;
- static int SCORE_WRONG_TYPE = 0x100;
- static int SCORE_UNCOERCIBLE = 0x10000;
-
- static interface Coercion {
- public int score( LuaValue value );
- public Object coerce( LuaValue value );
- };
+ static int SCORE_NULL_VALUE = 0x10;
+ static int SCORE_WRONG_TYPE = 0x100;
+ static int SCORE_UNCOERCIBLE = 0x10000;
- /**
+ interface Coercion {
+ int score(LuaValue value);
+
+ Object coerce(LuaValue value);
+ }
+
+ /**
* Coerce a LuaValue value to a specified java class
+ *
* @param value LuaValue to coerce
* @param clazz Class to coerce into
- * @return Object of type clazz (or a subclass) with the corresponding value.
+ * @return Object of type clazz (or a subclass) with the corresponding
+ * value.
*/
public static Object coerce(LuaValue value, Class clazz) {
return getCoercion(clazz).coerce(value);
}
-
+
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
-
+
static final class BoolCoercion implements Coercion {
+ @Override
public String toString() {
return "BoolCoercion()";
}
- public int score( LuaValue value ) {
- switch ( value.type() ) {
+
+ @Override
+ public int score(LuaValue value) {
+ switch (value.type()) {
case LuaValue.TBOOLEAN:
return 0;
}
return 1;
}
+ @Override
public Object coerce(LuaValue value) {
return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
}
}
static final class NumericCoercion implements Coercion {
- static final int TARGET_TYPE_BYTE = 0;
- static final int TARGET_TYPE_CHAR = 1;
- static final int TARGET_TYPE_SHORT = 2;
- static final int TARGET_TYPE_INT = 3;
- static final int TARGET_TYPE_LONG = 4;
- static final int TARGET_TYPE_FLOAT = 5;
- static final int TARGET_TYPE_DOUBLE = 6;
- static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" };
- final int targetType;
+ static final int TARGET_TYPE_BYTE = 0;
+ static final int TARGET_TYPE_CHAR = 1;
+ static final int TARGET_TYPE_SHORT = 2;
+ static final int TARGET_TYPE_INT = 3;
+ static final int TARGET_TYPE_LONG = 4;
+ static final int TARGET_TYPE_FLOAT = 5;
+ static final int TARGET_TYPE_DOUBLE = 6;
+ static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" };
+ final int targetType;
+
+ @Override
public String toString() {
- return "NumericCoercion("+TYPE_NAMES[targetType]+")";
+ return "NumericCoercion(" + TYPE_NAMES[targetType] + ")";
}
+
NumericCoercion(int targetType) {
this.targetType = targetType;
}
- public int score( LuaValue value ) {
+
+ @Override
+ public int score(LuaValue value) {
int fromStringPenalty = 0;
- if ( value.type() == LuaValue.TSTRING ) {
+ if (value.type() == LuaValue.TSTRING) {
value = value.tonumber();
- if ( value.isnil() ) {
+ if (value.isnil()) {
return SCORE_UNCOERCIBLE;
}
fromStringPenalty = 4;
}
- if ( value.isint() ) {
- switch ( targetType ) {
+ if (value.isint()) {
+ switch (targetType) {
case TARGET_TYPE_BYTE: {
int i = value.toint();
- return fromStringPenalty + ((i==(byte)i)? 0: SCORE_WRONG_TYPE);
+ return fromStringPenalty+(i == (byte) i? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_CHAR: {
int i = value.toint();
- return fromStringPenalty + ((i==(byte)i)? 1: (i==(char)i)? 0: SCORE_WRONG_TYPE);
+ return fromStringPenalty+(i == (byte) i? 1: i == (char) i? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_SHORT: {
int i = value.toint();
- return fromStringPenalty +
- ((i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE);
+ return fromStringPenalty+(i == (byte) i? 1: i == (short) i? 0: SCORE_WRONG_TYPE);
}
- case TARGET_TYPE_INT: {
+ case TARGET_TYPE_INT: {
int i = value.toint();
- return fromStringPenalty +
- ((i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0);
+ return fromStringPenalty+(i == (byte) i? 2: i == (char) i || i == (short) i? 1: 0);
}
- case TARGET_TYPE_FLOAT: return fromStringPenalty + 1;
- case TARGET_TYPE_LONG: return fromStringPenalty + 1;
- case TARGET_TYPE_DOUBLE: return fromStringPenalty + 2;
- default: return SCORE_WRONG_TYPE;
+ case TARGET_TYPE_FLOAT:
+ return fromStringPenalty+1;
+ case TARGET_TYPE_LONG:
+ return fromStringPenalty+1;
+ case TARGET_TYPE_DOUBLE:
+ return fromStringPenalty+2;
+ default:
+ return SCORE_WRONG_TYPE;
}
- } else if ( value.isnumber() ) {
- switch ( targetType ) {
- case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE;
- case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE;
- case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE;
- case TARGET_TYPE_INT: return SCORE_WRONG_TYPE;
+ } else if (value.isnumber()) {
+ switch (targetType) {
+ case TARGET_TYPE_BYTE:
+ return SCORE_WRONG_TYPE;
+ case TARGET_TYPE_CHAR:
+ return SCORE_WRONG_TYPE;
+ case TARGET_TYPE_SHORT:
+ return SCORE_WRONG_TYPE;
+ case TARGET_TYPE_INT:
+ return SCORE_WRONG_TYPE;
case TARGET_TYPE_LONG: {
double d = value.todouble();
- return fromStringPenalty + ((d==(long)d)? 0: SCORE_WRONG_TYPE);
+ return fromStringPenalty+(d == (long) d? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_FLOAT: {
double d = value.todouble();
- return fromStringPenalty + ((d==(float)d)? 0: SCORE_WRONG_TYPE);
+ return fromStringPenalty+(d == (float) d? 0: SCORE_WRONG_TYPE);
}
case TARGET_TYPE_DOUBLE: {
double d = value.todouble();
- return fromStringPenalty + (((d==(long)d) || (d==(float)d))? 1: 0);
+ return fromStringPenalty+(d == (long) d || d == (float) d? 1: 0);
}
- default: return SCORE_WRONG_TYPE;
+ default:
+ return SCORE_WRONG_TYPE;
}
} else {
return SCORE_UNCOERCIBLE;
}
}
+ @Override
public Object coerce(LuaValue value) {
- switch ( targetType ) {
- case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() );
- case TARGET_TYPE_CHAR: return new Character( (char) value.toint() );
- case TARGET_TYPE_SHORT: return new Short( (short) value.toint() );
- case TARGET_TYPE_INT: return new Integer( (int) value.toint() );
- case TARGET_TYPE_LONG: return new Long( (long) value.todouble() );
- case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() );
- case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() );
- default: return null;
+ switch (targetType) {
+ case TARGET_TYPE_BYTE:
+ return Byte.valueOf((byte) value.toint());
+ case TARGET_TYPE_CHAR:
+ return Character.valueOf((char) value.toint());
+ case TARGET_TYPE_SHORT:
+ return Short.valueOf((short) value.toint());
+ case TARGET_TYPE_INT:
+ return Integer.valueOf(value.toint());
+ case TARGET_TYPE_LONG:
+ return Long.valueOf((long) value.todouble());
+ case TARGET_TYPE_FLOAT:
+ return Float.valueOf((float) value.todouble());
+ case TARGET_TYPE_DOUBLE:
+ return Double.valueOf(value.todouble());
+ default:
+ return null;
}
}
}
static final class StringCoercion implements Coercion {
public static final int TARGET_TYPE_STRING = 0;
- public static final int TARGET_TYPE_BYTES = 1;
- final int targetType;
+ public static final int TARGET_TYPE_BYTES = 1;
+ final int targetType;
+
public StringCoercion(int targetType) {
this.targetType = targetType;
}
+
+ @Override
public String toString() {
- return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")";
+ return "StringCoercion(" + (targetType == TARGET_TYPE_STRING? "String": "byte[]") + ")";
}
+
+ @Override
public int score(LuaValue value) {
- switch ( value.type() ) {
+ switch (value.type()) {
case LuaValue.TSTRING:
- return value.checkstring().isValidUtf8()?
- (targetType==TARGET_TYPE_STRING? 0: 1):
- (targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE);
+ return value.checkstring().isValidUtf8()? targetType == TARGET_TYPE_STRING? 0: 1
+ : targetType == TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE;
case LuaValue.TNIL:
return SCORE_NULL_VALUE;
default:
return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE;
}
}
+
+ @Override
public Object coerce(LuaValue value) {
- if ( value.isnil() )
+ if (value.isnil())
return null;
- if ( targetType == TARGET_TYPE_STRING )
+ if (targetType == TARGET_TYPE_STRING)
return value.tojstring();
LuaString s = value.checkstring();
byte[] b = new byte[s.m_length];
@@ -221,33 +255,40 @@ public class CoerceLuaToJava {
}
static final class ArrayCoercion implements Coercion {
- final Class componentType;
+ final Class componentType;
final Coercion componentCoercion;
+
public ArrayCoercion(Class componentType) {
this.componentType = componentType;
this.componentCoercion = getCoercion(componentType);
}
+
+ @Override
public String toString() {
- return "ArrayCoercion("+componentType.getName()+")";
+ return "ArrayCoercion(" + componentType.getName() + ")";
}
+
+ @Override
public int score(LuaValue value) {
- switch ( value.type() ) {
+ switch (value.type()) {
case LuaValue.TTABLE:
- return value.length()==0? 0: componentCoercion.score( value.get(1) );
+ return value.length() == 0? 0: componentCoercion.score(value.get(1));
case LuaValue.TUSERDATA:
- return inheritanceLevels( componentType, value.touserdata().getClass().getComponentType() );
+ return inheritanceLevels(componentType, value.touserdata().getClass().getComponentType());
case LuaValue.TNIL:
return SCORE_NULL_VALUE;
- default:
+ default:
return SCORE_UNCOERCIBLE;
}
}
+
+ @Override
public Object coerce(LuaValue value) {
- switch ( value.type() ) {
+ switch (value.type()) {
case LuaValue.TTABLE: {
int n = value.length();
Object a = Array.newInstance(componentType, n);
- for ( int i=0; i
* Can get elements by their integer key index, as well as the length.
*
- * This class is not used directly.
- * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
- * when an array is supplied.
+ * This class is not used directly. It is returned by calls to
+ * {@link CoerceJavaToLua#coerce(Object)} when an array is supplied.
+ *
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaArray extends LuaUserdata {
private static final class LenFunction extends OneArgFunction {
+ @Override
public LuaValue call(LuaValue u) {
- return LuaValue.valueOf(Array.getLength(((LuaUserdata)u).m_instance));
+ return LuaValue.valueOf(Array.getLength(((LuaUserdata) u).m_instance));
}
}
static final LuaValue LENGTH = valueOf("length");
-
+
static final LuaTable array_metatable;
static {
array_metatable = new LuaTable();
array_metatable.rawset(LuaValue.LEN, new LenFunction());
}
-
+
JavaArray(Object instance) {
super(instance);
setmetatable(array_metatable);
}
-
+
+ @Override
public LuaValue get(LuaValue key) {
- if ( key.equals(LENGTH) )
+ if (key.equals(LENGTH))
return valueOf(Array.getLength(m_instance));
- if ( key.isint() ) {
- int i = key.toint() - 1;
- return i>=0 && i= 0 && i < Array.getLength(m_instance)
+ ? CoerceJavaToLua.coerce(Array.get(m_instance, key.toint()-1))
+ : NIL;
}
return super.get(key);
}
+ @Override
public void set(LuaValue key, LuaValue value) {
- if ( key.isint() ) {
- int i = key.toint() - 1;
- if ( i>=0 && i= 0 && i < Array.getLength(m_instance))
+ Array.set(m_instance, i, CoerceLuaToJava.coerce(value, m_instance.getClass().getComponentType()));
+ else if (m_metatable == null || !settable(this, key, value))
+ error("array index out of bounds");
+ } else
super.set(key, value);
- }
+ }
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/JavaClass.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java
similarity index 68%
rename from src/jse/org/luaj/vm2/lib/jse/JavaClass.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java
index 553c8e73..efe45319 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JavaClass.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java
@@ -10,7 +10,7 @@
*
* 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
@@ -38,11 +38,11 @@ import org.luaj.vm2.LuaValue;
/**
* LuaValue that represents a Java class.
*
- * Will respond to get() and set() by returning field values, or java methods.
+ * Will respond to get() and set() by returning field values, or java methods.
*
- * This class is not used directly.
- * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
- * when a Class is supplied.
+ * This class is not used directly. It is returned by calls to
+ * {@link CoerceJavaToLua#coerce(Object)} when a Class is supplied.
+ *
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
@@ -51,34 +51,34 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
static final Map classes = Collections.synchronizedMap(new HashMap());
static final LuaValue NEW = valueOf("new");
-
+
Map fields;
Map methods;
Map innerclasses;
-
+
static JavaClass forClass(Class c) {
JavaClass j = (JavaClass) classes.get(c);
- if ( j == null )
- classes.put( c, j = new JavaClass(c) );
+ if (j == null)
+ classes.put(c, j = new JavaClass(c));
return j;
}
-
+
JavaClass(Class c) {
super(c);
this.jclass = this;
}
+ @Override
public LuaValue coerce(Object javaValue) {
return this;
}
-
+
Field getField(LuaValue key) {
- if ( fields == null ) {
+ if (fields == null) {
Map m = new HashMap();
- Field[] f = ((Class)m_instance).getFields();
- for ( int i=0; i
- * May be called with arguments to return a JavaInstance
- * created by calling the constructor.
+ * May be called with arguments to return a JavaInstance created by calling the
+ * constructor.
*
- * This class is not used directly.
- * It is returned by calls to {@link JavaClass#new(LuaValue key)}
- * when the value of key is "new".
+ * This class is not used directly. It is returned by calls to
+ * {@link JavaClass#new(LuaValue key)} when the value of key is "new".
+ *
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaConstructor extends JavaMember {
static final Map constructors = Collections.synchronizedMap(new HashMap());
-
+
static JavaConstructor forConstructor(Constructor c) {
JavaConstructor j = (JavaConstructor) constructors.get(c);
- if ( j == null )
- constructors.put( c, j = new JavaConstructor(c) );
+ if (j == null)
+ constructors.put(c, j = new JavaConstructor(c));
return j;
}
-
+
public static LuaValue forConstructors(JavaConstructor[] array) {
return new Overload(array);
}
final Constructor constructor;
-
+
private JavaConstructor(Constructor c) {
- super( c.getParameterTypes(), c.getModifiers() );
+ super(c.getParameterTypes(), c.getModifiers());
this.constructor = c;
}
-
+
+ @Override
public Varargs invoke(Varargs args) {
Object[] a = convertArgs(args);
try {
- return CoerceJavaToLua.coerce( constructor.newInstance(a) );
+ return CoerceJavaToLua.coerce(constructor.newInstance(a));
} catch (InvocationTargetException e) {
throw new LuaError(e.getTargetException());
} catch (Exception e) {
- return LuaValue.error("coercion error "+e);
+ return LuaValue.error("coercion error " + e);
}
}
@@ -82,33 +83,35 @@ class JavaConstructor extends JavaMember {
*
* On invocation, will pick the best method from the list, and invoke it.
*
- * This class is not used directly.
- * It is returned by calls to calls to {@link JavaClass#get(LuaValue key)}
- * when key is "new" and there is more than one public constructor.
+ * This class is not used directly. It is returned by calls to calls to
+ * {@link JavaClass#get(LuaValue key)} when key is "new" and there is more
+ * than one public constructor.
*/
static class Overload extends VarArgFunction {
- final JavaConstructor[] constructors;
+ final JavaConstructor[] constructors;
+
public Overload(JavaConstructor[] c) {
this.constructors = c;
}
+ @Override
public Varargs invoke(Varargs args) {
JavaConstructor best = null;
int score = CoerceLuaToJava.SCORE_UNCOERCIBLE;
- for ( int i=0; i
- * Will respond to get() and set() by returning field values or methods.
+ * Will respond to get() and set() by returning field values or methods.
*
- * This class is not used directly.
- * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
- * when a subclass of Object is supplied.
+ * This class is not used directly. It is returned by calls to
+ * {@link CoerceJavaToLua#coerce(Object)} when a subclass of Object is supplied.
+ *
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaInstance extends LuaUserdata {
JavaClass jclass;
-
+
JavaInstance(Object instance) {
super(instance);
}
+ @Override
public LuaValue get(LuaValue key) {
- if ( jclass == null )
+ if (jclass == null)
jclass = JavaClass.forClass(m_instance.getClass());
Field f = jclass.getField(key);
- if ( f != null )
+ if (f != null)
try {
return CoerceJavaToLua.coerce(f.get(m_instance));
} catch (Exception e) {
throw new LuaError(e);
}
LuaValue m = jclass.getMethod(key);
- if ( m != null )
+ if (m != null)
return m;
Class c = jclass.getInnerClass(key);
- if ( c != null )
+ if (c != null)
return JavaClass.forClass(c);
return super.get(key);
}
+ @Override
public void set(LuaValue key, LuaValue value) {
- if ( jclass == null )
+ if (jclass == null)
jclass = JavaClass.forClass(m_instance.getClass());
Field f = jclass.getField(key);
- if ( f != null )
+ if (f != null)
try {
f.set(m_instance, CoerceLuaToJava.coerce(value, f.getType()));
return;
@@ -77,6 +79,6 @@ class JavaInstance extends LuaUserdata {
throw new LuaError(e);
}
super.set(key, value);
- }
-
+ }
+
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/JavaMember.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java
similarity index 64%
rename from src/jse/org/luaj/vm2/lib/jse/JavaMember.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java
index e4e9b7ed..f63e01c1 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JavaMember.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java
@@ -10,7 +10,7 @@
*
* 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
@@ -28,56 +28,56 @@ import org.luaj.vm2.lib.jse.CoerceLuaToJava.Coercion;
/**
* Java method or constructor.
*
- * Primarily handles argument coercion for parameter lists including scoring of compatibility and
- * java varargs handling.
+ * Primarily handles argument coercion for parameter lists including scoring of
+ * compatibility and java varargs handling.
*
- * This class is not used directly.
- * It is an abstract base class for {@link JavaConstructor} and {@link JavaMethod}.
+ * This class is not used directly. It is an abstract base class for
+ * {@link JavaConstructor} and {@link JavaMethod}.
+ *
* @see JavaConstructor
* @see JavaMethod
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
-abstract
-class JavaMember extends VarArgFunction {
-
+abstract class JavaMember extends VarArgFunction {
+
static final int METHOD_MODIFIERS_VARARGS = 0x80;
final Coercion[] fixedargs;
- final Coercion varargs;
-
+ final Coercion varargs;
+
protected JavaMember(Class[] params, int modifiers) {
- boolean isvarargs = ((modifiers & METHOD_MODIFIERS_VARARGS) != 0);
+ boolean isvarargs = (modifiers & METHOD_MODIFIERS_VARARGS) != 0;
fixedargs = new CoerceLuaToJava.Coercion[isvarargs? params.length-1: params.length];
- for ( int i=0; ifixedargs.length? CoerceLuaToJava.SCORE_WRONG_TYPE * (n-fixedargs.length): 0;
- for ( int j=0; j fixedargs.length? CoerceLuaToJava.SCORE_WRONG_TYPE*(n-fixedargs.length): 0;
+ for (int j = 0; j < fixedargs.length; j++)
+ s += fixedargs[j].score(args.arg(j+1));
+ if (varargs != null)
+ for (int k = fixedargs.length; k < n; k++)
+ s += varargs.score(args.arg(k+1));
return s;
}
-
+
protected Object[] convertArgs(Varargs args) {
Object[] a;
- if ( varargs == null ) {
+ if (varargs == null) {
a = new Object[fixedargs.length];
- for ( int i=0; i
- * Can be invoked via call(LuaValue...) and related methods.
+ * Can be invoked via call(LuaValue...) and related methods.
*
- * This class is not used directly.
- * It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)}
- * when a method is named.
+ * This class is not used directly. It is returned by calls to calls to
+ * {@link JavaInstance#get(LuaValue key)} when a method is named.
+ *
* @see CoerceJavaToLua
* @see CoerceLuaToJava
*/
class JavaMethod extends JavaMember {
static final Map methods = Collections.synchronizedMap(new HashMap());
-
+
static JavaMethod forMethod(Method m) {
JavaMethod j = (JavaMethod) methods.get(m);
- if ( j == null )
- methods.put( m, j = new JavaMethod(m) );
+ if (j == null)
+ methods.put(m, j = new JavaMethod(m));
return j;
}
-
+
static LuaFunction forMethods(JavaMethod[] m) {
return new Overload(m);
}
-
+
final Method method;
-
+
private JavaMethod(Method m) {
- super( m.getParameterTypes(), m.getModifiers() );
+ super(m.getParameterTypes(), m.getModifiers());
this.method = m;
try {
if (!m.isAccessible())
@@ -70,70 +70,80 @@ class JavaMethod extends JavaMember {
}
}
+ @Override
public LuaValue call() {
return error("method cannot be called without instance");
}
+ @Override
public LuaValue call(LuaValue arg) {
return invokeMethod(arg.checkuserdata(), LuaValue.NONE);
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return invokeMethod(arg1.checkuserdata(), arg2);
}
-
+
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return invokeMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3));
}
-
+
+ @Override
public Varargs invoke(Varargs args) {
return invokeMethod(args.checkuserdata(1), args.subargs(2));
}
-
+
LuaValue invokeMethod(Object instance, Varargs args) {
Object[] a = convertArgs(args);
try {
- return CoerceJavaToLua.coerce( method.invoke(instance, a) );
+ return CoerceJavaToLua.coerce(method.invoke(instance, a));
} catch (InvocationTargetException e) {
throw new LuaError(e.getTargetException());
} catch (Exception e) {
- return LuaValue.error("coercion error "+e);
+ return LuaValue.error("coercion error " + e);
}
}
-
+
/**
* LuaValue that represents an overloaded Java method.
*
* On invocation, will pick the best method from the list, and invoke it.
*
- * This class is not used directly.
- * It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)}
- * when an overloaded method is named.
+ * This class is not used directly. It is returned by calls to calls to
+ * {@link JavaInstance#get(LuaValue key)} when an overloaded method is
+ * named.
*/
static class Overload extends LuaFunction {
final JavaMethod[] methods;
-
+
Overload(JavaMethod[] methods) {
this.methods = methods;
}
+ @Override
public LuaValue call() {
return error("method cannot be called without instance");
}
+ @Override
public LuaValue call(LuaValue arg) {
return invokeBestMethod(arg.checkuserdata(), LuaValue.NONE);
}
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return invokeBestMethod(arg1.checkuserdata(), arg2);
}
-
+
+ @Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return invokeBestMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3));
}
-
+
+ @Override
public Varargs invoke(Varargs args) {
return invokeBestMethod(args.checkuserdata(1), args.subargs(2));
}
@@ -141,20 +151,20 @@ class JavaMethod extends JavaMember {
private LuaValue invokeBestMethod(Object instance, Varargs args) {
JavaMethod best = null;
int score = CoerceLuaToJava.SCORE_UNCOERCIBLE;
- for ( int i=0; i
- * Since JME has no file system by default, {@link BaseLib} implements
- * {@link ResourceFinder} using {@link Class#getResource(String)}.
- * The {@link org.luaj.vm2.lib.jse.JseBaseLib} implements {@link Globals#finder} by scanning the current directory
- * first, then falling back to {@link Class#getResource(String)} if that fails.
- * Otherwise, the behavior is the same as that of {@link BaseLib}.
- *
- * Typically, this library is included as part of a call to
+ * Since JME has no file system by default, {@link BaseLib} implements
+ * {@link ResourceFinder} using {@link Class#getResource(String)}. The
+ * {@link org.luaj.vm2.lib.jse.JseBaseLib} implements {@link Globals#finder} by
+ * scanning the current directory first, then falling back to
+ * {@link Class#getResource(String)} if that fails. Otherwise, the behavior is
+ * the same as that of {@link BaseLib}.
+ *
+ * Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
- *
- * For special cases where the smallest possible footprint is desired,
- * a minimal set of libraries could be loaded
- * directly via {@link Globals#load(LuaValue)} using code such as:
- *
However, other libraries such as PackageLib are not loaded in this case.
+ * For special cases where the smallest possible footprint is desired, a minimal
+ * set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
+ * using code such as:
+ *
+ *
+ * However, other libraries such as PackageLib are not loaded in this
+ * case.
*
* This is a direct port of the corresponding library in C.
+ *
* @see Globals
* @see BaseLib
* @see ResourceFinder
@@ -68,49 +81,50 @@ import org.luaj.vm2.lib.ResourceFinder;
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 Base Lib Reference
+ * @see Lua 5.2 Base Lib
+ * Reference
*/
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
-
/** Perform one-time initialization on the library by creating a table
* containing the library functions, adding that table to the supplied environment,
* adding the table to package.loaded, and returning table as the return value.
*
Specifically, extend the library loading to set the default value for {@link Globals#STDIN}
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, which must be a Globals instance.
+ * @param env the environment to load into, which must be a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
super.call(modname, env);
env.checkglobals().STDIN = System.in;
return env;
}
-
- /**
- * Try to open a file in the current working directory,
- * or fall back to base opener if not found.
- *
- * This implementation attempts to open the file using new File(filename).
+ /**
+ * Try to open a file in the current working directory, or fall back to base
+ * opener if not found.
+ *
+ * This implementation attempts to open the file using new File(filename).
* It falls back to the base implementation that looks it up as a resource
- * in the class path if not found as a plain file.
- *
+ * in the class path if not found as a plain file.
+ *
* @see org.luaj.vm2.lib.BaseLib
* @see org.luaj.vm2.lib.ResourceFinder
- *
+ *
* @param filename
- * @return InputStream, or null if not found.
+ * @return InputStream, or null if not found.
*/
+ @Override
public InputStream findResource(String filename) {
File f = new File(filename);
- if ( ! f.exists() )
+ if (!f.exists())
return super.findResource(filename);
try {
return new BufferedInputStream(new FileInputStream(f));
- } catch ( IOException ioe ) {
+ } catch (IOException ioe) {
return null;
}
}
}
-
diff --git a/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java
similarity index 66%
rename from src/jse/org/luaj/vm2/lib/jse/JseIoLib.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java
index cfaf6f4a..36e560d6 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -37,135 +37,170 @@ import org.luaj.vm2.lib.IoLib;
import org.luaj.vm2.lib.LibFunction;
/**
- * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}
- * library for the JSE platform.
+ * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements
+ * the lua standard {@code io} library for the JSE platform.
*
* It uses RandomAccessFile to implement seek on files.
*
* Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
- *
- * For special cases where the smallest possible footprint is desired,
- * a minimal set of libraries could be loaded
- * directly via {@link Globals#load(LuaValue)} using code such as:
- *
However, other libraries such as MathLib are not loaded in this case.
+ * For special cases where the smallest possible footprint is desired, a minimal
+ * set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
+ * using code such as:
+ *
+ *
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * However, other libraries such as MathLib are not loaded in this
+ * case.
+ *
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see IoLib
* @see org.luaj.vm2.lib.jme.JmeIoLib
- * @see Lua 5.2 I/O Lib Reference
+ * @see Lua 5.2 I/O Lib
+ * Reference
*/
public class JseIoLib extends IoLib {
+ @Override
protected File wrapStdin() throws IOException {
return new StdinFile();
}
-
+
+ @Override
protected File wrapStdout() throws IOException {
return new StdoutFile(FTYPE_STDOUT);
}
-
+
+ @Override
protected File wrapStderr() throws IOException {
return new StdoutFile(FTYPE_STDERR);
}
-
- protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
- RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw");
- if ( appendMode ) {
+
+ @Override
+ protected File openFile(String filename, boolean readMode, boolean appendMode, boolean updateMode,
+ boolean binaryMode) throws IOException {
+ RandomAccessFile f = new RandomAccessFile(filename, readMode? "r": "rw");
+ if (appendMode) {
f.seek(f.length());
} else {
- if ( ! readMode )
+ if (!readMode)
f.setLength(0);
}
- return new FileImpl( f );
- }
-
- protected File openProgram(String prog, String mode) throws IOException {
- final Process p = Runtime.getRuntime().exec(prog);
- return "w".equals(mode)?
- new FileImpl( p.getOutputStream() ):
- new FileImpl( p.getInputStream() );
+ return new FileImpl(f);
}
- protected File tmpFile() throws IOException {
- java.io.File f = java.io.File.createTempFile(".luaj","bin");
- f.deleteOnExit();
- return new FileImpl( new RandomAccessFile(f,"rw") );
+ @Override
+ protected File openProgram(String prog, String mode) throws IOException {
+ final Process p = Runtime.getRuntime().exec(prog);
+ return "w".equals(mode)? new FileImpl(p.getOutputStream()): new FileImpl(p.getInputStream());
}
-
+
+ @Override
+ protected File tmpFile() throws IOException {
+ java.io.File f = java.io.File.createTempFile(".luaj", "bin");
+ f.deleteOnExit();
+ return new FileImpl(new RandomAccessFile(f, "rw"));
+ }
+
private static void notimplemented() {
throw new LuaError("not implemented");
}
-
private final class FileImpl extends File {
private final RandomAccessFile file;
- private final InputStream is;
- private final OutputStream os;
- private boolean closed = false;
- private boolean nobuffer = false;
- private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) {
+ private final InputStream is;
+ private final OutputStream os;
+ private boolean closed = false;
+ private boolean nobuffer = false;
+
+ private FileImpl(RandomAccessFile file, InputStream is, OutputStream os) {
this.file = file;
- this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
+ this.is = is != null? is.markSupported()? is: new BufferedInputStream(is): null;
this.os = os;
}
- private FileImpl( RandomAccessFile f ) {
- this( f, null, null );
+
+ private FileImpl(RandomAccessFile f) {
+ this(f, null, null);
}
- private FileImpl( InputStream i ) {
- this( null, i, null );
+
+ private FileImpl(InputStream i) {
+ this(null, i, null);
}
- private FileImpl( OutputStream o ) {
- this( null, null, o );
+
+ private FileImpl(OutputStream o) {
+ this(null, null, o);
}
+
+ @Override
public String tojstring() {
- return "file (" + (this.closed ? "closed" : String.valueOf(this.hashCode())) + ")";
+ return "file (" + (this.closed? "closed": String.valueOf(this.hashCode())) + ")";
}
+
+ @Override
public boolean isstdfile() {
return file == null;
}
- public void close() throws IOException {
+
+ @Override
+ public void close() throws IOException {
closed = true;
- if ( file != null ) {
+ if (file != null) {
file.close();
}
}
+
+ @Override
public void flush() throws IOException {
- if ( os != null )
+ if (os != null)
os.flush();
}
+
+ @Override
public void write(LuaString s) throws IOException {
- if ( os != null )
- os.write( s.m_bytes, s.m_offset, s.m_length );
- else if ( file != null )
- file.write( s.m_bytes, s.m_offset, s.m_length );
+ if (os != null)
+ os.write(s.m_bytes, s.m_offset, s.m_length);
+ else if (file != null)
+ file.write(s.m_bytes, s.m_offset, s.m_length);
else
notimplemented();
- if ( nobuffer )
+ if (nobuffer)
flush();
}
+
+ @Override
public boolean isclosed() {
return closed;
}
+
+ @Override
public int seek(String option, int pos) throws IOException {
- if ( file != null ) {
- if ( "set".equals(option) ) {
+ if (file != null) {
+ if ("set".equals(option)) {
file.seek(pos);
- } else if ( "end".equals(option) ) {
+ } else if ("end".equals(option)) {
file.seek(file.length()+pos);
} else {
file.seek(file.getFilePointer()+pos);
@@ -175,23 +210,27 @@ public class JseIoLib extends IoLib {
notimplemented();
return 0;
}
+
+ @Override
public void setvbuf(String mode, int size) {
nobuffer = "no".equals(mode);
}
// get length remaining to read
+ @Override
public int remaining() throws IOException {
- return file!=null? (int) (file.length()-file.getFilePointer()): -1;
+ return file != null? (int) (file.length()-file.getFilePointer()): -1;
}
-
+
// peek ahead one character
+ @Override
public int peek() throws IOException {
- if ( is != null ) {
+ if (is != null) {
is.mark(1);
int c = is.read();
is.reset();
return c;
- } else if ( file != null ) {
+ } else if (file != null) {
long fp = file.getFilePointer();
int c = file.read();
file.seek(fp);
@@ -200,12 +239,13 @@ public class JseIoLib extends IoLib {
notimplemented();
return 0;
}
-
+
// return char if read, -1 if eof, throw IOException on other exception
+ @Override
public int read() throws IOException {
- if ( is != null )
+ if (is != null)
return is.read();
- else if ( file != null ) {
+ else if (file != null) {
return file.read();
}
notimplemented();
@@ -213,10 +253,11 @@ public class JseIoLib extends IoLib {
}
// return number of bytes read if positive, -1 if eof, throws IOException
+ @Override
public int read(byte[] bytes, int offset, int length) throws IOException {
- if (file!=null) {
+ if (file != null) {
return file.read(bytes, offset, length);
- } else if (is!=null) {
+ } else if (is != null) {
return is.read(bytes, offset, length);
} else {
notimplemented();
@@ -232,57 +273,64 @@ public class JseIoLib extends IoLib {
this.file_type = file_type;
}
+ @Override
public String tojstring() {
- return "file ("+this.hashCode()+")";
+ return "file (" + this.hashCode() + ")";
}
- private final PrintStream getPrintStream() {
- return file_type == FTYPE_STDERR?
- globals.STDERR:
- globals.STDOUT;
- }
+ private PrintStream getPrintStream() { return file_type == FTYPE_STDERR? globals.STDERR: globals.STDOUT; }
+ @Override
public void write(LuaString string) throws IOException {
getPrintStream().write(string.m_bytes, string.m_offset, string.m_length);
}
+ @Override
public void flush() throws IOException {
getPrintStream().flush();
}
+ @Override
public boolean isstdfile() {
return true;
}
+ @Override
public void close() throws IOException {
// do not close std files.
}
+ @Override
public boolean isclosed() {
return false;
}
+ @Override
public int seek(String option, int bytecount) throws IOException {
return 0;
}
+ @Override
public void setvbuf(String mode, int size) {
}
+ @Override
public int remaining() throws IOException {
return 0;
}
+ @Override
public int peek() throws IOException, EOFException {
return 0;
}
+ @Override
public int read() throws IOException, EOFException {
return 0;
}
- public int read(byte[] bytes, int offset, int length)
- throws IOException {
+ @Override
+ public int read(byte[] bytes, int offset, int length) throws IOException {
return 0;
}
}
@@ -291,39 +339,49 @@ public class JseIoLib extends IoLib {
private StdinFile() {
}
+ @Override
public String tojstring() {
- return "file ("+this.hashCode()+")";
+ return "file (" + this.hashCode() + ")";
}
+ @Override
public void write(LuaString string) throws IOException {
}
+ @Override
public void flush() throws IOException {
}
+ @Override
public boolean isstdfile() {
return true;
}
+ @Override
public void close() throws IOException {
// do not close std files.
}
+ @Override
public boolean isclosed() {
return false;
}
+ @Override
public int seek(String option, int bytecount) throws IOException {
return 0;
}
+ @Override
public void setvbuf(String mode, int size) {
}
+ @Override
public int remaining() throws IOException {
return -1;
}
+ @Override
public int peek() throws IOException, EOFException {
globals.STDIN.mark(1);
int c = globals.STDIN.read();
@@ -331,12 +389,13 @@ public class JseIoLib extends IoLib {
return c;
}
+ @Override
public int read() throws IOException, EOFException {
return globals.STDIN.read();
}
- public int read(byte[] bytes, int offset, int length)
- throws IOException {
+ @Override
+ public int read(byte[] bytes, int offset, int length) throws IOException {
return globals.STDIN.read(bytes, offset, length);
}
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java
similarity index 54%
rename from src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java
index 87f133a1..e0fb80ac 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -26,60 +26,78 @@ import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.TwoArgFunction;
-/**
- * Subclass of {@link LibFunction} which implements the lua standard {@code math}
- * library.
- *
- * It contains all lua math functions, including those not available on the JME platform.
- * See {@link org.luaj.vm2.lib.MathLib} for the exception list.
+/**
+ * Subclass of {@link LibFunction} which implements the lua standard
+ * {@code math} library.
*
- * Typically, this library is included as part of a call to
+ * It contains all lua math functions, including those not available on the JME
+ * platform. See {@link org.luaj.vm2.lib.MathLib} for the exception list.
+ *
+ * Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
- *
- * For special cases where the smallest possible footprint is desired,
- * a minimal set of libraries could be loaded
- * directly via {@link Globals#load(LuaValue)} using code such as:
- *
However, other libraries such as CoroutineLib are not loaded in this case.
+ * For special cases where the smallest possible footprint is desired, a minimal
+ * set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
+ * using code such as:
+ *
+ *
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
+ * However, other libraries such as CoroutineLib are not loaded in this
+ * case.
+ *
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see org.luaj.vm2.lib.jse.JseMathLib
- * @see Lua 5.2 Math Lib Reference
+ * @see Lua 5.2 Math Lib
+ * Reference
*/
public class JseMathLib extends org.luaj.vm2.lib.MathLib {
-
+
public JseMathLib() {}
-
- /** Perform one-time initialization on the library by creating a table
- * containing the library functions, adding that table to the supplied environment,
- * adding the table to package.loaded, and returning table as the return value.
- *
Specifically, adds all library functions that can be implemented directly
- * in JSE but not JME: acos, asin, atan, atan2, cosh, exp, log, pow, sinh, and tanh.
+ /**
+ * Perform one-time initialization on the library by creating a table
+ * containing the library functions, adding that table to the supplied
+ * environment, adding the table to package.loaded, and returning table as
+ * the return value.
+ *
+ * Specifically, adds all library functions that can be implemented directly
+ * in JSE but not JME: acos, asin, atan, atan2, cosh, exp, log, pow, sinh,
+ * and tanh.
+ *
* @param modname the module name supplied if this is loaded via 'require'.
- * @param env the environment to load into, which must be a Globals instance.
+ * @param env the environment to load into, which must be a Globals
+ * instance.
*/
+ @Override
public LuaValue call(LuaValue modname, LuaValue env) {
super.call(modname, env);
LuaValue math = env.get("math");
math.set("acos", new acos());
math.set("asin", new asin());
- LuaValue atan = new atan2();
- math.set("atan", atan);
- math.set("atan2", atan);
+ math.set("atan", new atan());
+ math.set("atan2", new atan2());
math.set("cosh", new cosh());
math.set("exp", new exp());
math.set("log", new log());
@@ -89,32 +107,70 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
return math;
}
- static final class acos extends UnaryOp { protected double call(double d) { return Math.acos(d); } }
- static final class asin extends UnaryOp { protected double call(double d) { return Math.asin(d); } }
- static final class atan2 extends TwoArgFunction {
+ static final class acos extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.acos(d); }
+ }
+
+ static final class asin extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.asin(d); }
+ }
+
+ static final class atan extends TwoArgFunction {
+ @Override
public LuaValue call(LuaValue x, LuaValue y) {
return valueOf(Math.atan2(x.checkdouble(), y.optdouble(1)));
- }
+ }
}
- static final class cosh extends UnaryOp { protected double call(double d) { return Math.cosh(d); } }
- static final class exp extends UnaryOp { protected double call(double d) { return Math.exp(d); } }
+
+ static final class atan2 extends TwoArgFunction {
+ @Override
+ public LuaValue call(LuaValue x, LuaValue y) {
+ return valueOf(Math.atan2(x.checkdouble(), y.checkdouble()));
+ }
+ }
+
+ static final class cosh extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.cosh(d); }
+ }
+
+ static final class exp extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.exp(d); }
+ }
+
static final class log extends TwoArgFunction {
+ @Override
public LuaValue call(LuaValue x, LuaValue base) {
double nat = Math.log(x.checkdouble());
double b = base.optdouble(Math.E);
- if (b != Math.E) nat /= Math.log(b);
+ if (b != Math.E)
+ nat /= Math.log(b);
return valueOf(nat);
}
}
- static final class pow extends BinaryOp { protected double call(double x, double y) { return Math.pow(x, y); } }
- static final class sinh extends UnaryOp { protected double call(double d) { return Math.sinh(d); } }
- static final class tanh extends UnaryOp { protected double call(double d) { return Math.tanh(d); } }
+
+ static final class pow extends BinaryOp {
+ @Override
+ protected double call(double x, double y) { return Math.pow(x, y); }
+ }
+
+ static final class sinh extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.sinh(d); }
+ }
+
+ static final class tanh extends UnaryOp {
+ @Override
+ protected double call(double d) { return Math.tanh(d); }
+ }
/** Faster, better version of pow() used by arithmetic operator ^ */
+ @Override
public double dpow_lib(double a, double b) {
return Math.pow(a, b);
}
-
-
-}
+}
diff --git a/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java
similarity index 74%
rename from src/jse/org/luaj/vm2/lib/jse/JseOsLib.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java
index af63c8af..42819775 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -31,10 +31,11 @@ import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.OsLib;
/**
- * Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
+ * Subclass of {@link LibFunction} which implements the standard lua {@code os}
+ * library.
*
- * This contains more complete implementations of the following functions
- * using features that are specific to JSE:
+ * This contains more complete implementations of the following functions using
+ * features that are specific to JSE:
*
- * Because the nature of the {@code os} library is to encapsulate
- * os-specific features, the behavior of these functions varies considerably
- * from their counterparts in the C platform.
+ * Because the nature of the {@code os} library is to encapsulate os-specific
+ * features, the behavior of these functions varies considerably from their
+ * counterparts in the C platform.
*
* Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
- *
- * For special cases where the smallest possible footprint is desired,
- * a minimal set of libraries could be loaded
- * directly via {@link Globals#load(LuaValue)} using code such as:
- *
However, other libraries such as MathLib are not loaded in this case.
+ * For special cases where the smallest possible footprint is desired, a minimal
+ * set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
+ * using code such as:
+ *
+ *
+ * However, other libraries such as MathLib are not loaded in this
+ * case.
+ *
+ *
* @see LibFunction
* @see OsLib
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
- * @see Lua 5.2 OS Lib Reference
+ * @see Lua 5.2 OS Lib
+ * Reference
*/
public class JseOsLib extends org.luaj.vm2.lib.OsLib {
-
+
/** return code indicating the execute() threw an I/O exception */
- public static final int EXEC_IOEXCEPTION = 1;
-
+ public static final int EXEC_IOEXCEPTION = 1;
+
/** return code indicating the execute() was interrupted */
public static final int EXEC_INTERRUPTED = -2;
-
+
/** return code indicating the execute() threw an unknown exception */
- public static final int EXEC_ERROR = -3;
-
+ public static final int EXEC_ERROR = -3;
+
/** public constructor */
public JseOsLib() {
}
+ @Override
protected String getenv(String varname) {
String s = System.getenv(varname);
- return s != null? s : System.getProperty(varname);
+ return s != null? s: System.getProperty(varname);
}
+ @Override
protected Varargs execute(String command) {
int exitValue;
try {
@@ -107,29 +122,32 @@ public class JseOsLib extends org.luaj.vm2.lib.OsLib {
return varargsOf(NIL, valueOf("signal"), valueOf(exitValue));
}
+ @Override
protected void remove(String filename) throws IOException {
File f = new File(filename);
- if ( ! f.exists() )
+ if (!f.exists())
throw new IOException("No such file or directory");
- if ( ! f.delete() )
+ if (!f.delete())
throw new IOException("Failed to delete");
}
+ @Override
protected void rename(String oldname, String newname) throws IOException {
File f = new File(oldname);
- if ( ! f.exists() )
+ if (!f.exists())
throw new IOException("No such file or directory");
- if ( ! f.renameTo(new File(newname)) )
+ if (!f.renameTo(new File(newname)))
throw new IOException("Failed to rename");
}
+ @Override
protected String tmpname() {
try {
- java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX);
+ java.io.File f = java.io.File.createTempFile(TMP_PREFIX, TMP_SUFFIX);
return f.getAbsolutePath();
- } catch ( IOException ioe ) {
+ } catch (IOException ioe) {
return super.tmpname();
}
}
-
+
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java
similarity index 83%
rename from src/jse/org/luaj/vm2/lib/jse/JsePlatform.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java
index 00575aaf..63a01c0c 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java
@@ -10,7 +10,7 @@
*
* 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
@@ -34,31 +34,45 @@ import org.luaj.vm2.lib.ResourceFinder;
import org.luaj.vm2.lib.StringLib;
import org.luaj.vm2.lib.TableLib;
-/** The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to standardize
- * how globals tables are initialized for the JSE platform.
+/**
+ * The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to
+ * standardize how globals tables are initialized for the JSE platform.
*
* It is used to allocate either a set of standard globals using
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
*
* A simple example of initializing globals and using them from Java is:
- *
- * For this to succeed, the file "main.lua" must be in the current directory or a resource.
- * See {@link org.luaj.vm2.lib.jse.JseBaseLib} for details on finding scripts using {@link ResourceFinder}.
+ * }
+ *
+ *
+ * For this to succeed, the file "main.lua" must be in the current directory or
+ * a resource. See {@link org.luaj.vm2.lib.jse.JseBaseLib} for details on
+ * finding scripts using {@link ResourceFinder}.
*
- * The standard globals will contain all standard libraries plus {@code luajava}:
+ * The standard globals will contain all standard libraries plus
+ * {@code luajava}:
*
- * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
+ * In addition, the {@link LuaC} compiler is installed so lua files may be
+ * loaded in their source form.
*
- * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}.
+ * The debug globals are simply the standard globals plus the {@code debug}
+ * library {@link DebugLib}.
*
* The class ensures that initialization is done in the correct order.
- *
+ *
* @see Globals
* @see org.luaj.vm2.lib.jme.JmePlatform
*/
@@ -85,7 +101,7 @@ public class JsePlatform {
/**
* Create a standard set of globals for JSE including all the libraries.
- *
+ *
* @return Table of globals initialized with the standard JSE libraries
* @see #debugGlobals()
* @see org.luaj.vm2.lib.jse.JsePlatform
@@ -108,9 +124,11 @@ public class JsePlatform {
return globals;
}
- /** Create standard globals including the {@link DebugLib} library.
- *
- * @return Table of globals initialized with the standard JSE and debug libraries
+ /**
+ * Create standard globals including the {@link DebugLib} library.
+ *
+ * @return Table of globals initialized with the standard JSE and debug
+ * libraries
* @see #standardGlobals()
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
@@ -122,10 +140,11 @@ public class JsePlatform {
return globals;
}
-
- /** Simple wrapper for invoking a lua function with command line arguments.
- * The supplied function is first given a new Globals object as its environment
- * then the program is run with arguments.
+ /**
+ * Simple wrapper for invoking a lua function with command line arguments.
+ * The supplied function is first given a new Globals object as its
+ * environment then the program is run with arguments.
+ *
* @return {@link Varargs} containing any values returned by mainChunk.
*/
public static Varargs luaMain(LuaValue mainChunk, String[] args) {
diff --git a/src/jse/org/luaj/vm2/lib/jse/JseProcess.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java
similarity index 70%
rename from src/jse/org/luaj/vm2/lib/jse/JseProcess.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java
index 3fcd79f1..337cf9ad 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JseProcess.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java
@@ -10,7 +10,7 @@
*
* 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
@@ -25,37 +25,48 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-/** Analog of Process that pipes input and output to client-specified streams.
+/**
+ * Analog of Process that pipes input and output to client-specified streams.
*/
public class JseProcess {
final Process process;
- final Thread input,output,error;
+ final Thread input, output, error;
- /** Construct a process around a command, with specified streams to redirect input and output to.
- *
- * @param cmd The command to execute, including arguments, if any
- * @param stdin Optional InputStream to read from as process input, or null if input is not needed.
- * @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
- * @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
+ /**
+ * Construct a process around a command, with specified streams to redirect
+ * input and output to.
+ *
+ * @param cmd The command to execute, including arguments, if any
+ * @param stdin Optional InputStream to read from as process input, or null
+ * if input is not needed.
+ * @param stdout Optional OutputStream to copy process output to, or null if
+ * output is ignored.
+ * @param stderr Optinoal OutputStream to copy process stderr output to, or
+ * null if output is ignored.
* @throws IOException If the system process could not be created.
* @see Process
*/
public JseProcess(String[] cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException {
- this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
+ this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
}
- /** Construct a process around a command, with specified streams to redirect input and output to.
- *
- * @param cmd The command to execute, including arguments, if any
- * @param stdin Optional InputStream to read from as process input, or null if input is not needed.
- * @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
- * @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
+ /**
+ * Construct a process around a command, with specified streams to redirect
+ * input and output to.
+ *
+ * @param cmd The command to execute, including arguments, if any
+ * @param stdin Optional InputStream to read from as process input, or null
+ * if input is not needed.
+ * @param stdout Optional OutputStream to copy process output to, or null if
+ * output is ignored.
+ * @param stderr Optinoal OutputStream to copy process stderr output to, or
+ * null if output is ignored.
* @throws IOException If the system process could not be created.
* @see Process
*/
public JseProcess(String cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException {
- this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
+ this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
}
private JseProcess(Process process, InputStream stdin, OutputStream stdout, OutputStream stderr) {
@@ -70,7 +81,9 @@ public class JseProcess {
return process.exitValue();
}
- /** Wait for the process to complete, and all pending output to finish.
+ /**
+ * Wait for the process to complete, and all pending output to finish.
+ *
* @return The exit status.
* @throws InterruptedException
*/
@@ -87,10 +100,9 @@ public class JseProcess {
}
/** Create a thread to copy bytes from input to output. */
- private Thread copyBytes(final InputStream input,
- final OutputStream output, final InputStream ownedInput,
- final OutputStream ownedOutput) {
- Thread t = (new CopyThread(output, ownedOutput, ownedInput, input));
+ private Thread copyBytes(final InputStream input, final OutputStream output, final InputStream ownedInput,
+ final OutputStream ownedOutput) {
+ Thread t = new CopyThread(output, ownedOutput, ownedInput, input);
t.start();
return t;
}
@@ -98,23 +110,23 @@ public class JseProcess {
private static final class CopyThread extends Thread {
private final OutputStream output;
private final OutputStream ownedOutput;
- private final InputStream ownedInput;
- private final InputStream input;
+ private final InputStream ownedInput;
+ private final InputStream input;
- private CopyThread(OutputStream output, OutputStream ownedOutput,
- InputStream ownedInput, InputStream input) {
+ private CopyThread(OutputStream output, OutputStream ownedOutput, InputStream ownedInput, InputStream input) {
this.output = output;
this.ownedOutput = ownedOutput;
this.ownedInput = ownedInput;
this.input = input;
}
+ @Override
public void run() {
try {
byte[] buf = new byte[1024];
int r;
try {
- while ((r = input.read(buf)) >= 0) {
+ while ( (r = input.read(buf)) >= 0 ) {
output.write(buf, 0, r);
}
} finally {
diff --git a/src/jse/org/luaj/vm2/lib/jse/JseStringLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java
similarity index 95%
rename from src/jse/org/luaj/vm2/lib/jse/JseStringLib.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java
index 41177787..3923b080 100644
--- a/src/jse/org/luaj/vm2/lib/jse/JseStringLib.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -22,15 +22,16 @@
package org.luaj.vm2.lib.jse;
public class JseStringLib extends org.luaj.vm2.lib.StringLib {
-
+
/** public constructor */
public JseStringLib() {
}
+ @Override
protected String format(String src, double x) {
String out;
try {
- out = String.format(src, new Object[] {Double.valueOf(x)});
+ out = String.format(src, Double.valueOf(x));
} catch (Throwable e) {
out = super.format(src, x);
}
diff --git a/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java
similarity index 64%
rename from src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java
rename to luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java
index 35f1f850..b7c0261b 100644
--- a/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java
@@ -10,7 +10,7 @@
*
* 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
@@ -21,7 +21,6 @@
******************************************************************************/
package org.luaj.vm2.lib.jse;
-
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -38,81 +37,89 @@ import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.VarArgFunction;
/**
- * Subclass of {@link LibFunction} which implements the features of the luajava package.
+ * Subclass of {@link LibFunction} which implements the features of the luajava
+ * package.
*
- * Luajava is an approach to mixing lua and java using simple functions that bind
- * java classes and methods to lua dynamically. The API is documented on the
- * luajava documentation pages.
- *
+ * Luajava is an approach to mixing lua and java using simple functions that
+ * bind java classes and methods to lua dynamically. The API is documented on
+ * the luajava documentation
+ * pages.
+ *
*
* Typically, this library is included as part of a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
- *
- *
- * The {@code luajava} library is available
- * on all JSE platforms via the call to {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
- * and the luajava api's are simply invoked from lua.
- * Because it makes extensive use of Java's reflection API, it is not available
- * on JME, but can be used in Android applications.
+ *
+ * The {@code luajava} library is available on all JSE platforms via the call to
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} and the luajava
+ * api's are simply invoked from lua. Because it makes extensive use of Java's
+ * reflection API, it is not available on JME, but can be used in Android
+ * applications.
*
- * This has been implemented to match as closely as possible the behavior in the corresponding library in C.
- *
+ * This has been implemented to match as closely as possible the behavior in the
+ * corresponding library in C.
+ *
* @see LibFunction
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
* @see LuaC
* @see CoerceJavaToLua
* @see CoerceLuaToJava
- * @see http://www.keplerproject.org/luajava/manual.html#luareference
+ * @see http://www.keplerproject.org/luajava/manual.html#luareference
*/
public class LuajavaLib extends VarArgFunction {
- static final int INIT = 0;
- static final int BINDCLASS = 1;
- static final int NEWINSTANCE = 2;
- static final int NEW = 3;
- static final int CREATEPROXY = 4;
- static final int LOADLIB = 5;
+ static final int INIT = 0;
+ static final int BINDCLASS = 1;
+ static final int NEWINSTANCE = 2;
+ static final int NEW = 3;
+ static final int CREATEPROXY = 4;
+ static final int LOADLIB = 5;
+
+ static final String[] NAMES = { "bindClass", "newInstance", "new", "createProxy", "loadLib", };
- static final String[] NAMES = {
- "bindClass",
- "newInstance",
- "new",
- "createProxy",
- "loadLib",
- };
-
static final int METHOD_MODIFIERS_VARARGS = 0x80;
public LuajavaLib() {
}
+ @Override
public Varargs invoke(Varargs args) {
try {
- switch ( opcode ) {
+ switch (opcode) {
case INIT: {
// LuaValue modname = args.arg1();
LuaValue env = args.arg(2);
LuaTable t = new LuaTable();
- bind( t, this.getClass(), NAMES, BINDCLASS );
+ bind(t, this.getClass(), NAMES, BINDCLASS);
env.set("luajava", t);
- if (!env.get("package").isnil()) env.get("package").get("loaded").set("luajava", t);
+ if (!env.get("package").isnil())
+ env.get("package").get("loaded").set("luajava", t);
return t;
}
case BINDCLASS: {
@@ -123,46 +130,47 @@ public class LuajavaLib extends VarArgFunction {
case NEW: {
// get constructor
final LuaValue c = args.checkvalue(1);
- final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
+ final Class clazz = opcode == NEWINSTANCE? classForName(c.tojstring())
+ : (Class) c.checkuserdata(Class.class);
final Varargs consargs = args.subargs(2);
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
}
-
+
case CREATEPROXY: {
final int niface = args.narg()-1;
- if ( niface <= 0 )
+ if (niface <= 0)
throw new LuaError("no interfaces");
final LuaValue lobj = args.checktable(niface+1);
-
+
// get the interfaces
final Class[] ifaces = new Class[niface];
- for ( int i=0; i 0 )
- sb.append( "," );
- sb.append( String.valueOf( p==1? b[i].pc1+1: b[i].pc0+1 ) );
+ for (int i = 0, n = b.length; i < n; i++) {
+ if (i > 0)
+ sb.append(",");
+ sb.append(String.valueOf(p == 1? b[i].pc1+1: b[i].pc0+1));
}
sb.append(")");
return sb.toString();
}
public static BasicBlock[] findBasicBlocks(Prototype p) {
-
+
// mark beginnings, endings
final int n = p.code.length;
final boolean[] isbeg = new boolean[n];
@@ -51,43 +50,45 @@ public class BasicBlock {
BranchVisitor bv = new MarkAndMergeVisitor(isbeg, isend);
visitBranches(p, bv); // 1st time to mark branches
visitBranches(p, bv); // 2nd time to catch merges
-
+
// create basic blocks
final BasicBlock[] blocks = new BasicBlock[n];
- for ( int i=0; i= SUPERTYPE_VARARGS )
+ if (p.is_vararg != 0 || superclassType >= SUPERTYPE_VARARGS)
superclassType = SUPERTYPE_VARARGS;
- for ( int i=0, n=p.code.length; i 2)) ) {
+ if (o == Lua.OP_TAILCALL || o == Lua.OP_RETURN && (Lua.GETARG_B(inst) < 1 || Lua.GETARG_B(inst) > 2)) {
superclassType = SUPERTYPE_VARARGS;
break;
}
}
-
+
// create class generator
- cg = new ClassGen(classname, SUPER_NAME_N[superclassType], filename,
- Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
+ cg = new ClassGen(classname, SUPER_NAME_N[superclassType], filename, Constants.ACC_PUBLIC | Constants.ACC_SUPER,
+ null);
cp = cg.getConstantPool(); // cg creates constant pool
// main instruction lists
@@ -197,24 +196,23 @@ public class JavaBuilder {
main = new InstructionList();
// create the fields
- for ( int i=0; i",
- cg.getClassName(), init, cg.getConstantPool());
+ // add class initializer
+ if (!init.isEmpty()) {
+ MethodGen mg = new MethodGen(Constants.ACC_STATIC, Type.VOID, ARG_TYPES_NONE, new String[] {}, "",
+ cg.getClassName(), init, cg.getConstantPool());
init.append(InstructionConstants.RETURN);
mg.setMaxStack();
cg.addMethod(mg.getMethod());
@@ -276,27 +274,27 @@ public class JavaBuilder {
// add default constructor
cg.addEmptyConstructor(Constants.ACC_PUBLIC);
-
+
// gen method
resolveBranches();
mg.setMaxStack();
cg.addMethod(mg.getMethod());
main.dispose();
- // add initupvalue1(LuaValue env) to initialize environment for main chunk
+ // add initupvalue1(LuaValue env) to initialize environment for main chunk
if (p.upvalues.length == 1 && superclassType == SUPERTYPE_VARARGS) {
- MethodGen mg = new MethodGen( Constants.ACC_PUBLIC | Constants.ACC_FINAL, // access flags
- Type.VOID, // return type
- ARG_TYPES_LUAVALUE, // argument types
- new String[] { "env" }, // arg names
- "initupvalue1",
- STR_LUAVALUE, // method, defining class
- main, cp);
- boolean isrw = pi.isReadWriteUpvalue( pi.upvals[0] );
+ MethodGen mg = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_FINAL, // access flags
+ Type.VOID, // return type
+ ARG_TYPES_LUAVALUE, // argument types
+ new String[] { "env" }, // arg names
+ "initupvalue1", STR_LUAVALUE, // method, defining class
+ main, cp);
+ boolean isrw = pi.isReadWriteUpvalue(pi.upvals[0]);
append(InstructionConstants.THIS);
append(new ALOAD(1));
- if ( isrw ) {
- append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKESTATIC));
+ if (isrw) {
+ append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE,
+ Constants.INVOKESTATIC));
append(factory.createFieldAccess(classname, upvalueName(0), TYPE_LOCALUPVALUE, Constants.PUTFIELD));
} else {
append(factory.createFieldAccess(classname, upvalueName(0), TYPE_LUAVALUE, Constants.PUTFIELD));
@@ -306,35 +304,35 @@ public class JavaBuilder {
cg.addMethod(mg.getMethod());
main.dispose();
}
-
- // add main function so class is invokable from the java command line
+
+ // add main function so class is invokable from the java command line
if (genmain) {
- MethodGen mg = new MethodGen( Constants.ACC_PUBLIC | Constants.ACC_STATIC, // access flags
- Type.VOID, // return type
- ARG_TYPES_STRINGARRAY, // argument types
- new String[] { "arg" }, // arg names
- "main",
- classname, // method, defining class
- main, cp);
+ MethodGen mg = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, // access flags
+ Type.VOID, // return type
+ ARG_TYPES_STRINGARRAY, // argument types
+ new String[] { "arg" }, // arg names
+ "main", classname, // method, defining class
+ main, cp);
append(factory.createNew(classname));
append(InstructionConstants.DUP);
- append(factory.createInvoke(classname, Constants.CONSTRUCTOR_NAME, Type.VOID, ARG_TYPES_NONE, Constants.INVOKESPECIAL));
+ append(factory.createInvoke(classname, Constants.CONSTRUCTOR_NAME, Type.VOID, ARG_TYPES_NONE,
+ Constants.INVOKESPECIAL));
append(new ALOAD(0));
- append(factory.createInvoke(STR_JSEPLATFORM, "luaMain", Type.VOID, ARG_TYPES_LUAVALUE_STRINGARRAY, Constants.INVOKESTATIC));
+ append(factory.createInvoke(STR_JSEPLATFORM, "luaMain", Type.VOID, ARG_TYPES_LUAVALUE_STRINGARRAY,
+ Constants.INVOKESTATIC));
append(InstructionConstants.RETURN);
mg.setMaxStack();
cg.addMethod(mg.getMethod());
main.dispose();
}
-
// convert to class bytes
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cg.getJavaClass().dump(baos);
return baos.toByteArray();
- } catch ( IOException ioe ) {
- throw new RuntimeException("JavaClass.dump() threw "+ioe);
+ } catch (IOException ioe) {
+ throw new RuntimeException("JavaClass.dump() threw " + ioe);
}
}
@@ -349,39 +347,40 @@ public class JavaBuilder {
public void loadNil() {
append(factory.createFieldAccess(STR_LUAVALUE, "NIL", TYPE_LUAVALUE, Constants.GETSTATIC));
}
-
+
public void loadNone() {
append(factory.createFieldAccess(STR_LUAVALUE, "NONE", TYPE_LUAVALUE, Constants.GETSTATIC));
}
public void loadBoolean(boolean b) {
- String field = (b? "TRUE": "FALSE");
+ String field = b? "TRUE": "FALSE";
append(factory.createFieldAccess(STR_LUAVALUE, field, TYPE_LUABOOLEAN, Constants.GETSTATIC));
}
-
- private Map plainSlotVars = new HashMap();
- private Map upvalueSlotVars = new HashMap();
- private Map localVarGenBySlot = new HashMap();
- private int findSlot( int slot, Map map, String prefix, Type type ) {
- Integer islot = Integer.valueOf(slot);
- if ( map.containsKey(islot) )
- return ((Integer)map.get(islot)).intValue();
+
+ private final Map plainSlotVars = new HashMap<>();
+ private final Map upvalueSlotVars = new HashMap<>();
+ private final Map localVarGenBySlot = new HashMap<>();
+
+ private int findSlot(int slot, Map map, String prefix, Type type) {
+ Integer islot = slot;
+ if (map.containsKey(islot))
+ return map.get(islot).intValue();
String name = prefix+slot;
LocalVariableGen local = mg.addLocalVariable(name, type, null, null);
int index = local.getIndex();
- map.put(islot, Integer.valueOf(index));
+ map.put(islot, index);
localVarGenBySlot.put(islot, local);
return index;
}
- private int findSlotIndex( int slot, boolean isupvalue ) {
- return isupvalue?
- findSlot( slot, upvalueSlotVars, PREFIX_UPVALUE_SLOT, TYPE_LOCALUPVALUE ):
- findSlot( slot, plainSlotVars, PREFIX_PLAIN_SLOT, TYPE_LUAVALUE );
+
+ private int findSlotIndex(int slot, boolean isupvalue) {
+ return isupvalue? findSlot(slot, upvalueSlotVars, PREFIX_UPVALUE_SLOT, TYPE_LOCALUPVALUE)
+ : findSlot(slot, plainSlotVars, PREFIX_PLAIN_SLOT, TYPE_LUAVALUE);
}
public void loadLocal(int pc, int slot) {
boolean isupval = pi.isUpvalueRefer(pc, slot);
- int index = findSlotIndex( slot, isupval );
+ int index = findSlotIndex(slot, isupval);
append(new ALOAD(index));
if (isupval) {
append(new PUSH(cp, 0));
@@ -391,11 +390,12 @@ public class JavaBuilder {
public void storeLocal(int pc, int slot) {
boolean isupval = pi.isUpvalueAssign(pc, slot);
- int index = findSlotIndex( slot, isupval );
+ int index = findSlotIndex(slot, isupval);
if (isupval) {
boolean isupcreate = pi.isUpvalueCreate(pc, slot);
- if ( isupcreate ) {
- append(factory.createInvoke(classname, "newupe", TYPE_LOCALUPVALUE, ARG_TYPES_NONE, Constants.INVOKESTATIC));
+ if (isupcreate) {
+ append(factory.createInvoke(classname, "newupe", TYPE_LOCALUPVALUE, ARG_TYPES_NONE,
+ Constants.INVOKESTATIC));
append(InstructionConstants.DUP);
append(new ASTORE(index));
} else {
@@ -411,12 +411,13 @@ public class JavaBuilder {
}
public void createUpvalues(int pc, int firstslot, int numslots) {
- for ( int i=0; i constants = new HashMap();
-
+
+ private final Map constants = new HashMap<>();
+
public void loadConstant(LuaValue value) {
- switch ( value.type() ) {
- case LuaValue.TNIL:
+ switch (value.type()) {
+ case LuaValue.TNIL:
loadNil();
break;
case LuaValue.TBOOLEAN:
- loadBoolean( value.toboolean() );
+ loadBoolean(value.toboolean());
break;
case LuaValue.TNUMBER:
case LuaValue.TSTRING:
- String name = (String) constants.get(value);
- if ( name == null ) {
- name = value.type() == LuaValue.TNUMBER?
- value.isinttype()?
- createLuaIntegerField(value.checkint()):
- createLuaDoubleField(value.checkdouble()):
- createLuaStringField(value.checkstring());
+ String name = constants.get(value);
+ if (name == null) {
+ name = value.type() == LuaValue.TNUMBER? value.isinttype()? createLuaIntegerField(value.checkint())
+ : createLuaDoubleField(value.checkdouble()): createLuaStringField(value.checkstring());
constants.put(value, name);
}
append(factory.createGetStatic(classname, name, TYPE_LUAVALUE));
break;
default:
- throw new IllegalArgumentException("bad constant type: "+value.type());
+ throw new IllegalArgumentException("bad constant type: " + value.type());
}
}
private String createLuaIntegerField(int value) {
String name = PREFIX_CONSTANT+constants.size();
- FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
- TYPE_LUAVALUE, name, cp);
+ FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, TYPE_LUAVALUE, name, cp);
cg.addField(fg.getField());
init.append(new PUSH(cp, value));
- init.append(factory.createInvoke(STR_LUAVALUE, "valueOf",
- TYPE_LUAINTEGER, ARG_TYPES_INT, Constants.INVOKESTATIC));
+ init.append(
+ factory.createInvoke(STR_LUAVALUE, "valueOf", TYPE_LUAINTEGER, ARG_TYPES_INT, Constants.INVOKESTATIC));
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
return name;
}
-
+
private String createLuaDoubleField(double value) {
String name = PREFIX_CONSTANT+constants.size();
- FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
- TYPE_LUAVALUE, name, cp);
+ FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, TYPE_LUAVALUE, name, cp);
cg.addField(fg.getField());
init.append(new PUSH(cp, value));
- init.append(factory.createInvoke(STR_LUAVALUE, "valueOf",
- TYPE_LUANUMBER, ARG_TYPES_DOUBLE, Constants.INVOKESTATIC));
- init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
+ init.append(
+ factory.createInvoke(STR_LUAVALUE, "valueOf", TYPE_LUANUMBER, ARG_TYPES_DOUBLE, Constants.INVOKESTATIC));
+ init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
return name;
}
private String createLuaStringField(LuaString value) {
String name = PREFIX_CONSTANT+constants.size();
- FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
- TYPE_LUAVALUE, name, cp);
+ FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, TYPE_LUAVALUE, name, cp);
cg.addField(fg.getField());
LuaString ls = value.checkstring();
- if ( ls.isValidUtf8() ) {
+ if (ls.isValidUtf8()) {
init.append(new PUSH(cp, value.tojstring()));
- init.append(factory.createInvoke(STR_LUASTRING, "valueOf",
- TYPE_LUASTRING, ARG_TYPES_STRING, Constants.INVOKESTATIC));
+ init.append(factory.createInvoke(STR_LUASTRING, "valueOf", TYPE_LUASTRING, ARG_TYPES_STRING,
+ Constants.INVOKESTATIC));
} else {
char[] c = new char[ls.m_length];
- for ( int j=0; j 1)
l.setStart(lastInstrHandles[start_pc-2]);
l.setName(name);
}
}
-
+
private void resolveBranches() {
- int nc = p.code.length;
+ int nc = p.code.length;
for (int pc = 0; pc < nc; pc++) {
if (branches[pc] != null) {
- int t=targets[pc];
- while ( t= branchDestHandles.length )
- throw new IllegalArgumentException("no target at or after "+targets[pc]+" op="+Lua.GET_OPCODE(p.code[targets[pc]]));
+ if (t >= branchDestHandles.length)
+ throw new IllegalArgumentException(
+ "no target at or after " + targets[pc] + " op=" + Lua.GET_OPCODE(p.code[targets[pc]]));
branches[pc].setTarget(branchDestHandles[t]);
}
}
}
-
+
public void setlistStack(int pc, int a0, int index0, int nvals) {
- for ( int i=0; i=0; a++, b-- ) {
- if ( b > 0 )
+ for (; b >= 0; a++, b--) {
+ if (b > 0)
builder.dup();
- builder.storeLocal( pc, a );
+ builder.storeLocal(pc, a);
}
break;
-
+
case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
- builder.loadUpvalue( b );
- loadLocalOrConstant( p, builder, pc, c );
+ builder.loadUpvalue(b);
+ loadLocalOrConstant(p, builder, pc, c);
builder.getTable();
- builder.storeLocal( pc, a );
+ builder.storeLocal(pc, a);
break;
case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
- builder.loadLocal( pc, b );
- loadLocalOrConstant( p, builder, pc, c );
+ builder.loadLocal(pc, b);
+ loadLocalOrConstant(p, builder, pc, c);
builder.getTable();
- builder.storeLocal( pc, a );
+ builder.storeLocal(pc, a);
break;
-
+
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
- builder.loadUpvalue( a );
- loadLocalOrConstant( p, builder, pc, b );
- loadLocalOrConstant( p, builder, pc, c );
+ builder.loadUpvalue(a);
+ loadLocalOrConstant(p, builder, pc, b);
+ loadLocalOrConstant(p, builder, pc, c);
builder.setTable();
break;
-
+
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
- builder.loadLocal( pc, a );
- loadLocalOrConstant( p, builder, pc, b );
- loadLocalOrConstant( p, builder, pc, c );
+ builder.loadLocal(pc, a);
+ loadLocalOrConstant(p, builder, pc, b);
+ loadLocalOrConstant(p, builder, pc, c);
builder.setTable();
break;
-
+
case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
- loadLocalOrConstant( p, builder, pc, b );
- loadLocalOrConstant( p, builder, pc, c );
- builder.binaryop( o );
- builder.storeLocal( pc, a );
+ loadLocalOrConstant(p, builder, pc, b);
+ loadLocalOrConstant(p, builder, pc, c);
+ builder.binaryop(o);
+ builder.storeLocal(pc, a);
break;
-
+
case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
- builder.loadLocal(pc,b);
+ builder.loadLocal(pc, b);
builder.dup();
builder.storeLocal(pc, a+1);
- loadLocalOrConstant( p, builder, pc, c );
+ loadLocalOrConstant(p, builder, pc, c);
builder.getTable();
builder.storeLocal(pc, a);
break;
-
+
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
- for ( int k=b; k<=c; k++ )
- builder.loadLocal(pc, k);
- if ( c > b+1 ) {
+ for (int k = b; k <= c; k++)
+ builder.loadLocal(pc, k);
+ if (c > b+1) {
builder.tobuffer();
- for ( int k=c; --k>=b; )
+ for (int k = c; --k >= b;)
builder.concatbuffer();
builder.tovalue();
} else {
@@ -195,14 +191,14 @@ public class JavaGen {
}
builder.storeLocal(pc, a);
break;
-
+
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
- builder.loadBoolean( b!=0 );
- builder.storeLocal( pc, a );
- if ( c!=0 )
+ builder.loadBoolean(b != 0);
+ builder.storeLocal(pc, a);
+ if (c != 0)
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+2);
break;
-
+
case Lua.OP_JMP: /* sBx pc+=sBx */
if (a > 0) {
for (int i = a-1; i < pi.openups.length; ++i) {
@@ -211,74 +207,77 @@ public class JavaGen {
}
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
break;
-
+
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
- loadLocalOrConstant( p, builder, pc, b );
- loadLocalOrConstant( p, builder, pc, c );
+ loadLocalOrConstant(p, builder, pc, b);
+ loadLocalOrConstant(p, builder, pc, c);
builder.compareop(o);
- builder.addBranch(pc, (a!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
+ builder.addBranch(pc, a != 0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE, pc+2);
break;
-
- case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
- builder.loadLocal( pc, a );
+
+ case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
+ builder.loadLocal(pc, a);
builder.toBoolean();
- builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
+ builder.addBranch(pc, c != 0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE, pc+2);
break;
-
+
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
- builder.loadLocal( pc, b );
+ builder.loadLocal(pc, b);
builder.toBoolean();
- builder.addBranch(pc, (c!=0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE), pc+2);
- builder.loadLocal( pc, b );
- builder.storeLocal( pc, a );
+ builder.addBranch(pc, c != 0? JavaBuilder.BRANCH_IFEQ: JavaBuilder.BRANCH_IFNE, pc+2);
+ builder.loadLocal(pc, b);
+ builder.storeLocal(pc, a);
break;
-
+
case Lua.OP_CALL: { /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
-
+
// load function
builder.loadLocal(pc, a);
-
+
// load args
- int narg = b - 1;
- switch ( narg ) {
- case 0: case 1: case 2: case 3:
- for ( int i=1; i 3
- builder.newVarargs( pc, a+1, b-1 );
+ builder.newVarargs(pc, a+1, b-1);
narg = -1;
break;
case -1: // prev vararg result
- loadVarargResults( builder, pc, a+1, vresultbase );
+ loadVarargResults(builder, pc, a+1, vresultbase);
narg = -1;
break;
}
-
+
// call or invoke
- boolean useinvoke = narg<0 || c<1 || c>2;
- if ( useinvoke )
+ boolean useinvoke = narg < 0 || c < 1 || c > 2;
+ if (useinvoke)
builder.invoke(narg);
else
builder.call(narg);
-
+
// handle results
- switch ( c ) {
- case 1:
- builder.pop();
+ switch (c) {
+ case 1:
+ builder.pop();
break;
case 2:
- if ( useinvoke )
- builder.arg( 1 );
+ if (useinvoke)
+ builder.arg(1);
builder.storeLocal(pc, a);
break;
default: // fixed result count - unpack args
- for ( int i=1; i 1
- builder.newVarargs( pc, a+1, b-1 );
+ builder.newVarargs(pc, a+1, b-1);
break;
case 0: // prev vararg result
- loadVarargResults( builder, pc, a+1, vresultbase );
+ loadVarargResults(builder, pc, a+1, vresultbase);
break;
}
builder.newTailcallVarargs();
builder.areturn();
break;
-
+
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
- if ( c == 1 ) {
+ if (c == 1) {
builder.loadNone();
} else {
- switch ( b ) {
- case 0: loadVarargResults( builder, pc, a, vresultbase ); break;
- case 1: builder.loadNone(); break;
- case 2: builder.loadLocal(pc, a); break;
- default: builder.newVarargs(pc, a, b-1); break;
+ switch (b) {
+ case 0:
+ loadVarargResults(builder, pc, a, vresultbase);
+ break;
+ case 1:
+ builder.loadNone();
+ break;
+ case 2:
+ builder.loadLocal(pc, a);
+ break;
+ default:
+ builder.newVarargs(pc, a, b-1);
+ break;
}
}
- builder.areturn();
+ builder.areturn();
break;
-
+
case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+2);
- builder.binaryop( Lua.OP_SUB );
+ builder.binaryop(Lua.OP_SUB);
builder.storeLocal(pc, a);
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
break;
-
+
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) = R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+2);
- builder.binaryop( Lua.OP_ADD );
+ builder.binaryop(Lua.OP_ADD);
builder.dup();
builder.dup();
builder.storeLocal(pc, a);
@@ -349,20 +356,20 @@ public class JavaGen {
builder.testForLoop();
builder.addBranch(pc, JavaBuilder.BRANCH_IFNE, pc+1+sbx);
break;
-
+
case Lua.OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+1);
builder.loadLocal(pc, a+2);
builder.invoke(2);
- for ( int i=1; i<=c; i++ ) {
- if ( i < c )
+ for (int i = 1; i <= c; i++) {
+ if (i < c)
builder.dup();
- builder.arg( i );
+ builder.arg(i);
builder.storeLocal(pc, a+2+i);
}
break;
-
+
case Lua.OP_TFORLOOP:/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
builder.loadLocal(pc, a+1);
builder.dup();
@@ -370,68 +377,68 @@ public class JavaGen {
builder.isNil();
builder.addBranch(pc, JavaBuilder.BRANCH_IFEQ, pc+1+sbx);
break;
-
+
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
- int index0 = (c-1)*Lua.LFIELDS_PER_FLUSH + 1;
- builder.loadLocal( pc, a );
- if ( b == 0 ) {
- int nstack = vresultbase - (a+1);
- if ( nstack > 0 ) {
- builder.setlistStack( pc, a+1, index0, nstack );
+ int index0 = (c-1)*Lua.LFIELDS_PER_FLUSH+1;
+ builder.loadLocal(pc, a);
+ if (b == 0) {
+ int nstack = vresultbase-(a+1);
+ if (nstack > 0) {
+ builder.setlistStack(pc, a+1, index0, nstack);
index0 += nstack;
}
- builder.setlistVarargs( index0, vresultbase );
+ builder.setlistVarargs(index0, vresultbase);
} else {
- builder.setlistStack( pc, a+1, index0, b );
+ builder.setlistStack(pc, a+1, index0, b);
builder.pop();
}
break;
-
+
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
{
Prototype newp = p.p[bx];
int nup = newp.upvalues.length;
String protoname = pi.subprotos[bx].name;
- builder.closureCreate( protoname );
- if ( nup > 0 )
+ builder.closureCreate(protoname);
+ if (nup > 0)
builder.dup();
- builder.storeLocal( pc, a );
- for ( int up=0; up unloaded = new HashMap<>();
+
+ public JavaLoader() {
+ }
+
+ public LuaFunction load(Prototype p, String classname, String filename, LuaValue env) {
+ JavaGen jg = new JavaGen(p, classname, filename, false);
+ return load(jg, env);
+ }
+
+ public LuaFunction load(JavaGen jg, LuaValue env) {
+ include(jg);
+ return load(jg.classname, env);
+ }
+
+ public LuaFunction load(String classname, LuaValue env) {
+ try {
+ Class c = loadClass(classname);
+ LuaFunction v = (LuaFunction) c.newInstance();
+ v.initupvalue1(env);
+ return v;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new IllegalStateException("bad class gen: " + e);
+ }
+ }
+
+ public void include(JavaGen jg) {
+ unloaded.put(jg.classname, jg.bytecode);
+ for (int i = 0, n = jg.inners != null? jg.inners.length: 0; i < n; i++)
+ include(jg.inners[i]);
+ }
+
+ @Override
+ public Class findClass(String classname) throws ClassNotFoundException {
+ byte[] bytes = unloaded.get(classname);
+ if (bytes != null)
+ return defineClass(classname, bytes, 0, bytes.length);
+ return super.findClass(classname);
+ }
+
+}
diff --git a/src/jse/org/luaj/vm2/luajc/LuaJC.java b/luaj-jse/src/main/java/org/luaj/vm2/luajc/LuaJC.java
similarity index 68%
rename from src/jse/org/luaj/vm2/luajc/LuaJC.java
rename to luaj-jse/src/main/java/org/luaj/vm2/luajc/LuaJC.java
index 4b74ef4f..9fd694b6 100644
--- a/src/jse/org/luaj/vm2/luajc/LuaJC.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/luajc/LuaJC.java
@@ -10,7 +10,7 @@
*
* 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
@@ -34,99 +34,105 @@ import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC;
/**
- * Implementation of {@link org.luaj.vm2.Globals.Compiler} which does direct
- * lua-to-java-bytecode compiling.
+ * Implementation of {@link org.luaj.vm2.Globals.Compiler} which does direct
+ * lua-to-java-bytecode compiling.
*
- * By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
- * {@link org.luaj.vm2.lib.jme.JmePlatform}
- * to construct globals, the plain compiler {@link LuaC} is installed and lua code
- * will only be compiled into lua bytecode and execute as {@link LuaClosure}.
+ * By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
+ * {@link org.luaj.vm2.lib.jme.JmePlatform} to construct globals, the plain
+ * compiler {@link LuaC} is installed and lua code will only be compiled into
+ * lua bytecode and execute as {@link LuaClosure}.
*
- * To override the default compiling behavior with {@link LuaJC}
- * lua-to-java bytecode compiler, install it before undumping code,
- * for example:
- *
{@code
+ * To override the default compiling behavior with {@link LuaJC} lua-to-java
+ * bytecode compiler, install it before undumping code, for example:
+ *
+ *
+ * {@code
* LuaValue globals = JsePlatform.standardGlobals();
* LuaJC.install(globals);
* LuaValue chunk = globals.load( "print('hello, world'), "main.lua");
* System.out.println(chunk.isclosure()); // Will be false when LuaJC is working.
* chunk.call();
- * }
+ * }
+ *
*
- * This requires the bcel library to be on the class path to work as expected.
- * If the library is not found, the default {@link LuaC} lua-to-lua-bytecode
- * compiler will be used.
- *
+ * This requires the bcel library to be on the class path to work as expected.
+ * If the library is not found, the default {@link LuaC} lua-to-lua-bytecode
+ * compiler will be used.
+ *
* @see Globals#compiler
* @see #install(Globals)
* @see org.luaj.vm2.compiler.LuaC
* @see LuaValue
*/
public class LuaJC implements Globals.Loader {
-
+
public static final LuaJC instance = new LuaJC();
-
- /**
- * Install the compiler as the main Globals.Loader to use in a set of globals.
- * Will fall back to the LuaC prototype compiler.
+
+ /**
+ * 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(Globals G) {
- G.loader = instance;
+ G.loader = instance;
}
-
+
protected LuaJC() {}
- public Hashtable compileAll(InputStream script, String chunkname, String filename, Globals globals, boolean genmain) throws IOException {
- final String classname = toStandardJavaClassName( chunkname );
+ 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(Reader script, String chunkname, String filename, Globals globals, boolean genmain) throws IOException {
- final String classname = toStandardJavaClassName( chunkname );
+
+ 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 );
+
+ 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 );
+ insert(h, gen);
return h;
}
-
+
private void insert(Hashtable h, JavaGen gen) {
h.put(gen.classname, gen.bytecode);
- for ( int i=0, n=gen.inners!=null? gen.inners.length: 0; i 0) && Character.isJavaIdentifierPart(c)))? c: '_');
+ classname.append(
+ i == 0 && Character.isJavaIdentifierStart(c) || i > 0 && Character.isJavaIdentifierPart(c)? c: '_');
}
return classname.toString();
}
-
- private static String toStandardLuaFileName( String luachunkname ) {
- String stub = toStub( luachunkname );
- String filename = stub.replace('.','/')+".lua";
+
+ private static String toStandardLuaFileName(String luachunkname) {
+ String stub = toStub(luachunkname);
+ String filename = stub.replace('.', '/') + ".lua";
return filename.startsWith("@")? filename.substring(1): filename;
}
-
- private static String toStub( String s ) {
- String stub = s.endsWith(".lua")? s.substring(0,s.length()-4): s;
- return stub;
+
+ private static String toStub(String s) {
+ return s.endsWith(".lua")? s.substring(0, s.length()-4): s;
}
}
diff --git a/src/jse/org/luaj/vm2/luajc/ProtoInfo.java b/luaj-jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java
similarity index 54%
rename from src/jse/org/luaj/vm2/luajc/ProtoInfo.java
rename to luaj-jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java
index 0d33f00a..c34c8586 100644
--- a/src/jse/org/luaj/vm2/luajc/ProtoInfo.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java
@@ -15,39 +15,39 @@ import org.luaj.vm2.Upvaldesc;
*/
public class ProtoInfo {
- public final String name;
- public final Prototype prototype; // the prototype that this info is about
- public final ProtoInfo[] subprotos; // one per enclosed prototype, or null
- public final BasicBlock[] blocks; // basic block analysis of code branching
- public final BasicBlock[] blocklist; // blocks in breadth-first order
- public final VarInfo[] params; // Parameters and initial values of stack variables
- public final VarInfo[][] vars; // Each variable
- public final UpvalInfo[] upvals; // from outer scope
+ public final String name;
+ public final Prototype prototype; // the prototype that this info is about
+ public final ProtoInfo[] subprotos; // one per enclosed prototype, or null
+ public final BasicBlock[] blocks; // basic block analysis of code branching
+ public final BasicBlock[] blocklist; // blocks in breadth-first order
+ public final VarInfo[] params; // Parameters and initial values of stack variables
+ public final VarInfo[][] vars; // Each variable
+ public final UpvalInfo[] upvals; // from outer scope
public final UpvalInfo[][] openups; // per slot, upvalues allocated by this prototype
-
+
// A main chunk proto info.
public ProtoInfo(Prototype p, String name) {
// For the outer chunk, we have one upvalue which is the environment.
- this(p,name,null);
+ this(p, name, null);
}
-
+
private ProtoInfo(Prototype p, String name, UpvalInfo[] u) {
this.name = name;
this.prototype = p;
this.upvals = u != null? u: new UpvalInfo[] { new UpvalInfo(this) };
- this.subprotos = p.p!=null&&p.p.length>0? new ProtoInfo[p.p.length]: null;
-
+ this.subprotos = p.p != null && p.p.length > 0? new ProtoInfo[p.p.length]: null;
+
// find basic blocks
this.blocks = BasicBlock.findBasicBlocks(p);
this.blocklist = BasicBlock.findLiveBlocks(blocks);
-
+
// params are inputs to first block
this.params = new VarInfo[p.maxstacksize];
- for ( int slot=0; slot b0.pc0 )
- propogateVars( v, pc-1, pc );
-
- int a,b,c;
+ if (pc > b0.pc0)
+ propogateVars(v, pc-1, pc);
+
+ int a, b, c;
int ins = prototype.code[pc];
int op = Lua.GET_OPCODE(ins);
-
+
// account for assignments, references and invalidations
- switch ( op ) {
+ switch (op) {
case Lua.OP_LOADK:/* A Bx R(A) := Kst(Bx) */
case Lua.OP_LOADBOOL:/* A B C R(A) := (Bool)B; if (C) pc++ */
case Lua.OP_GETUPVAL: /* A B R(A) := UpValue[B] */
case Lua.OP_NEWTABLE: /* A B C R(A) := {} (size = B,C) */
- a = Lua.GETARG_A( ins );
- v[a][pc] = new VarInfo(a,pc);
+ a = Lua.GETARG_A(ins);
+ v[a][pc] = new VarInfo(a, pc);
break;
-
- case Lua.OP_MOVE:/* A B R(A) := R(B) */
+
+ case Lua.OP_MOVE:/* A B R(A) := R(B) */
case Lua.OP_UNM: /* A B R(A) := -R(B) */
case Lua.OP_NOT: /* A B R(A) := not R(B) */
case Lua.OP_LEN: /* A B R(A) := length of R(B) */
- case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
+ case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
v[b][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ v[a][pc] = new VarInfo(a, pc);
break;
-
+
case Lua.OP_ADD: /* A B C R(A) := RK(B) + RK(C) */
case Lua.OP_SUB: /* A B C R(A) := RK(B) - RK(C) */
case Lua.OP_MUL: /* A B C R(A) := RK(B) * RK(C) */
case Lua.OP_DIV: /* A B C R(A) := RK(B) / RK(C) */
case Lua.OP_MOD: /* A B C R(A) := RK(B) % RK(C) */
case Lua.OP_POW: /* A B C R(A) := RK(B) ^ RK(C) */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
- if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
+ if (!Lua.ISK(b))
+ v[b][pc].isreferenced = true;
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
+ v[a][pc] = new VarInfo(a, pc);
break;
-
+
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
v[a][pc].isreferenced = true;
- if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
+ if (!Lua.ISK(b))
+ v[b][pc].isreferenced = true;
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
break;
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
- if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
- break;
-
- case Lua.OP_CONCAT: /* A B C R(A) := R(B).. ... ..R(C) */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
- for ( ; b<=c; b++ )
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
+ if (!Lua.ISK(b))
v[b][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
break;
-
+
+ case Lua.OP_CONCAT: /* A B C R(A) := R(B).. ... ..R(C) */
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
+ for (; b <= c; b++)
+ v[b][pc].isreferenced = true;
+ v[a][pc] = new VarInfo(a, pc);
+ break;
+
case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2); pc+=sBx */
- a = Lua.GETARG_A( ins );
+ a = Lua.GETARG_A(ins);
v[a+2][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ v[a][pc] = new VarInfo(a, pc);
break;
-
+
case Lua.OP_GETTABLE: /* A B C R(A) := R(B)[RK(C)] */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
v[b][pc].isreferenced = true;
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
+ v[a][pc] = new VarInfo(a, pc);
break;
-
+
case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
- a = Lua.GETARG_A( ins );
- c = Lua.GETARG_C( ins );
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ a = Lua.GETARG_A(ins);
+ c = Lua.GETARG_C(ins);
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
+ v[a][pc] = new VarInfo(a, pc);
break;
case Lua.OP_SELF: /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
v[b][pc].isreferenced = true;
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
- v[a+1][pc] = new VarInfo(a+1,pc);
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
+ v[a][pc] = new VarInfo(a, pc);
+ v[a+1][pc] = new VarInfo(a+1, pc);
break;
-
+
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2);
- if R(A) = R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
- a = Lua.GETARG_A( ins );
+ if R(A) = R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+ a = Lua.GETARG_A(ins);
v[a][pc].isreferenced = true;
v[a+2][pc].isreferenced = true;
- v[a][pc] = new VarInfo(a,pc);
+ v[a][pc] = new VarInfo(a, pc);
v[a][pc].isreferenced = true;
v[a+1][pc].isreferenced = true;
- v[a+3][pc] = new VarInfo(a+3,pc);
+ v[a+3][pc] = new VarInfo(a+3, pc);
break;
case Lua.OP_LOADNIL: /* A B R(A) := ... := R(A+B) := nil */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- for ( ; b-->=0; a++ )
- v[a][pc] = new VarInfo(a,pc);
+ a = Lua.GETARG_A(ins);
+ b = Lua.GETARG_B(ins);
+ for (; b-- >= 0; a++)
+ v[a][pc] = new VarInfo(a, pc);
break;
-
- case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
- a = Lua.GETARG_A( ins );
- b = Lua.GETARG_B( ins );
- for ( int j=1; j C) then pc++ */
- a = Lua.GETARG_A( ins );
+ case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
+ a = Lua.GETARG_A(ins);
v[a][pc].isreferenced = true;
break;
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
- b = Lua.GETARG_B( ins );
- c = Lua.GETARG_C( ins );
- if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
- if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
+ b = Lua.GETARG_B(ins);
+ c = Lua.GETARG_C(ins);
+ if (!Lua.ISK(b))
+ v[b][pc].isreferenced = true;
+ if (!Lua.ISK(c))
+ v[c][pc].isreferenced = true;
break;
case Lua.OP_JMP: /* sBx pc+=sBx */
- a = Lua.GETARG_A( ins );
+ a = Lua.GETARG_A(ins);
if (a > 0)
- for ( --a; a 0 && vars[slot][pc] != null && vars[slot][pc].pc == pc && vars[slot][pc-1] != null )
+ if (pc > 0 && vars[slot][pc] != null && vars[slot][pc].pc == pc && vars[slot][pc-1] != null)
pc -= 1;
- VarInfo v = pc<0? params[slot]: vars[slot][pc];
+ VarInfo v = pc < 0? params[slot]: vars[slot][pc];
return v != null && v.upvalue != null && v.upvalue.rw;
}
@@ -472,49 +485,49 @@ public class ProtoInfo {
public boolean isReadWriteUpvalue(UpvalInfo u) {
return u.rw;
}
-
+
private String[] findInnerprotoNames() {
if (prototype.p.length <= 0)
return null;
// find all the prototype names
String[] names = new String[prototype.p.length];
- Hashtable used = new Hashtable();
+ Hashtable used = new Hashtable();
int[] code = prototype.code;
int n = code.length;
- for ( int pc=0; pc 1;
+ }
+
+ private boolean includeVarAndPosteriorVars(VarInfo var) {
+ if (var == null || var == VarInfo.INVALID)
+ return false;
+ if (var.upvalue == this)
+ return true;
+ var.upvalue = this;
+ appendVar(var);
+ if (isLoopVariable(var))
+ return false;
+ boolean loopDetected = includePosteriorVarsCheckLoops(var);
+ if (loopDetected)
+ includePriorVarsIgnoreLoops(var);
+ return loopDetected;
+ }
+
+ private boolean isLoopVariable(VarInfo var) {
+ if (var.pc >= 0) {
+ switch (Lua.GET_OPCODE(pi.prototype.code[var.pc])) {
+ case Lua.OP_TFORLOOP:
+ case Lua.OP_FORLOOP:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean includePosteriorVarsCheckLoops(VarInfo prior) {
+ boolean loopDetected = false;
+ for (BasicBlock b : pi.blocklist) {
+ VarInfo v = pi.vars[slot][b.pc1];
+ if (v == prior) {
+ for (int j = 0, m = b.next != null? b.next.length: 0; j < m; j++) {
+ BasicBlock b1 = b.next[j];
+ VarInfo v1 = pi.vars[slot][b1.pc0];
+ if (v1 != prior) {
+ loopDetected |= includeVarAndPosteriorVars(v1);
+ if (v1.isPhiVar())
+ includePriorVarsIgnoreLoops(v1);
+ }
+ }
+ } else {
+ for (int pc = b.pc1-1; pc >= b.pc0; pc--) {
+ if (pi.vars[slot][pc] == prior) {
+ loopDetected |= includeVarAndPosteriorVars(pi.vars[slot][pc+1]);
+ break;
+ }
+ }
+ }
+ }
+ return loopDetected;
+ }
+
+ private void includePriorVarsIgnoreLoops(VarInfo poster) {
+ for (BasicBlock b : pi.blocklist) {
+ VarInfo v = pi.vars[slot][b.pc0];
+ if (v == poster) {
+ for (int j = 0, m = b.prev != null? b.prev.length: 0; j < m; j++) {
+ BasicBlock b0 = b.prev[j];
+ VarInfo v0 = pi.vars[slot][b0.pc1];
+ if (v0 != poster)
+ includeVarAndPosteriorVars(v0);
+ }
+ } else {
+ for (int pc = b.pc0+1; pc <= b.pc1; pc++) {
+ if (pi.vars[slot][pc] == poster) {
+ includeVarAndPosteriorVars(pi.vars[slot][pc-1]);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private void appendVar(VarInfo v) {
+ if (nvars == 0) {
+ var = new VarInfo[1];
+ } else if (nvars+1 >= var.length) {
+ VarInfo[] s = var;
+ var = new VarInfo[nvars*2+1];
+ System.arraycopy(s, 0, var, 0, nvars);
+ }
+ var[nvars++] = v;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(pi.name);
+ for (int i = 0; i < nvars; i++) {
+ sb.append(i > 0? ",": " ");
+ sb.append(String.valueOf(var[i]));
+ }
+ if (rw)
+ sb.append("(rw)");
+ return sb.toString();
+ }
+
+ private boolean testIsAllocUpvalue(VarInfo v) {
+ if (v.pc < 0)
+ return true;
+ BasicBlock b = pi.blocks[v.pc];
+ if (v.pc > b.pc0)
+ return pi.vars[slot][v.pc-1].upvalue != this;
+ if (b.prev == null) {
+ v = pi.params[slot];
+ if (v != null && v.upvalue != this)
+ return true;
+ } else {
+ for (BasicBlock element : b.prev) {
+ v = pi.vars[slot][element.pc1];
+ if (v != null && v.upvalue != this)
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/src/jse/org/luaj/vm2/luajc/VarInfo.java b/luaj-jse/src/main/java/org/luaj/vm2/luajc/VarInfo.java
similarity index 75%
rename from src/jse/org/luaj/vm2/luajc/VarInfo.java
rename to luaj-jse/src/main/java/org/luaj/vm2/luajc/VarInfo.java
index 6cc006e0..00f7c460 100644
--- a/src/jse/org/luaj/vm2/luajc/VarInfo.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/luajc/VarInfo.java
@@ -1,5 +1,5 @@
/**
- *
+ *
*/
package org.luaj.vm2.luajc;
@@ -24,10 +24,10 @@ public class VarInfo {
}
public final int slot; // where assigned
- public final int pc; // where assigned, or -1 if for block inputs
+ public final int pc; // where assigned, or -1 if for block inputs
- public UpvalInfo upvalue; // not null if this var is an upvalue
- public boolean allocupvalue; // true if this variable allocates r/w upvalue
+ public UpvalInfo upvalue; // not null if this var is an upvalue
+ public boolean allocupvalue; // true if this variable allocates r/w upvalue
// storage
public boolean isreferenced; // true if this variable is refenced by some
// opcode
@@ -37,15 +37,18 @@ public class VarInfo {
this.pc = pc;
}
+ @Override
public String toString() {
- return slot < 0 ? "x.x" : (slot + "." + pc);
+ return slot < 0? "x.x": slot + "." + pc;
}
- /** Return replacement variable if there is exactly one value possible,
- * otherwise compute entire collection of variables and return null.
- * Computes the list of aall variable values, and saves it for the future.
- *
- * @return new Variable to replace with if there is only one value, or null to leave alone.
+ /**
+ * Return replacement variable if there is exactly one value possible,
+ * otherwise compute entire collection of variables and return null.
+ * Computes the list of aall variable values, and saves it for the future.
+ *
+ * @return new Variable to replace with if there is only one value, or null
+ * to leave alone.
*/
public VarInfo resolvePhiVariableValues() {
return null;
@@ -55,15 +58,14 @@ public class VarInfo {
vars.add(this);
}
- public boolean isPhiVar() {
- return false;
- }
+ public boolean isPhiVar() { return false; }
private static final class ParamVarInfo extends VarInfo {
private ParamVarInfo(int slot, int pc) {
super(slot, pc);
}
+ @Override
public String toString() {
return slot + ".p";
}
@@ -74,6 +76,7 @@ public class VarInfo {
super(slot, pc);
}
+ @Override
public String toString() {
return "nil";
}
@@ -81,30 +84,31 @@ public class VarInfo {
private static final class PhiVarInfo extends VarInfo {
private final ProtoInfo pi;
- VarInfo[] values;
+ VarInfo[] values;
private PhiVarInfo(ProtoInfo pi, int slot, int pc) {
super(slot, pc);
this.pi = pi;
}
- public boolean isPhiVar() {
- return true;
- }
+ @Override
+ public boolean isPhiVar() { return true; }
+ @Override
public String toString() {
StringBuffer sb = new StringBuffer();
- sb.append( super.toString() );
+ sb.append(super.toString());
sb.append("={");
- for (int i=0, n=(values!=null? values.length : 0); i0 )
- sb.append( "," );
+ for (int i = 0, n = values != null? values.length: 0; i < n; i++) {
+ if (i > 0)
+ sb.append(",");
sb.append(String.valueOf(values[i]));
}
sb.append("}");
return sb.toString();
}
+ @Override
public VarInfo resolvePhiVariableValues() {
Set visitedBlocks = new HashSet();
Set vars = new HashSet();
@@ -119,26 +123,27 @@ public class VarInfo {
return v;
}
this.values = new VarInfo[n];
- for ( int i=0; i
- * This engine requires the types of the Bindings and ScriptContext to be
- * compatible with the engine. For creating new client context use
- * ScriptEngine.createContext() which will return {@link LuajContext},
- * and for client bindings use the default engine scoped bindings or
- * construct a {@link LuajBindings} directly.
+ * This engine requires the types of the Bindings and ScriptContext to be
+ * compatible with the engine. For creating new client context use
+ * ScriptEngine.createContext() which will return {@link LuajContext}, and for
+ * client bindings use the default engine scoped bindings or construct a
+ * {@link LuajBindings} directly.
*/
public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngine, Compilable {
-
- private static final String __ENGINE_VERSION__ = Lua._VERSION;
- private static final String __NAME__ = "Luaj";
- private static final String __SHORT_NAME__ = "Luaj";
- private static final String __LANGUAGE__ = "lua";
- private static final String __LANGUAGE_VERSION__ = "5.2";
- private static final String __ARGV__ = "arg";
- private static final String __FILENAME__ = "?";
-
- private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory();
-
- private LuajContext context;
- public LuaScriptEngine() {
- // set up context
- context = new LuajContext();
- context.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
- setContext(context);
-
- // set special values
- put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
- put(LANGUAGE, __LANGUAGE__);
- put(ENGINE, __NAME__);
- put(ENGINE_VERSION, __ENGINE_VERSION__);
- put(ARGV, __ARGV__);
- put(FILENAME, __FILENAME__);
- put(NAME, __SHORT_NAME__);
- put("THREADING", null);
- }
+ private static final String __ENGINE_VERSION__ = Lua._VERSION;
+ private static final String __NAME__ = "Luaj";
+ private static final String __SHORT_NAME__ = "Luaj";
+ private static final String __LANGUAGE__ = "lua";
+ private static final String __LANGUAGE_VERSION__ = "5.2";
+ private static final String __ARGV__ = "arg";
+ private static final String __FILENAME__ = "?";
+
+ private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory();
+
+ private final LuajContext context;
+
+ public LuaScriptEngine() {
+ // set up context
+ context = new LuajContext();
+ context.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
+ setContext(context);
+
+ // set special values
+ put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
+ put(LANGUAGE, __LANGUAGE__);
+ put(ENGINE, __NAME__);
+ put(ENGINE_VERSION, __ENGINE_VERSION__);
+ put(ARGV, __ARGV__);
+ put(FILENAME, __FILENAME__);
+ put(NAME, __SHORT_NAME__);
+ put("THREADING", null);
+ }
@Override
public CompiledScript compile(String script) throws ScriptException {
@@ -80,18 +98,15 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
@Override
public CompiledScript compile(Reader script) throws ScriptException {
try {
- InputStream is = new Utf8Encoder(script);
- try {
- final Globals g = context.globals;
- final LuaFunction f = g.load(script, "script").checkfunction();
- return new LuajCompiledScript(f, g);
- } catch ( LuaError lee ) {
- throw new ScriptException(lee.getMessage() );
- } finally {
- is.close();
+ try (InputStream is = new Utf8Encoder(script)) {
+ final Globals g = context.globals;
+ final LuaFunction f = g.load(script, "script").checkfunction();
+ return new LuajCompiledScript(f, g);
+ } catch (LuaError lee) {
+ throw new ScriptException(lee.getMessage());
}
- } catch ( Exception e ) {
- throw new ScriptException("eval threw "+e.toString());
+ } catch (Exception e) {
+ throw new ScriptException("eval threw " + e.toString());
}
}
@@ -116,49 +131,47 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
}
@Override
- public Object eval(String script, ScriptContext context)
- throws ScriptException {
+ public Object eval(String script, ScriptContext context) throws ScriptException {
return eval(new StringReader(script), context);
}
@Override
- public Object eval(Reader reader, ScriptContext context)
- throws ScriptException {
- return compile(reader).eval(context);
+ public Object eval(Reader reader, ScriptContext context) throws ScriptException {
+ return compile(reader).eval(context);
}
@Override
- public ScriptEngineFactory getFactory() {
- return myFactory;
- }
-
+ public ScriptEngineFactory getFactory() { return myFactory; }
class LuajCompiledScript extends CompiledScript {
final LuaFunction function;
- final Globals compiling_globals;
+ final Globals compiling_globals;
+
LuajCompiledScript(LuaFunction function, Globals compiling_globals) {
this.function = function;
this.compiling_globals = compiling_globals;
}
- public ScriptEngine getEngine() {
- return LuaScriptEngine.this;
+ @Override
+ public ScriptEngine getEngine() { return LuaScriptEngine.this; }
+
+ @Override
+ public Object eval() throws ScriptException {
+ return eval(getContext());
}
- public Object eval() throws ScriptException {
- return eval(getContext());
- }
-
- public Object eval(Bindings bindings) throws ScriptException {
- return eval(((LuajContext) getContext()).globals, bindings);
- }
-
- public Object eval(ScriptContext context) throws ScriptException {
- return eval(((LuajContext) context).globals, context.getBindings(ScriptContext.ENGINE_SCOPE));
+ @Override
+ public Object eval(Bindings bindings) throws ScriptException {
+ return eval(((LuajContext) getContext()).globals, bindings);
}
-
- Object eval(Globals g, Bindings b) throws ScriptException {
- g.setmetatable(new BindingsMetatable(b));
+
+ @Override
+ public Object eval(ScriptContext context) throws ScriptException {
+ return eval(((LuajContext) context).globals, context.getBindings(ScriptContext.ENGINE_SCOPE));
+ }
+
+ Object eval(Globals g, Bindings b) throws ScriptException {
+ g.setmetatable(new BindingsMetatable(b));
LuaFunction f = function;
if (f.isclosure())
f = new LuaClosure(f.checkclosure().p, g);
@@ -174,47 +187,50 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
}
}
- // ------ convert char stream to byte stream for lua compiler -----
+ // ------ convert char stream to byte stream for lua compiler -----
private final class Utf8Encoder extends InputStream {
private final Reader r;
- private final int[] buf = new int[2];
- private int n;
+ private final int[] buf = new int[2];
+ private int n;
private Utf8Encoder(Reader r) {
this.r = r;
}
+ @Override
public int read() throws IOException {
- if ( n > 0 )
+ if (n > 0)
return buf[--n];
int c = r.read();
- if ( c < 0x80 )
+ if (c < 0x80)
return c;
n = 0;
- if ( c < 0x800 ) {
- buf[n++] = (0x80 | ( c & 0x3f));
- return (0xC0 | ((c>>6) & 0x1f));
+ if (c < 0x800) {
+ buf[n++] = 0x80 | c & 0x3f;
+ return 0xC0 | c>>6 & 0x1f;
} else {
- buf[n++] = (0x80 | ( c & 0x3f));
- buf[n++] = (0x80 | ((c>>6) & 0x3f));
- return (0xE0 | ((c>>12) & 0x0f));
+ buf[n++] = 0x80 | c & 0x3f;
+ buf[n++] = 0x80 | c>>6 & 0x3f;
+ return 0xE0 | c>>12 & 0x0f;
}
}
}
-
+
static class BindingsMetatable extends LuaTable {
BindingsMetatable(final Bindings bindings) {
this.rawset(LuaValue.INDEX, new TwoArgFunction() {
+ @Override
public LuaValue call(LuaValue table, LuaValue key) {
- if (key.isstring())
+ if (key.isstring())
return toLua(bindings.get(key.tojstring()));
else
return this.rawget(key);
}
});
this.rawset(LuaValue.NEWINDEX, new ThreeArgFunction() {
+ @Override
public LuaValue call(LuaValue table, LuaValue key, LuaValue value) {
if (key.isstring()) {
final String k = key.tojstring();
@@ -231,33 +247,38 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
});
}
}
-
+
static private LuaValue toLua(Object javaValue) {
- return javaValue == null? LuaValue.NIL:
- javaValue instanceof LuaValue? (LuaValue) javaValue:
- CoerceJavaToLua.coerce(javaValue);
+ return javaValue == null? LuaValue.NIL
+ : javaValue instanceof LuaValue? (LuaValue) javaValue: CoerceJavaToLua.coerce(javaValue);
}
static private Object toJava(LuaValue luajValue) {
- switch ( luajValue.type() ) {
- case LuaValue.TNIL: return null;
- case LuaValue.TSTRING: return luajValue.tojstring();
- case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
- case LuaValue.TNUMBER: return luajValue.isinttype()?
- (Object) new Integer(luajValue.toint()):
- (Object) new Double(luajValue.todouble());
- default: return luajValue;
+ switch (luajValue.type()) {
+ case LuaValue.TNIL:
+ return null;
+ case LuaValue.TSTRING:
+ return luajValue.tojstring();
+ case LuaValue.TUSERDATA:
+ return luajValue.checkuserdata(Object.class);
+ case LuaValue.TNUMBER:
+ return luajValue.isinttype()? (Object) Integer.valueOf(luajValue.toint())
+ : (Object) Double.valueOf(luajValue.todouble());
+ default:
+ return luajValue;
}
}
static private Object toJava(Varargs v) {
final int n = v.narg();
switch (n) {
- case 0: return null;
- case 1: return toJava(v.arg1());
+ case 0:
+ return null;
+ case 1:
+ return toJava(v.arg1());
default:
Object[] o = new Object[n];
- for (int i=0; i extensions;
+ private final List mimeTypes;
+ private final List names;
+
+ public LuaScriptEngineFactory() {
+ extensions = Arrays.asList(EXTENSIONS);
+ mimeTypes = Arrays.asList(MIMETYPES);
+ names = Arrays.asList(NAMES);
+ }
+
+ @Override
+ public String getEngineName() { return getScriptEngine().get(ScriptEngine.ENGINE).toString(); }
+
+ @Override
+ public String getEngineVersion() { return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString(); }
+
+ @Override
+ public List getExtensions() { return extensions; }
+
+ @Override
+ public List getMimeTypes() { return mimeTypes; }
+
+ @Override
+ public List getNames() { return names; }
+
+ @Override
+ public String getLanguageName() { return getScriptEngine().get(ScriptEngine.LANGUAGE).toString(); }
+
+ @Override
+ public String getLanguageVersion() { return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString(); }
+
+ @Override
+ public Object getParameter(String key) {
+ return getScriptEngine().get(key).toString();
+ }
+
+ @Override
+ public String getMethodCallSyntax(String obj, String m, String... args) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(obj + ":" + m + "(");
+ int len = args.length;
+ for (int i = 0; i < len; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(args[i]);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ @Override
+ public String getOutputStatement(String toDisplay) {
+ return "print(" + toDisplay + ")";
+ }
+
+ @Override
+ public String getProgram(String... statements) {
+ StringBuffer sb = new StringBuffer();
+ int len = statements.length;
+ for (int i = 0; i < len; i++) {
+ if (i > 0) {
+ sb.append('\n');
+ }
+ sb.append(statements[i]);
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public ScriptEngine getScriptEngine() { return new LuaScriptEngine(); }
+}
diff --git a/src/jse/org/luaj/vm2/script/LuajContext.java b/luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java
similarity index 62%
rename from src/jse/org/luaj/vm2/script/LuajContext.java
rename to luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java
index 4668e41c..038dd867 100644
--- a/src/jse/org/luaj/vm2/script/LuajContext.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java
@@ -10,7 +10,7 @@
*
* 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
@@ -35,9 +35,9 @@ 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,
- * and manages the input and output redirection.
+/**
+ * Context for LuaScriptEngine execution which maintains its own Globals, and
+ * manages the input and output redirection.
*/
public class LuajContext extends SimpleScriptContext implements ScriptContext {
@@ -50,93 +50,96 @@ public class LuajContext extends SimpleScriptContext implements ScriptContext {
private final PrintStream stdout;
/** The initial value of globals.STDERR */
private final PrintStream stderr;
-
- /** Construct a LuajContext with its own globals which may
- * be debug globals depending on the value of the system
- * property 'org.luaj.debug'
+
+ /**
+ * Construct a LuajContext with its own globals which may be debug globals
+ * depending on the value of the system property 'org.luaj.debug'
*
- * If the system property 'org.luaj.debug' is set, the globals
- * created will be a debug globals that includes the debug
- * library. This may provide better stack traces, but may
- * have negative impact on performance.
+ * If the system property 'org.luaj.debug' is set, the globals created will
+ * be a debug globals that includes the debug library. This may provide
+ * better stack traces, but may have negative impact on performance.
*/
public LuajContext() {
- this("true".equals(System.getProperty("org.luaj.debug")),
- "true".equals(System.getProperty("org.luaj.luajc")));
+ 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, and optionally use the
- * luajc direct lua to java bytecode compiler.
+ /**
+ * Construct a LuajContext with its own globals, which which optionally are
+ * debug globals, and optionally use the luajc direct lua to java bytecode
+ * compiler.
*
- * If createDebugGlobals is set, the globals
- * created will be a debug globals that includes the debug
- * library. This may provide better stack traces, but may
- * 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.
+ * If createDebugGlobals is set, the globals created will be a debug globals
+ * that includes the debug library. This may provide better stack traces,
+ * but may 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, boolean useLuaJCCompiler) {
- globals = createDebugGlobals?
- JsePlatform.debugGlobals():
- JsePlatform.standardGlobals();
- if (useLuaJCCompiler)
- LuaJC.install(globals);
- stdin = globals.STDIN;
- stdout = globals.STDOUT;
- stderr = globals.STDERR;
- }
-
- @Override
- public void setErrorWriter(Writer writer) {
- globals.STDERR = writer != null?
- new PrintStream(new WriterOutputStream(writer)):
- stderr;
+ globals = createDebugGlobals? JsePlatform.debugGlobals(): JsePlatform.standardGlobals();
+ if (useLuaJCCompiler)
+ LuaJC.install(globals);
+ stdin = globals.STDIN;
+ stdout = globals.STDOUT;
+ stderr = globals.STDERR;
}
@Override
- public void setReader(Reader reader) {
- globals.STDIN = reader != null?
- new ReaderInputStream(reader):
- stdin;
+ public void setErrorWriter(Writer writer) {
+ globals.STDERR = writer != null? new PrintStream(new WriterOutputStream(writer)): stderr;
}
+ @Override
+ public void setReader(Reader reader) { globals.STDIN = reader != null? new ReaderInputStream(reader): stdin; }
+
@Override
public void setWriter(Writer writer) {
- globals.STDOUT = writer != null?
- new PrintStream(new WriterOutputStream(writer), true):
- stdout;
+ globals.STDOUT = writer != null? new PrintStream(new WriterOutputStream(writer), true): stdout;
}
static final class WriterOutputStream extends OutputStream {
final Writer w;
+
WriterOutputStream(Writer w) {
this.w = w;
}
+
+ @Override
public void write(int b) throws IOException {
- w.write(new String(new byte[] {(byte)b}));
+ w.write(new String(new byte[] { (byte) b }));
}
+
+ @Override
public void write(byte[] b, int o, int l) throws IOException {
w.write(new String(b, o, l));
}
+
+ @Override
public void write(byte[] b) throws IOException {
w.write(new String(b));
}
+
+ @Override
public void close() throws IOException {
w.close();
}
+
+ @Override
public void flush() throws IOException {
w.flush();
}
}
-
+
static final class ReaderInputStream extends InputStream {
final Reader r;
+
ReaderInputStream(Reader r) {
this.r = r;
}
+
+ @Override
public int read() throws IOException {
return r.read();
}
diff --git a/src/jse/org/luaj/vm2/server/DefaultLauncher.java b/luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java
similarity index 93%
rename from src/jse/org/luaj/vm2/server/DefaultLauncher.java
rename to luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java
index 098f64a4..cebf12b8 100644
--- a/src/jse/org/luaj/vm2/server/DefaultLauncher.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java
@@ -10,7 +10,7 @@
*
* 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
@@ -31,14 +31,14 @@ import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.lib.jse.JsePlatform;
/**
- * Default {@link Launcher} instance that creates standard globals
- * and runs the supplied scripts with chunk name 'main'.
+ * Default {@link Launcher} instance that creates standard globals and runs the
+ * supplied scripts with chunk name 'main'.
*
* Arguments are coerced into lua using {@link CoerceJavaToLua#coerce(Object)}.
*
- * Return values with simple types are coerced into Java simple types.
- * Tables, threads, and functions are returned as lua objects.
- *
+ * Return values with simple types are coerced into Java simple types. Tables,
+ * threads, and functions are returned as lua objects.
+ *
* @see Launcher
* @see LuajClassLoader
* @see LuajClassLoader#NewLauncher()
@@ -51,18 +51,23 @@ public class DefaultLauncher implements Launcher {
public DefaultLauncher() {
g = JsePlatform.standardGlobals();
}
-
+
/** Launches the script with chunk name 'main' */
+ @Override
public Object[] launch(String script, Object[] arg) {
return launchChunk(g.load(script, "main"), arg);
}
- /** Launches the script with chunk name 'main' and loading using modes 'bt' */
+ /**
+ * Launches the script with chunk name 'main' and loading using modes 'bt'
+ */
+ @Override
public Object[] launch(InputStream script, Object[] arg) {
return launchChunk(g.load(script, "main", "bt", g), arg);
}
/** Launches the script with chunk name 'main' */
+ @Override
public Object[] launch(Reader script, Object[] arg) {
return launchChunk(g.load(script, "main"), arg);
}
@@ -102,4 +107,4 @@ public class DefaultLauncher implements Launcher {
}
return return_values;
}
-}
\ No newline at end of file
+}
diff --git a/src/jse/org/luaj/vm2/server/Launcher.java b/luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java
similarity index 66%
rename from src/jse/org/luaj/vm2/server/Launcher.java
rename to luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java
index 378f7c81..1707e55e 100644
--- a/src/jse/org/luaj/vm2/server/Launcher.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java
@@ -10,7 +10,7 @@
*
* 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
@@ -24,16 +24,19 @@ package org.luaj.vm2.server;
import java.io.InputStream;
import java.io.Reader;
-/** Interface to launch lua scripts using the {@link LuajClassLoader}.
+/**
+ * Interface to launch lua scripts using the {@link LuajClassLoader}.
*
- * Note: This class is experimental and subject to change in future versions.
+ * Note: This class is experimental and subject to change in future
+ * versions.
*
- * This interface is purposely genericized to defer class loading so that
- * luaj classes can come from the class loader.
+ * This interface is purposely genericized to defer class loading so that luaj
+ * classes can come from the class loader.
*
- * The implementation should be acquired using {@link LuajClassLoader#NewLauncher()}
- * or {@link LuajClassLoader#NewLauncher(Class)} which ensure that the classes are
- * loaded to give each Launcher instance a pristine set of Globals, including
+ * The implementation should be acquired using
+ * {@link LuajClassLoader#NewLauncher()} or
+ * {@link LuajClassLoader#NewLauncher(Class)} which ensure that the classes are
+ * loaded to give each Launcher instance a pristine set of Globals, including
* the shared metatables.
*
* @see LuajClassLoader
@@ -43,28 +46,31 @@ import java.io.Reader;
* @since luaj 3.0.1
*/
public interface Launcher {
-
- /** Launch a script contained in a String.
- *
- * @param script The script contents.
- * @param arg Optional arguments supplied to the script.
- * @return return values from the script.
- */
- public Object[] launch(String script, Object[] arg);
- /** Launch a script from an InputStream.
- *
- * @param script The script as an InputStream.
- * @param arg Optional arguments supplied to the script.
+ /**
+ * Launch a script contained in a String.
+ *
+ * @param script The script contents.
+ * @param arg Optional arguments supplied to the script.
* @return return values from the script.
*/
- public Object[] launch(InputStream script, Object[] arg);
+ Object[] launch(String script, Object[] arg);
- /** Launch a script from a Reader.
- *
- * @param script The script as a Reader.
- * @param arg Optional arguments supplied to the script.
+ /**
+ * Launch a script from an InputStream.
+ *
+ * @param script The script as an InputStream.
+ * @param arg Optional arguments supplied to the script.
* @return return values from the script.
*/
- public Object[] launch(Reader script, Object[] arg);
-}
\ No newline at end of file
+ Object[] launch(InputStream script, Object[] arg);
+
+ /**
+ * Launch a script from a Reader.
+ *
+ * @param script The script as a Reader.
+ * @param arg Optional arguments supplied to the script.
+ * @return return values from the script.
+ */
+ Object[] launch(Reader script, Object[] arg);
+}
diff --git a/src/jse/org/luaj/vm2/server/LuajClassLoader.java b/luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java
similarity index 74%
rename from src/jse/org/luaj/vm2/server/LuajClassLoader.java
rename to luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java
index 3886c1f8..6db51243 100644
--- a/src/jse/org/luaj/vm2/server/LuajClassLoader.java
+++ b/luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java
@@ -10,7 +10,7 @@
*
* 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
@@ -28,16 +28,16 @@ import java.util.Map;
/**
* Class loader that can be used to launch a lua script in a Java VM that has a
- * unique set of classes for org.luaj classes.
+ * unique set of classes for org.luaj classes.
*
-* Note: This class is experimental and subject to change in future versions.
+ * Note: This class is experimental and subject to change in future
+ * versions.
*
- * By using a custom class loader per script, it allows the script to have
- * its own set of globals, including static values such as shared metatables
- * that cannot access lua values from other scripts because their classes are
- * loaded from different class loaders. Thus normally unsafe libraries such
- * as luajava can be exposed to scripts in a server environment using these
- * techniques.
+ * By using a custom class loader per script, it allows the script to have its
+ * own set of globals, including static values such as shared metatables that
+ * cannot access lua values from other scripts because their classes are loaded
+ * from different class loaders. Thus normally unsafe libraries such as luajava
+ * can be exposed to scripts in a server environment using these techniques.
*
* All classes in the package "org.luaj.vm2." are considered user classes, and
* loaded into this class loader from their bytes in the class path. Other
@@ -52,7 +52,7 @@ import java.util.Map;
* and prints the return values. This behavior can be changed by supplying a
* different implementation class to {@link #NewLauncher(Class)} which must
* extend {@link Launcher}.
- *
+ *
* @see Launcher
* @see #NewLauncher()
* @see #NewLauncher(Class)
@@ -61,70 +61,73 @@ import java.util.Map;
*/
public class LuajClassLoader extends ClassLoader {
- /** String describing the luaj packages to consider part of the user classes */
+ /**
+ * String describing the luaj packages to consider part of the user classes
+ */
static final String luajPackageRoot = "org.luaj.vm2.";
- /** String describing the Launcher interface to be considered a system class */
+ /**
+ * String describing the Launcher interface to be considered a system class
+ */
static final String launcherInterfaceRoot = Launcher.class.getName();
/** Local cache of classes loaded by this loader. */
- Map> classes = new HashMap>();
+ Map> classes = new HashMap<>();
/**
* Construct a default {@link Launcher} instance that will load classes in
* its own {@link LuajClassLoader} using the default implementation class
* {@link DefaultLauncher}.
*
- * The {@link Launcher} that is returned will be a pristine luaj vm
- * whose classes are loaded into this loader including static variables
- * such as shared metatables, and should not be able to directly access
- * variables from other Launcher instances.
- *
+ * The {@link Launcher} that is returned will be a pristine luaj vm whose
+ * classes are loaded into this loader including static variables such as
+ * shared metatables, and should not be able to directly access variables
+ * from other Launcher instances.
+ *
* @return {@link Launcher} instance that can be used to launch scripts.
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
- public static Launcher NewLauncher() throws InstantiationException,
- IllegalAccessException, ClassNotFoundException {
+ public static Launcher NewLauncher() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return NewLauncher(DefaultLauncher.class);
}
/**
- * Construct a {@link Launcher} instance that will load classes in
- * its own {@link LuajClassLoader} using a user-supplied implementation class
- * that implements {@link Launcher}.
+ * Construct a {@link Launcher} instance that will load classes in its own
+ * {@link LuajClassLoader} using a user-supplied implementation class that
+ * implements {@link Launcher}.
*
- * The {@link Launcher} that is returned will be a pristine luaj vm
- * whose classes are loaded into this loader including static variables
- * such as shared metatables, and should not be able to directly access
- * variables from other Launcher instances.
- *
- * @return instance of type 'launcher_class' that can be used to launch scripts.
+ * The {@link Launcher} that is returned will be a pristine luaj vm whose
+ * classes are loaded into this loader including static variables such as
+ * shared metatables, and should not be able to directly access variables
+ * from other Launcher instances.
+ *
+ * @return instance of type 'launcher_class' that can be used to launch
+ * scripts.
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public static Launcher NewLauncher(Class extends Launcher> launcher_class)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
+ throws InstantiationException, IllegalAccessException, ClassNotFoundException {
final LuajClassLoader loader = new LuajClassLoader();
- final Object instance = loader.loadAsUserClass(launcher_class.getName())
- .newInstance();
+ final Object instance = loader.loadAsUserClass(launcher_class.getName()).newInstance();
return (Launcher) instance;
}
/**
- * Test if a class name should be considered a user class and loaded
- * by this loader, or a system class and loaded by the system loader.
+ * Test if a class name should be considered a user class and loaded by this
+ * loader, or a system class and loaded by the system loader.
+ *
* @param classname Class name to test.
* @return true if this should be loaded into this class loader.
*/
public static boolean isUserClass(String classname) {
- return classname.startsWith(luajPackageRoot)
- && !classname.startsWith(launcherInterfaceRoot);
+ return classname.startsWith(luajPackageRoot) && !classname.startsWith(launcherInterfaceRoot);
}
+ @Override
public Class> loadClass(String classname) throws ClassNotFoundException {
if (classes.containsKey(classname))
return classes.get(classname);
@@ -143,13 +146,11 @@ public class LuajClassLoader extends ClassLoader {
for (int n = 0; (n = is.read(b)) >= 0;)
baos.write(b, 0, n);
byte[] bytes = baos.toByteArray();
- Class> result = super.defineClass(classname, bytes, 0,
- bytes.length);
+ Class> result = super.defineClass(classname, bytes, 0, bytes.length);
classes.put(classname, result);
return result;
} catch (java.io.IOException e) {
- throw new ClassNotFoundException("Read failed: " + classname
- + ": " + e);
+ throw new ClassNotFoundException("Read failed: " + classname + ": " + e);
}
}
throw new ClassNotFoundException("Not found: " + classname);
diff --git a/grammar/Lua51.jj b/luaj-jse/src/main/javacc/Lua51.jj
similarity index 98%
rename from grammar/Lua51.jj
rename to luaj-jse/src/main/javacc/Lua51.jj
index 9f09de3a..7febeaa6 100644
--- a/grammar/Lua51.jj
+++ b/luaj-jse/src/main/javacc/Lua51.jj
@@ -20,11 +20,11 @@ options {
DEBUG_LOOKAHEAD = false;
DEBUG_PARSER = false;
DEBUG_TOKEN_MANAGER = false;
- OUTPUT_DIRECTORY = "org/luaj/vm2/parser";
+ OUTPUT_DIRECTORY = "org/luaj/vm2/parser/lua51";
}
PARSER_BEGIN(LuaParser)
-package org.luaj.vm2.parser;
+package org.luaj.vm2.parser.lua51;
public class LuaParser {
diff --git a/grammar/Lua52.jj b/luaj-jse/src/main/javacc/Lua52.jj
similarity index 98%
rename from grammar/Lua52.jj
rename to luaj-jse/src/main/javacc/Lua52.jj
index d84f4c6f..a8f5c239 100644
--- a/grammar/Lua52.jj
+++ b/luaj-jse/src/main/javacc/Lua52.jj
@@ -20,11 +20,11 @@ options {
DEBUG_LOOKAHEAD = false;
DEBUG_PARSER = false;
DEBUG_TOKEN_MANAGER = false;
- OUTPUT_DIRECTORY = "org/luaj/vm2/parser";
+ OUTPUT_DIRECTORY = "org/luaj/vm2/parser/lua52";
}
PARSER_BEGIN(LuaParser)
-package org.luaj.vm2.parser;
+package org.luaj.vm2.parser.lua52;
public class LuaParser {
diff --git a/grammar/LuaParser.jj b/luaj-jse/src/main/javacc/LuaParser.jj
similarity index 100%
rename from grammar/LuaParser.jj
rename to luaj-jse/src/main/javacc/LuaParser.jj
diff --git a/src/jse/META-INF/services/javax.script.ScriptEngineFactory b/luaj-jse/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
similarity index 100%
rename from src/jse/META-INF/services/javax.script.ScriptEngineFactory
rename to luaj-jse/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
diff --git a/luaj-jse/src/test/java/org/luaj/jse/DumpLoadEndianIntTest.java b/luaj-jse/src/test/java/org/luaj/jse/DumpLoadEndianIntTest.java
new file mode 100644
index 00000000..ed372072
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/jse/DumpLoadEndianIntTest.java
@@ -0,0 +1,148 @@
+package org.luaj.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+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 org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaClosure;
+import org.luaj.vm2.LuaFunction;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Prototype;
+import org.luaj.vm2.compiler.DumpState;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+class DumpLoadEndianIntTest {
+ private static final String SAVECHUNKS = "SAVECHUNKS";
+
+ private static final boolean SHOULDPASS = true;
+ private static final boolean SHOULDFAIL = false;
+ private static final String mixedscript = "return tostring(1234)..'-#!-'..tostring(23.75)";
+ private static final String intscript = "return tostring(1234)..'-#!-'..tostring(23)";
+ private static final String withdoubles = "1234-#!-23.75";
+ private static final String withints = "1234-#!-23";
+
+ private Globals globals;
+
+ @BeforeEach
+ protected void setUp() throws Exception {
+ globals = JsePlatform.standardGlobals();
+ DumpState.ALLOW_INTEGER_CASTING = false;
+ }
+
+ @Test
+ void testBigDoubleCompile() {
+ doTest(false, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, false, mixedscript, withdoubles, withdoubles,
+ SHOULDPASS);
+ doTest(false, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, true, mixedscript, withdoubles, withdoubles,
+ SHOULDPASS);
+ }
+
+ @Test
+ void testLittleDoubleCompile() {
+ doTest(true, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, false, mixedscript, withdoubles, withdoubles,
+ SHOULDPASS);
+ doTest(true, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, true, mixedscript, withdoubles, withdoubles,
+ SHOULDPASS);
+ }
+
+ @Test
+ void testBigIntCompile() {
+ DumpState.ALLOW_INTEGER_CASTING = true;
+ doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDPASS);
+ doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDPASS);
+ DumpState.ALLOW_INTEGER_CASTING = false;
+ doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDFAIL);
+ doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDFAIL);
+ doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, intscript, withints, withints, SHOULDPASS);
+ doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, intscript, withints, withints, SHOULDPASS);
+ }
+
+ @Test
+ void testLittleIntCompile() {
+ DumpState.ALLOW_INTEGER_CASTING = true;
+ doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDPASS);
+ doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDPASS);
+ DumpState.ALLOW_INTEGER_CASTING = false;
+ doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDFAIL);
+ doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDFAIL);
+ doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, intscript, withints, withints, SHOULDPASS);
+ doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, intscript, withints, withints, SHOULDPASS);
+ }
+
+ @Test
+ void testBigNumpatchCompile() {
+ doTest(false, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, false, mixedscript, withdoubles, withdoubles,
+ SHOULDPASS);
+ doTest(false, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, true, mixedscript, withdoubles, withdoubles, SHOULDPASS);
+ }
+
+ @Test
+ void testLittleNumpatchCompile() {
+ doTest(true, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, false, mixedscript, withdoubles, withdoubles, SHOULDPASS);
+ doTest(true, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, true, mixedscript, withdoubles, withdoubles, SHOULDPASS);
+ }
+
+ private void doTest(boolean littleEndian, int numberFormat, boolean stripDebug, String script,
+ String expectedPriorDump, String expectedPostDump, boolean shouldPass) {
+ try {
+
+ // compile into prototype
+ Reader reader = new StringReader(script);
+ Prototype p = globals.compilePrototype(reader, "script");
+
+ // double check script result before dumping
+ LuaFunction f = new LuaClosure(p, globals);
+ LuaValue r = f.call();
+ String actual = r.tojstring();
+ assertEquals(expectedPriorDump, actual);
+
+ // dump into bytes
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ DumpState.dump(p, baos, stripDebug, numberFormat, littleEndian);
+ if (!shouldPass)
+ fail("dump should not have succeeded");
+ } catch (Exception e) {
+ if (shouldPass)
+ fail("dump threw " + e);
+ else
+ return;
+ }
+ byte[] dumped = baos.toByteArray();
+
+ // load again using compiler
+ InputStream is = new ByteArrayInputStream(dumped);
+ f = globals.load(is, "dumped", "b", globals).checkfunction();
+ r = f.call();
+ actual = r.tojstring();
+ assertEquals(expectedPostDump, actual);
+
+ // write test chunk
+ if (System.getProperty(SAVECHUNKS) != null && script.equals(mixedscript)) {
+ new File("build").mkdirs();
+ String filename = "build/test-" + (littleEndian? "little-": "big-")
+ + (numberFormat == DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES? "double-"
+ : numberFormat == DumpState.NUMBER_FORMAT_INTS_ONLY? "int-"
+ : numberFormat == DumpState.NUMBER_FORMAT_NUM_PATCH_INT32? "numpatch4-": "???-")
+ + (stripDebug? "nodebug-": "debug-") + "bin.lua";
+ FileOutputStream fos = new FileOutputStream(filename);
+ fos.write(dumped);
+ fos.close();
+ }
+
+ } catch (IOException e) {
+ fail(e.toString());
+ }
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/jse/FragmentsTest.java b/luaj-jse/src/test/java/org/luaj/jse/FragmentsTest.java
new file mode 100644
index 00000000..1e57881b
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/jse/FragmentsTest.java
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Luaj.org. 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.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaClosure;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Print;
+import org.luaj.vm2.Prototype;
+import org.luaj.vm2.Varargs;
+import org.luaj.vm2.lib.jse.JsePlatform;
+import org.luaj.vm2.luajc.LuaJC;
+
+/**
+ * Test compilation of various fragments that have caused problems for jit
+ * compiling during development.
+ *
+ */
+public class FragmentsTest {
+
+ static final int TEST_TYPE_LUAC = 0;
+ static final int TEST_TYPE_LUAJC = 1;
+
+ @Nested
+ public static class JseFragmentsTest extends FragmentsTestCase {
+ public JseFragmentsTest() { super(TEST_TYPE_LUAC); }
+ }
+
+ @Nested
+ public static class LuaJCFragmentsTest extends FragmentsTestCase {
+ public LuaJCFragmentsTest() { super(TEST_TYPE_LUAJC); }
+ }
+
+ abstract protected static class FragmentsTestCase {
+
+ final int TEST_TYPE;
+
+ protected FragmentsTestCase(int testType) {
+ this.TEST_TYPE = testType;
+ }
+
+ public void runFragment(Varargs expected, String script) {
+ try {
+ String name = this.getClass().getName();
+ Globals globals = JsePlatform.debugGlobals();
+ Reader reader = new StringReader(script);
+ LuaValue chunk;
+ switch (TEST_TYPE) {
+ case TEST_TYPE_LUAJC:
+ LuaJC.install(globals);
+ chunk = globals.load(reader, name);
+ break;
+ default:
+ Prototype p = globals.compilePrototype(reader, name);
+ chunk = new LuaClosure(p, globals);
+ Print.print(p);
+ break;
+ }
+ Varargs actual = chunk.invoke();
+ assertEquals(expected.narg(), actual.narg());
+ for (int i = 1; i <= actual.narg(); i++)
+ assertEquals(expected.arg(i), actual.arg(i));
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ fail(e.toString());
+ }
+ }
+
+ @Test
+ public void testFirstArgNilExtended() {
+ runFragment(LuaValue.NIL, "function f1(a) print( 'f1:', a ) return a end\n" + "b = f1()\n" + "return b");
+ }
+
+ @Test
+ public void testSimpleForloop() {
+ runFragment(LuaValue.valueOf(77),
+ "for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " return p\n" + "end\n");
+
+ }
+
+ @Test
+ public void testForloopParamUpvalues() {
+ runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(77), LuaValue.valueOf(1) }),
+ "for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " foo = function()\n" + " return p,n\n"
+ + " end\n" + " return foo()\n" + "end\n");
+
+ }
+
+ @Test
+ public void testArgVarargsUseBoth() {
+ runFragment(
+ LuaValue
+ .varargsOf(new LuaValue[] { LuaValue.valueOf("a"), LuaValue.valueOf("b"), LuaValue.valueOf("c") }),
+ "function v(arg,...)\n" + " return arg,...\n" + "end\n" + "return v('a','b','c')\n");
+ }
+
+ @Test
+ public void testArgParamUseNone() {
+ runFragment(LuaValue.valueOf("string"),
+ "function v(arg,...)\n" + " return type(arg)\n" + "end\n" + "return v('abc')\n");
+ }
+
+ @Test
+ public void testSetlistVarargs() {
+ runFragment(LuaValue.valueOf("abc"),
+ "local f = function() return 'abc' end\n" + "local g = { f() }\n" + "return g[1]\n");
+ }
+
+ @Test
+ public void testSelfOp() {
+ runFragment(LuaValue.valueOf("bcd"), "local s = 'abcde'\n" + "return s:sub(2,4)\n");
+ }
+
+ @Test
+ public void testSetListWithOffsetAndVarargs() {
+ runFragment(LuaValue.valueOf(1003), "local bar = {1000, math.sqrt(9)}\n" + "return bar[1]+bar[2]\n");
+ }
+
+ @Test
+ public void testMultiAssign() {
+ // arargs evaluations are all done before assignments
+ runFragment(
+ LuaValue
+ .varargsOf(new LuaValue[] { LuaValue.valueOf(111), LuaValue.valueOf(111), LuaValue.valueOf(111) }),
+ "a,b,c = 1,10,100\n" + "a,b,c = a+b+c, a+b+c, a+b+c\n" + "return a,b,c\n");
+ }
+
+ @Test
+ public void testUpvalues() {
+ runFragment(LuaValue.valueOf(999),
+ "local a = function(x)\n" + " return function(y)\n" + " return x + y\n" + " end\n" + "end\n"
+ + "local b = a(222)\n" + "local c = b(777)\n" + "print( 'c=', c )\n" + "return c\n");
+ }
+
+ @Test
+ public void testNonAsciiStringLiterals() {
+ runFragment(LuaValue.valueOf("7,8,12,10,9,11,133,222"), "local a='\\a\\b\\f\\n\\t\\v\\133\\222'\n"
+ + "local t={string.byte(a,1,#a)}\n" + "return table.concat(t,',')\n");
+ }
+
+ @Test
+ public void testControlCharStringLiterals() {
+ runFragment(LuaValue.valueOf("97,0,98,18,99,18,100,18,48,101"), "local a='a\\0b\\18c\\018d\\0180e'\n"
+ + "local t={string.byte(a,1,#a)}\n" + "return table.concat(t,',')\n");
+ }
+
+ @Test
+ public void testLoopVarNames() {
+ runFragment(LuaValue.valueOf(" 234,1,aa 234,2,bb"),
+ "local w = ''\n" + "function t()\n" + " for f,var in ipairs({'aa','bb'}) do\n" + " local s = 234\n"
+ + " w = w..' '..s..','..f..','..var\n" + " end\n" + "end\n" + "t()\n" + "return w\n");
+
+ }
+
+ @Test
+ public void testForLoops() {
+ runFragment(LuaValue.valueOf("12345 357 963"),
+ "local s,t,u = '','',''\n" + "for m=1,5 do\n" + " s = s..m\n" + "end\n" + "for m=3,7,2 do\n"
+ + " t = t..m\n" + "end\n" + "for m=9,3,-3 do\n" + " u = u..m\n" + "end\n"
+ + "return s..' '..t..' '..u\n");
+ }
+
+ @Test
+ public void testLocalFunctionDeclarations() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf("function"), LuaValue.valueOf("nil")),
+ "local function aaa()\n" + " return type(aaa)\n" + "end\n" + "local bbb = function()\n"
+ + " return type(bbb)\n" + "end\n" + "return aaa(),bbb()\n");
+ }
+
+ @Test
+ public void testNilsInTableConstructor() {
+ runFragment(LuaValue.valueOf("1=111 2=222 3=333 "),
+ "local t = { 111, 222, 333, nil, nil }\n" + "local s = ''\n" + "for i,v in ipairs(t) do \n"
+ + " s=s..tostring(i)..'='..tostring(v)..' '\n" + "end\n" + "return s\n");
+
+ }
+
+ @Test
+ public void testUnreachableCode() {
+ runFragment(LuaValue.valueOf(66),
+ "local function foo(x) return x * 2 end\n" + "local function bar(x, y)\n" + " if x==y then\n"
+ + " return y\n" + " else\n" + " return foo(x)\n" + " end\n" + "end\n"
+ + "return bar(33,44)\n");
+
+ }
+
+ @Test
+ public void testVarargsWithParameters() {
+ runFragment(LuaValue.valueOf(222),
+ "local func = function(t,...)\n" + " return (...)\n" + "end\n" + "return func(111,222,333)\n");
+ }
+
+ @Test
+ public void testNoReturnValuesPlainCall() {
+ runFragment(LuaValue.TRUE, "local testtable = {}\n" + "return pcall( function() testtable[1]=2 end )\n");
+ }
+
+ @Test
+ public void testVarargsInTableConstructor() {
+ runFragment(LuaValue.valueOf(222), "local function foo() return 111,222,333 end\n"
+ + "local t = {'a','b',c='c',foo()}\n" + "return t[4]\n");
+ }
+
+ @Test
+ public void testVarargsInFirstArg() {
+ runFragment(LuaValue.valueOf(123), "function aaa(x) return x end\n" + "function bbb(y) return y end\n"
+ + "function ccc(z) return z end\n" + "return ccc( aaa(bbb(123)), aaa(456) )\n");
+ }
+
+ @Test
+ public void testSetUpvalueTableInitializer() {
+ runFragment(LuaValue.valueOf("b"), "local aliases = {a='b'}\n" + "local foo = function()\n"
+ + " return aliases\n" + "end\n" + "return foo().a\n");
+ }
+
+ @Test
+ public void testLoadNilUpvalue() {
+ runFragment(LuaValue.NIL, "tostring = function() end\n" + "local pc \n" + "local pcall = function(...)\n"
+ + " pc(...)\n" + "end\n" + "return NIL\n");
+ }
+
+ @Test
+ public void testUpvalueClosure() {
+ runFragment(LuaValue.NIL, "print()\n" + "local function f2() end\n" + "local function f3()\n"
+ + " return f3\n" + "end\n" + "return NIL\n");
+ }
+
+ @Test
+ public void testUninitializedUpvalue() {
+ runFragment(LuaValue.NIL, "local f\n" + "do\n" + " function g()\n" + " print(f())\n" + " end\n"
+ + "end\n" + "return NIL\n");
+ }
+
+ @Test
+ public void testTestOpUpvalues() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3)),
+ "print( nil and 'T' or 'F' )\n" + "local a,b,c = 1,2,3\n" + "function foo()\n" + " return a,b,c\n"
+ + "end\n" + "return foo()\n");
+ }
+
+ @Test
+ public void testTestSimpleBinops() {
+ runFragment(
+ LuaValue.varargsOf(
+ new LuaValue[] { LuaValue.FALSE, LuaValue.FALSE, LuaValue.TRUE, LuaValue.TRUE, LuaValue.FALSE }),
+ "local a,b,c = 2,-2.5,0\n" + "return (a==c), (b==c), (a==a), (a>c), (b>0)\n");
+ }
+
+ @Test
+ public void testNumericForUpvalues() {
+ runFragment(LuaValue.valueOf(8), "for i = 3,4 do\n" + " i = i + 5\n" + " local a = function()\n"
+ + " return i\n" + " end\n" + " return a()\n" + "end\n");
+ }
+
+ @Test
+ public void testNumericForUpvalues2() {
+ runFragment(LuaValue.valueOf("222 222"),
+ "local t = {}\n" + "local template = [[123 456]]\n" + "for i = 1,2 do\n"
+ + " t[i] = template:gsub('%d', function(s)\n" + " return i\n" + " end)\n" + "end\n"
+ + "return t[2]\n");
+ }
+
+ @Test
+ public void testReturnUpvalue() {
+ runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.ONE, LuaValue.valueOf(5), }), "local a = 1\n"
+ + "local b\n" + "function c()\n" + " b=5\n" + " return a\n" + "end\n" + "return c(),b\n");
+ }
+
+ @Test
+ public void testUninitializedAroundBranch() {
+ runFragment(LuaValue.valueOf(333),
+ "local state\n" + "if _G then\n" + " state = 333\n" + "end\n" + "return state\n");
+ }
+
+ @Test
+ public void testLoadedNilUpvalue() {
+ runFragment(LuaValue.NIL, "local a = print()\n" + "local b = c and { d = e }\n" + "local f\n"
+ + "local function g()\n" + " return f\n" + "end\n" + "return g()\n");
+ }
+
+ @Test
+ public void testUpvalueInFirstSlot() {
+ runFragment(LuaValue.valueOf("foo"), "local p = {'foo'}\n" + "bar = function()\n" + " return p \n"
+ + "end\n" + "for i,key in ipairs(p) do\n" + " print()\n" + "end\n" + "return bar()[1]");
+ }
+
+ @Test
+ public void testReadOnlyAndReadWriteUpvalues() {
+ runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(333), LuaValue.valueOf(222) }),
+ "local a = 111\n" + "local b = 222\n" + "local c = function()\n" + " a = a + b\n"
+ + " return a,b\n" + "end\n" + "return c()\n");
+ }
+
+ @Test
+ public void testNestedUpvalues() {
+ runFragment(
+ LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(5), LuaValue.valueOf(8), LuaValue.valueOf(9) }),
+ "local x = 3\n" + "local y = 5\n" + "local function f()\n" + " return y\n" + "end\n"
+ + "local function g(x1, y1)\n" + " x = x1\n" + " y = y1\n" + " return x,y\n" + "end\n"
+ + "return f(), g(8,9)\n" + "\n");
+ }
+
+ @Test
+ public void testLoadBool() {
+ runFragment(LuaValue.NONE, "print( type(foo)=='string' )\n" + "local a,b\n" + "if print() then\n"
+ + " b = function()\n" + " return a\n" + " end\n" + "end\n");
+ }
+
+ @Test
+ public void testBasicForLoop() {
+ runFragment(LuaValue.valueOf(2), "local data\n" + "for i = 1, 2 do\n" + " data = i\n" + "end\n"
+ + "local bar = function()\n" + " return data\n" + "end\n" + "return bar()\n");
+ }
+
+ @Test
+ public void testGenericForMultipleValues() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf(3), LuaValue.valueOf(2), LuaValue.valueOf(1)),
+ "local iter = function() return 1,2,3,4 end\n" + "local foo = function() return iter,5 end\n"
+ + "for a,b,c in foo() do\n" + " return c,b,a\n" + "end\n");
+ }
+
+ @Test
+ public void testPhiUpvalue() {
+ runFragment(LuaValue.valueOf(6), "local a = foo or 0\n" + "local function b(c)\n"
+ + " if c > a then a = c end\n" + " return a\n" + "end\n" + "b(6)\n" + "return a\n");
+ }
+
+ @Test
+ public void testAssignReferUpvalues() {
+ runFragment(LuaValue.valueOf(123), "local entity = 234\n" + "local function c()\n" + " return entity\n"
+ + "end\n" + "entity = (a == b) and 123\n" + "if entity then\n" + " return entity\n" + "end\n");
+ }
+
+ @Test
+ public void testSimpleRepeatUntil() {
+ runFragment(LuaValue.valueOf(5),
+ "local a\n" + "local w\n" + "repeat\n" + " a = w\n" + "until not a\n" + "return 5\n");
+ }
+
+ @Test
+ public void testLoopVarUpvalues() {
+ runFragment(LuaValue.valueOf("b"),
+ "local env = {}\n" + "for a,b in pairs(_G) do\n" + " c = function()\n" + " return b\n"
+ + " end\n" + "end\n" + "local e = env\n" + "local f = {a='b'}\n" + "for k,v in pairs(f) do\n"
+ + " return env[k] or v\n" + "end\n");
+ }
+
+ @Test
+ public void testPhiVarUpvalue() {
+ runFragment(LuaValue.valueOf(2), "local a = 1\n" + "local function b()\n" + " a = a + 1\n"
+ + " return function() end\n" + "end\n" + "for i in b() do\n" + " a = 3\n" + "end\n" + "return a\n");
+ }
+
+ @Test
+ public void testUpvaluesInElseClauses() {
+ runFragment(LuaValue.valueOf(111),
+ "if a then\n" + " foo(bar)\n" + "elseif _G then\n" + " local x = 111\n" + " if d then\n"
+ + " foo(bar)\n" + " else\n" + " local y = function()\n" + " return x\n"
+ + " end\n" + " return y()\n" + " end\n" + "end\n");
+ }
+
+ @Test
+ public void testUpvalueInDoBlock() {
+ runFragment(LuaValue.NONE,
+ "do\n" + " local x = 10\n" + " function g()\n" + " return x\n" + " end\n" + "end\n" + "g()\n");
+ }
+
+ @Test
+ public void testNullError() {
+ runFragment(LuaValue.varargsOf(LuaValue.FALSE, LuaValue.NIL), "return pcall(error)\n");
+ }
+
+ @Test
+ public void testFindWithOffset() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf(8), LuaValue.valueOf(5)), "string = \"abcdef:ghi\"\n"
+ + "substring = string:sub(3)\n" + "idx = substring:find(\":\")\n" + "return #substring, idx\n");
+ }
+
+ @Test
+ public void testErrorArgIsString() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("c")),
+ "a,b = pcall(error, 'c'); return type(b), b\n");
+ }
+
+ @Test
+ public void testErrorArgIsNil() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf("nil"), LuaValue.NIL),
+ "a,b = pcall(error); return type(b), b\n");
+ }
+
+ @Test
+ public void testErrorArgIsTable() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf("table"), LuaValue.valueOf("d")),
+ "a,b = pcall(error, {c='d'}); return type(b), b.c\n");
+ }
+
+ @Test
+ public void testErrorArgIsNumber() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("1")),
+ "a,b = pcall(error, 1); return type(b), b\n");
+ }
+
+ @Test
+ public void testErrorArgIsBool() {
+ runFragment(LuaValue.varargsOf(LuaValue.valueOf("boolean"), LuaValue.TRUE),
+ "a,b = pcall(error, true); return type(b), b\n");
+ }
+
+ @Test
+ public void testBalancedMatchOnEmptyString() {
+ runFragment(LuaValue.NIL, "return (\"\"):match(\"%b''\")\n");
+ }
+
+ @Test
+ public void testReturnValueForTableRemove() {
+ runFragment(LuaValue.NONE, "return table.remove({ })");
+ }
+
+ @Test
+ public void testTypeOfTableRemoveReturnValue() {
+ runFragment(LuaValue.valueOf("nil"), "local k = table.remove({ }) return type(k)");
+ }
+
+ @Test
+ public void testVarargBugReport() {
+ runFragment(
+ LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3) }),
+ "local i = function(...) return ... end\n" + "local v1, v2, v3 = i(1, 2, 3)\n" + "return v1, v2, v3");
+
+ }
+ }
+}
diff --git a/test/junit/org/luaj/vm2/LoadOrderTest.java b/luaj-jse/src/test/java/org/luaj/jse/LoadOrderTest.java
similarity index 82%
rename from test/junit/org/luaj/vm2/LoadOrderTest.java
rename to luaj-jse/src/test/java/org/luaj/jse/LoadOrderTest.java
index de8ae6a0..64096299 100644
--- a/test/junit/org/luaj/vm2/LoadOrderTest.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/LoadOrderTest.java
@@ -19,26 +19,31 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
-package org.luaj.vm2;
+package org.luaj.jse;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.InputStream;
import java.io.Reader;
-import junit.framework.TestCase;
-
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaString;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.server.Launcher;
import org.luaj.vm2.server.LuajClassLoader;
// Tests using class loading orders that have caused problems for some use cases.
-public class LoadOrderTest extends TestCase {
+class LoadOrderTest {
- public void testLoadGlobalsFirst() {
+ @Test
+ void testLoadGlobalsFirst() {
Globals g = JsePlatform.standardGlobals();
assertNotNull(g);
}
- public void testLoadStringFirst() {
+ @Test
+ void testLoadStringFirst() {
LuaString BAR = LuaString.valueOf("bar");
assertNotNull(BAR);
}
@@ -47,22 +52,25 @@ public class LoadOrderTest extends TestCase {
// Static initializer that causes LuaString->LuaValue->LuaString
private static final LuaString FOO = LuaString.valueOf("foo");
+ @Override
public Object[] launch(String script, Object[] arg) {
return new Object[] { FOO };
}
+ @Override
public Object[] launch(InputStream script, Object[] arg) {
return null;
}
+ @Override
public Object[] launch(Reader script, Object[] arg) {
return null;
}
}
- public void testClassLoadsStringFirst() throws Exception {
- Launcher launcher = LuajClassLoader
- .NewLauncher(TestLauncherLoadStringFirst.class);
+ @Test
+ void testClassLoadsStringFirst() throws Exception {
+ Launcher launcher = LuajClassLoader.NewLauncher(TestLauncherLoadStringFirst.class);
Object[] results = launcher.launch("foo", null);
assertNotNull(results);
}
diff --git a/luaj-jse/src/test/java/org/luaj/jse/LuaPrototypeTest.java b/luaj-jse/src/test/java/org/luaj/jse/LuaPrototypeTest.java
new file mode 100644
index 00000000..987c56e6
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/jse/LuaPrototypeTest.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Luaj.org. 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.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+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.ZeroArgFunction;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+class LuaPrototypeTest {
+
+ private Prototype createPrototype(String script, String name) {
+ try {
+ Globals globals = JsePlatform.standardGlobals();
+ Reader reader = new StringReader(script);
+ return globals.compilePrototype(reader, name);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ fail(e.toString());
+ return null;
+ }
+ }
+
+ @Test
+ void testFunctionClosureThreadEnv() {
+
+ // set up suitable environments for execution
+ LuaValue aaa = LuaValue.valueOf("aaa");
+ LuaValue eee = LuaValue.valueOf("eee");
+ final Globals globals = JsePlatform.standardGlobals();
+ LuaTable newenv = LuaValue.tableOf(new LuaValue[] { LuaValue.valueOf("a"), LuaValue.valueOf("aaa"),
+ LuaValue.valueOf("b"), LuaValue.valueOf("bbb"), });
+ LuaTable mt = LuaValue.tableOf(new LuaValue[] { LuaValue.INDEX, globals });
+ newenv.setmetatable(mt);
+ globals.set("a", aaa);
+ newenv.set("a", eee);
+
+ // function tests
+ {
+ LuaFunction f = new ZeroArgFunction() {
+ @Override
+ public LuaValue call() { return globals.get("a"); }
+ };
+ assertEquals(aaa, f.call());
+ }
+
+ // closure tests
+ {
+ Prototype p = createPrototype("return a\n", "closuretester");
+ LuaClosure c = new LuaClosure(p, globals);
+
+ // Test that a clusure with a custom enviroment uses that environment.
+ assertEquals(aaa, c.call());
+ c = new LuaClosure(p, newenv);
+ assertEquals(newenv, c.upValues[0].getValue());
+ assertEquals(eee, c.call());
+ }
+ }
+}
diff --git a/test/junit/org/luaj/vm2/OrphanedThreadTest.java b/luaj-jse/src/test/java/org/luaj/jse/OrphanedThreadTest.java
similarity index 59%
rename from test/junit/org/luaj/vm2/OrphanedThreadTest.java
rename to luaj-jse/src/test/java/org/luaj/jse/OrphanedThreadTest.java
index 14cecb4c..3f7becd2 100644
--- a/test/junit/org/luaj/vm2/OrphanedThreadTest.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/OrphanedThreadTest.java
@@ -19,97 +19,97 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
-package org.luaj.vm2;
+package org.luaj.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import java.lang.ref.WeakReference;
-import junit.framework.TestCase;
-
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaThread;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
-
-public class OrphanedThreadTest extends TestCase {
+class OrphanedThreadTest {
Globals globals;
+
LuaThread luathread;
- WeakReference luathr_ref;
- LuaValue function;
- WeakReference func_ref;
-
+ LuaValue function;
+
+ WeakReference luathr_ref;
+ WeakReference func_ref;
+
+ @BeforeEach
protected void setUp() throws Exception {
LuaThread.thread_orphan_check_interval = 5;
globals = JsePlatform.standardGlobals();
}
-
+
+ @AfterEach
protected void tearDown() {
LuaThread.thread_orphan_check_interval = 30000;
}
-
- public void testCollectOrphanedNormalThread() throws Exception {
+
+ @Test
+ void testCollectOrphanedNormalThread() throws Exception {
function = new NormalFunction(globals);
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
-
- public void testCollectOrphanedEarlyCompletionThread() throws Exception {
+
+ @Test
+ void testCollectOrphanedEarlyCompletionThread() throws Exception {
function = new EarlyCompletionFunction(globals);
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
-
- public void testCollectOrphanedAbnormalThread() throws Exception {
+
+ @Test
+ void testCollectOrphanedAbnormalThread() throws Exception {
function = new AbnormalFunction(globals);
doTest(LuaValue.FALSE, LuaValue.valueOf("abnormal condition"));
}
-
- public void testCollectOrphanedClosureThread() throws Exception {
- String script =
- "print('in closure, arg is '..(...))\n" +
- "arg = coroutine.yield(1)\n" +
- "print('in closure.2, arg is '..arg)\n" +
- "arg = coroutine.yield(0)\n" +
- "print('leakage in closure.3, arg is '..arg)\n" +
- "return 'done'\n";
+
+ @Test
+ void testCollectOrphanedClosureThread() throws Exception {
+ String script = "print('in closure, arg is '..(...))\n" + "arg = coroutine.yield(1)\n"
+ + "print('in closure.2, arg is '..arg)\n" + "arg = coroutine.yield(0)\n"
+ + "print('leakage in closure.3, arg is '..arg)\n" + "return 'done'\n";
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
-
- public void testCollectOrphanedPcallClosureThread() throws Exception {
- String script =
- "f = function(x)\n" +
- " print('in pcall-closure, arg is '..(x))\n" +
- " arg = coroutine.yield(1)\n" +
- " print('in pcall-closure.2, arg is '..arg)\n" +
- " arg = coroutine.yield(0)\n" +
- " print('leakage in pcall-closure.3, arg is '..arg)\n" +
- " return 'done'\n" +
- "end\n" +
- "print( 'pcall-closre.result:', pcall( f, ... ) )\n";
+
+ @Test
+ void testCollectOrphanedPcallClosureThread() throws Exception {
+ String script = "f = function(x)\n" + " print('in pcall-closure, arg is '..(x))\n"
+ + " arg = coroutine.yield(1)\n" + " print('in pcall-closure.2, arg is '..arg)\n"
+ + " arg = coroutine.yield(0)\n" + " print('leakage in pcall-closure.3, arg is '..arg)\n"
+ + " return 'done'\n" + "end\n" + "print( 'pcall-closre.result:', pcall( f, ... ) )\n";
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
-
- public void testCollectOrphanedLoadCloasureThread() throws Exception {
- String script =
- "t = { \"print \", \"'hello, \", \"world'\", }\n" +
- "i = 0\n" +
- "arg = ...\n" +
- "f = function()\n" +
- " i = i + 1\n" +
- " print('in load-closure, arg is', arg, 'next is', t[i])\n" +
- " arg = coroutine.yield(1)\n" +
- " return t[i]\n" +
- "end\n" +
- "load(f)()\n";
+
+ @Test
+ void testCollectOrphanedLoadCloasureThread() throws Exception {
+ String script = "t = { \"print \", \"'hello, \", \"world'\", }\n" + "i = 0\n" + "arg = ...\n"
+ + "f = function()\n" + " i = i + 1\n" + " print('in load-closure, arg is', arg, 'next is', t[i])\n"
+ + " arg = coroutine.yield(1)\n" + " return t[i]\n" + "end\n" + "load(f)()\n";
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ONE);
}
private void doTest(LuaValue status2, LuaValue value2) throws Exception {
luathread = new LuaThread(globals, function);
- luathr_ref = new WeakReference(luathread);
- func_ref = new WeakReference(function);
- assertNotNull(luathr_ref.get());
-
+ luathr_ref = new WeakReference<>(luathread);
+ func_ref = new WeakReference<>(function);
+ assertNotNull(luathr_ref.get());
+
// resume two times
Varargs a = luathread.resume(LuaValue.valueOf("foo"));
assertEquals(LuaValue.ONE, a.arg(2));
@@ -117,62 +117,70 @@ public class OrphanedThreadTest extends TestCase {
a = luathread.resume(LuaValue.valueOf("bar"));
assertEquals(value2, a.arg(2));
assertEquals(status2, a.arg1());
-
+
// drop strong references
luathread = null;
function = null;
-
+
// gc
- for (int i=0; i<100 && (luathr_ref.get() != null || func_ref.get() != null); i++) {
+ for (int i = 0; i < 100 && (luathr_ref.get() != null || func_ref.get() != null); i++) {
Runtime.getRuntime().gc();
Thread.sleep(5);
}
-
+
// check reference
assertNull(luathr_ref.get());
assertNull(func_ref.get());
}
-
-
+
static class NormalFunction extends OneArgFunction {
final Globals globals;
+
public NormalFunction(Globals globals) {
this.globals = globals;
}
+
+ @Override
public LuaValue call(LuaValue arg) {
- System.out.println("in normal.1, arg is "+arg);
+ System.out.println("in normal.1, arg is " + arg);
arg = globals.yield(ONE).arg1();
- System.out.println("in normal.2, arg is "+arg);
+ System.out.println("in normal.2, arg is " + arg);
arg = globals.yield(ZERO).arg1();
- System.out.println("in normal.3, arg is "+arg);
+ System.out.println("in normal.3, arg is " + arg);
return NONE;
- }
+ }
}
-
+
static class EarlyCompletionFunction extends OneArgFunction {
final Globals globals;
+
public EarlyCompletionFunction(Globals globals) {
this.globals = globals;
}
+
+ @Override
public LuaValue call(LuaValue arg) {
- System.out.println("in early.1, arg is "+arg);
+ System.out.println("in early.1, arg is " + arg);
arg = globals.yield(ONE).arg1();
- System.out.println("in early.2, arg is "+arg);
+ System.out.println("in early.2, arg is " + arg);
return ZERO;
- }
+ }
}
-
+
static class AbnormalFunction extends OneArgFunction {
final Globals globals;
+
public AbnormalFunction(Globals globals) {
this.globals = globals;
}
+
+ @Override
public LuaValue call(LuaValue arg) {
- System.out.println("in abnormal.1, arg is "+arg);
+ System.out.println("in abnormal.1, arg is " + arg);
arg = globals.yield(ONE).arg1();
- System.out.println("in abnormal.2, arg is "+arg);
+ System.out.println("in abnormal.2, arg is " + arg);
error("abnormal condition");
return ZERO;
- }
+ }
}
}
diff --git a/luaj-jse/src/test/java/org/luaj/jse/RequireClassTest.java b/luaj-jse/src/test/java/org/luaj/jse/RequireClassTest.java
new file mode 100644
index 00000000..7ce82f09
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/jse/RequireClassTest.java
@@ -0,0 +1,96 @@
+package org.luaj.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.jse.require.RequireSampleClassCastExcep;
+import org.luaj.jse.require.RequireSampleLoadLuaError;
+import org.luaj.jse.require.RequireSampleLoadRuntimeExcep;
+import org.luaj.jse.require.RequireSampleSuccess;
+import org.luaj.vm2.LuaError;
+import org.luaj.vm2.LuaTable;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+class RequireClassTest {
+
+ private LuaTable globals;
+ private LuaValue require;
+
+ @BeforeEach
+ public void setUp() {
+ globals = JsePlatform.standardGlobals();
+ require = globals.get("require");
+ }
+
+ @Test
+ void testLoadClass() {
+ LuaValue result = globals.load(new RequireSampleSuccess());
+ assertEquals("require-sample-success-", result.tojstring());
+ }
+
+ @Test
+ void testRequireClassSuccess() {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleSuccess.class.getName()));
+ assertEquals("require-sample-success-" + RequireSampleSuccess.class.getName(), result.tojstring());
+ result = require.call(LuaValue.valueOf(RequireSampleSuccess.class.getName()));
+ assertEquals("require-sample-success-" + RequireSampleSuccess.class.getName(), result.tojstring());
+ }
+
+ @Test
+ void testRequireClassLoadLuaError() {
+ try {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadLuaError.class.getName()));
+ fail("incorrectly loaded class that threw lua error");
+ } catch (LuaError le) {
+ assertEquals("sample-load-lua-error", le.getMessage());
+ }
+ try {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadLuaError.class.getName()));
+ fail("incorrectly loaded class that threw lua error");
+ } catch (LuaError le) {
+ assertEquals("loop or previous error loading module '" + RequireSampleLoadLuaError.class.getName() + "'",
+ le.getMessage());
+ }
+ }
+
+ @Test
+ void testRequireClassLoadRuntimeException() {
+ try {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadRuntimeExcep.class.getName()));
+ fail("incorrectly loaded class that threw runtime exception");
+ } catch (RuntimeException le) {
+ assertEquals("sample-load-runtime-exception", le.getMessage());
+ }
+ try {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadRuntimeExcep.class.getName()));
+ fail("incorrectly loaded class that threw runtime exception");
+ } catch (LuaError le) {
+ assertEquals(
+ "loop or previous error loading module '" + RequireSampleLoadRuntimeExcep.class.getName() + "'",
+ le.getMessage());
+ }
+ }
+
+ @Test
+ void testRequireClassClassCastException() {
+ try {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()));
+ fail("incorrectly loaded class that threw class cast exception");
+ } catch (LuaError le) {
+ String msg = le.getMessage();
+ if (msg.indexOf("not found") < 0)
+ fail("expected 'not found' message but got " + msg);
+ }
+ try {
+ LuaValue result = require.call(LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()));
+ fail("incorrectly loaded class that threw class cast exception");
+ } catch (LuaError le) {
+ String msg = le.getMessage();
+ if (msg.indexOf("not found") < 0)
+ fail("expected 'not found' message but got " + msg);
+ }
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/jse/SimpleLuaCallsTest.java b/luaj-jse/src/test/java/org/luaj/jse/SimpleLuaCallsTest.java
new file mode 100644
index 00000000..9d6f9fcd
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/jse/SimpleLuaCallsTest.java
@@ -0,0 +1,96 @@
+package org.luaj.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaDouble;
+import org.luaj.vm2.LuaInteger;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+class SimpleLuaCallsTest {
+
+ private Globals globals;
+
+ @BeforeEach
+ protected void setUp() throws Exception {
+ globals = JsePlatform.standardGlobals();
+ }
+
+ private void doTest(String script) {
+ try {
+ LuaValue c = globals.load(script, "script");
+ c.call();
+ } catch (Exception e) {
+ fail("i/o exception: " + e);
+ }
+ }
+
+ @Test
+ void testTrivial() {
+ String s = "print( 2 )\n";
+ doTest(s);
+ }
+
+ @Test
+ void testAlmostTrivial() {
+ String s = "print( 2 )\n" + "print( 3 )\n";
+ doTest(s);
+ }
+
+ @Test
+ void testSimple() {
+ String s = "print( 'hello, world' )\n" + "for i = 2,4 do\n" + " print( 'i', i )\n" + "end\n";
+ doTest(s);
+ }
+
+ @Test
+ void testBreak() {
+ String s = "a=1\n" + "while true do\n" + " if a>10 then\n" + " break\n" + " end\n" + " a=a+1\n"
+ + " print( a )\n" + "end\n";
+ doTest(s);
+ }
+
+ @Test
+ void testShebang() {
+ String s = "#!../lua\n" + "print( 2 )\n";
+ doTest(s);
+ }
+
+ @Test
+ void testInlineTable() {
+ String s = "A = {g=10}\n" + "print( A )\n";
+ doTest(s);
+ }
+
+ @Test
+ void testEqualsAnd() {
+ String s = "print( 1 == b and b )\n";
+ doTest(s);
+ }
+
+ private static final int[] samehash = { 0, 1, -1, 2, -2, 4, 8, 16, 32, Integer.MAX_VALUE, Integer.MIN_VALUE };
+ private static final double[] diffhash = { .5, 1, 1.5, 1, .5, 1.5, 1.25, 2.5 };
+
+ @Test
+ void testDoubleHashCode() {
+ for (int i = 0; i < samehash.length; i++) {
+ LuaValue j = LuaInteger.valueOf(samehash[i]);
+ LuaValue d = LuaDouble.valueOf(samehash[i]);
+ int hj = j.hashCode();
+ int hd = d.hashCode();
+ assertEquals(hj, hd);
+ }
+ for (int i = 0; i < diffhash.length; i += 2) {
+ LuaValue c = LuaValue.valueOf(diffhash[i+0]);
+ LuaValue d = LuaValue.valueOf(diffhash[i+1]);
+ int hc = c.hashCode();
+ int hd = d.hashCode();
+ assertTrue(hc != hd, "hash codes are same: " + hc);
+ }
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/jse/StringMatchingTest.java b/luaj-jse/src/test/java/org/luaj/jse/StringMatchingTest.java
new file mode 100644
index 00000000..8fe6efd0
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/jse/StringMatchingTest.java
@@ -0,0 +1,47 @@
+package org.luaj.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaString;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+class StringMatchingTest {
+
+ @BeforeEach
+ protected void setUp() throws Exception {
+ JsePlatform.standardGlobals();
+ }
+
+ @Test
+ void testMatchShortPatterns() {
+ LuaValue[] args = { LuaString.valueOf("%bxy") };
+ LuaString empty = LuaString.valueOf("");
+
+ LuaString a = LuaString.valueOf("a");
+ LuaString ax = LuaString.valueOf("ax");
+ LuaString axb = LuaString.valueOf("axb");
+ LuaString axby = LuaString.valueOf("axby");
+ LuaString xbya = LuaString.valueOf("xbya");
+ LuaString bya = LuaString.valueOf("bya");
+ LuaString xby = LuaString.valueOf("xby");
+ LuaString axbya = LuaString.valueOf("axbya");
+ LuaValue nil = LuaValue.NIL;
+
+ assertEquals(nil, empty.invokemethod("match", args));
+ assertEquals(nil, a.invokemethod("match", args));
+ assertEquals(nil, ax.invokemethod("match", args));
+ assertEquals(nil, axb.invokemethod("match", args));
+ assertEquals(xby, axby.invokemethod("match", args));
+ assertEquals(xby, xbya.invokemethod("match", args));
+ assertEquals(nil, bya.invokemethod("match", args));
+ assertEquals(xby, xby.invokemethod("match", args));
+ assertEquals(xby, axbya.invokemethod("match", args));
+ assertEquals(xby, axbya.substring(0, 4).invokemethod("match", args));
+ assertEquals(nil, axbya.substring(0, 3).invokemethod("match", args));
+ assertEquals(xby, axbya.substring(1, 5).invokemethod("match", args));
+ assertEquals(nil, axbya.substring(2, 5).invokemethod("match", args));
+ }
+}
diff --git a/test/junit/org/luaj/vm2/UTF8StreamTest.java b/luaj-jse/src/test/java/org/luaj/jse/UTF8StreamTest.java
similarity index 82%
rename from test/junit/org/luaj/vm2/UTF8StreamTest.java
rename to luaj-jse/src/test/java/org/luaj/jse/UTF8StreamTest.java
index 1d9f3d23..d87a9e8d 100644
--- a/test/junit/org/luaj/vm2/UTF8StreamTest.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/UTF8StreamTest.java
@@ -19,18 +19,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
-package org.luaj.vm2;
+package org.luaj.jse;
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
-public class UTF8StreamTest extends TestCase {
+class UTF8StreamTest {
- public void testUtf8CharsInStream() {
- String script = "x = \"98\u00b0: today's temp!\"\n"
- + "print('x = ', x)\n"
- + "return x";
+ @Test
+ void testUtf8CharsInStream() {
+ String script = "x = \"98\u00b0: today's temp!\"\n" + "print('x = ', x)\n" + "return x";
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load(script);
LuaValue result = chunk.call();
diff --git a/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleClassCastExcep.java
similarity index 69%
rename from test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java
rename to luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleClassCastExcep.java
index 88ba21f6..dc7f0910 100644
--- a/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleClassCastExcep.java
@@ -1,17 +1,18 @@
-package org.luaj.vm2.require;
+package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
/**
- * This should fail while trying to load via "require() because it is not a LibFunction"
+ * This should fail while trying to load via "require() because it is not a
+ * LibFunction"
*
*/
public class RequireSampleClassCastExcep {
-
- public RequireSampleClassCastExcep() {
+
+ public RequireSampleClassCastExcep() {
}
-
+
public LuaValue call() {
return LuaValue.valueOf("require-sample-class-cast-excep");
- }
+ }
}
diff --git a/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleLoadLuaError.java
similarity index 62%
rename from test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java
rename to luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleLoadLuaError.java
index 0ba5e148..268ad70e 100644
--- a/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleLoadLuaError.java
@@ -1,20 +1,20 @@
-package org.luaj.vm2.require;
+package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.ZeroArgFunction;
/**
- * This should fail while trying to load via
- * "require()" because it throws a LuaError
+ * This should fail while trying to load via "require()" because it throws a
+ * LuaError
*
*/
public class RequireSampleLoadLuaError extends ZeroArgFunction {
-
- public RequireSampleLoadLuaError() {
+
+ public RequireSampleLoadLuaError() {
}
-
+
public LuaValue call() {
error("sample-load-lua-error");
return LuaValue.valueOf("require-sample-load-lua-error");
- }
+ }
}
diff --git a/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleLoadRuntimeExcep.java
similarity index 58%
rename from test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java
rename to luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleLoadRuntimeExcep.java
index 1f416b89..c627bae1 100644
--- a/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleLoadRuntimeExcep.java
@@ -1,18 +1,19 @@
-package org.luaj.vm2.require;
+package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.ZeroArgFunction;
/**
-* This should fail while trying to load via "require()" because it throws a RuntimeException
+ * This should fail while trying to load via "require()" because it throws a
+ * RuntimeException
*
*/
public class RequireSampleLoadRuntimeExcep extends ZeroArgFunction {
-
- public RequireSampleLoadRuntimeExcep() {
+
+ public RequireSampleLoadRuntimeExcep() {
}
-
+
public LuaValue call() {
throw new RuntimeException("sample-load-runtime-exception");
- }
+ }
}
diff --git a/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleSuccess.java
similarity index 63%
rename from test/junit/org/luaj/vm2/require/RequireSampleSuccess.java
rename to luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleSuccess.java
index 766d3eb8..821c26a1 100644
--- a/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java
+++ b/luaj-jse/src/test/java/org/luaj/jse/require/RequireSampleSuccess.java
@@ -1,18 +1,19 @@
-package org.luaj.vm2.require;
+package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.TwoArgFunction;
/**
- * This should succeed as a library that can be loaded dynamically via "require()"
+ * This should succeed as a library that can be loaded dynamically via
+ * "require()"
*/
public class RequireSampleSuccess extends TwoArgFunction {
-
- public RequireSampleSuccess() {
+
+ public RequireSampleSuccess() {
}
-
+
public LuaValue call(LuaValue modname, LuaValue env) {
env.checkglobals();
- return LuaValue.valueOf("require-sample-success-"+modname.tojstring());
- }
+ return LuaValue.valueOf("require-sample-success-" + modname.tojstring());
+ }
}
diff --git a/test/junit/org/luaj/vm2/lib/jse/JsePlatformTest.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/JsePlatformTest.java
similarity index 71%
rename from test/junit/org/luaj/vm2/lib/jse/JsePlatformTest.java
rename to luaj-jse/src/test/java/org/luaj/vm2/lib/jse/JsePlatformTest.java
index 80f3e773..b6e72087 100644
--- a/test/junit/org/luaj/vm2/lib/jse/JsePlatformTest.java
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/JsePlatformTest.java
@@ -1,15 +1,16 @@
package org.luaj.vm2.lib.jse;
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
-
-public class JsePlatformTest extends TestCase {
- public void testLuaMainPassesArguments() {
- Globals globals = JsePlatform.standardGlobals();
+class JsePlatformTest {
+ @Test
+ void testLuaMainPassesArguments() {
+ Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("return #arg, arg.n, arg[2], arg[1]");
Varargs results = JsePlatform.luaMain(chunk, new String[] { "aaa", "bbb" });
assertEquals(results.narg(), 4);
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuaJavaCoercionTest.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuaJavaCoercionTest.java
new file mode 100644
index 00000000..3acdc59d
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuaJavaCoercionTest.java
@@ -0,0 +1,531 @@
+package org.luaj.vm2.lib.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaError;
+import org.luaj.vm2.LuaInteger;
+import org.luaj.vm2.LuaString;
+import org.luaj.vm2.LuaTable;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Varargs;
+
+class LuaJavaCoercionTest {
+
+ private static LuaValue globals;
+ private static LuaValue ZERO = LuaValue.ZERO;
+ private static LuaValue ONE = LuaValue.ONE;
+ private static LuaValue TWO = LuaValue.valueOf(2);
+ private static LuaValue THREE = LuaValue.valueOf(3);
+ private static LuaString LENGTH = LuaString.valueOf("length");
+
+ @BeforeEach
+ protected void setUp() throws Exception {
+ globals = JsePlatform.standardGlobals();
+ }
+
+ @Test
+ void testJavaIntToLuaInt() {
+ Integer i = Integer.valueOf(777);
+ LuaValue v = CoerceJavaToLua.coerce(i);
+ assertEquals(LuaInteger.class, v.getClass());
+ assertEquals(777, v.toint());
+ }
+
+ @Test
+ void testLuaIntToJavaInt() {
+ LuaInteger i = LuaInteger.valueOf(777);
+ Object o = CoerceLuaToJava.coerce(i, int.class);
+ assertEquals(Integer.class, o.getClass());
+ assertEquals(777, ((Number) o).intValue());
+ o = CoerceLuaToJava.coerce(i, Integer.class);
+ assertEquals(Integer.class, o.getClass());
+ assertEquals(new Integer(777), o);
+ }
+
+ @Test
+ void testJavaStringToLuaString() {
+ String s = new String("777");
+ LuaValue v = CoerceJavaToLua.coerce(s);
+ assertEquals(LuaString.class, v.getClass());
+ assertEquals("777", v.toString());
+ }
+
+ @Test
+ void testLuaStringToJavaString() {
+ LuaString s = LuaValue.valueOf("777");
+ Object o = CoerceLuaToJava.coerce(s, String.class);
+ assertEquals(String.class, o.getClass());
+ assertEquals("777", o);
+ }
+
+ @Test
+ void testJavaClassToLuaUserdata() {
+ LuaValue va = CoerceJavaToLua.coerce(ClassA.class);
+ LuaValue va1 = CoerceJavaToLua.coerce(ClassA.class);
+ LuaValue vb = CoerceJavaToLua.coerce(ClassB.class);
+ assertSame(va, va1);
+ assertNotSame(va, vb);
+ LuaValue vi = CoerceJavaToLua.coerce(new ClassA());
+ assertNotSame(va, vi);
+ assertTrue(vi.isuserdata());
+ assertTrue(vi.isuserdata(ClassA.class));
+ assertFalse(vi.isuserdata(ClassB.class));
+ LuaValue vj = CoerceJavaToLua.coerce(new ClassB());
+ assertNotSame(vb, vj);
+ assertTrue(vj.isuserdata());
+ assertFalse(vj.isuserdata(ClassA.class));
+ assertTrue(vj.isuserdata(ClassB.class));
+ }
+
+ static class ClassA {
+ }
+
+ static class ClassB {
+ }
+
+ @Test
+ void testJavaIntArrayToLuaTable() {
+ int[] i = { 222, 333 };
+ LuaValue v = CoerceJavaToLua.coerce(i);
+ assertEquals(JavaArray.class, v.getClass());
+ assertEquals(LuaInteger.valueOf(222), v.get(ONE));
+ assertEquals(LuaInteger.valueOf(333), v.get(TWO));
+ assertEquals(TWO, v.get(LENGTH));
+ assertEquals(LuaValue.NIL, v.get(THREE));
+ assertEquals(LuaValue.NIL, v.get(ZERO));
+ v.set(ONE, LuaInteger.valueOf(444));
+ v.set(TWO, LuaInteger.valueOf(555));
+ assertEquals(444, i[0]);
+ assertEquals(555, i[1]);
+ assertEquals(LuaInteger.valueOf(444), v.get(ONE));
+ assertEquals(LuaInteger.valueOf(555), v.get(TWO));
+ try {
+ v.set(ZERO, LuaInteger.valueOf(777));
+ fail("array bound exception not thrown");
+ } catch (LuaError lee) {
+ // expected
+ }
+ try {
+ v.set(THREE, LuaInteger.valueOf(777));
+ fail("array bound exception not thrown");
+ } catch (LuaError lee) {
+ // expected
+ }
+ }
+
+ @Test
+ void testLuaTableToJavaIntArray() {
+ LuaTable t = new LuaTable();
+ t.set(1, LuaInteger.valueOf(222));
+ t.set(2, LuaInteger.valueOf(333));
+ int[] i = null;
+ Object o = CoerceLuaToJava.coerce(t, int[].class);
+ assertEquals(int[].class, o.getClass());
+ i = (int[]) o;
+ assertEquals(2, i.length);
+ assertEquals(222, i[0]);
+ assertEquals(333, i[1]);
+ }
+
+ @Test
+ void testIntArrayScoringTables() {
+ int a = 5;
+ LuaValue la = LuaInteger.valueOf(a);
+ LuaTable tb = new LuaTable();
+ tb.set(1, la);
+ LuaTable tc = new LuaTable();
+ tc.set(1, tb);
+
+ int saa = CoerceLuaToJava.getCoercion(int.class).score(la);
+ int sab = CoerceLuaToJava.getCoercion(int[].class).score(la);
+ int sac = CoerceLuaToJava.getCoercion(int[][].class).score(la);
+ assertTrue(saa < sab);
+ assertTrue(saa < sac);
+ int sba = CoerceLuaToJava.getCoercion(int.class).score(tb);
+ int sbb = CoerceLuaToJava.getCoercion(int[].class).score(tb);
+ int sbc = CoerceLuaToJava.getCoercion(int[][].class).score(tb);
+ assertTrue(sbb < sba);
+ assertTrue(sbb < sbc);
+ int sca = CoerceLuaToJava.getCoercion(int.class).score(tc);
+ int scb = CoerceLuaToJava.getCoercion(int[].class).score(tc);
+ int scc = CoerceLuaToJava.getCoercion(int[][].class).score(tc);
+ assertTrue(scc < sca);
+ assertTrue(scc < scb);
+ }
+
+ @Test
+ void testIntArrayScoringUserdata() {
+ int a = 5;
+ int[] b = { 44, 66 };
+ int[][] c = { { 11, 22 }, { 33, 44 } };
+ LuaValue va = CoerceJavaToLua.coerce(a);
+ LuaValue vb = CoerceJavaToLua.coerce(b);
+ LuaValue vc = CoerceJavaToLua.coerce(c);
+
+ int vaa = CoerceLuaToJava.getCoercion(int.class).score(va);
+ int vab = CoerceLuaToJava.getCoercion(int[].class).score(va);
+ int vac = CoerceLuaToJava.getCoercion(int[][].class).score(va);
+ assertTrue(vaa < vab);
+ assertTrue(vaa < vac);
+ int vba = CoerceLuaToJava.getCoercion(int.class).score(vb);
+ int vbb = CoerceLuaToJava.getCoercion(int[].class).score(vb);
+ int vbc = CoerceLuaToJava.getCoercion(int[][].class).score(vb);
+ assertTrue(vbb < vba);
+ assertTrue(vbb < vbc);
+ int vca = CoerceLuaToJava.getCoercion(int.class).score(vc);
+ int vcb = CoerceLuaToJava.getCoercion(int[].class).score(vc);
+ int vcc = CoerceLuaToJava.getCoercion(int[][].class).score(vc);
+ assertTrue(vcc < vca);
+ assertTrue(vcc < vcb);
+ }
+
+ public static class SampleClass {
+ public String sample() { return "void-args"; }
+
+ public String sample(int a) { return "int-args " + a; }
+
+ public String sample(int[] a) { return "int-array-args " + a[0] + "," + a[1]; }
+
+ public String sample(int[][] a) {
+ return "int-array-array-args " + a[0][0] + "," + a[0][1] + "," + a[1][0] + "," + a[1][1];
+ }
+ }
+
+ @Test
+ void testMatchVoidArgs() {
+ LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
+ LuaValue result = v.method("sample");
+ assertEquals("void-args", result.toString());
+ }
+
+ @Test
+ void testMatchIntArgs() {
+ LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
+ LuaValue arg = CoerceJavaToLua.coerce(new Integer(123));
+ LuaValue result = v.method("sample", arg);
+ assertEquals("int-args 123", result.toString());
+ }
+
+ @Test
+ void testMatchIntArrayArgs() {
+ LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
+ LuaValue arg = CoerceJavaToLua.coerce(new int[] { 345, 678 });
+ LuaValue result = v.method("sample", arg);
+ assertEquals("int-array-args 345,678", result.toString());
+ }
+
+ @Test
+ void testMatchIntArrayArrayArgs() {
+ LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
+ LuaValue arg = CoerceJavaToLua.coerce(new int[][] { { 22, 33 }, { 44, 55 } });
+ LuaValue result = v.method("sample", arg);
+ assertEquals("int-array-array-args 22,33,44,55", result.toString());
+ }
+
+ public static final class SomeException extends RuntimeException {
+ public SomeException(String message) {
+ super(message);
+ }
+ }
+
+ public static final class SomeClass {
+ public static void someMethod() {
+ throw new SomeException("this is some message");
+ }
+ }
+
+ @Test
+ void testExceptionMessage() {
+ String script = "local c = luajava.bindClass( \"" + SomeClass.class.getName() + "\" )\n"
+ + "return pcall( c.someMethod, c )";
+ Varargs vresult = globals.get("load").call(LuaValue.valueOf(script)).invoke(LuaValue.NONE);
+ LuaValue status = vresult.arg1();
+ LuaValue message = vresult.arg(2);
+ assertEquals(LuaValue.FALSE, status);
+ int index = message.toString().indexOf("this is some message");
+ assertTrue(index >= 0, "bad message: " + message);
+ }
+
+ @Test
+ void testLuaErrorCause() {
+ String script = "luajava.bindClass( \"" + SomeClass.class.getName() + "\"):someMethod()";
+ LuaValue chunk = globals.get("load").call(LuaValue.valueOf(script));
+ try {
+ chunk.invoke(LuaValue.NONE);
+ fail("call should not have succeeded");
+ } catch (LuaError lee) {
+ Throwable c = lee.getCause();
+ assertEquals(SomeException.class, c.getClass());
+ }
+ }
+
+ public interface VarArgsInterface {
+ public String varargsMethod(String a, String... v);
+
+ public String arrayargsMethod(String a, String[] v);
+ }
+
+ @Test
+ void testVarArgsProxy() {
+ String script = "return luajava.createProxy( \"" + VarArgsInterface.class.getName() + "\", \n" + "{\n"
+ + " varargsMethod = function(a,...)\n" + " return table.concat({a,...},'-')\n" + " end,\n"
+ + " arrayargsMethod = function(a,array)\n" + " return tostring(a)..(array and \n"
+ + " ('-'..tostring(array.length)\n" + " ..'-'..tostring(array[1])\n"
+ + " ..'-'..tostring(array[2])\n" + " ) or '-nil')\n" + " end,\n" + "} )\n";
+ Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
+ if (!chunk.arg1().toboolean())
+ fail(chunk.arg(2).toString());
+ LuaValue result = chunk.arg1().call();
+ Object u = result.touserdata();
+ VarArgsInterface v = (VarArgsInterface) u;
+ assertEquals("foo", v.varargsMethod("foo"));
+ assertEquals("foo-bar", v.varargsMethod("foo", "bar"));
+ assertEquals("foo-bar-etc", v.varargsMethod("foo", "bar", "etc"));
+ assertEquals("foo-0-nil-nil", v.arrayargsMethod("foo", new String[0]));
+ assertEquals("foo-1-bar-nil", v.arrayargsMethod("foo", new String[] { "bar" }));
+ assertEquals("foo-2-bar-etc", v.arrayargsMethod("foo", new String[] { "bar", "etc" }));
+ assertEquals("foo-3-bar-etc", v.arrayargsMethod("foo", new String[] { "bar", "etc", "etc" }));
+ assertEquals("foo-nil", v.arrayargsMethod("foo", null));
+ }
+
+ @Test
+ void testBigNum() {
+ String script = "bigNumA = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n"
+ + "bigNumB = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n"
+ + "bigNumC = bigNumA:multiply(bigNumB);\n" +
+ //"print(bigNumA:toString())\n" +
+ //"print(bigNumB:toString())\n" +
+ //"print(bigNumC:toString())\n" +
+ "return bigNumA:toString(), bigNumB:toString(), bigNumC:toString()";
+ Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
+ if (!chunk.arg1().toboolean())
+ fail(chunk.arg(2).toString());
+ Varargs results = chunk.arg1().invoke();
+ int nresults = results.narg();
+ String sa = results.tojstring(1);
+ String sb = results.tojstring(2);
+ String sc = results.tojstring(3);
+ assertEquals(3, nresults);
+ assertEquals("12345678901234567890", sa);
+ assertEquals("12345678901234567890", sb);
+ assertEquals("152415787532388367501905199875019052100", sc);
+ }
+
+ public interface IA {
+ }
+
+ public interface IB extends IA {
+ }
+
+ public interface IC extends IB {
+ }
+
+ public static class A implements IA {
+ }
+
+ public static class B extends A implements IB {
+ public String set(Object x) { return "set(Object) "; }
+
+ public String set(String x) { return "set(String) " + x; }
+
+ public String set(A x) { return "set(A) "; }
+
+ public String set(B x) { return "set(B) "; }
+
+ public String set(C x) { return "set(C) "; }
+
+ public String set(byte x) { return "set(byte) " + x; }
+
+ public String set(char x) { return "set(char) " + (int) x; }
+
+ public String set(short x) { return "set(short) " + x; }
+
+ public String set(int x) { return "set(int) " + x; }
+
+ public String set(long x) { return "set(long) " + x; }
+
+ public String set(float x) { return "set(float) " + x; }
+
+ public String set(double x) { return "set(double) " + x; }
+
+ public String setr(double x) { return "setr(double) " + x; }
+
+ public String setr(float x) { return "setr(float) " + x; }
+
+ public String setr(long x) { return "setr(long) " + x; }
+
+ public String setr(int x) { return "setr(int) " + x; }
+
+ public String setr(short x) { return "setr(short) " + x; }
+
+ public String setr(char x) { return "setr(char) " + (int) x; }
+
+ public String setr(byte x) { return "setr(byte) " + x; }
+
+ public String setr(C x) { return "setr(C) "; }
+
+ public String setr(B x) { return "setr(B) "; }
+
+ public String setr(A x) { return "setr(A) "; }
+
+ public String setr(String x) { return "setr(String) " + x; }
+
+ public String setr(Object x) { return "setr(Object) "; }
+
+ public Object getObject() { return new Object(); }
+
+ public String getString() { return "abc"; }
+
+ public byte[] getbytearray() { return new byte[] { 1, 2, 3 }; }
+
+ public A getA() { return new A(); }
+
+ public B getB() { return new B(); }
+
+ public C getC() { return new C(); }
+
+ public byte getbyte() { return 1; }
+
+ public char getchar() { return 65000; }
+
+ public short getshort() { return -32000; }
+
+ public int getint() { return 100000; }
+
+ public long getlong() { return 50000000000L; }
+
+ public float getfloat() { return 6.5f; }
+
+ public double getdouble() { return Math.PI; }
+ }
+
+ public static class C extends B implements IC {
+ }
+
+ public static class D extends C implements IA {
+ }
+
+ @Test
+ void testOverloadedJavaMethodObject() { doOverloadedMethodTest("Object", ""); }
+
+ @Test
+ void testOverloadedJavaMethodString() { doOverloadedMethodTest("String", "abc"); }
+
+ @Test
+ void testOverloadedJavaMethodA() { doOverloadedMethodTest("A", ""); }
+
+ @Test
+ void testOverloadedJavaMethodB() { doOverloadedMethodTest("B", ""); }
+
+ @Test
+ void testOverloadedJavaMethodC() { doOverloadedMethodTest("C", ""); }
+
+ @Test
+ void testOverloadedJavaMethodByte() { doOverloadedMethodTest("byte", "1"); }
+
+ @Test
+ void testOverloadedJavaMethodChar() { doOverloadedMethodTest("char", "65000"); }
+
+ @Test
+ void testOverloadedJavaMethodShort() { doOverloadedMethodTest("short", "-32000"); }
+
+ @Test
+ void testOverloadedJavaMethodInt() { doOverloadedMethodTest("int", "100000"); }
+
+ @Test
+ void testOverloadedJavaMethodLong() { doOverloadedMethodTest("long", "50000000000"); }
+
+ @Test
+ void testOverloadedJavaMethodFloat() { doOverloadedMethodTest("float", "6.5"); }
+
+ @Test
+ void testOverloadedJavaMethodDouble() { doOverloadedMethodTest("double", "3.141592653589793"); }
+
+ private void doOverloadedMethodTest(String typename, String value) {
+ String script = "local a = luajava.newInstance('" + B.class.getName() + "');\n" + "local b = a:set(a:get"
+ + typename + "())\n" + "local c = a:setr(a:get" + typename + "())\n" + "return b,c";
+ Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
+ if (!chunk.arg1().toboolean())
+ fail(chunk.arg(2).toString());
+ Varargs results = chunk.arg1().invoke();
+ int nresults = results.narg();
+ assertEquals(2, nresults);
+ LuaValue b = results.arg(1);
+ LuaValue c = results.arg(2);
+ String sb = b.tojstring();
+ String sc = c.tojstring();
+ assertEquals("set(" + typename + ") " + value, sb);
+ assertEquals("setr(" + typename + ") " + value, sc);
+ }
+
+ @Test
+ void testClassInheritanceLevels() {
+ assertEquals(0, CoerceLuaToJava.inheritanceLevels(Object.class, Object.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(Object.class, String.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(Object.class, A.class));
+ assertEquals(2, CoerceLuaToJava.inheritanceLevels(Object.class, B.class));
+ assertEquals(3, CoerceLuaToJava.inheritanceLevels(Object.class, C.class));
+
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, Object.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, String.class));
+ assertEquals(0, CoerceLuaToJava.inheritanceLevels(A.class, A.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(A.class, B.class));
+ assertEquals(2, CoerceLuaToJava.inheritanceLevels(A.class, C.class));
+
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, Object.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, String.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, A.class));
+ assertEquals(0, CoerceLuaToJava.inheritanceLevels(B.class, B.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(B.class, C.class));
+
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, Object.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, String.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, A.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, B.class));
+ assertEquals(0, CoerceLuaToJava.inheritanceLevels(C.class, C.class));
+ }
+
+ @Test
+ void testInterfaceInheritanceLevels() {
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(IA.class, A.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(IB.class, B.class));
+ assertEquals(2, CoerceLuaToJava.inheritanceLevels(IA.class, B.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(IC.class, C.class));
+ assertEquals(2, CoerceLuaToJava.inheritanceLevels(IB.class, C.class));
+ assertEquals(3, CoerceLuaToJava.inheritanceLevels(IA.class, C.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(IA.class, D.class));
+ assertEquals(2, CoerceLuaToJava.inheritanceLevels(IC.class, D.class));
+ assertEquals(3, CoerceLuaToJava.inheritanceLevels(IB.class, D.class));
+
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, A.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, A.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, B.class));
+ assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, IA.class));
+ assertEquals(1, CoerceLuaToJava.inheritanceLevels(IA.class, IB.class));
+ }
+
+ @Test
+ void testCoerceJavaToLuaLuaValue() {
+ assertSame(LuaValue.NIL, CoerceJavaToLua.coerce(LuaValue.NIL));
+ assertSame(LuaValue.ZERO, CoerceJavaToLua.coerce(LuaValue.ZERO));
+ assertSame(LuaValue.ONE, CoerceJavaToLua.coerce(LuaValue.ONE));
+ assertSame(LuaValue.INDEX, CoerceJavaToLua.coerce(LuaValue.INDEX));
+ LuaTable table = LuaValue.tableOf();
+ assertSame(table, CoerceJavaToLua.coerce(table));
+ }
+
+ @Test
+ void testCoerceJavaToLuaByeArray() {
+ byte[] bytes = "abcd".getBytes();
+ LuaValue value = CoerceJavaToLua.coerce(bytes);
+ assertEquals(LuaString.class, value.getClass());
+ assertEquals(LuaValue.valueOf("abcd"), value);
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java
new file mode 100644
index 00000000..d7e70210
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java
@@ -0,0 +1,66 @@
+package org.luaj.vm2.lib.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaValue;
+
+class LuajavaAccessibleMembersTest {
+
+ private Globals globals;
+
+ @BeforeEach
+ protected void setUp() throws Exception {
+ globals = JsePlatform.standardGlobals();
+ }
+
+ private String invokeScript(String script) {
+ try {
+ LuaValue c = globals.load(script, "script");
+ return c.call().tojstring();
+ } catch (Exception e) {
+ fail("exception: " + e);
+ return "failed";
+ }
+ }
+
+ @Test
+ void testAccessFromPrivateClassImplementedMethod() {
+ assertEquals("privateImpl-aaa-interface_method(bar)",
+ invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');"
+ + "a = b:create_PrivateImpl('aaa');" + "return a:interface_method('bar');"));
+ }
+
+ @Test
+ void testAccessFromPrivateClassPublicMethod() {
+ assertEquals("privateImpl-aaa-public_method", invokeScript("b = luajava.newInstance('"
+ + TestClass.class.getName() + "');" + "a = b:create_PrivateImpl('aaa');" + "return a:public_method();"));
+ }
+
+ @Test
+ void testAccessFromPrivateClassGetPublicField() {
+ assertEquals("aaa", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');"
+ + "a = b:create_PrivateImpl('aaa');" + "return a.public_field;"));
+ }
+
+ @Test
+ void testAccessFromPrivateClassSetPublicField() {
+ assertEquals("foo", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');"
+ + "a = b:create_PrivateImpl('aaa');" + "a.public_field = 'foo';" + "return a.public_field;"));
+ }
+
+ @Test
+ void testAccessFromPrivateClassPublicConstructor() {
+ assertEquals("privateImpl-constructor", invokeScript("b = luajava.newInstance('" + TestClass.class.getName()
+ + "');" + "c = b:get_PrivateImplClass();" + "return luajava.new(c);"));
+ }
+
+ @Test
+ void testAccessPublicEnum() {
+ assertEquals("class org.luaj.vm2.lib.jse.TestClass$SomeEnum",
+ invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');" + "return b.SomeEnum"));
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java
new file mode 100644
index 00000000..78cd657b
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java
@@ -0,0 +1,318 @@
+package org.luaj.vm2.lib.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaError;
+import org.luaj.vm2.LuaValue;
+
+class LuajavaClassMembersTest {
+ public static class A {
+ protected A() {}
+ }
+
+ public static class B extends A {
+ public byte m_byte_field;
+ public int m_int_field;
+ public double m_double_field;
+ public String m_string_field;
+
+ protected B() {}
+
+ public B(int i) { m_int_field = i; }
+
+ public String setString(String x) { return "setString(String) " + x; }
+
+ public String getString() { return "abc"; }
+
+ public int getint() { return 100000; }
+
+ public String uniq() { return "uniq()"; }
+
+ public String uniqs(String s) { return "uniqs(string:" + s + ")"; }
+
+ public String uniqi(int i) { return "uniqi(int:" + i + ")"; }
+
+ public String uniqsi(String s, int i) { return "uniqsi(string:" + s + ",int:" + i + ")"; }
+
+ public String uniqis(int i, String s) { return "uniqis(int:" + i + ",string:" + s + ")"; }
+
+ public String pick() { return "pick()"; }
+
+ public String pick(String s) { return "pick(string:" + s + ")"; }
+
+ public String pick(int i) { return "pick(int:" + i + ")"; }
+
+ public String pick(String s, int i) { return "pick(string:" + s + ",int:" + i + ")"; }
+
+ public String pick(int i, String s) { return "pick(int:" + i + ",string:" + s + ")"; }
+
+ public static String staticpick() { return "static-pick()"; }
+
+ public static String staticpick(String s) { return "static-pick(string:" + s + ")"; }
+
+ public static String staticpick(int i) { return "static-pick(int:" + i + ")"; }
+
+ public static String staticpick(String s, int i) { return "static-pick(string:" + s + ",int:" + i + ")"; }
+
+ public static String staticpick(int i, String s) { return "static-pick(int:" + i + ",string:" + s + ")"; }
+ }
+
+ public static class C extends B {
+ public C() {}
+
+ public C(String s) { m_string_field = s; }
+
+ public C(int i) { m_int_field = i; }
+
+ public C(String s, int i) { m_string_field = s; m_int_field = i; }
+
+ @Override
+ public int getint() { return 200000; }
+
+ @Override
+ public String pick(String s) { return "class-c-pick(string:" + s + ")"; }
+
+ @Override
+ public String pick(int i) { return "class-c-pick(int:" + i + ")"; }
+
+ public static class D {
+ public static String name() { return "name-of-D"; }
+ }
+ }
+
+ static LuaValue ZERO = LuaValue.ZERO;
+ static LuaValue ONE = LuaValue.ONE;
+ static LuaValue PI = LuaValue.valueOf(Math.PI);
+ static LuaValue THREE = LuaValue.valueOf(3);
+ static LuaValue NUMS = LuaValue.valueOf(123);
+ static LuaValue ABC = LuaValue.valueOf("abc");
+ static LuaValue SOMEA = CoerceJavaToLua.coerce(new A());
+ static LuaValue SOMEB = CoerceJavaToLua.coerce(new B());
+ static LuaValue SOMEC = CoerceJavaToLua.coerce(new C());
+
+ @Test
+ void testSetByteField() {
+ B b = new B();
+ JavaInstance i = new JavaInstance(b);
+ i.set("m_byte_field", ONE);
+ assertEquals(1, b.m_byte_field);
+ assertEquals(ONE, i.get("m_byte_field"));
+ i.set("m_byte_field", PI);
+ assertEquals(3, b.m_byte_field);
+ assertEquals(THREE, i.get("m_byte_field"));
+ i.set("m_byte_field", ABC);
+ assertEquals(0, b.m_byte_field);
+ assertEquals(ZERO, i.get("m_byte_field"));
+ }
+
+ @Test
+ void testSetDoubleField() {
+ B b = new B();
+ JavaInstance i = new JavaInstance(b);
+ i.set("m_double_field", ONE);
+ assertEquals(1., b.m_double_field);
+ assertEquals(ONE, i.get("m_double_field"));
+ i.set("m_double_field", PI);
+ assertEquals(Math.PI, b.m_double_field);
+ assertEquals(PI, i.get("m_double_field"));
+ i.set("m_double_field", ABC);
+ assertEquals(0., b.m_double_field);
+ assertEquals(ZERO, i.get("m_double_field"));
+ }
+
+ @Test
+ void testNoFactory() {
+ JavaClass c = JavaClass.forClass(A.class);
+ try {
+ c.call();
+ fail("did not throw lua error as expected");
+ } catch (LuaError e) {
+ }
+ }
+
+ @Test
+ void testUniqueFactoryCoercible() {
+ JavaClass c = JavaClass.forClass(B.class);
+ assertEquals(JavaClass.class, c.getClass());
+ LuaValue constr = c.get("new");
+ assertEquals(JavaConstructor.class, constr.getClass());
+ LuaValue v = constr.call(NUMS);
+ Object b = v.touserdata();
+ assertEquals(B.class, b.getClass());
+ assertEquals(123, ((B) b).m_int_field);
+ Object b0 = constr.call().touserdata();
+ assertEquals(B.class, b0.getClass());
+ assertEquals(0, ((B) b0).m_int_field);
+ }
+
+ @Test
+ void testUniqueFactoryUncoercible() {
+ JavaClass f = JavaClass.forClass(B.class);
+ LuaValue constr = f.get("new");
+ assertEquals(JavaConstructor.class, constr.getClass());
+ try {
+ LuaValue v = constr.call(LuaValue.userdataOf(new Object()));
+ Object b = v.touserdata();
+ // fail( "did not throw lua error as expected" );
+ assertEquals(0, ((B) b).m_int_field);
+ } catch (LuaError e) {
+ }
+ }
+
+ @Test
+ void testOverloadedFactoryCoercible() {
+ JavaClass f = JavaClass.forClass(C.class);
+ LuaValue constr = f.get("new");
+ assertEquals(JavaConstructor.Overload.class, constr.getClass());
+ Object c = constr.call().touserdata();
+ Object ci = constr.call(LuaValue.valueOf(123)).touserdata();
+ Object cs = constr.call(LuaValue.valueOf("abc")).touserdata();
+ Object csi = constr.call(LuaValue.valueOf("def"), LuaValue.valueOf(456)).touserdata();
+ assertEquals(C.class, c.getClass());
+ assertEquals(C.class, ci.getClass());
+ assertEquals(C.class, cs.getClass());
+ assertEquals(C.class, csi.getClass());
+ assertEquals(null, ((C) c).m_string_field);
+ assertEquals(0, ((C) c).m_int_field);
+ assertEquals("abc", ((C) cs).m_string_field);
+ assertEquals(0, ((C) cs).m_int_field);
+ assertEquals(null, ((C) ci).m_string_field);
+ assertEquals(123, ((C) ci).m_int_field);
+ assertEquals("def", ((C) csi).m_string_field);
+ assertEquals(456, ((C) csi).m_int_field);
+ }
+
+ @Test
+ void testOverloadedFactoryUncoercible() {
+ JavaClass f = JavaClass.forClass(C.class);
+ try {
+ Object c = f.call(LuaValue.userdataOf(new Object()));
+ // fail( "did not throw lua error as expected" );
+ assertEquals(0, ((C) c).m_int_field);
+ assertEquals(null, ((C) c).m_string_field);
+ } catch (LuaError e) {
+ }
+ }
+
+ @Test
+ void testNoAttribute() {
+ JavaClass f = JavaClass.forClass(A.class);
+ LuaValue v = f.get("bogus");
+ assertEquals(v, LuaValue.NIL);
+ try {
+ f.set("bogus", ONE);
+ fail("did not throw lua error as expected");
+ } catch (LuaError e) {
+ }
+ }
+
+ @Test
+ void testFieldAttributeCoercible() {
+ JavaInstance i = new JavaInstance(new B());
+ i.set("m_int_field", ONE);
+ assertEquals(1, i.get("m_int_field").toint());
+ i.set("m_int_field", THREE);
+ assertEquals(3, i.get("m_int_field").toint());
+ i = new JavaInstance(new C());
+ i.set("m_int_field", ONE);
+ assertEquals(1, i.get("m_int_field").toint());
+ i.set("m_int_field", THREE);
+ assertEquals(3, i.get("m_int_field").toint());
+ }
+
+ @Test
+ void testUniqueMethodAttributeCoercible() {
+ B b = new B();
+ JavaInstance ib = new JavaInstance(b);
+ LuaValue b_getString = ib.get("getString");
+ LuaValue b_getint = ib.get("getint");
+ assertEquals(JavaMethod.class, b_getString.getClass());
+ assertEquals(JavaMethod.class, b_getint.getClass());
+ assertEquals("abc", b_getString.call(SOMEB).tojstring());
+ assertEquals(100000, b_getint.call(SOMEB).toint());
+ assertEquals("abc", b_getString.call(SOMEC).tojstring());
+ assertEquals(200000, b_getint.call(SOMEC).toint());
+ }
+
+ @Test
+ void testUniqueMethodAttributeArgsCoercible() {
+ B b = new B();
+ JavaInstance ib = new JavaInstance(b);
+ LuaValue uniq = ib.get("uniq");
+ LuaValue uniqs = ib.get("uniqs");
+ LuaValue uniqi = ib.get("uniqi");
+ LuaValue uniqsi = ib.get("uniqsi");
+ LuaValue uniqis = ib.get("uniqis");
+ assertEquals(JavaMethod.class, uniq.getClass());
+ assertEquals(JavaMethod.class, uniqs.getClass());
+ assertEquals(JavaMethod.class, uniqi.getClass());
+ assertEquals(JavaMethod.class, uniqsi.getClass());
+ assertEquals(JavaMethod.class, uniqis.getClass());
+ assertEquals("uniq()", uniq.call(SOMEB).tojstring());
+ assertEquals("uniqs(string:abc)", uniqs.call(SOMEB, ABC).tojstring());
+ assertEquals("uniqi(int:1)", uniqi.call(SOMEB, ONE).tojstring());
+ assertEquals("uniqsi(string:abc,int:1)", uniqsi.call(SOMEB, ABC, ONE).tojstring());
+ assertEquals("uniqis(int:1,string:abc)", uniqis.call(SOMEB, ONE, ABC).tojstring());
+ assertEquals("uniqis(int:1,string:abc)",
+ uniqis.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEB, ONE, ABC, ONE })).arg1().tojstring());
+ }
+
+ @Test
+ void testOverloadedMethodAttributeCoercible() {
+ B b = new B();
+ JavaInstance ib = new JavaInstance(b);
+ LuaValue p = ib.get("pick");
+ assertEquals("pick()", p.call(SOMEB).tojstring());
+ assertEquals("pick(string:abc)", p.call(SOMEB, ABC).tojstring());
+ assertEquals("pick(int:1)", p.call(SOMEB, ONE).tojstring());
+ assertEquals("pick(string:abc,int:1)", p.call(SOMEB, ABC, ONE).tojstring());
+ assertEquals("pick(int:1,string:abc)", p.call(SOMEB, ONE, ABC).tojstring());
+ assertEquals("pick(int:1,string:abc)",
+ p.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEB, ONE, ABC, ONE })).arg1().tojstring());
+ }
+
+ @Test
+ void testUnboundOverloadedMethodAttributeCoercible() {
+ B b = new B();
+ JavaInstance ib = new JavaInstance(b);
+ LuaValue p = ib.get("pick");
+ assertEquals(JavaMethod.Overload.class, p.getClass());
+ assertEquals("pick()", p.call(SOMEC).tojstring());
+ assertEquals("class-c-pick(string:abc)", p.call(SOMEC, ABC).tojstring());
+ assertEquals("class-c-pick(int:1)", p.call(SOMEC, ONE).tojstring());
+ assertEquals("pick(string:abc,int:1)", p.call(SOMEC, ABC, ONE).tojstring());
+ assertEquals("pick(int:1,string:abc)", p.call(SOMEC, ONE, ABC).tojstring());
+ assertEquals("pick(int:1,string:abc)",
+ p.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEC, ONE, ABC, ONE })).arg1().tojstring());
+ }
+
+ @Test
+ void testOverloadedStaticMethodAttributeCoercible() {
+ B b = new B();
+ JavaInstance ib = new JavaInstance(b);
+ LuaValue p = ib.get("staticpick");
+ assertEquals("static-pick()", p.call(SOMEB).tojstring());
+ assertEquals("static-pick(string:abc)", p.call(SOMEB, ABC).tojstring());
+ assertEquals("static-pick(int:1)", p.call(SOMEB, ONE).tojstring());
+ assertEquals("static-pick(string:abc,int:1)", p.call(SOMEB, ABC, ONE).tojstring());
+ assertEquals("static-pick(int:1,string:abc)", p.call(SOMEB, ONE, ABC).tojstring());
+ assertEquals("static-pick(int:1,string:abc)",
+ p.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEB, ONE, ABC, ONE })).arg1().tojstring());
+ }
+
+ @Test
+ void testGetInnerClass() {
+ C c = new C();
+ JavaInstance ic = new JavaInstance(c);
+ LuaValue d = ic.get("D");
+ assertFalse(d.isnil());
+ assertSame(d, JavaClass.forClass(C.D.class));
+ LuaValue e = ic.get("E");
+ assertTrue(e.isnil());
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java
new file mode 100644
index 00000000..3aebd9eb
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java
@@ -0,0 +1,138 @@
+package org.luaj.vm2.lib.jse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.Date;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaValue;
+
+class OsLibTest {
+
+ LuaValue jse_lib;
+ double time;
+
+ @BeforeEach
+ public void setUp() {
+ jse_lib = JsePlatform.standardGlobals().get("os");
+ time = new Date(2001-1900, 7, 23, 14, 55, 02).getTime()/1000.0;
+ }
+
+ private void test(String format, String expected) {
+ String actual = jse_lib.get("date").call(LuaValue.valueOf(format), LuaValue.valueOf(time)).tojstring();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void testStringDateChars() { test("foo", "foo"); }
+
+ @Test
+ void testStringDate_a() { test("%a", "Thu"); }
+
+ @Test
+ void testStringDate_A() { test("%A", "Thursday"); }
+
+ @Test
+ void testStringDate_b() { test("%b", "Aug"); }
+
+ @Test
+ void testStringDate_B() { test("%B", "August"); }
+
+ @Test
+ void testStringDate_c() { test("%c", "Thu Aug 23 14:55:02 2001"); }
+
+ @Test
+ void testStringDate_d() { test("%d", "23"); }
+
+ @Test
+ void testStringDate_H() { test("%H", "14"); }
+
+ @Test
+ void testStringDate_I() { test("%I", "02"); }
+
+ @Test
+ void testStringDate_j() { test("%j", "235"); }
+
+ @Test
+ void testStringDate_m() { test("%m", "08"); }
+
+ @Test
+ void testStringDate_M() { test("%M", "55"); }
+
+ @Test
+ void testStringDate_p() { test("%p", "PM"); }
+
+ @Test
+ void testStringDate_S() { test("%S", "02"); }
+
+ @Test
+ void testStringDate_U() { test("%U", "33"); }
+
+ @Test
+ void testStringDate_w() { test("%w", "4"); }
+
+ @Test
+ void testStringDate_W() { test("%W", "34"); }
+
+ @Test
+ void testStringDate_x() { test("%x", "08/23/01"); }
+
+ @Test
+ void testStringDate_X() { test("%X", "14:55:02"); }
+
+ @Test
+ void testStringDate_y() { test("%y", "01"); }
+
+ @Test
+ void testStringDate_Y() { test("%Y", "2001"); }
+
+ @Test
+ void testStringDate_Pct() { test("%%", "%"); }
+
+ static final double DAY = 24.*3600.;
+
+ @Test
+ void testStringDate_UW_neg4() { time -= 4*DAY; test("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); }
+
+ @Test
+ void testStringDate_UW_neg3() { time -= 3*DAY; test("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_neg2() { time -= 2*DAY; test("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_neg1() { time -= DAY; test("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos0() { time += 0; test("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos1() { time += DAY; test("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos2() { time += 2*DAY; test("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); }
+
+ @Test
+ void testStringDate_UW_pos3() { time += 3*DAY; test("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); }
+
+ @Test
+ void testStringDate_UW_pos4() { time += 4*DAY; test("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); }
+
+ @Test
+ void testJseOsGetenvForEnvVariables() {
+ LuaValue USER = LuaValue.valueOf("USER");
+ LuaValue jse_user = jse_lib.get("getenv").call(USER);
+ assertFalse(jse_user.isnil());
+ }
+
+ @Test
+ void testJseOsGetenvForSystemProperties() {
+ System.setProperty("test.key.foo", "test.value.bar");
+ LuaValue key = LuaValue.valueOf("test.key.foo");
+ LuaValue value = LuaValue.valueOf("test.value.bar");
+ LuaValue jse_value = jse_lib.get("getenv").call(key);
+ assertEquals(value, jse_value);
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/TestClass.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/TestClass.java
new file mode 100644
index 00000000..4e8e2931
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/TestClass.java
@@ -0,0 +1,31 @@
+package org.luaj.vm2.lib.jse;
+
+public class TestClass {
+ private static class PrivateImpl implements TestInterface {
+ public String public_field;
+
+ public PrivateImpl() {
+ this.public_field = "privateImpl-constructor";
+ }
+
+ PrivateImpl(String f) {
+ this.public_field = f;
+ }
+
+ public String public_method() { return "privateImpl-" + public_field + "-public_method"; }
+
+ public String interface_method(String x) {
+ return "privateImpl-" + public_field + "-interface_method(" + x + ")";
+ }
+
+ public String toString() { return public_field; }
+ }
+
+ public TestInterface create_PrivateImpl(String f) { return new PrivateImpl(f); }
+
+ public Class get_PrivateImplClass() { return PrivateImpl.class; }
+
+ public enum SomeEnum {
+ ValueOne, ValueTwo,
+ }
+}
diff --git a/test/junit/org/luaj/vm2/lib/jse/TestInterface.java b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/TestInterface.java
similarity index 65%
rename from test/junit/org/luaj/vm2/lib/jse/TestInterface.java
rename to luaj-jse/src/test/java/org/luaj/vm2/lib/jse/TestInterface.java
index 1b58a0a5..a64d3303 100644
--- a/test/junit/org/luaj/vm2/lib/jse/TestInterface.java
+++ b/luaj-jse/src/test/java/org/luaj/vm2/lib/jse/TestInterface.java
@@ -1,5 +1,5 @@
package org.luaj.vm2.lib.jse;
-public interface TestInterface {
+public interface TestInterface {
String interface_method(String x);
-}
\ No newline at end of file
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/CompileClosureTest.java b/luaj-jse/src/test/java/org/luaj/vm2/script/CompileClosureTest.java
new file mode 100644
index 00000000..648d4491
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/CompileClosureTest.java
@@ -0,0 +1,27 @@
+package org.luaj.vm2.script;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaValue;
+
+class CompileClosureTest extends DefaultBindingsTestCase {
+ @BeforeEach
+ @Override
+ protected void setUp() throws Exception {
+ System.setProperty("org.luaj.luajc", "false");
+ super.setUp();
+ }
+
+ @Test
+ void testCompiledFunctionIsClosure() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("return 'foo'");
+ LuaValue value = ((LuaScriptEngine.LuajCompiledScript) cs).function;
+ assertTrue(value.isclosure());
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/CompileNonClosureTest.java b/luaj-jse/src/test/java/org/luaj/vm2/script/CompileNonClosureTest.java
new file mode 100644
index 00000000..a4c191d6
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/CompileNonClosureTest.java
@@ -0,0 +1,27 @@
+package org.luaj.vm2.script;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaValue;
+
+class CompileNonClosureTest extends DefaultBindingsTestCase {
+ @BeforeEach
+ @Override
+ protected void setUp() throws Exception {
+ System.setProperty("org.luaj.luajc", "true");
+ super.setUp();
+ }
+
+ @Test
+ void testCompiledFunctionIsNotClosure() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("return 'foo'");
+ LuaValue value = ((LuaScriptEngine.LuajCompiledScript) cs).function;
+ assertFalse(value.isclosure());
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/DefaultBindingsTestCase.java b/luaj-jse/src/test/java/org/luaj/vm2/script/DefaultBindingsTestCase.java
new file mode 100644
index 00000000..56b3bb75
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/DefaultBindingsTestCase.java
@@ -0,0 +1,10 @@
+package org.luaj.vm2.script;
+
+import javax.script.Bindings;
+
+abstract class DefaultBindingsTestCase extends EngineTestCase {
+ @Override
+ protected Bindings createBindings() {
+ return e.createBindings();
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/EngineTestCase.java b/luaj-jse/src/test/java/org/luaj/vm2/script/EngineTestCase.java
new file mode 100644
index 00000000..e65b5cd3
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/EngineTestCase.java
@@ -0,0 +1,186 @@
+package org.luaj.vm2.script;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.CharArrayReader;
+import java.io.CharArrayWriter;
+import java.io.Reader;
+
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaFunction;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.lib.OneArgFunction;
+
+abstract class EngineTestCase {
+ protected ScriptEngine e;
+ protected Bindings b;
+
+ protected abstract Bindings createBindings();
+
+ @BeforeEach
+ protected void setUp() throws Exception {
+ this.e = new ScriptEngineManager().getEngineByName("luaj");
+ this.b = createBindings();
+ }
+
+ @Test
+ void testSqrtIntResult() throws ScriptException {
+ e.put("x", 25);
+ e.eval("y = math.sqrt(x)");
+ Object y = e.get("y");
+ assertEquals(5, y);
+ }
+
+ @Test
+ void testOneArgFunction() throws ScriptException {
+ e.put("x", 25);
+ e.eval("y = math.sqrt(x)");
+ Object y = e.get("y");
+ assertEquals(5, y);
+ e.put("f", new OneArgFunction() {
+ @Override
+ public LuaValue call(LuaValue arg) {
+ return LuaValue.valueOf(arg.toString() + "123");
+ }
+ });
+ Object r = e.eval("return f('abc')");
+ assertEquals("abc123", r);
+ }
+
+ @Test
+ void testCompiledScript() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = math.sqrt(x); return y");
+ b.put("x", 144);
+ assertEquals(12, cs.eval(b));
+ }
+
+ @Test
+ void testBuggyLuaScript() {
+ try {
+ e.eval("\n\nbuggy lua code\n\n");
+ } catch (ScriptException se) {
+ assertEquals("eval threw javax.script.ScriptException: [string \"script\"]:3: syntax error",
+ se.getMessage());
+ return;
+ }
+ fail("buggy script did not throw ScriptException as expected.");
+ }
+
+ @Test
+ void testScriptRedirection() throws ScriptException {
+ Reader input = new CharArrayReader("abcdefg\nhijk".toCharArray());
+ CharArrayWriter output = new CharArrayWriter();
+ CharArrayWriter errors = new CharArrayWriter();
+ String script = "print(\"string written using 'print'\")\n"
+ + "io.write(\"string written using 'io.write()'\\n\")\n"
+ + "io.stdout:write(\"string written using 'io.stdout:write()'\\n\")\n"
+ + "io.stderr:write(\"string written using 'io.stderr:write()'\\n\")\n"
+ + "io.write([[string read using 'io.stdin:read(\"*l\")':]]..io.stdin:read(\"*l\")..\"\\n\")\n";
+
+ // Evaluate script with redirection set
+ e.getContext().setReader(input);
+ e.getContext().setWriter(output);
+ e.getContext().setErrorWriter(errors);
+ e.eval(script);
+ final String expectedOutput = "string written using 'print'\n" + "string written using 'io.write()'\n"
+ + "string written using 'io.stdout:write()'\n" + "string read using 'io.stdin:read(\"*l\")':abcdefg\n";
+ assertEquals(expectedOutput, output.toString());
+ final String expectedErrors = "string written using 'io.stderr:write()'\n";
+ assertEquals(expectedErrors, errors.toString());
+
+ // Evaluate script with redirection reset
+ output.reset();
+ errors.reset();
+ // e.getContext().setReader(null); // This will block if using actual STDIN
+ e.getContext().setWriter(null);
+ e.getContext().setErrorWriter(null);
+ e.eval(script);
+ assertEquals("", output.toString());
+ assertEquals("", errors.toString());
+ }
+
+ @Test
+ void testBindingJavaInt() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
+ b.put("x", 111);
+ assertEquals("x number 111", cs.eval(b));
+ assertEquals(111, b.get("y"));
+ }
+
+ @Test
+ void testBindingJavaDouble() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
+ b.put("x", 125.125);
+ assertEquals("x number 125.125", cs.eval(b));
+ assertEquals(125.125, b.get("y"));
+ }
+
+ @Test
+ void testBindingJavaString() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
+ b.put("x", "foo");
+ assertEquals("x string foo", cs.eval(b));
+ assertEquals("foo", b.get("y"));
+ }
+
+ @Test
+ void testBindingJavaObject() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
+ b.put("x", new SomeUserClass());
+ assertEquals("x userdata some-user-value", cs.eval(b));
+ assertEquals(SomeUserClass.class, b.get("y").getClass());
+ }
+
+ @Test
+ void testBindingJavaArray() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..#x..' '..x[1]..' '..x[2]\n");
+ b.put("x", new int[] { 777, 888 });
+ assertEquals("x userdata 2 777 888", cs.eval(b));
+ assertEquals(int[].class, b.get("y").getClass());
+ }
+
+ @Test
+ void testBindingLuaFunction() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("y = function(x) return 678 + x end; return 'foo'");
+ assertEquals("foo", cs.eval(b).toString());
+ assertTrue(b.get("y") instanceof LuaFunction);
+ assertEquals(LuaValue.valueOf(801), ((LuaFunction) b.get("y")).call(LuaValue.valueOf(123)));
+ }
+
+ @Test
+ void testUserClasses() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("x = x or luajava.newInstance('java.lang.String', 'test')\n"
+ + "return 'x ' .. type(x) .. ' ' .. tostring(x)\n");
+ assertEquals("x string test", cs.eval(b));
+ b.put("x", new SomeUserClass());
+ assertEquals("x userdata some-user-value", cs.eval(b));
+ }
+
+ @Test
+ void testReturnMultipleValues() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("return 'foo', 'bar'\n");
+ Object o = cs.eval();
+ assertEquals(Object[].class, o.getClass());
+ Object[] array = (Object[]) o;
+ assertEquals(2, array.length);
+ assertEquals("foo", array[0]);
+ assertEquals("bar", array[1]);
+ }
+
+ private static class SomeUserClass {
+ @Override
+ public String toString() {
+ return "some-user-value";
+ }
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/LookupEngineTest.java b/luaj-jse/src/test/java/org/luaj/vm2/script/LookupEngineTest.java
new file mode 100644
index 00000000..4f73ae79
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/LookupEngineTest.java
@@ -0,0 +1,43 @@
+package org.luaj.vm2.script;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+
+import org.junit.jupiter.api.Test;
+
+class LookupEngineTest {
+ @Test
+ void testGetEngineByExtension() {
+ ScriptEngine e = new ScriptEngineManager().getEngineByExtension(".lua");
+ assertNotNull(e);
+ assertEquals(LuaScriptEngine.class, e.getClass());
+ }
+
+ @Test
+ void testGetEngineByName() {
+ ScriptEngine e = new ScriptEngineManager().getEngineByName("luaj");
+ assertNotNull(e);
+ assertEquals(LuaScriptEngine.class, e.getClass());
+ }
+
+ @Test
+ void testGetEngineByMimeType() {
+ ScriptEngine e = new ScriptEngineManager().getEngineByMimeType("text/lua");
+ assertNotNull(e);
+ assertEquals(LuaScriptEngine.class, e.getClass());
+ }
+
+ @Test
+ void testFactoryMetadata() {
+ ScriptEngine e = new ScriptEngineManager().getEngineByName("luaj");
+ ScriptEngineFactory f = e.getFactory();
+ assertEquals("Luaj", f.getEngineName());
+ assertEquals("Luaj 0.0", f.getEngineVersion());
+ assertEquals("lua", f.getLanguageName());
+ assertEquals("5.2", f.getLanguageVersion());
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/SimpleBindingsTest.java b/luaj-jse/src/test/java/org/luaj/vm2/script/SimpleBindingsTest.java
new file mode 100644
index 00000000..c30d943a
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/SimpleBindingsTest.java
@@ -0,0 +1,11 @@
+package org.luaj.vm2.script;
+
+import javax.script.Bindings;
+import javax.script.SimpleBindings;
+
+class SimpleBindingsTest extends EngineTestCase {
+ @Override
+ protected Bindings createBindings() {
+ return new SimpleBindings();
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/UserContextTest.java b/luaj-jse/src/test/java/org/luaj/vm2/script/UserContextTest.java
new file mode 100644
index 00000000..bd3163d3
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/UserContextTest.java
@@ -0,0 +1,55 @@
+package org.luaj.vm2.script;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class UserContextTest {
+ protected ScriptEngine e;
+ protected Bindings b;
+ protected ScriptContext c;
+
+ @BeforeEach
+ public void setUp() {
+ this.e = new ScriptEngineManager().getEngineByName("luaj");
+ this.c = new LuajContext();
+ this.b = c.getBindings(ScriptContext.ENGINE_SCOPE);
+ }
+
+ @Test
+ void testUncompiledScript() throws ScriptException {
+ b.put("x", 144);
+ assertEquals(12, e.eval("z = math.sqrt(x); return z", b));
+ assertEquals(12, b.get("z"));
+ assertEquals(null, e.getBindings(ScriptContext.ENGINE_SCOPE).get("z"));
+ assertEquals(null, e.getBindings(ScriptContext.GLOBAL_SCOPE).get("z"));
+
+ b.put("x", 25);
+ assertEquals(5, e.eval("z = math.sqrt(x); return z", c));
+ assertEquals(5, b.get("z"));
+ assertEquals(null, e.getBindings(ScriptContext.ENGINE_SCOPE).get("z"));
+ assertEquals(null, e.getBindings(ScriptContext.GLOBAL_SCOPE).get("z"));
+ }
+
+ @Test
+ void testCompiledScript() throws ScriptException {
+ CompiledScript cs = ((Compilable) e).compile("z = math.sqrt(x); return z");
+
+ b.put("x", 144);
+ assertEquals(12, cs.eval(b));
+ assertEquals(12, b.get("z"));
+
+ b.put("x", 25);
+ assertEquals(5, cs.eval(c));
+ assertEquals(5, b.get("z"));
+ }
+}
diff --git a/luaj-jse/src/test/java/org/luaj/vm2/script/WriterTest.java b/luaj-jse/src/test/java/org/luaj/vm2/script/WriterTest.java
new file mode 100644
index 00000000..a70ab95e
--- /dev/null
+++ b/luaj-jse/src/test/java/org/luaj/vm2/script/WriterTest.java
@@ -0,0 +1,38 @@
+package org.luaj.vm2.script;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.CharArrayWriter;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class WriterTest {
+ protected ScriptEngine e;
+ protected Bindings b;
+
+ @BeforeEach
+ public void setUp() {
+ this.e = new ScriptEngineManager().getEngineByName("luaj");
+ this.b = e.getBindings(ScriptContext.ENGINE_SCOPE);
+ }
+
+ @Test
+ void testWriter() throws ScriptException {
+ CharArrayWriter output = new CharArrayWriter();
+ CharArrayWriter errors = new CharArrayWriter();
+ e.getContext().setWriter(output);
+ e.getContext().setErrorWriter(errors);
+ e.eval("io.write( [[line]] )");
+ assertEquals("line", output.toString());
+ e.eval("io.write( [[ one\nline two\n]] )");
+ assertEquals("line one\nline two\n", output.toString());
+ output.reset();
+ }
+}
diff --git a/luaj-jse/src/test/resources/.keep b/luaj-jse/src/test/resources/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/luaj-sources-3.0.2.jar b/luaj-sources-3.0.2.jar
new file mode 100644
index 00000000..4cefe052
Binary files /dev/null and b/luaj-sources-3.0.2.jar differ
diff --git a/luaj-test/.gitignore b/luaj-test/.gitignore
new file mode 100644
index 00000000..29c1928e
--- /dev/null
+++ b/luaj-test/.gitignore
@@ -0,0 +1,4 @@
+abc.txt
+seektest.txt
+tmp1.out
+tmp2.out
diff --git a/luaj-test/pom.xml b/luaj-test/pom.xml
new file mode 100644
index 00000000..c1372b40
--- /dev/null
+++ b/luaj-test/pom.xml
@@ -0,0 +1,70 @@
+
+ 4.0.0
+
+
+ org.luaj
+ luaj-parent
+ 3.0-SNAPSHOT
+
+
+ luaj-test
+
+ LuaJ-Tests
+ Testsuites for LuaJ
+
+
+
+ org.luaj
+ luaj-core
+ ${project.version}
+
+
+ org.luaj
+ luaj-jme
+ ${project.version}
+
+
+ org.luaj
+ luaj-jse
+ ${project.version}
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.microemu
+ microemulator
+ 2.0.4
+ test
+
+
+ org.microemu
+ microemu-jsr-75
+ 2.0.4
+ test
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ report-aggregate
+ verify
+
+ report-aggregate
+
+
+
+
+
+
+
+
diff --git a/luaj-test/src/main/java/.keep b/luaj-test/src/main/java/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/luaj-test/src/main/resources/.keep b/luaj-test/src/main/resources/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/luaj-test/src/test/java/org/luaj/CompatibiltyTest.java b/luaj-test/src/test/java/org/luaj/CompatibiltyTest.java
new file mode 100644
index 00000000..c15e1173
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/CompatibiltyTest.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Luaj.org. 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;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaBoolean;
+import org.luaj.vm2.LuaFunction;
+import org.luaj.vm2.LuaNil;
+import org.luaj.vm2.LuaNumber;
+import org.luaj.vm2.LuaString;
+import org.luaj.vm2.LuaThread;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.luajc.LuaJC;
+
+/**
+ * Compatibility tests for the Luaj VM
+ *
+ * Results are compared for exact match with the installed C-based lua
+ * environment.
+ */
+public class CompatibiltyTest {
+
+ abstract static class CompatibiltyTestCase extends PlatformTestCase {
+ LuaValue savedStringMetatable;
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ savedStringMetatable = LuaString.s_metatable;
+ setBaseDir("compatibility");
+ super.setUp();
+ }
+
+ @AfterEach
+ protected void tearDown() {
+ LuaNil.s_metatable = null;
+ LuaBoolean.s_metatable = null;
+ LuaNumber.s_metatable = null;
+ LuaFunction.s_metatable = null;
+ LuaThread.s_metatable = null;
+ LuaString.s_metatable = savedStringMetatable;
+ }
+
+ @Test
+ void testBaseLib() { runTest("baselib"); }
+
+ @Test
+ void testCoroutineLib() { runTest("coroutinelib"); }
+
+ @Disabled("Too many failing tests")
+ @Test
+ void testDebugLib() { runTest("debuglib"); }
+
+ @Test
+ void testErrors() { runTest("errors"); }
+
+ @Test
+ void testFunctions() { runTest("functions"); }
+
+ @Test
+ void testIoLib() { runTest("iolib"); }
+
+ @Test
+ void testManyUpvals() { runTest("manyupvals"); }
+
+ @Test
+ void testMathLib() { runTest("mathlib"); }
+
+ @Test
+ void testMetatags() { runTest("metatags"); }
+
+ @Test
+ void testOsLib() { runTest("oslib"); }
+
+ @Test
+ void testStringLib() { runTest("stringlib"); }
+
+ @Test
+ void testTableLib() { runTest("tablelib"); }
+
+ @Test
+ void testTailcalls() { runTest("tailcalls"); }
+
+ @Test
+ void testUpvalues() { runTest("upvalues"); }
+
+ @Test
+ void testVm() { runTest("vm"); }
+ }
+
+ @Nested
+ public static class JmeCompatibilityTest extends CompatibiltyTestCase {
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ setPlatform(PlatformTestCase.PlatformType.JME);
+ System.setProperty("JME", "true");
+ super.setUp();
+ }
+
+ // Emulator cannot create files for writing
+ @Override
+ void testIoLib() {}
+
+ // Emulator cannot create files for writing
+ @Override
+ void testOsLib() {}
+ }
+
+ @Nested
+ public static class JseCompatibilityTest extends CompatibiltyTestCase {
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ setPlatform(PlatformTestCase.PlatformType.JSE);
+ System.setProperty("JME", "false");
+ super.setUp();
+ }
+ }
+
+ @Nested
+ public static class LuaJCCompatibilityTest extends CompatibiltyTestCase {
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ setPlatform(PlatformTestCase.PlatformType.LUAJIT);
+ System.setProperty("JME", "false");
+ super.setUp();
+ LuaJC.install(globals);
+ }
+
+ // not supported on this platform - don't test
+ @Override
+ void testDebugLib() {}
+
+ // FIXME Test failures
+ @Override
+ void testBaseLib() {}
+
+ // FIXME Test failures
+ @Override
+ void testCoroutineLib() {}
+
+ // FIXME Test failures
+ @Override
+ void testIoLib() {}
+
+ // FIXME Test failures
+ @Override
+ void testMetatags() {}
+
+ // FIXME Test failures
+ @Override
+ void testOsLib() {}
+
+ // FIXME Test failures
+ @Override
+ void testStringLib() {}
+ }
+}
diff --git a/luaj-test/src/test/java/org/luaj/CompilerTest.java b/luaj-test/src/test/java/org/luaj/CompilerTest.java
new file mode 100644
index 00000000..3f85bc8f
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/CompilerTest.java
@@ -0,0 +1,95 @@
+package org.luaj;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class CompilerTest extends CompilingTestCase {
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ setBaseDir("lua5.2.1-tests");
+ super.setUp();
+ }
+
+ @Test
+ void testAll() { doTest("all"); }
+
+ @Test
+ void testApi() { doTest("api"); }
+
+ @Test
+ void testAttrib() { doTest("attrib"); }
+
+ @Test
+ void testBig() { doTest("big"); }
+
+ @Test
+ void testBitwise() { doTest("bitwise"); }
+
+ @Test
+ void testCalls() { doTest("calls"); }
+
+ @Test
+ void testChecktable() { doTest("checktable"); }
+
+ @Test
+ void testClosure() { doTest("closure"); }
+
+ @Test
+ void testCode() { doTest("code"); }
+
+ @Test
+ void testConstruct() { doTest("constructs"); }
+
+ @Test
+ void testCoroutine() { doTest("coroutine"); }
+
+ @Test
+ void testDb() { doTest("db"); }
+
+ @Test
+ void testErrors() { doTest("errors"); }
+
+ @Test
+ void testEvents() { doTest("events"); }
+
+ @Test
+ void testFiles() { doTest("files"); }
+
+ @Test
+ void testGc() { doTest("gc"); }
+
+ @Test
+ void testGoto() { doTest("goto"); }
+
+ @Test
+ void testLiterals() { doTest("literals"); }
+
+ @Test
+ void testLocals() { doTest("locals"); }
+
+ @Test
+ void testMain() { doTest("main"); }
+
+ @Test
+ void testMath() { doTest("math"); }
+
+ @Test
+ void testNextvar() { doTest("nextvar"); }
+
+ @Test
+ void testPm() { doTest("pm"); }
+
+ @Test
+ void testSort() { doTest("sort"); }
+
+ @Test
+ void testStrings() { doTest("strings"); }
+
+ @Test
+ void testVararg() { doTest("vararg"); }
+
+ @Test
+ void testVerybig() { doTest("verybig"); }
+}
diff --git a/luaj-test/src/test/java/org/luaj/CompilingTestCase.java b/luaj-test/src/test/java/org/luaj/CompilingTestCase.java
new file mode 100644
index 00000000..482aa16c
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/CompilingTestCase.java
@@ -0,0 +1,53 @@
+package org.luaj;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.luaj.vm2.Print;
+import org.luaj.vm2.Prototype;
+import org.luaj.vm2.compiler.DumpState;
+
+abstract class CompilingTestCase extends ResourcesTestCase {
+
+ protected void doTest(String name) {
+ try {
+ // compile in memory
+ Prototype p = globals.loadPrototype(inputStreamOfLua(name), "@" + name + ".lua", "bt");
+ String actual = protoToString(p);
+
+ // load expected value from jar
+ Prototype e = globals.loadPrototype(inputStreamOfBytecode(name), name, "b");
+ String expected = protoToString(e);
+
+ // compare results
+ assertEquals(expected, actual);
+
+ // dump into memory
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DumpState.dump(p, baos, false);
+ ByteArrayInputStream dumped = new ByteArrayInputStream(baos.toByteArray());
+
+ // re-undump
+ Prototype p2 = globals.loadPrototype(dumped, name, "b");
+ String actual2 = protoToString(p2);
+
+ // compare again
+ assertEquals(actual, actual2);
+
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ }
+
+ private String protoToString(Prototype p) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ Print.ps = ps;
+ Print.printFunction(p, true);
+ return baos.toString();
+ }
+}
diff --git a/test/junit/org/luaj/vm2/ErrorsTest.java b/luaj-test/src/test/java/org/luaj/ErrorsTest.java
similarity index 60%
rename from test/junit/org/luaj/vm2/ErrorsTest.java
rename to luaj-test/src/test/java/org/luaj/ErrorsTest.java
index 264d3d4d..7aa61021 100644
--- a/test/junit/org/luaj/vm2/ErrorsTest.java
+++ b/luaj-test/src/test/java/org/luaj/ErrorsTest.java
@@ -19,45 +19,65 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
-package org.luaj.vm2;
+package org.luaj;
import java.io.IOException;
import java.io.InputStream;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
/**
* Test argument type check errors
*
- * Results are compared for exact match with
- * the installed C-based lua environment.
+ * Results are compared for exact match with the installed C-based lua
+ * environment.
*/
-public class ErrorsTest extends ScriptDrivenTest {
+class ErrorsTest extends PlatformTestCase {
- private static final String dir = "errors/";
-
- public ErrorsTest() {
- super(ScriptDrivenTest.PlatformType.JSE, dir);
- }
-
- protected void setUp() throws Exception {
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ setBaseDir("errors");
+ setPlatform(PlatformTestCase.PlatformType.JSE);
super.setUp();
}
- public void testBaseLibArgs() {
+ @Test
+ void testBaseLibArgs() {
globals.STDIN = new InputStream() {
+ @Override
public int read() throws IOException {
return -1;
}
};
- runTest("baselibargs");
+ runTest("baselibargs");
}
- public void testCoroutineLibArgs() { runTest("coroutinelibargs"); }
- public void testDebugLibArgs() { runTest("debuglibargs"); }
- public void testIoLibArgs() { runTest("iolibargs"); }
- public void testMathLibArgs() { runTest("mathlibargs"); }
- public void testModuleLibArgs() { runTest("modulelibargs"); }
- public void testOperators() { runTest("operators"); }
- public void testStringLibArgs() { runTest("stringlibargs"); }
- public void testTableLibArgs() { runTest("tablelibargs"); }
-
+
+ @Test
+ void testCoroutineLibArgs() { runTest("coroutinelibargs"); }
+
+ @Disabled("Too many failing tests")
+ @Test
+ void testDebugLibArgs() { runTest("debuglibargs"); }
+
+ @Test
+ void testIoLibArgs() { runTest("iolibargs"); }
+
+ @Test
+ void testMathLibArgs() { runTest("mathlibargs"); }
+
+ @Test
+ void testModuleLibArgs() { runTest("modulelibargs"); }
+
+ @Test
+ void testOperators() { runTest("operators"); }
+
+ @Test
+ void testStringLibArgs() { runTest("stringlibargs"); }
+
+ @Test
+ void testTableLibArgs() { runTest("tablelibargs"); }
+
}
diff --git a/luaj-test/src/test/java/org/luaj/LuaParserTest.java b/luaj-test/src/test/java/org/luaj/LuaParserTest.java
new file mode 100644
index 00000000..6fbe0687
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/LuaParserTest.java
@@ -0,0 +1,20 @@
+package org.luaj;
+
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.luaj.vm2.parser.LuaParser;
+
+public class LuaParserTest extends CompilerTest {
+
+ @Override
+ protected void doTest(String name) {
+ try {
+ LuaParser parser = new LuaParser(inputStreamOfLua(name), ISO_8859_1);
+ parser.Chunk();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/luaj-test/src/test/java/org/luaj/PlatformTestCase.java b/luaj-test/src/test/java/org/luaj/PlatformTestCase.java
new file mode 100644
index 00000000..265e99d3
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/PlatformTestCase.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Luaj.org. 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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.lib.jme.JmePlatform;
+import org.luaj.vm2.lib.jse.JsePlatform;
+import org.luaj.vm2.lib.jse.JseProcess;
+import org.luaj.vm2.luajc.LuaJC;
+
+abstract class PlatformTestCase extends ResourcesTestCase {
+ public static final boolean nocompile = "true".equals(System.getProperty("nocompile"));
+
+ public enum PlatformType {
+ JME, JSE, LUAJIT,
+ }
+
+ private PlatformType platform;
+
+ private void initGlobals() {
+ switch (platform) {
+ default:
+ case JSE:
+ case LUAJIT:
+ globals = JsePlatform.debugGlobals();
+ break;
+ case JME:
+ globals = JmePlatform.debugGlobals();
+ break;
+ }
+ }
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ initGlobals();
+ globals.finder = filename -> {
+ try {
+ return inputStreamOfFile(filename);
+ } catch (IOException e) {
+ return null;
+ }
+ };
+ }
+
+ protected void setPlatform(PlatformType platform) { this.platform = platform; }
+
+ protected void runTest(String testName) {
+ try {
+ // override print()
+ final ByteArrayOutputStream output = new ByteArrayOutputStream();
+ final PrintStream oldps = globals.STDOUT;
+ final PrintStream ps = new PrintStream(output);
+ globals.STDOUT = ps;
+
+ // run the script
+ try {
+ LuaValue chunk = loadScript(testName, globals);
+ chunk.call(LuaValue.valueOf(platform.toString()));
+
+ ps.flush();
+ String actualOutput = new String(output.toByteArray());
+ String expectedOutput = getExpectedOutput(testName);
+ actualOutput = actualOutput.replaceAll("\r\n", "\n");
+ expectedOutput = expectedOutput.replaceAll("\r\n", "\n");
+
+ if (!expectedOutput.equals(actualOutput))
+ Files.write(new File(testName + ".out").toPath(), actualOutput.getBytes(), new OpenOption[0]);
+ assertEquals(expectedOutput, actualOutput);
+ } finally {
+ globals.STDOUT = oldps;
+ ps.close();
+ }
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe.toString());
+ } catch (InterruptedException ie) {
+ throw new RuntimeException(ie.toString());
+ }
+ }
+
+ private LuaValue loadScript(String name, Globals globals) throws IOException {
+ InputStream script = inputStreamOfLua(name);
+ if (script == null)
+ fail("Could not load script for test case: " + name);
+ try {
+ switch (this.platform) {
+ case LUAJIT:
+ if (nocompile) {
+ LuaValue c = (LuaValue) Class.forName(name).newInstance();
+ return c;
+ } else {
+ LuaJC.install(globals);
+ return globals.load(script, name, "bt", globals);
+ }
+ default:
+ return globals.load(script, "@" + name + ".lua", "bt", globals);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new IOException(e.toString());
+ } finally {
+ script.close();
+ }
+ }
+
+ private String getExpectedOutput(final String name) throws IOException, InterruptedException {
+ InputStream output = inputStreamOfResult(platform.name().toLowerCase() + "/" + name);
+ if (output != null)
+ try {
+ return readString(output);
+ } finally {
+ output.close();
+ }
+ String expectedOutput = executeLuaProcess(name);
+ if (expectedOutput == null)
+ throw new IOException("Failed to get comparison output or run process for " + name);
+ return expectedOutput;
+ }
+
+ private String executeLuaProcess(String name) throws IOException, InterruptedException {
+ InputStream script = inputStreamOfLua(name);
+ if (script == null)
+ throw new IOException("Failed to find source file " + script);
+ try {
+ String luaCommand = System.getProperty("LUA_COMMAND");
+ if (luaCommand == null)
+ luaCommand = "lua";
+ String[] args = new String[] { luaCommand, "-", platform.toString() };
+ return collectProcessOutput(args, script);
+ } finally {
+ script.close();
+ }
+ }
+
+ private static String collectProcessOutput(String[] cmd, final InputStream input)
+ throws IOException, InterruptedException {
+ Runtime r = Runtime.getRuntime();
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new JseProcess(cmd, input, baos, System.err).waitFor();
+ return new String(baos.toByteArray());
+ }
+
+ private static String readString(InputStream is) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ copy(is, baos);
+ return new String(baos.toByteArray());
+ }
+
+ private static void copy(InputStream is, OutputStream os) throws IOException {
+ byte[] buf = new byte[1024];
+ int r;
+ while ( (r = is.read(buf)) >= 0 ) {
+ os.write(buf, 0, r);
+ }
+ }
+
+}
diff --git a/luaj-test/src/test/java/org/luaj/RegressionsTest.java b/luaj-test/src/test/java/org/luaj/RegressionsTest.java
new file mode 100644
index 00000000..10b4c983
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/RegressionsTest.java
@@ -0,0 +1,47 @@
+package org.luaj;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Framework to add regression tests as problem areas are found.
+ *
+ * To add a new regression test: 1) run "unpack.sh" in the project root 2) add a
+ * new "lua" file in the "regressions" subdirectory 3) run "repack.sh" in the
+ * project root 4) add a line to the source file naming the new test
+ *
+ * After adding a test, check in the zip file rather than the individual
+ * regression test files.
+ *
+ * @author jrosebor
+ */
+class RegressionsTest extends CompilingTestCase {
+
+ @BeforeEach
+ @Override
+ protected void setUp() {
+ setBaseDir("regressions");
+ super.setUp();
+ }
+
+ @Test
+ void testModulo() { doTest("modulo"); }
+
+ @Test
+ void testConstruct() { doTest("construct"); }
+
+ @Test
+ void testBigAttrs() { doTest("bigattr"); }
+
+ @Test
+ void testControlChars() { doTest("controlchars"); }
+
+ @Test
+ void testComparators() { doTest("comparators"); }
+
+ @Test
+ void testMathRandomseed() { doTest("mathrandomseed"); }
+
+ @Test
+ void testVarargs() { doTest("varargs"); }
+}
diff --git a/luaj-test/src/test/java/org/luaj/ResourcesTestCase.java b/luaj-test/src/test/java/org/luaj/ResourcesTestCase.java
new file mode 100644
index 00000000..8a980a44
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/ResourcesTestCase.java
@@ -0,0 +1,38 @@
+package org.luaj;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+abstract class ResourcesTestCase {
+
+ private String baseDir;
+
+ protected Globals globals;
+
+ @BeforeEach
+ protected void setUp() {
+ globals = JsePlatform.standardGlobals();
+ }
+
+ protected void setBaseDir(String baseDir) { this.baseDir = baseDir; }
+
+ protected InputStream inputStreamOfFile(String file) throws IOException {
+ return getClass().getClassLoader().getResourceAsStream(baseDir + "/" + file);
+ }
+
+ protected InputStream inputStreamOfLua(String name) throws IOException {
+ return inputStreamOfFile(name + ".lua");
+ }
+
+ protected InputStream inputStreamOfResult(String name) throws IOException {
+ return inputStreamOfFile(name + ".out");
+ }
+
+ protected InputStream inputStreamOfBytecode(String name) throws IOException {
+ return inputStreamOfFile(name + ".lc");
+ }
+}
diff --git a/test/java/org/luaj/luajc/SampleMainChunk.java b/luaj-test/src/test/java/org/luaj/luajc/SampleMainChunk.java
similarity index 52%
rename from test/java/org/luaj/luajc/SampleMainChunk.java
rename to luaj-test/src/test/java/org/luaj/luajc/SampleMainChunk.java
index 87168ada..4d697f44 100644
--- a/test/java/org/luaj/luajc/SampleMainChunk.java
+++ b/luaj-test/src/test/java/org/luaj/luajc/SampleMainChunk.java
@@ -8,43 +8,43 @@ import org.luaj.vm2.lib.VarArgFunction;
public class SampleMainChunk extends VarArgFunction {
static final LuaValue $print = valueOf("print");
- static final LuaValue $foo = valueOf("foo");
-
- LuaValue[] rw_ENV; // The environment when it is read-write
+ static final LuaValue $foo = valueOf("foo");
+
+ LuaValue[] rw_ENV; // The environment when it is read-write
// LuaValue ro_ENV; // The environment when it is read-only in all sub-functions
-
- LuaValue[] rw_openup1; // upvalue that we create and modify in "slot" 1, passed to sub-function in initer.
- LuaValue[] rw_openup2; // array is instantiated on first set or before supply to closure, after that value is get, set.
- LuaValue[] rw_openup3; // closing these nulls them out, sub-functions still retain references to array & can use
- LuaValue ro_openup4; // open upvalue that is read-only once it is supplied to an inner function.
- LuaValue ro_openup5; // closing this also nulls it out.
-
+
+ LuaValue[] rw_openup1; // upvalue that we create and modify in "slot" 1, passed to sub-function in initer.
+ LuaValue[] rw_openup2; // array is instantiated on first set or before supply to closure, after that value is get, set.
+ LuaValue[] rw_openup3; // closing these nulls them out, sub-functions still retain references to array & can use
+ LuaValue ro_openup4; // open upvalue that is read-only once it is supplied to an inner function.
+ LuaValue ro_openup5; // closing this also nulls it out.
+
// Must have this in the main chunk so it can be loaded and instantiated on all platforms.
public SampleMainChunk() {
}
-
+
public void initupvalue1(LuaValue[] v) {
this.rw_ENV = v;
}
public Varargs invoke(Varargs args) {
rw_ENV[0].get($print).call($foo);
-
+
rw_ENV[0].set($print, new InnerFunction(rw_openup3, rw_openup1, ro_openup5));
-
+
return null;
}
-
+
static class InnerFunction extends TwoArgFunction {
static final LuaValue $print = valueOf("print"); // A constant, named for what it is.
- static final LuaValue $foo = valueOf("foo");
-
- final LuaValue[] rw_upvalue1; // from enclosing function, corresponds to upvaldesc not instack.
- final LuaValue[] rw_upvalue2; // from enclosing function, corresponds to upvaldesc not instack.
- final LuaValue ro_upvalue3; // from enclosing function, but read-only everywhere.
+ static final LuaValue $foo = valueOf("foo");
- LuaValue[] rw_openup1; // closing these nulls them out, sub-functions still retain references to array & can use
- LuaValue ro_openup2; // open upvalue that is read-only once it is supplied to an inner function.
+ final LuaValue[] rw_upvalue1; // from enclosing function, corresponds to upvaldesc not instack.
+ final LuaValue[] rw_upvalue2; // from enclosing function, corresponds to upvaldesc not instack.
+ final LuaValue ro_upvalue3; // from enclosing function, but read-only everywhere.
+
+ LuaValue[] rw_openup1; // closing these nulls them out, sub-functions still retain references to array & can use
+ LuaValue ro_openup2; // open upvalue that is read-only once it is supplied to an inner function.
InnerFunction(LuaValue[] rw_upvalue1, LuaValue[] rw_upvalue2, LuaValue ro_upvalue3) {
this.rw_upvalue1 = rw_upvalue1;
@@ -55,7 +55,7 @@ public class SampleMainChunk extends VarArgFunction {
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return NIL;
}
-
+
}
}
diff --git a/test/java/org/luaj/luajc/TestLuaJ.java b/luaj-test/src/test/java/org/luaj/luajc/TestLuaJ.java
similarity index 81%
rename from test/java/org/luaj/luajc/TestLuaJ.java
rename to luaj-test/src/test/java/org/luaj/luajc/TestLuaJ.java
index eee17c5c..cbd8d7b5 100644
--- a/test/java/org/luaj/luajc/TestLuaJ.java
+++ b/luaj-test/src/test/java/org/luaj/luajc/TestLuaJ.java
@@ -30,41 +30,33 @@ import org.luaj.vm2.lib.jse.JsePlatform;
/** Test the plain old bytecode interpreter */
public class TestLuaJ {
// create the script
- public static String name = "script";
- public static String script =
- "function r(q,...)\n"+
- " local a=arg\n"+
- " return a and a[2]\n"+
- "end\n" +
- "function s(q,...)\n"+
- " local a=arg\n"+
- " local b=...\n"+
- " return a and a[2],b\n"+
- "end\n" +
- "print( r(111,222,333),s(111,222,333) )";
-
+ public static String name = "script";
+ public static String script = "function r(q,...)\n" + " local a=arg\n" + " return a and a[2]\n" + "end\n"
+ + "function s(q,...)\n" + " local a=arg\n" + " local b=...\n" + " return a and a[2],b\n" + "end\n"
+ + "print( r(111,222,333),s(111,222,333) )";
+
public static void main(String[] args) throws Exception {
System.out.println(script);
-
+
// create an environment to run in
Globals globals = JsePlatform.standardGlobals();
-
+
// compile into a chunk, or load as a class
LuaValue chunk = globals.load(script, "script");
-
+
// The loaded chunk should be a closure, which contains the prototype.
- print( chunk.checkclosure().p );
+ print(chunk.checkclosure().p);
// The chunk can be called with arguments as desired.
chunk.call(LuaValue.ZERO, LuaValue.ONE);
}
private static void print(Prototype p) {
- System.out.println("--- "+p);
+ System.out.println("--- " + p);
Print.printCode(p);
- if (p.p!=null)
- for ( int i=0,n=p.p.length; i 0)
filename = args[0];
- System.out.println("filename: "+filename);
+ System.out.println("filename: " + filename);
try {
-
+
// create an environment to run in
globals = JsePlatform.standardGlobals();
@@ -56,47 +56,44 @@ public class TestLuaJC {
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")) ) {
+ if (!(args.length > 0 && args[0].equals("nocompile"))) {
LuaJC.install(globals);
f = globals.loadfile(filename).arg1();
}
-
+
// call with arguments
Varargs v = f.invoke(LuaValue.NONE);
-
+
// print the result
- System.out.println("result: "+v);
+ System.out.println("result: " + v);
// Write out the files.
// saveClasses();
-
- } catch ( Throwable e ) {
+
+ } catch (Throwable e) {
e.printStackTrace();
}
}
private static void saveClasses() throws Exception {
- // create the chunk
+ // create the chunk
String destdir = ".";
-
+
InputStream is = globals.finder.findResource(filename);
Hashtable t = LuaJC.instance.compileAll(is, filename, filename, globals, true);
- // write out the chunk
- for ( Enumeration e = t.keys(); e.hasMoreElements(); ) {
- String key = (String) e.nextElement();
- byte[] bytes = (byte[]) t.get(key);
- String destpath = (destdir!=null? destdir+"/": "") + key + ".class";
- System.out.println(
- "chunk "+filename+
- " from "+filename+
- " written to "+destpath
- +" length="+bytes.length+" bytes");
- FileOutputStream fos = new FileOutputStream( destpath );
- fos.write( bytes );
- fos.close();
- }
-
+ // write out the chunk
+ for (Enumeration e = t.keys(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ byte[] bytes = (byte[]) t.get(key);
+ String destpath = (destdir != null? destdir + "/": "") + key + ".class";
+ System.out.println("chunk " + filename + " from " + filename + " written to " + destpath + " length="
+ + bytes.length + " bytes");
+ FileOutputStream fos = new FileOutputStream(destpath);
+ fos.write(bytes);
+ fos.close();
+ }
+
}
-
+
}
diff --git a/luaj-test/src/test/java/org/luaj/math/MathLibComparisonTest.java b/luaj-test/src/test/java/org/luaj/math/MathLibComparisonTest.java
new file mode 100644
index 00000000..14a5a2b4
--- /dev/null
+++ b/luaj-test/src/test/java/org/luaj/math/MathLibComparisonTest.java
@@ -0,0 +1,250 @@
+package org.luaj.math;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.luaj.vm2.LuaError;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.lib.jme.JmePlatform;
+import org.luaj.vm2.lib.jse.JsePlatform;
+
+class MathLibComparisonTest {
+
+ private LuaValue j2se;
+ private LuaValue j2me;
+ private boolean supportedOnJ2me;
+
+ @BeforeEach
+ protected void setUp() {
+ j2se = JsePlatform.standardGlobals().get("math");
+ j2me = JmePlatform.standardGlobals().get("math");
+ supportedOnJ2me = true;
+ }
+
+ @Test
+ void testMathDPow() {
+ assertEquals(1, j2mepow(2, 0), 0);
+ assertEquals(2, j2mepow(2, 1), 0);
+ assertEquals(8, j2mepow(2, 3), 0);
+ assertEquals(-8, j2mepow(-2, 3), 0);
+ assertEquals(1/8., j2mepow(2, -3), 0);
+ assertEquals(-1/8., j2mepow(-2, -3), 0);
+ assertEquals(16, j2mepow(256, .5), 0);
+ assertEquals(4, j2mepow(256, .25), 0);
+ assertEquals(64, j2mepow(256, .75), 0);
+ assertEquals(1./16, j2mepow(256, -.5), 0);
+ assertEquals(1./4, j2mepow(256, -.25), 0);
+ assertEquals(1./64, j2mepow(256, -.75), 0);
+ assertEquals(Double.NaN, j2mepow(-256, .5), 0);
+ assertEquals(1, j2mepow(.5, 0), 0);
+ assertEquals(.5, j2mepow(.5, 1), 0);
+ assertEquals(.125, j2mepow(.5, 3), 0);
+ assertEquals(2, j2mepow(.5, -1), 0);
+ assertEquals(8, j2mepow(.5, -3), 0);
+ assertEquals(1, j2mepow(0.0625, 0), 0);
+ assertEquals(0.00048828125, j2mepow(0.0625, 2.75), 0);
+ }
+
+ private double j2mepow(double x, double y) {
+ return j2me.get("pow").call(LuaValue.valueOf(x), LuaValue.valueOf(y)).todouble();
+ }
+
+ @Test
+ void testAbs() {
+ tryMathOp("abs", 23.45);
+ tryMathOp("abs", -23.45);
+ }
+
+ @Test
+ void testCos() {
+ tryTrigOps("cos");
+ }
+
+ @Test
+ void testCosh() {
+ supportedOnJ2me = false;
+ tryTrigOps("cosh");
+ }
+
+ @Test
+ void testDeg() {
+ tryTrigOps("deg");
+ }
+
+ @Test
+ void testExp() {
+ tryMathOp("exp", 0);
+ tryMathOp("exp", 0.1);
+ tryMathOp("exp", .9);
+ tryMathOp("exp", 1.);
+ tryMathOp("exp", 9);
+ tryMathOp("exp", -.1);
+ tryMathOp("exp", -.9);
+ tryMathOp("exp", -1.);
+ tryMathOp("exp", -9);
+ }
+
+ @Test
+ void testLog() {
+ supportedOnJ2me = false;
+ tryMathOp("log", 0.1);
+ tryMathOp("log", .9);
+ tryMathOp("log", 1.);
+ tryMathOp("log", 9);
+ tryMathOp("log", -.1);
+ tryMathOp("log", -.9);
+ tryMathOp("log", -1.);
+ tryMathOp("log", -9);
+ }
+
+ @Test
+ void testRad() {
+ tryMathOp("rad", 0);
+ tryMathOp("rad", 0.1);
+ tryMathOp("rad", .9);
+ tryMathOp("rad", 1.);
+ tryMathOp("rad", 9);
+ tryMathOp("rad", 10);
+ tryMathOp("rad", 100);
+ tryMathOp("rad", -.1);
+ tryMathOp("rad", -.9);
+ tryMathOp("rad", -1.);
+ tryMathOp("rad", -9);
+ tryMathOp("rad", -10);
+ tryMathOp("rad", -100);
+ }
+
+ @Test
+ void testSin() {
+ tryTrigOps("sin");
+ }
+
+ @Test
+ void testSinh() {
+ supportedOnJ2me = false;
+ tryTrigOps("sinh");
+ }
+
+ @Test
+ void testSqrt() {
+ tryMathOp("sqrt", 0);
+ tryMathOp("sqrt", 0.1);
+ tryMathOp("sqrt", .9);
+ tryMathOp("sqrt", 1.);
+ tryMathOp("sqrt", 9);
+ tryMathOp("sqrt", 10);
+ tryMathOp("sqrt", 100);
+ }
+
+ @Test
+ void testTan() {
+ tryTrigOps("tan");
+ }
+
+ @Test
+ void testTanh() {
+ supportedOnJ2me = false;
+ tryTrigOps("tanh");
+ }
+
+ @Test
+ void testAtan2() {
+ supportedOnJ2me = false;
+ tryDoubleOps("atan2", false);
+ }
+
+ @Test
+ void testFmod() {
+ tryDoubleOps("fmod", false);
+ }
+
+ @Test
+ void testPow() {
+ tryDoubleOps("pow", true);
+ }
+
+ private void tryDoubleOps(String op, boolean positiveOnly) {
+ // y>0, x>0
+ tryMathOp(op, 0.1, 4.0);
+ tryMathOp(op, .9, 4.0);
+ tryMathOp(op, 1., 4.0);
+ tryMathOp(op, 9, 4.0);
+ tryMathOp(op, 10, 4.0);
+ tryMathOp(op, 100, 4.0);
+
+ // y>0, x<0
+ tryMathOp(op, 0.1, -4.0);
+ tryMathOp(op, .9, -4.0);
+ tryMathOp(op, 1., -4.0);
+ tryMathOp(op, 9, -4.0);
+ tryMathOp(op, 10, -4.0);
+ tryMathOp(op, 100, -4.0);
+
+ if (!positiveOnly) {
+ // y<0, x>0
+ tryMathOp(op, -0.1, 4.0);
+ tryMathOp(op, -.9, 4.0);
+ tryMathOp(op, -1., 4.0);
+ tryMathOp(op, -9, 4.0);
+ tryMathOp(op, -10, 4.0);
+ tryMathOp(op, -100, 4.0);
+
+ // y<0, x<0
+ tryMathOp(op, -0.1, -4.0);
+ tryMathOp(op, -.9, -4.0);
+ tryMathOp(op, -1., -4.0);
+ tryMathOp(op, -9, -4.0);
+ tryMathOp(op, -10, -4.0);
+ tryMathOp(op, -100, -4.0);
+ }
+
+ // degenerate cases
+ tryMathOp(op, 0, 1);
+ tryMathOp(op, 1, 0);
+ tryMathOp(op, -1, 0);
+ tryMathOp(op, 0, -1);
+ tryMathOp(op, 0, 0);
+ }
+
+ private void tryTrigOps(String op) {
+ tryMathOp(op, 0);
+ tryMathOp(op, Math.PI/8);
+ tryMathOp(op, Math.PI*7/8);
+ tryMathOp(op, Math.PI*8/8);
+ tryMathOp(op, Math.PI*9/8);
+ tryMathOp(op, -Math.PI/8);
+ tryMathOp(op, -Math.PI*7/8);
+ tryMathOp(op, -Math.PI*8/8);
+ tryMathOp(op, -Math.PI*9/8);
+ }
+
+ private void tryMathOp(String op, double x) {
+ try {
+ double expected = j2se.get(op).call(LuaValue.valueOf(x)).todouble();
+ double actual = j2me.get(op).call(LuaValue.valueOf(x)).todouble();
+ if (supportedOnJ2me)
+ assertEquals(expected, actual, 1.e-4);
+ else
+ fail("j2me should throw exception for math." + op + " but returned " + actual);
+ } catch (LuaError lee) {
+ if (supportedOnJ2me)
+ throw lee;
+ }
+ }
+
+ private void tryMathOp(String op, double a, double b) {
+ try {
+ double expected = j2se.get(op).call(LuaValue.valueOf(a), LuaValue.valueOf(b)).todouble();
+ double actual = j2me.get(op).call(LuaValue.valueOf(a), LuaValue.valueOf(b)).todouble();
+ if (supportedOnJ2me)
+ assertEquals(expected, actual, 1.e-5);
+ else
+ fail("j2me should throw exception for math." + op + " but returned " + actual);
+ } catch (LuaError lee) {
+ if (supportedOnJ2me)
+ throw lee;
+ }
+ }
+}
diff --git a/luaj-test/src/test/resources/compatibility/baselib.lua b/luaj-test/src/test/resources/compatibility/baselib.lua
new file mode 100644
index 00000000..7bec960a
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/baselib.lua
@@ -0,0 +1,279 @@
+
+-- tostring replacement that assigns ids
+local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'}
+tostring = function(x)
+ if not x or not types[type(x)] then return ts(x) end
+ if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end
+ return id[x]
+end
+
+-- wrap pcall to return one result
+-- error message are tested elsewhere
+local pc = pcall
+local pcall = function(...)
+ local s,e = pc(...)
+ if s then return e end
+ return false, type(e)
+end
+
+-- print
+print()
+print(11)
+print("abc",123,nil,"pqr")
+print( nil and 'T' or 'F' )
+print( false and 'T' or 'F' )
+print( 0 and 'T' or 'F' )
+
+-- assert
+print( 'assert(true)', assert(true) )
+print( 'pcall(assert,true)', pcall(assert,true) )
+print( 'pcall(assert,false)', pcall(assert,false) )
+print( 'pcall(assert,nil)', pcall(assert,nil) )
+print( 'pcall(assert,true,"msg")', pcall(assert,true,"msg") )
+print( 'pcall(assert,false,"msg")', pcall(assert,false,"msg") )
+print( 'pcall(assert,nil,"msg")', pcall(assert,nil,"msg") )
+print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") )
+
+-- collectgarbage (not supported)
+print( 'collectgarbage("count")', type(collectgarbage("count")))
+print( 'collectgarbage("collect")', type(collectgarbage("collect")))
+print( 'collectgarbage("count")', type(collectgarbage("count")))
+
+-- dofile (not supported)
+-- ipairs
+print( 'pcall(ipairs)', pcall(ipairs) )
+print( 'pcall(ipairs,nil)', pcall(ipairs,nil) )
+print( 'pcall(ipairs,"a")', pcall(ipairs,"a") )
+print( 'pcall(ipairs,1)', pcall(ipairs,1) )
+for k,v in ipairs({}) do print('ipairs1',k,v)end
+for k,v in ipairs({'one','two'}) do print('ipairs2',k,v)end
+for k,v in ipairs({aa='aaa',bb='bbb'}) do print('ipairs3',k,v)end
+for k,v in ipairs({aa='aaa',bb='bbb','one','two'}) do print('ipairs4',k,v)end
+for k,v in ipairs({[30]='30',[20]='20'}) do print('ipairs5',k,v)end
+
+-- load
+-- FIXME after empty string is printed which it shouldmt
+-- t = { "print ", "'table ", "loaded'", "", " print'after empty string'" }
+-- i = 0
+-- f = function() i = i + 1; return t[i]; end
+-- c,e = load(f)
+-- if c then print('load: ', pcall(c)) else print('load failed:', e) end
+
+-- loadfile
+-- load
+local lst = "print(3+4); return 8"
+local chunk, err = load( lst )
+print( 'load("'..lst..'")', chunk, err )
+print( 'load("'..lst..'")()', chunk() )
+
+-- pairs
+print( 'pcall(pairs)', pcall(pairs) )
+print( 'pcall(pairs,nil)', pcall(pairs,nil) )
+print( 'pcall(pairs,"a")', pcall(pairs,"a") )
+print( 'pcall(pairs,1)', pcall(pairs,1) )
+for k,v in pairs({}) do print('pairs1',k,v)end
+for k,v in pairs({'one','two'}) do print('pairs2',k,v)end
+for k,v in pairs({aa='aaa'}) do print('pairs3',k,v)end
+for k,v in pairs({aa='aaa','one','two'}) do print('pairs4',k,v)end
+for k,v in pairs({[20]='30',[30]='20'}) do print('pairs5',k,v)end
+
+-- _G
+print( '_G["abc"] (before)', _G["abc"] )
+abc='def'
+print( '_G["abc"] (after)', _G["abc"] )
+
+-- type
+print( 'type(nil)', type(nil) )
+print( 'type("a")', type("a") )
+print( 'type(1)', type(1) )
+print( 'type(1.5)', type(1.5) )
+print( 'type(function() end)', type(function() end) )
+print( 'type({})', type({}) )
+print( 'type(true)', type(true) )
+print( 'type(false)', type(false) )
+print( 'pcall(type,type)', pcall(type,type) )
+print( 'pcall(type)', pcall(type) )
+print( '(function() return pcall(type) end)()', (function() return pcall(type) end)() )
+local function la() return pcall(type) end
+print( 'la()', la() )
+function ga() return pcall(type) end
+print( 'ga()', ga() )
+
+-- getmetatable, setmetatable
+ta = { aa1="aaa1", aa2="aaa2" }
+tb = { bb1="bbb1", bb2="bbb2" }
+print( 'getmetatable(ta)', getmetatable(ta) )
+print( 'getmetatable(tb)', getmetatable(tb) )
+print( 'setmetatable(ta),{cc1="ccc1"}', type( setmetatable(ta,{cc1="ccc1"}) ) )
+print( 'setmetatable(tb),{dd1="ddd1"}', type( setmetatable(tb,{dd1="ddd1"}) ) )
+print( 'getmetatable(ta)["cc1"]', getmetatable(ta)["cc1"] )
+print( 'getmetatable(tb)["dd1"]', getmetatable(tb)["dd1"] )
+print( 'getmetatable(1)', getmetatable(1) )
+print( 'pcall(setmetatable,1)', pcall(setmetatable,1) )
+print( 'pcall(setmetatable,nil)', pcall(setmetatable,nil) )
+print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") )
+print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) )
+
+-- rawget,rawset
+local mt = {aa="aaa", bb="bbb"}
+mt.__index = mt
+mt.__newindex = mt
+local s = {cc="ccc", dd="ddd", }
+local t = {cc="ccc", dd="ddd"}
+setmetatable(t,mt)
+print( 'pcall(rawget)', pcall(rawget))
+print( 'pcall(rawget,"a")', pcall(rawget,"a"))
+print( 'pcall(rawget,s)', pcall(rawget,s))
+print( 'pcall(rawget,t)', pcall(rawget,t))
+
+function printtables()
+ function printtable(name,t)
+ print( ' '..name, t["aa"], t["bb"], t["cc"], t["dd"], t["ee"], t["ff"], t["gg"] )
+ print( ' '..name,
+ rawget(t,"aa"),
+ rawget(t,"bb"),
+ rawget(t,"cc"),
+ rawget(t,"dd"),
+ rawget(t,"ee"),
+ rawget(t,"ff"),
+ rawget(t,"gg") )
+ end
+ printtable( 's', s )
+ printtable( 't', t )
+ printtable( 'mt', mt )
+end
+printtables()
+print( 'pcall(rawset,s,"aa","www")', rawset(s,"aa","www"))
+printtables()
+print( 'pcall(rawset,s,"cc","xxx")', rawset(s,"cc","xxx"))
+printtables()
+print( 'pcall(rawset,t,"aa","yyy")', rawset(t,"aa","yyy"))
+printtables()
+print( 'pcall(rawset,t,"dd","zzz")', rawset(t,"dd","zzz"))
+printtables()
+
+-- rawlen
+print( 'pcall(rawlen, {})', pcall(rawlen, {}))
+print( 'pcall(rawlen, {"a"})', pcall(rawlen, {'a'}))
+print( 'pcall(rawlen, {"a","b"})', pcall(rawlen, {'a','b'}))
+print( 'pcall(rawlen, "")', pcall(rawlen, ""))
+print( 'pcall(rawlen, "a")', pcall(rawlen, 'a'))
+print( 'pcall(rawlen, "ab")', pcall(rawlen, 'ab'))
+print( 'pcall(rawlen, 1)', pcall(rawlen, 1))
+print( 'pcall(rawlen, nil)', pcall(rawlen, nil))
+print( 'pcall(rawlen)', pcall(rawlen))
+
+printtables()
+print( 's["ee"]="ppp"' ); s["ee"]="ppp"
+printtables()
+print( 's["cc"]="qqq"' ); s["cc"]="qqq"
+printtables()
+print( 't["ff"]="rrr"' ); t["ff"]="rrr"
+printtables()
+print( 't["dd"]="sss"' ); t["dd"]="sss"
+printtables()
+print( 'mt["gg"]="ttt"' ); mt["gg"]="ttt"
+printtables()
+
+
+-- select
+print( 'pcall(select)', pcall(select) )
+print( 'select(1,11,22,33,44,55)', select(1,11,22,33,44,55) )
+print( 'select(2,11,22,33,44,55)', select(2,11,22,33,44,55) )
+print( 'select(3,11,22,33,44,55)', select(3,11,22,33,44,55) )
+print( 'select(4,11,22,33,44,55)', select(4,11,22,33,44,55) )
+print( 'pcall(select,5,11,22,33,44,55)', pcall(select,5,11,22,33,44,55) )
+print( 'pcall(select,6,11,22,33,44,55)', pcall(select,6,11,22,33,44,55) )
+print( 'pcall(select,7,11,22,33,44,55)', pcall(select,7,11,22,33,44,55) )
+print( 'pcall(select,0,11,22,33,44,55)', pcall(select,0,11,22,33,44,55) )
+print( 'pcall(select,-1,11,22,33,44,55)', pcall(select,-1,11,22,33,44,55) )
+print( 'pcall(select,-2,11,22,33,44,55)', pcall(select,-2,11,22,33,44,55) )
+print( 'pcall(select,-4,11,22,33,44,55)', pcall(select,-4,11,22,33,44,55) )
+print( 'pcall(select,-5,11,22,33,44,55)', pcall(select,-5,11,22,33,44,55) )
+print( 'pcall(select,-6,11,22,33,44,55)', pcall(select,-6,11,22,33,44,55) )
+print( 'pcall(select,1)', pcall(select,1) )
+print( 'pcall(select,select)', pcall(select,select) )
+print( 'pcall(select,{})', pcall(select,{}) )
+print( 'pcall(select,"2",11,22,33)', pcall(select,"2",11,22,33) )
+print( 'pcall(select,"abc",11,22,33)', pcall(select,"abc",11,22,33) )
+
+
+-- tonumber
+print( 'pcall(tonumber)', pcall(tostring) )
+print( 'pcall(tonumber,nil)', pcall(tonumber,nil) )
+print( 'pcall(tonumber,"abc")', pcall(tonumber,"abc") )
+print( 'pcall(tonumber,"123")', pcall(tonumber,"123") )
+print( 'pcall(tonumber,"123",10)', pcall(tonumber,"123", 10) )
+print( 'pcall(tonumber,"123",8)', pcall(tonumber,"123", 8) )
+print( 'pcall(tonumber,"123",6)', pcall(tonumber,"123", 6) )
+print( 'pcall(tonumber,"10101",4)', pcall(tonumber,"10101", 4) )
+print( 'pcall(tonumber,"10101",3)', pcall(tonumber,"10101", 3) )
+print( 'pcall(tonumber,"10101",2)', pcall(tonumber,"10101", 2) )
+print( 'pcall(tonumber,"1a1",16)', pcall(tonumber,"1a1", 16) )
+print( 'pcall(tonumber,"1a1",32)', pcall(tonumber,"1a1", 32) )
+print( 'pcall(tonumber,"1a1",54)', pcall(tonumber,"1a1", 54) )
+print( 'pcall(tonumber,"1a1",1)', pcall(tonumber,"1a1", 1) )
+print( 'pcall(tonumber,"1a1",0)', pcall(tonumber,"1a1", 0) )
+print( 'pcall(tonumber,"1a1",-1)', pcall(tonumber,"1a1", -1) )
+print( 'pcall(tonumber,"1a1","32")', pcall(tonumber,"1a1", "32") )
+print( 'pcall(tonumber,"123","456")', pcall(tonumber,"123","456") )
+print( 'pcall(tonumber,"1a1",10)', pcall(tonumber,"1a1", 10) )
+print( 'pcall(tonumber,"151",4)', pcall(tonumber,"151", 4) )
+print( 'pcall(tonumber,"151",3)', pcall(tonumber,"151", 3) )
+print( 'pcall(tonumber,"151",2)', pcall(tonumber,"151", 2) )
+print( 'pcall(tonumber,"123",8,8)', pcall(tonumber,"123", 8, 8) )
+print( 'pcall(tonumber,123)', pcall(tonumber,123) )
+print( 'pcall(tonumber,true)', pcall(tonumber,true) )
+print( 'pcall(tonumber,false)', pcall(tonumber,false) )
+print( 'pcall(tonumber,tonumber)', pcall(tonumber,tonumber) )
+print( 'pcall(tonumber,function() end)', pcall(tonumber,function() end) )
+print( 'pcall(tonumber,{"one","two",a="aa",b="bb"})', pcall(tonumber,{"one","two",a="aa",b="bb"}) )
+print( 'pcall(tonumber,"123.456")', pcall(tonumber,"123.456") )
+print( 'pcall(tonumber," 123.456")', pcall(tonumber," 123.456") )
+print( 'pcall(tonumber," 234qwer")', pcall(tonumber," 234qwer") )
+print( 'pcall(tonumber,"0x20")', pcall(tonumber,"0x20") )
+print( 'pcall(tonumber," 0x20")', pcall(tonumber," 0x20") )
+print( 'pcall(tonumber,"0x20 ")', pcall(tonumber,"0x20 ") )
+print( 'pcall(tonumber," 0x20 ")', pcall(tonumber," 0x20 ") )
+print( 'pcall(tonumber,"0X20")', pcall(tonumber,"0X20") )
+print( 'pcall(tonumber," 0X20")', pcall(tonumber," 0X20") )
+print( 'pcall(tonumber,"0X20 ")', pcall(tonumber,"0X20 ") )
+print( 'pcall(tonumber," 0X20 ")', pcall(tonumber," 0X20 ") )
+print( 'pcall(tonumber,"0x20",10)', pcall(tonumber,"0x20",10) )
+print( 'pcall(tonumber,"0x20",16)', pcall(tonumber,"0x20",16) )
+print( 'pcall(tonumber,"0x20",8)', pcall(tonumber,"0x20",8) )
+
+-- tostring
+print( 'pcall(tostring)', pcall(tostring) )
+print( 'pcall(tostring,nil)', pcall(tostring,nil) )
+print( 'pcall(tostring,"abc")', pcall(tostring,"abc") )
+print( 'pcall(tostring,"abc","def")', pcall(tostring,"abc","def") )
+print( 'pcall(tostring,123)', pcall(tostring,123) )
+print( 'pcall(tostring,true)', pcall(tostring,true) )
+print( 'pcall(tostring,false)', pcall(tostring,false) )
+print( 'tostring(tostring)', type(tostring(tostring)) )
+print( 'tostring(function() end)', type(tostring(function() end)) )
+print( 'tostring({"one","two",a="aa",b="bb"})', type(tostring({"one","two",a="aa",b="bb"})) )
+
+-- _VERSION
+print( '_VERSION', type(_VERSION) )
+
+-- xpcall
+local errfunc = function( detail )
+ print( ' in errfunc', type(detail) )
+ return 'response-from-xpcall'
+end
+local badfunc = function() error( 'error-from-badfunc' ) end
+local wrappedbad = function() pcall( badfunc ) end
+print( 'pcall(badfunc)', pcall(badfunc) )
+print( 'pcall(badfunc,errfunc)', pcall(badfunc,errfunc) )
+print( 'pcall(badfunc,badfunc)', pcall(badfunc,badfunc) )
+print( 'pcall(wrappedbad)', pcall(wrappedbad) )
+print( 'pcall(wrappedbad,errfunc)', pcall(wrappedbad,errfunc) )
+print( 'pcall(xpcall(badfunc))', pcall(xpcall,badfunc) )
+print( 'pcall(xpcall(badfunc,errfunc))', pcall(xpcall,badfunc,errfunc) )
+print( 'pcall(xpcall(badfunc,badfunc))', pcall(xpcall,badfunc,badfunc) )
+print( 'pcall(xpcall(wrappedbad))', pcall(xpcall,wrappedbad) )
+-- FIXME Shouldnt print errfunc
+-- print( 'xpcall(wrappedbad,errfunc)', xpcall(wrappedbad,errfunc) )
+
diff --git a/test/lua/coroutinelib.lua b/luaj-test/src/test/resources/compatibility/coroutinelib.lua
similarity index 100%
rename from test/lua/coroutinelib.lua
rename to luaj-test/src/test/resources/compatibility/coroutinelib.lua
diff --git a/luaj-test/src/test/resources/compatibility/create_results.sh b/luaj-test/src/test/resources/compatibility/create_results.sh
new file mode 100755
index 00000000..4ed831ed
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/create_results.sh
@@ -0,0 +1,11 @@
+for l in *.lua
+do
+ echo $l
+ result=${l/\.lua/\.out}
+ lua $l > jse/$result
+ lua $l 'JME' > jme/$result
+ luajit $l > luajit/$result
+done
+
+# TODO Test is currently disabled
+rm luajit/debuglib.out
diff --git a/test/lua/debuglib.lua b/luaj-test/src/test/resources/compatibility/debuglib.lua
similarity index 100%
rename from test/lua/debuglib.lua
rename to luaj-test/src/test/resources/compatibility/debuglib.lua
diff --git a/test/lua/errors.lua b/luaj-test/src/test/resources/compatibility/errors.lua
similarity index 100%
rename from test/lua/errors.lua
rename to luaj-test/src/test/resources/compatibility/errors.lua
diff --git a/test/lua/functions.lua b/luaj-test/src/test/resources/compatibility/functions.lua
similarity index 100%
rename from test/lua/functions.lua
rename to luaj-test/src/test/resources/compatibility/functions.lua
diff --git a/luaj-test/src/test/resources/compatibility/iolib.lua b/luaj-test/src/test/resources/compatibility/iolib.lua
new file mode 100644
index 00000000..5c8a9646
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/iolib.lua
@@ -0,0 +1,160 @@
+local platform = ...
+--print( 'platform', platform )
+
+-- simple io-library tests
+--
+-- C version on Windows will add change \n into \r\n for text files at least
+--
+local tostr,files,nfiles = tostring,{},0
+tostring = function(x)
+ local s = tostr(x)
+ if s:sub(1,4) ~= 'file' then return s end
+ if files[s] then return files[s] end
+ files[s] = 'file.'..nfiles
+ nfiles = nfiles + 1
+ return files[s]
+end
+print( io ~= nil )
+print( io.open ~= nil )
+print( io.stdin ~= nil )
+print( io.stdout ~= nil )
+print( io.stderr ~= nil )
+print( 'write', io.write() )
+print( 'write', io.write("This") )
+print( 'write', io.write(" is a pen.") )
+print( 'flush', io.flush() )
+
+local f = io.open("abc.txt","w")
+print( 'f', type(f) )
+print( io.type(f) )
+print( 'write', f:write("abcdef 12345 \t\t 678910 more\aaaaaaa\bbbbthe rest") )
+print( 'type(f)', io.type(f) )
+print( 'close', f:close() )
+print( 'type(f)', io.type(f) )
+print( 'type("f")', io.type("f") )
+
+local g = io.open("abc.txt","r")
+local t = { g:read(3, 3, "*n", "*n", "*l", "*l", "*a") }
+for i,v in ipairs(t) do
+ print( string.format("%q",tostring(v)), type(v))
+ print( '----- ', i )
+end
+
+local h,s = io.open("abc.txt", "a")
+print( 'h', io.type(h), string.sub(tostring(h),1,6), s )
+print( 'write', h:write('and more and more and more text.') )
+print( 'close', h:close() )
+
+if platform ~= 'JME' then
+ local j = io.open( "abc.txt", "r" )
+ print( 'j', io.type(j) )
+ print( 'seek', j:seek("set", 3) )
+ print( 'read', j:read(4), j:read(3) )
+ print( 'seek', j:seek("set", 2) )
+ print( 'read', j:read(4), j:read(3) )
+ print( 'seek', j:seek("cur", -8 ) )
+ print( 'read', j:read(4), j:read(3) )
+ print( 'seek(cur,0)', j:seek("cur",0) )
+ print( 'seek(cur,20)', j:seek("cur",20) )
+ print( 'seek(end,-5)', j:seek("end", -5) )
+ print( 'read(4)', string.format("%q", tostring(j:read(4))) )
+ print( 'read(4)', string.format("%q", tostring(j:read(4))) )
+ print( 'read(4)', string.format("%q", tostring(j:read(4))) )
+ print( 'close', j:close() )
+end
+
+-- write a few lines, including a non-terminating one
+files = {}
+f = io.open("abc.txt","w")
+print( 'f.type', io.type(f) )
+print( 'f', f )
+print( 'write', f:write("line one\nline two\n\nafter blank line\nunterminated line") )
+print( 'type(f)', io.type(f) )
+print( 'close', f:close() )
+files = {}
+
+-- read using io.lines()
+for l in io.lines("abc.txt") do
+ print( string.format('%q',l) )
+end
+io.input("abc.txt")
+for l in io.lines() do
+ print( string.format('%q',l) )
+end
+io.input(io.open("abc.txt","r"))
+for l in io.lines() do
+ print( string.format('%q',l) )
+end
+io.input("abc.txt")
+io.input(io.input())
+for l in io.lines() do
+ print( string.format('%q',l) )
+end
+
+local count = 0
+io.tmpfile = function()
+ count = count + 1
+ return io.open("tmp"..count..".out","w")
+end
+
+local a = io.tmpfile()
+local b = io.tmpfile()
+print( io.type(a) )
+print( io.type(b) )
+print( "a:write", a:write('aaaaaaa') )
+print( "b:write", b:write('bbbbbbb') )
+print( "a:setvbuf", a:setvbuf("no") )
+print( "a:setvbuf", a:setvbuf("full",1024) )
+print( "a:setvbuf", a:setvbuf("line") )
+print( "a:write", a:write('ccccc') )
+print( "b:write", b:write('ddddd') )
+print( "a:flush", a:flush() )
+print( "b:flush", b:flush() )
+
+--[[
+print( "a:read", a:read(7) )
+print( "b:read", b:read(7) )
+print( "a:seek", a:seek("cur",-4) )
+print( "b:seek", b:seek("cur",-4) )
+print( "a:read", ( a:read(7) ) )
+print( "b:read", ( b:read(7) ) )
+print( "a:seek", a:seek("cur",-8) )
+print( "b:seek", b:seek("cur",-8) )
+print( "a:read", ( a:read(7) ) )
+print( "b:read", ( b:read(7) ) )
+--]]
+
+local pcall = function(...)
+ local s,e = pcall(...)
+ if s then return s end
+ return s,e:match("closed")
+end
+
+b:close()
+print( 'a:close', pcall( a.close, a ) )
+print( 'a:write', pcall( a.write, a, 'eee') )
+print( 'a:flush', pcall( a.flush, a) )
+print( 'a:read', pcall( a.read, a, 5) )
+print( 'a:lines', pcall( a.lines, a) )
+print( 'a:seek', pcall( a.seek, a, "cur", -2) )
+print( 'a:setvbuf', pcall( a.setvbuf, a, "no") )
+print( 'a:close', pcall( a.close, a ) )
+print( 'io.type(a)', pcall( io.type, a ) )
+
+print( 'io.close()', pcall( io.close ) )
+print( 'io.close(io.output())', pcall( io.close, io.output() ) )
+
+io.output('abc.txt')
+print( 'io.close()', pcall( io.close ) )
+print( 'io.write', pcall( io.write, 'eee') )
+print( 'io.flush', pcall( io.flush) )
+-- FIXME closing a closed file leads to a segfault in luajit
+-- print( 'io.close', pcall( io.close ) )
+io.input('abc.txt'):close()
+print( 'io.read', pcall( io.read, 5) )
+print( 'io.lines', pcall( io.lines) )
+
+os.remove('abc.txt')
+for i=1,count do
+ os.remove('tmp'..i..'.out')
+end
diff --git a/luaj-test/src/test/resources/compatibility/jme/baselib.out b/luaj-test/src/test/resources/compatibility/jme/baselib.out
new file mode 100644
index 00000000..66c0118f
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/baselib.out
@@ -0,0 +1,237 @@
+
+11
+abc 123 nil pqr
+F
+F
+T
+assert(true) true
+pcall(assert,true) true
+pcall(assert,false) false string
+pcall(assert,nil) false string
+pcall(assert,true,"msg") true
+pcall(assert,false,"msg") false string
+pcall(assert,nil,"msg") false string
+pcall(assert,false,"msg","msg2") false string
+collectgarbage("count") number
+collectgarbage("collect") number
+collectgarbage("count") number
+pcall(ipairs) false string
+pcall(ipairs,nil) false string
+pcall(ipairs,"a") false string
+pcall(ipairs,1) false string
+ipairs2 1 one
+ipairs2 2 two
+ipairs4 1 one
+ipairs4 2 two
+load("print(3+4); return 8") func.1 nil
+7
+load("print(3+4); return 8")() 8
+pcall(pairs) false string
+pcall(pairs,nil) false string
+pcall(pairs,"a") false string
+pcall(pairs,1) false string
+pairs2 1 one
+pairs2 2 two
+pairs3 aa aaa
+pairs4 1 one
+pairs4 2 two
+pairs4 aa aaa
+pairs5 20 30
+pairs5 30 20
+_G["abc"] (before) nil
+_G["abc"] (after) def
+type(nil) nil
+type("a") string
+type(1) number
+type(1.5) number
+type(function() end) function
+type({}) table
+type(true) boolean
+type(false) boolean
+pcall(type,type) function
+pcall(type) false string
+(function() return pcall(type) end)() false string
+la() false string
+ga() false string
+getmetatable(ta) nil
+getmetatable(tb) nil
+setmetatable(ta),{cc1="ccc1"} table
+setmetatable(tb),{dd1="ddd1"} table
+getmetatable(ta)["cc1"] ccc1
+getmetatable(tb)["dd1"] ddd1
+getmetatable(1) nil
+pcall(setmetatable,1) false string
+pcall(setmetatable,nil) false string
+pcall(setmetatable,"ABC") false string
+pcall(setmetatable,function() end) false string
+pcall(rawget) false string
+pcall(rawget,"a") false string
+pcall(rawget,s) false string
+pcall(rawget,t) false string
+ s nil nil ccc ddd nil nil nil
+ s nil nil ccc ddd nil nil nil
+ t aaa bbb ccc ddd nil nil nil
+ t nil nil ccc ddd nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+pcall(rawset,s,"aa","www") tbl.2
+ s www nil ccc ddd nil nil nil
+ s www nil ccc ddd nil nil nil
+ t aaa bbb ccc ddd nil nil nil
+ t nil nil ccc ddd nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+pcall(rawset,s,"cc","xxx") tbl.2
+ s www nil xxx ddd nil nil nil
+ s www nil xxx ddd nil nil nil
+ t aaa bbb ccc ddd nil nil nil
+ t nil nil ccc ddd nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+pcall(rawset,t,"aa","yyy") tbl.3
+ s www nil xxx ddd nil nil nil
+ s www nil xxx ddd nil nil nil
+ t yyy bbb ccc ddd nil nil nil
+ t yyy nil ccc ddd nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+pcall(rawset,t,"dd","zzz") tbl.3
+ s www nil xxx ddd nil nil nil
+ s www nil xxx ddd nil nil nil
+ t yyy bbb ccc zzz nil nil nil
+ t yyy nil ccc zzz nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+pcall(rawlen, {}) 0
+pcall(rawlen, {"a"}) 1
+pcall(rawlen, {"a","b"}) 2
+pcall(rawlen, "") 0
+pcall(rawlen, "a") 1
+pcall(rawlen, "ab") 2
+pcall(rawlen, 1) false string
+pcall(rawlen, nil) false string
+pcall(rawlen) false string
+ s www nil xxx ddd nil nil nil
+ s www nil xxx ddd nil nil nil
+ t yyy bbb ccc zzz nil nil nil
+ t yyy nil ccc zzz nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+s["ee"]="ppp"
+ s www nil xxx ddd ppp nil nil
+ s www nil xxx ddd ppp nil nil
+ t yyy bbb ccc zzz nil nil nil
+ t yyy nil ccc zzz nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+s["cc"]="qqq"
+ s www nil qqq ddd ppp nil nil
+ s www nil qqq ddd ppp nil nil
+ t yyy bbb ccc zzz nil nil nil
+ t yyy nil ccc zzz nil nil nil
+ mt aaa bbb nil nil nil nil nil
+ mt aaa bbb nil nil nil nil nil
+t["ff"]="rrr"
+ s www nil qqq ddd ppp nil nil
+ s www nil qqq ddd ppp nil nil
+ t yyy bbb ccc zzz nil rrr nil
+ t yyy nil ccc zzz nil nil nil
+ mt aaa bbb nil nil nil rrr nil
+ mt aaa bbb nil nil nil rrr nil
+t["dd"]="sss"
+ s www nil qqq ddd ppp nil nil
+ s www nil qqq ddd ppp nil nil
+ t yyy bbb ccc sss nil rrr nil
+ t yyy nil ccc sss nil nil nil
+ mt aaa bbb nil nil nil rrr nil
+ mt aaa bbb nil nil nil rrr nil
+mt["gg"]="ttt"
+ s www nil qqq ddd ppp nil nil
+ s www nil qqq ddd ppp nil nil
+ t yyy bbb ccc sss nil rrr ttt
+ t yyy nil ccc sss nil nil nil
+ mt aaa bbb nil nil nil rrr ttt
+ mt aaa bbb nil nil nil rrr ttt
+pcall(select) false string
+select(1,11,22,33,44,55) 11 22 33 44 55
+select(2,11,22,33,44,55) 22 33 44 55
+select(3,11,22,33,44,55) 33 44 55
+select(4,11,22,33,44,55) 44 55
+pcall(select,5,11,22,33,44,55) 55
+pcall(select,6,11,22,33,44,55) nil
+pcall(select,7,11,22,33,44,55) nil
+pcall(select,0,11,22,33,44,55) false string
+pcall(select,-1,11,22,33,44,55) 55
+pcall(select,-2,11,22,33,44,55) 44
+pcall(select,-4,11,22,33,44,55) 22
+pcall(select,-5,11,22,33,44,55) 11
+pcall(select,-6,11,22,33,44,55) false string
+pcall(select,1) nil
+pcall(select,select) false string
+pcall(select,{}) false string
+pcall(select,"2",11,22,33) 22
+pcall(select,"abc",11,22,33) false string
+pcall(tonumber) nil
+pcall(tonumber,nil) nil
+pcall(tonumber,"abc") nil
+pcall(tonumber,"123") 123
+pcall(tonumber,"123",10) 123
+pcall(tonumber,"123",8) 83
+pcall(tonumber,"123",6) 51
+pcall(tonumber,"10101",4) 273
+pcall(tonumber,"10101",3) 91
+pcall(tonumber,"10101",2) 21
+pcall(tonumber,"1a1",16) 417
+pcall(tonumber,"1a1",32) 1345
+pcall(tonumber,"1a1",54) false string
+pcall(tonumber,"1a1",1) false string
+pcall(tonumber,"1a1",0) false string
+pcall(tonumber,"1a1",-1) false string
+pcall(tonumber,"1a1","32") 1345
+pcall(tonumber,"123","456") false string
+pcall(tonumber,"1a1",10) nil
+pcall(tonumber,"151",4) nil
+pcall(tonumber,"151",3) nil
+pcall(tonumber,"151",2) nil
+pcall(tonumber,"123",8,8) 83
+pcall(tonumber,123) 123
+pcall(tonumber,true) nil
+pcall(tonumber,false) nil
+pcall(tonumber,tonumber) nil
+pcall(tonumber,function() end) nil
+pcall(tonumber,{"one","two",a="aa",b="bb"}) nil
+pcall(tonumber,"123.456") 123.456
+pcall(tonumber," 123.456") 123.456
+pcall(tonumber," 234qwer") nil
+pcall(tonumber,"0x20") 32
+pcall(tonumber," 0x20") 32
+pcall(tonumber,"0x20 ") 32
+pcall(tonumber," 0x20 ") 32
+pcall(tonumber,"0X20") 32
+pcall(tonumber," 0X20") 32
+pcall(tonumber,"0X20 ") 32
+pcall(tonumber," 0X20 ") 32
+pcall(tonumber,"0x20",10) nil
+pcall(tonumber,"0x20",16) nil
+pcall(tonumber,"0x20",8) nil
+pcall(tostring) nil
+pcall(tostring,nil) nil
+pcall(tostring,"abc") abc
+pcall(tostring,"abc","def") abc
+pcall(tostring,123) 123
+pcall(tostring,true) true
+pcall(tostring,false) false
+tostring(tostring) string
+tostring(function() end) string
+tostring({"one","two",a="aa",b="bb"}) string
+_VERSION string
+pcall(badfunc) false string
+pcall(badfunc,errfunc) false string
+pcall(badfunc,badfunc) false string
+pcall(wrappedbad) nil
+pcall(wrappedbad,errfunc) nil
+pcall(xpcall(badfunc)) false string
+ in errfunc string
+pcall(xpcall(badfunc,errfunc)) false
+pcall(xpcall(badfunc,badfunc)) false
+pcall(xpcall(wrappedbad)) false string
diff --git a/luaj-test/src/test/resources/compatibility/jme/coroutinelib.out b/luaj-test/src/test/resources/compatibility/jme/coroutinelib.out
new file mode 100644
index 00000000..a759fbb1
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/coroutinelib.out
@@ -0,0 +1,99 @@
+running is not nil
+co.status suspended
+co-body 1 10
+foo 2
+main true 4
+co.status suspended
+co-body r
+main true 11 -9
+co.status suspended
+co-body x y
+running is not nil
+co.status.inside running
+co.status.inside running
+co.status.inside2 normal
+main true 10 end
+co.status dead
+main false cannot resume dead coroutine
+co.status dead
+running is not nil
+co.status suspended
+co-body 1 10
+foo 2
+main true 4
+co.status suspended
+co-body nil nil
+main true 11 -9
+co.status suspended
+co-body x y
+main true 10 end
+co.status dead
+main false cannot resume dead coroutine
+co.status dead
+co-body 1 10
+foo 2
+g 4
+co-body r
+g 11 -9
+co-body x y
+g 10 end
+g cannot resume dead coroutine
+(main) sending args 111 222 333
+(echocr) first args 111 222 333
+(main) resume returns true 111 222 333
+(main) sending args
+(echoch) yield returns
+(main) resume returns true
+(main) sending args 111
+(echoch) yield returns 111
+(main) resume returns true 111
+(main) sending args 111 222 333
+(echoch) yield returns 111 222 333
+(main) resume returns true 111 222 333
+main-b suspended
+main-c suspended
+ b-resumed main-arg-for-b true
+ b-b running
+ b-c suspended
+ b-resume-b false cannot resume non-suspended coroutine
+ c-resumed b-arg-for-c true
+ c-b normal
+ c-c running
+ c-resume-b false cannot resume non-suspended coroutine
+ c-resume-c false cannot resume non-suspended coroutine
+ b-resume-c true c-rslt
+main-resume-b true b-rslt
+ c-resumed main-arg-for-c true
+ c-b suspended
+ c-c running
+ b-resumed b-arg-for-b true
+ b-b running
+ b-c normal
+ b-resume-b false cannot resume non-suspended coroutine
+ b-resume-c false cannot resume non-suspended coroutine
+ c-resume-b true b-rslt
+ c-resume-c false cannot resume non-suspended coroutine
+main-resume-c true c-rslt
+main-b suspended
+main-c suspended
+ b-resumed main-arg-for-b true
+ b-b running
+ b-c suspended
+ b-resume-b false cannot resume non-suspended coroutine
+ c-resumed b-arg-for-c true
+ c-b normal
+ c-c running
+ c-resume-b false cannot resume non-suspended coroutine
+ c-resume-c false cannot resume non-suspended coroutine
+ b-resume-c true c-rslt
+main-resume-b true b-rslt
+main-resume-c true
+main-b suspended
+main-c dead
+ b-resumed main-arg-for-b true
+ b-b running
+ b-c dead
+ b-resume-b false cannot resume non-suspended coroutine
+ b-resume-c false cannot resume dead coroutine
+main-resume-b true b-rslt
+main-resume-c false cannot resume dead coroutine
diff --git a/luaj-test/src/test/resources/compatibility/jme/debuglib.out b/luaj-test/src/test/resources/compatibility/jme/debuglib.out
new file mode 100644
index 00000000..663fe0be
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/debuglib.out
@@ -0,0 +1,329 @@
+has debug true
+----- debug.getlocal, debug.setlocal
+true h-3-0 -> 3-0 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={3,0,#} f locals=,3,0,#,4,5,6
+true h-3-1 -> 3-1 get=a,3 set=a,nil get=a,# g locals=7,8,9 tbl={3,1,#} f locals=,#,1,#,4,5,6
+true h-3-2 -> 3-2 get=b,2 set=b,nil get=b,# g locals=7,8,9 tbl={3,2,#} f locals=,3,#,#,4,5,6
+true h-3-3 -> 3-3 get=c,# set=c,nil get=c,# g locals=7,8,9 tbl={3,3,#} f locals=,3,3,#,4,5,6
+true h-3-4 -> 3-4 get=d,4 set=d,nil get=d,# g locals=7,8,9 tbl={3,4,#} f locals=,3,4,#,#,5,6
+true h-3-5 -> 3-5 get=e,5 set=e,nil get=e,# g locals=7,8,9 tbl={3,5,#} f locals=,3,5,#,4,#,6
+true h-3-6 -> 3-6 get=f,6 set=f,nil get=f,# g locals=7,8,9 tbl={3,6,#} f locals=,3,6,#,4,5,#
+true h-3-7 -> 3-7 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={3,7,#} f locals=,3,7,#,4,5,6
+true h-2-0 -> 2-0 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={2,0,#} f locals=,2,0,#,4,5,6
+true h-2-1 -> 2-1 get=p,7 set=p,nil get=p,# g locals=#,8,9 tbl={2,1,#} f locals=,2,1,#,4,5,6
+true h-2-2 -> 2-2 get=q,8 set=q,nil get=q,# g locals=7,#,9 tbl={2,2,#} f locals=,2,2,#,4,5,6
+true h-2-3 -> 2-3 get=r,9 set=r,nil get=r,# g locals=7,8,# tbl={2,3,#} f locals=,2,3,#,4,5,6
+true h-2-4 -> 2-4 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={2,4,#} f locals=,2,4,#,4,5,6
+true h-2-5 -> 2-5 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={2,5,#} f locals=,2,5,#,4,5,6
+true h-2-6 -> 2-6 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={2,6,#} f locals=,2,6,#,4,5,6
+true h-2-7 -> 2-7 get=nil,nil set=nil,nil get=nil,nil g locals=7,8,9 tbl={2,7,#} f locals=,2,7,#,4,5,6
+true h-1-3 -> 1-3 get=n,# set=n,nil get=n,# g locals=7,8,9 tbl={1,3,#} f locals=,1,3,#,4,5,6
+true h-1-4 -> 1-4 get=#,nil set=x1,nil get=x1,# g locals=7,8,9 tbl={1,4,#} f locals=,1,4,#,4,5,6
+true h-1-5 -> 1-5 get=nil,# set=y1,nil get=y1,# g locals=7,8,9 tbl={1,5,#} f locals=,1,5,#,4,5,6
+true h-1-6 -> 1-6 get=nil,nil set=nil,nil get=x2,nil g locals=7,8,9 tbl={1,6,#} f locals=,1,6,#,4,5,6
+true h-1-7 -> 1-7 get=nil,nil set=nil,nil get=y2,nil g locals=7,8,9 tbl={1,7,#} f locals=,1,7,#,4,5,6
+----- debug.getupvalue, debug.setupvalue
+h 101 102 103 104 105 106 107 108 109
+f -> 1-0 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,101,102,103,104,105,106,107,108,109
+f -> 1-1 get=true,m,101 set=true,m,nil get=true,m,777001 tbl=true,777001,102,103,104,105,106,107,108,109
+f -> 1-2 get=true,n,102 set=true,n,nil get=true,n,777002 tbl=true,777001,777002,103,104,105,106,107,108,109
+f -> 1-3 get=true,o,103 set=true,o,nil get=true,o,777003 tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-4 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-5 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-6 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-7 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-8 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-9 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+f -> 1-10 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+g -> 2-0 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,777001,777002,777003,104,105,106,107,108,109
+g -> 2-1 get=true,m,777001 set=true,m,nil get=true,m,888001 tbl=true,888001,777002,777003,104,105,106,107,108,109
+g -> 2-2 get=true,n,777002 set=true,n,nil get=true,n,888002 tbl=true,888001,888002,777003,104,105,106,107,108,109
+g -> 2-3 get=true,o,777003 set=true,o,nil get=true,o,888003 tbl=true,888001,888002,888003,104,105,106,107,108,109
+g -> 2-4 get=true,p,104 set=true,p,nil get=true,p,888004 tbl=true,888001,888002,888003,888004,105,106,107,108,109
+g -> 2-5 get=true,q,105 set=true,q,nil get=true,q,888005 tbl=true,888001,888002,888003,888004,888005,106,107,108,109
+g -> 2-6 get=true,r,106 set=true,r,nil get=true,r,888006 tbl=true,888001,888002,888003,888004,888005,888006,107,108,109
+g -> 2-7 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,888001,888002,888003,888004,888005,888006,107,108,109
+g -> 2-8 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,888001,888002,888003,888004,888005,888006,107,108,109
+g -> 2-9 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,888001,888002,888003,888004,888005,888006,107,108,109
+g -> 2-10 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,888001,888002,888003,888004,888005,888006,107,108,109
+h -> 3-0 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,888001,888002,888003,888004,888005,888006,107,108,109
+h -> 3-1 get=true,m,888001 set=true,m,nil get=true,m,999001 tbl=true,999001,888002,888003,888004,888005,888006,107,108,109
+h -> 3-2 get=true,n,888002 set=true,n,nil get=true,n,999002 tbl=true,999001,999002,888003,888004,888005,888006,107,108,109
+h -> 3-3 get=true,o,888003 set=true,o,nil get=true,o,999003 tbl=true,999001,999002,999003,888004,888005,888006,107,108,109
+h -> 3-4 get=true,p,888004 set=true,p,nil get=true,p,999004 tbl=true,999001,999002,999003,999004,888005,888006,107,108,109
+h -> 3-5 get=true,q,888005 set=true,q,nil get=true,q,999005 tbl=true,999001,999002,999003,999004,999005,888006,107,108,109
+h -> 3-6 get=true,r,888006 set=true,r,nil get=true,r,999006 tbl=true,999001,999002,999003,999004,999005,999006,107,108,109
+h -> 3-7 get=true,v,107 set=true,v,nil get=true,v,999007 tbl=true,999001,999002,999003,999004,999005,999006,999007,108,109
+h -> 3-8 get=true,w,108 set=true,w,nil get=true,w,999008 tbl=true,999001,999002,999003,999004,999005,999006,999007,999008,109
+h -> 3-9 get=true,x,109 set=true,x,nil get=true,x,999009 tbl=true,999001,999002,999003,999004,999005,999006,999007,999008,999009
+h -> 3-10 get=true,nil,nil set=true,nil,nil get=true,nil,nil tbl=true,999001,999002,999003,999004,999005,999006,999007,999008,999009
+----- debug.setmetatable, debug.getmetatable
+a.a=bbb a.b=nil b.a=nil b.b=nil
+a.a=bbb a.b=ccc b.a=nil b.b=nil
+boolean table nil table
+boolean nil nil nil
+boolean table nil nil
+a.a=bbb a.b=nil b.a=nil b.b=nil
+boolean nil nil nil
+get=true,true,nil
+set=true,true,nil
+get=true,true,nil
+get=true,true,nil
+set=true,true,nil
+get=true,true,nil
+true nil
+true 1
+true 1
+----- debug.getinfo
+6
+---
+debug.getinfo(1)
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ currentline: 144
+ linedefined: 141
+ lastlinedefined: 155
+ nups: 5
+ func: function
+debug.getinfo(1,"")
+debug.getinfo(1,"l")
+ currentline: 146
+debug.getinfo(1,"fL")
+ func: function
+ activelines: {}
+debug.getinfo(2)
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ currentline: 157
+ linedefined: 135
+ lastlinedefined: 159
+ nups: 6
+ func: function
+debug.getinfo(2,"l")
+ currentline: 157
+debug.getinfo(2,"fL")
+ func: function
+ activelines: {}
+debug.getinfo(10,"")
+true
+debug.getinfo(-10,"")
+true
+---
+5
+e,f,g true function function
+debug.getinfo(f)
+true
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ currentline: -1
+ linedefined: 137
+ lastlinedefined: 140
+ nups: 1
+ func: function
+debug.getinfo(f,"nSlufL")
+true
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ currentline: -1
+ linedefined: 137
+ lastlinedefined: 140
+ nups: 1
+ func: function
+ activelines: {}
+debug.getinfo(f,"n")
+true
+debug.getinfo(f,"S")
+true
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ linedefined: 137
+ lastlinedefined: 140
+debug.getinfo(f,"l")
+true
+ currentline: -1
+debug.getinfo(f,"u")
+true
+ nups: 1
+debug.getinfo(f,"f")
+true
+ func: function
+debug.getinfo(f,"L")
+true
+ activelines: {}
+debug.getinfo(g)
+true
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ currentline: -1
+ linedefined: 141
+ lastlinedefined: 155
+ nups: 5
+ func: function
+debug.getinfo(test)
+true
+ source: @debuglib.lua
+ short_src: debuglib.lua
+ what: Lua
+ currentline: -1
+ linedefined: 135
+ lastlinedefined: 159
+ nups: 6
+ func: function
+----- debug.sethook, debug.gethook
+ ... in hook call nil
+ info[2]=debuglib.lua,177
+ ... in hook call nil
+ info[2]=debuglib.lua,176
+ ... in hook call nil
+ info[2]=[C],-1
+ ... in hook call nil
+ info[2]=[C],-1
+hook = c -> result=true,nil,nil,nil,false,false,nil
+ ... in hook return nil
+ info[2]=[C],-1
+ ... in hook return nil
+ info[2]=[C],-1
+hook = r -> result=true,nil,nil,nil,false,false,nil
+ ... in hook line 192
+ info[2]=debuglib.lua,192
+ ... in hook line 177
+ info[2]=debuglib.lua,177
+ ... in hook line 178
+ info[2]=debuglib.lua,178
+ ... in hook line 176
+ info[2]=debuglib.lua,176
+ ... in hook line 195
+ info[2]=debuglib.lua,195
+hook = l -> result=true,nil,nil,nil,false,false,nil
+ ... in hook return nil
+ info[2]=[C],-1
+ ... in hook line 192
+ info[2]=debuglib.lua,192
+ ... in hook call nil
+ info[2]=debuglib.lua,177
+ ... in hook line 177
+ info[2]=debuglib.lua,177
+ ... in hook line 178
+ info[2]=debuglib.lua,178
+ ... in hook call nil
+ info[2]=debuglib.lua,176
+ ... in hook line 176
+ info[2]=debuglib.lua,176
+ ... in hook call nil
+ info[2]=[C],-1
+ ... in hook return nil
+ info[2]=[C],-1
+ ... in hook line 195
+ info[2]=debuglib.lua,195
+ ... in hook call nil
+ info[2]=[C],-1
+hook = crl -> result=true,nil,nil,nil,false,false,nil
+----- debug.traceback
+hi
+stack traceback:
+ debuglib.lua:216: in function
+ [C]: in function 'pcall'
+ debuglib.lua:219: in function 'b'
+ debuglib.lua:222: in function 'c'
+ debuglib.lua:225: in function '__index'
+ debuglib.lua:227: in function 'e'
+ debuglib.lua:231: in function 'g'
+ debuglib.lua:235: in function 'i'
+ debuglib.lua:238: in function
+ [C]: in function 'pcall'
+ debuglib.lua:240: in main chunk
+ [C]: in ?
+----- debug.upvalueid
+debug.getupvalue(a1,1) x 100
+debug.getupvalue(a1,2) y 200
+debug.getupvalue(a2,1) x 100
+debug.getupvalue(a2,2) y 200
+debug.upvalueid(a1,1) == debug.upvalueid(a1,1) true
+debug.upvalueid(a1,1) == debug.upvalueid(a2,1) true
+debug.upvalueid(a1,1) == debug.upvalueid(a1,2) false
+----- debug.upvaluejoin
+a1 101 201 301 401
+a2 102 202 501 601
+debug.upvaluejoin(a1,1,a2,2)
+debug.upvaluejoin(a1,3,a2,4)
+a1 203 203 602 402
+a2 103 204 502 603
+a1 205 205 604 403
+a2 104 206 503 605
+debug.getupvalue(a1,1) x 206
+debug.getupvalue(a2,1) x 104
+debug.upvalueid(a1,1) == debug.upvalueid(a1,1) true
+debug.upvalueid(a1,1) == debug.upvalueid(a2,1) false
+debug.upvalueid(a2,1) == debug.upvalueid(a1,1) false
+debug.upvalueid(a2,1) == debug.upvalueid(a2,1) true
+debug.upvalueid(a1,1) == debug.upvalueid(a1,2) true
+debug.upvalueid(a1,1) == debug.upvalueid(a2,2) true
+debug.upvalueid(a2,1) == debug.upvalueid(a1,2) false
+debug.upvalueid(a2,1) == debug.upvalueid(a2,2) false
+debug.upvalueid(a1,1) == debug.upvalueid(a1,3) false
+debug.upvalueid(a1,1) == debug.upvalueid(a2,3) false
+debug.upvalueid(a2,1) == debug.upvalueid(a1,3) false
+debug.upvalueid(a2,1) == debug.upvalueid(a2,3) false
+debug.upvalueid(a1,1) == debug.upvalueid(a1,4) false
+debug.upvalueid(a1,1) == debug.upvalueid(a2,4) false
+debug.upvalueid(a2,1) == debug.upvalueid(a1,4) false
+debug.upvalueid(a2,1) == debug.upvalueid(a2,4) false
+debug.getupvalue(a1,2) y 206
+debug.getupvalue(a2,2) y 206
+debug.upvalueid(a1,2) == debug.upvalueid(a1,1) true
+debug.upvalueid(a1,2) == debug.upvalueid(a2,1) false
+debug.upvalueid(a2,2) == debug.upvalueid(a1,1) true
+debug.upvalueid(a2,2) == debug.upvalueid(a2,1) false
+debug.upvalueid(a1,2) == debug.upvalueid(a1,2) true
+debug.upvalueid(a1,2) == debug.upvalueid(a2,2) true
+debug.upvalueid(a2,2) == debug.upvalueid(a1,2) true
+debug.upvalueid(a2,2) == debug.upvalueid(a2,2) true
+debug.upvalueid(a1,2) == debug.upvalueid(a1,3) false
+debug.upvalueid(a1,2) == debug.upvalueid(a2,3) false
+debug.upvalueid(a2,2) == debug.upvalueid(a1,3) false
+debug.upvalueid(a2,2) == debug.upvalueid(a2,3) false
+debug.upvalueid(a1,2) == debug.upvalueid(a1,4) false
+debug.upvalueid(a1,2) == debug.upvalueid(a2,4) false
+debug.upvalueid(a2,2) == debug.upvalueid(a1,4) false
+debug.upvalueid(a2,2) == debug.upvalueid(a2,4) false
+debug.getupvalue(a1,3) z 605
+debug.getupvalue(a2,3) z 503
+debug.upvalueid(a1,3) == debug.upvalueid(a1,1) false
+debug.upvalueid(a1,3) == debug.upvalueid(a2,1) false
+debug.upvalueid(a2,3) == debug.upvalueid(a1,1) false
+debug.upvalueid(a2,3) == debug.upvalueid(a2,1) false
+debug.upvalueid(a1,3) == debug.upvalueid(a1,2) false
+debug.upvalueid(a1,3) == debug.upvalueid(a2,2) false
+debug.upvalueid(a2,3) == debug.upvalueid(a1,2) false
+debug.upvalueid(a2,3) == debug.upvalueid(a2,2) false
+debug.upvalueid(a1,3) == debug.upvalueid(a1,3) true
+debug.upvalueid(a1,3) == debug.upvalueid(a2,3) false
+debug.upvalueid(a2,3) == debug.upvalueid(a1,3) false
+debug.upvalueid(a2,3) == debug.upvalueid(a2,3) true
+debug.upvalueid(a1,3) == debug.upvalueid(a1,4) false
+debug.upvalueid(a1,3) == debug.upvalueid(a2,4) true
+debug.upvalueid(a2,3) == debug.upvalueid(a1,4) false
+debug.upvalueid(a2,3) == debug.upvalueid(a2,4) false
+debug.getupvalue(a1,4) w 403
+debug.getupvalue(a2,4) w 605
+debug.upvalueid(a1,4) == debug.upvalueid(a1,1) false
+debug.upvalueid(a1,4) == debug.upvalueid(a2,1) false
+debug.upvalueid(a2,4) == debug.upvalueid(a1,1) false
+debug.upvalueid(a2,4) == debug.upvalueid(a2,1) false
+debug.upvalueid(a1,4) == debug.upvalueid(a1,2) false
+debug.upvalueid(a1,4) == debug.upvalueid(a2,2) false
+debug.upvalueid(a2,4) == debug.upvalueid(a1,2) false
+debug.upvalueid(a2,4) == debug.upvalueid(a2,2) false
+debug.upvalueid(a1,4) == debug.upvalueid(a1,3) false
+debug.upvalueid(a1,4) == debug.upvalueid(a2,3) false
+debug.upvalueid(a2,4) == debug.upvalueid(a1,3) true
+debug.upvalueid(a2,4) == debug.upvalueid(a2,3) false
+debug.upvalueid(a1,4) == debug.upvalueid(a1,4) true
+debug.upvalueid(a1,4) == debug.upvalueid(a2,4) false
+debug.upvalueid(a2,4) == debug.upvalueid(a1,4) false
+debug.upvalueid(a2,4) == debug.upvalueid(a2,4) true
diff --git a/luaj-test/src/test/resources/compatibility/jme/errors.out b/luaj-test/src/test/resources/compatibility/jme/errors.out
new file mode 100644
index 00000000..cc674319
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/errors.out
@@ -0,0 +1,97 @@
+a(error) false nil
+a(error,"msg") false string
+a(error,"msg",0) false string
+a(error,"msg",1) false string
+a(error,"msg",2) false string
+a(error,"msg",3) false string
+a(error,"msg",4) false string
+a(error,"msg",5) false string
+a(error,"msg",6) false string
+a(nil()) false string
+a(t()) false string
+a(s()) false string
+a(true()) false string
+a(nil+1) false string
+a(a+1) false string
+a(s+1) false string
+a(true+1) false string
+a(nil.x) false string
+a(a.x) false string
+a(s.x) true nil
+a(true.x) false string
+a(nil.x=5) false string
+a(a.x=5) false string
+a(s.x=5) false string
+a(true.x=5) false string
+a(#nil) false string
+a(#t) true 0
+a(#s) true 11
+a(#a) false string
+a(#true) false string
+a(nil>1) false string
+a(a>1) false string
+a(s>1) false string
+a(true>1) false string
+a(-nil) false string
+a(-a) false string
+a(-s) false string
+a(-true) false string
+-------- string concatenation
+"a".."b" true
+"a"..nil false
+nil.."b" false
+"a"..{} false
+{}.."b" false
+"a"..2 true
+2.."b" true
+"a"..print false
+print.."b" false
+"a"..true false
+true.."b" false
+nil..true false
+"a"..3.5 true
+3.5.."b" true
+-------- table concatenation
+"a".."b" true
+"a"..nil false
+nil.."b" false
+"a"..{} false
+{}.."b" false
+"a"..2 true
+2.."b" true
+"a"..print false
+print.."b" false
+"a"..true false
+true.."b" false
+nil..true false
+"a"..3.5 true
+3.5.."b" true
+-------- pairs tests
+a(pairs(nil)) false string
+a(pairs(a)) false string
+a(pairs(s)) false string
+a(pairs(t)) true func.1
+a(pairs(true)) false string
+-------- setmetatable tests
+a(setmetatable(nil)) false string
+a(setmetatable(a)) false string
+a(setmetatable(s)) false string
+a(setmetatable(true)) false string
+a(setmetatable(t)) true tbl.2
+a(getmetatable(t)) true tbl.3
+a(setmetatable(t*)) true tbl.2
+a(getmetatable(t)) true tbl.4
+a(setmetatable(t)) false string
+a(getmetatable(t)) true tbl.4
+a(setmetatable(t)) true tbl.5
+a(getmetatable(t)) true tbl.6
+a(setmetatable(t*)) true tbl.5
+a(getmetatable(t)) true some string
+a(setmetatable(t)) false string
+a(getmetatable(t)) true some string
+a(setmetatable(t,nil)) false string
+a(setmetatable(t)) false string
+a(setmetatable({},"abc")) false string
+error("msg","arg") false string
+loadfile("bogus.txt") true nil
+dofile("bogus.txt") false string
diff --git a/luaj-test/src/test/resources/compatibility/jme/functions.out b/luaj-test/src/test/resources/compatibility/jme/functions.out
new file mode 100644
index 00000000..cdffa68a
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/functions.out
@@ -0,0 +1,68 @@
+f0:
+f0:
+f0:
+f0:
+f0:
+f1: nil
+f1: a1/1
+f1: a1/2
+f1: a1/3
+f1: a1/4
+f2: nil nil
+f2: a1/1 nil
+f2: a1/2 a2/2
+f2: a1/3 a2/3
+f2: a1/4 a2/4
+f3: nil nil nil
+f3: a1/1 nil nil
+f3: a1/2 a2/2 nil
+f3: a1/3 a2/3 a3/3
+f3: a1/4 a2/4 a3/4
+f4: nil nil nil nil
+f4: a1/1 nil nil nil
+f4: a1/2 a2/2 nil nil
+f4: a1/3 a2/3 a3/3 nil
+f4: a1/4 a2/4 a3/4 a4/4
+z0: nil
+z2: c2.3/4
+z4: c4.1/4
+g0: nil nil nil nil (eol)
+g2: b2.3/4 b2.4/4 nil nil (eol)
+g4: b4.1/4 b4.2/4 b4.3/4 b4.4/4 (eol)
+11 12 13
+23 22 21
+32 45 58
+a nil
+...
+...,a nil nil
+a,... nil
+a q
+...
+...,a nil q
+a,... q
+a q
+... r
+...,a r q
+a,... q r
+a q
+... r s
+...,a r q
+a,... q r s
+third abc nil | nil nil nil
+third def nil | nil nil nil
+third def nil | nil nil nil
+third abc p | p nil nil
+third def nil | p nil nil
+third def nil | p nil nil
+third abc p | p q nil
+third def q | p q nil
+third def q | p q nil
+third abc p | p q r
+third def q | p q r
+third def q | p q r
+third abc p | p q r
+third def q | p q r
+third def q | p q r
+third abc nil | nil nil nil
+third def nil | nil nil nil
+third def nil | nil nil nil
diff --git a/luaj-test/src/test/resources/compatibility/jme/iolib.out b/luaj-test/src/test/resources/compatibility/jme/iolib.out
new file mode 100644
index 00000000..881d616d
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/iolib.out
@@ -0,0 +1,81 @@
+true
+true
+true
+true
+true
+write file.0
+Thiswrite file.0
+ is a pen.write file.0
+flush true
+f userdata
+file.1
+write file.2
+type(f) file.1
+close true
+type(f) closed file
+type("f") nil
+"abc" string
+----- 1
+"def" string
+----- 2
+"12345" number
+----- 3
+"678910" number
+----- 4
+" more\7aaaaaa\8bbbthe rest" string
+----- 5
+h file.1 file.4 nil
+write file.3
+close true
+f.type file.5
+f file.6
+write file.6
+type(f) file.5
+close true
+"line one"
+"line two"
+""
+"after blank line"
+"unterminated line"
+"line one"
+"line two"
+""
+"after blank line"
+"unterminated line"
+"line one"
+"line two"
+""
+"after blank line"
+"unterminated line"
+"line one"
+"line two"
+""
+"after blank line"
+"unterminated line"
+file.7
+file.7
+a:write file.8
+b:write file.9
+a:setvbuf true
+a:setvbuf true
+a:setvbuf true
+a:write file.8
+b:write file.9
+a:flush true
+b:flush true
+a:close true
+a:write false closed
+a:flush false closed
+a:read false closed
+a:lines false closed
+a:seek false closed
+a:setvbuf false closed
+a:close false closed
+io.type(a) true
+io.close() true
+io.close(io.output()) true
+io.close() true
+io.write false closed
+io.flush false closed
+io.read false closed
+io.lines false closed
diff --git a/luaj-test/src/test/resources/compatibility/jme/manyupvals.out b/luaj-test/src/test/resources/compatibility/jme/manyupvals.out
new file mode 100644
index 00000000..2b33d840
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/manyupvals.out
@@ -0,0 +1,1981 @@
+ local f1
+ f1 = function() return 1 end
+ local f2
+ f2 = function() return 1 end
+ local f3
+ do
+ local result
+ function f3()
+ if not result then
+ result = f1() + f2()
+ end
+ return result
+ end
+ end
+ local f4
+ do
+ local result
+ function f4()
+ if not result then
+ result = f2() + f3()
+ end
+ return result
+ end
+ end
+ local f5
+ do
+ local result
+ function f5()
+ if not result then
+ result = f3() + f4()
+ end
+ return result
+ end
+ end
+ local f6
+ do
+ local result
+ function f6()
+ if not result then
+ result = f4() + f5()
+ end
+ return result
+ end
+ end
+ local f7
+ do
+ local result
+ function f7()
+ if not result then
+ result = f5() + f6()
+ end
+ return result
+ end
+ end
+ local f8
+ do
+ local result
+ function f8()
+ if not result then
+ result = f6() + f7()
+ end
+ return result
+ end
+ end
+ local f9
+ do
+ local result
+ function f9()
+ if not result then
+ result = f7() + f8()
+ end
+ return result
+ end
+ end
+ local f10
+ do
+ local result
+ function f10()
+ if not result then
+ result = f8() + f9()
+ end
+ return result
+ end
+ end
+ local f11
+ do
+ local result
+ function f11()
+ if not result then
+ result = f9() + f10()
+ end
+ return result
+ end
+ end
+ local f12
+ do
+ local result
+ function f12()
+ if not result then
+ result = f10() + f11()
+ end
+ return result
+ end
+ end
+ local f13
+ do
+ local result
+ function f13()
+ if not result then
+ result = f11() + f12()
+ end
+ return result
+ end
+ end
+ local f14
+ do
+ local result
+ function f14()
+ if not result then
+ result = f12() + f13()
+ end
+ return result
+ end
+ end
+ local f15
+ do
+ local result
+ function f15()
+ if not result then
+ result = f13() + f14()
+ end
+ return result
+ end
+ end
+ local f16
+ do
+ local result
+ function f16()
+ if not result then
+ result = f14() + f15()
+ end
+ return result
+ end
+ end
+ local f17
+ do
+ local result
+ function f17()
+ if not result then
+ result = f15() + f16()
+ end
+ return result
+ end
+ end
+ local f18
+ do
+ local result
+ function f18()
+ if not result then
+ result = f16() + f17()
+ end
+ return result
+ end
+ end
+ local f19
+ do
+ local result
+ function f19()
+ if not result then
+ result = f17() + f18()
+ end
+ return result
+ end
+ end
+ local f20
+ do
+ local result
+ function f20()
+ if not result then
+ result = f18() + f19()
+ end
+ return result
+ end
+ end
+ local f21
+ do
+ local result
+ function f21()
+ if not result then
+ result = f19() + f20()
+ end
+ return result
+ end
+ end
+ local f22
+ do
+ local result
+ function f22()
+ if not result then
+ result = f20() + f21()
+ end
+ return result
+ end
+ end
+ local f23
+ do
+ local result
+ function f23()
+ if not result then
+ result = f21() + f22()
+ end
+ return result
+ end
+ end
+ local f24
+ do
+ local result
+ function f24()
+ if not result then
+ result = f22() + f23()
+ end
+ return result
+ end
+ end
+ local f25
+ do
+ local result
+ function f25()
+ if not result then
+ result = f23() + f24()
+ end
+ return result
+ end
+ end
+ local f26
+ do
+ local result
+ function f26()
+ if not result then
+ result = f24() + f25()
+ end
+ return result
+ end
+ end
+ local f27
+ do
+ local result
+ function f27()
+ if not result then
+ result = f25() + f26()
+ end
+ return result
+ end
+ end
+ local f28
+ do
+ local result
+ function f28()
+ if not result then
+ result = f26() + f27()
+ end
+ return result
+ end
+ end
+ local f29
+ do
+ local result
+ function f29()
+ if not result then
+ result = f27() + f28()
+ end
+ return result
+ end
+ end
+ local f30
+ do
+ local result
+ function f30()
+ if not result then
+ result = f28() + f29()
+ end
+ return result
+ end
+ end
+ local f31
+ do
+ local result
+ function f31()
+ if not result then
+ result = f29() + f30()
+ end
+ return result
+ end
+ end
+ local f32
+ do
+ local result
+ function f32()
+ if not result then
+ result = f30() + f31()
+ end
+ return result
+ end
+ end
+ local f33
+ do
+ local result
+ function f33()
+ if not result then
+ result = f31() + f32()
+ end
+ return result
+ end
+ end
+ local f34
+ do
+ local result
+ function f34()
+ if not result then
+ result = f32() + f33()
+ end
+ return result
+ end
+ end
+ local f35
+ do
+ local result
+ function f35()
+ if not result then
+ result = f33() + f34()
+ end
+ return result
+ end
+ end
+ local f36
+ do
+ local result
+ function f36()
+ if not result then
+ result = f34() + f35()
+ end
+ return result
+ end
+ end
+ local f37
+ do
+ local result
+ function f37()
+ if not result then
+ result = f35() + f36()
+ end
+ return result
+ end
+ end
+ local f38
+ do
+ local result
+ function f38()
+ if not result then
+ result = f36() + f37()
+ end
+ return result
+ end
+ end
+ local f39
+ do
+ local result
+ function f39()
+ if not result then
+ result = f37() + f38()
+ end
+ return result
+ end
+ end
+ local f40
+ do
+ local result
+ function f40()
+ if not result then
+ result = f38() + f39()
+ end
+ return result
+ end
+ end
+ local f41
+ do
+ local result
+ function f41()
+ if not result then
+ result = f39() + f40()
+ end
+ return result
+ end
+ end
+ local f42
+ do
+ local result
+ function f42()
+ if not result then
+ result = f40() + f41()
+ end
+ return result
+ end
+ end
+ local f43
+ do
+ local result
+ function f43()
+ if not result then
+ result = f41() + f42()
+ end
+ return result
+ end
+ end
+ local f44
+ do
+ local result
+ function f44()
+ if not result then
+ result = f42() + f43()
+ end
+ return result
+ end
+ end
+ local f45
+ do
+ local result
+ function f45()
+ if not result then
+ result = f43() + f44()
+ end
+ return result
+ end
+ end
+ local f46
+ do
+ local result
+ function f46()
+ if not result then
+ result = f44() + f45()
+ end
+ return result
+ end
+ end
+ local f47
+ do
+ local result
+ function f47()
+ if not result then
+ result = f45() + f46()
+ end
+ return result
+ end
+ end
+ local f48
+ do
+ local result
+ function f48()
+ if not result then
+ result = f46() + f47()
+ end
+ return result
+ end
+ end
+ local f49
+ do
+ local result
+ function f49()
+ if not result then
+ result = f47() + f48()
+ end
+ return result
+ end
+ end
+ local f50
+ do
+ local result
+ function f50()
+ if not result then
+ result = f48() + f49()
+ end
+ return result
+ end
+ end
+ local f51
+ do
+ local result
+ function f51()
+ if not result then
+ result = f49() + f50()
+ end
+ return result
+ end
+ end
+ local f52
+ do
+ local result
+ function f52()
+ if not result then
+ result = f50() + f51()
+ end
+ return result
+ end
+ end
+ local f53
+ do
+ local result
+ function f53()
+ if not result then
+ result = f51() + f52()
+ end
+ return result
+ end
+ end
+ local f54
+ do
+ local result
+ function f54()
+ if not result then
+ result = f52() + f53()
+ end
+ return result
+ end
+ end
+ local f55
+ do
+ local result
+ function f55()
+ if not result then
+ result = f53() + f54()
+ end
+ return result
+ end
+ end
+ local f56
+ do
+ local result
+ function f56()
+ if not result then
+ result = f54() + f55()
+ end
+ return result
+ end
+ end
+ local f57
+ do
+ local result
+ function f57()
+ if not result then
+ result = f55() + f56()
+ end
+ return result
+ end
+ end
+ local f58
+ do
+ local result
+ function f58()
+ if not result then
+ result = f56() + f57()
+ end
+ return result
+ end
+ end
+ local f59
+ do
+ local result
+ function f59()
+ if not result then
+ result = f57() + f58()
+ end
+ return result
+ end
+ end
+ local f60
+ do
+ local result
+ function f60()
+ if not result then
+ result = f58() + f59()
+ end
+ return result
+ end
+ end
+ local f61
+ do
+ local result
+ function f61()
+ if not result then
+ result = f59() + f60()
+ end
+ return result
+ end
+ end
+ local f62
+ do
+ local result
+ function f62()
+ if not result then
+ result = f60() + f61()
+ end
+ return result
+ end
+ end
+ local f63
+ do
+ local result
+ function f63()
+ if not result then
+ result = f61() + f62()
+ end
+ return result
+ end
+ end
+ local f64
+ do
+ local result
+ function f64()
+ if not result then
+ result = f62() + f63()
+ end
+ return result
+ end
+ end
+ local f65
+ do
+ local result
+ function f65()
+ if not result then
+ result = f63() + f64()
+ end
+ return result
+ end
+ end
+ local f66
+ do
+ local result
+ function f66()
+ if not result then
+ result = f64() + f65()
+ end
+ return result
+ end
+ end
+ local f67
+ do
+ local result
+ function f67()
+ if not result then
+ result = f65() + f66()
+ end
+ return result
+ end
+ end
+ local f68
+ do
+ local result
+ function f68()
+ if not result then
+ result = f66() + f67()
+ end
+ return result
+ end
+ end
+ local f69
+ do
+ local result
+ function f69()
+ if not result then
+ result = f67() + f68()
+ end
+ return result
+ end
+ end
+ local f70
+ do
+ local result
+ function f70()
+ if not result then
+ result = f68() + f69()
+ end
+ return result
+ end
+ end
+ local f71
+ do
+ local result
+ function f71()
+ if not result then
+ result = f69() + f70()
+ end
+ return result
+ end
+ end
+ local f72
+ do
+ local result
+ function f72()
+ if not result then
+ result = f70() + f71()
+ end
+ return result
+ end
+ end
+ local f73
+ do
+ local result
+ function f73()
+ if not result then
+ result = f71() + f72()
+ end
+ return result
+ end
+ end
+ local f74
+ do
+ local result
+ function f74()
+ if not result then
+ result = f72() + f73()
+ end
+ return result
+ end
+ end
+ local f75
+ do
+ local result
+ function f75()
+ if not result then
+ result = f73() + f74()
+ end
+ return result
+ end
+ end
+ local f76
+ do
+ local result
+ function f76()
+ if not result then
+ result = f74() + f75()
+ end
+ return result
+ end
+ end
+ local f77
+ do
+ local result
+ function f77()
+ if not result then
+ result = f75() + f76()
+ end
+ return result
+ end
+ end
+ local f78
+ do
+ local result
+ function f78()
+ if not result then
+ result = f76() + f77()
+ end
+ return result
+ end
+ end
+ local f79
+ do
+ local result
+ function f79()
+ if not result then
+ result = f77() + f78()
+ end
+ return result
+ end
+ end
+ local f80
+ do
+ local result
+ function f80()
+ if not result then
+ result = f78() + f79()
+ end
+ return result
+ end
+ end
+ local f81
+ do
+ local result
+ function f81()
+ if not result then
+ result = f79() + f80()
+ end
+ return result
+ end
+ end
+ local f82
+ do
+ local result
+ function f82()
+ if not result then
+ result = f80() + f81()
+ end
+ return result
+ end
+ end
+ local f83
+ do
+ local result
+ function f83()
+ if not result then
+ result = f81() + f82()
+ end
+ return result
+ end
+ end
+ local f84
+ do
+ local result
+ function f84()
+ if not result then
+ result = f82() + f83()
+ end
+ return result
+ end
+ end
+ local f85
+ do
+ local result
+ function f85()
+ if not result then
+ result = f83() + f84()
+ end
+ return result
+ end
+ end
+ local f86
+ do
+ local result
+ function f86()
+ if not result then
+ result = f84() + f85()
+ end
+ return result
+ end
+ end
+ local f87
+ do
+ local result
+ function f87()
+ if not result then
+ result = f85() + f86()
+ end
+ return result
+ end
+ end
+ local f88
+ do
+ local result
+ function f88()
+ if not result then
+ result = f86() + f87()
+ end
+ return result
+ end
+ end
+ local f89
+ do
+ local result
+ function f89()
+ if not result then
+ result = f87() + f88()
+ end
+ return result
+ end
+ end
+ local f90
+ do
+ local result
+ function f90()
+ if not result then
+ result = f88() + f89()
+ end
+ return result
+ end
+ end
+ local f91
+ do
+ local result
+ function f91()
+ if not result then
+ result = f89() + f90()
+ end
+ return result
+ end
+ end
+ local f92
+ do
+ local result
+ function f92()
+ if not result then
+ result = f90() + f91()
+ end
+ return result
+ end
+ end
+ local f93
+ do
+ local result
+ function f93()
+ if not result then
+ result = f91() + f92()
+ end
+ return result
+ end
+ end
+ local f94
+ do
+ local result
+ function f94()
+ if not result then
+ result = f92() + f93()
+ end
+ return result
+ end
+ end
+ local f95
+ do
+ local result
+ function f95()
+ if not result then
+ result = f93() + f94()
+ end
+ return result
+ end
+ end
+ local f96
+ do
+ local result
+ function f96()
+ if not result then
+ result = f94() + f95()
+ end
+ return result
+ end
+ end
+ local f97
+ do
+ local result
+ function f97()
+ if not result then
+ result = f95() + f96()
+ end
+ return result
+ end
+ end
+ local f98
+ do
+ local result
+ function f98()
+ if not result then
+ result = f96() + f97()
+ end
+ return result
+ end
+ end
+ local f99
+ do
+ local result
+ function f99()
+ if not result then
+ result = f97() + f98()
+ end
+ return result
+ end
+ end
+ local f100
+ do
+ local result
+ function f100()
+ if not result then
+ result = f98() + f99()
+ end
+ return result
+ end
+ end
+ local f101
+ do
+ local result
+ function f101()
+ if not result then
+ result = f99() + f100()
+ end
+ return result
+ end
+ end
+ local f102
+ do
+ local result
+ function f102()
+ if not result then
+ result = f100() + f101()
+ end
+ return result
+ end
+ end
+ local f103
+ do
+ local result
+ function f103()
+ if not result then
+ result = f101() + f102()
+ end
+ return result
+ end
+ end
+ local f104
+ do
+ local result
+ function f104()
+ if not result then
+ result = f102() + f103()
+ end
+ return result
+ end
+ end
+ local f105
+ do
+ local result
+ function f105()
+ if not result then
+ result = f103() + f104()
+ end
+ return result
+ end
+ end
+ local f106
+ do
+ local result
+ function f106()
+ if not result then
+ result = f104() + f105()
+ end
+ return result
+ end
+ end
+ local f107
+ do
+ local result
+ function f107()
+ if not result then
+ result = f105() + f106()
+ end
+ return result
+ end
+ end
+ local f108
+ do
+ local result
+ function f108()
+ if not result then
+ result = f106() + f107()
+ end
+ return result
+ end
+ end
+ local f109
+ do
+ local result
+ function f109()
+ if not result then
+ result = f107() + f108()
+ end
+ return result
+ end
+ end
+ local f110
+ do
+ local result
+ function f110()
+ if not result then
+ result = f108() + f109()
+ end
+ return result
+ end
+ end
+ local f111
+ do
+ local result
+ function f111()
+ if not result then
+ result = f109() + f110()
+ end
+ return result
+ end
+ end
+ local f112
+ do
+ local result
+ function f112()
+ if not result then
+ result = f110() + f111()
+ end
+ return result
+ end
+ end
+ local f113
+ do
+ local result
+ function f113()
+ if not result then
+ result = f111() + f112()
+ end
+ return result
+ end
+ end
+ local f114
+ do
+ local result
+ function f114()
+ if not result then
+ result = f112() + f113()
+ end
+ return result
+ end
+ end
+ local f115
+ do
+ local result
+ function f115()
+ if not result then
+ result = f113() + f114()
+ end
+ return result
+ end
+ end
+ local f116
+ do
+ local result
+ function f116()
+ if not result then
+ result = f114() + f115()
+ end
+ return result
+ end
+ end
+ local f117
+ do
+ local result
+ function f117()
+ if not result then
+ result = f115() + f116()
+ end
+ return result
+ end
+ end
+ local f118
+ do
+ local result
+ function f118()
+ if not result then
+ result = f116() + f117()
+ end
+ return result
+ end
+ end
+ local f119
+ do
+ local result
+ function f119()
+ if not result then
+ result = f117() + f118()
+ end
+ return result
+ end
+ end
+ local f120
+ do
+ local result
+ function f120()
+ if not result then
+ result = f118() + f119()
+ end
+ return result
+ end
+ end
+ local f121
+ do
+ local result
+ function f121()
+ if not result then
+ result = f119() + f120()
+ end
+ return result
+ end
+ end
+ local f122
+ do
+ local result
+ function f122()
+ if not result then
+ result = f120() + f121()
+ end
+ return result
+ end
+ end
+ local f123
+ do
+ local result
+ function f123()
+ if not result then
+ result = f121() + f122()
+ end
+ return result
+ end
+ end
+ local f124
+ do
+ local result
+ function f124()
+ if not result then
+ result = f122() + f123()
+ end
+ return result
+ end
+ end
+ local f125
+ do
+ local result
+ function f125()
+ if not result then
+ result = f123() + f124()
+ end
+ return result
+ end
+ end
+ local f126
+ do
+ local result
+ function f126()
+ if not result then
+ result = f124() + f125()
+ end
+ return result
+ end
+ end
+ local f127
+ do
+ local result
+ function f127()
+ if not result then
+ result = f125() + f126()
+ end
+ return result
+ end
+ end
+ local f128
+ do
+ local result
+ function f128()
+ if not result then
+ result = f126() + f127()
+ end
+ return result
+ end
+ end
+ local f129
+ do
+ local result
+ function f129()
+ if not result then
+ result = f127() + f128()
+ end
+ return result
+ end
+ end
+ local f130
+ do
+ local result
+ function f130()
+ if not result then
+ result = f128() + f129()
+ end
+ return result
+ end
+ end
+ local f131
+ do
+ local result
+ function f131()
+ if not result then
+ result = f129() + f130()
+ end
+ return result
+ end
+ end
+ local f132
+ do
+ local result
+ function f132()
+ if not result then
+ result = f130() + f131()
+ end
+ return result
+ end
+ end
+ local f133
+ do
+ local result
+ function f133()
+ if not result then
+ result = f131() + f132()
+ end
+ return result
+ end
+ end
+ local f134
+ do
+ local result
+ function f134()
+ if not result then
+ result = f132() + f133()
+ end
+ return result
+ end
+ end
+ local f135
+ do
+ local result
+ function f135()
+ if not result then
+ result = f133() + f134()
+ end
+ return result
+ end
+ end
+ local f136
+ do
+ local result
+ function f136()
+ if not result then
+ result = f134() + f135()
+ end
+ return result
+ end
+ end
+ local f137
+ do
+ local result
+ function f137()
+ if not result then
+ result = f135() + f136()
+ end
+ return result
+ end
+ end
+ local f138
+ do
+ local result
+ function f138()
+ if not result then
+ result = f136() + f137()
+ end
+ return result
+ end
+ end
+ local f139
+ do
+ local result
+ function f139()
+ if not result then
+ result = f137() + f138()
+ end
+ return result
+ end
+ end
+ local f140
+ do
+ local result
+ function f140()
+ if not result then
+ result = f138() + f139()
+ end
+ return result
+ end
+ end
+ local f141
+ do
+ local result
+ function f141()
+ if not result then
+ result = f139() + f140()
+ end
+ return result
+ end
+ end
+ local f142
+ do
+ local result
+ function f142()
+ if not result then
+ result = f140() + f141()
+ end
+ return result
+ end
+ end
+ local f143
+ do
+ local result
+ function f143()
+ if not result then
+ result = f141() + f142()
+ end
+ return result
+ end
+ end
+ local f144
+ do
+ local result
+ function f144()
+ if not result then
+ result = f142() + f143()
+ end
+ return result
+ end
+ end
+ local f145
+ do
+ local result
+ function f145()
+ if not result then
+ result = f143() + f144()
+ end
+ return result
+ end
+ end
+ local f146
+ do
+ local result
+ function f146()
+ if not result then
+ result = f144() + f145()
+ end
+ return result
+ end
+ end
+ local f147
+ do
+ local result
+ function f147()
+ if not result then
+ result = f145() + f146()
+ end
+ return result
+ end
+ end
+ local f148
+ do
+ local result
+ function f148()
+ if not result then
+ result = f146() + f147()
+ end
+ return result
+ end
+ end
+ local f149
+ do
+ local result
+ function f149()
+ if not result then
+ result = f147() + f148()
+ end
+ return result
+ end
+ end
+ local f150
+ do
+ local result
+ function f150()
+ if not result then
+ result = f148() + f149()
+ end
+ return result
+ end
+ end
+ local f151
+ do
+ local result
+ function f151()
+ if not result then
+ result = f149() + f150()
+ end
+ return result
+ end
+ end
+ local f152
+ do
+ local result
+ function f152()
+ if not result then
+ result = f150() + f151()
+ end
+ return result
+ end
+ end
+ local f153
+ do
+ local result
+ function f153()
+ if not result then
+ result = f151() + f152()
+ end
+ return result
+ end
+ end
+ local f154
+ do
+ local result
+ function f154()
+ if not result then
+ result = f152() + f153()
+ end
+ return result
+ end
+ end
+ local f155
+ do
+ local result
+ function f155()
+ if not result then
+ result = f153() + f154()
+ end
+ return result
+ end
+ end
+ local f156
+ do
+ local result
+ function f156()
+ if not result then
+ result = f154() + f155()
+ end
+ return result
+ end
+ end
+ local f157
+ do
+ local result
+ function f157()
+ if not result then
+ result = f155() + f156()
+ end
+ return result
+ end
+ end
+ local f158
+ do
+ local result
+ function f158()
+ if not result then
+ result = f156() + f157()
+ end
+ return result
+ end
+ end
+ local f159
+ do
+ local result
+ function f159()
+ if not result then
+ result = f157() + f158()
+ end
+ return result
+ end
+ end
+ local f160
+ do
+ local result
+ function f160()
+ if not result then
+ result = f158() + f159()
+ end
+ return result
+ end
+ end
+ local f161
+ do
+ local result
+ function f161()
+ if not result then
+ result = f159() + f160()
+ end
+ return result
+ end
+ end
+ local f162
+ do
+ local result
+ function f162()
+ if not result then
+ result = f160() + f161()
+ end
+ return result
+ end
+ end
+ local f163
+ do
+ local result
+ function f163()
+ if not result then
+ result = f161() + f162()
+ end
+ return result
+ end
+ end
+ local f164
+ do
+ local result
+ function f164()
+ if not result then
+ result = f162() + f163()
+ end
+ return result
+ end
+ end
+ local f165
+ do
+ local result
+ function f165()
+ if not result then
+ result = f163() + f164()
+ end
+ return result
+ end
+ end
+ local f166
+ do
+ local result
+ function f166()
+ if not result then
+ result = f164() + f165()
+ end
+ return result
+ end
+ end
+ local f167
+ do
+ local result
+ function f167()
+ if not result then
+ result = f165() + f166()
+ end
+ return result
+ end
+ end
+ local f168
+ do
+ local result
+ function f168()
+ if not result then
+ result = f166() + f167()
+ end
+ return result
+ end
+ end
+ local f169
+ do
+ local result
+ function f169()
+ if not result then
+ result = f167() + f168()
+ end
+ return result
+ end
+ end
+ local f170
+ do
+ local result
+ function f170()
+ if not result then
+ result = f168() + f169()
+ end
+ return result
+ end
+ end
+ local f171
+ do
+ local result
+ function f171()
+ if not result then
+ result = f169() + f170()
+ end
+ return result
+ end
+ end
+ local f172
+ do
+ local result
+ function f172()
+ if not result then
+ result = f170() + f171()
+ end
+ return result
+ end
+ end
+ local f173
+ do
+ local result
+ function f173()
+ if not result then
+ result = f171() + f172()
+ end
+ return result
+ end
+ end
+ local f174
+ do
+ local result
+ function f174()
+ if not result then
+ result = f172() + f173()
+ end
+ return result
+ end
+ end
+ local f175
+ do
+ local result
+ function f175()
+ if not result then
+ result = f173() + f174()
+ end
+ return result
+ end
+ end
+ local f176
+ do
+ local result
+ function f176()
+ if not result then
+ result = f174() + f175()
+ end
+ return result
+ end
+ end
+ local f177
+ do
+ local result
+ function f177()
+ if not result then
+ result = f175() + f176()
+ end
+ return result
+ end
+ end
+ local f178
+ do
+ local result
+ function f178()
+ if not result then
+ result = f176() + f177()
+ end
+ return result
+ end
+ end
+ local f179
+ do
+ local result
+ function f179()
+ if not result then
+ result = f177() + f178()
+ end
+ return result
+ end
+ end
+ local f180
+ do
+ local result
+ function f180()
+ if not result then
+ result = f178() + f179()
+ end
+ return result
+ end
+ end
+ local f181
+ do
+ local result
+ function f181()
+ if not result then
+ result = f179() + f180()
+ end
+ return result
+ end
+ end
+ local f182
+ do
+ local result
+ function f182()
+ if not result then
+ result = f180() + f181()
+ end
+ return result
+ end
+ end
+ local f183
+ do
+ local result
+ function f183()
+ if not result then
+ result = f181() + f182()
+ end
+ return result
+ end
+ end
+ local f184
+ do
+ local result
+ function f184()
+ if not result then
+ result = f182() + f183()
+ end
+ return result
+ end
+ end
+ local f185
+ do
+ local result
+ function f185()
+ if not result then
+ result = f183() + f184()
+ end
+ return result
+ end
+ end
+ local f186
+ do
+ local result
+ function f186()
+ if not result then
+ result = f184() + f185()
+ end
+ return result
+ end
+ end
+ local f187
+ do
+ local result
+ function f187()
+ if not result then
+ result = f185() + f186()
+ end
+ return result
+ end
+ end
+ local f188
+ do
+ local result
+ function f188()
+ if not result then
+ result = f186() + f187()
+ end
+ return result
+ end
+ end
+ local f189
+ do
+ local result
+ function f189()
+ if not result then
+ result = f187() + f188()
+ end
+ return result
+ end
+ end
+ local f190
+ do
+ local result
+ function f190()
+ if not result then
+ result = f188() + f189()
+ end
+ return result
+ end
+ end
+ local f191
+ do
+ local result
+ function f191()
+ if not result then
+ result = f189() + f190()
+ end
+ return result
+ end
+ end
+ local f192
+ do
+ local result
+ function f192()
+ if not result then
+ result = f190() + f191()
+ end
+ return result
+ end
+ end
+ local f193
+ do
+ local result
+ function f193()
+ if not result then
+ result = f191() + f192()
+ end
+ return result
+ end
+ end
+ local f194
+ do
+ local result
+ function f194()
+ if not result then
+ result = f192() + f193()
+ end
+ return result
+ end
+ end
+ local f195
+ do
+ local result
+ function f195()
+ if not result then
+ result = f193() + f194()
+ end
+ return result
+ end
+ end
+ local f196
+ do
+ local result
+ function f196()
+ if not result then
+ result = f194() + f195()
+ end
+ return result
+ end
+ end
+ local f197
+ do
+ local result
+ function f197()
+ if not result then
+ result = f195() + f196()
+ end
+ return result
+ end
+ end
+ local f198
+ do
+ local result
+ function f198()
+ if not result then
+ result = f196() + f197()
+ end
+ return result
+ end
+ end
+ local f199
+ do
+ local result
+ function f199()
+ if not result then
+ result = f197() + f198()
+ end
+ return result
+ end
+ end
+ print("5th fibonacci number is", f5())
+ print("10th fibonacci number is", f10())
+-- FIXME Precision??
+-- print("199th fibonacci number is", f199())
+
+5th fibonacci number is 5
+10th fibonacci number is 55
diff --git a/luaj-test/src/test/resources/compatibility/jme/mathlib.out b/luaj-test/src/test/resources/compatibility/jme/mathlib.out
new file mode 100644
index 00000000..750f7a61
--- /dev/null
+++ b/luaj-test/src/test/resources/compatibility/jme/mathlib.out
@@ -0,0 +1,729 @@
+---------- miscellaneous tests ----------
+math.sin( 0.0 ) true
+math.cos( math.pi ) true -1
+math.sqrt( 9.0 ) true 3
+math.modf( 5.25 ) true 5 0.25
+math.frexp(0.00625) true 0.8 -7
+-5 ^ 2 true -25
+-5 / 2 true -2.5
+-5 % 2 true 1
+---------- constants ----------
+math.huge true
+math.pi true 3.1415
+---------- unary operator - ----------
+--2.5 true
+--2 true
+-0 true
+-2 true -2
+-2.5 true -2.5
+-'-2.5' true 2.5
+-'-2' true 2
+-'0' true
+-'2' true -2
+-'2.5' true -2.5
+---------- unary operator not ----------
+not -2.5 true false
+not -2 true false
+not 0 true false
+not 2 true false
+not 2.5 true false
+not '-2.5' true false
+not '-2' true false
+not '0' true false
+not '2' true false
+not '2.5' true false
+---------- binary operator + ----------
+2+0 true 2
+-2.5+0 true -2.5
+2+1 true 3
+5+2 true 7
+-5+2 true -3
+16+2 true 18
+-16+-2 true -18
+0.5+0 true 0.5
+0.5+1 true 1.5
+0.5+2 true 2.5
+0.5+-1 true -0.5
+0.5+2 true 2.5
+2.25+0 true 2.25
+2.25+2 true 4.25
+-2+0 true -2
+3+3 true 6
+'2'+'0' true 2
+'2.5'+'3' true 5.5
+'-2'+'1.5' true -0.5
+'-2.5'+'-1.5' true -4
+'3.0'+'3.0' true 6
+2.75+2.75 true 5.5
+'2.75'+'2.75' true 5.5
+3+'3' true 6
+'3'+3 true 6
+2.75+'2.75' true 5.5
+'2.75'+2.75 true 5.5
+-3+'-4' true -7
+'-3'+4 true 1
+-3+'4' true 1
+'-3'+-4 true -7
+-4.75+'2.75' true -2
+'-2.75'+1.75 true -1
+4.75+'-2.75' true 2
+'2.75'+-1.75 true 1
+---------- binary operator - ----------
+2-0 true 2
+-2.5-0 true -2.5
+2-1 true 1
+5-2 true 3
+-5-2 true -7
+16-2 true 14
+-16--2 true -14
+0.5-0 true 0.5
+0.5-1 true -0.5
+0.5-2 true -1.5
+0.5--1 true 1.5
+0.5-2 true -1.5
+2.25-0 true 2.25
+2.25-2 true 0.25
+-2-0 true -2
+3-3 true
+'2'-'0' true 2
+'2.5'-'3' true -0.5
+'-2'-'1.5' true -3.5
+'-2.5'-'-1.5' true -1
+'3.0'-'3.0' true
+2.75-2.75 true
+'2.75'-'2.75' true
+3-'3' true
+'3'-3 true
+2.75-'2.75' true
+'2.75'-2.75 true
+-3-'-4' true 1
+'-3'-4 true -7
+-3-'4' true -7
+'-3'--4 true 1
+-4.75-'2.75' true -7.5
+'-2.75'-1.75 true -4.5
+4.75-'-2.75' true 7.5
+'2.75'--1.75 true 4.5
+---------- binary operator * ----------
+2*0 true